diff --git a/docs/wisp-squash-design.md b/docs/wisp-squash-design.md new file mode 100644 index 00000000..ae3987c4 --- /dev/null +++ b/docs/wisp-squash-design.md @@ -0,0 +1,372 @@ +# Wisp Squash Design: Cadences, Rules, Templates + +Design specification for how wisps squash to digests in Gas Town. + +## Problem Statement + +Wisps are ephemeral molecules that need to be condensed into digests for: +- **Audit trail**: What happened, when, by whom +- **Activity feed**: Observable progress in the capability ledger +- **Space efficiency**: Ephemeral data doesn't accumulate indefinitely + +Currently under-designed: +- **Cadences**: When should squash happen? +- **Templates**: What should digests contain? +- **Retention**: How long to keep, when to aggregate? + +## Squash Cadences + +### Patrol Wisps (Deacon, Witness, Refinery) + +**Trigger**: End of each patrol cycle + +``` +patrol-start → steps → loop-or-exit step → squash → new wisp +``` + +| Decision Point | Action | +|----------------|--------| +| `loop-or-exit` with low context | Squash current wisp, create new wisp | +| `loop-or-exit` with high context | Squash current wisp, handoff | +| Extraordinary action | Squash immediately, handoff | + +**Rationale**: Each patrol cycle is a logical unit. Squashing per-cycle keeps +digests meaningful and prevents context-filling sessions from losing history. + +### Work Wisps (Polecats) + +**Trigger**: Before `gt done` or molecule completion + +``` +work-assigned → steps → all-complete → squash → gt done → merge queue +``` + +Polecats typically use regular molecules (not wisps), but when wisps are used +for exploratory work: + +| Scenario | Action | +|----------|--------| +| Molecule completes | Squash to digest | +| Molecule abandoned | Burn (no digest) | +| Molecule handed off | Squash, include handoff context | + +### Time-Based Cadences (Future) + +For long-running molecules that span multiple sessions: + +| Duration | Action | +|----------|--------| +| Session ends | Auto-squash if molecule in progress | +| > 24 hours | Create checkpoint digest | +| > 7 days | Warning: stale molecule | + +**Not implemented initially** - simplicity first. + +## Summary Templates + +### Template Structure + +Digests have three sections: +1. **Header**: Standard metadata (who, what, when) +2. **Body**: Context-specific content (from template) +3. **Footer**: System metrics (steps, duration, commit refs) + +### Patrol Digest Template + +```markdown +## Patrol Digest: {{.Agent}} + +**Cycle**: {{.CycleNumber}} | **Duration**: {{.Duration}} + +### Actions Taken +{{range .Actions}} +- {{.Icon}} {{.Description}} +{{end}} + +### Issues Filed +{{range .IssuesFiled}} +- {{.ID}}: {{.Title}} +{{end}} + +### Metrics +- Inbox: {{.InboxCount}} messages processed +- Health checks: {{.HealthChecks}} +- Alerts: {{.AlertCount}} +``` + +### Work Digest Template + +```markdown +## Work Digest: {{.IssueTitle}} + +**Issue**: {{.IssueID}} | **Agent**: {{.Agent}} | **Duration**: {{.Duration}} + +### Summary +{{.Summary}} + +### Steps Completed +{{range .Steps}} +- [{{.Status}}] {{.Title}} +{{end}} + +### Artifacts +- Commits: {{range .Commits}}{{.Short}}, {{end}} +- Files changed: {{.FilesChanged}} +- Lines: +{{.LinesAdded}} -{{.LinesRemoved}} +``` + +### Formula-Defined Templates + +Formulas can define custom squash templates in `[squash]` section: + +```toml +formula = "mol-my-workflow" +version = 1 + +[squash] +template = """ +## {{.Title}} Complete + +Duration: {{.Duration}} +Key metrics: +{{range .Steps}} +- {{.ID}}: {{.CustomField}} +{{end}} +""" + +# Template variables from step outputs +[squash.vars] +include_metrics = true +summary_length = "short" # short | medium | detailed +``` + +**Resolution order**: +1. Formula-defined template (if present) +2. Type-specific default (patrol vs work) +3. Minimal fallback (current behavior) + +## Retention Rules + +### Digest Lifecycle + +``` +Wisp → Squash → Digest (active) → Digest (archived) → Rollup +``` + +| Phase | Duration | Storage | +|-------|----------|---------| +| Active | 30 days | `.beads/issues.jsonl` | +| Archived | 1 year | `.beads/archive/` (compressed) | +| Rollup | Permanent | Weekly/monthly summaries | + +### Rollup Strategy + +After retention period, digests aggregate into rollups: + +**Weekly Patrol Rollup**: +```markdown +## Week of {{.WeekStart}} + +| Agent | Cycles | Issues Filed | Merges | Incidents | +|-------|--------|--------------|--------|-----------| +| Deacon | 140 | 3 | - | 0 | +| Witness | 168 | 12 | - | 2 | +| Refinery | 84 | 0 | 47 | 1 | +``` + +**Monthly Work Rollup**: +```markdown +## {{.Month}} Work Summary + +Issues completed: {{.TotalIssues}} +Total duration: {{.TotalDuration}} +Contributors: {{range .Contributors}}{{.Name}}, {{end}} + +Top categories: +{{range .Categories}} +- {{.Name}}: {{.Count}} issues +{{end}} +``` + +### Retention Configuration + +Per-rig settings in `config.json`: + +```json +{ + "retention": { + "digest_active_days": 30, + "digest_archive_days": 365, + "rollup_weekly": true, + "rollup_monthly": true, + "auto_archive": true + } +} +``` + +## Implementation Plan + +### Phase 1: Template System (MVP) + +1. Add `[squash]` section parsing to formula loader +2. Create default templates for patrol and work digests +3. Enhance `bd mol squash` to use templates +4. Add `--template` flag for override + +### Phase 2: Cadence Automation + +1. Hook squash into `gt done` flow +2. Add patrol cycle completion detection +3. Emit squash events for activity feed + +### Phase 3: Retention & Archival + +1. Implement digest aging (active → archived) +2. Add `bd archive` command for manual archival +3. Create rollup generator for weekly/monthly summaries +4. Background daemon task for auto-archival + +## Commands + +### Squash with Template + +```bash +# Use formula-defined template +bd mol squash + +# Use explicit template +bd mol squash --template=detailed + +# Add custom summary +bd mol squash --summary="Patrol complete: 3 issues filed" +``` + +### View Digests + +```bash +# List recent digests +bd list --label=digest + +# View rollups +bd rollup list +bd rollup show weekly-2025-01 +``` + +### Archive Management + +```bash +# Archive old digests +bd archive --older-than=30d + +# Generate rollup +bd rollup generate --week=2025-01 + +# Restore from archive +bd archive restore +``` + +## Activity Feed Integration + +Digests feed into the activity feed for observability: + +```json +{ + "type": "digest", + "agent": "gastown/witness", + "timestamp": "2025-12-30T10:00:00Z", + "summary": "Patrol cycle 47 complete", + "metrics": { + "issues_filed": 2, + "polecats_nudged": 1, + "duration_minutes": 12 + } +} +``` + +The feed curator (daemon) can aggregate these for dashboards. + +## Formula Example + +Complete formula with squash configuration: + +```toml +formula = "mol-witness-patrol" +version = 1 +type = "workflow" +description = "Witness patrol cycle" + +[squash] +trigger = "on_complete" +template_type = "patrol" +include_metrics = true + +[[steps]] +id = "inbox-check" +title = "Check inbox" +description = "Process messages and escalations" + +[[steps]] +id = "health-scan" +title = "Scan polecat health" +description = "Check all polecats for stuck/idle" + +[[steps]] +id = "nudge-stuck" +title = "Nudge stuck workers" +description = "Send nudges to idle polecats" + +[[steps]] +id = "loop-or-exit" +title = "Loop or exit decision" +description = "Decide whether to continue or handoff" +``` + +## Migration + +### Existing Digests + +Current minimal digests remain valid. New template system is additive: +- Old digests: Title, basic description +- New digests: Structured content, metrics + +### Backward Compatibility + +- `bd mol squash` without template uses current behavior +- Formulas without `[squash]` section use type defaults +- No breaking changes to existing workflows + +## Design Decisions + +### Why Squash Per-Cycle? + +**Alternative**: Squash on session end only + +**Rejected because**: +- Sessions can crash mid-cycle (lost audit trail) +- High-context sessions may span multiple cycles +- Per-cycle gives finer granularity + +### Why Formula-Defined Templates? + +**Alternative**: Hard-coded templates per role + +**Rejected because**: +- Different workflows have different metrics +- Extensibility for custom formulas +- Separation of concerns (workflow defines its own output) + +### Why Retain Forever (as Rollups)? + +**Alternative**: Delete after N days + +**Rejected because**: +- Capability ledger needs long-term history +- Rollups are small (aggregate stats) +- Audit requirements vary by use case + +## Future Considerations + +- **Search**: Full-text search over archived digests +- **Analytics**: Metrics aggregation dashboard +- **Export**: Export digests to external systems +- **Compliance**: Configurable retention for regulatory needs