Design wisp squash architecture: cadences, templates, retention (gt-cekg)
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>
This commit is contained in:
372
docs/wisp-squash-design.md
Normal file
372
docs/wisp-squash-design.md
Normal file
@@ -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 <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
|
||||
|
||||
```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 <digest-id>
|
||||
```
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user