From bb5a78c4fa9afa8264f5917a5f9a848db58f58a4 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Fri, 26 Dec 2025 23:48:50 -0800 Subject: [PATCH] =?UTF-8?q?refactor:=20Update=20bd=20pour/wisp=20=E2=86=92?= =?UTF-8?q?=20bd=20mol=20pour/wisp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beads CLI restructured: pour and wisp are now subcommands of mol. - bd pour → bd mol pour - bd wisp → bd mol wisp Updated all documentation, templates, and code to use new command structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .beads/formulas/beads-release.formula.toml | 2 +- .beads/formulas/mol-gastown-boot.formula.json | 62 +++++++++++++++++++ .beads/formulas/mol-gastown-boot.formula.toml | 2 +- README.md | 2 +- docs/reference.md | 10 +-- internal/cmd/prime.go | 6 +- internal/doctor/wisp_check.go | 6 +- internal/templates/roles/crew.md.tmpl | 1 + internal/templates/roles/deacon.md.tmpl | 4 +- internal/templates/roles/mayor.md.tmpl | 1 + internal/templates/roles/polecat.md.tmpl | 1 + internal/templates/roles/witness.md.tmpl | 2 +- 12 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 .beads/formulas/mol-gastown-boot.formula.json diff --git a/.beads/formulas/beads-release.formula.toml b/.beads/formulas/beads-release.formula.toml index ef26f926..84b302e2 100644 --- a/.beads/formulas/beads-release.formula.toml +++ b/.beads/formulas/beads-release.formula.toml @@ -14,7 +14,7 @@ This formula orchestrates a complete release cycle: ## Usage ```bash -bd wisp create beads-release --var version=0.37.0 +bd mol wisp create beads-release --var version=0.37.0 ``` Or assign to a polecat: diff --git a/.beads/formulas/mol-gastown-boot.formula.json b/.beads/formulas/mol-gastown-boot.formula.json new file mode 100644 index 00000000..80f3db2e --- /dev/null +++ b/.beads/formulas/mol-gastown-boot.formula.json @@ -0,0 +1,62 @@ +{ + "formula": "mol-gastown-boot", + "description": "Mayor bootstraps Gas Town via a verification-gated lifecycle molecule.\n\n## Purpose\nWhen Mayor executes \"boot up gas town\", this proto provides the workflow.\nEach step has action + verification - steps stay open until outcome is confirmed.\n\n## Key Principles\n1. **Verification-gated steps** - Not \"command ran\" but \"outcome confirmed\"\n2. **gt peek for verification** - Capture session output to detect stalls\n3. **gt nudge for recovery** - Reliable message delivery to unstick agents\n4. **Parallel where possible** - Witnesses and refineries can start in parallel\n5. **Ephemeral execution** - Boot is a wisp, squashed to digest after completion\n\n## Execution\n```bash\nbd mol wisp mol-gastown-boot # Create wisp\n```", + "version": 1, + "steps": [ + { + "id": "ensure-daemon", + "title": "Ensure daemon", + "description": "Verify the Gas Town daemon is running.\n\n## Action\n```bash\ngt daemon status || gt daemon start\n```\n\n## Verify\n1. Daemon PID file exists: `~/.gt/daemon.pid`\n2. Process is alive: `kill -0 $(cat ~/.gt/daemon.pid)`\n3. Daemon responds: `gt daemon status` returns success\n\n## OnFail\nCannot start daemon. Log error and continue - some commands work without daemon." + }, + { + "id": "ensure-deacon", + "title": "Ensure deacon", + "needs": ["ensure-daemon"], + "description": "Start the Deacon and verify patrol mode is active.\n\n## Action\n```bash\ngt deacon start\n```\n\n## Verify\n1. Session exists: `tmux has-session -t gt-deacon 2>/dev/null`\n2. Not stalled: `gt peek deacon/` does NOT show \"> Try\" prompt\n3. Heartbeat fresh: `deacon/heartbeat.json` modified < 2 min ago\n\n## OnStall\n```bash\ngt nudge deacon/ \"Start patrol.\"\nsleep 30\n# Re-verify\n```" + }, + { + "id": "ensure-witnesses", + "title": "Ensure witnesses", + "needs": ["ensure-deacon"], + "type": "parallel", + "description": "Parallel container: Start all rig witnesses.\n\nChildren execute in parallel. Container completes when all children complete.", + "children": [ + { + "id": "ensure-gastown-witness", + "title": "Ensure gastown witness", + "description": "Start the gastown rig Witness.\n\n## Action\n```bash\ngt witness start gastown\n```\n\n## Verify\n1. Session exists: `tmux has-session -t gastown-witness 2>/dev/null`\n2. Not stalled: `gt peek gastown/witness` does NOT show \"> Try\" prompt\n3. Heartbeat fresh: Last patrol cycle < 5 min ago" + }, + { + "id": "ensure-beads-witness", + "title": "Ensure beads witness", + "description": "Start the beads rig Witness.\n\n## Action\n```bash\ngt witness start beads\n```\n\n## Verify\n1. Session exists: `tmux has-session -t beads-witness 2>/dev/null`\n2. Not stalled: `gt peek beads/witness` does NOT show \"> Try\" prompt\n3. Heartbeat fresh: Last patrol cycle < 5 min ago" + } + ] + }, + { + "id": "ensure-refineries", + "title": "Ensure refineries", + "needs": ["ensure-deacon"], + "type": "parallel", + "description": "Parallel container: Start all rig refineries.\n\nChildren execute in parallel. Container completes when all children complete.", + "children": [ + { + "id": "ensure-gastown-refinery", + "title": "Ensure gastown refinery", + "description": "Start the gastown rig Refinery.\n\n## Action\n```bash\ngt refinery start gastown\n```\n\n## Verify\n1. Session exists: `tmux has-session -t gastown-refinery 2>/dev/null`\n2. Not stalled: `gt peek gastown/refinery` does NOT show \"> Try\" prompt\n3. Queue processing: Refinery can receive merge requests" + }, + { + "id": "ensure-beads-refinery", + "title": "Ensure beads refinery", + "description": "Start the beads rig Refinery.\n\n## Action\n```bash\ngt refinery start beads\n```\n\n## Verify\n1. Session exists: `tmux has-session -t beads-refinery 2>/dev/null`\n2. Not stalled: `gt peek beads/refinery` does NOT show \"> Try\" prompt\n3. Queue processing: Refinery can receive merge requests" + } + ] + }, + { + "id": "verify-town-health", + "title": "Verify town health", + "needs": ["ensure-witnesses", "ensure-refineries"], + "description": "Final verification that Gas Town is healthy.\n\n## Action\n```bash\ngt status\n```\n\n## Verify\n1. Daemon running: Shows daemon status OK\n2. Deacon active: Shows deacon in patrol mode\n3. All witnesses: Each rig witness shows active\n4. All refineries: Each rig refinery shows active\n\n## OnFail\nLog degraded state but consider boot complete. Some agents may need manual recovery.\nRun `gt doctor` for detailed diagnostics." + } + ] +} diff --git a/.beads/formulas/mol-gastown-boot.formula.toml b/.beads/formulas/mol-gastown-boot.formula.toml index beaae718..febb4fde 100644 --- a/.beads/formulas/mol-gastown-boot.formula.toml +++ b/.beads/formulas/mol-gastown-boot.formula.toml @@ -14,7 +14,7 @@ Each step has action + verification - steps stay open until outcome is confirmed ## Execution ```bash -bd wisp mol-gastown-boot # Create wisp +bd mol wisp mol-gastown-boot # Create wisp ```""" formula = "mol-gastown-boot" version = 1 diff --git a/README.md b/README.md index 7f6f00dc..2c81b430 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ needs = ["test"] ```bash bd formula list # See available formulas bd cook shiny # Cook into a protomolecule -bd pour shiny --var feature=auth # Create runnable molecule +bd mol pour shiny --var feature=auth # Create runnable molecule gt sling gt-xyz myproject # Assign to worker ``` diff --git a/docs/reference.md b/docs/reference.md index ef66fb56..207dc361 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -110,9 +110,9 @@ Formula (source TOML) ─── "Ice-9" ▼ bd cook Protomolecule (frozen template) ─── Solid │ - ├─▶ bd pour ──▶ Mol (persistent) ─── Liquid ──▶ bd squash ──▶ Digest + ├─▶ bd mol pour ──▶ Mol (persistent) ─── Liquid ──▶ bd squash ──▶ Digest │ - └─▶ bd wisp ──▶ Wisp (ephemeral) ─── Vapor ──┬▶ bd squash ──▶ Digest + └─▶ bd mol wisp ──▶ Wisp (ephemeral) ─── Vapor ──┬▶ bd squash ──▶ Digest └▶ bd burn ──▶ (gone) ``` @@ -130,8 +130,8 @@ bd cook # Formula → Proto # Molecules bd mol list # Available protos bd mol show # Proto details -bd pour # Create mol -bd wisp # Create wisp +bd mol pour # Create mol +bd mol wisp # Create wisp bd mol bond # Attach to existing mol bd mol squash # Condense to digest bd mol burn # Discard wisp @@ -237,7 +237,7 @@ Deacon, Witness, and Refinery run continuous patrol loops using wisps: | **Refinery** | `mol-refinery-patrol` | Process merge queue, review PRs | ``` -1. bd wisp mol--patrol +1. bd mol wisp mol--patrol 2. Execute steps (check workers, process queue, run plugins) 3. bd mol squash (or burn if routine) 4. Loop diff --git a/internal/cmd/prime.go b/internal/cmd/prime.go index 42ae4487..5adbae94 100644 --- a/internal/cmd/prime.go +++ b/internal/cmd/prime.go @@ -459,7 +459,7 @@ func outputStartupDirective(ctx RoleContext) { fmt.Println("2. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages") fmt.Println("3. Check for attached patrol: `gt mol status`") fmt.Println(" - If mol attached → **RUN IT** (resume from current step)") - fmt.Println(" - If no mol → create patrol: `bd wisp mol-witness-patrol`") + fmt.Println(" - If no mol → create patrol: `bd mol wisp mol-witness-patrol`") case RolePolecat: fmt.Println() fmt.Println("---") @@ -480,7 +480,7 @@ func outputStartupDirective(ctx RoleContext) { fmt.Println("2. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages") fmt.Println("3. Check for attached patrol: `gt mol status`") fmt.Println(" - If mol attached → **RUN IT** (resume from current step)") - fmt.Println(" - If no mol → create patrol: `bd wisp mol-refinery-patrol`") + fmt.Println(" - If no mol → create patrol: `bd mol wisp mol-refinery-patrol`") case RoleCrew: fmt.Println() fmt.Println("---") @@ -502,7 +502,7 @@ func outputStartupDirective(ctx RoleContext) { fmt.Println("3. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages") fmt.Println("4. Check for attached patrol: `gt mol status`") fmt.Println(" - If mol attached → **RUN IT** (resume from current step)") - fmt.Println(" - If no mol → create patrol: `bd wisp mol-deacon-patrol`") + fmt.Println(" - If no mol → create patrol: `bd mol wisp mol-deacon-patrol`") } } diff --git a/internal/doctor/wisp_check.go b/internal/doctor/wisp_check.go index 95e7d750..b96445e7 100644 --- a/internal/doctor/wisp_check.go +++ b/internal/doctor/wisp_check.go @@ -124,15 +124,15 @@ func (c *WispGCCheck) countAbandonedWisps(rigPath string) int { return count } -// Fix runs bd wisp gc in each rig with abandoned wisps. +// Fix runs bd mol wisp gc in each rig with abandoned wisps. func (c *WispGCCheck) Fix(ctx *CheckContext) error { var lastErr error for rigName := range c.abandonedRigs { rigPath := filepath.Join(ctx.TownRoot, rigName) - // Run bd --no-daemon wisp gc - cmd := exec.Command("bd", "--no-daemon", "wisp", "gc") + // Run bd --no-daemon mol wisp gc + cmd := exec.Command("bd", "--no-daemon", "mol", "wisp", "gc") cmd.Dir = rigPath if output, err := cmd.CombinedOutput(); err != nil { lastErr = fmt.Errorf("%s: %v (%s)", rigName, err, string(output)) diff --git a/internal/templates/roles/crew.md.tmpl b/internal/templates/roles/crew.md.tmpl index 19bf2890..fcc55756 100644 --- a/internal/templates/roles/crew.md.tmpl +++ b/internal/templates/roles/crew.md.tmpl @@ -42,6 +42,7 @@ Town ({{ .TownRoot }}) - Mail ALWAYS uses town beads - `gt mail` routes there automatically - Project issues use your clone's beads - `bd` commands use local `.beads/` - Run `bd sync` to push/pull beads changes via the `beads-sync` branch +- **GitHub URLs**: Use `git remote -v` to verify repo URLs - never assume orgs like `anthropics/` ## Prefix-Based Routing diff --git a/internal/templates/roles/deacon.md.tmpl b/internal/templates/roles/deacon.md.tmpl index f2fdd42b..4020a0fb 100644 --- a/internal/templates/roles/deacon.md.tmpl +++ b/internal/templates/roles/deacon.md.tmpl @@ -66,7 +66,7 @@ gt mail inbox gt mol attach-from-mail # Step 3: Still nothing? Create patrol wisp (two-step: create then pin) -bd wisp create mol-deacon-patrol +bd mol wisp create mol-deacon-patrol bd update --status=pinned --assignee=deacon ``` @@ -135,7 +135,7 @@ Then squash and decide: bd mol squash --summary="Patrol complete: checked inbox, scanned health, no issues" # Option A: Loop (low context) -bd wisp create mol-deacon-patrol +bd mol wisp create mol-deacon-patrol bd update --status=pinned --assignee=deacon # Continue to first step... diff --git a/internal/templates/roles/mayor.md.tmpl b/internal/templates/roles/mayor.md.tmpl index 16632c46..8eab6e59 100644 --- a/internal/templates/roles/mayor.md.tmpl +++ b/internal/templates/roles/mayor.md.tmpl @@ -68,6 +68,7 @@ Town ({{ .TownRoot }}) - **Rig beads**: Project work lives in git worktrees (crew/*, polecats/*) - The rig-level `/.beads/` is **gitignored** (local runtime state) - Rig beads use `beads-sync` branch for multi-clone coordination +- **GitHub URLs**: Use `git remote -v` to verify repo URLs - never assume orgs like `anthropics/` ## Prefix-Based Routing diff --git a/internal/templates/roles/polecat.md.tmpl b/internal/templates/roles/polecat.md.tmpl index 4e63f668..245ae293 100644 --- a/internal/templates/roles/polecat.md.tmpl +++ b/internal/templates/roles/polecat.md.tmpl @@ -39,6 +39,7 @@ Town ({{ .TownRoot }}) - You're in a project git worktree - your `.beads/` is tracked in the project repo - The rig-level `{{ .RigName }}/.beads/` is **gitignored** (local runtime state) - Run `bd sync` to push/pull beads changes via the `beads-sync` branch +- **GitHub URLs**: Use `git remote -v` to verify repo URLs - never assume orgs like `anthropics/` ## Prefix-Based Routing diff --git a/internal/templates/roles/witness.md.tmpl b/internal/templates/roles/witness.md.tmpl index 72af7432..2b159d51 100644 --- a/internal/templates/roles/witness.md.tmpl +++ b/internal/templates/roles/witness.md.tmpl @@ -99,7 +99,7 @@ gt mail inbox gt mol attach-from-mail # Step 4: Still nothing? Create patrol wisp -bd wisp mol-witness-patrol --assignee={{ .RigName }}/witness +bd mol wisp mol-witness-patrol --assignee={{ .RigName }}/witness ``` **Hook → Execute. No exceptions.**