Adds comprehensive design for how wisps squash to digests: - Cadences: patrol wisps squash per-cycle, work wisps on completion - Templates: structured formats for patrol and work digests, formula-defined - Retention: 30d active, 1yr archive, weekly/monthly rollups - Activity feed integration for observability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.2 KiB
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:
- Header: Standard metadata (who, what, when)
- Body: Context-specific content (from template)
- Footer: System metrics (steps, duration, commit refs)
Patrol Digest Template
## 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
## 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:
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:
- Formula-defined template (if present)
- Type-specific default (patrol vs work)
- 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:
## 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:
## {{.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:
{
"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)
- Add
[squash]section parsing to formula loader - Create default templates for patrol and work digests
- Enhance
bd mol squashto use templates - Add
--templateflag for override
Phase 2: Cadence Automation
- Hook squash into
gt doneflow - Add patrol cycle completion detection
- Emit squash events for activity feed
Phase 3: Retention & Archival
- Implement digest aging (active → archived)
- Add
bd archivecommand for manual archival - Create rollup generator for weekly/monthly summaries
- Background daemon task for auto-archival
Commands
Squash with Template
# Use formula-defined template
bd mol squash <id>
# Use explicit template
bd mol squash <id> --template=detailed
# Add custom summary
bd mol squash <id> --summary="Patrol complete: 3 issues filed"
View Digests
# List recent digests
bd list --label=digest
# View rollups
bd rollup list
bd rollup show weekly-2025-01
Archive Management
# Archive old digests
bd archive --older-than=30d
# Generate rollup
bd rollup generate --week=2025-01
# Restore from archive
bd archive restore <digest-id>
Activity Feed Integration
Digests feed into the activity feed for observability:
{
"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:
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 squashwithout 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