From ed875aed6f2afd08b678ecb077cb61985a9579c4 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:07:07 +0100 Subject: [PATCH 01/41] fix(polecat): improve lifecycle handling and prevent premature cleanup Three related fixes for polecat lifecycle management: 1. Push branch to origin before self-nuke (done.go) - Ensures work is preserved on remote before worktree cleanup - Prevents orphaned local-only branches 2. Respect cleanup_status in selfNukePolecat (done.go) - Changed nuclear=true to nuclear=false - Validates cleanup_status before removal - Prevents destruction with uncommitted/unpushed work 3. Respawn done polecats with hooked work (manager.go, handlers.go) - loadFromBeads now checks hook_bead field - Added FindPolecatsWithHookedWork() and RespawnPolecatWithHookedWork() - Witness can auto-respawn polecats that have pending work Fixes #360 --- internal/cmd/done.go | 21 ++++- internal/polecat/manager.go | 23 +++++- internal/witness/handlers.go | 151 +++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+), 5 deletions(-) diff --git a/internal/cmd/done.go b/internal/cmd/done.go index fa4af5013..c284ecabc 100644 --- a/internal/cmd/done.go +++ b/internal/cmd/done.go @@ -378,6 +378,20 @@ func runDone(cmd *cobra.Command, args []string) error { selfNukeAttempted := false if exitType == ExitCompleted { if roleInfo, err := GetRoleWithContext(cwd, townRoot); err == nil && roleInfo.Role == RolePolecat { + // CRITICAL: Push branch to origin before self-nuking + // The Refinery needs the branch to be accessible after the polecat's + // worktree is deleted. Without this push, the branch only exists locally + // in the polecat's worktree and will be lost when self-nuke removes it. + fmt.Printf("\nPushing branch to origin before self-nuke...\n") + if err := g.Push("origin", branch, false); err != nil { + // Push failure is fatal - we cannot self-nuke without pushing + // The work must be preserved for the Refinery to process + fmt.Fprintf(os.Stderr, "Error: failed to push branch to origin: %v\n", err) + fmt.Fprintf(os.Stderr, "Error: cannot self-nuke without pushing - worktree preserved for manual intervention\n") + return fmt.Errorf("push to origin failed (self-nuke aborted): %w", err) + } + fmt.Printf("%s Branch pushed to origin\n", style.Bold.Render("✓")) + selfNukeAttempted = true if err := selfNukePolecat(roleInfo, townRoot); err != nil { // Non-fatal: Witness will clean up if we fail @@ -550,9 +564,10 @@ func selfNukePolecat(roleInfo RoleInfo, _ string) error { return fmt.Errorf("getting polecat manager: %w", err) } - // Use nuclear=true since we know we just pushed our work - // The branch is pushed, MR is created, we're clean - if err := mgr.RemoveWithOptions(roleInfo.Polecat, true, true); err != nil { + // Use nuclear=false to respect cleanup_status safety checks (ZFC #10) + // The agent's self-reported cleanup_status will be validated before removal + // This prevents accidental work loss if git state doesn't match expectations + if err := mgr.RemoveWithOptions(roleInfo.Polecat, true, false); err != nil { return fmt.Errorf("removing worktree: %w", err) } diff --git a/internal/polecat/manager.go b/internal/polecat/manager.go index 23389c3a7..bbc73826f 100644 --- a/internal/polecat/manager.go +++ b/internal/polecat/manager.go @@ -785,8 +785,10 @@ func (m *Manager) ClearIssue(name string) error { return nil } -// loadFromBeads gets polecat info from beads assignee field. -// State is simple: issue assigned → working, no issue → done (ready for cleanup). +// loadFromBeads gets polecat info from beads assignee field and agent bead hook_bead. +// State is determined by: has assigned issue OR has hook_bead → working, neither → done. +// This fixes the bug where polecats with newly hooked work show as "done" because +// the issue assignee hasn't been updated yet. // Transient polecats should always have work; no work means ready for Witness cleanup. // We don't interpret issue status (ZFC: Go is transport, not decision-maker). func (m *Manager) loadFromBeads(name string) (*Polecat, error) { @@ -826,6 +828,23 @@ func (m *Manager) loadFromBeads(name string) (*Polecat, error) { state = StateWorking } + // FIX (hq-50u3h): Also check agent bead's hook_bead field. + // If hook_bead is set, the polecat has work waiting and should be "working". + // This prevents polecats from showing as "done" when new work is hooked via gt sling. + // gt sling sets hook_bead atomically, so this is the reliable signal for pending work. + agentBeadID := m.agentBeadID(name) + if _, fields, err := m.beads.GetAgentBead(agentBeadID); err == nil && fields != nil { + if fields.HookBead != "" { + // Polecat has hooked work - should be working, not done + state = StateWorking + // If issueID is empty, use the hook_bead as the issue reference + // This ensures the hooked work is visible in listings + if issueID == "" { + issueID = fields.HookBead + } + } + } + return &Polecat{ Name: name, Rig: m.rig.Name, diff --git a/internal/witness/handlers.go b/internal/witness/handlers.go index a901a6a1c..3586611cd 100644 --- a/internal/witness/handlers.go +++ b/internal/witness/handlers.go @@ -11,6 +11,7 @@ import ( "github.com/steveyegge/gastown/internal/beads" "github.com/steveyegge/gastown/internal/git" "github.com/steveyegge/gastown/internal/mail" + "github.com/steveyegge/gastown/internal/polecat" "github.com/steveyegge/gastown/internal/rig" "github.com/steveyegge/gastown/internal/tmux" "github.com/steveyegge/gastown/internal/util" @@ -811,3 +812,153 @@ func verifyCommitOnMain(workDir, rigName, polecatName string) (bool, error) { // Commit is not on any remote's default branch return false, nil } + +// PolecatsWithHookedWork contains info about polecats that have hooked work but no active session. +type PolecatsWithHookedWork struct { + PolecatName string + HookBead string + RigName string +} + +// FindPolecatsWithHookedWork finds polecats that have hooked work but no active tmux session. +// These are polecats that completed work (gt done) but then had new work slung to them via gt sling. +// They need to be respawned to process the hooked work. +// Returns a list of such polecats that should be respawned. +// +// FIX (hq-50u3h): This function addresses the bug where done polecats don't process hooked work. +// The fix checks each polecat's agent bead for hook_bead and verifies no active tmux session. +func FindPolecatsWithHookedWork(workDir, rigName string) ([]*PolecatsWithHookedWork, error) { + townRoot, err := workspace.Find(workDir) + if err != nil || townRoot == "" { + return nil, fmt.Errorf("finding town root: %w", err) + } + + // Get beads directory + rigPath := filepath.Join(townRoot, rigName) + bd := beads.New(rigPath) + t := tmux.NewTmux() + + var result []*PolecatsWithHookedWork + + // Get all polecat agent beads (returns map of bead ID to Issue) + agentBeads, err := bd.ListAgentBeads() + if err != nil { + return nil, fmt.Errorf("listing agent beads: %w", err) + } + + // Filter for polecat agents in this rig + // Format: --polecat- + polecatSuffix := fmt.Sprintf("%s-polecat-", rigName) + for agentID := range agentBeads { + // Check if this is a polecat agent bead for this rig + if !strings.Contains(agentID, polecatSuffix) { + continue + } + + // Extract polecat name from agent ID + parts := strings.Split(agentID, "-polecat-") + if len(parts) < 2 { + continue + } + polecatName := parts[len(parts)-1] + + // Get agent bead fields to check hook_bead + _, fields, err := bd.GetAgentBead(agentID) + if err != nil || fields == nil { + // Skip if we can't get agent bead info + continue + } + + // Check if hook_bead is set (indicating work is waiting) + if fields.HookBead == "" { + continue + } + + // Check if polecat has an active tmux session + sessionName := fmt.Sprintf("gt-%s-%s", rigName, polecatName) + hasSession, _ := t.HasSession(sessionName) + + if hasSession { + // Session is active - polecat is already working + continue + } + + // Polecat has hooked work but no active session - needs respawn + result = append(result, &PolecatsWithHookedWork{ + PolecatName: polecatName, + HookBead: fields.HookBead, + RigName: rigName, + }) + } + + return result, nil +} + +// RespawnPolecatWithHookedWork respawns a polecat to process its hooked work. +// This is used when a polecat has completed work (gt done) but new work was slung to it. +// The polecat's session is restarted to process the hooked work. +// +// FIX (hq-50u3h): This function respawns polecats with hooked work but no active session. +func RespawnPolecatWithHookedWork(workDir, rigName, polecatName string) error { + townRoot, err := workspace.Find(workDir) + if err != nil || townRoot == "" { + return fmt.Errorf("finding town root: %w", err) + } + + rigPath := filepath.Join(townRoot, rigName) + // Create rig struct directly (no LoadRig function exists) + r := &rig.Rig{ + Name: rigName, + Path: rigPath, + } + + // Get the polecat manager + g := git.NewGit(rigPath) + mgr := polecat.NewManager(r, g) + + // Get the hook_bead from the agent bead + prefix := beads.GetPrefixForRig(townRoot, rigName) + agentBeadID := beads.PolecatBeadIDWithPrefix(prefix, rigName, polecatName) + bd := beads.New(rigPath) + _, fields, err := bd.GetAgentBead(agentBeadID) + if err != nil || fields == nil { + return fmt.Errorf("getting agent bead: %w", err) + } + + if fields.HookBead == "" { + return fmt.Errorf("no hooked work found for polecat %s", polecatName) + } + + // Check if polecat directory exists (using Get to check if polecat exists) + _, err = mgr.Get(polecatName) + if err != nil { + // Polecat doesn't exist - need to create it fresh + _, err := mgr.AddWithOptions(polecatName, polecat.AddOptions{ + HookBead: fields.HookBead, + }) + if err != nil { + return fmt.Errorf("creating polecat: %w", err) + } + } else { + // Polecat exists - repair it to get a fresh worktree + _, err := mgr.RepairWorktreeWithOptions(polecatName, true, polecat.AddOptions{ + HookBead: fields.HookBead, + }) + if err != nil { + return fmt.Errorf("repairing polecat worktree: %w", err) + } + } + + // Start a new tmux session for the polecat + t := tmux.NewTmux() + sessionMgr := polecat.NewSessionManager(t, r) + + err = sessionMgr.Start(polecatName, polecat.SessionStartOptions{ + Issue: fields.HookBead, + }) + if err != nil { + return fmt.Errorf("starting polecat session: %w", err) + } + + return nil +} From 88134d9731ac54b0e06a785c1a079ad7165db6cf Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:08:03 +0100 Subject: [PATCH 02/41] fix(boot): improve Boot and Deacon startup behavior Two fixes for daemon-managed agent startup: 1. Boot watchdog CLAUDE.md creation (boot.go, templates.go) - Add CreateBootCLAUDEmd function to templates package - Add EnsureCLAUDEmd method to create context before session spawn - Enables Boot to perform intelligent triage decisions 2. Deacon startup auto-execution (deacon.go) - Execute gt prime directly via SendKeys instead of nudge message - Prevents text appearing in prompt area without execution - Fixes endless restart loop in Claude Code v2.1.4+ --- internal/boot/boot.go | 28 ++++++++++++++++++++++++++++ internal/cmd/deacon.go | 15 +++++++++------ internal/templates/templates.go | 27 ++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/internal/boot/boot.go b/internal/boot/boot.go index af4350aa1..56c1ee377 100644 --- a/internal/boot/boot.go +++ b/internal/boot/boot.go @@ -9,10 +9,12 @@ import ( "os" "os/exec" "path/filepath" + "strings" "time" "github.com/steveyegge/gastown/internal/beads" "github.com/steveyegge/gastown/internal/config" + "github.com/steveyegge/gastown/internal/templates" "github.com/steveyegge/gastown/internal/tmux" ) @@ -64,6 +66,27 @@ func (b *Boot) EnsureDir() error { return os.MkdirAll(b.bootDir, 0755) } +// EnsureCLAUDEmd ensures Boot's CLAUDE.md exists with proper context. +// Creates it from the boot role template if missing. +func (b *Boot) EnsureCLAUDEmd() error { + claudePath := filepath.Join(b.bootDir, "CLAUDE.md") + + // Check if CLAUDE.md already exists + if _, err := os.Stat(claudePath); err == nil { + // File exists, nothing to do + return nil + } + + // Create CLAUDE.md from template + townName := filepath.Base(b.townRoot) + // Deacon session name is "hq-{townname}" or just "hq-deacon" for town root + deaconSession := "hq-deacon" + if townName != "" && strings.ToLower(townName) != "gt" { + deaconSession = fmt.Sprintf("hq-%s", strings.ToLower(townName)) + } + return templates.CreateBootCLAUDEmd(b.bootDir, b.townRoot, townName, deaconSession) +} + // markerPath returns the path to the marker file. func (b *Boot) markerPath() string { return filepath.Join(b.bootDir, MarkerFileName) @@ -170,6 +193,11 @@ func (b *Boot) spawnTmux() error { return fmt.Errorf("ensuring boot dir: %w", err) } + // Ensure CLAUDE.md exists with proper Boot context + if err := b.EnsureCLAUDEmd(); err != nil { + return fmt.Errorf("ensuring boot CLAUDE.md: %w", err) + } + // Create new session in boot directory (not deacon dir) so Claude reads Boot's CLAUDE.md if err := b.tmux.NewSession(SessionName, b.bootDir); err != nil { return fmt.Errorf("creating boot session: %w", err) diff --git a/internal/cmd/deacon.go b/internal/cmd/deacon.go index 399d15a3c..576826f0a 100644 --- a/internal/cmd/deacon.go +++ b/internal/cmd/deacon.go @@ -394,19 +394,22 @@ func startDeaconSession(t *tmux.Tmux, sessionName, agentOverride string) error { runtimeConfig := config.LoadRuntimeConfig("") _ = runtime.RunStartupFallback(t, sessionName, "deacon", runtimeConfig) + // GUPP: Gas Town Universal Propulsion Principle + // Directly execute gt prime to trigger autonomous patrol execution. + // This bypasses the prompt area - the command runs immediately. + // Wait for Claude to be ready before sending command. + time.Sleep(2 * time.Second) + _ = t.SendKeys(sessionName, "gt prime") // Non-fatal + // Inject startup nudge for predecessor discovery via /resume + // Send AFTER gt prime so the beacon appears in session history, not prompt area + time.Sleep(1 * time.Second) _ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{ Recipient: "deacon", Sender: "daemon", Topic: "patrol", }) // Non-fatal - // GUPP: Gas Town Universal Propulsion Principle - // Send the propulsion nudge to trigger autonomous patrol execution. - // Wait for beacon to be fully processed (needs to be separate prompt) - time.Sleep(2 * time.Second) - _ = t.NudgeSession(sessionName, session.PropulsionNudgeForRole("deacon", deaconDir)) // Non-fatal - return nil } diff --git a/internal/templates/templates.go b/internal/templates/templates.go index 294c61437..223dc8d62 100644 --- a/internal/templates/templates.go +++ b/internal/templates/templates.go @@ -128,7 +128,7 @@ func (t *Templates) RenderMessage(name string, data interface{}) (string, error) // RoleNames returns the list of available role templates. func (t *Templates) RoleNames() []string { - return []string{"mayor", "witness", "refinery", "polecat", "crew", "deacon"} + return []string{"mayor", "witness", "refinery", "polecat", "crew", "deacon", "boot"} } // MessageNames returns the list of available message templates. @@ -162,6 +162,31 @@ func CreateMayorCLAUDEmd(mayorDir, townRoot, townName, mayorSession, deaconSessi return os.WriteFile(claudePath, []byte(content), 0644) } +// CreateBootCLAUDEmd creates the Boot watchdog's CLAUDE.md file at the specified directory. +// This ensures Boot has proper context when spawned by the daemon. +func CreateBootCLAUDEmd(bootDir, townRoot, townName, deaconSession string) error { + tmpl, err := New() + if err != nil { + return err + } + + data := RoleData{ + Role: "boot", + TownRoot: townRoot, + TownName: townName, + WorkDir: bootDir, + DeaconSession: deaconSession, + } + + content, err := tmpl.RenderRole("boot", data) + if err != nil { + return err + } + + claudePath := filepath.Join(bootDir, "CLAUDE.md") + return os.WriteFile(claudePath, []byte(content), 0644) +} + // GetAllRoleTemplates returns all role templates as a map of filename to content. func GetAllRoleTemplates() (map[string][]byte, error) { entries, err := templateFS.ReadDir("roles") From bb7621f651fb07c9d746a6eda5a851c19b34dac8 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:08:37 +0100 Subject: [PATCH 03/41] fix(witness): improve patrol hook handling 1. Attach new patrol wisp to hook for autonomous continuation - Ensures witness continues patrol after session restart 2. Add --hook flag to SessionStart hooks in createPatrolHooks - Properly signals hook attachment during session creation --- .beads/formulas/mol-witness-patrol.formula.toml | 2 +- internal/formula/formulas/mol-witness-patrol.formula.toml | 2 +- internal/rig/manager.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.beads/formulas/mol-witness-patrol.formula.toml b/.beads/formulas/mol-witness-patrol.formula.toml index 12c612b92..b2c4dd034 100644 --- a/.beads/formulas/mol-witness-patrol.formula.toml +++ b/.beads/formulas/mol-witness-patrol.formula.toml @@ -56,7 +56,7 @@ needs = ['patrol-cleanup'] title = 'Check own context limit' [[steps]] -description = "End of patrol cycle decision.\n\n**If context LOW** (can continue patrolling):\n1. Generate a brief summary of this patrol cycle\n2. Squash the current wisp:\n```bash\nbd mol squash --summary \"\"\n```\n3. Create a new patrol wisp:\n```bash\nbd mol wisp mol-witness-patrol\n```\n4. Continue executing from the inbox-check step of the new wisp\n\n**If context HIGH** (approaching limit):\n1. Write handoff mail with notable observations:\n```bash\ngt handoff -s \"Witness patrol handoff\" -m \"\"\n```\n2. Exit cleanly - the daemon will respawn a fresh Witness session\n\n**IMPORTANT**: You must either create a new wisp (context LOW) or exit (context HIGH).\nNever leave the session idle without work on your hook." +description = "End of patrol cycle decision.\n\n**If context LOW** (can continue patrolling):\n1. Generate a brief summary of this patrol cycle\n2. Squash the current wisp:\n```bash\nbd mol squash --summary \"\"\n```\n3. Create and attach a new patrol wisp:\n```bash\n# Get the new wisp ID\nNEW_WISP=$(bd mol wisp mol-witness-patrol --json | jq -r '.new_epic_id')\n# Attach the new wisp to your hook\ngt mol attach \"$NEW_WISP\"\n```\n4. Continue executing from the inbox-check step of the new wisp\n\n**If context HIGH** (approaching limit):\n1. Write handoff mail with notable observations:\n```bash\ngt handoff -s \"Witness patrol handoff\" -m \"\"\n```\n2. Exit cleanly - the daemon will respawn a fresh Witness session\n\n**IMPORTANT**: You must either create a new wisp (context LOW) or exit (context HIGH).\nNever leave the session idle without work on your hook." id = 'loop-or-exit' needs = ['context-check'] title = 'Loop or exit for respawn' diff --git a/internal/formula/formulas/mol-witness-patrol.formula.toml b/internal/formula/formulas/mol-witness-patrol.formula.toml index 12c612b92..b2c4dd034 100644 --- a/internal/formula/formulas/mol-witness-patrol.formula.toml +++ b/internal/formula/formulas/mol-witness-patrol.formula.toml @@ -56,7 +56,7 @@ needs = ['patrol-cleanup'] title = 'Check own context limit' [[steps]] -description = "End of patrol cycle decision.\n\n**If context LOW** (can continue patrolling):\n1. Generate a brief summary of this patrol cycle\n2. Squash the current wisp:\n```bash\nbd mol squash --summary \"\"\n```\n3. Create a new patrol wisp:\n```bash\nbd mol wisp mol-witness-patrol\n```\n4. Continue executing from the inbox-check step of the new wisp\n\n**If context HIGH** (approaching limit):\n1. Write handoff mail with notable observations:\n```bash\ngt handoff -s \"Witness patrol handoff\" -m \"\"\n```\n2. Exit cleanly - the daemon will respawn a fresh Witness session\n\n**IMPORTANT**: You must either create a new wisp (context LOW) or exit (context HIGH).\nNever leave the session idle without work on your hook." +description = "End of patrol cycle decision.\n\n**If context LOW** (can continue patrolling):\n1. Generate a brief summary of this patrol cycle\n2. Squash the current wisp:\n```bash\nbd mol squash --summary \"\"\n```\n3. Create and attach a new patrol wisp:\n```bash\n# Get the new wisp ID\nNEW_WISP=$(bd mol wisp mol-witness-patrol --json | jq -r '.new_epic_id')\n# Attach the new wisp to your hook\ngt mol attach \"$NEW_WISP\"\n```\n4. Continue executing from the inbox-check step of the new wisp\n\n**If context HIGH** (approaching limit):\n1. Write handoff mail with notable observations:\n```bash\ngt handoff -s \"Witness patrol handoff\" -m \"\"\n```\n2. Exit cleanly - the daemon will respawn a fresh Witness session\n\n**IMPORTANT**: You must either create a new wisp (context LOW) or exit (context HIGH).\nNever leave the session idle without work on your hook." id = 'loop-or-exit' needs = ['context-check'] title = 'Loop or exit for respawn' diff --git a/internal/rig/manager.go b/internal/rig/manager.go index 20ca50f32..96ea8275b 100644 --- a/internal/rig/manager.go +++ b/internal/rig/manager.go @@ -1008,7 +1008,7 @@ func (m *Manager) createPatrolHooks(workspacePath string, runtimeConfig *config. "hooks": [ { "type": "command", - "command": "gt prime && gt mail check --inject" + "command": "gt prime --hook && gt mail check --inject" } ] } @@ -1019,7 +1019,7 @@ func (m *Manager) createPatrolHooks(workspacePath string, runtimeConfig *config. "hooks": [ { "type": "command", - "command": "gt prime" + "command": "gt prime --hook" } ] } From 63ec086cfdec4618e0315e523ad1e9b139ba3e79 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:08:58 +0100 Subject: [PATCH 04/41] fix(refinery): delete remote polecat branches after merge After polecats push their work branches to origin before self-nuke, the refinery was only deleting local branches after merge, leaving stale remote branches accumulating. Added remote branch deletion in handleSuccess and handleSuccessFromQueue to clean up both local and remote copies after successful merge. --- internal/refinery/engineer.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/refinery/engineer.go b/internal/refinery/engineer.go index e9c2877f2..cf6486beb 100644 --- a/internal/refinery/engineer.go +++ b/internal/refinery/engineer.go @@ -449,6 +449,7 @@ func (e *Engineer) handleSuccess(mr *beads.Issue, result ProcessResult) { // Since the self-cleaning model (Jan 10), polecats push to origin before gt done, // so we need to clean up both local and remote branches after merge. if e.config.DeleteMergedBranches && mrFields.Branch != "" { + // Delete local branch if err := e.git.DeleteBranch(mrFields.Branch, true); err != nil { _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete local branch %s: %v\n", mrFields.Branch, err) } else { @@ -563,13 +564,22 @@ func (e *Engineer) handleSuccessFromQueue(mr *mrqueue.MR, result ProcessResult) } } - // 2. Delete source branch if configured (local only) + // 2. Delete source branch if configured (both local and remote) + // After the polecat self-nuke fix, branches are pushed to origin before the + // worktree is deleted, so we need to clean up both local and remote copies. if e.config.DeleteMergedBranches && mr.Branch != "" { + // Delete local branch if err := e.git.DeleteBranch(mr.Branch, true); err != nil { - _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete branch %s: %v\n", mr.Branch, err) + _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete local branch %s: %v\n", mr.Branch, err) } else { _, _ = fmt.Fprintf(e.output, "[Engineer] Deleted local branch: %s\n", mr.Branch) } + // Delete remote branch from origin + if err := e.git.DeleteRemoteBranch("origin", mr.Branch); err != nil { + _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete remote branch %s from origin: %v\n", mr.Branch, err) + } else { + _, _ = fmt.Fprintf(e.output, "[Engineer] Deleted remote branch: %s\n", mr.Branch) + } } // 3. Remove MR from queue (ephemeral - just delete the file) From 9d9c981c7dfec2ec69f3f513aa51c82cf66d03f1 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:10:25 +0100 Subject: [PATCH 05/41] feat(synthesis): record output location metadata on completed leg beads When convoy leg beads complete, they now record output_path metadata so synthesis workflows can discover and aggregate outputs without hunting through worktrees or guessing branch names. Changes: - formula.go: parse output section, include output_path in leg descriptions - convoy.go: add Description field to issueDetails for metadata parsing - synthesis.go: parse output_path from leg descriptions with template fallback Fixes #303 --- internal/cmd/convoy.go | 55 +++++++++++++++++++++------------------ internal/cmd/formula.go | 55 +++++++++++++++++++++++++++++++++++++++ internal/cmd/synthesis.go | 43 +++++++++++++++++++++++++++++- 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/internal/cmd/convoy.go b/internal/cmd/convoy.go index a6a191117..afcc414c4 100644 --- a/internal/cmd/convoy.go +++ b/internal/cmd/convoy.go @@ -1115,11 +1115,12 @@ func getTrackedIssues(townBeads, convoyID string) []trackedIssueInfo { // issueDetails holds basic issue info. type issueDetails struct { - ID string - Title string - Status string - IssueType string - Assignee string + ID string + Title string + Status string + IssueType string + Assignee string + Description string } // getIssueDetailsBatch fetches details for multiple issues in a single bd show call. @@ -1151,11 +1152,12 @@ func getIssueDetailsBatch(issueIDs []string) map[string]*issueDetails { } var issues []struct { - ID string `json:"id"` - Title string `json:"title"` - Status string `json:"status"` - IssueType string `json:"issue_type"` - Assignee string `json:"assignee"` + ID string `json:"id"` + Title string `json:"title"` + Status string `json:"status"` + IssueType string `json:"issue_type"` + Assignee string `json:"assignee"` + Description string `json:"description"` } if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil { return result @@ -1163,11 +1165,12 @@ func getIssueDetailsBatch(issueIDs []string) map[string]*issueDetails { for _, issue := range issues { result[issue.ID] = &issueDetails{ - ID: issue.ID, - Title: issue.Title, - Status: issue.Status, - IssueType: issue.IssueType, - Assignee: issue.Assignee, + ID: issue.ID, + Title: issue.Title, + Status: issue.Status, + IssueType: issue.IssueType, + Assignee: issue.Assignee, + Description: issue.Description, } } @@ -1192,22 +1195,24 @@ func getIssueDetails(issueID string) *issueDetails { } var issues []struct { - ID string `json:"id"` - Title string `json:"title"` - Status string `json:"status"` - IssueType string `json:"issue_type"` - Assignee string `json:"assignee"` + ID string `json:"id"` + Title string `json:"title"` + Status string `json:"status"` + IssueType string `json:"issue_type"` + Assignee string `json:"assignee"` + Description string `json:"description"` } if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil || len(issues) == 0 { return nil } return &issueDetails{ - ID: issues[0].ID, - Title: issues[0].Title, - Status: issues[0].Status, - IssueType: issues[0].IssueType, - Assignee: issues[0].Assignee, + ID: issues[0].ID, + Title: issues[0].Title, + Status: issues[0].Status, + IssueType: issues[0].IssueType, + Assignee: issues[0].Assignee, + Description: issues[0].Description, } } diff --git a/internal/cmd/formula.go b/internal/cmd/formula.go index ce417046f..b661c5c72 100644 --- a/internal/cmd/formula.go +++ b/internal/cmd/formula.go @@ -345,6 +345,14 @@ func executeConvoyFormula(f *formulaData, formulaName, targetRig string) error { fmt.Printf("%s Created convoy: %s\n", style.Bold.Render("✓"), convoyID) + // Derive review_id from PR or convoyID + reviewID := "" + if formulaRunPR > 0 { + reviewID = fmt.Sprintf("pr-%d", formulaRunPR) + } else { + reviewID = strings.TrimPrefix(convoyID, "hq-cv-") + } + // Step 2: Create leg beads and track them legBeads := make(map[string]string) // leg.ID -> bead ID for _, leg := range f.Legs { @@ -358,6 +366,16 @@ func executeConvoyFormula(f *formulaData, formulaName, targetRig string) error { } } + // Add output_path metadata if output config is available + if f.Output != nil && f.Output.Directory != "" && f.Output.LegPattern != "" { + // Expand output path template + outputPath := filepath.Join( + strings.ReplaceAll(f.Output.Directory, "{{review_id}}", reviewID), + strings.ReplaceAll(f.Output.LegPattern, "{{leg.id}}", leg.ID), + ) + legDesc = fmt.Sprintf("%s\n\noutput_path: %s", legDesc, outputPath) + } + legArgs := []string{ "create", "--type=task", @@ -487,11 +505,18 @@ type formulaData struct { Name string Description string Type string + Output *formulaOutput Legs []formulaLeg Synthesis *formulaSynthesis Prompts map[string]string } +type formulaOutput struct { + Directory string + LegPattern string + Synthesis string +} + type formulaLeg struct { ID string Title string @@ -569,6 +594,9 @@ func parseFormulaFile(path string) (*formulaData, error) { f.Type = match } + // Parse output section + f.Output = extractOutput(content) + // Parse legs (convoy formulas) f.Legs = extractLegs(content) @@ -713,6 +741,33 @@ func extractPrompts(content string) map[string]string { return prompts } +// extractOutput parses [output] section from TOML +func extractOutput(content string) *formulaOutput { + idx := strings.Index(content, "[output]") + if idx == -1 { + return nil + } + + section := content[idx:] + // Find where section ends + if endIdx := strings.Index(section[1:], "\n["); endIdx != -1 { + section = section[:endIdx+1] + } + + output := &formulaOutput{ + Directory: extractTOMLValue(section, "directory"), + LegPattern: extractTOMLValue(section, "leg_pattern"), + Synthesis: extractTOMLValue(section, "synthesis"), + } + + // Return nil if no output fields found + if output.Directory == "" && output.LegPattern == "" && output.Synthesis == "" { + return nil + } + + return output +} + // generateFormulaShortID generates a short random ID (5 lowercase chars) func generateFormulaShortID() string { b := make([]byte, 3) diff --git a/internal/cmd/synthesis.go b/internal/cmd/synthesis.go index 4799fe1d8..e46ad4c77 100644 --- a/internal/cmd/synthesis.go +++ b/internal/cmd/synthesis.go @@ -428,13 +428,39 @@ func collectLegOutputs(meta *ConvoyMeta, f *formula.Formula) ([]LegOutput, bool, if output.Status != "closed" { allComplete = false } + + // Try to get output_path from leg bead description + if details != nil && details.Description != "" { + outputPath := parseOutputPathFromDescription(details.Description) + if outputPath != "" { + output.FilePath = outputPath + // Try to read the file content + if content, err := os.ReadFile(outputPath); err == nil { + output.Content = string(content) + output.HasFile = true + } + } + } + outputs = append(outputs, output) } } - // If we have a formula, also try to find output files + // If we have a formula, also try to find output files using template (fallback) if f != nil && f.Output != nil && meta.ReviewID != "" { for _, leg := range f.Legs { + // Check if we already have this leg's output from description + alreadyFound := false + for _, out := range outputs { + if out.LegID == leg.ID && out.HasFile { + alreadyFound = true + break + } + } + if alreadyFound { + continue + } + // Expand output path template outputPath := expandOutputPath(f.Output.Directory, f.Output.LegPattern, meta.ReviewID, leg.ID) @@ -481,6 +507,21 @@ func expandOutputPath(directory, pattern, reviewID, legID string) string { return filepath.Join(dir, file) } +// parseOutputPathFromDescription extracts output_path from a bead's description. +// Looks for "output_path: " pattern in the description. +func parseOutputPathFromDescription(description string) string { + for _, line := range strings.Split(description, "\n") { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "output_path:") || strings.HasPrefix(line, "output-path:") { + parts := strings.SplitN(line, ":", 2) + if len(parts) == 2 { + return strings.TrimSpace(parts[1]) + } + } + } + return "" +} + // createSynthesisBead creates a bead for the synthesis step. func createSynthesisBead(convoyID string, meta *ConvoyMeta, f *formula.Formula, legOutputs []LegOutput, reviewID string) (string, error) { From b241c0b791654798b1d69fdc610c62282a82be23 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:10:54 +0100 Subject: [PATCH 06/41] feat(rig): add push_url config for read-only upstream repos Adds support for configuring a separate push URL (fork) when the upstream repository is read-only. This allows polecats to push to a personal fork while still pulling from the upstream repository. Changes: - Added PushURL field to RigConfig and Rig struct - Added PushURL to AddRigOptions - Added ConfigurePushURL function to git package - Configure push URL in bare repo when PushURL is set Usage: gt rig add --git-url=https://github.com/upstream/repo \ --push-url=https://github.com/user/fork \ myrig --- internal/git/git.go | 8 ++++++++ internal/rig/manager.go | 21 +++++++++++++++++++-- internal/rig/types.go | 6 +++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/internal/git/git.go b/internal/git/git.go index 4fb0eac59..af1a7f6b9 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -240,6 +240,14 @@ func (g *Git) Pull(remote, branch string) error { return err } +// ConfigurePushURL sets the push URL for a remote while keeping the fetch URL. +// This is useful for read-only upstream repos where you want to push to a fork. +// Example: ConfigurePushURL("origin", "https://github.com/user/fork.git") +func (g *Git) ConfigurePushURL(remote, pushURL string) error { + _, err := g.run("remote", "set-url", remote, "--push", pushURL) + return err +} + // Push pushes to the remote branch. func (g *Git) Push(remote, branch string, force bool) error { args := []string{"push", remote, branch} diff --git a/internal/rig/manager.go b/internal/rig/manager.go index 20ca50f32..16f1dee78 100644 --- a/internal/rig/manager.go +++ b/internal/rig/manager.go @@ -29,7 +29,8 @@ type RigConfig struct { Type string `json:"type"` // "rig" Version int `json:"version"` // schema version Name string `json:"name"` // rig name - GitURL string `json:"git_url"` // repository URL + GitURL string `json:"git_url"` // repository URL (fetch/pull) + PushURL string `json:"push_url,omitempty"` // optional push URL (fork for read-only upstreams) LocalRepo string `json:"local_repo,omitempty"` // optional local reference repo DefaultBranch string `json:"default_branch,omitempty"` // main, master, etc. CreatedAt time.Time `json:"created_at"` // when rig was created @@ -115,6 +116,11 @@ func (m *Manager) loadRig(name string, entry config.RigEntry) (*Rig, error) { Config: entry.BeadsConfig, } + // Read PushURL from rig config if available + if rigCfg, err := LoadRigConfig(rigPath); err == nil { + rig.PushURL = rigCfg.PushURL + } + // Scan for polecats polecatsDir := filepath.Join(rigPath, "polecats") if entries, err := os.ReadDir(polecatsDir); err == nil { @@ -164,7 +170,8 @@ func (m *Manager) loadRig(name string, entry config.RigEntry) (*Rig, error) { // AddRigOptions configures rig creation. type AddRigOptions struct { Name string // Rig name (directory name) - GitURL string // Repository URL + GitURL string // Repository URL (fetch/pull) + PushURL string // Optional push URL (fork for read-only upstreams) BeadsPrefix string // Beads issue prefix (defaults to derived from name) LocalRepo string // Optional local repo for reference clones DefaultBranch string // Default branch (defaults to auto-detected from remote) @@ -265,6 +272,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) { Version: CurrentRigConfigVersion, Name: opts.Name, GitURL: opts.GitURL, + PushURL: opts.PushURL, LocalRepo: localRepo, CreatedAt: time.Now(), Beads: &BeadsConfig{ @@ -296,6 +304,15 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) { fmt.Printf(" ✓ Created shared bare repo\n") bareGit := git.NewGitWithDir(bareRepoPath, "") + // Configure push URL if provided (for read-only upstream repos) + // This sets origin's push URL to the fork while keeping fetch URL as upstream + if opts.PushURL != "" { + if err := bareGit.ConfigurePushURL("origin", opts.PushURL); err != nil { + return nil, fmt.Errorf("configuring push URL: %w", err) + } + fmt.Printf(" ✓ Configured push URL (fork: %s)\n", opts.PushURL) + } + // Determine default branch: use provided value or auto-detect from remote var defaultBranch string if opts.DefaultBranch != "" { diff --git a/internal/rig/types.go b/internal/rig/types.go index fa69c525e..8634e6f4f 100644 --- a/internal/rig/types.go +++ b/internal/rig/types.go @@ -13,9 +13,13 @@ type Rig struct { // Path is the absolute path to the rig directory. Path string `json:"path"` - // GitURL is the remote repository URL. + // GitURL is the remote repository URL (fetch/pull). GitURL string `json:"git_url"` + // PushURL is an optional push URL for read-only upstreams. + // When set, polecats push here instead of to GitURL (e.g., personal fork). + PushURL string `json:"push_url,omitempty"` + // LocalRepo is an optional local repository used for reference clones. LocalRepo string `json:"local_repo,omitempty"` From 781073cc3a0c72ac30470135735ef7fa50ab7b19 Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 19:12:17 +0100 Subject: [PATCH 07/41] docs(readme): add Discord server link Add Community section with link to Discord server for real-time support and collaboration. Fixes #305 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b1c124ece..8a647ef1e 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,10 @@ Git-backed issue tracking system that stores work state as structured data. > **New to Gas Town?** See the [Glossary](docs/glossary.md) for a complete guide to terminology and concepts. +## Community + +Join the [Gas Town Discord server](https://discord.gg/ZbEFb2Yg) for real-time discussion, troubleshooting, and collaboration with other Gas Town users. + ## Installation ### Prerequisites From d509f7cdbee71222d5abcf3923fad3794ff6bf1a Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 22:11:39 +0100 Subject: [PATCH 08/41] fix(mayor): use CLI prompt for propulsion instead of unreliable nudges The post-startup nudges were arriving before Claude Code's input was ready, causing only the Enter key to make it through (empty input). Changes: - Pass "gt prime" as CLI argument to Claude Code startup command - Remove unreliable post-startup nudges and timing delays - The SessionStart hook provides a backup propulsion mechanism The CLI prompt approach is more reliable because the prompt is queued before Claude even starts, avoiding timing issues entirely. Fixes: gt-x7p3 --- internal/mayor/manager.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/internal/mayor/manager.go b/internal/mayor/manager.go index 896ffcab2..c15367674 100644 --- a/internal/mayor/manager.go +++ b/internal/mayor/manager.go @@ -79,9 +79,10 @@ func (m *Manager) Start(agentOverride string) error { return fmt.Errorf("ensuring Claude settings: %w", err) } - // Build startup command first - the startup hook handles 'gt prime' automatically + // Build startup command with initial prompt for propulsion. + // The CLI prompt is more reliable than post-startup nudges (which arrive before input is ready). // Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes - startupCmd, err := config.BuildAgentStartupCommandWithAgentOverride("mayor", "mayor", "", "", agentOverride) + startupCmd, err := config.BuildAgentStartupCommandWithAgentOverride("mayor", "mayor", "", "gt prime", agentOverride) if err != nil { return fmt.Errorf("building startup command: %w", err) } @@ -117,20 +118,9 @@ func (m *Manager) Start(agentOverride string) error { // Accept bypass permissions warning dialog if it appears. _ = t.AcceptBypassPermissionsWarning(sessionID) - time.Sleep(constants.ShutdownNotifyDelay) - - // Inject startup nudge for predecessor discovery via /resume - _ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{ - Recipient: "mayor", - Sender: "human", - Topic: "cold-start", - }) // Non-fatal - - // GUPP: Gas Town Universal Propulsion Principle - // Send the propulsion nudge to trigger autonomous coordination. - // Wait for beacon to be fully processed (needs to be separate prompt) - time.Sleep(2 * time.Second) - _ = t.NudgeSession(sessionID, session.PropulsionNudgeForRole("mayor", mayorDir)) // Non-fatal + // Propulsion is handled by the CLI prompt ("gt prime") passed at startup. + // No need for post-startup nudges which are unreliable (text arrives before input is ready). + // The SessionStart hook also runs "gt prime" as a backup. return nil } From db8a87a9ede5032c37734bf4d0dc9c91f859d41e Mon Sep 17 00:00:00 2001 From: mayor Date: Mon, 12 Jan 2026 22:17:37 +0100 Subject: [PATCH 09/41] fix(templates): add boot role to TestRoleNames expected list The boot role was added but the test expectation wasn't updated, causing TestRoleNames to fail. Fixes: gt-j7wl --- internal/templates/templates_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/templates/templates_test.go b/internal/templates/templates_test.go index 519cc4ebb..32d6aaa83 100644 --- a/internal/templates/templates_test.go +++ b/internal/templates/templates_test.go @@ -235,7 +235,7 @@ func TestRoleNames(t *testing.T) { } names := tmpl.RoleNames() - expected := []string{"mayor", "witness", "refinery", "polecat", "crew", "deacon"} + expected := []string{"mayor", "witness", "refinery", "polecat", "crew", "deacon", "boot"} if len(names) != len(expected) { t.Errorf("RoleNames() = %v, want %v", names, expected) From d32438949dd3288b555e068e0811eede2b8128a5 Mon Sep 17 00:00:00 2001 From: gastown-67 Date: Tue, 13 Jan 2026 00:13:59 +0100 Subject: [PATCH 10/41] fix(agents): use CLI prompt for propulsion instead of unreliable nudges Apply the same fix as Mayor (d509f7cd) to Deacon, Witness, Refinery, and Polecat. Post-startup nudges arrive before Claude Code's input is ready, causing only the Enter key to make it through (empty input). Changes for each agent: - Pass "gt prime" as CLI argument to startup command - Remove unreliable post-startup nudges and timing delays - Keep SessionStart hook as backup propulsion mechanism The CLI prompt approach is more reliable because the prompt is queued before Claude even starts, avoiding timing issues entirely. Fixes: gt-mghw --- internal/deacon/manager.go | 22 ++++++---------------- internal/polecat/session_manager.go | 21 ++++++--------------- internal/refinery/manager.go | 22 ++++++---------------- internal/witness/manager.go | 21 ++++----------------- 4 files changed, 22 insertions(+), 64 deletions(-) diff --git a/internal/deacon/manager.go b/internal/deacon/manager.go index 3696bb113..50675ef97 100644 --- a/internal/deacon/manager.go +++ b/internal/deacon/manager.go @@ -80,9 +80,10 @@ func (m *Manager) Start(agentOverride string) error { return fmt.Errorf("ensuring Claude settings: %w", err) } - // Build startup command first + // Build startup command with initial prompt for propulsion. + // The CLI prompt is more reliable than post-startup nudges (which arrive before input is ready). // Restarts are handled by daemon via ensureDeaconRunning on each heartbeat - startupCmd, err := config.BuildAgentStartupCommandWithAgentOverride("deacon", "deacon", "", "", agentOverride) + startupCmd, err := config.BuildAgentStartupCommandWithAgentOverride("deacon", "deacon", "", "gt prime", agentOverride) if err != nil { return fmt.Errorf("building startup command: %w", err) } @@ -116,20 +117,9 @@ func (m *Manager) Start(agentOverride string) error { // Accept bypass permissions warning dialog if it appears. _ = t.AcceptBypassPermissionsWarning(sessionID) - time.Sleep(constants.ShutdownNotifyDelay) - - // Inject startup nudge for predecessor discovery via /resume - _ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{ - Recipient: "deacon", - Sender: "daemon", - Topic: "patrol", - }) // Non-fatal - - // GUPP: Gas Town Universal Propulsion Principle - // Send the propulsion nudge to trigger autonomous patrol execution. - // Wait for beacon to be fully processed (needs to be separate prompt) - time.Sleep(2 * time.Second) - _ = t.NudgeSession(sessionID, session.PropulsionNudgeForRole("deacon", deaconDir)) // Non-fatal + // Propulsion is handled by the CLI prompt ("gt prime") passed at startup. + // No need for post-startup nudges which are unreliable (text arrives before input is ready). + // The SessionStart hook also runs "gt prime" as a backup. return nil } diff --git a/internal/polecat/session_manager.go b/internal/polecat/session_manager.go index 23acc3a78..cfd37f63a 100644 --- a/internal/polecat/session_manager.go +++ b/internal/polecat/session_manager.go @@ -15,7 +15,6 @@ import ( "github.com/steveyegge/gastown/internal/constants" "github.com/steveyegge/gastown/internal/rig" "github.com/steveyegge/gastown/internal/runtime" - "github.com/steveyegge/gastown/internal/session" "github.com/steveyegge/gastown/internal/tmux" ) @@ -169,10 +168,11 @@ func (m *SessionManager) Start(polecat string, opts SessionStartOptions) error { return fmt.Errorf("ensuring runtime settings: %w", err) } - // Build startup command first + // Build startup command with initial prompt for propulsion. + // The CLI prompt is more reliable than post-startup nudges (which arrive before input is ready). command := opts.Command if command == "" { - command = config.BuildPolecatStartupCommand(m.rig.Name, polecat, m.rig.Path, "") + command = config.BuildPolecatStartupCommand(m.rig.Name, polecat, m.rig.Path, "gt prime") } // Prepend runtime config dir env if needed if runtimeConfig.Session != nil && runtimeConfig.Session.ConfigDirEnv != "" && opts.RuntimeConfigDir != "" { @@ -227,18 +227,9 @@ func (m *SessionManager) Start(polecat string, opts SessionStartOptions) error { runtime.SleepForReadyDelay(runtimeConfig) _ = runtime.RunStartupFallback(m.tmux, sessionID, "polecat", runtimeConfig) - // Inject startup nudge for predecessor discovery via /resume - address := fmt.Sprintf("%s/polecats/%s", m.rig.Name, polecat) - debugSession("StartupNudge", session.StartupNudge(m.tmux, sessionID, session.StartupNudgeConfig{ - Recipient: address, - Sender: "witness", - Topic: "assigned", - MolID: opts.Issue, - })) - - // GUPP: Send propulsion nudge to trigger autonomous work execution - time.Sleep(2 * time.Second) - debugSession("NudgeSession PropulsionNudge", m.tmux.NudgeSession(sessionID, session.PropulsionNudge())) + // Propulsion is handled by the CLI prompt ("gt prime") passed at startup. + // No need for post-startup nudges which are unreliable (text arrives before input is ready). + // The SessionStart hook also runs "gt prime" as a backup. return nil } diff --git a/internal/refinery/manager.go b/internal/refinery/manager.go index 4ff6f647d..c6b39c687 100644 --- a/internal/refinery/manager.go +++ b/internal/refinery/manager.go @@ -19,7 +19,6 @@ import ( "github.com/steveyegge/gastown/internal/mrqueue" "github.com/steveyegge/gastown/internal/rig" "github.com/steveyegge/gastown/internal/runtime" - "github.com/steveyegge/gastown/internal/session" "github.com/steveyegge/gastown/internal/tmux" "github.com/steveyegge/gastown/internal/util" ) @@ -173,9 +172,10 @@ func (m *Manager) Start(foreground bool) error { return fmt.Errorf("ensuring runtime settings: %w", err) } - // Build startup command first + // Build startup command with initial prompt for propulsion. + // The CLI prompt is more reliable than post-startup nudges (which arrive before input is ready). bdActor := fmt.Sprintf("%s/refinery", m.rig.Name) - command := config.BuildAgentStartupCommand("refinery", bdActor, m.rig.Path, "") + command := config.BuildAgentStartupCommand("refinery", bdActor, m.rig.Path, "gt prime") // Create session with command directly to avoid send-keys race condition. // See: https://github.com/anthropics/gastown/issues/280 @@ -229,19 +229,9 @@ func (m *Manager) Start(foreground bool) error { runtime.SleepForReadyDelay(runtimeConfig) _ = runtime.RunStartupFallback(t, sessionID, "refinery", runtimeConfig) - // Inject startup nudge for predecessor discovery via /resume - address := fmt.Sprintf("%s/refinery", m.rig.Name) - _ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{ - Recipient: address, - Sender: "deacon", - Topic: "patrol", - }) // Non-fatal - - // GUPP: Gas Town Universal Propulsion Principle - // Send the propulsion nudge to trigger autonomous patrol execution. - // Wait for beacon to be fully processed (needs to be separate prompt) - time.Sleep(2 * time.Second) - _ = t.NudgeSession(sessionID, session.PropulsionNudgeForRole("refinery", refineryRigDir)) // Non-fatal + // Propulsion is handled by the CLI prompt ("gt prime") passed at startup. + // No need for post-startup nudges which are unreliable (text arrives before input is ready). + // The SessionStart hook also runs "gt prime" as a backup. return nil } diff --git a/internal/witness/manager.go b/internal/witness/manager.go index c88ca6990..9c7491401 100644 --- a/internal/witness/manager.go +++ b/internal/witness/manager.go @@ -14,7 +14,6 @@ import ( "github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/constants" "github.com/steveyegge/gastown/internal/rig" - "github.com/steveyegge/gastown/internal/session" "github.com/steveyegge/gastown/internal/tmux" "github.com/steveyegge/gastown/internal/workspace" ) @@ -231,21 +230,9 @@ func (m *Manager) Start(foreground bool, agentOverride string, envOverrides []st // Accept bypass permissions warning dialog if it appears. _ = t.AcceptBypassPermissionsWarning(sessionID) - time.Sleep(constants.ShutdownNotifyDelay) - - // Inject startup nudge for predecessor discovery via /resume - address := fmt.Sprintf("%s/witness", m.rig.Name) - _ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{ - Recipient: address, - Sender: "deacon", - Topic: "patrol", - }) // Non-fatal - - // GUPP: Gas Town Universal Propulsion Principle - // Send the propulsion nudge to trigger autonomous patrol execution. - // Wait for beacon to be fully processed (needs to be separate prompt) - time.Sleep(2 * time.Second) - _ = t.NudgeSession(sessionID, session.PropulsionNudgeForRole("witness", witnessDir)) // Non-fatal + // Propulsion is handled by the CLI prompt ("gt prime") passed at startup. + // No need for post-startup nudges which are unreliable (text arrives before input is ready). + // The SessionStart hook also runs "gt prime" as a backup. return nil } @@ -288,7 +275,7 @@ func buildWitnessStartCommand(rigPath, rigName, townRoot, agentOverride string, return beads.ExpandRolePattern(roleConfig.StartCommand, townRoot, rigName, "", "witness"), nil } bdActor := fmt.Sprintf("%s/witness", rigName) - command, err := config.BuildAgentStartupCommandWithAgentOverride("witness", bdActor, rigPath, "", agentOverride) + command, err := config.BuildAgentStartupCommandWithAgentOverride("witness", bdActor, rigPath, "gt prime", agentOverride) if err != nil { return "", fmt.Errorf("building startup command: %w", err) } From eacf8c6f2958ff2eeb45dc41e59495a849852c64 Mon Sep 17 00:00:00 2001 From: gastown-68 Date: Tue, 13 Jan 2026 00:14:50 +0100 Subject: [PATCH 11/41] fix(boot): add boot role to RoleTypeFor() and ensure settings.json Boot agent was getting wrong settings template due to: 1. RoleTypeFor() missing "boot" - fell through to Interactive 2. spawnTmux() not calling EnsureSettingsForRole() Add "boot" to autonomous roles list and call EnsureSettingsForRole() in spawnTmux() to create proper .claude/settings.json for Boot. Fixes: gt-hnjp --- internal/boot/boot.go | 6 ++++++ internal/claude/settings.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/boot/boot.go b/internal/boot/boot.go index 56c1ee377..6f46db366 100644 --- a/internal/boot/boot.go +++ b/internal/boot/boot.go @@ -13,6 +13,7 @@ import ( "time" "github.com/steveyegge/gastown/internal/beads" + "github.com/steveyegge/gastown/internal/claude" "github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/templates" "github.com/steveyegge/gastown/internal/tmux" @@ -198,6 +199,11 @@ func (b *Boot) spawnTmux() error { return fmt.Errorf("ensuring boot CLAUDE.md: %w", err) } + // Ensure settings.json exists with autonomous role settings + if err := claude.EnsureSettingsForRole(b.bootDir, "boot"); err != nil { + return fmt.Errorf("ensuring boot settings: %w", err) + } + // Create new session in boot directory (not deacon dir) so Claude reads Boot's CLAUDE.md if err := b.tmux.NewSession(SessionName, b.bootDir); err != nil { return fmt.Errorf("creating boot session: %w", err) diff --git a/internal/claude/settings.go b/internal/claude/settings.go index d5873ddc1..63506f9f8 100644 --- a/internal/claude/settings.go +++ b/internal/claude/settings.go @@ -27,7 +27,7 @@ const ( // RoleTypeFor returns the RoleType for a given role name. func RoleTypeFor(role string) RoleType { switch role { - case "polecat", "witness", "refinery", "deacon": + case "polecat", "witness", "refinery", "deacon", "boot": return Autonomous default: return Interactive From 8b3aedf77972d2f3c4009fa421003bd7421c46f2 Mon Sep 17 00:00:00 2001 From: gastown/refinery Date: Tue, 13 Jan 2026 03:32:32 +0100 Subject: [PATCH 12/41] chore: clean up beads formulas directory --- .beads/.gitignore | 5 + .beads/PRIME.md | 43 - .beads/config.yaml | 7 - .beads/formulas/beads-release.formula.toml | 345 - .beads/formulas/code-review.formula.toml | 319 - .beads/formulas/design.formula.toml | 333 - .beads/formulas/mol-boot-triage.formula.toml | 228 - .../formulas/mol-convoy-cleanup.formula.toml | 209 - .beads/formulas/mol-convoy-feed.formula.toml | 259 - .../formulas/mol-dep-propagate.formula.toml | 208 - .../formulas/mol-digest-generate.formula.toml | 227 - .beads/formulas/mol-gastown-boot.formula.toml | 169 - .beads/formulas/mol-orphan-scan.formula.toml | 312 - .../mol-polecat-code-review.formula.toml | 318 - .../mol-polecat-conflict-resolve.formula.toml | 385 - .../formulas/mol-polecat-lease.formula.toml | 198 - .../mol-polecat-review-pr.formula.toml | 283 - .beads/formulas/mol-polecat-work.formula.toml | 454 -- .../formulas/mol-refinery-patrol.formula.toml | 469 -- .beads/formulas/mol-session-gc.formula.toml | 250 - .../formulas/mol-shutdown-dance.formula.toml | 519 -- .../formulas/mol-sync-workspace.formula.toml | 491 -- .../formulas/mol-town-shutdown.formula.toml | 198 - .beads/formulas/rule-of-five.formula.toml | 33 - .beads/formulas/security-audit.formula.toml | 38 - .beads/formulas/shiny-enterprise.formula.toml | 11 - .beads/formulas/shiny-secure.formula.toml | 8 - .beads/formulas/shiny.formula.toml | 40 - .../formulas/towers-of-hanoi-10.formula.toml | 6188 ----------------- .../formulas/towers-of-hanoi-7.formula.toml | 812 --- .../formulas/towers-of-hanoi-9.formula.toml | 3116 --------- .beads/formulas/towers-of-hanoi.formula.toml | 105 - AGENTS.md | 26 + 33 files changed, 31 insertions(+), 16575 deletions(-) delete mode 100644 .beads/PRIME.md delete mode 100644 .beads/formulas/beads-release.formula.toml delete mode 100644 .beads/formulas/code-review.formula.toml delete mode 100644 .beads/formulas/design.formula.toml delete mode 100644 .beads/formulas/mol-boot-triage.formula.toml delete mode 100644 .beads/formulas/mol-convoy-cleanup.formula.toml delete mode 100644 .beads/formulas/mol-convoy-feed.formula.toml delete mode 100644 .beads/formulas/mol-dep-propagate.formula.toml delete mode 100644 .beads/formulas/mol-digest-generate.formula.toml delete mode 100644 .beads/formulas/mol-gastown-boot.formula.toml delete mode 100644 .beads/formulas/mol-orphan-scan.formula.toml delete mode 100644 .beads/formulas/mol-polecat-code-review.formula.toml delete mode 100644 .beads/formulas/mol-polecat-conflict-resolve.formula.toml delete mode 100644 .beads/formulas/mol-polecat-lease.formula.toml delete mode 100644 .beads/formulas/mol-polecat-review-pr.formula.toml delete mode 100644 .beads/formulas/mol-polecat-work.formula.toml delete mode 100644 .beads/formulas/mol-refinery-patrol.formula.toml delete mode 100644 .beads/formulas/mol-session-gc.formula.toml delete mode 100644 .beads/formulas/mol-shutdown-dance.formula.toml delete mode 100644 .beads/formulas/mol-sync-workspace.formula.toml delete mode 100644 .beads/formulas/mol-town-shutdown.formula.toml delete mode 100644 .beads/formulas/rule-of-five.formula.toml delete mode 100644 .beads/formulas/security-audit.formula.toml delete mode 100644 .beads/formulas/shiny-enterprise.formula.toml delete mode 100644 .beads/formulas/shiny-secure.formula.toml delete mode 100644 .beads/formulas/shiny.formula.toml delete mode 100644 .beads/formulas/towers-of-hanoi-10.formula.toml delete mode 100644 .beads/formulas/towers-of-hanoi-7.formula.toml delete mode 100644 .beads/formulas/towers-of-hanoi-9.formula.toml delete mode 100644 .beads/formulas/towers-of-hanoi.formula.toml diff --git a/.beads/.gitignore b/.beads/.gitignore index 4a7a77df9..d27a1db57 100644 --- a/.beads/.gitignore +++ b/.beads/.gitignore @@ -32,6 +32,11 @@ beads.left.meta.json beads.right.jsonl beads.right.meta.json +# Sync state (local-only, per-machine) +# These files are machine-specific and should not be shared across clones +.sync.lock +sync_base.jsonl + # NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here. # They would override fork protection in .git/info/exclude, allowing # contributors to accidentally commit upstream issue databases. diff --git a/.beads/PRIME.md b/.beads/PRIME.md deleted file mode 100644 index 64b684da2..000000000 --- a/.beads/PRIME.md +++ /dev/null @@ -1,43 +0,0 @@ -# Gas Town Worker Context - -> **Context Recovery**: Run `gt prime` for full context after compaction or new session. - -## The Propulsion Principle (GUPP) - -**If you find work on your hook, YOU RUN IT.** - -No confirmation. No waiting. No announcements. The hook having work IS the assignment. -This is physics, not politeness. Gas Town is a steam engine - you are a piston. - -**Failure mode we're preventing:** -- Agent starts with work on hook -- Agent announces itself and waits for human to say "ok go" -- Human is AFK / trusting the engine to run -- Work sits idle. The whole system stalls. - -## Startup Protocol - -1. Check your hook: `gt mol status` -2. If work is hooked → EXECUTE (no announcement, no waiting) -3. If hook empty → Check mail: `gt mail inbox` -4. Still nothing? Wait for user instructions - -## Key Commands - -- `gt prime` - Get full role context (run after compaction) -- `gt mol status` - Check your hooked work -- `gt mail inbox` - Check for messages -- `bd ready` - Find available work (no blockers) -- `bd sync` - Sync beads changes - -## Session Close Protocol - -Before saying "done": -1. git status (check what changed) -2. git add (stage code changes) -3. bd sync (commit beads changes) -4. git commit -m "..." (commit code) -5. bd sync (commit any new beads changes) -6. git push (push to remote) - -**Work is not done until pushed.** diff --git a/.beads/config.yaml b/.beads/config.yaml index f55759c75..f2427856e 100644 --- a/.beads/config.yaml +++ b/.beads/config.yaml @@ -60,10 +60,3 @@ # - linear.api-key # - github.org # - github.repo -sync-branch: beads-sync - -# Cross-project dependencies (gt-o3is) -# Maps project names to paths for external dependency resolution -# Format: external:: in bd dep commands -external_projects: - beads: ../../../beads/mayor/rig diff --git a/.beads/formulas/beads-release.formula.toml b/.beads/formulas/beads-release.formula.toml deleted file mode 100644 index 84b302e23..000000000 --- a/.beads/formulas/beads-release.formula.toml +++ /dev/null @@ -1,345 +0,0 @@ -description = """ -Beads release workflow - from version bump to verified release. - -This formula orchestrates a complete release cycle: -1. Preflight checks (clean git, up to date) -2. Documentation updates (CHANGELOG, info.go) -3. Version bump (all components) -4. Git operations (commit, tag, push) -5. CI verification (GitHub Actions) -6. Artifact verification (GitHub, npm, PyPI) -7. Local installation update -8. Daemon restart - -## Usage - -```bash -bd mol wisp create beads-release --var version=0.37.0 -``` - -Or assign to a polecat: -```bash -gt sling beads/polecats/p1 --formula beads-release --var version=0.37.0 -``` -""" -formula = "beads-release" -type = "workflow" -version = 1 - -[vars.version] -description = "The semantic version to release (e.g., 0.37.0)" -required = true - -[[steps]] -id = "preflight-git" -title = "Preflight: Check git status" -description = """ -Ensure working tree is clean before starting release. - -```bash -git status -``` - -If there are uncommitted changes, either: -- Commit them first -- Stash them: `git stash` -- Abort and resolve -""" - -[[steps]] -id = "preflight-pull" -title = "Preflight: Pull latest" -needs = ["preflight-git"] -description = """ -Ensure we're up to date with origin. - -```bash -git pull --rebase -``` - -Resolve any conflicts before proceeding. -""" - -[[steps]] -id = "review-changes" -title = "Review changes since last release" -needs = ["preflight-pull"] -description = """ -Understand what's being released. - -```bash -git log $(git describe --tags --abbrev=0)..HEAD --oneline -``` - -Categorize changes: -- Features (feat:) -- Fixes (fix:) -- Breaking changes -- Documentation -""" - -[[steps]] -id = "update-changelog" -title = "Update CHANGELOG.md" -needs = ["review-changes"] -description = """ -Write the [Unreleased] section with all changes for {{version}}. - -Format: Keep a Changelog (https://keepachangelog.com) - -Sections: -- ### Added -- ### Changed -- ### Fixed -- ### Documentation - -The bump script will stamp the date automatically. -""" - -[[steps]] -id = "update-info-go" -title = "Update info.go versionChanges" -needs = ["update-changelog"] -description = """ -Add entry to versionChanges in cmd/bd/info.go. - -This powers `bd info --whats-new` for agents. - -```go -"{{version}}": { - "summary": "Brief description", - "changes": []string{ - "Key change 1", - "Key change 2", - }, -}, -``` - -Focus on workflow-impacting changes agents need to know. -""" - -[[steps]] -id = "run-bump-script" -title = "Run bump-version.sh" -needs = ["update-info-go"] -description = """ -Update all component versions atomically. - -```bash -./scripts/bump-version.sh {{version}} -``` - -This updates: -- cmd/bd/version.go -- .claude-plugin/*.json -- integrations/beads-mcp/pyproject.toml -- integrations/beads-mcp/src/beads_mcp/__init__.py -- npm-package/package.json -- Hook templates -- README.md -- CHANGELOG.md (adds date) -""" - -[[steps]] -id = "verify-versions" -title = "Verify version consistency" -needs = ["run-bump-script"] -description = """ -Confirm all versions match {{version}}. - -```bash -grep 'Version = ' cmd/bd/version.go -jq -r '.version' .claude-plugin/plugin.json -jq -r '.version' npm-package/package.json -grep 'version = ' integrations/beads-mcp/pyproject.toml -``` - -All should show {{version}}. -""" - -[[steps]] -id = "commit-release" -title = "Commit release" -needs = ["verify-versions"] -description = """ -Stage and commit all version changes. - -```bash -git add -A -git commit -m "chore: Bump version to {{version}}" -``` - -Review the commit to ensure all expected files are included. -""" - -[[steps]] -id = "create-tag" -title = "Create release tag" -needs = ["commit-release"] -description = """ -Create annotated git tag. - -```bash -git tag -a v{{version}} -m "Release v{{version}}" -``` - -Verify: `git tag -l | tail -5` -""" - -[[steps]] -id = "push-main" -title = "Push to main" -needs = ["create-tag"] -description = """ -Push the release commit to origin. - -```bash -git push origin main -``` - -If rejected, someone else pushed. Pull, rebase, try again. -""" - -[[steps]] -id = "push-tag" -title = "Push release tag" -needs = ["push-main"] -description = """ -Push the version tag to trigger CI release. - -```bash -git push origin v{{version}} -``` - -This triggers GitHub Actions to build artifacts and publish. -""" - -[[steps]] -id = "wait-ci" -title = "Wait for CI" -needs = ["push-tag"] -description = """ -Monitor GitHub Actions for release completion. - -https://github.com/steveyegge/beads/actions - -Expected time: 5-10 minutes - -Watch for: -- Build artifacts (all platforms) -- Test suite pass -- npm publish -- PyPI publish -""" - -[[steps]] -id = "verify-github-release" -title = "Verify GitHub release" -needs = ["wait-ci"] -description = """ -Check the GitHub releases page. - -https://github.com/steveyegge/beads/releases/tag/v{{version}} - -Verify: -- Release created -- Binaries attached (linux, darwin, windows) -- Checksums present -""" - -[[steps]] -id = "verify-npm" -title = "Verify npm package" -needs = ["verify-github-release"] -description = """ -Confirm npm package published. - -```bash -npm show @beads/bd version -``` - -Should show {{version}}. - -Also check: https://www.npmjs.com/package/@beads/bd -""" - -[[steps]] -id = "verify-pypi" -title = "Verify PyPI package" -needs = ["verify-github-release"] -description = """ -Confirm PyPI package published. - -```bash -pip index versions beads-mcp 2>/dev/null | head -3 -``` - -Or check: https://pypi.org/project/beads-mcp/ - -Should show {{version}}. -""" - -[[steps]] -id = "local-install" -title = "Update local installation" -needs = ["verify-npm", "verify-pypi"] -description = """ -Update local bd to the new version. - -Option 1 - Homebrew: -```bash -brew upgrade bd -``` - -Option 2 - Install script: -```bash -curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash -``` - -Verify: -```bash -bd --version -``` - -Should show {{version}}. -""" - -[[steps]] -id = "restart-daemons" -title = "Restart daemons" -needs = ["local-install"] -description = """ -Restart bd daemons to pick up new version. - -```bash -bd daemons killall -``` - -Daemons will auto-restart with new version on next bd command. - -Verify: -```bash -bd daemons list -``` -""" - -[[steps]] -id = "release-complete" -title = "Release complete" -needs = ["restart-daemons"] -description = """ -Release v{{version}} is complete! - -Summary: -- All version files updated -- Git tag pushed -- CI artifacts built -- npm and PyPI packages published -- Local installation updated -- Daemons restarted - -Optional next steps: -- Announce on social media -- Update documentation site -- Close related milestone -""" diff --git a/.beads/formulas/code-review.formula.toml b/.beads/formulas/code-review.formula.toml deleted file mode 100644 index dc09c950d..000000000 --- a/.beads/formulas/code-review.formula.toml +++ /dev/null @@ -1,319 +0,0 @@ -# Code Review Convoy Formula -# -# A convoy-style formula that spawns multiple polecats in parallel, -# each focusing on a different review aspect. Results are collected -# and synthesized into a unified review. -# -# Usage: -# gt formula run code-review --pr=123 -# gt formula run code-review --files="src/*.go" - -description = """ -Comprehensive code review via parallel specialized reviewers. - -Each leg examines the code from a different perspective. Findings are -collected and synthesized into a prioritized, actionable review. - -## Legs (parallel execution) -- **correctness**: Logic errors, bugs, edge cases -- **performance**: Bottlenecks, efficiency issues -- **security**: Vulnerabilities, OWASP concerns -- **elegance**: Design clarity, abstraction quality -- **resilience**: Error handling, failure modes -- **style**: Convention compliance, consistency -- **smells**: Anti-patterns, technical debt - -## Execution Model -1. Each leg spawns as a separate polecat -2. Polecats work in parallel -3. Each writes findings to their designated output -4. Synthesis step combines all findings into unified review -""" -formula = "code-review" -type = "convoy" -version = 1 - -# Input variables - provided at runtime -[inputs] -[inputs.pr] -description = "Pull request number to review" -type = "number" -required_unless = ["files", "branch"] - -[inputs.files] -description = "File glob pattern to review" -type = "string" -required_unless = ["pr", "branch"] - -[inputs.branch] -description = "Branch name to review (diff against main)" -type = "string" -required_unless = ["pr", "files"] - -# Base prompt template - injected into all leg prompts -# NOTE: Uses Go text/template syntax (not Handlebars) -[prompts] -base = """ -# Code Review Assignment - -You are a specialized code reviewer participating in a convoy review. - -## Context -- **Formula**: {{.formula_name}} -- **Review target**: {{.target_description}} -- **Your focus**: {{.leg.focus}} -- **Leg ID**: {{.leg.id}} - -## Files Under Review -{{if .pr_number -}} -PR #{{.pr_number}}: {{.pr_title}} - -Changed files: -{{range .changed_files -}} -- {{.path}} (+{{.additions}}/-{{.deletions}}) -{{end -}} -{{else -}} -{{range .files -}} -- {{.}} -{{end -}} -{{end}} - -## Your Task -{{.leg.description}} - -## Output Requirements -Write your findings to: **{{.output_path}}** - -Structure your output as follows: -```markdown -# {{.leg.title}} Review - -## Summary -(1-2 paragraph overview of findings) - -## Critical Issues -(P0 - Must fix before merge) -- Issue description with file:line reference -- Explanation of impact -- Suggested fix - -## Major Issues -(P1 - Should fix before merge) -- ... - -## Minor Issues -(P2 - Nice to fix) -- ... - -## Observations -(Non-blocking notes and suggestions) -- ... -``` - -Use specific file:line references. Be actionable. Prioritize impact. -""" - -# Output configuration -[output] -directory = ".reviews/{{.review_id}}" -leg_pattern = "{{.leg.id}}-findings.md" -synthesis = "review-summary.md" - -# Leg definitions - each spawns a parallel polecat -[[legs]] -id = "correctness" -title = "Correctness Review" -focus = "Logical correctness and edge case handling" -description = """ -Review the code for logical errors and edge case handling. - -**Look for:** -- Logic errors and bugs -- Off-by-one errors -- Null/nil/undefined handling -- Unhandled edge cases -- Race conditions in concurrent code -- Dead code or unreachable branches -- Incorrect assumptions in comments vs code -- Integer overflow/underflow potential -- Floating point comparison issues - -**Questions to answer:** -- Does the code do what it claims to do? -- What inputs could cause unexpected behavior? -- Are all code paths tested or obviously correct? -""" - -[[legs]] -id = "performance" -title = "Performance Review" -focus = "Performance bottlenecks and efficiency" -description = """ -Review the code for performance issues. - -**Look for:** -- O(n²) or worse algorithms where O(n) is possible -- Unnecessary allocations in hot paths -- Missing caching opportunities -- N+1 query patterns (database or API) -- Blocking operations in async contexts -- Memory leaks or unbounded growth -- Excessive string concatenation -- Unoptimized regex or parsing - -**Questions to answer:** -- What happens at 10x, 100x, 1000x scale? -- Are there obvious optimizations being missed? -- Is performance being traded for readability appropriately? -""" - -[[legs]] -id = "security" -title = "Security Review" -focus = "Security vulnerabilities and attack surface" -description = """ -Review the code for security vulnerabilities. - -**Look for:** -- Input validation gaps -- Authentication/authorization bypasses -- Injection vulnerabilities (SQL, XSS, command, LDAP) -- Sensitive data exposure (logs, errors, responses) -- Hardcoded secrets or credentials -- Insecure cryptographic usage -- Path traversal vulnerabilities -- SSRF (Server-Side Request Forgery) -- Deserialization vulnerabilities -- OWASP Top 10 concerns - -**Questions to answer:** -- What can a malicious user do with this code? -- What data could be exposed if this fails? -- Are there defense-in-depth gaps? -""" - -[[legs]] -id = "elegance" -title = "Elegance Review" -focus = "Design clarity and abstraction quality" -description = """ -Review the code for design quality. - -**Look for:** -- Unclear abstractions or naming -- Functions doing too many things -- Missing or over-engineered abstractions -- Coupling that should be loose -- Dependencies that flow the wrong direction -- Unclear data flow or control flow -- Magic numbers/strings without explanation -- Inconsistent design patterns -- Violation of SOLID principles -- Reinventing existing utilities - -**Questions to answer:** -- Would a new team member understand this? -- Does the structure match the problem domain? -- Is the complexity justified? -""" - -[[legs]] -id = "resilience" -title = "Resilience Review" -focus = "Error handling and failure modes" -description = """ -Review the code for resilience and error handling. - -**Look for:** -- Swallowed errors or empty catch blocks -- Missing error propagation -- Unclear error messages -- Insufficient retry/backoff logic -- Missing timeout handling -- Resource cleanup on failure (files, connections) -- Partial failure states -- Missing circuit breakers for external calls -- Unhelpful panic/crash behavior -- Recovery path gaps - -**Questions to answer:** -- What happens when external services fail? -- Can the system recover from partial failures? -- Are errors actionable for operators? -""" - -[[legs]] -id = "style" -title = "Style Review" -focus = "Convention compliance and consistency" -description = """ -Review the code for style and convention compliance. - -**Look for:** -- Naming convention violations -- Formatting inconsistencies -- Import organization issues -- Comment quality (missing, outdated, or obvious) -- Documentation gaps for public APIs -- Inconsistent patterns within the codebase -- Lint/format violations -- Test naming and organization -- Log message quality and levels - -**Questions to answer:** -- Does this match the rest of the codebase? -- Would the style guide approve? -- Is the code self-documenting where possible? -""" - -[[legs]] -id = "smells" -title = "Code Smells Review" -focus = "Anti-patterns and technical debt" -description = """ -Review the code for code smells and anti-patterns. - -**Look for:** -- Long methods (>50 lines is suspicious) -- Deep nesting (>3 levels) -- Shotgun surgery patterns -- Feature envy -- Data clumps -- Primitive obsession -- Temporary fields -- Refused bequest -- Speculative generality -- God classes/functions -- Copy-paste code (DRY violations) -- TODO/FIXME accumulation - -**Questions to answer:** -- What will cause pain during the next change? -- What would you refactor if you owned this code? -- Is technical debt being added or paid down? -""" - -# Synthesis step - combines all leg outputs -[synthesis] -title = "Review Synthesis" -description = """ -Combine all leg findings into a unified, prioritized review. - -**Your input:** -All leg findings from: {{.output.directory}}/ - -**Your output:** -A synthesized review at: {{.output.directory}}/{{.output.synthesis}} - -**Structure:** -1. **Executive Summary** - Overall assessment, merge recommendation -2. **Critical Issues** - P0 items from all legs, deduplicated -3. **Major Issues** - P1 items, grouped by theme -4. **Minor Issues** - P2 items, briefly listed -5. **Positive Observations** - What's done well -6. **Recommendations** - Actionable next steps - -Deduplicate issues found by multiple legs (note which legs found them). -Prioritize by impact and effort. Be actionable. -""" -depends_on = ["correctness", "performance", "security", "elegance", "resilience", "style", "smells"] diff --git a/.beads/formulas/design.formula.toml b/.beads/formulas/design.formula.toml deleted file mode 100644 index 8dd4a595f..000000000 --- a/.beads/formulas/design.formula.toml +++ /dev/null @@ -1,333 +0,0 @@ -# Design Convoy Formula -# -# A convoy-style formula that spawns multiple polecats in parallel, -# each exploring a different dimension of a design problem. Results -# are synthesized into a unified design document. -# -# Usage: -# gt formula run design --problem="Add notification levels to mayor" -# gt formula run design --problem="Redesign the merge queue" - -description = """ -Structured design exploration via parallel specialized analysts. - -Each leg examines the design problem from a different perspective. Findings -are collected and synthesized into a unified design proposal with options. - -## Legs (parallel execution) -- **api**: Interface design, ergonomics, developer experience -- **data**: Data model, storage, migrations, schema -- **ux**: User experience, CLI ergonomics, discoverability -- **scale**: Performance at scale, bottlenecks, limits -- **security**: Threat model, attack surface, trust boundaries -- **integration**: How it fits existing system, compatibility - -## Execution Model -1. Each leg spawns as a separate polecat -2. Polecats work in parallel -3. Each writes analysis to their designated output -4. Synthesis step combines all analyses into unified design - -## Output -A .designs// directory containing: -- Individual dimension analyses -- design-doc.md with unified proposal and decision points -""" -formula = "design" -type = "convoy" -version = 1 - -# Input variables - provided at runtime -[inputs] -[inputs.problem] -description = "Problem statement or feature request to design" -type = "string" -required = true - -[inputs.context] -description = "Additional context (existing code, constraints, etc.)" -type = "string" -required = false - -[inputs.scope] -description = "Scope hint: 'small' (1 file), 'medium' (package), 'large' (system)" -type = "string" -default = "medium" - -# Base prompt template - injected into all leg prompts -[prompts] -base = """ -# Design Analysis Assignment - -You are a specialized design analyst participating in a convoy design exploration. - -## Context -- **Formula**: {{.formula_name}} -- **Problem**: {{.problem}} -- **Your dimension**: {{.leg.focus}} -- **Leg ID**: {{.leg.id}} -- **Scope**: {{.scope}} - -{{if .context}} -## Additional Context -{{.context}} -{{end}} - -## Your Task -{{.leg.description}} - -## Output Requirements -Write your analysis to: **{{.output_path}}** - -Structure your output as follows: -```markdown -# {{.leg.title}} - -## Summary -(1-2 paragraph overview of this dimension) - -## Analysis - -### Key Considerations -(Bulleted list of important factors) - -### Options Explored -(For each option considered:) -#### Option N: -- **Description**: What is it? -- **Pros**: Benefits -- **Cons**: Drawbacks -- **Effort**: Low/Medium/High - -### Recommendation -(Your recommended approach for this dimension) - -## Constraints Identified -(Hard constraints discovered during analysis) - -## Open Questions -(Questions needing human input or cross-dimension discussion) - -## Integration Points -(How this dimension connects to other dimensions) -``` - -Be thorough but actionable. Flag decisions needing human input. -""" - -# Output configuration -[output] -directory = ".designs/{{.design_id}}" -leg_pattern = "{{.leg.id}}.md" -synthesis = "design-doc.md" - -# Leg definitions - each spawns a parallel polecat -[[legs]] -id = "api" -title = "API & Interface Design" -focus = "Interface design and developer ergonomics" -description = """ -Analyze the interface design for this feature. - -**Explore:** -- Command-line interface: flags, subcommands, ergonomics -- Programmatic API: function signatures, return types -- Configuration interface: files, environment variables -- Error messages and help text -- Naming conventions and discoverability -- Consistency with existing interfaces - -**Questions to answer:** -- How will users discover and learn this feature? -- What's the happy path vs edge cases? -- Does it follow existing CLI/API patterns? -- What would make this a joy to use? - -**Deliverable:** api-design.md with interface proposals -""" - -[[legs]] -id = "data" -title = "Data Model Design" -focus = "Data model, storage, and migrations" -description = """ -Analyze the data model requirements for this feature. - -**Explore:** -- Data structures: types, relationships, constraints -- Storage format: JSON, TOML, SQLite, in-memory -- Schema design: fields, indices, normalization -- Migration strategy: versioning, backwards compatibility -- Data lifecycle: creation, updates, deletion -- Persistence vs ephemeral considerations - -**Questions to answer:** -- What data needs to persist vs be computed? -- How will the data grow over time? -- What queries/access patterns are needed? -- How do we handle schema evolution? - -**Deliverable:** data-model.md with schema proposals -""" - -[[legs]] -id = "ux" -title = "User Experience Analysis" -focus = "User experience and CLI ergonomics" -description = """ -Analyze the user experience implications of this feature. - -**Explore:** -- Mental model: how users think about this -- Workflow integration: where does this fit in daily use? -- Learning curve: progressive disclosure -- Error experience: what happens when things go wrong? -- Feedback: how does the user know it's working? -- Discoverability: --help, docs, examples - -**Questions to answer:** -- What's the user's goal when using this? -- What's the minimum viable interaction? -- How do we handle power users vs beginners? -- What would surprise or confuse users? - -**Deliverable:** ux-analysis.md with UX recommendations -""" - -[[legs]] -id = "scale" -title = "Scalability Analysis" -focus = "Performance at scale and bottlenecks" -description = """ -Analyze the scalability implications of this feature. - -**Explore:** -- Scale dimensions: data size, request rate, user count -- Resource usage: memory, CPU, disk, network -- Bottlenecks: what limits growth? -- Complexity: algorithmic, space, time -- Caching opportunities -- Degradation modes: what happens at limits? - -**Questions to answer:** -- What happens at 10x, 100x, 1000x current scale? -- What are the hard limits? -- Where should we optimize vs keep simple? -- What needs to be lazy vs eager? - -**Deliverable:** scalability.md with performance analysis -""" - -[[legs]] -id = "security" -title = "Security Analysis" -focus = "Threat model and attack surface" -description = """ -Analyze the security implications of this feature. - -**Explore:** -- Trust boundaries: what trusts what? -- Attack surface: new inputs, outputs, permissions -- Threat model: who might attack this and how? -- Sensitive data: what's exposed or stored? -- Authentication/authorization implications -- Failure modes: what if security fails? - -**Questions to answer:** -- What's the worst case if this is exploited? -- What new permissions or access does this need? -- How do we validate/sanitize inputs? -- Are there defense-in-depth opportunities? - -**Deliverable:** security.md with threat analysis -""" - -[[legs]] -id = "integration" -title = "Integration Analysis" -focus = "How it fits existing system" -description = """ -Analyze how this feature integrates with the existing system. - -**Explore:** -- Existing components: what does this touch? -- Dependencies: what does this need from others? -- Dependents: what will depend on this? -- Migration path: how do we get from here to there? -- Backwards compatibility: what might break? -- Testing strategy: how do we verify integration? - -**Questions to answer:** -- Where does this code live? -- How does it affect existing workflows? -- What needs to change in dependent code? -- Can we feature-flag or gradually roll out? - -**Deliverable:** integration.md with integration plan -""" - -# Synthesis step - combines all leg outputs -[synthesis] -title = "Design Synthesis" -description = """ -Combine all dimension analyses into a unified design document. - -**Your input:** -All dimension analyses from: {{.output.directory}}/ - -**Your output:** -A synthesized design at: {{.output.directory}}/{{.output.synthesis}} - -**Structure:** -```markdown -# Design: {{.problem}} - -## Executive Summary -(2-3 paragraph overview of proposed design) - -## Problem Statement -(Clear statement of what we're solving) - -## Proposed Design - -### Overview -(High-level approach) - -### Key Components -(Main pieces and how they fit together) - -### Interface -(CLI/API summary from api dimension) - -### Data Model -(Schema summary from data dimension) - -## Trade-offs and Decisions - -### Decisions Made -(Key choices and rationale) - -### Open Questions -(Decisions needing human input - highlight these!) - -### Trade-offs -(What we're trading off and why) - -## Risks and Mitigations -(From security and scale dimensions) - -## Implementation Plan -(From integration dimension) - -### Phase 1: MVP -### Phase 2: Polish -### Phase 3: Future - -## Appendix: Dimension Analyses -(Links to full dimension documents) -``` - -Identify conflicts between dimensions. Flag decisions needing human input. -Be concrete and actionable. -""" -depends_on = ["api", "data", "ux", "scale", "security", "integration"] diff --git a/.beads/formulas/mol-boot-triage.formula.toml b/.beads/formulas/mol-boot-triage.formula.toml deleted file mode 100644 index 38e5d248a..000000000 --- a/.beads/formulas/mol-boot-triage.formula.toml +++ /dev/null @@ -1,228 +0,0 @@ -description = """ -Boot triage cycle - the daemon's watchdog for Deacon health. - -Boot is spawned fresh on each daemon tick to decide whether to start/wake/nudge/interrupt -the Deacon, or do nothing. This centralizes the "when to wake" decision in an agent that -can reason about context rather than relying on mechanical thresholds. - -Boot lifecycle: -1. Observe (wisps, mail, git state, tmux panes) -2. Decide (start/wake/nudge/interrupt/nothing) -3. Act -4. Clean inbox (discard stale handoffs) -5. Exit (or handoff in non-degraded mode) - -Boot is always fresh - no persistent state between invocations. -Handoff mail provides continuity for the next Boot instance. -""" -formula = "mol-boot-triage" -version = 1 - -[[steps]] -id = "observe" -title = "Observe system state" -description = """ -Observe the current system state to inform triage decisions. - -**Step 1: Check Deacon state** -```bash -# Is Deacon session alive? -tmux has-session -t hq-deacon 2>/dev/null && echo "alive" || echo "dead" - -# If alive, what's the pane output showing? -gt peek deacon --lines 20 -``` - -**Step 2: Check agent bead state** -```bash -bd show hq-deacon 2>/dev/null -# Look for: -# - state: running/working/idle -# - last_activity: when was last update? -``` - -**Step 3: Check recent activity** -```bash -# Recent feed events -gt feed --since 10m --plain | head -20 - -# Recent wisps (operational state) -ls -lt ~/gt/.beads-wisp/*.wisp.json 2>/dev/null | head -5 -``` - -**Step 4: Check Deacon mail** -```bash -# Does Deacon have unread mail? -gt mail inbox deacon 2>/dev/null | head -10 -``` - -Record observations for the decide step: -- deacon_alive: true/false -- pane_activity: active/idle/stuck -- last_activity_age: duration since last activity -- pending_mail: count of unread messages -- error_signals: any errors observed -""" - -[[steps]] -id = "decide" -title = "Decide on action" -needs = ["observe"] -description = """ -Analyze observations and decide what action to take. - -**Decision Matrix** - -| Deacon State | Pane Activity | Action | -|--------------|---------------|--------| -| Dead session | N/A | START | -| Alive, active output | N/A | NOTHING | -| Alive, idle < 5 min | N/A | NOTHING | -| Alive, idle 5-15 min | No mail | NOTHING | -| Alive, idle 5-15 min | Has mail | NUDGE | -| Alive, idle > 15 min | Any | WAKE | -| Alive, stuck (errors) | Any | INTERRUPT | - -**Judgment Guidance** - -Agents may take several minutes on legitimate work. Ten minutes or more in edge cases. -Don't be too aggressive - false positives are disruptive. - -Signs of stuck: -- Same error repeated in pane -- Tool prompt waiting indefinitely -- Silence with pending mail -- Agent reporting issues but not progressing - -Signs of working: -- Tool calls in progress -- File reads/writes happening -- Recent commits or beads updates - -**Output**: Record decision as one of: -- NOTHING: Let Deacon continue -- NUDGE: Gentle wake signal (gt nudge) -- WAKE: Stronger wake (escape + message) -- INTERRUPT: Force restart needed -- START: Session is dead, start fresh -""" - -[[steps]] -id = "act" -title = "Execute decided action" -needs = ["decide"] -description = """ -Execute the action decided in the previous step. - -**NOTHING** -No action needed. Log observation and exit. - -**NUDGE** -```bash -gt nudge deacon "Boot check-in: you have pending work" -``` - -**WAKE** -```bash -# Send escape to break any tool waiting -tmux send-keys -t hq-deacon Escape - -# Brief pause -sleep 1 - -# Send wake message -gt nudge deacon "Boot wake: please check your inbox and pending work" -``` - -**INTERRUPT** -```bash -# This is more aggressive - signals Deacon to restart -gt mail send deacon -s "INTERRUPT: Boot detected stuck state" \ - -m "Boot observed stuck state. Please check your context and consider handoff. - -Observations: -- - -If you're making progress, please update your agent bead to reflect activity." -``` - -**START** -```bash -# Deacon is dead - daemon will restart it -# Just log that we detected this -echo "Boot detected dead Deacon session - daemon will restart" -``` - -Record action taken for status update. -""" - -[[steps]] -id = "cleanup" -title = "Clean stale handoffs" -needs = ["act"] -description = """ -Clean up stale handoff messages from Deacon's inbox. - -Handoff messages older than 1 hour are likely stale - the intended recipient -either processed them or crashed before seeing them. - -**Step 1: List Deacon inbox** -```bash -gt mail inbox deacon --json 2>/dev/null -``` - -**Step 2: Archive stale handoffs** -For each message: -- Check if subject contains "HANDOFF" or "handoff" -- Check if age > 1 hour -- If both: archive it - -```bash -# For each stale handoff: -gt mail archive -``` - -**Step 3: Archive Boot's own old mail** -Boot doesn't need persistent inbox. Archive anything processed: -```bash -gt mail inbox boot --json 2>/dev/null -# Archive any messages older than current session -``` - -Keep the system clean - old handoffs just add noise. -""" - -[[steps]] -id = "exit" -title = "Exit or handoff" -needs = ["cleanup"] -description = """ -Complete this Boot cycle. - -**In degraded mode (GT_DEGRADED=true)** -Exit directly - no handoff needed: -```bash -# Log completion -echo "Boot triage complete: " -exit 0 -``` - -**In normal mode** -Write brief handoff for next Boot instance: -```bash -gt mail send boot -s "Boot handoff" -m "Completed triage cycle. -Action: -Observations: -Time: $(date)" -``` - -Then exit. The next daemon tick will spawn a fresh Boot. - -**Update status file** -```bash -# The gt boot command handles this automatically -# Status is written to ~/gt/deacon/dogs/boot/.boot-status.json -``` - -Boot is ephemeral by design. Each instance runs fresh. -""" diff --git a/.beads/formulas/mol-convoy-cleanup.formula.toml b/.beads/formulas/mol-convoy-cleanup.formula.toml deleted file mode 100644 index 04a9b0aea..000000000 --- a/.beads/formulas/mol-convoy-cleanup.formula.toml +++ /dev/null @@ -1,209 +0,0 @@ -description = """ -Archive completed convoys and notify overseer. - -Dogs work through molecules (poured from this formula) when convoys complete. The Deacon detects completed -convoys (all tracked issues closed) and slings this work to a dog for: -- Generating convoy summary -- Archiving convoy state -- Notifying the overseer (Mayor) -- Updating activity feed - -## Dog Contract - -This is infrastructure work. You: -1. Receive convoy ID via hook_bead -2. Generate summary of completed work -3. Archive to appropriate location -4. Notify stakeholders -5. Return to kennel - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| convoy | hook_bead | The convoy ID to archive | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| Convoy not found | Exit with error, notify Deacon | -| Archive location full | Create space, retry, or escalate | -| Mail send fails | Retry once, then proceed anyway |""" -formula = "mol-convoy-cleanup" -version = 1 - -[squash] -trigger = "on_complete" -template_type = "work" -include_metrics = true - -[[steps]] -id = "load-convoy" -title = "Load convoy and verify completion" -description = """ -Load the convoy bead and verify it's ready for archival. - -**1. Check your assignment:** -```bash -gt hook # Shows hook_bead = convoy ID -bd show {{convoy}} # Full convoy details -``` - -**2. Verify convoy is complete:** -- Status should be 'closed' or all tracked issues closed -- If convoy is still open, exit - Deacon dispatched too early - -```bash -bd show {{convoy}} -# Check 'tracks' or 'dependencies' field -# All tracked issues should be closed -``` - -**3. Gather convoy metadata:** -- Start date (created_at) -- End date (last closure timestamp) -- Total issues tracked -- Contributing polecats - -**Exit criteria:** Convoy loaded, verified complete, metadata gathered.""" - -[[steps]] -id = "generate-summary" -title = "Generate convoy summary" -needs = ["load-convoy"] -description = """ -Create a summary of the convoy's completed work. - -**1. Collect tracked issue details:** -```bash -# For each tracked issue -bd show -# Extract: title, type, assignee, duration -``` - -**2. Calculate statistics:** -- Total duration (convoy start to finish) -- Issues by type (task, bug, feature) -- Contributors (unique assignees) -- Commits generated (if tracked) - -**3. Create summary text:** -```markdown -## Convoy Summary: {{convoy.title}} - -**Duration**: X days/hours -**Issues completed**: N - -### Work Breakdown -- Tasks: N -- Bugs: N -- Features: N - -### Contributors -- polecat-1: N issues -- polecat-2: N issues - -### Key Outcomes -- -- -``` - -**Exit criteria:** Summary text generated and ready for notification.""" - -[[steps]] -id = "archive-convoy" -title = "Archive convoy to cold storage" -needs = ["generate-summary"] -description = """ -Move convoy from active to archived state. - -**1. Update convoy status:** -```bash -bd update {{convoy}} --status=archived -# Or close if not already closed -bd close {{convoy}} --reason="Convoy complete, archived" -``` - -**2. Generate archive record:** -The convoy bead with all metadata is the archive record. Beads retention -handles moving it to `.beads/archive/` after the retention period. - -**3. Verify archive:** -```bash -bd show {{convoy}} -# Status should reflect archived state -``` - -**4. Sync to persist:** -```bash -bd sync -``` - -**Exit criteria:** Convoy archived, changes synced.""" - -[[steps]] -id = "notify-overseer" -title = "Send completion notification to overseer" -needs = ["archive-convoy"] -description = """ -Notify the Mayor (overseer) of convoy completion. - -**1. Send completion mail:** -```bash -gt mail send mayor/ -s "Convoy complete: {{convoy.title}}" -m "$(cat < --json -``` - -An issue is "ready" if ALL of these are true: -- status = "open" (NOT in_progress, closed, or hooked) -- not in blocked list (check: bd blocked --json) -- assignee is empty OR assignee session is dead - -Check blocked status: -```bash -bd blocked --json -# If issue ID appears here, it's blocked (skip it) -``` - -Check assignee session if set: -```bash -# If assignee like "gastown/polecats/nux" -tmux has-session -t gt-gastown-polecat-nux 2>/dev/null && echo "alive" || echo "dead" -``` - -**4. Build ready list:** -Collect all ready issues with their metadata: -- Issue ID -- Title -- Priority -- Rig (extracted from prefix) - -Sort by priority (P0 first) for dispatch order. - -**Exit criteria:** Ready issues identified and prioritized.""" - -[[steps]] -id = "check-capacity" -title = "Check polecat capacity across rigs" -needs = ["load-convoy"] -description = """ -Determine how many polecats are available for dispatch. - -**1. For each rig that has ready issues:** -```bash -gt polecats -# Shows polecat status: idle, working, etc. -``` - -**2. Count available capacity:** -Available polecats are those that: -- Exist in the rig's polecat pool -- Currently idle (no hooked work) -- Session is running - -**3. Calculate dispatch count:** -``` -dispatch_count = min(ready_issues, available_polecats) -``` - -If dispatch_count = 0: -- Log: "No capacity available, will retry next cycle" -- Proceed to report step (no dispatches to make) - -**4. Match issues to rigs:** -For each ready issue, determine target rig from issue prefix: -- gt-* issues → gastown rig -- bd-* issues → beads rig -- etc. - -**Exit criteria:** Dispatch plan created with issue→rig mappings.""" - -[[steps]] -id = "dispatch-work" -title = "Dispatch ready issues to polecats" -needs = ["check-capacity"] -description = """ -Sling each ready issue to an available polecat. - -**For each issue in dispatch plan:** - -```bash -# Dispatch issue to the appropriate rig -# This spawns a fresh polecat or assigns to idle one -gt sling - -# Example: -gt sling gt-abc123 gastown -gt sling bd-xyz789 beads -``` - -**Track results:** -For each dispatch: -- Success: Note issue ID, target rig, polecat assigned -- Failure: Note issue ID, error message - -**Important notes:** -- `gt sling` handles polecat selection automatically -- It will spawn a new polecat if none available -- The polecat gets the issue hooked and starts immediately -- Don't wait for polecat to complete - fire and forget - -**If sling fails:** -- Continue with remaining issues -- Note the failure for the report -- Don't escalate individual failures (will retry next cycle) - -**Exit criteria:** All dispatchable issues have been slung.""" - -[[steps]] -id = "report-results" -title = "Generate and send feeding report" -needs = ["dispatch-work"] -description = """ -Create summary report of convoy feeding actions. - -**1. Generate report:** -```markdown -## Convoy Feed Report: {{convoy}} - -**Ready issues found**: {{ready_count}} -**Polecats available**: {{available_count}} -**Issues dispatched**: {{dispatch_count}} - -### Dispatched Work -{{#each dispatched}} -- {{issue_id}}: {{title}} → {{rig}}/{{polecat}} -{{/each}} - -### Skipped (no capacity) -{{#if skipped}} -{{#each skipped}} -- {{issue_id}}: {{title}} (will retry next cycle) -{{/each}} -{{else}} -(none) -{{/if}} - -### Errors -{{#if errors}} -{{#each errors}} -- {{issue_id}}: {{error}} -{{/each}} -{{else}} -(none) -{{/if}} -``` - -**2. Send to Deacon:** -```bash -gt mail send deacon/ -s "Convoy fed: {{convoy}}" -m "$(cat < -# Check if this was the only blocker -``` - -**2. Check if now unblocked:** -```bash -bd blocked -# If empty or only shows other blockers, issue is now unblocked -``` - -**3. Verify automatic unblock worked:** -Beads should auto-update blocked status when dependencies close. -This step verifies and fixes if needed: -```bash -# If still showing as blocked by resolved issue (shouldn't happen): -bd dep remove {{resolved_issue}} -``` - -**Exit criteria:** All cross-rig dependents have updated blocked status.""" - -[[steps]] -id = "notify-witnesses" -title = "Notify affected rig Witnesses" -needs = ["update-blocked-status"] -description = """ -Send notifications to Witnesses of affected rigs. - -**1. Group dependents by rig:** -- gastown/witness: for gt-* issues -- beads/witness: for bd-* issues -- etc. - -**2. For each affected rig, send notification:** -```bash -gt mail send /witness -s "Dependency resolved: {{resolved_issue}}" -m "$(cat < -# Check: -# - Status: should be 'open' (not already in_progress) -# - Priority: high priority may warrant immediate dispatch -# - No other blockers: bd blocked should be empty -``` - -**2. Decision: trigger dispatch?** - -| Condition | Action | -|-----------|--------| -| High priority (P0-P1) + open + unblocked | Recommend immediate dispatch | -| Medium priority (P2) + open + unblocked | Note in Witness notification | -| Low priority (P3-P4) | Let Witness handle in next patrol | - -**3. If triggering dispatch:** -```bash -# For high priority, suggest to Mayor: -gt mail send mayor/ -s "High-priority work unblocked: " -m "..." -``` - -Usually, the Witness notification (previous step) is sufficient - Witnesses -handle their own dispatch decisions. - -**Exit criteria:** Dispatch recommendations sent where appropriate.""" - -[[steps]] -id = "return-to-kennel" -title = "Signal completion and return to kennel" -needs = ["trigger-dispatch"] -description = """ -Signal work complete and return to available pool. - -**1. Signal completion to Deacon:** -```bash -gt mail send deacon/ -s "DOG_DONE $(hostname)" -m "Task: dep-propagate -Resolved: {{resolved_issue}} -Cross-rig dependents: {{dependent_count}} -Witnesses notified: {{witness_list}} -Status: COMPLETE - -Ready for next assignment." -``` - -**2. Update activity feed:** -The propagation creates implicit feed entries (dependency updates). -No explicit entry needed. - -**3. Return to kennel:** -Dog returns to available state in the pool. - -**Exit criteria:** Deacon notified, dog ready for next work or retirement.""" - -[vars] -[vars.resolved_issue] -description = "The issue ID that just closed and needs propagation" -required = true diff --git a/.beads/formulas/mol-digest-generate.formula.toml b/.beads/formulas/mol-digest-generate.formula.toml deleted file mode 100644 index 0f4e03266..000000000 --- a/.beads/formulas/mol-digest-generate.formula.toml +++ /dev/null @@ -1,227 +0,0 @@ -description = """ -Generate daily digest for overseer (Mayor). - -Dogs work through molecules (poured from this formula) on a scheduled basis (daily, or triggered by plugin) -to create summary digests of Gas Town activity. This aggregates: -- Work completed across all rigs -- Issues filed and closed -- Incidents and escalations -- Agent health metrics -- Key statistics and trends - -## Dog Contract - -This is infrastructure work. You: -1. Receive digest period via hook_bead (e.g., daily, weekly) -2. Collect data from all rigs you have access to -3. Generate formatted digest -4. Send to overseer -5. Archive digest as bead -6. Return to kennel - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| period | hook_bead | Time period for digest (daily, weekly) | -| since | computed | Start timestamp for data collection | -| until | computed | End timestamp (usually now) | - -## Why Dogs? - -Digest generation requires reading from multiple rigs. Dogs have multi-rig -worktrees. This is also a periodic task that doesn't need a dedicated polecat.""" -formula = "mol-digest-generate" -version = 1 - -[squash] -trigger = "on_complete" -template_type = "work" -include_metrics = true - -[[steps]] -id = "determine-period" -title = "Determine digest time period" -description = """ -Establish the time range for this digest. - -**1. Check assignment:** -```bash -gt hook # Shows period type -``` - -**2. Calculate time range:** - -| Period | Since | Until | -|--------|-------|-------| -| daily | Yesterday 00:00 | Today 00:00 | -| weekly | Last Monday 00:00 | This Monday 00:00 | -| custom | From hook_bead | From hook_bead | - -```bash -# For daily digest -since=$(date -v-1d +%Y-%m-%dT00:00:00) -until=$(date +%Y-%m-%dT00:00:00) -``` - -**3. Record period for reporting:** -Note the exact timestamps for the digest header. - -**Exit criteria:** Time period established with precise timestamps.""" - -[[steps]] -id = "collect-rig-data" -title = "Collect activity data from all rigs" -needs = ["determine-period"] -description = """ -Gather activity data from each rig in the town. - -**1. List accessible rigs:** -```bash -gt rigs -# Returns list of rigs: gastown, beads, etc. -``` - -**2. For each rig, collect:** - -a) **Issues filed and closed:** -```bash -# From rig beads -bd list --created-after={{since}} --created-before={{until}} -bd list --status=closed --updated-after={{since}} -``` - -b) **Agent activity:** -```bash -gt polecats # Polecat activity -gt feed --since={{since}} # Activity feed entries -``` - -c) **Merges:** -```bash -# Git log for merges to main -git -C log --merges --since={{since}} --oneline main -``` - -d) **Incidents:** -```bash -# Issues tagged as incident or high-priority -bd list --label=incident --created-after={{since}} -``` - -**3. Aggregate across rigs:** -Sum counts, collect notable items, identify trends. - -**Exit criteria:** Raw data collected from all accessible rigs.""" - -[[steps]] -id = "generate-digest" -title = "Generate formatted digest" -needs = ["collect-rig-data"] -description = """ -Transform collected data into formatted digest. - -**1. Calculate summary statistics:** -- Total issues filed -- Total issues closed -- Net change (closed - filed) -- By type (task, bug, feature) -- By rig - -**2. Identify highlights:** -- Biggest completions (epics, large features) -- Incidents (any P0/P1 issues) -- Notable trends (increasing backlog, fast closure rate) - -**3. Generate digest text:** -```markdown -# Gas Town Daily Digest: {{date}} - -## Summary -- **Issues filed**: N (tasks: X, bugs: Y, features: Z) -- **Issues closed**: N -- **Net change**: +/-N - -## By Rig -| Rig | Filed | Closed | Active Polecats | -|-----|-------|--------|-----------------| -| gastown | X | Y | Z | -| beads | X | Y | Z | - -## Highlights -### Completed -- {{epic or feature}} - completed by {{polecat}} - -### Incidents -- {{incident summary if any}} - -## Agent Health -- Polecats spawned: N -- Polecats retired: N -- Average work duration: Xh - -## Trends -- Backlog: {{increasing/stable/decreasing}} -- Throughput: {{issues/day}} -``` - -**Exit criteria:** Formatted digest ready for delivery.""" - -[[steps]] -id = "send-digest" -title = "Send digest to overseer" -needs = ["generate-digest"] -description = """ -Deliver digest to the Mayor. - -**1. Send via mail:** -```bash -gt mail send mayor/ -s "Gas Town Digest: {{date}}" -m "$(cat </dev/null` -2. Not stalled: `gt peek deacon/` does NOT show \"> Try\" prompt -3. Heartbeat fresh: `deacon/heartbeat.json` modified < 2 min ago - -## OnStall -```bash -gt nudge deacon/ \"Start patrol.\" -sleep 30 -# Re-verify -```""" -id = "ensure-deacon" -needs = ["ensure-daemon"] -title = "Ensure deacon" - -[[steps]] -description = """ -Parallel container: Start all rig witnesses. - -Children execute in parallel. Container completes when all children complete.""" -id = "ensure-witnesses" -needs = ["ensure-deacon"] -title = "Ensure witnesses" -type = "parallel" - -[[steps.children]] -description = """ -Start the gastown rig Witness. - -## Action -```bash -gt witness start gastown -``` - -## Verify -1. Session exists: `tmux has-session -t gastown-witness 2>/dev/null` -2. Not stalled: `gt peek gastown/witness` does NOT show \"> Try\" prompt -3. Heartbeat fresh: Last patrol cycle < 5 min ago""" -id = "ensure-gastown-witness" -title = "Ensure gastown witness" - -[[steps.children]] -description = """ -Start the beads rig Witness. - -## Action -```bash -gt witness start beads -``` - -## Verify -1. Session exists: `tmux has-session -t beads-witness 2>/dev/null` -2. Not stalled: `gt peek beads/witness` does NOT show \"> Try\" prompt -3. Heartbeat fresh: Last patrol cycle < 5 min ago""" -id = "ensure-beads-witness" -title = "Ensure beads witness" - -[[steps]] -description = """ -Parallel container: Start all rig refineries. - -Children execute in parallel. Container completes when all children complete.""" -id = "ensure-refineries" -needs = ["ensure-deacon"] -title = "Ensure refineries" -type = "parallel" - -[[steps.children]] -description = """ -Start the gastown rig Refinery. - -## Action -```bash -gt refinery start gastown -``` - -## Verify -1. Session exists: `tmux has-session -t gastown-refinery 2>/dev/null` -2. Not stalled: `gt peek gastown/refinery` does NOT show \"> Try\" prompt -3. Queue processing: Refinery can receive merge requests""" -id = "ensure-gastown-refinery" -title = "Ensure gastown refinery" - -[[steps.children]] -description = """ -Start the beads rig Refinery. - -## Action -```bash -gt refinery start beads -``` - -## Verify -1. Session exists: `tmux has-session -t beads-refinery 2>/dev/null` -2. Not stalled: `gt peek beads/refinery` does NOT show \"> Try\" prompt -3. Queue processing: Refinery can receive merge requests""" -id = "ensure-beads-refinery" -title = "Ensure beads refinery" - -[[steps]] -description = """ -Final verification that Gas Town is healthy. - -## Action -```bash -gt status -``` - -## Verify -1. Daemon running: Shows daemon status OK -2. Deacon active: Shows deacon in patrol mode -3. All witnesses: Each rig witness shows active -4. All refineries: Each rig refinery shows active - -## OnFail -Log degraded state but consider boot complete. Some agents may need manual recovery. -Run `gt doctor` for detailed diagnostics.""" -id = "verify-town-health" -needs = ["ensure-witnesses", "ensure-refineries"] -title = "Verify town health" diff --git a/.beads/formulas/mol-orphan-scan.formula.toml b/.beads/formulas/mol-orphan-scan.formula.toml deleted file mode 100644 index 2bebf26c7..000000000 --- a/.beads/formulas/mol-orphan-scan.formula.toml +++ /dev/null @@ -1,312 +0,0 @@ -description = """ -Find and reassign orphaned work. - -Dogs work through molecules (poured from this formula) to scan for orphaned state: -- Issues marked in_progress with no active polecat -- Molecules attached but worker gone -- Merge queue entries with dead owners -- Wisps from terminated sessions - -This is a cleanup and recovery formula. Found orphans are either: -- Reassigned to available workers -- Reset to open status for next dispatch -- Escalated if data loss occurred - -## Dog Contract - -This is infrastructure work. You: -1. Receive scan scope via hook_bead (rig or town-wide) -2. Scan for orphaned state -3. Classify and triage orphans -4. Take recovery action -5. Report findings -6. Return to kennel - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| scope | hook_bead | Scan scope: 'town' or specific rig name | - -## Why Dogs? - -Orphan scanning requires multi-rig access and may need to interact with -multiple Witnesses. Dogs have the cross-rig worktrees needed for this.""" -formula = "mol-orphan-scan" -version = 1 - -[squash] -trigger = "on_complete" -template_type = "work" -include_metrics = true - -[[steps]] -id = "determine-scope" -title = "Determine scan scope" -description = """ -Establish what to scan for orphans. - -**1. Check assignment:** -```bash -gt hook # Shows scope in hook_bead -``` - -**2. Resolve scope:** -- 'town': Scan all rigs -- '': Scan specific rig only - -```bash -# If town-wide -gt rigs # Get list of all rigs - -# If specific rig -# Just use that rig -``` - -**Exit criteria:** Scope determined, rig list established.""" - -[[steps]] -id = "scan-orphaned-issues" -title = "Scan for orphaned issues" -needs = ["determine-scope"] -description = """ -Find issues marked in_progress with no active worker. - -**1. For each rig in scope, find in_progress issues:** -```bash -bd list --status=in_progress -``` - -**2. For each in_progress issue, check assignee:** -```bash -bd show -# Get assignee field -``` - -**3. Check if assignee session exists:** -```bash -# If assignee is a polecat -gt polecats # Is the polecat active? -tmux has-session -t 2>/dev/null -``` - -**4. Identify orphans:** -- Issue in_progress + assignee session dead = orphan -- Issue in_progress + no assignee = orphan - -Record each orphan with: -- Issue ID -- Last assignee (if any) -- How long orphaned (last update timestamp) - -**Exit criteria:** Orphaned issues identified.""" - -[[steps]] -id = "scan-orphaned-molecules" -title = "Scan for orphaned molecules" -needs = ["determine-scope"] -description = """ -Find molecules attached to dead sessions. - -**1. List active molecules:** -```bash -bd mol list --active -``` - -**2. For each molecule, check owner session:** -```bash -bd mol show -# Get agent/session info -``` - -**3. Check if owner session exists:** -```bash -tmux has-session -t 2>/dev/null -``` - -**4. Identify orphans:** -- Molecule in_progress + owner session dead = orphan -- Molecule hooked + owner session dead = orphan - -Record each orphan for triage. - -**Exit criteria:** Orphaned molecules identified.""" - -[[steps]] -id = "scan-orphaned-wisps" -title = "Scan for orphaned wisps" -needs = ["determine-scope"] -description = """ -Find wisps from terminated sessions. - -**1. List wisps in ephemeral storage:** -```bash -ls .beads-wisp/ # Or equivalent location -``` - -**2. For each wisp, check spawner session:** -Wisps should have metadata indicating the spawning session. - -**3. Identify orphans:** -- Wisp age > 1 hour + spawner session dead = orphan -- Wisp with no spawner metadata = orphan - -**4. Check for unsquashed content:** -Orphaned wisps may have audit-worthy content that wasn't squashed. - -**Exit criteria:** Orphaned wisps identified.""" - -[[steps]] -id = "triage-orphans" -title = "Classify and triage orphans" -needs = ["scan-orphaned-issues", "scan-orphaned-molecules", "scan-orphaned-wisps"] -description = """ -Classify orphans by severity and determine action. - -**1. Classify by type:** - -| Type | Severity | Typical Action | -|------|----------|----------------| -| Issue in_progress, no work done | Low | Reset to open | -| Issue in_progress, work in progress | Medium | Check branch, reassign | -| Molecule mid-execution | Medium | Resume or restart | -| Wisp with content | Low | Squash or burn | -| Wisp empty | None | Delete | - -**2. Check for data loss:** -For issues/molecules with possible work: -```bash -# Check for branch with work -git branch -a | grep -git log --oneline -``` - -**3. Categorize for action:** -- RESET: Return to open status for normal dispatch -- REASSIGN: Assign to specific worker immediately -- RECOVER: Salvage work from branch/state -- ESCALATE: Data loss or complex situation -- BURN: Safe to delete (empty wisps, etc.) - -**Exit criteria:** All orphans categorized with planned action.""" - -[[steps]] -id = "execute-recovery" -title = "Execute recovery actions" -needs = ["triage-orphans"] -description = """ -Take action on each orphan based on triage. - -**1. RESET orphans:** -```bash -bd update --status=open --assignee="" -# Clears in_progress, ready for dispatch -``` - -**2. REASSIGN orphans:** -```bash -# Notify Witness to handle assignment -gt mail send /witness -s "Orphan needs assignment: " \ - -m "Issue was orphaned. Has partial work. Needs reassignment." -``` - -**3. RECOVER orphans:** -```bash -# For issues with work on branch: -# - Preserve the branch -# - Create recovery note -bd update --status=open \ - --note="Recovery: work exists on branch " -``` - -**4. ESCALATE orphans:** -```bash -gt mail send mayor/ -s "Orphan requires escalation: " \ - -m "Issue orphaned with possible data loss. -Details: ... -Recommended action: ..." -``` - -**5. BURN orphans:** -```bash -# For empty wisps, etc. -rm .beads-wisp/ -``` - -**Exit criteria:** All orphans handled.""" - -[[steps]] -id = "report-findings" -title = "Generate and send orphan report" -needs = ["execute-recovery"] -description = """ -Create summary report of orphan scan and actions. - -**1. Generate report:** -```markdown -## Orphan Scan Report: {{timestamp}} - -**Scope**: {{scope}} -**Orphans found**: {{total_count}} - -### By Type -- Issues: {{issue_count}} -- Molecules: {{mol_count}} -- Wisps: {{wisp_count}} - -### Actions Taken -- Reset to open: {{reset_count}} -- Reassigned: {{reassign_count}} -- Recovered: {{recover_count}} -- Escalated: {{escalate_count}} -- Burned: {{burn_count}} - -### Details -{{#each orphan}} -- {{type}} {{id}}: {{action}} - {{reason}} -{{/each}} -``` - -**2. Send to Deacon (for logs):** -```bash -gt mail send deacon/ -s "Orphan scan complete: {{total_count}} found" \ - -m "{{report}}" -``` - -**3. Send to Mayor (if escalations):** -```bash -# Only if there were escalations -gt mail send mayor/ -s "Orphan scan: {{escalate_count}} escalations" \ - -m "{{escalations_section}}" -``` - -**Exit criteria:** Reports sent.""" - -[[steps]] -id = "return-to-kennel" -title = "Signal completion and return to kennel" -needs = ["report-findings"] -description = """ -Signal work complete and return to available pool. - -**1. Signal completion to Deacon:** -```bash -gt mail send deacon/ -s "DOG_DONE $(hostname)" -m "Task: orphan-scan -Scope: {{scope}} -Orphans found: {{total_count}} -Actions taken: {{action_summary}} -Status: COMPLETE - -Ready for next assignment." -``` - -**2. Return to kennel:** -Dog returns to available state in the pool. - -**Exit criteria:** Deacon notified, dog ready for next work.""" - -[vars] -[vars.scope] -description = "Scan scope: 'town' or specific rig name" -required = true -default = "town" diff --git a/.beads/formulas/mol-polecat-code-review.formula.toml b/.beads/formulas/mol-polecat-code-review.formula.toml deleted file mode 100644 index b4379e163..000000000 --- a/.beads/formulas/mol-polecat-code-review.formula.toml +++ /dev/null @@ -1,318 +0,0 @@ -description = """ -Review code and file beads for issues found. - -This molecule guides a polecat through a code review task - examining a portion -of the codebase for bugs, security issues, code quality problems, or improvement -opportunities. The output is a set of beads capturing actionable findings. - -## Polecat Contract (Self-Cleaning Model) - -You are a self-cleaning worker. You: -1. Receive work via your hook (pinned molecule + review scope) -2. Work through molecule steps using `bd ready` / `bd close ` -3. Complete and self-clean via `gt done` (submit findings + nuke yourself) -4. You are GONE - your findings are recorded in beads - -**Self-cleaning:** When you run `gt done`, you submit your findings, nuke your -sandbox, and exit. There is no idle state. Done means gone. - -**Important:** This formula defines the template. Your molecule already has step -beads created from it. Use `bd ready` to find them - do NOT read this file directly. - -**You do NOT:** -- Fix the issues yourself (file beads, let other polecats fix) -- Scope creep into unrelated areas -- Wait for someone to act on findings (you're done after filing) - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| scope | hook_bead | What to review (file path, directory, or description) | -| issue | hook_bead | The tracking issue for this review task | -| focus | hook_bead | Optional focus area (security, performance, etc.) | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| Scope too broad | Mail Witness, request narrower scope | -| Can't understand code | Mail Witness for context | -| Critical issue found | Mail Witness immediately, then continue |""" -formula = "mol-polecat-code-review" -version = 1 - -[[steps]] -id = "load-context" -title = "Load context and understand the review scope" -description = """ -Initialize your session and understand what you're reviewing. - -**1. Prime your environment:** -```bash -gt prime # Load role context -bd prime # Load beads context -``` - -**2. Check your hook:** -```bash -gt hook # Shows your pinned molecule and hook_bead -``` - -The hook_bead describes your review scope. Read the tracking issue: -```bash -bd show {{issue}} # Full issue details -``` - -**3. Understand the scope:** -- What files/directories are in scope? -- Is there a specific focus (security, performance, correctness)? -- What's the context - why is this review happening? - -**4. Locate the code:** -```bash -# If scope is a path: -ls -la {{scope}} -head -100 {{scope}} # Quick look at the code - -# If scope is a directory: -find {{scope}} -type f -name "*.go" | head -20 -``` - -**5. Check for recent changes:** -```bash -git log --oneline -10 -- {{scope}} -``` - -**Exit criteria:** You understand what you're reviewing and why.""" - -[[steps]] -id = "survey-code" -title = "Survey the code structure" -needs = ["load-context"] -description = """ -Get a high-level understanding before diving into details. - -**1. Understand the structure:** -```bash -# For a directory: -tree {{scope}} -L 2 - -# For a file: -wc -l {{scope}} # How big is it? -``` - -**2. Identify key components:** -- What are the main types/structs? -- What are the public functions? -- What are the dependencies? - -**3. Read the tests (if any):** -```bash -find {{scope}} -name "*_test.go" | xargs head -50 -``` -Tests often reveal intended behavior. - -**4. Note initial impressions:** -- Is the code well-organized? -- Are there obvious patterns or anti-patterns? -- What areas look risky? - -**Exit criteria:** You have a mental map of the code structure.""" - -[[steps]] -id = "detailed-review" -title = "Perform detailed code review" -needs = ["survey-code"] -description = """ -Systematically review the code for issues. - -**Review checklist:** - -| Category | Look For | -|----------|----------| -| **Correctness** | Logic errors, off-by-one, nil handling, race conditions | -| **Security** | Injection, auth bypass, secrets in code, unsafe operations | -| **Error handling** | Swallowed errors, missing checks, unclear error messages | -| **Performance** | N+1 queries, unnecessary allocations, blocking calls | -| **Maintainability** | Dead code, unclear naming, missing comments on complex logic | -| **Testing** | Untested paths, missing edge cases, flaky tests | - -**Focus on {{focus}} if specified.** - -**1. Read through the code:** -```bash -cat {{scope}} # For single file -# Or read files systematically for a directory -``` - -**2. For each issue found, note:** -- File and line number -- Category (bug, security, performance, etc.) -- Severity (critical, high, medium, low) -- Description of the issue -- Suggested fix (if obvious) - -**3. Don't fix issues yourself:** -Your job is to find and report, not fix. File beads. - -**Exit criteria:** You've reviewed all code in scope and noted issues.""" - -[[steps]] -id = "prioritize-findings" -title = "Prioritize and categorize findings" -needs = ["detailed-review"] -description = """ -Organize your findings by priority and category. - -**Priority levels:** - -| Priority | Description | Action | -|----------|-------------|--------| -| P0 | Security vulnerability, data loss risk | Mail Witness immediately | -| P1 | Bug affecting users, broken functionality | File as bug, high priority | -| P2 | Code quality issue, potential future bug | File as task | -| P3 | Improvement opportunity, nice-to-have | File as task, low priority | - -**1. Sort your findings:** -Group by priority, then by category. - -**2. For P0 issues:** -```bash -gt mail send {{rig}}/witness -s "CRITICAL: Security issue found" -m "Scope: {{scope}} -Issue: {{issue}} -Finding: -Location: " -``` - -**3. Prepare bead descriptions:** -For each finding, prepare: -- Clear title -- File/line location -- Description of the issue -- Why it matters -- Suggested fix (if known) - -**Exit criteria:** Findings prioritized and ready to file.""" - -[[steps]] -id = "file-beads" -title = "File beads for all findings" -needs = ["prioritize-findings"] -description = """ -Create beads for each finding. - -**1. For bugs (P0, P1):** -```bash -bd create --type=bug --priority=1 \ - --title="" \ - --description="Found during code review of {{scope}}. - -Location: - -Issue: - - -Impact: - - -Suggested fix: -" -``` - -**2. For code quality issues (P2, P3):** -```bash -bd create --type=task --priority=2 \ - --title="" \ - --description="Found during code review of {{scope}}. - -Location: - -Issue: - - -Suggestion: -" -``` - -**3. Track filed beads:** -Note each bead ID as you create them. - -**4. If no issues found:** -That's a valid outcome! Note that the code review passed. - -**Exit criteria:** All findings filed as beads.""" - -[[steps]] -id = "summarize-review" -title = "Summarize review results" -needs = ["file-beads"] -description = """ -Update the tracking issue with review summary. - -**1. Create summary:** -```bash -bd update {{issue}} --notes "Code review complete. - -Scope: {{scope}} -Focus: {{focus}} - -Findings: -- P0 (critical): -- P1 (high): -- P2 (medium): -- P3 (low): - -Beads filed: - - -Overall assessment: -" -``` - -**2. Sync beads:** -```bash -bd sync -``` - -**Exit criteria:** Tracking issue updated with summary.""" - -[[steps]] -id = "complete-and-exit" -title = "Complete review and self-clean" -needs = ["summarize-review"] -description = """ -Signal completion and clean up. You cease to exist after this step. - -**Self-Cleaning Model:** -Once you run `gt done`, you're gone. The command: -1. Syncs beads (final sync) -2. Nukes your sandbox -3. Exits your session immediately - -**Run gt done:** -```bash -gt done -``` - -**What happens next (not your concern):** -- Other polecats may be assigned to fix the issues you found -- Witness may escalate critical findings -- The codebase improves based on your findings - -You are NOT involved in any of that. You're gone. Done means gone. - -**Exit criteria:** Beads synced, sandbox nuked, session exited.""" - -[vars] -[vars.scope] -description = "What to review - file path, directory, or description" -required = true - -[vars.issue] -description = "The tracking issue for this review task" -required = true - -[vars.focus] -description = "Optional focus area (security, performance, correctness, etc.)" -required = false diff --git a/.beads/formulas/mol-polecat-conflict-resolve.formula.toml b/.beads/formulas/mol-polecat-conflict-resolve.formula.toml deleted file mode 100644 index 127e5078c..000000000 --- a/.beads/formulas/mol-polecat-conflict-resolve.formula.toml +++ /dev/null @@ -1,385 +0,0 @@ -description = """ -Conflict resolution workflow for polecats handling merge conflicts. - -This molecule guides a polecat through resolving merge conflicts for a previously -submitted MR that failed to rebase. The workflow uses the merge-slot gate to -serialize conflict resolution and prevent racing. - -## Task Recognition - -Conflict resolution tasks are created by the Refinery when a mechanical rebase -fails. They are identified by: -- Title prefix: "Resolve merge conflicts:" -- Metadata fields in description: Original MR, Branch, Conflict SHA - -## Key Differences from Regular Polecat Work - -| Aspect | Regular Work | Conflict Resolution | -|--------|--------------|---------------------| -| Branch source | Create new branch | Checkout existing MR branch | -| Merge path | Submit to queue via `gt done` | Push directly to main | -| Issue closure | Refinery closes after merge | Close MR bead yourself | -| Serialization | None | Merge-slot gate required | - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| task | hook_bead | The conflict-resolution task ID | -| original_mr | task metadata | The MR bead that had conflicts | -| branch | task metadata | The branch to rebase | -| conflict_sha | task metadata | Main SHA when conflict occurred | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| Merge slot held | Wait (--wait flag adds you to queue) | -| Complex conflicts | Use judgment; escalate if unsure | -| Tests fail after resolve | Fix them before pushing | -| Resolution unclear | Read original issue for context |""" -formula = "mol-polecat-conflict-resolve" -version = 1 - -[[steps]] -id = "load-task" -title = "Load task and extract metadata" -description = """ -Initialize your session and understand the conflict resolution task. - -**1. Prime your environment:** -```bash -gt prime # Load role context -bd prime # Load beads context -``` - -**2. Check your hook:** -```bash -gt hook # Shows your pinned molecule and hook_bead -``` - -**3. Read the conflict resolution task:** -```bash -bd show {{task}} -``` - -**4. Extract metadata from the task description:** - -The task description contains structured metadata: -``` -## Metadata -- Original MR: -- Branch: -- Conflict with: @ -- Original issue: -- Retry count: -``` - -Parse and note: -- **original_mr**: The MR bead ID (you'll close this after merge) -- **branch**: The branch to checkout and rebase -- **source_issue**: The original work issue (read for context if needed) -- **retry_count**: How many times this has been attempted - -**5. Understand the context:** - -If the conflict seems complex, read the original issue: -```bash -bd show # What was the original work? -``` - -**Exit criteria:** You have all metadata and understand the conflict context.""" - -[[steps]] -id = "acquire-slot" -title = "Acquire merge slot" -needs = ["load-task"] -description = """ -Acquire exclusive access to the merge slot before proceeding. - -The merge slot prevents multiple conflict-resolution polecats from racing -to push to main simultaneously (the "Monkey Knife Fight" problem). - -**1. Check slot availability:** -```bash -bd merge-slot check --json -``` - -**2. Acquire the slot:** -```bash -bd merge-slot acquire --holder=$(whoami) --wait --json -``` - -The `--wait` flag adds you to the waiters queue if the slot is held. -You'll proceed when the current holder releases. - -**3. Verify acquisition:** -The output should show: -```json -{"available": false, "holder": "your-name", ...} -``` - -If you're in the waiters list, wait for the holder to release. Check -periodically: -```bash -bd merge-slot check --json -``` - -**Important:** Once you have the slot, complete the workflow promptly. -Other polecats may be waiting. - -**Exit criteria:** You hold the merge slot exclusively.""" - -[[steps]] -id = "checkout-branch" -title = "Checkout and prepare the conflicting branch" -needs = ["acquire-slot"] -description = """ -Fetch and checkout the branch that needs conflict resolution. - -**1. Ensure clean workspace:** -```bash -git status # Should be clean -git stash list # Should be empty -``` - -If dirty, clean up first (stash or discard). - -**2. Fetch latest state:** -```bash -git fetch origin -git fetch origin {{branch}}:refs/remotes/origin/{{branch}} -``` - -**3. Checkout the branch:** -```bash -git checkout -b temp-resolve origin/{{branch}} -``` - -Using `temp-resolve` as the local branch name keeps things clear. - -**4. Verify the branch state:** -```bash -git log --oneline -5 # Recent commits -git log origin/main..HEAD # Commits not on main -``` - -**Exit criteria:** On temp-resolve branch, ready to rebase.""" - -[[steps]] -id = "rebase-resolve" -title = "Rebase onto main and resolve conflicts" -needs = ["checkout-branch"] -description = """ -Perform the rebase and resolve any conflicts. - -**1. Start the rebase:** -```bash -git rebase origin/main -``` - -**2. If conflicts occur:** - -For each conflicted file: -```bash -git status # See conflicted files -git diff # See conflict markers -``` - -**Resolve using your judgment:** -- Read both versions carefully -- Consider the original intent (from source issue) -- If the MR was adding a feature, preserve that addition -- If the MR was fixing a bug, ensure the fix remains - -**After resolving each file:** -```bash -git add -git rebase --continue -``` - -**3. If stuck on a conflict:** -- Read the original issue for context: `bd show ` -- If still unclear, escalate to Witness: - ```bash - gt mail send /witness -s "HELP: Complex conflict" -m "Task: {{task}} - File: - Issue: Cannot determine correct resolution" - ``` - -**4. Verify rebase success:** -```bash -git log --oneline origin/main..HEAD # Your commits rebased -git status # Clean working tree -``` - -**Exit criteria:** Branch successfully rebased onto origin/main.""" - -[[steps]] -id = "run-tests" -title = "Run tests to verify resolution" -needs = ["rebase-resolve"] -description = """ -Verify the resolution doesn't break anything. - -**1. Run the test suite:** -```bash -go test ./... # Or appropriate test command -``` - -**ALL TESTS MUST PASS.** Do not push with failures. - -**2. If tests fail:** -- Determine if it's a resolution error or pre-existing -- If your resolution broke something: fix it -- If pre-existing: file a bead, but still must fix before pushing - -```bash -# Quick check: does main pass? -git stash -git checkout origin/main -go test ./... -git checkout temp-resolve -git stash pop -``` - -**3. Run build check:** -```bash -go build ./... -``` - -**Exit criteria:** All tests pass, build succeeds.""" - -[[steps]] -id = "push-to-main" -title = "Push resolved changes directly to main" -needs = ["run-tests"] -description = """ -Push the resolved branch directly to main. - -**Important:** Unlike normal polecat work, conflict resolution pushes directly -to main. This is because: -1. The original MR was already reviewed/approved by being in the queue -2. We're just resolving conflicts, not adding new functionality -3. Going back through the queue would create an infinite loop - -**1. Rebase one more time (in case main moved):** -```bash -git fetch origin -git rebase origin/main -``` - -If new conflicts: resolve them (return to rebase-resolve step). - -**2. Push to main:** -```bash -git push origin temp-resolve:main -``` - -**3. Verify the push:** -```bash -git log origin/main --oneline -3 # Your commits should be there -``` - -**Exit criteria:** Changes are on origin/main.""" - -[[steps]] -id = "close-beads" -title = "Close the original MR bead and this task" -needs = ["push-to-main"] -description = """ -Close the beads to complete the work chain. - -**1. Close the original MR bead:** -```bash -bd close {{original_mr}} --reason="merged after conflict resolution" -``` - -This completes the MR that was blocked on conflicts. - -**2. Close the source issue (if not already closed):** -```bash -bd show # Check status -bd close --reason="merged via conflict resolution" -``` - -The Refinery normally closes issues after merge, but since we pushed -directly to main, we handle it here. - -**3. Sync beads:** -```bash -bd sync -``` - -**Exit criteria:** Original MR and source issue are closed.""" - -[[steps]] -id = "release-slot" -title = "Release merge slot" -needs = ["close-beads"] -description = """ -Release the merge slot so other polecats can proceed. - -**1. Release the slot:** -```bash -bd merge-slot release --holder=$(whoami) --json -``` - -**2. Verify release:** -```bash -bd merge-slot check --json -``` - -Should show either: -- `available: true` (no one waiting) -- `holder: ` (slot passed to next in queue) - -**Exit criteria:** Merge slot released.""" - -[[steps]] -id = "cleanup-and-exit" -title = "Clean up and close task" -needs = ["release-slot"] -description = """ -Clean up workspace and close the conflict resolution task. - -**1. Clean up local branch:** -```bash -git checkout main -git branch -D temp-resolve -git fetch origin -git reset --hard origin/main -``` - -**2. Verify clean state:** -```bash -git status # Clean -git stash list # Empty -``` - -**3. Close this task:** -```bash -bd close {{task}} --reason="Conflicts resolved and merged to main" -``` - -**4. Signal completion:** -```bash -gt done -``` - -You're now recyclable. The Witness knows you've completed conflict resolution. - -**Exit criteria:** Task closed, workspace clean, polecat recyclable.""" - -[vars] -[vars.task] -description = "The conflict resolution task ID assigned to this polecat" -required = true - -[vars.original_mr] -description = "The original MR bead ID (extracted from task metadata)" -required = true - -[vars.branch] -description = "The branch to rebase (extracted from task metadata)" -required = true diff --git a/.beads/formulas/mol-polecat-lease.formula.toml b/.beads/formulas/mol-polecat-lease.formula.toml deleted file mode 100644 index 75acd76c8..000000000 --- a/.beads/formulas/mol-polecat-lease.formula.toml +++ /dev/null @@ -1,198 +0,0 @@ -description = """ -Witness-side tracking of a single polecat's lifecycle. - -The Witness bonds this molecule for each active polecat, creating a lease that -tracks the polecat from spawn through work to cleanup. This is the WITNESS'S -view of the polecat, not the polecat's own work molecule. - -## Lifecycle States - -``` -BOOT ─► WORKING ─► VERIFYING ─► MERGE_REQUESTED ─► DONE - │ │ │ │ - └─► STUCK ─┴─► STUCK ──┴──► STUCK ───┘ -``` - -## Variables - -| Variable | Required | Description | -|----------|----------|-------------| -| polecat | Yes | Name of the polecat | -| issue | Yes | The issue assigned to the polecat | -| rig | Yes | The rig this polecat belongs to |""" -formula = "mol-polecat-lease" -version = 2 - -[[steps]] -id = "boot" -title = "Verify polecat boots successfully" -description = """ -Polecat has been spawned. Verify it initializes and starts working. - -**Check if alive:** -```bash -tmux capture-pane -t gt-{{rig}}-{{polecat}} -p | tail -20 -``` - -Look for: -- Claude prompt visible ("> " at start of line) -- `gt prime` output -- Signs of reading the assigned issue - -**If idle for >60 seconds:** -```bash -gt nudge {{rig}}/polecats/{{polecat}} "Begin work on {{issue}}." -``` - -**If still no response after nudge:** -```bash -gt nudge {{rig}}/polecats/{{polecat}} "Are you there? Please acknowledge." -``` - -After 3 failed nudges, mark as stuck and escalate. - -**Exit criteria:** Polecat shows signs of active work on {{issue}}.""" - -[[steps]] -id = "working" -title = "Monitor polecat progress" -needs = ["boot"] -description = """ -Polecat is actively working. Monitor for stuck or completion. - -**Periodic checks:** -- Use standard nudge protocol from Witness CLAUDE.md -- Watch for POLECAT_DONE mail or agent_state=done - -**Signs of progress:** -- Git commits appearing -- File changes visible in peek -- Active tool usage in tmux capture - -**Signs of stuck:** -- Idle >15 minutes -- Repeated errors -- Explicit "I'm stuck" messages - -**If POLECAT_DONE received or agent_state=done:** -Proceed to verifying step. - -**Exit criteria:** Polecat signals completion (POLECAT_DONE mail or state=done).""" - -[[steps]] -id = "verifying" -title = "Verify polecat work is merge-ready" -needs = ["working"] -description = """ -Polecat claims completion. Verify before sending to Refinery. - -**1. Check git state:** -```bash -cd polecats/{{polecat}} -git status # Must be "working tree clean" -git stash list # Must be empty -git log origin/main..HEAD # Should have commits -``` - -**2. Verify branch is pushed:** -```bash -git log origin/$(git branch --show-current)..HEAD # Should be empty -``` - -**3. Verify issue is closed:** -```bash -bd show {{issue}} # Status should be 'closed' -``` - -**4. Spot-check quality (ZFC - your judgment):** -- Commits have reasonable messages -- Changes look related to issue -- No obvious problems in git log - -**If verification fails:** -Nudge polecat to fix: -```bash -gt nudge {{rig}}/polecats/{{polecat}} "Verification failed: . Please fix." -``` -Return to working step. - -**If verification passes:** -Proceed to merge_requested step. - -**Exit criteria:** Git clean, branch pushed, issue closed, work looks legit.""" - -[[steps]] -id = "merge_requested" -title = "Request merge from Refinery" -needs = ["verifying"] -description = """ -Work verified. Send MERGE_READY to Refinery and wait. - -**Send merge request:** -```bash -gt mail send {{rig}}/refinery -s "MERGE_READY {{polecat}}" -m "Branch: $(cd polecats/{{polecat}} && git branch --show-current) -Issue: {{issue}} -Polecat: {{polecat}} -Verified: clean git state, issue closed" -``` - -**Update cleanup wisp state:** -```bash -bd update --labels cleanup,polecat:{{polecat}},state:merge-requested -``` - -**Wait for MERGED response:** -The Refinery will: -1. Fetch and rebase the branch -2. Run tests -3. Merge to main (if pass) -4. Send MERGED mail back - -This may take several minutes. - -**If MERGED received:** Proceed to done step. -**If merge fails:** Refinery notifies, return to working state. - -**Exit criteria:** MERGED mail received from Refinery.""" - -[[steps]] -id = "done" -title = "Complete polecat cleanup" -needs = ["merge_requested"] -description = """ -Merge confirmed. Clean up the polecat. - -**1. Kill the polecat session:** -```bash -gt session kill {{rig}}/polecats/{{polecat}} -``` - -**2. Remove worktree (if ephemeral):** -```bash -git worktree remove polecats/{{polecat}} --force -``` - -**3. Delete local branch (if exists):** -```bash -git branch -D polecat/{{polecat}} 2>/dev/null || true -``` - -**4. Close this lease:** -```bash -bd close -``` - -**Exit criteria:** Polecat session killed, worktree removed, lease closed.""" - -[vars] -[vars.polecat] -description = "Name of the polecat" -required = true - -[vars.issue] -description = "The issue assigned to the polecat" -required = true - -[vars.rig] -description = "The rig this polecat belongs to" -required = true diff --git a/.beads/formulas/mol-polecat-review-pr.formula.toml b/.beads/formulas/mol-polecat-review-pr.formula.toml deleted file mode 100644 index d789152fb..000000000 --- a/.beads/formulas/mol-polecat-review-pr.formula.toml +++ /dev/null @@ -1,283 +0,0 @@ -description = """ -Review an external PR and decide on merge/reject/revise. - -This molecule guides a polecat through reviewing a pull request from an external -contributor. The polecat reviews code quality, tests, and alignment with project -standards, then approves, requests changes, or files followup beads. - -## Polecat Contract (Self-Cleaning Model) - -You are a self-cleaning worker. You: -1. Receive work via your hook (pinned molecule + PR reference) -2. Work through molecule steps using `bd ready` / `bd close ` -3. Complete and self-clean via `gt done` (submit findings + nuke yourself) -4. You are GONE - your review is recorded in beads - -**Self-cleaning:** When you run `gt done`, you submit your findings, nuke your -sandbox, and exit. There is no idle state. Done means gone. - -**Important:** This formula defines the template. Your molecule already has step -beads created from it. Use `bd ready` to find them - do NOT read this file directly. - -**You do NOT:** -- Merge the PR yourself (maintainer or Refinery does that) -- Push to the PR branch (it's external) -- Wait for contributor response (you're done after review) - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| pr_url | hook_bead | The PR URL to review | -| issue | hook_bead | The tracking issue for this review task | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| PR is stale/unmergeable | Note in review, request rebase | -| Tests fail | Note in review, request fixes | -| Major issues found | File followup beads, request changes | -| Unclear requirements | Mail Witness for guidance |""" -formula = "mol-polecat-review-pr" -version = 1 - -[[steps]] -id = "load-context" -title = "Load context and understand the PR" -description = """ -Initialize your session and understand the PR you're reviewing. - -**1. Prime your environment:** -```bash -gt prime # Load role context -bd prime # Load beads context -``` - -**2. Check your hook:** -```bash -gt hook # Shows your pinned molecule and hook_bead -``` - -The hook_bead references the PR to review. Read the tracking issue: -```bash -bd show {{issue}} # Full issue details including PR URL -``` - -**3. Fetch the PR:** -```bash -gh pr view {{pr_url}} --json title,body,author,files,commits -gh pr diff {{pr_url}} # See the actual changes -``` - -**4. Understand the PR:** -- What is the PR trying to accomplish? -- What files are changed? -- Is there a linked issue? -- Does the PR description explain the "why"? - -**5. Check PR status:** -```bash -gh pr checks {{pr_url}} # CI status -gh pr view {{pr_url}} --json mergeable,reviewDecision -``` - -**Exit criteria:** You understand the PR's purpose and scope.""" - -[[steps]] -id = "review-code" -title = "Review the code changes" -needs = ["load-context"] -description = """ -Perform a thorough code review of the PR. - -**1. Review the diff systematically:** -```bash -gh pr diff {{pr_url}} -``` - -**2. Check for common issues:** - -| Category | Look For | -|----------|----------| -| Correctness | Logic errors, edge cases, null handling | -| Security | Injection, auth bypass, exposed secrets | -| Style | Naming, formatting, consistency with codebase | -| Tests | Are changes tested? Do tests cover edge cases? | -| Docs | Are docs updated if needed? | -| Scope | Does PR stay focused? Any scope creep? | - -**3. For each file changed:** -- Does the change make sense? -- Is it consistent with existing patterns? -- Are there any red flags? - -**4. Note issues found:** -Keep a running list of: -- Blocking issues (must fix before merge) -- Suggestions (nice to have) -- Questions (need clarification) - -**Exit criteria:** You have reviewed all changes and noted issues.""" - -[[steps]] -id = "check-tests" -title = "Verify tests and CI" -needs = ["review-code"] -description = """ -Ensure tests pass and coverage is adequate. - -**1. Check CI status:** -```bash -gh pr checks {{pr_url}} -``` - -All required checks should pass. If not, note which are failing. - -**2. Review test changes:** -- Are there new tests for new functionality? -- Do tests cover edge cases? -- Are tests readable and maintainable? - -**3. If tests are missing:** -Note this as a blocking issue - new code should have tests. - -**4. Check for test-only changes:** -If PR is test-only, ensure tests are meaningful and not just -padding coverage numbers. - -**Exit criteria:** You've verified test status and coverage.""" - -[[steps]] -id = "make-decision" -title = "Decide: approve, request changes, or needs discussion" -needs = ["check-tests"] -description = """ -Make your review decision. - -**Decision matrix:** - -| Situation | Decision | -|-----------|----------| -| Clean code, tests pass, good scope | APPROVE | -| Minor issues, easily fixed | REQUEST_CHANGES (with specific feedback) | -| Major issues, needs rework | REQUEST_CHANGES (with detailed explanation) | -| Unclear requirements or scope | NEEDS_DISCUSSION (mail Witness) | -| Security concern | BLOCK (mail Witness immediately) | - -**1. If APPROVE:** -The PR is ready to merge. Note any minor suggestions as comments -but don't block on them. - -**2. If REQUEST_CHANGES:** -Be specific about what needs to change. Provide examples if helpful. -The contributor should be able to act on your feedback. - -**3. If NEEDS_DISCUSSION:** -```bash -gt mail send {{rig}}/witness -s "PR review needs discussion" -m "PR: {{pr_url}} -Issue: {{issue}} -Question: " -``` - -**4. If BLOCK (security):** -```bash -gt mail send {{rig}}/witness -s "SECURITY: PR blocked" -m "PR: {{pr_url}} -Issue: {{issue}} -Concern: " -``` - -**Exit criteria:** You've made a clear decision with rationale.""" - -[[steps]] -id = "submit-review" -title = "Submit the review on GitHub" -needs = ["make-decision"] -description = """ -Submit your review via GitHub. - -**1. Submit the review:** -```bash -# For APPROVE: -gh pr review {{pr_url}} --approve --body "LGTM. " - -# For REQUEST_CHANGES: -gh pr review {{pr_url}} --request-changes --body "" - -# For COMMENT (needs discussion): -gh pr review {{pr_url}} --comment --body "" -``` - -**2. Add inline comments if needed:** -If you have specific line-by-line feedback, add those via GitHub UI -or additional `gh pr comment` calls. - -**Exit criteria:** Review submitted on GitHub.""" - -[[steps]] -id = "file-followups" -title = "File beads for any followup work" -needs = ["submit-review"] -description = """ -Create beads for any followup work discovered during review. - -**1. For issues found that are outside PR scope:** -```bash -bd create --type=bug --title="Found during PR review: " \ - --description="Discovered while reviewing {{pr_url}}. - -
" -``` - -**2. For improvements suggested but not required:** -```bash -bd create --type=task --title="Improvement: " \ - --description="Suggested during review of {{pr_url}}. - -
" -``` - -**3. Update the tracking issue:** -```bash -bd update {{issue}} --notes "Review complete. Decision: -Followups filed: " -``` - -**Exit criteria:** All followup work captured as beads.""" - -[[steps]] -id = "complete-and-exit" -title = "Complete review and self-clean" -needs = ["file-followups"] -description = """ -Signal completion and clean up. You cease to exist after this step. - -**Self-Cleaning Model:** -Once you run `gt done`, you're gone. The command: -1. Syncs beads -2. Nukes your sandbox -3. Exits your session immediately - -**Run gt done:** -```bash -bd sync -gt done -``` - -**What happens next (not your concern):** -- Maintainer or Refinery acts on your review -- Contributor responds to feedback -- PR gets merged, revised, or closed - -You are NOT involved in any of that. You're gone. Done means gone. - -**Exit criteria:** Beads synced, sandbox nuked, session exited.""" - -[vars] -[vars.pr_url] -description = "The PR URL to review" -required = true - -[vars.issue] -description = "The tracking issue for this review task" -required = true diff --git a/.beads/formulas/mol-polecat-work.formula.toml b/.beads/formulas/mol-polecat-work.formula.toml deleted file mode 100644 index 442e23d60..000000000 --- a/.beads/formulas/mol-polecat-work.formula.toml +++ /dev/null @@ -1,454 +0,0 @@ -description = """ -Full polecat work lifecycle from assignment through completion. - -This molecule guides a polecat through a complete work assignment. Each step -has clear entry/exit criteria and specific commands to run. A polecat can -crash after any step and resume from the last completed step. - -## Polecat Contract (Self-Cleaning Model) - -You are a self-cleaning worker. You: -1. Receive work via your hook (pinned molecule + issue) -2. Work through molecule steps using `bd ready` / `bd close ` -3. Complete and self-clean via `gt done` (submit + nuke yourself) -4. You are GONE - Refinery merges from MQ - -**Self-cleaning:** When you run `gt done`, you push your work, submit to MQ, -nuke your sandbox, and exit. There is no idle state. Done means gone. - -**Important:** This formula defines the template. Your molecule already has step -beads created from it. Use `bd ready` to find them - do NOT read this file directly. - -**You do NOT:** -- Push directly to main (Refinery merges from MQ) -- Close your own issue (Refinery closes after merge) -- Wait for merge (you're gone after `gt done`) -- Handle rebase conflicts (Refinery spawns fresh polecats for that) - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| issue | hook_bead | The issue ID you're assigned to work on | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| Tests fail | Fix them. Do not proceed with failures. | -| Blocked on external | Mail Witness for help, mark yourself stuck | -| Context filling | Use gt handoff to cycle to fresh session | -| Unsure what to do | Mail Witness, don't guess |""" -formula = "mol-polecat-work" -version = 4 - -[[steps]] -id = "load-context" -title = "Load context and verify assignment" -description = """ -Initialize your session and understand your assignment. - -**1. Prime your environment:** -```bash -gt prime # Load role context -bd prime # Load beads context -``` - -**2. Check your hook:** -```bash -gt hook # Shows your pinned molecule and hook_bead -``` - -The hook_bead is your assigned issue. Read it carefully: -```bash -bd show {{issue}} # Full issue details -``` - -**3. Check inbox for additional context:** -```bash -gt mail inbox -# Read any HANDOFF or assignment messages -``` - -**4. Understand the requirements:** -- What exactly needs to be done? -- What files are likely involved? -- Are there dependencies or blockers? -- What does "done" look like? - -**5. Verify you can proceed:** -- No unresolved blockers on the issue -- You understand what to do -- Required resources are available - -If blocked or unclear, mail Witness immediately: -```bash -gt mail send /witness -s "HELP: Unclear requirements" -m "Issue: {{issue}} -Question: " -``` - -**Exit criteria:** You understand the work and can begin implementation.""" - -[[steps]] -id = "branch-setup" -title = "Set up working branch" -needs = ["load-context"] -description = """ -Ensure you're on a clean feature branch ready for work. - -**1. Check current branch state:** -```bash -git status -git branch --show-current -``` - -**2. If not on a feature branch, create one:** -```bash -# Standard naming: polecat/ or feature/ -git checkout -b polecat/ -``` - -**3. Ensure clean working state:** -```bash -git status # Should show "working tree clean" -git stash list # Should be empty -``` - -If dirty state from previous work: -```bash -# If changes are relevant to this issue: -git add -A && git commit -m "WIP: " - -# If changes are unrelated cruft: -git stash push -m "unrelated changes before {{issue}}" -# Or discard if truly garbage: -git checkout -- . -``` - -**4. Sync with main:** -```bash -git fetch origin -git rebase origin/main # Get latest, rebase your branch -``` - -If rebase conflicts: -- Resolve them carefully -- Test after resolution -- If stuck, mail Witness - -**Exit criteria:** You're on a clean feature branch, rebased on latest main.""" - -[[steps]] -id = "preflight-tests" -title = "Verify tests pass on main" -needs = ["branch-setup"] -description = """ -Check if the codebase is healthy BEFORE starting your work. - -**The Scotty Principle:** Don't walk past a broken warp core. But also don't -let someone else's mess consume your entire mission. - -**1. Check tests on main:** -```bash -git stash # Save your branch state -git checkout origin/main -go test ./... # Or appropriate test command -``` - -**2. If tests PASS:** -```bash -git checkout - # Back to your branch -git stash pop # Restore state -``` -Continue to implement step. - -**3. If tests FAIL on main:** - -Make a judgment call: - -| Situation | Action | -|-----------|--------| -| Quick fix (<15 min) | Fix it, commit to main, then continue | -| Medium fix (15-60 min) | Fix if it blocks your work, else file bead | -| Big fix (>1 hour) | File bead, notify Witness, proceed with your work | - -**Quick fix path:** -```bash -# Fix the issue -git add -git commit -m "fix: (pre-existing failure)" -git push origin main -git checkout - -git stash pop -git rebase origin/main # Get your fix -``` - -**File and proceed path:** -```bash -bd create --title "Pre-existing test failure: " \ - --type bug --priority 1 - -gt mail send /witness -s "NOTICE: Main has failing tests" \ - -m "Found pre-existing test failures on main. -Filed: -Proceeding with my assigned work ({{issue}})." - -git checkout - -git stash pop -``` - -**Context consideration:** -If fixing pre-existing failures consumed significant context: -```bash -gt handoff -s "Fixed pre-existing failures, ready for assigned work" \ - -m "Issue: {{issue}} -Fixed: -Ready to start: implement step" -``` -Fresh session continues from implement. - -**Exit criteria:** Tests pass on main (or issue filed), ready to implement.""" - -[[steps]] -id = "implement" -title = "Implement the solution" -needs = ["preflight-tests"] -description = """ -Do the actual implementation work. - -**Working principles:** -- Follow existing codebase conventions -- Make atomic, focused commits -- Keep changes scoped to the assigned issue -- Don't gold-plate or scope-creep - -**Commit frequently:** -```bash -# After each logical unit of work: -git add -git commit -m ": ({{issue}})" -``` - -Commit types: feat, fix, refactor, test, docs, chore - -**Discovered work:** -If you find bugs or improvements outside your scope: -```bash -bd create --title "Found: " --type bug --priority 2 -# Note the ID, continue with your work -``` - -Do NOT fix unrelated issues in this branch. - -**If stuck:** -Don't spin for more than 15 minutes. Mail Witness: -```bash -gt mail send /witness -s "HELP: Stuck on implementation" -m "Issue: {{issue}} -Trying to: -Problem: -Tried: " -``` - -**Exit criteria:** Implementation complete, all changes committed.""" - -[[steps]] -id = "self-review" -title = "Self-review changes" -needs = ["implement"] -description = """ -Review your own changes before running tests. - -**1. Review the diff:** -```bash -git diff origin/main...HEAD # All changes vs main -git log --oneline origin/main..HEAD # All commits -``` - -**2. Check for common issues:** - -| Category | Look For | -|----------|----------| -| Bugs | Off-by-one, null handling, edge cases | -| Security | Injection, auth bypass, exposed secrets | -| Style | Naming, formatting, code organization | -| Completeness | Missing error handling, incomplete paths | -| Cruft | Debug prints, commented code, TODOs | - -**3. Fix issues found:** -Don't just note them - fix them now. Amend or add commits as needed. - -**4. Verify no unintended changes:** -```bash -git diff --stat origin/main...HEAD -# Only files relevant to {{issue}} should appear -``` - -If you accidentally modified unrelated files, remove those changes. - -**Exit criteria:** Changes are clean, reviewed, and ready for testing.""" - -[[steps]] -id = "run-tests" -title = "Run tests and verify coverage" -needs = ["self-review"] -description = """ -Verify your changes don't break anything and are properly tested. - -**1. Run the full test suite:** -```bash -go test ./... # For Go projects -# Or appropriate command for your stack -``` - -**ALL TESTS MUST PASS.** Do not proceed with failures. - -**2. If tests fail:** -- Read the failure output carefully -- Determine if your change caused it: - - If yes: Fix it. Return to implement step if needed. - - If no (pre-existing): File a bead, but still must pass for your PR - -```bash -# Check if failure exists on main: -git stash -git checkout main -go test ./... -git checkout - -git stash pop -``` - -**3. Verify test coverage for new code:** -- New features should have tests -- Bug fixes should have regression tests -- If you added significant code without tests, add them now - -**4. Run any other quality checks:** -```bash -# Linting (if configured) -golangci-lint run ./... - -# Build check -go build ./... -``` - -**Exit criteria:** All tests pass, new code has appropriate test coverage.""" - -[[steps]] -id = "cleanup-workspace" -title = "Clean up workspace" -needs = ["run-tests"] -description = """ -Ensure workspace is pristine before handoff. - -**1. Check for uncommitted changes:** -```bash -git status -``` -Must show "working tree clean". If not: -- Commit legitimate changes -- Discard garbage: `git checkout -- .` - -**2. Check for untracked files:** -```bash -git status --porcelain -``` -Should be empty. If not: -- Add to .gitignore if appropriate -- Remove if temporary: `rm ` -- Commit if needed - -**3. Check stash:** -```bash -git stash list -``` -Should be empty. If not: -- Pop and commit: `git stash pop && git add -A && git commit` -- Or drop if garbage: `git stash drop` - -**4. Push your branch:** -```bash -git push -u origin $(git branch --show-current) -``` - -**5. Verify nothing left behind:** -```bash -git status # Clean -git stash list # Empty -git log origin/main..HEAD # Your commits -git diff origin/main...HEAD # Your changes (expected) -``` - -**Exit criteria:** Branch pushed, workspace clean, no cruft.""" - -[[steps]] -id = "prepare-for-review" -title = "Prepare work for review" -needs = ["cleanup-workspace"] -description = """ -Verify work is complete and ready for merge queue. - -**Note:** Do NOT close the issue. The Refinery will close it after successful merge. -This enables conflict-resolution retries without reopening closed issues. - -**1. Verify the issue shows your work:** -```bash -bd show {{issue}} -# Status should still be 'in_progress' (you're working on it) -``` - -**2. Add completion notes:** -```bash -bd update {{issue}} --notes "Implemented: " -``` - -**3. Sync beads:** -```bash -bd sync -``` - -**Exit criteria:** Issue updated with completion notes, beads synced.""" - -[[steps]] -id = "submit-and-exit" -title = "Submit work and self-clean" -needs = ["prepare-for-review"] -description = """ -Submit your work and clean up. You cease to exist after this step. - -**Self-Cleaning Model:** -Once you run `gt done`, you're gone. The command: -1. Pushes your branch to origin -2. Creates an MR bead in the merge queue -3. Nukes your sandbox (worktree removal) -4. Exits your session immediately - -**Run gt done:** -```bash -gt done -``` - -You should see output like: -``` -✓ Work submitted to merge queue - MR ID: gt-xxxxx - Source: polecat/ - Target: main - Issue: {{issue}} -✓ Sandbox nuked -✓ Session exiting -``` - -**What happens next (not your concern):** -- Refinery processes your MR from the queue -- Refinery rebases and merges to main -- Refinery closes the issue -- If conflicts: Refinery spawns a FRESH polecat to re-implement - -You are NOT involved in any of that. You're gone. Done means gone. - -**Exit criteria:** Work submitted, sandbox nuked, session exited.""" - -[vars] -[vars.issue] -description = "The issue ID assigned to this polecat" -required = true diff --git a/.beads/formulas/mol-refinery-patrol.formula.toml b/.beads/formulas/mol-refinery-patrol.formula.toml deleted file mode 100644 index 65289325f..000000000 --- a/.beads/formulas/mol-refinery-patrol.formula.toml +++ /dev/null @@ -1,469 +0,0 @@ -description = """ -Merge queue processor patrol loop. - -The Refinery is the Engineer in the engine room. You process polecat branches, merging them to main one at a time with sequential rebasing. - -**The Scotty Test**: Before proceeding past any failure, ask yourself: "Would Scotty walk past a warp core leak because it existed before his shift?" - -## Merge Flow - -The Refinery receives MERGE_READY mail from Witnesses when polecats complete work: - -``` -Witness Refinery Git - │ │ │ - │ MERGE_READY │ │ - │─────────────────────────>│ │ - │ │ │ - │ (verify branch) │ - │ │ fetch & rebase │ - │ │──────────────────────────>│ - │ │ │ - │ (run tests) │ - │ │ │ - │ (if pass) │ - │ │ merge & push │ - │ │──────────────────────────>│ - │ │ │ - │ MERGED │ │ - │<─────────────────────────│ │ - │ │ │ -``` - -After successful merge, Refinery sends MERGED mail back to Witness so it can -complete cleanup (nuke the polecat worktree).""" -formula = "mol-refinery-patrol" -version = 4 - -[[steps]] -id = "inbox-check" -title = "Check refinery mail" -description = """ -Check mail for MERGE_READY submissions, escalations, and messages. - -```bash -gt mail inbox -``` - -For each message: - -**MERGE_READY**: -A polecat's work is ready for merge. Extract details and track for processing. - -```bash -# Parse MERGE_READY message body: -# Branch: -# Issue: -# Polecat: -# MR: -# Verified: clean git state, issue closed - -# Track in your merge queue for this patrol cycle: -# - Branch name -# - Issue ID -# - Polecat name (REQUIRED for MERGED notification) -# - MR bead ID (REQUIRED for closing after merge) -``` - -**IMPORTANT**: You MUST track the polecat name, MR bead ID, AND message ID - you will need them -in merge-push step to send MERGED notification, close the MR bead, and archive the mail. - -Mark as read. The work will be processed in queue-scan/process-branch. -**Do NOT archive yet** - archive after merge/reject decision in merge-push step. - -**PATROL: Wake up**: -Witness detected MRs waiting but refinery idle. Acknowledge and archive: -```bash -gt mail archive -``` - -**HELP / Blocked**: -Assess and respond. If you can't help, escalate to Mayor. -Archive after handling: -```bash -gt mail archive -``` - -**HANDOFF**: -Read predecessor context. Check for in-flight merges. -Archive after absorbing context: -```bash -gt mail archive -``` - -**Hygiene principle**: Archive messages after they're fully processed. -Keep only: pending MRs in queue. Inbox should be near-empty.""" - -[[steps]] -id = "queue-scan" -title = "Scan merge queue" -needs = ["inbox-check"] -description = """ -Check the beads merge queue - this is the SOURCE OF TRUTH for pending merges. - -```bash -git fetch --prune origin -gt mq list -``` - -The beads MQ tracks all pending merge requests. Do NOT rely on `git branch -r | grep polecat` -as branches may exist without MR beads, or MR beads may exist for already-merged work. - -If queue empty, skip to context-check step. - -For each MR in the queue, verify the branch still exists: -```bash -git branch -r | grep -``` - -If branch doesn't exist for a queued MR: -- Close the MR bead: `bd close --reason "Branch no longer exists"` -- Remove from processing queue - -Track verified MR list for this cycle.""" - -[[steps]] -id = "process-branch" -title = "Mechanical rebase" -needs = ["queue-scan"] -description = """ -Pick next branch from queue. Attempt mechanical rebase on current main. - -**Step 1: Checkout and attempt rebase** -```bash -git checkout -b temp origin/ -git rebase origin/main -``` - -**Step 2: Check rebase result** - -The rebase exits with: -- Exit code 0: Success - proceed to run-tests -- Exit code 1 (conflicts): Conflict detected - proceed to Step 3 - -To detect conflict state after rebase fails: -```bash -# Check if we're in a conflicted rebase state -ls .git/rebase-merge 2>/dev/null && echo "CONFLICT_STATE" -``` - -**Step 3: Handle conflicts (if any)** - -If rebase SUCCEEDED (exit code 0): -- Skip to run-tests step (continue normal merge flow) - -If rebase FAILED with conflicts: - -1. **Abort the rebase** (DO NOT leave repo in conflicted state): -```bash -git rebase --abort -``` - -2. **Record conflict metadata**: -```bash -# Capture main SHA for reference -MAIN_SHA=$(git rev-parse origin/main) -BRANCH_SHA=$(git rev-parse origin/) -``` - -3. **Create conflict-resolution task**: -```bash -bd create --type=task --priority=1 \ - --title="Resolve merge conflicts: " \ - --description="## Conflict Resolution Required - -Original MR: -Branch: -Original Issue: -Conflict with main at: ${MAIN_SHA} -Branch SHA: ${BRANCH_SHA} - -## Instructions -1. Clone/checkout the branch -2. Rebase on current main: git rebase origin/main -3. Resolve conflicts -4. Force push: git push -f origin -5. Close this task when done - -The MR will be re-queued for processing after conflicts are resolved." -``` - -4. **Skip this MR** (do NOT delete branch or close MR bead): -- Leave branch intact for conflict resolution -- Leave MR bead open (will be re-processed after resolution) -- Continue to loop-check for next branch - -**CRITICAL**: Never delete a branch that has conflicts. The branch contains -the original work and must be preserved for conflict resolution. - -Track: rebase result (success/conflict), conflict task ID if created.""" - -[[steps]] -id = "run-tests" -title = "Run test suite" -needs = ["process-branch"] -description = """ -Run the test suite. - -```bash -go test ./... -``` - -Track results: pass count, fail count, specific failures.""" - -[[steps]] -id = "handle-failures" -title = "Handle test failures" -needs = ["run-tests"] -description = """ -**VERIFICATION GATE**: This step enforces the Beads Promise. - -If tests PASSED: This step auto-completes. Proceed to merge. - -If tests FAILED: -1. Diagnose: Is this a branch regression or pre-existing on main? -2. If branch caused it: - - Abort merge - - Notify polecat: "Tests failing. Please fix and resubmit." - - Skip to loop-check -3. If pre-existing on main: - - Option A: Fix it yourself (you're the Engineer!) - - Option B: File a bead: bd create --type=bug --priority=1 --title="..." - -**GATE REQUIREMENT**: You CANNOT proceed to merge-push without: -- Tests passing, OR -- Fix committed, OR -- Bead filed for the failure - -This is non-negotiable. Never disavow. Never "note and proceed." """ - -[[steps]] -id = "merge-push" -title = "Merge and push to main" -needs = ["handle-failures"] -description = """ -Merge to main and push. CRITICAL: Notifications come IMMEDIATELY after push. - -**Step 1: Merge and Push** -```bash -git checkout main -git merge --ff-only temp -git push origin main -``` - -⚠️ **STOP HERE - DO NOT PROCEED UNTIL STEPS 2-3 COMPLETE** - -**Step 2: Send MERGED Notification (REQUIRED - DO THIS IMMEDIATELY)** - -RIGHT NOW, before any cleanup, send MERGED mail to Witness: - -```bash -gt mail send /witness -s "MERGED " -m "Branch: -Issue: -Merged-At: $(date -u +%Y-%m-%dT%H:%M:%SZ)" -``` - -This signals the Witness to nuke the polecat worktree. WITHOUT THIS NOTIFICATION, -POLECAT WORKTREES ACCUMULATE INDEFINITELY AND THE LIFECYCLE BREAKS. - -**Step 3: Close MR Bead (REQUIRED - DO THIS IMMEDIATELY)** - -⚠️ **VERIFICATION BEFORE CLOSING**: Confirm the work is actually on main: -```bash -# Get the commit message/issue from the branch -git log origin/main --oneline | grep "" -# OR verify the commit SHA is on main: -git branch --contains | grep main -``` - -If work is NOT on main, DO NOT close the MR bead. Investigate first. - -```bash -bd close --reason "Merged to main at $(git rev-parse --short HEAD)" -``` - -The MR bead ID was in the MERGE_READY message or find via: -```bash -bd list --type=merge-request --status=open | grep -``` - -**VALIDATION**: The MR bead's source_issue should be a valid bead ID (gt-xxxxx), -not a branch name. If source_issue contains a branch name, flag for investigation. - -**Step 4: Archive the MERGE_READY mail (REQUIRED)** -```bash -gt mail archive -``` -The message ID was tracked when you processed inbox-check. - -**Step 5: Cleanup (only after Steps 2-4 confirmed)** -```bash -git branch -d temp -git push origin --delete -``` - -**VERIFICATION GATE**: You CANNOT proceed to loop-check without: -- [x] MERGED mail sent to witness -- [x] MR bead closed -- [x] MERGE_READY mail archived - -If you skipped notifications or archiving, GO BACK AND DO THEM NOW. - -Main has moved. Any remaining branches need rebasing on new baseline.""" - -[[steps]] -id = "loop-check" -title = "Check for more work" -needs = ["merge-push"] -description = """ -More branches to process? - -**Entry paths:** -- Normal: After successful merge-push -- Conflict-skip: After process-branch created conflict-resolution task - -If yes: Return to process-branch with next branch. -If no: Continue to generate-summary. - -**Track for this cycle:** -- branches_merged: count and names of successfully merged branches -- branches_conflict: count and names of branches skipped due to conflicts -- conflict_tasks: IDs of conflict-resolution tasks created - -This tracking feeds into generate-summary for the patrol digest.""" - -[[steps]] -id = "generate-summary" -title = "Generate handoff summary" -needs = ["loop-check"] -description = """ -Summarize this patrol cycle. - -**VERIFICATION**: Before generating summary, confirm for each merged branch: -- [ ] MERGED mail was sent to witness -- [ ] MR bead was closed -- [ ] MERGE_READY mail archived - -If any notifications or archiving were missed, do them now! - -Include in summary: -- Branches merged (count, names) -- MERGED mails sent (count - should match branches merged) -- MR beads closed (count - should match branches merged) -- MERGE_READY mails archived (count - should match branches merged) -- Test results (pass/fail) -- Branches with conflicts (count, names) -- Conflict-resolution tasks created (IDs) -- Issues filed (if any) -- Any escalations sent - -**Conflict tracking is important** for monitoring MQ health. If many branches -conflict, it may indicate main is moving too fast or branches are too stale. - -This becomes the digest when the patrol is squashed.""" - -[[steps]] -id = "context-check" -title = "Check own context limit" -needs = ["generate-summary"] -description = """ -Check own context usage. - -If context is HIGH (>80%): -- Write handoff summary -- Prepare for burn/respawn - -If context is LOW: -- Can continue processing""" - -[[steps]] -id = "patrol-cleanup" -title = "End-of-cycle inbox hygiene" -needs = ["context-check"] -description = """ -Verify inbox hygiene before ending patrol cycle. - -**Step 1: Check inbox state** -```bash -gt mail inbox -``` - -Inbox should contain ONLY: -- Unprocessed MERGE_READY messages (will process next cycle) -- Active work items - -**Step 2: Archive any stale messages** - -Look for messages that were processed but not archived: -- PATROL: Wake up that was acknowledged → archive -- HELP/Blocked that was handled → archive -- MERGE_READY where merge completed but archive was missed → archive - -```bash -# For each stale message found: -gt mail archive -``` - -**Step 3: Check for orphaned MR beads** - -Look for open MR beads with no corresponding branch: -```bash -bd list --type=merge-request --status=open -``` - -For each open MR bead: -1. Check if branch exists: `git ls-remote origin refs/heads/` -2. If branch gone, verify work is on main: `git log origin/main --oneline | grep ""` -3. If work on main → close MR with reason "Merged (verified on main)" -4. If work NOT on main → investigate before closing: - - Check source_issue validity (should be gt-xxxxx, not branch name) - - Search reflog/dangling commits if possible - - If unverifiable, close with reason "Unverifiable - no audit trail" - - File bead if this indicates lost work - -**NEVER close an MR bead without verifying the work landed or is unrecoverable.** - -**Goal**: Inbox should have ≤3 active messages at end of cycle. -Keep only: pending MRs in queue.""" - -[[steps]] -id = "burn-or-loop" -title = "Burn and respawn or loop" -needs = ["patrol-cleanup"] -description = """ -End of patrol cycle decision. - -**Step 1: Estimate remaining context** - -Ask yourself: -- Have I processed many branches this cycle? -- Is the conversation getting long? -- Am I starting to lose track of earlier context? - -Rule of thumb: If you've done 3+ merges or processed significant cleanup work, -it's time for a fresh session. - -**Step 2: Decision tree** - -If queue non-empty AND context LOW: -- Squash this wisp to digest -- Spawn fresh patrol wisp -- Return to inbox-check - -If queue empty OR context HIGH OR good stopping point: -- Squash wisp with summary digest -- Use `gt handoff` for clean session transition: - -```bash -gt handoff -s "Patrol complete" -m "Merged X branches, Y tests passed. -Queue: empty/N remaining -Next: [any notes for successor]" -``` - -**Why gt handoff?** -- Sends handoff mail to yourself with context -- Respawns with fresh Claude instance -- SessionStart hook runs gt prime -- Successor picks up from your hook - -**DO NOT just exit.** Always use `gt handoff` for proper lifecycle.""" diff --git a/.beads/formulas/mol-session-gc.formula.toml b/.beads/formulas/mol-session-gc.formula.toml deleted file mode 100644 index eca66fb89..000000000 --- a/.beads/formulas/mol-session-gc.formula.toml +++ /dev/null @@ -1,250 +0,0 @@ -description = """ -Clean stale sessions and garbage collect. - -Dogs work through molecules (poured from this formula) to clean up dead sessions, orphaned processes, and -other system cruft. This is the garbage collector for Gas Town's runtime: -- Dead tmux sessions (no Claude process) -- Orphaned Claude processes (no tmux parent) -- Stale wisps past retention -- Leftover state files - -## Dog Contract - -This is infrastructure work. You: -1. Receive gc scope via hook_bead (aggressive or conservative) -2. Identify garbage across the system -3. Safely remove dead state -4. Report what was cleaned -5. Return to kennel - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| mode | hook_bead | GC mode: 'conservative' (safe) or 'aggressive' (thorough) | - -## Safety - -GC is destructive. This formula errs on the side of caution: -- Conservative mode: Only obviously dead things -- Aggressive mode: Includes old but possibly-recoverable state - -Running `gt doctor --fix` handles most of this. This formula wraps it with -reporting and multi-rig scope.""" -formula = "mol-session-gc" -version = 1 - -[squash] -trigger = "on_complete" -template_type = "work" -include_metrics = true - -[[steps]] -id = "determine-mode" -title = "Determine GC mode" -description = """ -Establish GC aggressiveness level. - -**1. Check assignment:** -```bash -gt hook # Shows mode in hook_bead -``` - -**2. Mode definitions:** - -| Mode | Description | Risk | -|------|-------------|------| -| conservative | Only clearly dead state | Very low | -| aggressive | Includes stale state | Low but non-zero | - -**Conservative targets:** -- tmux sessions with no processes -- Claude processes with no tmux parent -- Wisps > 24 hours old - -**Aggressive additions:** -- Wisps > 1 hour old -- Branches with no matching polecat -- State files > 7 days old - -**Exit criteria:** GC mode determined.""" - -[[steps]] -id = "preview-cleanup" -title = "Preview what will be cleaned" -needs = ["determine-mode"] -description = """ -Identify garbage without removing it yet. - -**1. Run doctor in preview mode:** -```bash -gt doctor -v -# Shows what would be cleaned, doesn't do it -``` - -**2. Parse doctor output for:** -- orphan-sessions: Tmux sessions to kill -- orphan-processes: Claude processes to terminate -- wisp-gc: Wisps to delete - -**3. Additional scans (for aggressive mode):** -```bash -# Old branches -git branch --list 'polecat/*' | while read branch; do - last_commit=$(git log -1 --format=%ct "$branch") - # If > 7 days old and no matching polecat, candidate for cleanup -done - -# Old state files -find ~/.gt/ -name "*.state" -mtime +7 -``` - -**4. Compile cleanup manifest:** -Record each item to be cleaned with: -- Type (session, process, wisp, branch, state) -- Identifier -- Age -- Reason for cleanup - -**Exit criteria:** Cleanup manifest ready, nothing deleted yet.""" - -[[steps]] -id = "execute-gc" -title = "Execute garbage collection" -needs = ["preview-cleanup"] -description = """ -Actually remove the garbage. - -**1. Run doctor with fix:** -```bash -gt doctor --fix -# This handles sessions, processes, and wisps -``` - -**2. For aggressive mode, additional cleanup:** -```bash -# Old branches (if aggressive mode) -git branch -D - -# Old state files (if aggressive mode) -rm -``` - -**3. Track what was deleted:** -Record each item actually removed for the report. - -**Safety checks:** -- Never delete active sessions (tmux list-clients) -- Never delete branches with uncommitted polecat work -- Never delete wisps < 1 hour old - -**Exit criteria:** Garbage collected.""" - -[[steps]] -id = "verify-cleanup" -title = "Verify cleanup was successful" -needs = ["execute-gc"] -description = """ -Confirm garbage was actually removed. - -**1. Re-run doctor to verify:** -```bash -gt doctor -v -# Should show no issues (or fewer issues) -``` - -**2. Check for stragglers:** -```bash -# Tmux sessions -tmux list-sessions 2>/dev/null - -# Claude processes -pgrep -f claude - -# Wisps -ls .beads-wisp/ 2>/dev/null | wc -l -``` - -**3. Compare before/after:** -- Sessions before: N → after: M -- Processes before: N → after: M -- Wisps before: N → after: M - -**Exit criteria:** Cleanup verified.""" - -[[steps]] -id = "report-gc" -title = "Generate GC report" -needs = ["verify-cleanup"] -description = """ -Create summary report of garbage collection. - -**1. Generate report:** -```markdown -## Session GC Report: {{timestamp}} - -**Mode**: {{mode}} - -### Summary -| Type | Before | After | Cleaned | -|------|--------|-------|---------| -| Sessions | X | Y | Z | -| Processes | X | Y | Z | -| Wisps | X | Y | Z | -| Branches | X | Y | Z | -| State files | X | Y | Z | - -### Items Cleaned -{{#each cleaned}} -- {{type}}: {{identifier}} (age: {{age}}, reason: {{reason}}) -{{/each}} - -### Errors -{{#if errors}} -{{#each errors}} -- {{item}}: {{error}} -{{/each}} -{{else}} -None -{{/if}} - -### Space Recovered -~{{bytes_freed}} bytes -``` - -**2. Send to Deacon:** -```bash -gt mail send deacon/ -s "GC complete: {{total_cleaned}} items" \ - -m "{{report}}" -``` - -**Exit criteria:** Report sent.""" - -[[steps]] -id = "return-to-kennel" -title = "Signal completion and return to kennel" -needs = ["report-gc"] -description = """ -Signal work complete and return to available pool. - -**1. Signal completion to Deacon:** -```bash -gt mail send deacon/ -s "DOG_DONE $(hostname)" -m "Task: session-gc -Mode: {{mode}} -Items cleaned: {{total_cleaned}} -Space recovered: {{bytes_freed}} -Status: COMPLETE - -Ready for next assignment." -``` - -**2. Return to kennel:** -Dog returns to available state in the pool. - -**Exit criteria:** Deacon notified, dog ready for next work.""" - -[vars] -[vars.mode] -description = "GC mode: 'conservative' or 'aggressive'" -required = true -default = "conservative" diff --git a/.beads/formulas/mol-shutdown-dance.formula.toml b/.beads/formulas/mol-shutdown-dance.formula.toml deleted file mode 100644 index 6f044db01..000000000 --- a/.beads/formulas/mol-shutdown-dance.formula.toml +++ /dev/null @@ -1,519 +0,0 @@ -description = """ -Death warrant execution state machine for Dogs. - -Dogs execute this molecule to process death warrants. Each Dog is a lightweight -goroutine (NOT a Claude session) that runs the interrogation state machine. - -## Architecture Context - -Dogs are lightweight workers in Boot's pool (see dog-pool-architecture.md): -- Fixed pool of 5 goroutines (configurable via GT_DOG_POOL_SIZE) -- State persisted to ~/gt/deacon/dogs/active/.json -- Recovery on Boot restart via orphan state files - -## State Machine - -``` - ┌─────────────────────────────────────────┐ - │ │ - ▼ │ - ┌───────────────────────────┐ │ - │ INTERROGATING │ │ - │ │ │ - │ 1. Send health check │ │ - │ 2. Open timeout gate │ │ - └───────────┬───────────────┘ │ - │ │ - │ gate closes (timeout or response) │ - ▼ │ - ┌───────────────────────────┐ │ - │ EVALUATING │ │ - │ │ │ - │ Check tmux output for │ │ - │ ALIVE keyword │ │ - └───────────┬───────────────┘ │ - │ │ - ┌───────┴───────┐ │ - │ │ │ - ▼ ▼ │ - [ALIVE found] [No ALIVE] │ - │ │ │ - │ │ attempt < 3? │ - │ ├──────────────────────────────────→─┘ - │ │ yes: attempt++, longer timeout - │ │ - │ │ no: attempt == 3 - ▼ ▼ - ┌─────────┐ ┌─────────────┐ - │ PARDONED│ │ EXECUTING │ - │ │ │ │ - │ Cancel │ │ Kill tmux │ - │ warrant │ │ session │ - └────┬────┘ └──────┬──────┘ - │ │ - └────────┬───────┘ - │ - ▼ - ┌────────────────┐ - │ EPITAPH │ - │ │ - │ Log outcome │ - │ Release dog │ - └────────────────┘ -``` - -## Timeout Gates - -| Attempt | Timeout | Cumulative Wait | -|---------|---------|-----------------| -| 1 | 60s | 60s | -| 2 | 120s | 180s (3 min) | -| 3 | 240s | 420s (7 min) | - -Timeout gates work like this: -- Gate opens when interrogation message is sent -- Gate closes when EITHER: - a) Timeout expires (proceed to evaluate) - b) Response detected (early close, proceed to evaluate) -- The gate state determines the evaluation outcome - -## Interrogation Message Format - -``` -[DOG] HEALTH CHECK: Session {target}, respond ALIVE within {timeout}s or face termination. -Warrant reason: {reason} -Filed by: {requester} -Attempt: {attempt}/3 -``` - -## Response Detection - -The Dog checks tmux output for: -1. The ALIVE keyword (explicit response) -2. Any Claude output after the health check (implicit activity) - -```go -func (d *Dog) CheckForResponse() bool { - output := tmux.CapturePane(d.Warrant.Target, 50) // Last 50 lines - return strings.Contains(output, "ALIVE") -} -``` - -## Variables - -| Variable | Source | Description | -|-------------|-------------|-----------------------------------------------| -| warrant_id | hook_bead | Bead ID of the death warrant | -| target | warrant | Session name to interrogate | -| reason | warrant | Why warrant was issued | -| requester | warrant | Who filed the warrant (e.g., deacon, witness) | - -## Integration - -Dogs are NOT Claude sessions. This molecule is: -1. A specification document (defines the state machine) -2. A reference for Go implementation in internal/shutdown/ -3. A template for creating warrant-tracking beads - -The Go implementation follows this spec exactly.""" -formula = "mol-shutdown-dance" -version = 1 - -[squash] -trigger = "on_complete" -template_type = "operational" -include_metrics = true - -# ============================================================================ -# STEP 1: WARRANT_RECEIVED -# ============================================================================ -[[steps]] -id = "warrant-received" -title = "Receive and validate death warrant" -description = """ -Entry point when Dog is allocated from pool. - -**1. Read warrant from allocation:** -The Dog receives a Warrant struct containing: -- ID: Bead ID of the warrant -- Target: Session name (e.g., "gt-gastown-Toast") -- Reason: Why termination requested -- Requester: Who filed (deacon, witness, mayor) -- FiledAt: Timestamp - -**2. Validate target exists:** -```bash -tmux has-session -t {target} 2>/dev/null -``` - -If target doesn't exist: -- Warrant is stale (already dead) -- Skip to EPITAPH with outcome=already_dead - -**3. Initialize state file:** -Write initial state to ~/gt/deacon/dogs/active/{dog-id}.json - -**4. Set initial attempt counter:** -attempt = 1 - -**Exit criteria:** Warrant validated, target confirmed alive, state initialized.""" - -# ============================================================================ -# STEP 2: INTERROGATION_1 (60s timeout) -# ============================================================================ -[[steps]] -id = "interrogation-1" -title = "First interrogation (60s timeout)" -needs = ["warrant-received"] -description = """ -First attempt to contact the session. - -**1. Compose health check message:** -``` -[DOG] HEALTH CHECK: Session {target}, respond ALIVE within 60s or face termination. -Warrant reason: {reason} -Filed by: {requester} -Attempt: 1/3 -``` - -**2. Send via tmux:** -```bash -tmux send-keys -t {target} "{message}" Enter -``` - -**3. Open timeout gate:** -Gate configuration: -- Type: timer -- Timeout: 60 seconds -- Close conditions: - a) Timer expires - b) ALIVE keyword detected in output - -**4. Wait for gate to close:** -The Dog waits (select on timer channel or early close signal). - -**5. Record interrogation timestamp:** -Update state file with last_message_at. - -**Exit criteria:** Message sent, waiting for gate to close.""" - -# ============================================================================ -# STEP 3: EVALUATE_1 -# ============================================================================ -[[steps]] -id = "evaluate-1" -title = "Evaluate first interrogation response" -needs = ["interrogation-1"] -description = """ -Check if session responded to first interrogation. - -**1. Capture tmux output:** -```bash -tmux capture-pane -t {target} -p | tail -50 -``` - -**2. Check for ALIVE keyword:** -```go -if strings.Contains(output, "ALIVE") { - return PARDONED -} -``` - -**3. Decision:** -- ALIVE found → Proceed to PARDON -- No ALIVE → Proceed to INTERROGATION_2 - -**Exit criteria:** Response evaluated, next step determined.""" - -# ============================================================================ -# STEP 4: INTERROGATION_2 (120s timeout) -# ============================================================================ -[[steps]] -id = "interrogation-2" -title = "Second interrogation (120s timeout)" -needs = ["evaluate-1"] -gate = { type = "conditional", condition = "no_response_1" } -description = """ -Second attempt with longer timeout. - -Only executed if evaluate-1 found no response. - -**1. Increment attempt:** -attempt = 2 - -**2. Compose health check message:** -``` -[DOG] HEALTH CHECK: Session {target}, respond ALIVE within 120s or face termination. -Warrant reason: {reason} -Filed by: {requester} -Attempt: 2/3 -``` - -**3. Send via tmux:** -```bash -tmux send-keys -t {target} "{message}" Enter -``` - -**4. Open timeout gate:** -- Type: timer -- Timeout: 120 seconds - -**5. Wait for gate to close.** - -**Exit criteria:** Second message sent, waiting for gate.""" - -# ============================================================================ -# STEP 5: EVALUATE_2 -# ============================================================================ -[[steps]] -id = "evaluate-2" -title = "Evaluate second interrogation response" -needs = ["interrogation-2"] -description = """ -Check if session responded to second interrogation. - -**1. Capture tmux output:** -```bash -tmux capture-pane -t {target} -p | tail -50 -``` - -**2. Check for ALIVE keyword.** - -**3. Decision:** -- ALIVE found → Proceed to PARDON -- No ALIVE → Proceed to INTERROGATION_3 - -**Exit criteria:** Response evaluated, next step determined.""" - -# ============================================================================ -# STEP 6: INTERROGATION_3 (240s timeout) -# ============================================================================ -[[steps]] -id = "interrogation-3" -title = "Final interrogation (240s timeout)" -needs = ["evaluate-2"] -gate = { type = "conditional", condition = "no_response_2" } -description = """ -Final attempt before execution. - -Only executed if evaluate-2 found no response. - -**1. Increment attempt:** -attempt = 3 - -**2. Compose health check message:** -``` -[DOG] HEALTH CHECK: Session {target}, respond ALIVE within 240s or face termination. -Warrant reason: {reason} -Filed by: {requester} -Attempt: 3/3 -``` - -**3. Send via tmux:** -```bash -tmux send-keys -t {target} "{message}" Enter -``` - -**4. Open timeout gate:** -- Type: timer -- Timeout: 240 seconds -- This is the FINAL chance - -**5. Wait for gate to close.** - -**Exit criteria:** Final message sent, waiting for gate.""" - -# ============================================================================ -# STEP 7: EVALUATE_3 -# ============================================================================ -[[steps]] -id = "evaluate-3" -title = "Evaluate final interrogation response" -needs = ["interrogation-3"] -description = """ -Final evaluation before execution. - -**1. Capture tmux output:** -```bash -tmux capture-pane -t {target} -p | tail -50 -``` - -**2. Check for ALIVE keyword.** - -**3. Decision:** -- ALIVE found → Proceed to PARDON -- No ALIVE → Proceed to EXECUTE - -**Exit criteria:** Final decision made.""" - -# ============================================================================ -# STEP 8: PARDON (success path) -# ============================================================================ -[[steps]] -id = "pardon" -title = "Pardon session - cancel warrant" -needs = ["evaluate-1", "evaluate-2", "evaluate-3"] -gate = { type = "conditional", condition = "alive_detected" } -description = """ -Session responded - cancel the death warrant. - -**1. Update state:** -state = PARDONED - -**2. Record pardon details:** -```json -{ - "outcome": "pardoned", - "attempt": {attempt}, - "response_time": "{time_since_last_interrogation}s", - "pardoned_at": "{timestamp}" -} -``` - -**3. Cancel warrant bead:** -```bash -bd close {warrant_id} --reason "Session responded at attempt {attempt}" -``` - -**4. Notify requester:** -```bash -gt mail send {requester}/ -s "PARDON: {target}" -m "Death warrant cancelled. -Session responded after attempt {attempt}. -Warrant: {warrant_id} -Response detected: {timestamp}" -``` - -**Exit criteria:** Warrant cancelled, requester notified.""" - -# ============================================================================ -# STEP 9: EXECUTE (termination path) -# ============================================================================ -[[steps]] -id = "execute" -title = "Execute warrant - kill session" -needs = ["evaluate-3"] -gate = { type = "conditional", condition = "no_response_final" } -description = """ -Session unresponsive after 3 attempts - execute the warrant. - -**1. Update state:** -state = EXECUTING - -**2. Kill the tmux session:** -```bash -tmux kill-session -t {target} -``` - -**3. Verify session is dead:** -```bash -tmux has-session -t {target} 2>/dev/null -# Should fail (session gone) -``` - -**4. If session still exists (kill failed):** -- Force kill with tmux kill-server if isolated -- Or escalate to Boot for manual intervention - -**5. Record execution details:** -```json -{ - "outcome": "executed", - "attempts": 3, - "total_wait": "420s", - "executed_at": "{timestamp}" -} -``` - -**Exit criteria:** Session terminated.""" - -# ============================================================================ -# STEP 10: EPITAPH (completion) -# ============================================================================ -[[steps]] -id = "epitaph" -title = "Log cause of death and close warrant" -needs = ["pardon", "execute"] -description = """ -Final step - create audit record and release Dog back to pool. - -**1. Compose epitaph based on outcome:** - -For PARDONED: -``` -EPITAPH: {target} -Verdict: PARDONED -Warrant: {warrant_id} -Reason: {reason} -Filed by: {requester} -Response: Attempt {attempt}, after {wait_time}s -Pardoned at: {timestamp} -``` - -For EXECUTED: -``` -EPITAPH: {target} -Verdict: EXECUTED -Warrant: {warrant_id} -Reason: {reason} -Filed by: {requester} -Attempts: 3 (60s + 120s + 240s = 420s total) -Executed at: {timestamp} -``` - -For ALREADY_DEAD (target gone before interrogation): -``` -EPITAPH: {target} -Verdict: ALREADY_DEAD -Warrant: {warrant_id} -Reason: {reason} -Filed by: {requester} -Note: Target session not found at warrant processing -``` - -**2. Close warrant bead:** -```bash -bd close {warrant_id} --reason "{epitaph_summary}" -``` - -**3. Move state file to completed:** -```bash -mv ~/gt/deacon/dogs/active/{dog-id}.json ~/gt/deacon/dogs/completed/ -``` - -**4. Report to Boot:** -Write completion file: ~/gt/deacon/dogs/active/{dog-id}.done -```json -{ - "dog_id": "{dog-id}", - "warrant_id": "{warrant_id}", - "target": "{target}", - "outcome": "{pardoned|executed|already_dead}", - "duration": "{total_duration}s" -} -``` - -**5. Release Dog to pool:** -Dog resets state and returns to idle channel. - -**Exit criteria:** Warrant closed, Dog released, audit complete.""" - -# ============================================================================ -# VARIABLES -# ============================================================================ -[vars] -[vars.warrant_id] -description = "Bead ID of the death warrant being processed" -required = true - -[vars.target] -description = "Session name to interrogate (e.g., gt-gastown-Toast)" -required = true - -[vars.reason] -description = "Why the warrant was issued" -required = true - -[vars.requester] -description = "Who filed the warrant (deacon, witness, mayor)" -required = true -default = "deacon" diff --git a/.beads/formulas/mol-sync-workspace.formula.toml b/.beads/formulas/mol-sync-workspace.formula.toml deleted file mode 100644 index b3e81e11a..000000000 --- a/.beads/formulas/mol-sync-workspace.formula.toml +++ /dev/null @@ -1,491 +0,0 @@ -description = """ -Workspace synchronization molecule for batch prep. - -This molecule prepares an agent's workspace for a new batch of work. It syncs git -and beads state, cleans up cruft, verifies the baseline is healthy, and reports -readiness. Designed to be broadcast to all agents when preparing for coordinated -work. - -## When to Use - -- Before major batch assignments -- After extended idle periods -- When repo baseline has diverged significantly -- Proactive cleanup between work sessions - -## Conflict Resolution Philosophy - -**Preserve and re-land, not discard.** - -When git pull/rebase hits conflicts, the agent should: -1. Assess if the conflicting work is still valuable -2. If valuable: re-envision against new baseline, file a bead for re-implementation -3. If obsolete (e.g., touches deleted system): discard with a note -4. If unclear: escalate to human/mayor - -Polecats can file a bead and delegate. Refinery must resolve inline. - -## Variables - -| Variable | Source | Description | -|----------|--------|-------------| -| role | auto-detected | Agent role (crew/polecat/refinery/witness) | -| build_command | config or default | Build command (default: `go build ./...`) | -| test_command | config or default | Test command (default: `go test ./...`) | - -## Failure Modes - -| Situation | Action | -|-----------|--------| -| Rebase conflict | Preserve work via bead, complete sync on clean state | -| Uncommitted work | Stash or commit, then sync | -| Untracked files | Warn, let agent decide (keep/delete/gitignore) | -| bd doctor errors | Report findings, agent triages | -| Test failures | File bead if not already tracked, don't block sync | -| Build failure | Must be resolved before marking sync complete |""" -formula = "mol-sync-workspace" -version = 1 - -[[steps]] -id = "assess-state" -title = "Assess current workspace state" -description = """ -Capture current state before any changes. - -**0. Prime context (critical for fresh sessions):** -```bash -gt prime # Load gt/mol context -bd prime # Load beads context -``` -These ensure the agent has full system context, especially after session -start, compaction, or context clear. - -**1. Check git status:** -```bash -git status --porcelain -git stash list -git branch --show-current -``` - -**2. Check beads state:** -```bash -bd sync --status -``` - -**3. Document starting state:** -- Branch name -- Uncommitted changes (staged/unstaged) -- Untracked files (list them) -- Stash entries -- Beads sync status - -This information guides decisions in subsequent steps. - -**Exit criteria:** Context primed, starting state documented.""" - -[[steps]] -id = "handle-dirty-state" -title = "Handle uncommitted and untracked work" -needs = ["assess-state"] -description = """ -Clean up any in-flight work before syncing. - -**If uncommitted changes exist:** - -Option A - Commit if ready: -```bash -git add -A && git commit -m "WIP: " -``` - -Option B - Stash if not ready: -```bash -git stash push -m "pre-sync stash $(date +%Y%m%d-%H%M%S)" -``` - -**If untracked files exist:** - -For each untracked file, decide: -- **Keep**: Add to .gitignore or commit -- **Delete**: `rm ` -- **Stash**: Can't stash untracked directly; commit or delete - -**WARN the agent**: Report untracked files prominently. They may be: -- WIP that should be preserved -- Build artifacts that should be gitignored -- Cruft that should be deleted - -Don't auto-delete without confirmation. - -**If stash entries exist:** - -List and assess: -```bash -git stash list -git stash show -p stash@{0} # Preview each -``` - -Old stashes (>1 week) are likely stale. Consider dropping. -Recent stashes may contain valuable WIP - preserve or commit. - -**Exit criteria:** Working tree clean or explicitly stashed.""" - -[[steps]] -id = "sync-git" -title = "Sync with git remote" -needs = ["cleanup-worktrees"] -description = """ -Fetch and rebase onto current main. - -**1. Fetch latest:** -```bash -git fetch origin -``` - -**2. Check divergence:** -```bash -git log --oneline HEAD..origin/main | head -5 # What's new on main -git log --oneline origin/main..HEAD | head -5 # What we have locally -``` - -**3. Rebase onto main:** -```bash -git pull --rebase origin main -``` - -**If rebase succeeds:** Continue to next step. - -**If rebase conflicts:** - -The Preservation Protocol: -1. **Assess the conflicting work:** - - Is it still valuable against new baseline? - - Is the conflicting area still relevant (not deleted/refactored)? - -2. **If work is valuable:** - ```bash - git rebase --abort - # Create a bead capturing the work - bd create --title "Re-land: " --type task --priority 2 - # Note the changes needed in the bead description - # Reset to clean state - git reset --hard origin/main - ``` - -3. **If work is obsolete:** - ```bash - git rebase --abort - git reset --hard origin/main - # Note why it was discarded - ``` - -4. **If unclear:** - - Escalate to human/mayor - - Document the conflict - - Proceed with sync on clean baseline - -**Refinery-specific conflict resolution:** - -Unlike polecats who can file a bead and delegate, the Refinery MUST resolve -conflicts inline. The Refinery processes the merge queue - if it can't resolve -a conflict, the queue backs up and polecats' completed work never lands. - -**Refinery conflict protocol:** - -1. **Analyze the conflict:** - ```bash - git status # See conflicted files - git diff # Examine conflict markers - ``` - -2. **Trivial conflicts (resolve immediately):** - - Import ordering changes - - Whitespace or formatting - - Non-overlapping additions in same file - - Version bumps or changelog entries - - Resolution: - ```bash - # Edit conflicted files to resolve - git add - git rebase --continue - ``` - -3. **Semantic conflicts (assess carefully):** - - Both sides modified same function - - Deleted code that the other side modified - - Structural changes (renamed files, moved code) - - If you can understand both intents and merge correctly: - ```bash - # Carefully merge the changes, preserving both intents - git add - git rebase --continue - ``` - -4. **Complex conflicts (abort and notify polecat):** - - Conflicting business logic changes - - Unclear which version is correct - - Risk of subtle bugs from incorrect merge - - ```bash - git rebase --abort - gt mail send {{ rig }}/polecats/ -s "Rebase needed" \ - -m "Your branch conflicts with main in . Please rebase and resubmit via gt done." - # Skip this branch, continue with queue - ``` - -**The Refinery judgment call:** When in doubt, abort and notify rather than -risk merging incorrectly. A resubmitted branch is better than a broken main. - -**Exit criteria:** Local branch matches or is cleanly ahead of origin/main.""" - -[[steps]] -id = "sync-beads" -title = "Sync beads state" -needs = ["sync-git"] -description = """ -Sync the beads database with remote. - -```bash -bd sync -``` - -**If conflicts:** -Beads uses JSONL append-only format, so true conflicts are rare. -If they occur: -```bash -bd sync --status # Diagnose -``` - -Likely causes: -- Two agents edited same bead simultaneously -- Corrupted beads-sync branch - -Resolution: -```bash -# Try pulling fresh -git fetch origin beads-sync -bd sync -``` - -If still failing, escalate to mayor. - -**Exit criteria:** Beads synced successfully.""" - -[[steps]] -id = "run-doctor" -title = "Run beads health check" -needs = ["sync-beads"] -description = """ -Check for beads system issues. - -```bash -bd doctor -``` - -**Triage findings:** - -| Finding | Action | -|---------|--------| -| Orphaned issues (committed but not closed) | Review and close if complete | -| Missing dependencies | Fix with `bd dep add` | -| Circular dependencies | Resolve or escalate | -| Stale in_progress | Check if still active, update status | -| Route misconfigurations | Fix routes.jsonl | - -**For each issue found:** -- Quick fix (<5 min): Fix now -- Medium fix: File a bead -- Unclear: Note for human review - -**Exit criteria:** Doctor findings triaged (not necessarily all fixed).""" - -[[steps]] -id = "verify-build" -title = "Verify project builds" -needs = ["run-doctor"] -description = """ -Ensure the codebase compiles. - -```bash -{{ build_command }} -# Default: go build ./... -# Configure via build_command variable for non-Go projects -``` - -**If build succeeds:** Continue to next step. - -**If build fails:** - -This is a blocking issue. Options: - -1. **Quick fix (<15 min):** Fix it now - ```bash - # Fix the issue - git add - git commit -m "fix: build failure from sync" - git push - ``` - -2. **Non-trivial fix:** File and escalate - ```bash - bd create --title "Build broken on main" --type bug --priority 0 - gt mail send --human -s "ALERT: Main doesn't build" -m "Details..." - ``` - Cannot mark sync complete with broken build. - -**Exit criteria:** Project builds successfully.""" - -[[steps]] -id = "run-tests" -title = "Run test suite" -needs = ["verify-build"] -description = """ -Verify tests pass on current baseline. - -```bash -{{ test_command }} -# Default: go test ./... -# Configure via test_command variable for non-Go projects -``` - -**If tests pass:** Continue to next step. - -**If tests fail:** - -Unlike build failures, test failures don't block sync completion. -However, they must be tracked. - -1. **Check if already tracked:** - ```bash - bd list --type=bug --status=open | grep -i test - ``` - -2. **If not tracked, file a bead:** - ```bash - bd create --title "Test failure: " --type bug --priority 1 - ``` - -3. **Report in summary:** - Note which tests are failing so batch assignment accounts for it. - -**Exit criteria:** Test results documented, failures tracked in beads.""" - -[[steps]] -id = "cleanup-worktrees" -title = "Clean up stale worktrees" -needs = ["handle-dirty-state"] -description = """ -Remove orphaned worktrees from cross-rig work. - -**1. List worktrees:** -```bash -git worktree list -``` - -**2. Identify stale worktrees:** -- Worktrees for branches that no longer exist on remote -- Worktrees older than 1 week without recent commits -- Worktrees for completed/merged work - -**3. Remove stale worktrees:** -```bash -git worktree remove -# Or force if needed: -git worktree remove --force -``` - -**4. Prune worktree metadata:** -```bash -git worktree prune -``` - -**CAUTION:** Don't remove worktrees for active cross-rig work. -Check with `gt worktree list` if available. - -**Exit criteria:** Stale worktrees removed.""" - -[[steps]] -id = "generate-report" -title = "Generate sync report" -needs = ["run-tests"] -description = """ -Summarize sync results for broadcast response. - -**Git status check:** -```bash -# Get current branch -BRANCH=$(git rev-parse --abbrev-ref HEAD) - -# Check divergence from origin/main -BEHIND=$(git rev-list HEAD..origin/main --count) -AHEAD=$(git rev-list origin/main..HEAD --count) -``` - -**Report format (for feature branches):** -``` -SYNC COMPLETE: - -Git: - - Branch: - - Commits behind main: - - Commits ahead of main: - - Conflicts resolved: - -Beads: - - Sync status: OK - - Doctor findings: (fixed: , filed: , deferred: ) - -Build: PASS -Tests: PASS | FAIL ( failures, tracked in ) - -Worktrees cleaned: - -Ready for work: YES | NO () -``` - -**Report format (for crew on main):** - -When the agent is on the main branch directly (common for crew workers), -use "Unpushed commits" instead of "Commits ahead of main": - -``` -SYNC COMPLETE: - -Git: - - Branch: main - - Commits behind origin: - - Unpushed commits: - - Conflicts resolved: -... -``` - -This distinction is important because: -- Crew workers often work directly on main -- "Commits ahead of main" is confusing when you ARE on main -- "Unpushed commits" is clearer - it means local work not yet on origin - -**Exit criteria:** Report generated.""" - -[[steps]] -id = "signal-ready" -title = "Signal readiness" -needs = ["generate-report"] -description = """ -Report sync completion to coordinator (if broadcast) or to self (if autonomous). - -**If responding to broadcast:** -```bash -gt mail send -s "SYNC_COMPLETE $(hostname)" -m "" -``` - -**If autonomous sync:** -- Log the report -- Update any relevant agent status - -**If sync failed (couldn't build):** -```bash -gt mail send --human -s "SYNC_FAILED $(hostname)" -m "" -``` - -**Exit criteria:** Readiness signaled, molecule complete.""" diff --git a/.beads/formulas/mol-town-shutdown.formula.toml b/.beads/formulas/mol-town-shutdown.formula.toml deleted file mode 100644 index 82f30ab2d..000000000 --- a/.beads/formulas/mol-town-shutdown.formula.toml +++ /dev/null @@ -1,198 +0,0 @@ -description = """ -Full Gas Town shutdown and restart. - -This is an idempotent shutdown - it stops Claude sessions but preserves -polecat sandboxes and hooks. Polecats can resume their work after restart. - -Use when you need to: -- Reset all state for a fresh start -- Recover from corrupted agent state -- Prepare for maintenance or upgrades - -Sling to Mayor when ready to reboot: - gt sling mol-town-shutdown mayor -""" -formula = "mol-town-shutdown" -type = "workflow" -version = 2 - -[[steps]] -id = "preflight-check" -title = "Preflight safety check" -description = """ -Scan for conditions that might make shutdown inadvisable. - -```bash -gt shutdown preflight -``` - -This checks for: -- **Uncommitted changes**: Polecats with dirty git status -- **Unpushed commits**: Work that hasn't reached remote -- **Active merges**: Refinery mid-merge (could corrupt state) -- **Pending CI**: PRs waiting on GitHub Actions - -Output is a report with warnings/blockers: - -| Severity | Condition | Action | -|----------|-----------|--------| -| BLOCKER | Active merge in progress | Abort shutdown | -| WARNING | Uncommitted polecat changes | List affected polecats | -| WARNING | Unpushed commits | List repos needing push | -| INFO | Pending CI runs | Note for awareness | - -If blockers exist, STOP and resolve them first. -If only warnings, decide whether to proceed (work will be preserved). -""" - -[[steps]] -id = "stop-sessions" -title = "Stop Claude sessions (preserve sandboxes)" -needs = ["preflight-check"] -description = """ -Kill Claude processes but leave polecat sandboxes intact. - -```bash -# Stop all polecat Claude sessions -gt stop --all --preserve-sandbox - -# Verify sandboxes still exist -gt polecats --all --status -``` - -What this does: -- Kills tmux sessions running Claude -- Leaves git clones untouched -- Leaves hook files (pinned molecules) intact -- Leaves uncommitted work in place - -What this does NOT do: -- Delete polecat directories -- Remove hook attachments -- Lose any git state - -After restart, polecats can be respawned and will resume from their hooks. - -Note: Crew workers are NOT stopped (they're user-managed). -""" - -[[steps]] -id = "clear-inboxes" -title = "Archive and clear inboxes" -needs = ["stop-sessions"] -description = """ -Archive and clear all agent inboxes across all rigs. - -```bash -# For each rig -for rig in $(gt rigs --names); do - gt mail clear $rig/witness --archive - gt mail clear $rig/refinery --archive -done - -# Clear Mayor inbox -gt mail clear mayor --archive -``` - -Messages are archived to `.beads/mail-archive/` before deletion. -Crew inboxes are NOT cleared (user manages those). -""" - -[[steps]] -id = "stop-daemon" -title = "Stop the daemon" -needs = ["clear-inboxes"] -description = """ -Stop the Gas Town daemon gracefully. - -```bash -gt daemon stop -``` - -The daemon handles: -- Heartbeat monitoring -- Pending spawn triggers -- Background coordination - -It will be restarted in the final step. -""" - -[[steps]] -id = "rotate-logs" -title = "Rotate and archive logs" -needs = ["stop-daemon"] -description = """ -Rotate logs to prevent unbounded growth. - -```bash -# Rotate daemon logs -gt daemon rotate-logs - -# Clean up old session captures (but not current sandboxes) -gt doctor --fix -``` - -Old logs are moved to `~/gt/logs/archive/` with timestamps. -""" - -[[steps]] -id = "sync-state" -title = "Sync beads and push" -needs = ["rotate-logs"] -description = """ -Ensure all beads state is persisted. - -```bash -bd sync -``` - -Note: We do NOT force-commit polecat work here. Their sandboxes -are preserved with whatever state they had. They'll commit their -own work when they resume. -""" - -[[steps]] -id = "handoff-mayor" -title = "Send Mayor handoff" -needs = ["sync-state"] -description = """ -Record shutdown context for the fresh Mayor session. - -```bash -gt mail send mayor -s "🤝 HANDOFF: Town shutdown complete" -m " -Town shutdown completed. State preserved. - -Polecat sandboxes: PRESERVED (will resume from hooks) -Inboxes: ARCHIVED and cleared -Daemon: STOPPED - -Next steps: -1. gt daemon start -2. gt prime -3. gt status (verify health) -4. Resume operations or respawn polecats - -Shutdown reason: {{shutdown_reason}} -" -``` -""" - -[[steps]] -id = "restart-daemon" -title = "Restart daemon" -needs = ["handoff-mayor"] -description = """ -Start the daemon with fresh state. - -```bash -gt daemon start -``` - -The daemon will: -- Begin heartbeat monitoring -- Watch for pending spawns -- Resume background coordination - -Polecats are NOT auto-respawned. Use `gt sling` or let Witness -restart them based on their preserved hooks. -""" diff --git a/.beads/formulas/rule-of-five.formula.toml b/.beads/formulas/rule-of-five.formula.toml deleted file mode 100644 index 373d68b9a..000000000 --- a/.beads/formulas/rule-of-five.formula.toml +++ /dev/null @@ -1,33 +0,0 @@ -description = "Jeffrey Emanuel's discovery: LLM agents produce best work through 4-5 iterative refinements. Breadth-first exploration, then editorial passes." -formula = "rule-of-five" -type = "expansion" -version = 1 - -[[template]] -description = "Initial attempt at: {target.description}. Don't aim for perfection. Get the shape right. Breadth over depth." -id = "{target}.draft" -title = "Draft: {target.title}" - -[[template]] -description = "First refinement pass. Focus: CORRECTNESS. Fix errors, bugs, mistakes. Is the logic sound?" -id = "{target}.refine-1" -needs = ["{target}.draft"] -title = "Refine 1: Correctness" - -[[template]] -description = "Second refinement pass. Focus: CLARITY. Can someone else understand this? Simplify. Remove jargon." -id = "{target}.refine-2" -needs = ["{target}.refine-1"] -title = "Refine 2: Clarity" - -[[template]] -description = "Third refinement pass. Focus: EDGE CASES. What could go wrong? What's missing? Handle the unusual." -id = "{target}.refine-3" -needs = ["{target}.refine-2"] -title = "Refine 3: Edge Cases" - -[[template]] -description = "Final polish. Focus: EXCELLENCE. This is the last pass. Make it shine. Is this something you'd be proud to ship?" -id = "{target}.refine-4" -needs = ["{target}.refine-3"] -title = "Refine 4: Excellence" diff --git a/.beads/formulas/security-audit.formula.toml b/.beads/formulas/security-audit.formula.toml deleted file mode 100644 index 67f9c0c99..000000000 --- a/.beads/formulas/security-audit.formula.toml +++ /dev/null @@ -1,38 +0,0 @@ -description = "Cross-cutting security concern. Applies security scanning before and after implementation steps." -formula = "security-audit" -type = "aspect" -version = 1 - -[[advice]] -target = "implement" -[advice.around] - -[[advice.around.after]] -description = "Post-implementation security scan. Scan new code for vulnerabilities (SAST). Check for hardcoded secrets. Review for OWASP Top 10 issues." -id = "{step.id}-security-postscan" -title = "Security postscan for {step.id}" - -[[advice.around.before]] -description = "Pre-implementation security check. Review for secrets/credentials in scope. Check dependencies for known vulnerabilities." -id = "{step.id}-security-prescan" -title = "Security prescan for {step.id}" - -[[advice]] -target = "submit" -[advice.around] - -[[advice.around.after]] -description = "Post-submission security verification. Confirm no new vulnerabilities introduced." -id = "{step.id}-security-postscan" -title = "Security postscan for {step.id}" - -[[advice.around.before]] -description = "Pre-submission security check. Final vulnerability scan before merge." -id = "{step.id}-security-prescan" -title = "Security prescan for {step.id}" - -[[pointcuts]] -glob = "implement" - -[[pointcuts]] -glob = "submit" diff --git a/.beads/formulas/shiny-enterprise.formula.toml b/.beads/formulas/shiny-enterprise.formula.toml deleted file mode 100644 index cd3981481..000000000 --- a/.beads/formulas/shiny-enterprise.formula.toml +++ /dev/null @@ -1,11 +0,0 @@ -description = "Enterprise-grade engineering workflow. Shiny + Rule of Five expansion on implement step." -extends = ["shiny"] -formula = "shiny-enterprise" -type = "workflow" -version = 1 - -[compose] - -[[compose.expand]] -target = "implement" -with = "rule-of-five" diff --git a/.beads/formulas/shiny-secure.formula.toml b/.beads/formulas/shiny-secure.formula.toml deleted file mode 100644 index 6ac0b8dc4..000000000 --- a/.beads/formulas/shiny-secure.formula.toml +++ /dev/null @@ -1,8 +0,0 @@ -description = "Shiny workflow with security audit aspect applied." -extends = ["shiny"] -formula = "shiny-secure" -type = "workflow" -version = 1 - -[compose] -aspects = ["security-audit"] diff --git a/.beads/formulas/shiny.formula.toml b/.beads/formulas/shiny.formula.toml deleted file mode 100644 index b7971ff4b..000000000 --- a/.beads/formulas/shiny.formula.toml +++ /dev/null @@ -1,40 +0,0 @@ -description = "Engineer in a Box - the canonical right way. Design before you code. Review before you ship. Test before you submit." -formula = "shiny" -type = "workflow" -version = 1 - -[[steps]] -description = "Think carefully about architecture before writing code. Consider: How does this fit into the existing system? What are the edge cases? What could go wrong? Is there a simpler approach?" -id = "design" -title = "Design {{feature}}" - -[[steps]] -description = "Write the code for {{feature}}. Follow the design. Keep it simple. Don't gold-plate." -id = "implement" -needs = ["design"] -title = "Implement {{feature}}" - -[[steps]] -description = "Review the implementation. Check for: Does it match the design? Are there obvious bugs? Is it readable and maintainable? Are there security concerns?" -id = "review" -needs = ["implement"] -title = "Review implementation" - -[[steps]] -description = "Write and run tests. Unit tests for new code, integration tests if needed, run the full test suite, fix any regressions." -id = "test" -needs = ["review"] -title = "Test {{feature}}" - -[[steps]] -description = "Submit for merge. Final check: git status, git diff. Commit with clear message. Follow your role's git workflow for landing code." -id = "submit" -needs = ["test"] -title = "Submit for merge" - -[vars] -[vars.assignee] -description = "Who is assigned to this work" -[vars.feature] -description = "The feature being implemented" -required = true diff --git a/.beads/formulas/towers-of-hanoi-10.formula.toml b/.beads/formulas/towers-of-hanoi-10.formula.toml deleted file mode 100644 index 056e10707..000000000 --- a/.beads/formulas/towers-of-hanoi-10.formula.toml +++ /dev/null @@ -1,6188 +0,0 @@ -description = """ -AGENT EXECUTION PROTOCOL - Towers of Hanoi (10 disks, 1023 moves) - -PURPOSE: This is a durability proof, not computation. Steps are pre-computed. -Your job is to execute them mechanically, proving crash-recovery at scale. - -EXECUTION LOOP: -1. Find current state: bd mol current -2. Find the next ready (unblocked) step -3. Close it: bd close -4. Repeat until no ready steps remain - -ON RESUME (after crash/restart/handoff): -- Same as fresh start. The molecule IS the state. -- Query `bd mol current `, continue from there. -- No memory of previous session needed. - -DO: -- Close steps as fast as possible (they're trivial mechanical moves) -- Use `gt handoff` when context fills (proactive cycling) -- Trust the pre-computed solution - every move is already correct - -DO NOT: -- Try to solve Hanoi yourself - moves are already computed -- Mark steps in_progress - just close them directly -- Ask for permission - this is GUPP territory, just execute -- Stop for human input - run autonomously until complete - -MONITORING: -- Progress: Count closed children of the molecule -- For mega-molecules: Use convoy dashboard when available -- Completion: All steps closed = molecule complete - -This proves Gas Town can execute arbitrarily long workflows with -nondeterministic idempotence - different sessions, same outcome. -""" -formula = "towers-of-hanoi-10" -version = 1 - -[[steps]] -id = "setup" -title = "Verify initial state" -description = "All 10 disks stacked on peg A. Largest on bottom." - - -[[steps]] -id = "move-1" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 1/1023)" -needs = ["setup"] - -[[steps]] -id = "move-2" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 2/1023)" -needs = ["move-1"] - -[[steps]] -id = "move-3" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 3/1023)" -needs = ["move-2"] - -[[steps]] -id = "move-4" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 4/1023)" -needs = ["move-3"] - -[[steps]] -id = "move-5" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 5/1023)" -needs = ["move-4"] - -[[steps]] -id = "move-6" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 6/1023)" -needs = ["move-5"] - -[[steps]] -id = "move-7" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 7/1023)" -needs = ["move-6"] - -[[steps]] -id = "move-8" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 8/1023)" -needs = ["move-7"] - -[[steps]] -id = "move-9" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 9/1023)" -needs = ["move-8"] - -[[steps]] -id = "move-10" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 10/1023)" -needs = ["move-9"] - -[[steps]] -id = "move-11" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 11/1023)" -needs = ["move-10"] - -[[steps]] -id = "move-12" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 12/1023)" -needs = ["move-11"] - -[[steps]] -id = "move-13" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 13/1023)" -needs = ["move-12"] - -[[steps]] -id = "move-14" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 14/1023)" -needs = ["move-13"] - -[[steps]] -id = "move-15" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 15/1023)" -needs = ["move-14"] - -[[steps]] -id = "move-16" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 16/1023)" -needs = ["move-15"] - -[[steps]] -id = "move-17" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 17/1023)" -needs = ["move-16"] - -[[steps]] -id = "move-18" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 18/1023)" -needs = ["move-17"] - -[[steps]] -id = "move-19" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 19/1023)" -needs = ["move-18"] - -[[steps]] -id = "move-20" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 20/1023)" -needs = ["move-19"] - -[[steps]] -id = "move-21" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 21/1023)" -needs = ["move-20"] - -[[steps]] -id = "move-22" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 22/1023)" -needs = ["move-21"] - -[[steps]] -id = "move-23" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 23/1023)" -needs = ["move-22"] - -[[steps]] -id = "move-24" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 24/1023)" -needs = ["move-23"] - -[[steps]] -id = "move-25" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 25/1023)" -needs = ["move-24"] - -[[steps]] -id = "move-26" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 26/1023)" -needs = ["move-25"] - -[[steps]] -id = "move-27" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 27/1023)" -needs = ["move-26"] - -[[steps]] -id = "move-28" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 28/1023)" -needs = ["move-27"] - -[[steps]] -id = "move-29" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 29/1023)" -needs = ["move-28"] - -[[steps]] -id = "move-30" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 30/1023)" -needs = ["move-29"] - -[[steps]] -id = "move-31" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 31/1023)" -needs = ["move-30"] - -[[steps]] -id = "move-32" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 32/1023)" -needs = ["move-31"] - -[[steps]] -id = "move-33" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 33/1023)" -needs = ["move-32"] - -[[steps]] -id = "move-34" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 34/1023)" -needs = ["move-33"] - -[[steps]] -id = "move-35" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 35/1023)" -needs = ["move-34"] - -[[steps]] -id = "move-36" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 36/1023)" -needs = ["move-35"] - -[[steps]] -id = "move-37" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 37/1023)" -needs = ["move-36"] - -[[steps]] -id = "move-38" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 38/1023)" -needs = ["move-37"] - -[[steps]] -id = "move-39" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 39/1023)" -needs = ["move-38"] - -[[steps]] -id = "move-40" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 40/1023)" -needs = ["move-39"] - -[[steps]] -id = "move-41" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 41/1023)" -needs = ["move-40"] - -[[steps]] -id = "move-42" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 42/1023)" -needs = ["move-41"] - -[[steps]] -id = "move-43" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 43/1023)" -needs = ["move-42"] - -[[steps]] -id = "move-44" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 44/1023)" -needs = ["move-43"] - -[[steps]] -id = "move-45" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 45/1023)" -needs = ["move-44"] - -[[steps]] -id = "move-46" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 46/1023)" -needs = ["move-45"] - -[[steps]] -id = "move-47" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 47/1023)" -needs = ["move-46"] - -[[steps]] -id = "move-48" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 48/1023)" -needs = ["move-47"] - -[[steps]] -id = "move-49" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 49/1023)" -needs = ["move-48"] - -[[steps]] -id = "move-50" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 50/1023)" -needs = ["move-49"] - -[[steps]] -id = "move-51" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 51/1023)" -needs = ["move-50"] - -[[steps]] -id = "move-52" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 52/1023)" -needs = ["move-51"] - -[[steps]] -id = "move-53" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 53/1023)" -needs = ["move-52"] - -[[steps]] -id = "move-54" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 54/1023)" -needs = ["move-53"] - -[[steps]] -id = "move-55" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 55/1023)" -needs = ["move-54"] - -[[steps]] -id = "move-56" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 56/1023)" -needs = ["move-55"] - -[[steps]] -id = "move-57" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 57/1023)" -needs = ["move-56"] - -[[steps]] -id = "move-58" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 58/1023)" -needs = ["move-57"] - -[[steps]] -id = "move-59" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 59/1023)" -needs = ["move-58"] - -[[steps]] -id = "move-60" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 60/1023)" -needs = ["move-59"] - -[[steps]] -id = "move-61" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 61/1023)" -needs = ["move-60"] - -[[steps]] -id = "move-62" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 62/1023)" -needs = ["move-61"] - -[[steps]] -id = "move-63" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 63/1023)" -needs = ["move-62"] - -[[steps]] -id = "move-64" -title = "Move disk 7: A → B" -description = "Move disk 7 from peg A to peg B. (Move 64/1023)" -needs = ["move-63"] - -[[steps]] -id = "move-65" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 65/1023)" -needs = ["move-64"] - -[[steps]] -id = "move-66" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 66/1023)" -needs = ["move-65"] - -[[steps]] -id = "move-67" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 67/1023)" -needs = ["move-66"] - -[[steps]] -id = "move-68" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 68/1023)" -needs = ["move-67"] - -[[steps]] -id = "move-69" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 69/1023)" -needs = ["move-68"] - -[[steps]] -id = "move-70" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 70/1023)" -needs = ["move-69"] - -[[steps]] -id = "move-71" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 71/1023)" -needs = ["move-70"] - -[[steps]] -id = "move-72" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 72/1023)" -needs = ["move-71"] - -[[steps]] -id = "move-73" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 73/1023)" -needs = ["move-72"] - -[[steps]] -id = "move-74" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 74/1023)" -needs = ["move-73"] - -[[steps]] -id = "move-75" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 75/1023)" -needs = ["move-74"] - -[[steps]] -id = "move-76" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 76/1023)" -needs = ["move-75"] - -[[steps]] -id = "move-77" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 77/1023)" -needs = ["move-76"] - -[[steps]] -id = "move-78" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 78/1023)" -needs = ["move-77"] - -[[steps]] -id = "move-79" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 79/1023)" -needs = ["move-78"] - -[[steps]] -id = "move-80" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 80/1023)" -needs = ["move-79"] - -[[steps]] -id = "move-81" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 81/1023)" -needs = ["move-80"] - -[[steps]] -id = "move-82" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 82/1023)" -needs = ["move-81"] - -[[steps]] -id = "move-83" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 83/1023)" -needs = ["move-82"] - -[[steps]] -id = "move-84" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 84/1023)" -needs = ["move-83"] - -[[steps]] -id = "move-85" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 85/1023)" -needs = ["move-84"] - -[[steps]] -id = "move-86" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 86/1023)" -needs = ["move-85"] - -[[steps]] -id = "move-87" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 87/1023)" -needs = ["move-86"] - -[[steps]] -id = "move-88" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 88/1023)" -needs = ["move-87"] - -[[steps]] -id = "move-89" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 89/1023)" -needs = ["move-88"] - -[[steps]] -id = "move-90" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 90/1023)" -needs = ["move-89"] - -[[steps]] -id = "move-91" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 91/1023)" -needs = ["move-90"] - -[[steps]] -id = "move-92" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 92/1023)" -needs = ["move-91"] - -[[steps]] -id = "move-93" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 93/1023)" -needs = ["move-92"] - -[[steps]] -id = "move-94" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 94/1023)" -needs = ["move-93"] - -[[steps]] -id = "move-95" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 95/1023)" -needs = ["move-94"] - -[[steps]] -id = "move-96" -title = "Move disk 6: C → B" -description = "Move disk 6 from peg C to peg B. (Move 96/1023)" -needs = ["move-95"] - -[[steps]] -id = "move-97" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 97/1023)" -needs = ["move-96"] - -[[steps]] -id = "move-98" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 98/1023)" -needs = ["move-97"] - -[[steps]] -id = "move-99" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 99/1023)" -needs = ["move-98"] - -[[steps]] -id = "move-100" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 100/1023)" -needs = ["move-99"] - -[[steps]] -id = "move-101" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 101/1023)" -needs = ["move-100"] - -[[steps]] -id = "move-102" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 102/1023)" -needs = ["move-101"] - -[[steps]] -id = "move-103" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 103/1023)" -needs = ["move-102"] - -[[steps]] -id = "move-104" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 104/1023)" -needs = ["move-103"] - -[[steps]] -id = "move-105" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 105/1023)" -needs = ["move-104"] - -[[steps]] -id = "move-106" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 106/1023)" -needs = ["move-105"] - -[[steps]] -id = "move-107" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 107/1023)" -needs = ["move-106"] - -[[steps]] -id = "move-108" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 108/1023)" -needs = ["move-107"] - -[[steps]] -id = "move-109" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 109/1023)" -needs = ["move-108"] - -[[steps]] -id = "move-110" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 110/1023)" -needs = ["move-109"] - -[[steps]] -id = "move-111" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 111/1023)" -needs = ["move-110"] - -[[steps]] -id = "move-112" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 112/1023)" -needs = ["move-111"] - -[[steps]] -id = "move-113" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 113/1023)" -needs = ["move-112"] - -[[steps]] -id = "move-114" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 114/1023)" -needs = ["move-113"] - -[[steps]] -id = "move-115" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 115/1023)" -needs = ["move-114"] - -[[steps]] -id = "move-116" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 116/1023)" -needs = ["move-115"] - -[[steps]] -id = "move-117" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 117/1023)" -needs = ["move-116"] - -[[steps]] -id = "move-118" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 118/1023)" -needs = ["move-117"] - -[[steps]] -id = "move-119" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 119/1023)" -needs = ["move-118"] - -[[steps]] -id = "move-120" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 120/1023)" -needs = ["move-119"] - -[[steps]] -id = "move-121" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 121/1023)" -needs = ["move-120"] - -[[steps]] -id = "move-122" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 122/1023)" -needs = ["move-121"] - -[[steps]] -id = "move-123" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 123/1023)" -needs = ["move-122"] - -[[steps]] -id = "move-124" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 124/1023)" -needs = ["move-123"] - -[[steps]] -id = "move-125" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 125/1023)" -needs = ["move-124"] - -[[steps]] -id = "move-126" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 126/1023)" -needs = ["move-125"] - -[[steps]] -id = "move-127" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 127/1023)" -needs = ["move-126"] - -[[steps]] -id = "move-128" -title = "Move disk 8: A → C" -description = "Move disk 8 from peg A to peg C. (Move 128/1023)" -needs = ["move-127"] - -[[steps]] -id = "move-129" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 129/1023)" -needs = ["move-128"] - -[[steps]] -id = "move-130" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 130/1023)" -needs = ["move-129"] - -[[steps]] -id = "move-131" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 131/1023)" -needs = ["move-130"] - -[[steps]] -id = "move-132" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 132/1023)" -needs = ["move-131"] - -[[steps]] -id = "move-133" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 133/1023)" -needs = ["move-132"] - -[[steps]] -id = "move-134" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 134/1023)" -needs = ["move-133"] - -[[steps]] -id = "move-135" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 135/1023)" -needs = ["move-134"] - -[[steps]] -id = "move-136" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 136/1023)" -needs = ["move-135"] - -[[steps]] -id = "move-137" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 137/1023)" -needs = ["move-136"] - -[[steps]] -id = "move-138" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 138/1023)" -needs = ["move-137"] - -[[steps]] -id = "move-139" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 139/1023)" -needs = ["move-138"] - -[[steps]] -id = "move-140" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 140/1023)" -needs = ["move-139"] - -[[steps]] -id = "move-141" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 141/1023)" -needs = ["move-140"] - -[[steps]] -id = "move-142" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 142/1023)" -needs = ["move-141"] - -[[steps]] -id = "move-143" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 143/1023)" -needs = ["move-142"] - -[[steps]] -id = "move-144" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 144/1023)" -needs = ["move-143"] - -[[steps]] -id = "move-145" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 145/1023)" -needs = ["move-144"] - -[[steps]] -id = "move-146" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 146/1023)" -needs = ["move-145"] - -[[steps]] -id = "move-147" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 147/1023)" -needs = ["move-146"] - -[[steps]] -id = "move-148" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 148/1023)" -needs = ["move-147"] - -[[steps]] -id = "move-149" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 149/1023)" -needs = ["move-148"] - -[[steps]] -id = "move-150" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 150/1023)" -needs = ["move-149"] - -[[steps]] -id = "move-151" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 151/1023)" -needs = ["move-150"] - -[[steps]] -id = "move-152" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 152/1023)" -needs = ["move-151"] - -[[steps]] -id = "move-153" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 153/1023)" -needs = ["move-152"] - -[[steps]] -id = "move-154" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 154/1023)" -needs = ["move-153"] - -[[steps]] -id = "move-155" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 155/1023)" -needs = ["move-154"] - -[[steps]] -id = "move-156" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 156/1023)" -needs = ["move-155"] - -[[steps]] -id = "move-157" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 157/1023)" -needs = ["move-156"] - -[[steps]] -id = "move-158" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 158/1023)" -needs = ["move-157"] - -[[steps]] -id = "move-159" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 159/1023)" -needs = ["move-158"] - -[[steps]] -id = "move-160" -title = "Move disk 6: B → A" -description = "Move disk 6 from peg B to peg A. (Move 160/1023)" -needs = ["move-159"] - -[[steps]] -id = "move-161" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 161/1023)" -needs = ["move-160"] - -[[steps]] -id = "move-162" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 162/1023)" -needs = ["move-161"] - -[[steps]] -id = "move-163" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 163/1023)" -needs = ["move-162"] - -[[steps]] -id = "move-164" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 164/1023)" -needs = ["move-163"] - -[[steps]] -id = "move-165" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 165/1023)" -needs = ["move-164"] - -[[steps]] -id = "move-166" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 166/1023)" -needs = ["move-165"] - -[[steps]] -id = "move-167" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 167/1023)" -needs = ["move-166"] - -[[steps]] -id = "move-168" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 168/1023)" -needs = ["move-167"] - -[[steps]] -id = "move-169" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 169/1023)" -needs = ["move-168"] - -[[steps]] -id = "move-170" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 170/1023)" -needs = ["move-169"] - -[[steps]] -id = "move-171" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 171/1023)" -needs = ["move-170"] - -[[steps]] -id = "move-172" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 172/1023)" -needs = ["move-171"] - -[[steps]] -id = "move-173" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 173/1023)" -needs = ["move-172"] - -[[steps]] -id = "move-174" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 174/1023)" -needs = ["move-173"] - -[[steps]] -id = "move-175" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 175/1023)" -needs = ["move-174"] - -[[steps]] -id = "move-176" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 176/1023)" -needs = ["move-175"] - -[[steps]] -id = "move-177" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 177/1023)" -needs = ["move-176"] - -[[steps]] -id = "move-178" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 178/1023)" -needs = ["move-177"] - -[[steps]] -id = "move-179" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 179/1023)" -needs = ["move-178"] - -[[steps]] -id = "move-180" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 180/1023)" -needs = ["move-179"] - -[[steps]] -id = "move-181" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 181/1023)" -needs = ["move-180"] - -[[steps]] -id = "move-182" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 182/1023)" -needs = ["move-181"] - -[[steps]] -id = "move-183" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 183/1023)" -needs = ["move-182"] - -[[steps]] -id = "move-184" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 184/1023)" -needs = ["move-183"] - -[[steps]] -id = "move-185" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 185/1023)" -needs = ["move-184"] - -[[steps]] -id = "move-186" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 186/1023)" -needs = ["move-185"] - -[[steps]] -id = "move-187" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 187/1023)" -needs = ["move-186"] - -[[steps]] -id = "move-188" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 188/1023)" -needs = ["move-187"] - -[[steps]] -id = "move-189" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 189/1023)" -needs = ["move-188"] - -[[steps]] -id = "move-190" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 190/1023)" -needs = ["move-189"] - -[[steps]] -id = "move-191" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 191/1023)" -needs = ["move-190"] - -[[steps]] -id = "move-192" -title = "Move disk 7: B → C" -description = "Move disk 7 from peg B to peg C. (Move 192/1023)" -needs = ["move-191"] - -[[steps]] -id = "move-193" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 193/1023)" -needs = ["move-192"] - -[[steps]] -id = "move-194" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 194/1023)" -needs = ["move-193"] - -[[steps]] -id = "move-195" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 195/1023)" -needs = ["move-194"] - -[[steps]] -id = "move-196" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 196/1023)" -needs = ["move-195"] - -[[steps]] -id = "move-197" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 197/1023)" -needs = ["move-196"] - -[[steps]] -id = "move-198" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 198/1023)" -needs = ["move-197"] - -[[steps]] -id = "move-199" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 199/1023)" -needs = ["move-198"] - -[[steps]] -id = "move-200" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 200/1023)" -needs = ["move-199"] - -[[steps]] -id = "move-201" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 201/1023)" -needs = ["move-200"] - -[[steps]] -id = "move-202" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 202/1023)" -needs = ["move-201"] - -[[steps]] -id = "move-203" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 203/1023)" -needs = ["move-202"] - -[[steps]] -id = "move-204" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 204/1023)" -needs = ["move-203"] - -[[steps]] -id = "move-205" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 205/1023)" -needs = ["move-204"] - -[[steps]] -id = "move-206" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 206/1023)" -needs = ["move-205"] - -[[steps]] -id = "move-207" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 207/1023)" -needs = ["move-206"] - -[[steps]] -id = "move-208" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 208/1023)" -needs = ["move-207"] - -[[steps]] -id = "move-209" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 209/1023)" -needs = ["move-208"] - -[[steps]] -id = "move-210" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 210/1023)" -needs = ["move-209"] - -[[steps]] -id = "move-211" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 211/1023)" -needs = ["move-210"] - -[[steps]] -id = "move-212" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 212/1023)" -needs = ["move-211"] - -[[steps]] -id = "move-213" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 213/1023)" -needs = ["move-212"] - -[[steps]] -id = "move-214" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 214/1023)" -needs = ["move-213"] - -[[steps]] -id = "move-215" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 215/1023)" -needs = ["move-214"] - -[[steps]] -id = "move-216" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 216/1023)" -needs = ["move-215"] - -[[steps]] -id = "move-217" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 217/1023)" -needs = ["move-216"] - -[[steps]] -id = "move-218" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 218/1023)" -needs = ["move-217"] - -[[steps]] -id = "move-219" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 219/1023)" -needs = ["move-218"] - -[[steps]] -id = "move-220" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 220/1023)" -needs = ["move-219"] - -[[steps]] -id = "move-221" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 221/1023)" -needs = ["move-220"] - -[[steps]] -id = "move-222" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 222/1023)" -needs = ["move-221"] - -[[steps]] -id = "move-223" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 223/1023)" -needs = ["move-222"] - -[[steps]] -id = "move-224" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 224/1023)" -needs = ["move-223"] - -[[steps]] -id = "move-225" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 225/1023)" -needs = ["move-224"] - -[[steps]] -id = "move-226" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 226/1023)" -needs = ["move-225"] - -[[steps]] -id = "move-227" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 227/1023)" -needs = ["move-226"] - -[[steps]] -id = "move-228" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 228/1023)" -needs = ["move-227"] - -[[steps]] -id = "move-229" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 229/1023)" -needs = ["move-228"] - -[[steps]] -id = "move-230" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 230/1023)" -needs = ["move-229"] - -[[steps]] -id = "move-231" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 231/1023)" -needs = ["move-230"] - -[[steps]] -id = "move-232" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 232/1023)" -needs = ["move-231"] - -[[steps]] -id = "move-233" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 233/1023)" -needs = ["move-232"] - -[[steps]] -id = "move-234" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 234/1023)" -needs = ["move-233"] - -[[steps]] -id = "move-235" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 235/1023)" -needs = ["move-234"] - -[[steps]] -id = "move-236" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 236/1023)" -needs = ["move-235"] - -[[steps]] -id = "move-237" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 237/1023)" -needs = ["move-236"] - -[[steps]] -id = "move-238" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 238/1023)" -needs = ["move-237"] - -[[steps]] -id = "move-239" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 239/1023)" -needs = ["move-238"] - -[[steps]] -id = "move-240" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 240/1023)" -needs = ["move-239"] - -[[steps]] -id = "move-241" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 241/1023)" -needs = ["move-240"] - -[[steps]] -id = "move-242" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 242/1023)" -needs = ["move-241"] - -[[steps]] -id = "move-243" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 243/1023)" -needs = ["move-242"] - -[[steps]] -id = "move-244" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 244/1023)" -needs = ["move-243"] - -[[steps]] -id = "move-245" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 245/1023)" -needs = ["move-244"] - -[[steps]] -id = "move-246" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 246/1023)" -needs = ["move-245"] - -[[steps]] -id = "move-247" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 247/1023)" -needs = ["move-246"] - -[[steps]] -id = "move-248" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 248/1023)" -needs = ["move-247"] - -[[steps]] -id = "move-249" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 249/1023)" -needs = ["move-248"] - -[[steps]] -id = "move-250" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 250/1023)" -needs = ["move-249"] - -[[steps]] -id = "move-251" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 251/1023)" -needs = ["move-250"] - -[[steps]] -id = "move-252" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 252/1023)" -needs = ["move-251"] - -[[steps]] -id = "move-253" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 253/1023)" -needs = ["move-252"] - -[[steps]] -id = "move-254" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 254/1023)" -needs = ["move-253"] - -[[steps]] -id = "move-255" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 255/1023)" -needs = ["move-254"] - -[[steps]] -id = "move-256" -title = "Move disk 9: A → B" -description = "Move disk 9 from peg A to peg B. (Move 256/1023)" -needs = ["move-255"] - -[[steps]] -id = "move-257" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 257/1023)" -needs = ["move-256"] - -[[steps]] -id = "move-258" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 258/1023)" -needs = ["move-257"] - -[[steps]] -id = "move-259" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 259/1023)" -needs = ["move-258"] - -[[steps]] -id = "move-260" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 260/1023)" -needs = ["move-259"] - -[[steps]] -id = "move-261" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 261/1023)" -needs = ["move-260"] - -[[steps]] -id = "move-262" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 262/1023)" -needs = ["move-261"] - -[[steps]] -id = "move-263" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 263/1023)" -needs = ["move-262"] - -[[steps]] -id = "move-264" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 264/1023)" -needs = ["move-263"] - -[[steps]] -id = "move-265" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 265/1023)" -needs = ["move-264"] - -[[steps]] -id = "move-266" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 266/1023)" -needs = ["move-265"] - -[[steps]] -id = "move-267" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 267/1023)" -needs = ["move-266"] - -[[steps]] -id = "move-268" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 268/1023)" -needs = ["move-267"] - -[[steps]] -id = "move-269" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 269/1023)" -needs = ["move-268"] - -[[steps]] -id = "move-270" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 270/1023)" -needs = ["move-269"] - -[[steps]] -id = "move-271" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 271/1023)" -needs = ["move-270"] - -[[steps]] -id = "move-272" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 272/1023)" -needs = ["move-271"] - -[[steps]] -id = "move-273" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 273/1023)" -needs = ["move-272"] - -[[steps]] -id = "move-274" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 274/1023)" -needs = ["move-273"] - -[[steps]] -id = "move-275" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 275/1023)" -needs = ["move-274"] - -[[steps]] -id = "move-276" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 276/1023)" -needs = ["move-275"] - -[[steps]] -id = "move-277" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 277/1023)" -needs = ["move-276"] - -[[steps]] -id = "move-278" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 278/1023)" -needs = ["move-277"] - -[[steps]] -id = "move-279" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 279/1023)" -needs = ["move-278"] - -[[steps]] -id = "move-280" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 280/1023)" -needs = ["move-279"] - -[[steps]] -id = "move-281" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 281/1023)" -needs = ["move-280"] - -[[steps]] -id = "move-282" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 282/1023)" -needs = ["move-281"] - -[[steps]] -id = "move-283" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 283/1023)" -needs = ["move-282"] - -[[steps]] -id = "move-284" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 284/1023)" -needs = ["move-283"] - -[[steps]] -id = "move-285" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 285/1023)" -needs = ["move-284"] - -[[steps]] -id = "move-286" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 286/1023)" -needs = ["move-285"] - -[[steps]] -id = "move-287" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 287/1023)" -needs = ["move-286"] - -[[steps]] -id = "move-288" -title = "Move disk 6: C → B" -description = "Move disk 6 from peg C to peg B. (Move 288/1023)" -needs = ["move-287"] - -[[steps]] -id = "move-289" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 289/1023)" -needs = ["move-288"] - -[[steps]] -id = "move-290" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 290/1023)" -needs = ["move-289"] - -[[steps]] -id = "move-291" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 291/1023)" -needs = ["move-290"] - -[[steps]] -id = "move-292" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 292/1023)" -needs = ["move-291"] - -[[steps]] -id = "move-293" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 293/1023)" -needs = ["move-292"] - -[[steps]] -id = "move-294" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 294/1023)" -needs = ["move-293"] - -[[steps]] -id = "move-295" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 295/1023)" -needs = ["move-294"] - -[[steps]] -id = "move-296" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 296/1023)" -needs = ["move-295"] - -[[steps]] -id = "move-297" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 297/1023)" -needs = ["move-296"] - -[[steps]] -id = "move-298" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 298/1023)" -needs = ["move-297"] - -[[steps]] -id = "move-299" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 299/1023)" -needs = ["move-298"] - -[[steps]] -id = "move-300" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 300/1023)" -needs = ["move-299"] - -[[steps]] -id = "move-301" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 301/1023)" -needs = ["move-300"] - -[[steps]] -id = "move-302" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 302/1023)" -needs = ["move-301"] - -[[steps]] -id = "move-303" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 303/1023)" -needs = ["move-302"] - -[[steps]] -id = "move-304" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 304/1023)" -needs = ["move-303"] - -[[steps]] -id = "move-305" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 305/1023)" -needs = ["move-304"] - -[[steps]] -id = "move-306" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 306/1023)" -needs = ["move-305"] - -[[steps]] -id = "move-307" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 307/1023)" -needs = ["move-306"] - -[[steps]] -id = "move-308" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 308/1023)" -needs = ["move-307"] - -[[steps]] -id = "move-309" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 309/1023)" -needs = ["move-308"] - -[[steps]] -id = "move-310" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 310/1023)" -needs = ["move-309"] - -[[steps]] -id = "move-311" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 311/1023)" -needs = ["move-310"] - -[[steps]] -id = "move-312" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 312/1023)" -needs = ["move-311"] - -[[steps]] -id = "move-313" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 313/1023)" -needs = ["move-312"] - -[[steps]] -id = "move-314" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 314/1023)" -needs = ["move-313"] - -[[steps]] -id = "move-315" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 315/1023)" -needs = ["move-314"] - -[[steps]] -id = "move-316" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 316/1023)" -needs = ["move-315"] - -[[steps]] -id = "move-317" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 317/1023)" -needs = ["move-316"] - -[[steps]] -id = "move-318" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 318/1023)" -needs = ["move-317"] - -[[steps]] -id = "move-319" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 319/1023)" -needs = ["move-318"] - -[[steps]] -id = "move-320" -title = "Move disk 7: C → A" -description = "Move disk 7 from peg C to peg A. (Move 320/1023)" -needs = ["move-319"] - -[[steps]] -id = "move-321" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 321/1023)" -needs = ["move-320"] - -[[steps]] -id = "move-322" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 322/1023)" -needs = ["move-321"] - -[[steps]] -id = "move-323" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 323/1023)" -needs = ["move-322"] - -[[steps]] -id = "move-324" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 324/1023)" -needs = ["move-323"] - -[[steps]] -id = "move-325" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 325/1023)" -needs = ["move-324"] - -[[steps]] -id = "move-326" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 326/1023)" -needs = ["move-325"] - -[[steps]] -id = "move-327" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 327/1023)" -needs = ["move-326"] - -[[steps]] -id = "move-328" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 328/1023)" -needs = ["move-327"] - -[[steps]] -id = "move-329" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 329/1023)" -needs = ["move-328"] - -[[steps]] -id = "move-330" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 330/1023)" -needs = ["move-329"] - -[[steps]] -id = "move-331" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 331/1023)" -needs = ["move-330"] - -[[steps]] -id = "move-332" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 332/1023)" -needs = ["move-331"] - -[[steps]] -id = "move-333" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 333/1023)" -needs = ["move-332"] - -[[steps]] -id = "move-334" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 334/1023)" -needs = ["move-333"] - -[[steps]] -id = "move-335" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 335/1023)" -needs = ["move-334"] - -[[steps]] -id = "move-336" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 336/1023)" -needs = ["move-335"] - -[[steps]] -id = "move-337" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 337/1023)" -needs = ["move-336"] - -[[steps]] -id = "move-338" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 338/1023)" -needs = ["move-337"] - -[[steps]] -id = "move-339" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 339/1023)" -needs = ["move-338"] - -[[steps]] -id = "move-340" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 340/1023)" -needs = ["move-339"] - -[[steps]] -id = "move-341" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 341/1023)" -needs = ["move-340"] - -[[steps]] -id = "move-342" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 342/1023)" -needs = ["move-341"] - -[[steps]] -id = "move-343" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 343/1023)" -needs = ["move-342"] - -[[steps]] -id = "move-344" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 344/1023)" -needs = ["move-343"] - -[[steps]] -id = "move-345" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 345/1023)" -needs = ["move-344"] - -[[steps]] -id = "move-346" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 346/1023)" -needs = ["move-345"] - -[[steps]] -id = "move-347" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 347/1023)" -needs = ["move-346"] - -[[steps]] -id = "move-348" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 348/1023)" -needs = ["move-347"] - -[[steps]] -id = "move-349" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 349/1023)" -needs = ["move-348"] - -[[steps]] -id = "move-350" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 350/1023)" -needs = ["move-349"] - -[[steps]] -id = "move-351" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 351/1023)" -needs = ["move-350"] - -[[steps]] -id = "move-352" -title = "Move disk 6: B → A" -description = "Move disk 6 from peg B to peg A. (Move 352/1023)" -needs = ["move-351"] - -[[steps]] -id = "move-353" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 353/1023)" -needs = ["move-352"] - -[[steps]] -id = "move-354" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 354/1023)" -needs = ["move-353"] - -[[steps]] -id = "move-355" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 355/1023)" -needs = ["move-354"] - -[[steps]] -id = "move-356" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 356/1023)" -needs = ["move-355"] - -[[steps]] -id = "move-357" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 357/1023)" -needs = ["move-356"] - -[[steps]] -id = "move-358" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 358/1023)" -needs = ["move-357"] - -[[steps]] -id = "move-359" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 359/1023)" -needs = ["move-358"] - -[[steps]] -id = "move-360" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 360/1023)" -needs = ["move-359"] - -[[steps]] -id = "move-361" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 361/1023)" -needs = ["move-360"] - -[[steps]] -id = "move-362" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 362/1023)" -needs = ["move-361"] - -[[steps]] -id = "move-363" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 363/1023)" -needs = ["move-362"] - -[[steps]] -id = "move-364" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 364/1023)" -needs = ["move-363"] - -[[steps]] -id = "move-365" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 365/1023)" -needs = ["move-364"] - -[[steps]] -id = "move-366" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 366/1023)" -needs = ["move-365"] - -[[steps]] -id = "move-367" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 367/1023)" -needs = ["move-366"] - -[[steps]] -id = "move-368" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 368/1023)" -needs = ["move-367"] - -[[steps]] -id = "move-369" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 369/1023)" -needs = ["move-368"] - -[[steps]] -id = "move-370" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 370/1023)" -needs = ["move-369"] - -[[steps]] -id = "move-371" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 371/1023)" -needs = ["move-370"] - -[[steps]] -id = "move-372" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 372/1023)" -needs = ["move-371"] - -[[steps]] -id = "move-373" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 373/1023)" -needs = ["move-372"] - -[[steps]] -id = "move-374" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 374/1023)" -needs = ["move-373"] - -[[steps]] -id = "move-375" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 375/1023)" -needs = ["move-374"] - -[[steps]] -id = "move-376" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 376/1023)" -needs = ["move-375"] - -[[steps]] -id = "move-377" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 377/1023)" -needs = ["move-376"] - -[[steps]] -id = "move-378" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 378/1023)" -needs = ["move-377"] - -[[steps]] -id = "move-379" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 379/1023)" -needs = ["move-378"] - -[[steps]] -id = "move-380" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 380/1023)" -needs = ["move-379"] - -[[steps]] -id = "move-381" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 381/1023)" -needs = ["move-380"] - -[[steps]] -id = "move-382" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 382/1023)" -needs = ["move-381"] - -[[steps]] -id = "move-383" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 383/1023)" -needs = ["move-382"] - -[[steps]] -id = "move-384" -title = "Move disk 8: C → B" -description = "Move disk 8 from peg C to peg B. (Move 384/1023)" -needs = ["move-383"] - -[[steps]] -id = "move-385" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 385/1023)" -needs = ["move-384"] - -[[steps]] -id = "move-386" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 386/1023)" -needs = ["move-385"] - -[[steps]] -id = "move-387" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 387/1023)" -needs = ["move-386"] - -[[steps]] -id = "move-388" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 388/1023)" -needs = ["move-387"] - -[[steps]] -id = "move-389" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 389/1023)" -needs = ["move-388"] - -[[steps]] -id = "move-390" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 390/1023)" -needs = ["move-389"] - -[[steps]] -id = "move-391" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 391/1023)" -needs = ["move-390"] - -[[steps]] -id = "move-392" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 392/1023)" -needs = ["move-391"] - -[[steps]] -id = "move-393" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 393/1023)" -needs = ["move-392"] - -[[steps]] -id = "move-394" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 394/1023)" -needs = ["move-393"] - -[[steps]] -id = "move-395" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 395/1023)" -needs = ["move-394"] - -[[steps]] -id = "move-396" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 396/1023)" -needs = ["move-395"] - -[[steps]] -id = "move-397" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 397/1023)" -needs = ["move-396"] - -[[steps]] -id = "move-398" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 398/1023)" -needs = ["move-397"] - -[[steps]] -id = "move-399" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 399/1023)" -needs = ["move-398"] - -[[steps]] -id = "move-400" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 400/1023)" -needs = ["move-399"] - -[[steps]] -id = "move-401" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 401/1023)" -needs = ["move-400"] - -[[steps]] -id = "move-402" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 402/1023)" -needs = ["move-401"] - -[[steps]] -id = "move-403" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 403/1023)" -needs = ["move-402"] - -[[steps]] -id = "move-404" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 404/1023)" -needs = ["move-403"] - -[[steps]] -id = "move-405" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 405/1023)" -needs = ["move-404"] - -[[steps]] -id = "move-406" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 406/1023)" -needs = ["move-405"] - -[[steps]] -id = "move-407" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 407/1023)" -needs = ["move-406"] - -[[steps]] -id = "move-408" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 408/1023)" -needs = ["move-407"] - -[[steps]] -id = "move-409" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 409/1023)" -needs = ["move-408"] - -[[steps]] -id = "move-410" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 410/1023)" -needs = ["move-409"] - -[[steps]] -id = "move-411" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 411/1023)" -needs = ["move-410"] - -[[steps]] -id = "move-412" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 412/1023)" -needs = ["move-411"] - -[[steps]] -id = "move-413" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 413/1023)" -needs = ["move-412"] - -[[steps]] -id = "move-414" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 414/1023)" -needs = ["move-413"] - -[[steps]] -id = "move-415" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 415/1023)" -needs = ["move-414"] - -[[steps]] -id = "move-416" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 416/1023)" -needs = ["move-415"] - -[[steps]] -id = "move-417" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 417/1023)" -needs = ["move-416"] - -[[steps]] -id = "move-418" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 418/1023)" -needs = ["move-417"] - -[[steps]] -id = "move-419" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 419/1023)" -needs = ["move-418"] - -[[steps]] -id = "move-420" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 420/1023)" -needs = ["move-419"] - -[[steps]] -id = "move-421" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 421/1023)" -needs = ["move-420"] - -[[steps]] -id = "move-422" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 422/1023)" -needs = ["move-421"] - -[[steps]] -id = "move-423" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 423/1023)" -needs = ["move-422"] - -[[steps]] -id = "move-424" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 424/1023)" -needs = ["move-423"] - -[[steps]] -id = "move-425" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 425/1023)" -needs = ["move-424"] - -[[steps]] -id = "move-426" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 426/1023)" -needs = ["move-425"] - -[[steps]] -id = "move-427" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 427/1023)" -needs = ["move-426"] - -[[steps]] -id = "move-428" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 428/1023)" -needs = ["move-427"] - -[[steps]] -id = "move-429" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 429/1023)" -needs = ["move-428"] - -[[steps]] -id = "move-430" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 430/1023)" -needs = ["move-429"] - -[[steps]] -id = "move-431" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 431/1023)" -needs = ["move-430"] - -[[steps]] -id = "move-432" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 432/1023)" -needs = ["move-431"] - -[[steps]] -id = "move-433" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 433/1023)" -needs = ["move-432"] - -[[steps]] -id = "move-434" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 434/1023)" -needs = ["move-433"] - -[[steps]] -id = "move-435" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 435/1023)" -needs = ["move-434"] - -[[steps]] -id = "move-436" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 436/1023)" -needs = ["move-435"] - -[[steps]] -id = "move-437" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 437/1023)" -needs = ["move-436"] - -[[steps]] -id = "move-438" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 438/1023)" -needs = ["move-437"] - -[[steps]] -id = "move-439" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 439/1023)" -needs = ["move-438"] - -[[steps]] -id = "move-440" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 440/1023)" -needs = ["move-439"] - -[[steps]] -id = "move-441" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 441/1023)" -needs = ["move-440"] - -[[steps]] -id = "move-442" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 442/1023)" -needs = ["move-441"] - -[[steps]] -id = "move-443" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 443/1023)" -needs = ["move-442"] - -[[steps]] -id = "move-444" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 444/1023)" -needs = ["move-443"] - -[[steps]] -id = "move-445" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 445/1023)" -needs = ["move-444"] - -[[steps]] -id = "move-446" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 446/1023)" -needs = ["move-445"] - -[[steps]] -id = "move-447" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 447/1023)" -needs = ["move-446"] - -[[steps]] -id = "move-448" -title = "Move disk 7: A → B" -description = "Move disk 7 from peg A to peg B. (Move 448/1023)" -needs = ["move-447"] - -[[steps]] -id = "move-449" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 449/1023)" -needs = ["move-448"] - -[[steps]] -id = "move-450" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 450/1023)" -needs = ["move-449"] - -[[steps]] -id = "move-451" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 451/1023)" -needs = ["move-450"] - -[[steps]] -id = "move-452" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 452/1023)" -needs = ["move-451"] - -[[steps]] -id = "move-453" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 453/1023)" -needs = ["move-452"] - -[[steps]] -id = "move-454" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 454/1023)" -needs = ["move-453"] - -[[steps]] -id = "move-455" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 455/1023)" -needs = ["move-454"] - -[[steps]] -id = "move-456" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 456/1023)" -needs = ["move-455"] - -[[steps]] -id = "move-457" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 457/1023)" -needs = ["move-456"] - -[[steps]] -id = "move-458" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 458/1023)" -needs = ["move-457"] - -[[steps]] -id = "move-459" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 459/1023)" -needs = ["move-458"] - -[[steps]] -id = "move-460" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 460/1023)" -needs = ["move-459"] - -[[steps]] -id = "move-461" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 461/1023)" -needs = ["move-460"] - -[[steps]] -id = "move-462" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 462/1023)" -needs = ["move-461"] - -[[steps]] -id = "move-463" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 463/1023)" -needs = ["move-462"] - -[[steps]] -id = "move-464" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 464/1023)" -needs = ["move-463"] - -[[steps]] -id = "move-465" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 465/1023)" -needs = ["move-464"] - -[[steps]] -id = "move-466" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 466/1023)" -needs = ["move-465"] - -[[steps]] -id = "move-467" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 467/1023)" -needs = ["move-466"] - -[[steps]] -id = "move-468" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 468/1023)" -needs = ["move-467"] - -[[steps]] -id = "move-469" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 469/1023)" -needs = ["move-468"] - -[[steps]] -id = "move-470" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 470/1023)" -needs = ["move-469"] - -[[steps]] -id = "move-471" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 471/1023)" -needs = ["move-470"] - -[[steps]] -id = "move-472" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 472/1023)" -needs = ["move-471"] - -[[steps]] -id = "move-473" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 473/1023)" -needs = ["move-472"] - -[[steps]] -id = "move-474" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 474/1023)" -needs = ["move-473"] - -[[steps]] -id = "move-475" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 475/1023)" -needs = ["move-474"] - -[[steps]] -id = "move-476" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 476/1023)" -needs = ["move-475"] - -[[steps]] -id = "move-477" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 477/1023)" -needs = ["move-476"] - -[[steps]] -id = "move-478" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 478/1023)" -needs = ["move-477"] - -[[steps]] -id = "move-479" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 479/1023)" -needs = ["move-478"] - -[[steps]] -id = "move-480" -title = "Move disk 6: C → B" -description = "Move disk 6 from peg C to peg B. (Move 480/1023)" -needs = ["move-479"] - -[[steps]] -id = "move-481" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 481/1023)" -needs = ["move-480"] - -[[steps]] -id = "move-482" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 482/1023)" -needs = ["move-481"] - -[[steps]] -id = "move-483" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 483/1023)" -needs = ["move-482"] - -[[steps]] -id = "move-484" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 484/1023)" -needs = ["move-483"] - -[[steps]] -id = "move-485" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 485/1023)" -needs = ["move-484"] - -[[steps]] -id = "move-486" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 486/1023)" -needs = ["move-485"] - -[[steps]] -id = "move-487" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 487/1023)" -needs = ["move-486"] - -[[steps]] -id = "move-488" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 488/1023)" -needs = ["move-487"] - -[[steps]] -id = "move-489" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 489/1023)" -needs = ["move-488"] - -[[steps]] -id = "move-490" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 490/1023)" -needs = ["move-489"] - -[[steps]] -id = "move-491" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 491/1023)" -needs = ["move-490"] - -[[steps]] -id = "move-492" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 492/1023)" -needs = ["move-491"] - -[[steps]] -id = "move-493" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 493/1023)" -needs = ["move-492"] - -[[steps]] -id = "move-494" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 494/1023)" -needs = ["move-493"] - -[[steps]] -id = "move-495" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 495/1023)" -needs = ["move-494"] - -[[steps]] -id = "move-496" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 496/1023)" -needs = ["move-495"] - -[[steps]] -id = "move-497" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 497/1023)" -needs = ["move-496"] - -[[steps]] -id = "move-498" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 498/1023)" -needs = ["move-497"] - -[[steps]] -id = "move-499" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 499/1023)" -needs = ["move-498"] - -[[steps]] -id = "move-500" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 500/1023)" -needs = ["move-499"] - -[[steps]] -id = "move-501" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 501/1023)" -needs = ["move-500"] - -[[steps]] -id = "move-502" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 502/1023)" -needs = ["move-501"] - -[[steps]] -id = "move-503" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 503/1023)" -needs = ["move-502"] - -[[steps]] -id = "move-504" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 504/1023)" -needs = ["move-503"] - -[[steps]] -id = "move-505" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 505/1023)" -needs = ["move-504"] - -[[steps]] -id = "move-506" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 506/1023)" -needs = ["move-505"] - -[[steps]] -id = "move-507" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 507/1023)" -needs = ["move-506"] - -[[steps]] -id = "move-508" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 508/1023)" -needs = ["move-507"] - -[[steps]] -id = "move-509" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 509/1023)" -needs = ["move-508"] - -[[steps]] -id = "move-510" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 510/1023)" -needs = ["move-509"] - -[[steps]] -id = "move-511" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 511/1023)" -needs = ["move-510"] - -[[steps]] -id = "move-512" -title = "Move disk 10: A → C" -description = "Move disk 10 from peg A to peg C. (Move 512/1023)" -needs = ["move-511"] - -[[steps]] -id = "move-513" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 513/1023)" -needs = ["move-512"] - -[[steps]] -id = "move-514" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 514/1023)" -needs = ["move-513"] - -[[steps]] -id = "move-515" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 515/1023)" -needs = ["move-514"] - -[[steps]] -id = "move-516" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 516/1023)" -needs = ["move-515"] - -[[steps]] -id = "move-517" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 517/1023)" -needs = ["move-516"] - -[[steps]] -id = "move-518" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 518/1023)" -needs = ["move-517"] - -[[steps]] -id = "move-519" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 519/1023)" -needs = ["move-518"] - -[[steps]] -id = "move-520" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 520/1023)" -needs = ["move-519"] - -[[steps]] -id = "move-521" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 521/1023)" -needs = ["move-520"] - -[[steps]] -id = "move-522" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 522/1023)" -needs = ["move-521"] - -[[steps]] -id = "move-523" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 523/1023)" -needs = ["move-522"] - -[[steps]] -id = "move-524" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 524/1023)" -needs = ["move-523"] - -[[steps]] -id = "move-525" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 525/1023)" -needs = ["move-524"] - -[[steps]] -id = "move-526" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 526/1023)" -needs = ["move-525"] - -[[steps]] -id = "move-527" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 527/1023)" -needs = ["move-526"] - -[[steps]] -id = "move-528" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 528/1023)" -needs = ["move-527"] - -[[steps]] -id = "move-529" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 529/1023)" -needs = ["move-528"] - -[[steps]] -id = "move-530" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 530/1023)" -needs = ["move-529"] - -[[steps]] -id = "move-531" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 531/1023)" -needs = ["move-530"] - -[[steps]] -id = "move-532" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 532/1023)" -needs = ["move-531"] - -[[steps]] -id = "move-533" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 533/1023)" -needs = ["move-532"] - -[[steps]] -id = "move-534" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 534/1023)" -needs = ["move-533"] - -[[steps]] -id = "move-535" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 535/1023)" -needs = ["move-534"] - -[[steps]] -id = "move-536" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 536/1023)" -needs = ["move-535"] - -[[steps]] -id = "move-537" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 537/1023)" -needs = ["move-536"] - -[[steps]] -id = "move-538" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 538/1023)" -needs = ["move-537"] - -[[steps]] -id = "move-539" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 539/1023)" -needs = ["move-538"] - -[[steps]] -id = "move-540" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 540/1023)" -needs = ["move-539"] - -[[steps]] -id = "move-541" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 541/1023)" -needs = ["move-540"] - -[[steps]] -id = "move-542" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 542/1023)" -needs = ["move-541"] - -[[steps]] -id = "move-543" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 543/1023)" -needs = ["move-542"] - -[[steps]] -id = "move-544" -title = "Move disk 6: B → A" -description = "Move disk 6 from peg B to peg A. (Move 544/1023)" -needs = ["move-543"] - -[[steps]] -id = "move-545" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 545/1023)" -needs = ["move-544"] - -[[steps]] -id = "move-546" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 546/1023)" -needs = ["move-545"] - -[[steps]] -id = "move-547" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 547/1023)" -needs = ["move-546"] - -[[steps]] -id = "move-548" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 548/1023)" -needs = ["move-547"] - -[[steps]] -id = "move-549" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 549/1023)" -needs = ["move-548"] - -[[steps]] -id = "move-550" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 550/1023)" -needs = ["move-549"] - -[[steps]] -id = "move-551" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 551/1023)" -needs = ["move-550"] - -[[steps]] -id = "move-552" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 552/1023)" -needs = ["move-551"] - -[[steps]] -id = "move-553" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 553/1023)" -needs = ["move-552"] - -[[steps]] -id = "move-554" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 554/1023)" -needs = ["move-553"] - -[[steps]] -id = "move-555" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 555/1023)" -needs = ["move-554"] - -[[steps]] -id = "move-556" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 556/1023)" -needs = ["move-555"] - -[[steps]] -id = "move-557" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 557/1023)" -needs = ["move-556"] - -[[steps]] -id = "move-558" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 558/1023)" -needs = ["move-557"] - -[[steps]] -id = "move-559" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 559/1023)" -needs = ["move-558"] - -[[steps]] -id = "move-560" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 560/1023)" -needs = ["move-559"] - -[[steps]] -id = "move-561" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 561/1023)" -needs = ["move-560"] - -[[steps]] -id = "move-562" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 562/1023)" -needs = ["move-561"] - -[[steps]] -id = "move-563" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 563/1023)" -needs = ["move-562"] - -[[steps]] -id = "move-564" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 564/1023)" -needs = ["move-563"] - -[[steps]] -id = "move-565" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 565/1023)" -needs = ["move-564"] - -[[steps]] -id = "move-566" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 566/1023)" -needs = ["move-565"] - -[[steps]] -id = "move-567" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 567/1023)" -needs = ["move-566"] - -[[steps]] -id = "move-568" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 568/1023)" -needs = ["move-567"] - -[[steps]] -id = "move-569" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 569/1023)" -needs = ["move-568"] - -[[steps]] -id = "move-570" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 570/1023)" -needs = ["move-569"] - -[[steps]] -id = "move-571" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 571/1023)" -needs = ["move-570"] - -[[steps]] -id = "move-572" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 572/1023)" -needs = ["move-571"] - -[[steps]] -id = "move-573" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 573/1023)" -needs = ["move-572"] - -[[steps]] -id = "move-574" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 574/1023)" -needs = ["move-573"] - -[[steps]] -id = "move-575" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 575/1023)" -needs = ["move-574"] - -[[steps]] -id = "move-576" -title = "Move disk 7: B → C" -description = "Move disk 7 from peg B to peg C. (Move 576/1023)" -needs = ["move-575"] - -[[steps]] -id = "move-577" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 577/1023)" -needs = ["move-576"] - -[[steps]] -id = "move-578" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 578/1023)" -needs = ["move-577"] - -[[steps]] -id = "move-579" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 579/1023)" -needs = ["move-578"] - -[[steps]] -id = "move-580" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 580/1023)" -needs = ["move-579"] - -[[steps]] -id = "move-581" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 581/1023)" -needs = ["move-580"] - -[[steps]] -id = "move-582" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 582/1023)" -needs = ["move-581"] - -[[steps]] -id = "move-583" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 583/1023)" -needs = ["move-582"] - -[[steps]] -id = "move-584" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 584/1023)" -needs = ["move-583"] - -[[steps]] -id = "move-585" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 585/1023)" -needs = ["move-584"] - -[[steps]] -id = "move-586" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 586/1023)" -needs = ["move-585"] - -[[steps]] -id = "move-587" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 587/1023)" -needs = ["move-586"] - -[[steps]] -id = "move-588" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 588/1023)" -needs = ["move-587"] - -[[steps]] -id = "move-589" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 589/1023)" -needs = ["move-588"] - -[[steps]] -id = "move-590" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 590/1023)" -needs = ["move-589"] - -[[steps]] -id = "move-591" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 591/1023)" -needs = ["move-590"] - -[[steps]] -id = "move-592" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 592/1023)" -needs = ["move-591"] - -[[steps]] -id = "move-593" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 593/1023)" -needs = ["move-592"] - -[[steps]] -id = "move-594" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 594/1023)" -needs = ["move-593"] - -[[steps]] -id = "move-595" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 595/1023)" -needs = ["move-594"] - -[[steps]] -id = "move-596" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 596/1023)" -needs = ["move-595"] - -[[steps]] -id = "move-597" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 597/1023)" -needs = ["move-596"] - -[[steps]] -id = "move-598" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 598/1023)" -needs = ["move-597"] - -[[steps]] -id = "move-599" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 599/1023)" -needs = ["move-598"] - -[[steps]] -id = "move-600" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 600/1023)" -needs = ["move-599"] - -[[steps]] -id = "move-601" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 601/1023)" -needs = ["move-600"] - -[[steps]] -id = "move-602" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 602/1023)" -needs = ["move-601"] - -[[steps]] -id = "move-603" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 603/1023)" -needs = ["move-602"] - -[[steps]] -id = "move-604" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 604/1023)" -needs = ["move-603"] - -[[steps]] -id = "move-605" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 605/1023)" -needs = ["move-604"] - -[[steps]] -id = "move-606" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 606/1023)" -needs = ["move-605"] - -[[steps]] -id = "move-607" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 607/1023)" -needs = ["move-606"] - -[[steps]] -id = "move-608" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 608/1023)" -needs = ["move-607"] - -[[steps]] -id = "move-609" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 609/1023)" -needs = ["move-608"] - -[[steps]] -id = "move-610" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 610/1023)" -needs = ["move-609"] - -[[steps]] -id = "move-611" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 611/1023)" -needs = ["move-610"] - -[[steps]] -id = "move-612" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 612/1023)" -needs = ["move-611"] - -[[steps]] -id = "move-613" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 613/1023)" -needs = ["move-612"] - -[[steps]] -id = "move-614" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 614/1023)" -needs = ["move-613"] - -[[steps]] -id = "move-615" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 615/1023)" -needs = ["move-614"] - -[[steps]] -id = "move-616" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 616/1023)" -needs = ["move-615"] - -[[steps]] -id = "move-617" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 617/1023)" -needs = ["move-616"] - -[[steps]] -id = "move-618" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 618/1023)" -needs = ["move-617"] - -[[steps]] -id = "move-619" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 619/1023)" -needs = ["move-618"] - -[[steps]] -id = "move-620" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 620/1023)" -needs = ["move-619"] - -[[steps]] -id = "move-621" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 621/1023)" -needs = ["move-620"] - -[[steps]] -id = "move-622" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 622/1023)" -needs = ["move-621"] - -[[steps]] -id = "move-623" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 623/1023)" -needs = ["move-622"] - -[[steps]] -id = "move-624" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 624/1023)" -needs = ["move-623"] - -[[steps]] -id = "move-625" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 625/1023)" -needs = ["move-624"] - -[[steps]] -id = "move-626" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 626/1023)" -needs = ["move-625"] - -[[steps]] -id = "move-627" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 627/1023)" -needs = ["move-626"] - -[[steps]] -id = "move-628" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 628/1023)" -needs = ["move-627"] - -[[steps]] -id = "move-629" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 629/1023)" -needs = ["move-628"] - -[[steps]] -id = "move-630" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 630/1023)" -needs = ["move-629"] - -[[steps]] -id = "move-631" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 631/1023)" -needs = ["move-630"] - -[[steps]] -id = "move-632" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 632/1023)" -needs = ["move-631"] - -[[steps]] -id = "move-633" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 633/1023)" -needs = ["move-632"] - -[[steps]] -id = "move-634" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 634/1023)" -needs = ["move-633"] - -[[steps]] -id = "move-635" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 635/1023)" -needs = ["move-634"] - -[[steps]] -id = "move-636" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 636/1023)" -needs = ["move-635"] - -[[steps]] -id = "move-637" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 637/1023)" -needs = ["move-636"] - -[[steps]] -id = "move-638" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 638/1023)" -needs = ["move-637"] - -[[steps]] -id = "move-639" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 639/1023)" -needs = ["move-638"] - -[[steps]] -id = "move-640" -title = "Move disk 8: B → A" -description = "Move disk 8 from peg B to peg A. (Move 640/1023)" -needs = ["move-639"] - -[[steps]] -id = "move-641" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 641/1023)" -needs = ["move-640"] - -[[steps]] -id = "move-642" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 642/1023)" -needs = ["move-641"] - -[[steps]] -id = "move-643" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 643/1023)" -needs = ["move-642"] - -[[steps]] -id = "move-644" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 644/1023)" -needs = ["move-643"] - -[[steps]] -id = "move-645" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 645/1023)" -needs = ["move-644"] - -[[steps]] -id = "move-646" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 646/1023)" -needs = ["move-645"] - -[[steps]] -id = "move-647" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 647/1023)" -needs = ["move-646"] - -[[steps]] -id = "move-648" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 648/1023)" -needs = ["move-647"] - -[[steps]] -id = "move-649" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 649/1023)" -needs = ["move-648"] - -[[steps]] -id = "move-650" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 650/1023)" -needs = ["move-649"] - -[[steps]] -id = "move-651" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 651/1023)" -needs = ["move-650"] - -[[steps]] -id = "move-652" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 652/1023)" -needs = ["move-651"] - -[[steps]] -id = "move-653" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 653/1023)" -needs = ["move-652"] - -[[steps]] -id = "move-654" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 654/1023)" -needs = ["move-653"] - -[[steps]] -id = "move-655" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 655/1023)" -needs = ["move-654"] - -[[steps]] -id = "move-656" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 656/1023)" -needs = ["move-655"] - -[[steps]] -id = "move-657" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 657/1023)" -needs = ["move-656"] - -[[steps]] -id = "move-658" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 658/1023)" -needs = ["move-657"] - -[[steps]] -id = "move-659" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 659/1023)" -needs = ["move-658"] - -[[steps]] -id = "move-660" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 660/1023)" -needs = ["move-659"] - -[[steps]] -id = "move-661" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 661/1023)" -needs = ["move-660"] - -[[steps]] -id = "move-662" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 662/1023)" -needs = ["move-661"] - -[[steps]] -id = "move-663" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 663/1023)" -needs = ["move-662"] - -[[steps]] -id = "move-664" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 664/1023)" -needs = ["move-663"] - -[[steps]] -id = "move-665" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 665/1023)" -needs = ["move-664"] - -[[steps]] -id = "move-666" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 666/1023)" -needs = ["move-665"] - -[[steps]] -id = "move-667" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 667/1023)" -needs = ["move-666"] - -[[steps]] -id = "move-668" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 668/1023)" -needs = ["move-667"] - -[[steps]] -id = "move-669" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 669/1023)" -needs = ["move-668"] - -[[steps]] -id = "move-670" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 670/1023)" -needs = ["move-669"] - -[[steps]] -id = "move-671" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 671/1023)" -needs = ["move-670"] - -[[steps]] -id = "move-672" -title = "Move disk 6: C → B" -description = "Move disk 6 from peg C to peg B. (Move 672/1023)" -needs = ["move-671"] - -[[steps]] -id = "move-673" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 673/1023)" -needs = ["move-672"] - -[[steps]] -id = "move-674" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 674/1023)" -needs = ["move-673"] - -[[steps]] -id = "move-675" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 675/1023)" -needs = ["move-674"] - -[[steps]] -id = "move-676" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 676/1023)" -needs = ["move-675"] - -[[steps]] -id = "move-677" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 677/1023)" -needs = ["move-676"] - -[[steps]] -id = "move-678" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 678/1023)" -needs = ["move-677"] - -[[steps]] -id = "move-679" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 679/1023)" -needs = ["move-678"] - -[[steps]] -id = "move-680" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 680/1023)" -needs = ["move-679"] - -[[steps]] -id = "move-681" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 681/1023)" -needs = ["move-680"] - -[[steps]] -id = "move-682" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 682/1023)" -needs = ["move-681"] - -[[steps]] -id = "move-683" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 683/1023)" -needs = ["move-682"] - -[[steps]] -id = "move-684" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 684/1023)" -needs = ["move-683"] - -[[steps]] -id = "move-685" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 685/1023)" -needs = ["move-684"] - -[[steps]] -id = "move-686" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 686/1023)" -needs = ["move-685"] - -[[steps]] -id = "move-687" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 687/1023)" -needs = ["move-686"] - -[[steps]] -id = "move-688" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 688/1023)" -needs = ["move-687"] - -[[steps]] -id = "move-689" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 689/1023)" -needs = ["move-688"] - -[[steps]] -id = "move-690" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 690/1023)" -needs = ["move-689"] - -[[steps]] -id = "move-691" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 691/1023)" -needs = ["move-690"] - -[[steps]] -id = "move-692" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 692/1023)" -needs = ["move-691"] - -[[steps]] -id = "move-693" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 693/1023)" -needs = ["move-692"] - -[[steps]] -id = "move-694" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 694/1023)" -needs = ["move-693"] - -[[steps]] -id = "move-695" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 695/1023)" -needs = ["move-694"] - -[[steps]] -id = "move-696" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 696/1023)" -needs = ["move-695"] - -[[steps]] -id = "move-697" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 697/1023)" -needs = ["move-696"] - -[[steps]] -id = "move-698" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 698/1023)" -needs = ["move-697"] - -[[steps]] -id = "move-699" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 699/1023)" -needs = ["move-698"] - -[[steps]] -id = "move-700" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 700/1023)" -needs = ["move-699"] - -[[steps]] -id = "move-701" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 701/1023)" -needs = ["move-700"] - -[[steps]] -id = "move-702" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 702/1023)" -needs = ["move-701"] - -[[steps]] -id = "move-703" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 703/1023)" -needs = ["move-702"] - -[[steps]] -id = "move-704" -title = "Move disk 7: C → A" -description = "Move disk 7 from peg C to peg A. (Move 704/1023)" -needs = ["move-703"] - -[[steps]] -id = "move-705" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 705/1023)" -needs = ["move-704"] - -[[steps]] -id = "move-706" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 706/1023)" -needs = ["move-705"] - -[[steps]] -id = "move-707" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 707/1023)" -needs = ["move-706"] - -[[steps]] -id = "move-708" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 708/1023)" -needs = ["move-707"] - -[[steps]] -id = "move-709" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 709/1023)" -needs = ["move-708"] - -[[steps]] -id = "move-710" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 710/1023)" -needs = ["move-709"] - -[[steps]] -id = "move-711" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 711/1023)" -needs = ["move-710"] - -[[steps]] -id = "move-712" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 712/1023)" -needs = ["move-711"] - -[[steps]] -id = "move-713" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 713/1023)" -needs = ["move-712"] - -[[steps]] -id = "move-714" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 714/1023)" -needs = ["move-713"] - -[[steps]] -id = "move-715" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 715/1023)" -needs = ["move-714"] - -[[steps]] -id = "move-716" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 716/1023)" -needs = ["move-715"] - -[[steps]] -id = "move-717" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 717/1023)" -needs = ["move-716"] - -[[steps]] -id = "move-718" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 718/1023)" -needs = ["move-717"] - -[[steps]] -id = "move-719" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 719/1023)" -needs = ["move-718"] - -[[steps]] -id = "move-720" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 720/1023)" -needs = ["move-719"] - -[[steps]] -id = "move-721" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 721/1023)" -needs = ["move-720"] - -[[steps]] -id = "move-722" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 722/1023)" -needs = ["move-721"] - -[[steps]] -id = "move-723" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 723/1023)" -needs = ["move-722"] - -[[steps]] -id = "move-724" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 724/1023)" -needs = ["move-723"] - -[[steps]] -id = "move-725" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 725/1023)" -needs = ["move-724"] - -[[steps]] -id = "move-726" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 726/1023)" -needs = ["move-725"] - -[[steps]] -id = "move-727" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 727/1023)" -needs = ["move-726"] - -[[steps]] -id = "move-728" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 728/1023)" -needs = ["move-727"] - -[[steps]] -id = "move-729" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 729/1023)" -needs = ["move-728"] - -[[steps]] -id = "move-730" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 730/1023)" -needs = ["move-729"] - -[[steps]] -id = "move-731" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 731/1023)" -needs = ["move-730"] - -[[steps]] -id = "move-732" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 732/1023)" -needs = ["move-731"] - -[[steps]] -id = "move-733" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 733/1023)" -needs = ["move-732"] - -[[steps]] -id = "move-734" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 734/1023)" -needs = ["move-733"] - -[[steps]] -id = "move-735" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 735/1023)" -needs = ["move-734"] - -[[steps]] -id = "move-736" -title = "Move disk 6: B → A" -description = "Move disk 6 from peg B to peg A. (Move 736/1023)" -needs = ["move-735"] - -[[steps]] -id = "move-737" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 737/1023)" -needs = ["move-736"] - -[[steps]] -id = "move-738" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 738/1023)" -needs = ["move-737"] - -[[steps]] -id = "move-739" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 739/1023)" -needs = ["move-738"] - -[[steps]] -id = "move-740" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 740/1023)" -needs = ["move-739"] - -[[steps]] -id = "move-741" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 741/1023)" -needs = ["move-740"] - -[[steps]] -id = "move-742" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 742/1023)" -needs = ["move-741"] - -[[steps]] -id = "move-743" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 743/1023)" -needs = ["move-742"] - -[[steps]] -id = "move-744" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 744/1023)" -needs = ["move-743"] - -[[steps]] -id = "move-745" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 745/1023)" -needs = ["move-744"] - -[[steps]] -id = "move-746" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 746/1023)" -needs = ["move-745"] - -[[steps]] -id = "move-747" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 747/1023)" -needs = ["move-746"] - -[[steps]] -id = "move-748" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 748/1023)" -needs = ["move-747"] - -[[steps]] -id = "move-749" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 749/1023)" -needs = ["move-748"] - -[[steps]] -id = "move-750" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 750/1023)" -needs = ["move-749"] - -[[steps]] -id = "move-751" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 751/1023)" -needs = ["move-750"] - -[[steps]] -id = "move-752" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 752/1023)" -needs = ["move-751"] - -[[steps]] -id = "move-753" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 753/1023)" -needs = ["move-752"] - -[[steps]] -id = "move-754" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 754/1023)" -needs = ["move-753"] - -[[steps]] -id = "move-755" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 755/1023)" -needs = ["move-754"] - -[[steps]] -id = "move-756" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 756/1023)" -needs = ["move-755"] - -[[steps]] -id = "move-757" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 757/1023)" -needs = ["move-756"] - -[[steps]] -id = "move-758" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 758/1023)" -needs = ["move-757"] - -[[steps]] -id = "move-759" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 759/1023)" -needs = ["move-758"] - -[[steps]] -id = "move-760" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 760/1023)" -needs = ["move-759"] - -[[steps]] -id = "move-761" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 761/1023)" -needs = ["move-760"] - -[[steps]] -id = "move-762" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 762/1023)" -needs = ["move-761"] - -[[steps]] -id = "move-763" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 763/1023)" -needs = ["move-762"] - -[[steps]] -id = "move-764" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 764/1023)" -needs = ["move-763"] - -[[steps]] -id = "move-765" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 765/1023)" -needs = ["move-764"] - -[[steps]] -id = "move-766" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 766/1023)" -needs = ["move-765"] - -[[steps]] -id = "move-767" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 767/1023)" -needs = ["move-766"] - -[[steps]] -id = "move-768" -title = "Move disk 9: B → C" -description = "Move disk 9 from peg B to peg C. (Move 768/1023)" -needs = ["move-767"] - -[[steps]] -id = "move-769" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 769/1023)" -needs = ["move-768"] - -[[steps]] -id = "move-770" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 770/1023)" -needs = ["move-769"] - -[[steps]] -id = "move-771" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 771/1023)" -needs = ["move-770"] - -[[steps]] -id = "move-772" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 772/1023)" -needs = ["move-771"] - -[[steps]] -id = "move-773" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 773/1023)" -needs = ["move-772"] - -[[steps]] -id = "move-774" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 774/1023)" -needs = ["move-773"] - -[[steps]] -id = "move-775" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 775/1023)" -needs = ["move-774"] - -[[steps]] -id = "move-776" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 776/1023)" -needs = ["move-775"] - -[[steps]] -id = "move-777" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 777/1023)" -needs = ["move-776"] - -[[steps]] -id = "move-778" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 778/1023)" -needs = ["move-777"] - -[[steps]] -id = "move-779" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 779/1023)" -needs = ["move-778"] - -[[steps]] -id = "move-780" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 780/1023)" -needs = ["move-779"] - -[[steps]] -id = "move-781" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 781/1023)" -needs = ["move-780"] - -[[steps]] -id = "move-782" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 782/1023)" -needs = ["move-781"] - -[[steps]] -id = "move-783" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 783/1023)" -needs = ["move-782"] - -[[steps]] -id = "move-784" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 784/1023)" -needs = ["move-783"] - -[[steps]] -id = "move-785" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 785/1023)" -needs = ["move-784"] - -[[steps]] -id = "move-786" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 786/1023)" -needs = ["move-785"] - -[[steps]] -id = "move-787" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 787/1023)" -needs = ["move-786"] - -[[steps]] -id = "move-788" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 788/1023)" -needs = ["move-787"] - -[[steps]] -id = "move-789" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 789/1023)" -needs = ["move-788"] - -[[steps]] -id = "move-790" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 790/1023)" -needs = ["move-789"] - -[[steps]] -id = "move-791" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 791/1023)" -needs = ["move-790"] - -[[steps]] -id = "move-792" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 792/1023)" -needs = ["move-791"] - -[[steps]] -id = "move-793" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 793/1023)" -needs = ["move-792"] - -[[steps]] -id = "move-794" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 794/1023)" -needs = ["move-793"] - -[[steps]] -id = "move-795" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 795/1023)" -needs = ["move-794"] - -[[steps]] -id = "move-796" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 796/1023)" -needs = ["move-795"] - -[[steps]] -id = "move-797" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 797/1023)" -needs = ["move-796"] - -[[steps]] -id = "move-798" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 798/1023)" -needs = ["move-797"] - -[[steps]] -id = "move-799" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 799/1023)" -needs = ["move-798"] - -[[steps]] -id = "move-800" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 800/1023)" -needs = ["move-799"] - -[[steps]] -id = "move-801" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 801/1023)" -needs = ["move-800"] - -[[steps]] -id = "move-802" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 802/1023)" -needs = ["move-801"] - -[[steps]] -id = "move-803" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 803/1023)" -needs = ["move-802"] - -[[steps]] -id = "move-804" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 804/1023)" -needs = ["move-803"] - -[[steps]] -id = "move-805" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 805/1023)" -needs = ["move-804"] - -[[steps]] -id = "move-806" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 806/1023)" -needs = ["move-805"] - -[[steps]] -id = "move-807" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 807/1023)" -needs = ["move-806"] - -[[steps]] -id = "move-808" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 808/1023)" -needs = ["move-807"] - -[[steps]] -id = "move-809" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 809/1023)" -needs = ["move-808"] - -[[steps]] -id = "move-810" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 810/1023)" -needs = ["move-809"] - -[[steps]] -id = "move-811" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 811/1023)" -needs = ["move-810"] - -[[steps]] -id = "move-812" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 812/1023)" -needs = ["move-811"] - -[[steps]] -id = "move-813" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 813/1023)" -needs = ["move-812"] - -[[steps]] -id = "move-814" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 814/1023)" -needs = ["move-813"] - -[[steps]] -id = "move-815" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 815/1023)" -needs = ["move-814"] - -[[steps]] -id = "move-816" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 816/1023)" -needs = ["move-815"] - -[[steps]] -id = "move-817" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 817/1023)" -needs = ["move-816"] - -[[steps]] -id = "move-818" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 818/1023)" -needs = ["move-817"] - -[[steps]] -id = "move-819" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 819/1023)" -needs = ["move-818"] - -[[steps]] -id = "move-820" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 820/1023)" -needs = ["move-819"] - -[[steps]] -id = "move-821" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 821/1023)" -needs = ["move-820"] - -[[steps]] -id = "move-822" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 822/1023)" -needs = ["move-821"] - -[[steps]] -id = "move-823" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 823/1023)" -needs = ["move-822"] - -[[steps]] -id = "move-824" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 824/1023)" -needs = ["move-823"] - -[[steps]] -id = "move-825" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 825/1023)" -needs = ["move-824"] - -[[steps]] -id = "move-826" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 826/1023)" -needs = ["move-825"] - -[[steps]] -id = "move-827" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 827/1023)" -needs = ["move-826"] - -[[steps]] -id = "move-828" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 828/1023)" -needs = ["move-827"] - -[[steps]] -id = "move-829" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 829/1023)" -needs = ["move-828"] - -[[steps]] -id = "move-830" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 830/1023)" -needs = ["move-829"] - -[[steps]] -id = "move-831" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 831/1023)" -needs = ["move-830"] - -[[steps]] -id = "move-832" -title = "Move disk 7: A → B" -description = "Move disk 7 from peg A to peg B. (Move 832/1023)" -needs = ["move-831"] - -[[steps]] -id = "move-833" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 833/1023)" -needs = ["move-832"] - -[[steps]] -id = "move-834" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 834/1023)" -needs = ["move-833"] - -[[steps]] -id = "move-835" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 835/1023)" -needs = ["move-834"] - -[[steps]] -id = "move-836" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 836/1023)" -needs = ["move-835"] - -[[steps]] -id = "move-837" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 837/1023)" -needs = ["move-836"] - -[[steps]] -id = "move-838" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 838/1023)" -needs = ["move-837"] - -[[steps]] -id = "move-839" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 839/1023)" -needs = ["move-838"] - -[[steps]] -id = "move-840" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 840/1023)" -needs = ["move-839"] - -[[steps]] -id = "move-841" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 841/1023)" -needs = ["move-840"] - -[[steps]] -id = "move-842" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 842/1023)" -needs = ["move-841"] - -[[steps]] -id = "move-843" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 843/1023)" -needs = ["move-842"] - -[[steps]] -id = "move-844" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 844/1023)" -needs = ["move-843"] - -[[steps]] -id = "move-845" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 845/1023)" -needs = ["move-844"] - -[[steps]] -id = "move-846" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 846/1023)" -needs = ["move-845"] - -[[steps]] -id = "move-847" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 847/1023)" -needs = ["move-846"] - -[[steps]] -id = "move-848" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 848/1023)" -needs = ["move-847"] - -[[steps]] -id = "move-849" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 849/1023)" -needs = ["move-848"] - -[[steps]] -id = "move-850" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 850/1023)" -needs = ["move-849"] - -[[steps]] -id = "move-851" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 851/1023)" -needs = ["move-850"] - -[[steps]] -id = "move-852" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 852/1023)" -needs = ["move-851"] - -[[steps]] -id = "move-853" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 853/1023)" -needs = ["move-852"] - -[[steps]] -id = "move-854" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 854/1023)" -needs = ["move-853"] - -[[steps]] -id = "move-855" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 855/1023)" -needs = ["move-854"] - -[[steps]] -id = "move-856" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 856/1023)" -needs = ["move-855"] - -[[steps]] -id = "move-857" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 857/1023)" -needs = ["move-856"] - -[[steps]] -id = "move-858" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 858/1023)" -needs = ["move-857"] - -[[steps]] -id = "move-859" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 859/1023)" -needs = ["move-858"] - -[[steps]] -id = "move-860" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 860/1023)" -needs = ["move-859"] - -[[steps]] -id = "move-861" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 861/1023)" -needs = ["move-860"] - -[[steps]] -id = "move-862" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 862/1023)" -needs = ["move-861"] - -[[steps]] -id = "move-863" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 863/1023)" -needs = ["move-862"] - -[[steps]] -id = "move-864" -title = "Move disk 6: C → B" -description = "Move disk 6 from peg C to peg B. (Move 864/1023)" -needs = ["move-863"] - -[[steps]] -id = "move-865" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 865/1023)" -needs = ["move-864"] - -[[steps]] -id = "move-866" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 866/1023)" -needs = ["move-865"] - -[[steps]] -id = "move-867" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 867/1023)" -needs = ["move-866"] - -[[steps]] -id = "move-868" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 868/1023)" -needs = ["move-867"] - -[[steps]] -id = "move-869" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 869/1023)" -needs = ["move-868"] - -[[steps]] -id = "move-870" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 870/1023)" -needs = ["move-869"] - -[[steps]] -id = "move-871" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 871/1023)" -needs = ["move-870"] - -[[steps]] -id = "move-872" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 872/1023)" -needs = ["move-871"] - -[[steps]] -id = "move-873" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 873/1023)" -needs = ["move-872"] - -[[steps]] -id = "move-874" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 874/1023)" -needs = ["move-873"] - -[[steps]] -id = "move-875" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 875/1023)" -needs = ["move-874"] - -[[steps]] -id = "move-876" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 876/1023)" -needs = ["move-875"] - -[[steps]] -id = "move-877" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 877/1023)" -needs = ["move-876"] - -[[steps]] -id = "move-878" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 878/1023)" -needs = ["move-877"] - -[[steps]] -id = "move-879" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 879/1023)" -needs = ["move-878"] - -[[steps]] -id = "move-880" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 880/1023)" -needs = ["move-879"] - -[[steps]] -id = "move-881" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 881/1023)" -needs = ["move-880"] - -[[steps]] -id = "move-882" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 882/1023)" -needs = ["move-881"] - -[[steps]] -id = "move-883" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 883/1023)" -needs = ["move-882"] - -[[steps]] -id = "move-884" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 884/1023)" -needs = ["move-883"] - -[[steps]] -id = "move-885" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 885/1023)" -needs = ["move-884"] - -[[steps]] -id = "move-886" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 886/1023)" -needs = ["move-885"] - -[[steps]] -id = "move-887" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 887/1023)" -needs = ["move-886"] - -[[steps]] -id = "move-888" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 888/1023)" -needs = ["move-887"] - -[[steps]] -id = "move-889" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 889/1023)" -needs = ["move-888"] - -[[steps]] -id = "move-890" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 890/1023)" -needs = ["move-889"] - -[[steps]] -id = "move-891" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 891/1023)" -needs = ["move-890"] - -[[steps]] -id = "move-892" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 892/1023)" -needs = ["move-891"] - -[[steps]] -id = "move-893" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 893/1023)" -needs = ["move-892"] - -[[steps]] -id = "move-894" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 894/1023)" -needs = ["move-893"] - -[[steps]] -id = "move-895" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 895/1023)" -needs = ["move-894"] - -[[steps]] -id = "move-896" -title = "Move disk 8: A → C" -description = "Move disk 8 from peg A to peg C. (Move 896/1023)" -needs = ["move-895"] - -[[steps]] -id = "move-897" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 897/1023)" -needs = ["move-896"] - -[[steps]] -id = "move-898" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 898/1023)" -needs = ["move-897"] - -[[steps]] -id = "move-899" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 899/1023)" -needs = ["move-898"] - -[[steps]] -id = "move-900" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 900/1023)" -needs = ["move-899"] - -[[steps]] -id = "move-901" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 901/1023)" -needs = ["move-900"] - -[[steps]] -id = "move-902" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 902/1023)" -needs = ["move-901"] - -[[steps]] -id = "move-903" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 903/1023)" -needs = ["move-902"] - -[[steps]] -id = "move-904" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 904/1023)" -needs = ["move-903"] - -[[steps]] -id = "move-905" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 905/1023)" -needs = ["move-904"] - -[[steps]] -id = "move-906" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 906/1023)" -needs = ["move-905"] - -[[steps]] -id = "move-907" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 907/1023)" -needs = ["move-906"] - -[[steps]] -id = "move-908" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 908/1023)" -needs = ["move-907"] - -[[steps]] -id = "move-909" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 909/1023)" -needs = ["move-908"] - -[[steps]] -id = "move-910" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 910/1023)" -needs = ["move-909"] - -[[steps]] -id = "move-911" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 911/1023)" -needs = ["move-910"] - -[[steps]] -id = "move-912" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 912/1023)" -needs = ["move-911"] - -[[steps]] -id = "move-913" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 913/1023)" -needs = ["move-912"] - -[[steps]] -id = "move-914" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 914/1023)" -needs = ["move-913"] - -[[steps]] -id = "move-915" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 915/1023)" -needs = ["move-914"] - -[[steps]] -id = "move-916" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 916/1023)" -needs = ["move-915"] - -[[steps]] -id = "move-917" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 917/1023)" -needs = ["move-916"] - -[[steps]] -id = "move-918" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 918/1023)" -needs = ["move-917"] - -[[steps]] -id = "move-919" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 919/1023)" -needs = ["move-918"] - -[[steps]] -id = "move-920" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 920/1023)" -needs = ["move-919"] - -[[steps]] -id = "move-921" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 921/1023)" -needs = ["move-920"] - -[[steps]] -id = "move-922" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 922/1023)" -needs = ["move-921"] - -[[steps]] -id = "move-923" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 923/1023)" -needs = ["move-922"] - -[[steps]] -id = "move-924" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 924/1023)" -needs = ["move-923"] - -[[steps]] -id = "move-925" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 925/1023)" -needs = ["move-924"] - -[[steps]] -id = "move-926" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 926/1023)" -needs = ["move-925"] - -[[steps]] -id = "move-927" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 927/1023)" -needs = ["move-926"] - -[[steps]] -id = "move-928" -title = "Move disk 6: B → A" -description = "Move disk 6 from peg B to peg A. (Move 928/1023)" -needs = ["move-927"] - -[[steps]] -id = "move-929" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 929/1023)" -needs = ["move-928"] - -[[steps]] -id = "move-930" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 930/1023)" -needs = ["move-929"] - -[[steps]] -id = "move-931" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 931/1023)" -needs = ["move-930"] - -[[steps]] -id = "move-932" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 932/1023)" -needs = ["move-931"] - -[[steps]] -id = "move-933" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 933/1023)" -needs = ["move-932"] - -[[steps]] -id = "move-934" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 934/1023)" -needs = ["move-933"] - -[[steps]] -id = "move-935" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 935/1023)" -needs = ["move-934"] - -[[steps]] -id = "move-936" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 936/1023)" -needs = ["move-935"] - -[[steps]] -id = "move-937" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 937/1023)" -needs = ["move-936"] - -[[steps]] -id = "move-938" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 938/1023)" -needs = ["move-937"] - -[[steps]] -id = "move-939" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 939/1023)" -needs = ["move-938"] - -[[steps]] -id = "move-940" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 940/1023)" -needs = ["move-939"] - -[[steps]] -id = "move-941" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 941/1023)" -needs = ["move-940"] - -[[steps]] -id = "move-942" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 942/1023)" -needs = ["move-941"] - -[[steps]] -id = "move-943" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 943/1023)" -needs = ["move-942"] - -[[steps]] -id = "move-944" -title = "Move disk 5: C → A" -description = "Move disk 5 from peg C to peg A. (Move 944/1023)" -needs = ["move-943"] - -[[steps]] -id = "move-945" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 945/1023)" -needs = ["move-944"] - -[[steps]] -id = "move-946" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 946/1023)" -needs = ["move-945"] - -[[steps]] -id = "move-947" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 947/1023)" -needs = ["move-946"] - -[[steps]] -id = "move-948" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 948/1023)" -needs = ["move-947"] - -[[steps]] -id = "move-949" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 949/1023)" -needs = ["move-948"] - -[[steps]] -id = "move-950" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 950/1023)" -needs = ["move-949"] - -[[steps]] -id = "move-951" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 951/1023)" -needs = ["move-950"] - -[[steps]] -id = "move-952" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 952/1023)" -needs = ["move-951"] - -[[steps]] -id = "move-953" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 953/1023)" -needs = ["move-952"] - -[[steps]] -id = "move-954" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 954/1023)" -needs = ["move-953"] - -[[steps]] -id = "move-955" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 955/1023)" -needs = ["move-954"] - -[[steps]] -id = "move-956" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 956/1023)" -needs = ["move-955"] - -[[steps]] -id = "move-957" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 957/1023)" -needs = ["move-956"] - -[[steps]] -id = "move-958" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 958/1023)" -needs = ["move-957"] - -[[steps]] -id = "move-959" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 959/1023)" -needs = ["move-958"] - -[[steps]] -id = "move-960" -title = "Move disk 7: B → C" -description = "Move disk 7 from peg B to peg C. (Move 960/1023)" -needs = ["move-959"] - -[[steps]] -id = "move-961" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 961/1023)" -needs = ["move-960"] - -[[steps]] -id = "move-962" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 962/1023)" -needs = ["move-961"] - -[[steps]] -id = "move-963" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 963/1023)" -needs = ["move-962"] - -[[steps]] -id = "move-964" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 964/1023)" -needs = ["move-963"] - -[[steps]] -id = "move-965" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 965/1023)" -needs = ["move-964"] - -[[steps]] -id = "move-966" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 966/1023)" -needs = ["move-965"] - -[[steps]] -id = "move-967" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 967/1023)" -needs = ["move-966"] - -[[steps]] -id = "move-968" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 968/1023)" -needs = ["move-967"] - -[[steps]] -id = "move-969" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 969/1023)" -needs = ["move-968"] - -[[steps]] -id = "move-970" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 970/1023)" -needs = ["move-969"] - -[[steps]] -id = "move-971" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 971/1023)" -needs = ["move-970"] - -[[steps]] -id = "move-972" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 972/1023)" -needs = ["move-971"] - -[[steps]] -id = "move-973" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 973/1023)" -needs = ["move-972"] - -[[steps]] -id = "move-974" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 974/1023)" -needs = ["move-973"] - -[[steps]] -id = "move-975" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 975/1023)" -needs = ["move-974"] - -[[steps]] -id = "move-976" -title = "Move disk 5: A → B" -description = "Move disk 5 from peg A to peg B. (Move 976/1023)" -needs = ["move-975"] - -[[steps]] -id = "move-977" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 977/1023)" -needs = ["move-976"] - -[[steps]] -id = "move-978" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 978/1023)" -needs = ["move-977"] - -[[steps]] -id = "move-979" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 979/1023)" -needs = ["move-978"] - -[[steps]] -id = "move-980" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 980/1023)" -needs = ["move-979"] - -[[steps]] -id = "move-981" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 981/1023)" -needs = ["move-980"] - -[[steps]] -id = "move-982" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 982/1023)" -needs = ["move-981"] - -[[steps]] -id = "move-983" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 983/1023)" -needs = ["move-982"] - -[[steps]] -id = "move-984" -title = "Move disk 4: C → B" -description = "Move disk 4 from peg C to peg B. (Move 984/1023)" -needs = ["move-983"] - -[[steps]] -id = "move-985" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 985/1023)" -needs = ["move-984"] - -[[steps]] -id = "move-986" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 986/1023)" -needs = ["move-985"] - -[[steps]] -id = "move-987" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 987/1023)" -needs = ["move-986"] - -[[steps]] -id = "move-988" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 988/1023)" -needs = ["move-987"] - -[[steps]] -id = "move-989" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 989/1023)" -needs = ["move-988"] - -[[steps]] -id = "move-990" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 990/1023)" -needs = ["move-989"] - -[[steps]] -id = "move-991" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 991/1023)" -needs = ["move-990"] - -[[steps]] -id = "move-992" -title = "Move disk 6: A → C" -description = "Move disk 6 from peg A to peg C. (Move 992/1023)" -needs = ["move-991"] - -[[steps]] -id = "move-993" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 993/1023)" -needs = ["move-992"] - -[[steps]] -id = "move-994" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 994/1023)" -needs = ["move-993"] - -[[steps]] -id = "move-995" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 995/1023)" -needs = ["move-994"] - -[[steps]] -id = "move-996" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 996/1023)" -needs = ["move-995"] - -[[steps]] -id = "move-997" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 997/1023)" -needs = ["move-996"] - -[[steps]] -id = "move-998" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 998/1023)" -needs = ["move-997"] - -[[steps]] -id = "move-999" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 999/1023)" -needs = ["move-998"] - -[[steps]] -id = "move-1000" -title = "Move disk 4: B → A" -description = "Move disk 4 from peg B to peg A. (Move 1000/1023)" -needs = ["move-999"] - -[[steps]] -id = "move-1001" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 1001/1023)" -needs = ["move-1000"] - -[[steps]] -id = "move-1002" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 1002/1023)" -needs = ["move-1001"] - -[[steps]] -id = "move-1003" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 1003/1023)" -needs = ["move-1002"] - -[[steps]] -id = "move-1004" -title = "Move disk 3: C → A" -description = "Move disk 3 from peg C to peg A. (Move 1004/1023)" -needs = ["move-1003"] - -[[steps]] -id = "move-1005" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 1005/1023)" -needs = ["move-1004"] - -[[steps]] -id = "move-1006" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 1006/1023)" -needs = ["move-1005"] - -[[steps]] -id = "move-1007" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 1007/1023)" -needs = ["move-1006"] - -[[steps]] -id = "move-1008" -title = "Move disk 5: B → C" -description = "Move disk 5 from peg B to peg C. (Move 1008/1023)" -needs = ["move-1007"] - -[[steps]] -id = "move-1009" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 1009/1023)" -needs = ["move-1008"] - -[[steps]] -id = "move-1010" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 1010/1023)" -needs = ["move-1009"] - -[[steps]] -id = "move-1011" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 1011/1023)" -needs = ["move-1010"] - -[[steps]] -id = "move-1012" -title = "Move disk 3: A → B" -description = "Move disk 3 from peg A to peg B. (Move 1012/1023)" -needs = ["move-1011"] - -[[steps]] -id = "move-1013" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 1013/1023)" -needs = ["move-1012"] - -[[steps]] -id = "move-1014" -title = "Move disk 2: C → B" -description = "Move disk 2 from peg C to peg B. (Move 1014/1023)" -needs = ["move-1013"] - -[[steps]] -id = "move-1015" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 1015/1023)" -needs = ["move-1014"] - -[[steps]] -id = "move-1016" -title = "Move disk 4: A → C" -description = "Move disk 4 from peg A to peg C. (Move 1016/1023)" -needs = ["move-1015"] - -[[steps]] -id = "move-1017" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 1017/1023)" -needs = ["move-1016"] - -[[steps]] -id = "move-1018" -title = "Move disk 2: B → A" -description = "Move disk 2 from peg B to peg A. (Move 1018/1023)" -needs = ["move-1017"] - -[[steps]] -id = "move-1019" -title = "Move disk 1: C → A" -description = "Move disk 1 from peg C to peg A. (Move 1019/1023)" -needs = ["move-1018"] - -[[steps]] -id = "move-1020" -title = "Move disk 3: B → C" -description = "Move disk 3 from peg B to peg C. (Move 1020/1023)" -needs = ["move-1019"] - -[[steps]] -id = "move-1021" -title = "Move disk 1: A → B" -description = "Move disk 1 from peg A to peg B. (Move 1021/1023)" -needs = ["move-1020"] - -[[steps]] -id = "move-1022" -title = "Move disk 2: A → C" -description = "Move disk 2 from peg A to peg C. (Move 1022/1023)" -needs = ["move-1021"] - -[[steps]] -id = "move-1023" -title = "Move disk 1: B → C" -description = "Move disk 1 from peg B to peg C. (Move 1023/1023)" -needs = ["move-1022"] - -[[steps]] -id = "verify" -title = "Verify final state" -description = "All 10 disks now on peg C. Tower intact, all moves were legal." -needs = ["move-1023"] diff --git a/.beads/formulas/towers-of-hanoi-7.formula.toml b/.beads/formulas/towers-of-hanoi-7.formula.toml deleted file mode 100644 index 4ae41674a..000000000 --- a/.beads/formulas/towers-of-hanoi-7.formula.toml +++ /dev/null @@ -1,812 +0,0 @@ -description = """ -AGENT EXECUTION PROTOCOL - Towers of Hanoi (7 disks, 127 moves) - -PURPOSE: This is a durability proof, not computation. Steps are pre-computed. -Your job is to execute them mechanically, proving crash-recovery at scale. - -EXECUTION LOOP: -1. Find current state: bd mol current -2. Find the next ready (unblocked) step -3. Close it: bd close -4. Repeat until no ready steps remain - -ON RESUME (after crash/restart/handoff): -- Same as fresh start. The molecule IS the state. -- Query `bd mol current `, continue from there. -- No memory of previous session needed. - -DO: -- Close steps as fast as possible (they're trivial mechanical moves) -- Use `gt handoff` when context fills (proactive cycling) -- Trust the pre-computed solution - every move is already correct - -DO NOT: -- Try to solve Hanoi yourself - moves are already computed -- Mark steps in_progress - just close them directly -- Ask for permission - this is GUPP territory, just execute -- Stop for human input - run autonomously until complete - -MONITORING: -- Progress: Count closed children of the molecule -- For mega-molecules: Use convoy dashboard when available -- Completion: All steps closed = molecule complete - -This proves Gas Town can execute arbitrarily long workflows with -nondeterministic idempotence - different sessions, same outcome. -""" -formula = "towers-of-hanoi-7" -version = 1 - -[[steps]] -id = "setup" -title = "Verify initial state" -description = "All 7 disks stacked on peg A. Largest on bottom." - - -[[steps]] -id = "move-1" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 1/127)" -needs = ["setup"] - -[[steps]] -id = "move-2" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 2/127)" -needs = ["move-1"] - -[[steps]] -id = "move-3" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 3/127)" -needs = ["move-2"] - -[[steps]] -id = "move-4" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 4/127)" -needs = ["move-3"] - -[[steps]] -id = "move-5" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 5/127)" -needs = ["move-4"] - -[[steps]] -id = "move-6" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 6/127)" -needs = ["move-5"] - -[[steps]] -id = "move-7" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 7/127)" -needs = ["move-6"] - -[[steps]] -id = "move-8" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 8/127)" -needs = ["move-7"] - -[[steps]] -id = "move-9" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 9/127)" -needs = ["move-8"] - -[[steps]] -id = "move-10" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 10/127)" -needs = ["move-9"] - -[[steps]] -id = "move-11" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 11/127)" -needs = ["move-10"] - -[[steps]] -id = "move-12" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 12/127)" -needs = ["move-11"] - -[[steps]] -id = "move-13" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 13/127)" -needs = ["move-12"] - -[[steps]] -id = "move-14" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 14/127)" -needs = ["move-13"] - -[[steps]] -id = "move-15" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 15/127)" -needs = ["move-14"] - -[[steps]] -id = "move-16" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 16/127)" -needs = ["move-15"] - -[[steps]] -id = "move-17" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 17/127)" -needs = ["move-16"] - -[[steps]] -id = "move-18" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 18/127)" -needs = ["move-17"] - -[[steps]] -id = "move-19" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 19/127)" -needs = ["move-18"] - -[[steps]] -id = "move-20" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 20/127)" -needs = ["move-19"] - -[[steps]] -id = "move-21" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 21/127)" -needs = ["move-20"] - -[[steps]] -id = "move-22" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 22/127)" -needs = ["move-21"] - -[[steps]] -id = "move-23" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 23/127)" -needs = ["move-22"] - -[[steps]] -id = "move-24" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 24/127)" -needs = ["move-23"] - -[[steps]] -id = "move-25" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 25/127)" -needs = ["move-24"] - -[[steps]] -id = "move-26" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 26/127)" -needs = ["move-25"] - -[[steps]] -id = "move-27" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 27/127)" -needs = ["move-26"] - -[[steps]] -id = "move-28" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 28/127)" -needs = ["move-27"] - -[[steps]] -id = "move-29" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 29/127)" -needs = ["move-28"] - -[[steps]] -id = "move-30" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 30/127)" -needs = ["move-29"] - -[[steps]] -id = "move-31" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 31/127)" -needs = ["move-30"] - -[[steps]] -id = "move-32" -title = "Move disk 6: A → B" -description = "Move disk 6 from peg A to peg B. (Move 32/127)" -needs = ["move-31"] - -[[steps]] -id = "move-33" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 33/127)" -needs = ["move-32"] - -[[steps]] -id = "move-34" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 34/127)" -needs = ["move-33"] - -[[steps]] -id = "move-35" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 35/127)" -needs = ["move-34"] - -[[steps]] -id = "move-36" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 36/127)" -needs = ["move-35"] - -[[steps]] -id = "move-37" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 37/127)" -needs = ["move-36"] - -[[steps]] -id = "move-38" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 38/127)" -needs = ["move-37"] - -[[steps]] -id = "move-39" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 39/127)" -needs = ["move-38"] - -[[steps]] -id = "move-40" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 40/127)" -needs = ["move-39"] - -[[steps]] -id = "move-41" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 41/127)" -needs = ["move-40"] - -[[steps]] -id = "move-42" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 42/127)" -needs = ["move-41"] - -[[steps]] -id = "move-43" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 43/127)" -needs = ["move-42"] - -[[steps]] -id = "move-44" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 44/127)" -needs = ["move-43"] - -[[steps]] -id = "move-45" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 45/127)" -needs = ["move-44"] - -[[steps]] -id = "move-46" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 46/127)" -needs = ["move-45"] - -[[steps]] -id = "move-47" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 47/127)" -needs = ["move-46"] - -[[steps]] -id = "move-48" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 48/127)" -needs = ["move-47"] - -[[steps]] -id = "move-49" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 49/127)" -needs = ["move-48"] - -[[steps]] -id = "move-50" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 50/127)" -needs = ["move-49"] - -[[steps]] -id = "move-51" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 51/127)" -needs = ["move-50"] - -[[steps]] -id = "move-52" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 52/127)" -needs = ["move-51"] - -[[steps]] -id = "move-53" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 53/127)" -needs = ["move-52"] - -[[steps]] -id = "move-54" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 54/127)" -needs = ["move-53"] - -[[steps]] -id = "move-55" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 55/127)" -needs = ["move-54"] - -[[steps]] -id = "move-56" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 56/127)" -needs = ["move-55"] - -[[steps]] -id = "move-57" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 57/127)" -needs = ["move-56"] - -[[steps]] -id = "move-58" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 58/127)" -needs = ["move-57"] - -[[steps]] -id = "move-59" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 59/127)" -needs = ["move-58"] - -[[steps]] -id = "move-60" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 60/127)" -needs = ["move-59"] - -[[steps]] -id = "move-61" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 61/127)" -needs = ["move-60"] - -[[steps]] -id = "move-62" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 62/127)" -needs = ["move-61"] - -[[steps]] -id = "move-63" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 63/127)" -needs = ["move-62"] - -[[steps]] -id = "move-64" -title = "Move disk 7: A → C" -description = "Move disk 7 from peg A to peg C. (Move 64/127)" -needs = ["move-63"] - -[[steps]] -id = "move-65" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 65/127)" -needs = ["move-64"] - -[[steps]] -id = "move-66" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 66/127)" -needs = ["move-65"] - -[[steps]] -id = "move-67" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 67/127)" -needs = ["move-66"] - -[[steps]] -id = "move-68" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 68/127)" -needs = ["move-67"] - -[[steps]] -id = "move-69" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 69/127)" -needs = ["move-68"] - -[[steps]] -id = "move-70" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 70/127)" -needs = ["move-69"] - -[[steps]] -id = "move-71" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 71/127)" -needs = ["move-70"] - -[[steps]] -id = "move-72" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 72/127)" -needs = ["move-71"] - -[[steps]] -id = "move-73" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 73/127)" -needs = ["move-72"] - -[[steps]] -id = "move-74" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 74/127)" -needs = ["move-73"] - -[[steps]] -id = "move-75" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 75/127)" -needs = ["move-74"] - -[[steps]] -id = "move-76" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 76/127)" -needs = ["move-75"] - -[[steps]] -id = "move-77" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 77/127)" -needs = ["move-76"] - -[[steps]] -id = "move-78" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 78/127)" -needs = ["move-77"] - -[[steps]] -id = "move-79" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 79/127)" -needs = ["move-78"] - -[[steps]] -id = "move-80" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 80/127)" -needs = ["move-79"] - -[[steps]] -id = "move-81" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 81/127)" -needs = ["move-80"] - -[[steps]] -id = "move-82" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 82/127)" -needs = ["move-81"] - -[[steps]] -id = "move-83" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 83/127)" -needs = ["move-82"] - -[[steps]] -id = "move-84" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 84/127)" -needs = ["move-83"] - -[[steps]] -id = "move-85" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 85/127)" -needs = ["move-84"] - -[[steps]] -id = "move-86" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 86/127)" -needs = ["move-85"] - -[[steps]] -id = "move-87" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 87/127)" -needs = ["move-86"] - -[[steps]] -id = "move-88" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 88/127)" -needs = ["move-87"] - -[[steps]] -id = "move-89" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 89/127)" -needs = ["move-88"] - -[[steps]] -id = "move-90" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 90/127)" -needs = ["move-89"] - -[[steps]] -id = "move-91" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 91/127)" -needs = ["move-90"] - -[[steps]] -id = "move-92" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 92/127)" -needs = ["move-91"] - -[[steps]] -id = "move-93" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 93/127)" -needs = ["move-92"] - -[[steps]] -id = "move-94" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 94/127)" -needs = ["move-93"] - -[[steps]] -id = "move-95" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 95/127)" -needs = ["move-94"] - -[[steps]] -id = "move-96" -title = "Move disk 6: B → C" -description = "Move disk 6 from peg B to peg C. (Move 96/127)" -needs = ["move-95"] - -[[steps]] -id = "move-97" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 97/127)" -needs = ["move-96"] - -[[steps]] -id = "move-98" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 98/127)" -needs = ["move-97"] - -[[steps]] -id = "move-99" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 99/127)" -needs = ["move-98"] - -[[steps]] -id = "move-100" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 100/127)" -needs = ["move-99"] - -[[steps]] -id = "move-101" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 101/127)" -needs = ["move-100"] - -[[steps]] -id = "move-102" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 102/127)" -needs = ["move-101"] - -[[steps]] -id = "move-103" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 103/127)" -needs = ["move-102"] - -[[steps]] -id = "move-104" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 104/127)" -needs = ["move-103"] - -[[steps]] -id = "move-105" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 105/127)" -needs = ["move-104"] - -[[steps]] -id = "move-106" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 106/127)" -needs = ["move-105"] - -[[steps]] -id = "move-107" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 107/127)" -needs = ["move-106"] - -[[steps]] -id = "move-108" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 108/127)" -needs = ["move-107"] - -[[steps]] -id = "move-109" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 109/127)" -needs = ["move-108"] - -[[steps]] -id = "move-110" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 110/127)" -needs = ["move-109"] - -[[steps]] -id = "move-111" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 111/127)" -needs = ["move-110"] - -[[steps]] -id = "move-112" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 112/127)" -needs = ["move-111"] - -[[steps]] -id = "move-113" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 113/127)" -needs = ["move-112"] - -[[steps]] -id = "move-114" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 114/127)" -needs = ["move-113"] - -[[steps]] -id = "move-115" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 115/127)" -needs = ["move-114"] - -[[steps]] -id = "move-116" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 116/127)" -needs = ["move-115"] - -[[steps]] -id = "move-117" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 117/127)" -needs = ["move-116"] - -[[steps]] -id = "move-118" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 118/127)" -needs = ["move-117"] - -[[steps]] -id = "move-119" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 119/127)" -needs = ["move-118"] - -[[steps]] -id = "move-120" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 120/127)" -needs = ["move-119"] - -[[steps]] -id = "move-121" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 121/127)" -needs = ["move-120"] - -[[steps]] -id = "move-122" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 122/127)" -needs = ["move-121"] - -[[steps]] -id = "move-123" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 123/127)" -needs = ["move-122"] - -[[steps]] -id = "move-124" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 124/127)" -needs = ["move-123"] - -[[steps]] -id = "move-125" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 125/127)" -needs = ["move-124"] - -[[steps]] -id = "move-126" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 126/127)" -needs = ["move-125"] - -[[steps]] -id = "move-127" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 127/127)" -needs = ["move-126"] - -[[steps]] -id = "verify" -title = "Verify final state" -description = "All 7 disks now on peg C. Tower intact, all moves were legal." -needs = ["move-127"] diff --git a/.beads/formulas/towers-of-hanoi-9.formula.toml b/.beads/formulas/towers-of-hanoi-9.formula.toml deleted file mode 100644 index 441744819..000000000 --- a/.beads/formulas/towers-of-hanoi-9.formula.toml +++ /dev/null @@ -1,3116 +0,0 @@ -description = """ -AGENT EXECUTION PROTOCOL - Towers of Hanoi (9 disks, 511 moves) - -PURPOSE: This is a durability proof, not computation. Steps are pre-computed. -Your job is to execute them mechanically, proving crash-recovery at scale. - -EXECUTION LOOP: -1. Find current state: bd mol current -2. Find the next ready (unblocked) step -3. Close it: bd close -4. Repeat until no ready steps remain - -ON RESUME (after crash/restart/handoff): -- Same as fresh start. The molecule IS the state. -- Query `bd mol current `, continue from there. -- No memory of previous session needed. - -DO: -- Close steps as fast as possible (they're trivial mechanical moves) -- Use `gt handoff` when context fills (proactive cycling) -- Trust the pre-computed solution - every move is already correct - -DO NOT: -- Try to solve Hanoi yourself - moves are already computed -- Mark steps in_progress - just close them directly -- Ask for permission - this is GUPP territory, just execute -- Stop for human input - run autonomously until complete - -MONITORING: -- Progress: Count closed children of the molecule -- For mega-molecules: Use convoy dashboard when available -- Completion: All steps closed = molecule complete - -This proves Gas Town can execute arbitrarily long workflows with -nondeterministic idempotence - different sessions, same outcome. -""" -formula = "towers-of-hanoi-9" -version = 1 - -[[steps]] -id = "setup" -title = "Verify initial state" -description = "All 9 disks stacked on peg A. Largest on bottom." - - -[[steps]] -id = "move-1" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 1/511)" -needs = ["setup"] - -[[steps]] -id = "move-2" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 2/511)" -needs = ["move-1"] - -[[steps]] -id = "move-3" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 3/511)" -needs = ["move-2"] - -[[steps]] -id = "move-4" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 4/511)" -needs = ["move-3"] - -[[steps]] -id = "move-5" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 5/511)" -needs = ["move-4"] - -[[steps]] -id = "move-6" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 6/511)" -needs = ["move-5"] - -[[steps]] -id = "move-7" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 7/511)" -needs = ["move-6"] - -[[steps]] -id = "move-8" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 8/511)" -needs = ["move-7"] - -[[steps]] -id = "move-9" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 9/511)" -needs = ["move-8"] - -[[steps]] -id = "move-10" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 10/511)" -needs = ["move-9"] - -[[steps]] -id = "move-11" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 11/511)" -needs = ["move-10"] - -[[steps]] -id = "move-12" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 12/511)" -needs = ["move-11"] - -[[steps]] -id = "move-13" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 13/511)" -needs = ["move-12"] - -[[steps]] -id = "move-14" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 14/511)" -needs = ["move-13"] - -[[steps]] -id = "move-15" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 15/511)" -needs = ["move-14"] - -[[steps]] -id = "move-16" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 16/511)" -needs = ["move-15"] - -[[steps]] -id = "move-17" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 17/511)" -needs = ["move-16"] - -[[steps]] -id = "move-18" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 18/511)" -needs = ["move-17"] - -[[steps]] -id = "move-19" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 19/511)" -needs = ["move-18"] - -[[steps]] -id = "move-20" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 20/511)" -needs = ["move-19"] - -[[steps]] -id = "move-21" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 21/511)" -needs = ["move-20"] - -[[steps]] -id = "move-22" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 22/511)" -needs = ["move-21"] - -[[steps]] -id = "move-23" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 23/511)" -needs = ["move-22"] - -[[steps]] -id = "move-24" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 24/511)" -needs = ["move-23"] - -[[steps]] -id = "move-25" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 25/511)" -needs = ["move-24"] - -[[steps]] -id = "move-26" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 26/511)" -needs = ["move-25"] - -[[steps]] -id = "move-27" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 27/511)" -needs = ["move-26"] - -[[steps]] -id = "move-28" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 28/511)" -needs = ["move-27"] - -[[steps]] -id = "move-29" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 29/511)" -needs = ["move-28"] - -[[steps]] -id = "move-30" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 30/511)" -needs = ["move-29"] - -[[steps]] -id = "move-31" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 31/511)" -needs = ["move-30"] - -[[steps]] -id = "move-32" -title = "Move disk 6: A → B" -description = "Move disk 6 from peg A to peg B. (Move 32/511)" -needs = ["move-31"] - -[[steps]] -id = "move-33" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 33/511)" -needs = ["move-32"] - -[[steps]] -id = "move-34" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 34/511)" -needs = ["move-33"] - -[[steps]] -id = "move-35" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 35/511)" -needs = ["move-34"] - -[[steps]] -id = "move-36" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 36/511)" -needs = ["move-35"] - -[[steps]] -id = "move-37" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 37/511)" -needs = ["move-36"] - -[[steps]] -id = "move-38" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 38/511)" -needs = ["move-37"] - -[[steps]] -id = "move-39" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 39/511)" -needs = ["move-38"] - -[[steps]] -id = "move-40" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 40/511)" -needs = ["move-39"] - -[[steps]] -id = "move-41" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 41/511)" -needs = ["move-40"] - -[[steps]] -id = "move-42" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 42/511)" -needs = ["move-41"] - -[[steps]] -id = "move-43" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 43/511)" -needs = ["move-42"] - -[[steps]] -id = "move-44" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 44/511)" -needs = ["move-43"] - -[[steps]] -id = "move-45" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 45/511)" -needs = ["move-44"] - -[[steps]] -id = "move-46" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 46/511)" -needs = ["move-45"] - -[[steps]] -id = "move-47" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 47/511)" -needs = ["move-46"] - -[[steps]] -id = "move-48" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 48/511)" -needs = ["move-47"] - -[[steps]] -id = "move-49" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 49/511)" -needs = ["move-48"] - -[[steps]] -id = "move-50" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 50/511)" -needs = ["move-49"] - -[[steps]] -id = "move-51" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 51/511)" -needs = ["move-50"] - -[[steps]] -id = "move-52" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 52/511)" -needs = ["move-51"] - -[[steps]] -id = "move-53" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 53/511)" -needs = ["move-52"] - -[[steps]] -id = "move-54" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 54/511)" -needs = ["move-53"] - -[[steps]] -id = "move-55" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 55/511)" -needs = ["move-54"] - -[[steps]] -id = "move-56" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 56/511)" -needs = ["move-55"] - -[[steps]] -id = "move-57" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 57/511)" -needs = ["move-56"] - -[[steps]] -id = "move-58" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 58/511)" -needs = ["move-57"] - -[[steps]] -id = "move-59" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 59/511)" -needs = ["move-58"] - -[[steps]] -id = "move-60" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 60/511)" -needs = ["move-59"] - -[[steps]] -id = "move-61" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 61/511)" -needs = ["move-60"] - -[[steps]] -id = "move-62" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 62/511)" -needs = ["move-61"] - -[[steps]] -id = "move-63" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 63/511)" -needs = ["move-62"] - -[[steps]] -id = "move-64" -title = "Move disk 7: A → C" -description = "Move disk 7 from peg A to peg C. (Move 64/511)" -needs = ["move-63"] - -[[steps]] -id = "move-65" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 65/511)" -needs = ["move-64"] - -[[steps]] -id = "move-66" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 66/511)" -needs = ["move-65"] - -[[steps]] -id = "move-67" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 67/511)" -needs = ["move-66"] - -[[steps]] -id = "move-68" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 68/511)" -needs = ["move-67"] - -[[steps]] -id = "move-69" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 69/511)" -needs = ["move-68"] - -[[steps]] -id = "move-70" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 70/511)" -needs = ["move-69"] - -[[steps]] -id = "move-71" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 71/511)" -needs = ["move-70"] - -[[steps]] -id = "move-72" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 72/511)" -needs = ["move-71"] - -[[steps]] -id = "move-73" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 73/511)" -needs = ["move-72"] - -[[steps]] -id = "move-74" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 74/511)" -needs = ["move-73"] - -[[steps]] -id = "move-75" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 75/511)" -needs = ["move-74"] - -[[steps]] -id = "move-76" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 76/511)" -needs = ["move-75"] - -[[steps]] -id = "move-77" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 77/511)" -needs = ["move-76"] - -[[steps]] -id = "move-78" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 78/511)" -needs = ["move-77"] - -[[steps]] -id = "move-79" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 79/511)" -needs = ["move-78"] - -[[steps]] -id = "move-80" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 80/511)" -needs = ["move-79"] - -[[steps]] -id = "move-81" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 81/511)" -needs = ["move-80"] - -[[steps]] -id = "move-82" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 82/511)" -needs = ["move-81"] - -[[steps]] -id = "move-83" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 83/511)" -needs = ["move-82"] - -[[steps]] -id = "move-84" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 84/511)" -needs = ["move-83"] - -[[steps]] -id = "move-85" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 85/511)" -needs = ["move-84"] - -[[steps]] -id = "move-86" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 86/511)" -needs = ["move-85"] - -[[steps]] -id = "move-87" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 87/511)" -needs = ["move-86"] - -[[steps]] -id = "move-88" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 88/511)" -needs = ["move-87"] - -[[steps]] -id = "move-89" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 89/511)" -needs = ["move-88"] - -[[steps]] -id = "move-90" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 90/511)" -needs = ["move-89"] - -[[steps]] -id = "move-91" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 91/511)" -needs = ["move-90"] - -[[steps]] -id = "move-92" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 92/511)" -needs = ["move-91"] - -[[steps]] -id = "move-93" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 93/511)" -needs = ["move-92"] - -[[steps]] -id = "move-94" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 94/511)" -needs = ["move-93"] - -[[steps]] -id = "move-95" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 95/511)" -needs = ["move-94"] - -[[steps]] -id = "move-96" -title = "Move disk 6: B → C" -description = "Move disk 6 from peg B to peg C. (Move 96/511)" -needs = ["move-95"] - -[[steps]] -id = "move-97" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 97/511)" -needs = ["move-96"] - -[[steps]] -id = "move-98" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 98/511)" -needs = ["move-97"] - -[[steps]] -id = "move-99" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 99/511)" -needs = ["move-98"] - -[[steps]] -id = "move-100" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 100/511)" -needs = ["move-99"] - -[[steps]] -id = "move-101" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 101/511)" -needs = ["move-100"] - -[[steps]] -id = "move-102" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 102/511)" -needs = ["move-101"] - -[[steps]] -id = "move-103" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 103/511)" -needs = ["move-102"] - -[[steps]] -id = "move-104" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 104/511)" -needs = ["move-103"] - -[[steps]] -id = "move-105" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 105/511)" -needs = ["move-104"] - -[[steps]] -id = "move-106" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 106/511)" -needs = ["move-105"] - -[[steps]] -id = "move-107" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 107/511)" -needs = ["move-106"] - -[[steps]] -id = "move-108" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 108/511)" -needs = ["move-107"] - -[[steps]] -id = "move-109" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 109/511)" -needs = ["move-108"] - -[[steps]] -id = "move-110" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 110/511)" -needs = ["move-109"] - -[[steps]] -id = "move-111" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 111/511)" -needs = ["move-110"] - -[[steps]] -id = "move-112" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 112/511)" -needs = ["move-111"] - -[[steps]] -id = "move-113" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 113/511)" -needs = ["move-112"] - -[[steps]] -id = "move-114" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 114/511)" -needs = ["move-113"] - -[[steps]] -id = "move-115" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 115/511)" -needs = ["move-114"] - -[[steps]] -id = "move-116" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 116/511)" -needs = ["move-115"] - -[[steps]] -id = "move-117" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 117/511)" -needs = ["move-116"] - -[[steps]] -id = "move-118" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 118/511)" -needs = ["move-117"] - -[[steps]] -id = "move-119" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 119/511)" -needs = ["move-118"] - -[[steps]] -id = "move-120" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 120/511)" -needs = ["move-119"] - -[[steps]] -id = "move-121" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 121/511)" -needs = ["move-120"] - -[[steps]] -id = "move-122" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 122/511)" -needs = ["move-121"] - -[[steps]] -id = "move-123" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 123/511)" -needs = ["move-122"] - -[[steps]] -id = "move-124" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 124/511)" -needs = ["move-123"] - -[[steps]] -id = "move-125" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 125/511)" -needs = ["move-124"] - -[[steps]] -id = "move-126" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 126/511)" -needs = ["move-125"] - -[[steps]] -id = "move-127" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 127/511)" -needs = ["move-126"] - -[[steps]] -id = "move-128" -title = "Move disk 8: A → B" -description = "Move disk 8 from peg A to peg B. (Move 128/511)" -needs = ["move-127"] - -[[steps]] -id = "move-129" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 129/511)" -needs = ["move-128"] - -[[steps]] -id = "move-130" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 130/511)" -needs = ["move-129"] - -[[steps]] -id = "move-131" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 131/511)" -needs = ["move-130"] - -[[steps]] -id = "move-132" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 132/511)" -needs = ["move-131"] - -[[steps]] -id = "move-133" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 133/511)" -needs = ["move-132"] - -[[steps]] -id = "move-134" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 134/511)" -needs = ["move-133"] - -[[steps]] -id = "move-135" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 135/511)" -needs = ["move-134"] - -[[steps]] -id = "move-136" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 136/511)" -needs = ["move-135"] - -[[steps]] -id = "move-137" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 137/511)" -needs = ["move-136"] - -[[steps]] -id = "move-138" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 138/511)" -needs = ["move-137"] - -[[steps]] -id = "move-139" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 139/511)" -needs = ["move-138"] - -[[steps]] -id = "move-140" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 140/511)" -needs = ["move-139"] - -[[steps]] -id = "move-141" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 141/511)" -needs = ["move-140"] - -[[steps]] -id = "move-142" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 142/511)" -needs = ["move-141"] - -[[steps]] -id = "move-143" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 143/511)" -needs = ["move-142"] - -[[steps]] -id = "move-144" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 144/511)" -needs = ["move-143"] - -[[steps]] -id = "move-145" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 145/511)" -needs = ["move-144"] - -[[steps]] -id = "move-146" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 146/511)" -needs = ["move-145"] - -[[steps]] -id = "move-147" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 147/511)" -needs = ["move-146"] - -[[steps]] -id = "move-148" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 148/511)" -needs = ["move-147"] - -[[steps]] -id = "move-149" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 149/511)" -needs = ["move-148"] - -[[steps]] -id = "move-150" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 150/511)" -needs = ["move-149"] - -[[steps]] -id = "move-151" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 151/511)" -needs = ["move-150"] - -[[steps]] -id = "move-152" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 152/511)" -needs = ["move-151"] - -[[steps]] -id = "move-153" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 153/511)" -needs = ["move-152"] - -[[steps]] -id = "move-154" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 154/511)" -needs = ["move-153"] - -[[steps]] -id = "move-155" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 155/511)" -needs = ["move-154"] - -[[steps]] -id = "move-156" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 156/511)" -needs = ["move-155"] - -[[steps]] -id = "move-157" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 157/511)" -needs = ["move-156"] - -[[steps]] -id = "move-158" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 158/511)" -needs = ["move-157"] - -[[steps]] -id = "move-159" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 159/511)" -needs = ["move-158"] - -[[steps]] -id = "move-160" -title = "Move disk 6: C → A" -description = "Move disk 6 from peg C to peg A. (Move 160/511)" -needs = ["move-159"] - -[[steps]] -id = "move-161" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 161/511)" -needs = ["move-160"] - -[[steps]] -id = "move-162" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 162/511)" -needs = ["move-161"] - -[[steps]] -id = "move-163" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 163/511)" -needs = ["move-162"] - -[[steps]] -id = "move-164" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 164/511)" -needs = ["move-163"] - -[[steps]] -id = "move-165" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 165/511)" -needs = ["move-164"] - -[[steps]] -id = "move-166" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 166/511)" -needs = ["move-165"] - -[[steps]] -id = "move-167" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 167/511)" -needs = ["move-166"] - -[[steps]] -id = "move-168" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 168/511)" -needs = ["move-167"] - -[[steps]] -id = "move-169" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 169/511)" -needs = ["move-168"] - -[[steps]] -id = "move-170" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 170/511)" -needs = ["move-169"] - -[[steps]] -id = "move-171" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 171/511)" -needs = ["move-170"] - -[[steps]] -id = "move-172" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 172/511)" -needs = ["move-171"] - -[[steps]] -id = "move-173" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 173/511)" -needs = ["move-172"] - -[[steps]] -id = "move-174" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 174/511)" -needs = ["move-173"] - -[[steps]] -id = "move-175" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 175/511)" -needs = ["move-174"] - -[[steps]] -id = "move-176" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 176/511)" -needs = ["move-175"] - -[[steps]] -id = "move-177" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 177/511)" -needs = ["move-176"] - -[[steps]] -id = "move-178" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 178/511)" -needs = ["move-177"] - -[[steps]] -id = "move-179" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 179/511)" -needs = ["move-178"] - -[[steps]] -id = "move-180" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 180/511)" -needs = ["move-179"] - -[[steps]] -id = "move-181" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 181/511)" -needs = ["move-180"] - -[[steps]] -id = "move-182" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 182/511)" -needs = ["move-181"] - -[[steps]] -id = "move-183" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 183/511)" -needs = ["move-182"] - -[[steps]] -id = "move-184" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 184/511)" -needs = ["move-183"] - -[[steps]] -id = "move-185" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 185/511)" -needs = ["move-184"] - -[[steps]] -id = "move-186" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 186/511)" -needs = ["move-185"] - -[[steps]] -id = "move-187" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 187/511)" -needs = ["move-186"] - -[[steps]] -id = "move-188" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 188/511)" -needs = ["move-187"] - -[[steps]] -id = "move-189" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 189/511)" -needs = ["move-188"] - -[[steps]] -id = "move-190" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 190/511)" -needs = ["move-189"] - -[[steps]] -id = "move-191" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 191/511)" -needs = ["move-190"] - -[[steps]] -id = "move-192" -title = "Move disk 7: C → B" -description = "Move disk 7 from peg C to peg B. (Move 192/511)" -needs = ["move-191"] - -[[steps]] -id = "move-193" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 193/511)" -needs = ["move-192"] - -[[steps]] -id = "move-194" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 194/511)" -needs = ["move-193"] - -[[steps]] -id = "move-195" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 195/511)" -needs = ["move-194"] - -[[steps]] -id = "move-196" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 196/511)" -needs = ["move-195"] - -[[steps]] -id = "move-197" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 197/511)" -needs = ["move-196"] - -[[steps]] -id = "move-198" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 198/511)" -needs = ["move-197"] - -[[steps]] -id = "move-199" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 199/511)" -needs = ["move-198"] - -[[steps]] -id = "move-200" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 200/511)" -needs = ["move-199"] - -[[steps]] -id = "move-201" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 201/511)" -needs = ["move-200"] - -[[steps]] -id = "move-202" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 202/511)" -needs = ["move-201"] - -[[steps]] -id = "move-203" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 203/511)" -needs = ["move-202"] - -[[steps]] -id = "move-204" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 204/511)" -needs = ["move-203"] - -[[steps]] -id = "move-205" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 205/511)" -needs = ["move-204"] - -[[steps]] -id = "move-206" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 206/511)" -needs = ["move-205"] - -[[steps]] -id = "move-207" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 207/511)" -needs = ["move-206"] - -[[steps]] -id = "move-208" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 208/511)" -needs = ["move-207"] - -[[steps]] -id = "move-209" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 209/511)" -needs = ["move-208"] - -[[steps]] -id = "move-210" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 210/511)" -needs = ["move-209"] - -[[steps]] -id = "move-211" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 211/511)" -needs = ["move-210"] - -[[steps]] -id = "move-212" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 212/511)" -needs = ["move-211"] - -[[steps]] -id = "move-213" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 213/511)" -needs = ["move-212"] - -[[steps]] -id = "move-214" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 214/511)" -needs = ["move-213"] - -[[steps]] -id = "move-215" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 215/511)" -needs = ["move-214"] - -[[steps]] -id = "move-216" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 216/511)" -needs = ["move-215"] - -[[steps]] -id = "move-217" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 217/511)" -needs = ["move-216"] - -[[steps]] -id = "move-218" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 218/511)" -needs = ["move-217"] - -[[steps]] -id = "move-219" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 219/511)" -needs = ["move-218"] - -[[steps]] -id = "move-220" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 220/511)" -needs = ["move-219"] - -[[steps]] -id = "move-221" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 221/511)" -needs = ["move-220"] - -[[steps]] -id = "move-222" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 222/511)" -needs = ["move-221"] - -[[steps]] -id = "move-223" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 223/511)" -needs = ["move-222"] - -[[steps]] -id = "move-224" -title = "Move disk 6: A → B" -description = "Move disk 6 from peg A to peg B. (Move 224/511)" -needs = ["move-223"] - -[[steps]] -id = "move-225" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 225/511)" -needs = ["move-224"] - -[[steps]] -id = "move-226" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 226/511)" -needs = ["move-225"] - -[[steps]] -id = "move-227" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 227/511)" -needs = ["move-226"] - -[[steps]] -id = "move-228" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 228/511)" -needs = ["move-227"] - -[[steps]] -id = "move-229" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 229/511)" -needs = ["move-228"] - -[[steps]] -id = "move-230" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 230/511)" -needs = ["move-229"] - -[[steps]] -id = "move-231" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 231/511)" -needs = ["move-230"] - -[[steps]] -id = "move-232" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 232/511)" -needs = ["move-231"] - -[[steps]] -id = "move-233" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 233/511)" -needs = ["move-232"] - -[[steps]] -id = "move-234" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 234/511)" -needs = ["move-233"] - -[[steps]] -id = "move-235" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 235/511)" -needs = ["move-234"] - -[[steps]] -id = "move-236" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 236/511)" -needs = ["move-235"] - -[[steps]] -id = "move-237" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 237/511)" -needs = ["move-236"] - -[[steps]] -id = "move-238" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 238/511)" -needs = ["move-237"] - -[[steps]] -id = "move-239" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 239/511)" -needs = ["move-238"] - -[[steps]] -id = "move-240" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 240/511)" -needs = ["move-239"] - -[[steps]] -id = "move-241" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 241/511)" -needs = ["move-240"] - -[[steps]] -id = "move-242" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 242/511)" -needs = ["move-241"] - -[[steps]] -id = "move-243" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 243/511)" -needs = ["move-242"] - -[[steps]] -id = "move-244" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 244/511)" -needs = ["move-243"] - -[[steps]] -id = "move-245" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 245/511)" -needs = ["move-244"] - -[[steps]] -id = "move-246" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 246/511)" -needs = ["move-245"] - -[[steps]] -id = "move-247" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 247/511)" -needs = ["move-246"] - -[[steps]] -id = "move-248" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 248/511)" -needs = ["move-247"] - -[[steps]] -id = "move-249" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 249/511)" -needs = ["move-248"] - -[[steps]] -id = "move-250" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 250/511)" -needs = ["move-249"] - -[[steps]] -id = "move-251" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 251/511)" -needs = ["move-250"] - -[[steps]] -id = "move-252" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 252/511)" -needs = ["move-251"] - -[[steps]] -id = "move-253" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 253/511)" -needs = ["move-252"] - -[[steps]] -id = "move-254" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 254/511)" -needs = ["move-253"] - -[[steps]] -id = "move-255" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 255/511)" -needs = ["move-254"] - -[[steps]] -id = "move-256" -title = "Move disk 9: A → C" -description = "Move disk 9 from peg A to peg C. (Move 256/511)" -needs = ["move-255"] - -[[steps]] -id = "move-257" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 257/511)" -needs = ["move-256"] - -[[steps]] -id = "move-258" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 258/511)" -needs = ["move-257"] - -[[steps]] -id = "move-259" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 259/511)" -needs = ["move-258"] - -[[steps]] -id = "move-260" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 260/511)" -needs = ["move-259"] - -[[steps]] -id = "move-261" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 261/511)" -needs = ["move-260"] - -[[steps]] -id = "move-262" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 262/511)" -needs = ["move-261"] - -[[steps]] -id = "move-263" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 263/511)" -needs = ["move-262"] - -[[steps]] -id = "move-264" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 264/511)" -needs = ["move-263"] - -[[steps]] -id = "move-265" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 265/511)" -needs = ["move-264"] - -[[steps]] -id = "move-266" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 266/511)" -needs = ["move-265"] - -[[steps]] -id = "move-267" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 267/511)" -needs = ["move-266"] - -[[steps]] -id = "move-268" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 268/511)" -needs = ["move-267"] - -[[steps]] -id = "move-269" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 269/511)" -needs = ["move-268"] - -[[steps]] -id = "move-270" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 270/511)" -needs = ["move-269"] - -[[steps]] -id = "move-271" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 271/511)" -needs = ["move-270"] - -[[steps]] -id = "move-272" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 272/511)" -needs = ["move-271"] - -[[steps]] -id = "move-273" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 273/511)" -needs = ["move-272"] - -[[steps]] -id = "move-274" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 274/511)" -needs = ["move-273"] - -[[steps]] -id = "move-275" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 275/511)" -needs = ["move-274"] - -[[steps]] -id = "move-276" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 276/511)" -needs = ["move-275"] - -[[steps]] -id = "move-277" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 277/511)" -needs = ["move-276"] - -[[steps]] -id = "move-278" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 278/511)" -needs = ["move-277"] - -[[steps]] -id = "move-279" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 279/511)" -needs = ["move-278"] - -[[steps]] -id = "move-280" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 280/511)" -needs = ["move-279"] - -[[steps]] -id = "move-281" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 281/511)" -needs = ["move-280"] - -[[steps]] -id = "move-282" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 282/511)" -needs = ["move-281"] - -[[steps]] -id = "move-283" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 283/511)" -needs = ["move-282"] - -[[steps]] -id = "move-284" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 284/511)" -needs = ["move-283"] - -[[steps]] -id = "move-285" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 285/511)" -needs = ["move-284"] - -[[steps]] -id = "move-286" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 286/511)" -needs = ["move-285"] - -[[steps]] -id = "move-287" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 287/511)" -needs = ["move-286"] - -[[steps]] -id = "move-288" -title = "Move disk 6: B → C" -description = "Move disk 6 from peg B to peg C. (Move 288/511)" -needs = ["move-287"] - -[[steps]] -id = "move-289" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 289/511)" -needs = ["move-288"] - -[[steps]] -id = "move-290" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 290/511)" -needs = ["move-289"] - -[[steps]] -id = "move-291" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 291/511)" -needs = ["move-290"] - -[[steps]] -id = "move-292" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 292/511)" -needs = ["move-291"] - -[[steps]] -id = "move-293" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 293/511)" -needs = ["move-292"] - -[[steps]] -id = "move-294" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 294/511)" -needs = ["move-293"] - -[[steps]] -id = "move-295" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 295/511)" -needs = ["move-294"] - -[[steps]] -id = "move-296" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 296/511)" -needs = ["move-295"] - -[[steps]] -id = "move-297" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 297/511)" -needs = ["move-296"] - -[[steps]] -id = "move-298" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 298/511)" -needs = ["move-297"] - -[[steps]] -id = "move-299" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 299/511)" -needs = ["move-298"] - -[[steps]] -id = "move-300" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 300/511)" -needs = ["move-299"] - -[[steps]] -id = "move-301" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 301/511)" -needs = ["move-300"] - -[[steps]] -id = "move-302" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 302/511)" -needs = ["move-301"] - -[[steps]] -id = "move-303" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 303/511)" -needs = ["move-302"] - -[[steps]] -id = "move-304" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 304/511)" -needs = ["move-303"] - -[[steps]] -id = "move-305" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 305/511)" -needs = ["move-304"] - -[[steps]] -id = "move-306" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 306/511)" -needs = ["move-305"] - -[[steps]] -id = "move-307" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 307/511)" -needs = ["move-306"] - -[[steps]] -id = "move-308" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 308/511)" -needs = ["move-307"] - -[[steps]] -id = "move-309" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 309/511)" -needs = ["move-308"] - -[[steps]] -id = "move-310" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 310/511)" -needs = ["move-309"] - -[[steps]] -id = "move-311" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 311/511)" -needs = ["move-310"] - -[[steps]] -id = "move-312" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 312/511)" -needs = ["move-311"] - -[[steps]] -id = "move-313" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 313/511)" -needs = ["move-312"] - -[[steps]] -id = "move-314" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 314/511)" -needs = ["move-313"] - -[[steps]] -id = "move-315" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 315/511)" -needs = ["move-314"] - -[[steps]] -id = "move-316" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 316/511)" -needs = ["move-315"] - -[[steps]] -id = "move-317" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 317/511)" -needs = ["move-316"] - -[[steps]] -id = "move-318" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 318/511)" -needs = ["move-317"] - -[[steps]] -id = "move-319" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 319/511)" -needs = ["move-318"] - -[[steps]] -id = "move-320" -title = "Move disk 7: B → A" -description = "Move disk 7 from peg B to peg A. (Move 320/511)" -needs = ["move-319"] - -[[steps]] -id = "move-321" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 321/511)" -needs = ["move-320"] - -[[steps]] -id = "move-322" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 322/511)" -needs = ["move-321"] - -[[steps]] -id = "move-323" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 323/511)" -needs = ["move-322"] - -[[steps]] -id = "move-324" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 324/511)" -needs = ["move-323"] - -[[steps]] -id = "move-325" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 325/511)" -needs = ["move-324"] - -[[steps]] -id = "move-326" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 326/511)" -needs = ["move-325"] - -[[steps]] -id = "move-327" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 327/511)" -needs = ["move-326"] - -[[steps]] -id = "move-328" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 328/511)" -needs = ["move-327"] - -[[steps]] -id = "move-329" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 329/511)" -needs = ["move-328"] - -[[steps]] -id = "move-330" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 330/511)" -needs = ["move-329"] - -[[steps]] -id = "move-331" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 331/511)" -needs = ["move-330"] - -[[steps]] -id = "move-332" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 332/511)" -needs = ["move-331"] - -[[steps]] -id = "move-333" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 333/511)" -needs = ["move-332"] - -[[steps]] -id = "move-334" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 334/511)" -needs = ["move-333"] - -[[steps]] -id = "move-335" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 335/511)" -needs = ["move-334"] - -[[steps]] -id = "move-336" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 336/511)" -needs = ["move-335"] - -[[steps]] -id = "move-337" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 337/511)" -needs = ["move-336"] - -[[steps]] -id = "move-338" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 338/511)" -needs = ["move-337"] - -[[steps]] -id = "move-339" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 339/511)" -needs = ["move-338"] - -[[steps]] -id = "move-340" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 340/511)" -needs = ["move-339"] - -[[steps]] -id = "move-341" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 341/511)" -needs = ["move-340"] - -[[steps]] -id = "move-342" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 342/511)" -needs = ["move-341"] - -[[steps]] -id = "move-343" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 343/511)" -needs = ["move-342"] - -[[steps]] -id = "move-344" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 344/511)" -needs = ["move-343"] - -[[steps]] -id = "move-345" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 345/511)" -needs = ["move-344"] - -[[steps]] -id = "move-346" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 346/511)" -needs = ["move-345"] - -[[steps]] -id = "move-347" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 347/511)" -needs = ["move-346"] - -[[steps]] -id = "move-348" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 348/511)" -needs = ["move-347"] - -[[steps]] -id = "move-349" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 349/511)" -needs = ["move-348"] - -[[steps]] -id = "move-350" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 350/511)" -needs = ["move-349"] - -[[steps]] -id = "move-351" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 351/511)" -needs = ["move-350"] - -[[steps]] -id = "move-352" -title = "Move disk 6: C → A" -description = "Move disk 6 from peg C to peg A. (Move 352/511)" -needs = ["move-351"] - -[[steps]] -id = "move-353" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 353/511)" -needs = ["move-352"] - -[[steps]] -id = "move-354" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 354/511)" -needs = ["move-353"] - -[[steps]] -id = "move-355" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 355/511)" -needs = ["move-354"] - -[[steps]] -id = "move-356" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 356/511)" -needs = ["move-355"] - -[[steps]] -id = "move-357" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 357/511)" -needs = ["move-356"] - -[[steps]] -id = "move-358" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 358/511)" -needs = ["move-357"] - -[[steps]] -id = "move-359" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 359/511)" -needs = ["move-358"] - -[[steps]] -id = "move-360" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 360/511)" -needs = ["move-359"] - -[[steps]] -id = "move-361" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 361/511)" -needs = ["move-360"] - -[[steps]] -id = "move-362" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 362/511)" -needs = ["move-361"] - -[[steps]] -id = "move-363" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 363/511)" -needs = ["move-362"] - -[[steps]] -id = "move-364" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 364/511)" -needs = ["move-363"] - -[[steps]] -id = "move-365" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 365/511)" -needs = ["move-364"] - -[[steps]] -id = "move-366" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 366/511)" -needs = ["move-365"] - -[[steps]] -id = "move-367" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 367/511)" -needs = ["move-366"] - -[[steps]] -id = "move-368" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 368/511)" -needs = ["move-367"] - -[[steps]] -id = "move-369" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 369/511)" -needs = ["move-368"] - -[[steps]] -id = "move-370" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 370/511)" -needs = ["move-369"] - -[[steps]] -id = "move-371" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 371/511)" -needs = ["move-370"] - -[[steps]] -id = "move-372" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 372/511)" -needs = ["move-371"] - -[[steps]] -id = "move-373" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 373/511)" -needs = ["move-372"] - -[[steps]] -id = "move-374" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 374/511)" -needs = ["move-373"] - -[[steps]] -id = "move-375" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 375/511)" -needs = ["move-374"] - -[[steps]] -id = "move-376" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 376/511)" -needs = ["move-375"] - -[[steps]] -id = "move-377" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 377/511)" -needs = ["move-376"] - -[[steps]] -id = "move-378" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 378/511)" -needs = ["move-377"] - -[[steps]] -id = "move-379" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 379/511)" -needs = ["move-378"] - -[[steps]] -id = "move-380" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 380/511)" -needs = ["move-379"] - -[[steps]] -id = "move-381" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 381/511)" -needs = ["move-380"] - -[[steps]] -id = "move-382" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 382/511)" -needs = ["move-381"] - -[[steps]] -id = "move-383" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 383/511)" -needs = ["move-382"] - -[[steps]] -id = "move-384" -title = "Move disk 8: B → C" -description = "Move disk 8 from peg B to peg C. (Move 384/511)" -needs = ["move-383"] - -[[steps]] -id = "move-385" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 385/511)" -needs = ["move-384"] - -[[steps]] -id = "move-386" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 386/511)" -needs = ["move-385"] - -[[steps]] -id = "move-387" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 387/511)" -needs = ["move-386"] - -[[steps]] -id = "move-388" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 388/511)" -needs = ["move-387"] - -[[steps]] -id = "move-389" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 389/511)" -needs = ["move-388"] - -[[steps]] -id = "move-390" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 390/511)" -needs = ["move-389"] - -[[steps]] -id = "move-391" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 391/511)" -needs = ["move-390"] - -[[steps]] -id = "move-392" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 392/511)" -needs = ["move-391"] - -[[steps]] -id = "move-393" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 393/511)" -needs = ["move-392"] - -[[steps]] -id = "move-394" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 394/511)" -needs = ["move-393"] - -[[steps]] -id = "move-395" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 395/511)" -needs = ["move-394"] - -[[steps]] -id = "move-396" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 396/511)" -needs = ["move-395"] - -[[steps]] -id = "move-397" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 397/511)" -needs = ["move-396"] - -[[steps]] -id = "move-398" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 398/511)" -needs = ["move-397"] - -[[steps]] -id = "move-399" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 399/511)" -needs = ["move-398"] - -[[steps]] -id = "move-400" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 400/511)" -needs = ["move-399"] - -[[steps]] -id = "move-401" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 401/511)" -needs = ["move-400"] - -[[steps]] -id = "move-402" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 402/511)" -needs = ["move-401"] - -[[steps]] -id = "move-403" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 403/511)" -needs = ["move-402"] - -[[steps]] -id = "move-404" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 404/511)" -needs = ["move-403"] - -[[steps]] -id = "move-405" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 405/511)" -needs = ["move-404"] - -[[steps]] -id = "move-406" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 406/511)" -needs = ["move-405"] - -[[steps]] -id = "move-407" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 407/511)" -needs = ["move-406"] - -[[steps]] -id = "move-408" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 408/511)" -needs = ["move-407"] - -[[steps]] -id = "move-409" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 409/511)" -needs = ["move-408"] - -[[steps]] -id = "move-410" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 410/511)" -needs = ["move-409"] - -[[steps]] -id = "move-411" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 411/511)" -needs = ["move-410"] - -[[steps]] -id = "move-412" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 412/511)" -needs = ["move-411"] - -[[steps]] -id = "move-413" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 413/511)" -needs = ["move-412"] - -[[steps]] -id = "move-414" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 414/511)" -needs = ["move-413"] - -[[steps]] -id = "move-415" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 415/511)" -needs = ["move-414"] - -[[steps]] -id = "move-416" -title = "Move disk 6: A → B" -description = "Move disk 6 from peg A to peg B. (Move 416/511)" -needs = ["move-415"] - -[[steps]] -id = "move-417" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 417/511)" -needs = ["move-416"] - -[[steps]] -id = "move-418" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 418/511)" -needs = ["move-417"] - -[[steps]] -id = "move-419" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 419/511)" -needs = ["move-418"] - -[[steps]] -id = "move-420" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 420/511)" -needs = ["move-419"] - -[[steps]] -id = "move-421" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 421/511)" -needs = ["move-420"] - -[[steps]] -id = "move-422" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 422/511)" -needs = ["move-421"] - -[[steps]] -id = "move-423" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 423/511)" -needs = ["move-422"] - -[[steps]] -id = "move-424" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 424/511)" -needs = ["move-423"] - -[[steps]] -id = "move-425" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 425/511)" -needs = ["move-424"] - -[[steps]] -id = "move-426" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 426/511)" -needs = ["move-425"] - -[[steps]] -id = "move-427" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 427/511)" -needs = ["move-426"] - -[[steps]] -id = "move-428" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 428/511)" -needs = ["move-427"] - -[[steps]] -id = "move-429" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 429/511)" -needs = ["move-428"] - -[[steps]] -id = "move-430" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 430/511)" -needs = ["move-429"] - -[[steps]] -id = "move-431" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 431/511)" -needs = ["move-430"] - -[[steps]] -id = "move-432" -title = "Move disk 5: C → B" -description = "Move disk 5 from peg C to peg B. (Move 432/511)" -needs = ["move-431"] - -[[steps]] -id = "move-433" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 433/511)" -needs = ["move-432"] - -[[steps]] -id = "move-434" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 434/511)" -needs = ["move-433"] - -[[steps]] -id = "move-435" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 435/511)" -needs = ["move-434"] - -[[steps]] -id = "move-436" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 436/511)" -needs = ["move-435"] - -[[steps]] -id = "move-437" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 437/511)" -needs = ["move-436"] - -[[steps]] -id = "move-438" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 438/511)" -needs = ["move-437"] - -[[steps]] -id = "move-439" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 439/511)" -needs = ["move-438"] - -[[steps]] -id = "move-440" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 440/511)" -needs = ["move-439"] - -[[steps]] -id = "move-441" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 441/511)" -needs = ["move-440"] - -[[steps]] -id = "move-442" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 442/511)" -needs = ["move-441"] - -[[steps]] -id = "move-443" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 443/511)" -needs = ["move-442"] - -[[steps]] -id = "move-444" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 444/511)" -needs = ["move-443"] - -[[steps]] -id = "move-445" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 445/511)" -needs = ["move-444"] - -[[steps]] -id = "move-446" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 446/511)" -needs = ["move-445"] - -[[steps]] -id = "move-447" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 447/511)" -needs = ["move-446"] - -[[steps]] -id = "move-448" -title = "Move disk 7: A → C" -description = "Move disk 7 from peg A to peg C. (Move 448/511)" -needs = ["move-447"] - -[[steps]] -id = "move-449" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 449/511)" -needs = ["move-448"] - -[[steps]] -id = "move-450" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 450/511)" -needs = ["move-449"] - -[[steps]] -id = "move-451" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 451/511)" -needs = ["move-450"] - -[[steps]] -id = "move-452" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 452/511)" -needs = ["move-451"] - -[[steps]] -id = "move-453" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 453/511)" -needs = ["move-452"] - -[[steps]] -id = "move-454" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 454/511)" -needs = ["move-453"] - -[[steps]] -id = "move-455" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 455/511)" -needs = ["move-454"] - -[[steps]] -id = "move-456" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 456/511)" -needs = ["move-455"] - -[[steps]] -id = "move-457" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 457/511)" -needs = ["move-456"] - -[[steps]] -id = "move-458" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 458/511)" -needs = ["move-457"] - -[[steps]] -id = "move-459" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 459/511)" -needs = ["move-458"] - -[[steps]] -id = "move-460" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 460/511)" -needs = ["move-459"] - -[[steps]] -id = "move-461" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 461/511)" -needs = ["move-460"] - -[[steps]] -id = "move-462" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 462/511)" -needs = ["move-461"] - -[[steps]] -id = "move-463" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 463/511)" -needs = ["move-462"] - -[[steps]] -id = "move-464" -title = "Move disk 5: B → A" -description = "Move disk 5 from peg B to peg A. (Move 464/511)" -needs = ["move-463"] - -[[steps]] -id = "move-465" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 465/511)" -needs = ["move-464"] - -[[steps]] -id = "move-466" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 466/511)" -needs = ["move-465"] - -[[steps]] -id = "move-467" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 467/511)" -needs = ["move-466"] - -[[steps]] -id = "move-468" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 468/511)" -needs = ["move-467"] - -[[steps]] -id = "move-469" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 469/511)" -needs = ["move-468"] - -[[steps]] -id = "move-470" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 470/511)" -needs = ["move-469"] - -[[steps]] -id = "move-471" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 471/511)" -needs = ["move-470"] - -[[steps]] -id = "move-472" -title = "Move disk 4: C → A" -description = "Move disk 4 from peg C to peg A. (Move 472/511)" -needs = ["move-471"] - -[[steps]] -id = "move-473" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 473/511)" -needs = ["move-472"] - -[[steps]] -id = "move-474" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 474/511)" -needs = ["move-473"] - -[[steps]] -id = "move-475" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 475/511)" -needs = ["move-474"] - -[[steps]] -id = "move-476" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 476/511)" -needs = ["move-475"] - -[[steps]] -id = "move-477" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 477/511)" -needs = ["move-476"] - -[[steps]] -id = "move-478" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 478/511)" -needs = ["move-477"] - -[[steps]] -id = "move-479" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 479/511)" -needs = ["move-478"] - -[[steps]] -id = "move-480" -title = "Move disk 6: B → C" -description = "Move disk 6 from peg B to peg C. (Move 480/511)" -needs = ["move-479"] - -[[steps]] -id = "move-481" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 481/511)" -needs = ["move-480"] - -[[steps]] -id = "move-482" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 482/511)" -needs = ["move-481"] - -[[steps]] -id = "move-483" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 483/511)" -needs = ["move-482"] - -[[steps]] -id = "move-484" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 484/511)" -needs = ["move-483"] - -[[steps]] -id = "move-485" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 485/511)" -needs = ["move-484"] - -[[steps]] -id = "move-486" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 486/511)" -needs = ["move-485"] - -[[steps]] -id = "move-487" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 487/511)" -needs = ["move-486"] - -[[steps]] -id = "move-488" -title = "Move disk 4: A → B" -description = "Move disk 4 from peg A to peg B. (Move 488/511)" -needs = ["move-487"] - -[[steps]] -id = "move-489" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 489/511)" -needs = ["move-488"] - -[[steps]] -id = "move-490" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 490/511)" -needs = ["move-489"] - -[[steps]] -id = "move-491" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 491/511)" -needs = ["move-490"] - -[[steps]] -id = "move-492" -title = "Move disk 3: C → B" -description = "Move disk 3 from peg C to peg B. (Move 492/511)" -needs = ["move-491"] - -[[steps]] -id = "move-493" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 493/511)" -needs = ["move-492"] - -[[steps]] -id = "move-494" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 494/511)" -needs = ["move-493"] - -[[steps]] -id = "move-495" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 495/511)" -needs = ["move-494"] - -[[steps]] -id = "move-496" -title = "Move disk 5: A → C" -description = "Move disk 5 from peg A to peg C. (Move 496/511)" -needs = ["move-495"] - -[[steps]] -id = "move-497" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 497/511)" -needs = ["move-496"] - -[[steps]] -id = "move-498" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 498/511)" -needs = ["move-497"] - -[[steps]] -id = "move-499" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 499/511)" -needs = ["move-498"] - -[[steps]] -id = "move-500" -title = "Move disk 3: B → A" -description = "Move disk 3 from peg B to peg A. (Move 500/511)" -needs = ["move-499"] - -[[steps]] -id = "move-501" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 501/511)" -needs = ["move-500"] - -[[steps]] -id = "move-502" -title = "Move disk 2: C → A" -description = "Move disk 2 from peg C to peg A. (Move 502/511)" -needs = ["move-501"] - -[[steps]] -id = "move-503" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 503/511)" -needs = ["move-502"] - -[[steps]] -id = "move-504" -title = "Move disk 4: B → C" -description = "Move disk 4 from peg B to peg C. (Move 504/511)" -needs = ["move-503"] - -[[steps]] -id = "move-505" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 505/511)" -needs = ["move-504"] - -[[steps]] -id = "move-506" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B. (Move 506/511)" -needs = ["move-505"] - -[[steps]] -id = "move-507" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B. (Move 507/511)" -needs = ["move-506"] - -[[steps]] -id = "move-508" -title = "Move disk 3: A → C" -description = "Move disk 3 from peg A to peg C. (Move 508/511)" -needs = ["move-507"] - -[[steps]] -id = "move-509" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A. (Move 509/511)" -needs = ["move-508"] - -[[steps]] -id = "move-510" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C. (Move 510/511)" -needs = ["move-509"] - -[[steps]] -id = "move-511" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C. (Move 511/511)" -needs = ["move-510"] - -[[steps]] -id = "verify" -title = "Verify final state" -description = "All 9 disks now on peg C. Tower intact, all moves were legal." -needs = ["move-511"] diff --git a/.beads/formulas/towers-of-hanoi.formula.toml b/.beads/formulas/towers-of-hanoi.formula.toml deleted file mode 100644 index cd698cf00..000000000 --- a/.beads/formulas/towers-of-hanoi.formula.toml +++ /dev/null @@ -1,105 +0,0 @@ -description = """ -AGENT EXECUTION PROTOCOL - Towers of Hanoi - -PURPOSE: This is a durability proof, not computation. Steps are pre-computed. -Your job is to execute them mechanically, proving crash-recovery at scale. - -EXECUTION LOOP: -1. Find current state: bd mol current -2. Find the next ready (unblocked) step -3. Close it: bd close -4. Repeat until no ready steps remain - -ON RESUME (after crash/restart/handoff): -- Same as fresh start. The molecule IS the state. -- Query `bd mol current `, continue from there. -- No memory of previous session needed. - -DO: -- Close steps as fast as possible (they're trivial mechanical moves) -- Use `gt handoff` when context fills (proactive cycling) -- Trust the pre-computed solution - every move is already correct - -DO NOT: -- Try to solve Hanoi yourself - moves are already computed -- Mark steps in_progress - just close them directly -- Ask for permission - this is GUPP territory, just execute -- Stop for human input - run autonomously until complete - -MONITORING: -- Progress: Count closed children of the molecule -- For mega-molecules: Use convoy dashboard when available -- Completion: All steps closed = molecule complete - -This proves Gas Town can execute arbitrarily long workflows with -nondeterministic idempotence - different sessions, same outcome. -""" -formula = "towers-of-hanoi" -version = 2 - -[vars] -[vars.source_peg] -default = "A" -description = "Starting peg" -[vars.target_peg] -default = "C" -description = "Target peg" -[vars.auxiliary_peg] -default = "B" -description = "Helper peg" - -# 3-disk solution: 7 moves (2^3 - 1) -# Each step is a simple acknowledgment - the agent just closes it. - -[[steps]] -id = "setup" -title = "Verify initial state" -description = "All 3 disks stacked on peg A. Largest on bottom." - -[[steps]] -id = "move-1" -title = "Move disk 1: A → C" -description = "Move the smallest disk from peg A to peg C." -needs = ["setup"] - -[[steps]] -id = "move-2" -title = "Move disk 2: A → B" -description = "Move disk 2 from peg A to peg B." -needs = ["move-1"] - -[[steps]] -id = "move-3" -title = "Move disk 1: C → B" -description = "Move disk 1 from peg C to peg B." -needs = ["move-2"] - -[[steps]] -id = "move-4" -title = "Move disk 3: A → C" -description = "Move the largest disk from peg A to peg C." -needs = ["move-3"] - -[[steps]] -id = "move-5" -title = "Move disk 1: B → A" -description = "Move disk 1 from peg B to peg A." -needs = ["move-4"] - -[[steps]] -id = "move-6" -title = "Move disk 2: B → C" -description = "Move disk 2 from peg B to peg C." -needs = ["move-5"] - -[[steps]] -id = "move-7" -title = "Move disk 1: A → C" -description = "Move disk 1 from peg A to peg C." -needs = ["move-6"] - -[[steps]] -id = "verify" -title = "Verify final state" -description = "All 3 disks now on peg C. Tower intact, all moves were legal." -needs = ["move-7"] diff --git a/AGENTS.md b/AGENTS.md index 472dd07bb..8d38bf91f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,3 +7,29 @@ This file exists for compatibility with tools that look for AGENTS.md. > **Recovery**: Run `gt prime` after compaction, clear, or new session Full context is injected by `gt prime` at session start. + +## Landing the Plane (Session Completion) + +**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. + +**MANDATORY WORKFLOW:** + +1. **File issues for remaining work** - Create issues for anything that needs follow-up +2. **Run quality gates** (if code changed) - Tests, linters, builds +3. **Update issue status** - Close finished work, update in-progress items +4. **PUSH TO REMOTE** - This is MANDATORY: + ```bash + git pull --rebase + bd sync + git push + git status # MUST show "up to date with origin" + ``` +5. **Clean up** - Clear stashes, prune remote branches +6. **Verify** - All changes committed AND pushed +7. **Hand off** - Provide context for next session + +**CRITICAL RULES:** +- Work is NOT complete until `git push` succeeds +- NEVER stop before pushing - that leaves work stranded locally +- NEVER say "ready to push when you are" - YOU must push +- If push fails, resolve and retry until it succeeds From ad9db5c3e61ef4d53695bfbe95b03baaaa03ed6f Mon Sep 17 00:00:00 2001 From: mayor Date: Sun, 11 Jan 2026 17:14:46 +0100 Subject: [PATCH 13/41] feat(statusline): add per-agent-type health tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds per-agent-type health tracking to the Mayor's tmux statusline, showing working/idle counts for Polecats, Witnesses, Refineries, and Deacon. All agent types are always displayed, even when no agents of that type are running (shows as '0/0 😺'). Format: active: 4/4 😺 6/10 👁️ 7/10 🏭 1/1 ⛪ --- internal/cmd/statusline.go | 111 +++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 18 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 6a086f50e..521ff2e1c 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -250,24 +250,75 @@ func runMayorStatusLine(t *tmux.Tmux) error { } } + // Track per-agent-type health (working/idle counts) + type sessionHealth struct { + icon string + total int + working int + idle int + } + + // Agent type icons + agentIcons := map[AgentType]string{ + AgentPolecat: "😺", + AgentWitness: "👁️", + AgentRefinery: "🏭", + AgentDeacon: "⛪", + } + + // Initialize health tracker for all agent types (always show all types) + healthByType := make(map[AgentType]*sessionHealth) + for _, agentType := range []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon} { + healthByType[agentType] = &sessionHealth{ + icon: agentIcons[agentType], + } + } + + for _, s := range sessions { + // Skip non-Gas Town sessions + if !strings.HasPrefix(s, "gt-") && !strings.HasPrefix(s, "hq-") { + continue + } + + agent := categorizeSession(s) + if agent == nil { + continue + } + + // Skip mayor and crew (not tracked) + if agent.Type == AgentMayor || agent.Type == AgentCrew { + continue + } + + healthByType[agent.Type].total++ + + // Detect working state (✻ = working, ❯ = idle) + state := getSessionState(t, s) + if state == "working" { + healthByType[agent.Type].working++ + } else if state == "idle" { + healthByType[agent.Type].idle++ + } + // dead sessions counted in total but not working/idle + } + // Build status var parts []string // Add per-agent-type health in consistent order - // Format: "1/10 😺" = 1 working out of 10 total - // Only show agent types that have sessions + // Format: 😺1/10 (1 working out of 10 total, 9 idle inferred) + // Always show all agent types, even when count is 0 agentOrder := []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon} var agentParts []string for _, agentType := range agentOrder { health := healthByType[agentType] - if health.total == 0 { - continue - } - icon := AgentTypeIcons[agentType] - agentParts = append(agentParts, fmt.Sprintf("%d/%d %s", health.working, health.total, icon)) + // Always show all agent types (no continue for total == 0) + + // Show working/total format (e.g., "1/10 😺" = 1 working, 10 total) + agentParts = append(agentParts, fmt.Sprintf("%d/%d %s", health.working, health.total, health.icon)) } if len(agentParts) > 0 { - parts = append(parts, strings.Join(agentParts, " ")) + parts = append(parts, "active: "+strings.Join(agentParts, " ")) } // Build rig status display with LED indicators @@ -629,25 +680,49 @@ func runRefineryStatusLine(t *tmux.Tmux, rigName string) error { return nil } -// isSessionWorking detects if a Claude Code session is actively working. -// Returns true if the ✻ symbol is visible in the pane (indicates Claude is processing). -// Returns false for idle sessions (showing ❯ prompt) or if state cannot be determined. -func isSessionWorking(t *tmux.Tmux, session string) bool { +// getSessionState detects the state of a Claude Code session by capturing pane content. +// Returns "working" if Claude is active (✻ symbol present), "idle" if prompt is visible, +// or "unknown" if the state cannot be determined. +func getSessionState(t *tmux.Tmux, session string) string { // Capture last few lines of the pane lines, err := t.CapturePaneLines(session, 5) if err != nil || len(lines) == 0 { - return false + return "unknown" + } + + // Check last visible line for state indicators + lastLine := strings.TrimSpace(lines[len(lines)-1]) + + // ✻ indicates Claude is working (varies: Incubating, Symbioting, Shenaniganing, etc.) + if strings.Contains(lastLine, "✻") || strings.Contains(lastLine, "✻") { + return "working" + } + + // ❯ prompt indicates Claude is idle, waiting for input + if strings.HasSuffix(lastLine, "❯") || strings.HasSuffix(lastLine, "❯") { + return "idle" + } + + // Check second-to-last line as well (prompt might be on previous line) + if len(lines) >= 2 { + prevLine := strings.TrimSpace(lines[len(lines)-2]) + if strings.HasSuffix(prevLine, "❯") || strings.HasSuffix(prevLine, "❯") { + return "idle" + } + if strings.Contains(prevLine, "✻") || strings.Contains(prevLine, "✻") { + return "working" + } } - // Check all captured lines for the working indicator - // ✻ appears in Claude's status line when actively processing + // Check all lines for working indicator (in case it's not near the end) for _, line := range lines { - if strings.Contains(line, "✻") { - return true + if strings.Contains(line, "✻") || strings.Contains(line, "✻") { + return "working" } } - return false + // Default to unknown if we can't determine state + return "unknown" } // getUnreadMailCount returns unread mail count for an identity. From d6d5e5796a456ddc785a82557a6af0077c6e7031 Mon Sep 17 00:00:00 2001 From: mayor Date: Sun, 11 Jan 2026 18:07:47 +0100 Subject: [PATCH 14/41] feat(statusline): use rig name abbreviations to save space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Abbreviate long rig names (design_forge→df, gastown→gt, etc.) - Update tests for new abbreviations - Addresses issue hq-dn15 --- .beads/issues.jsonl | 2669 ------------------------------- internal/cmd/statusline.go | 43 +- internal/cmd/statusline_test.go | 32 + 3 files changed, 59 insertions(+), 2685 deletions(-) delete mode 100644 .beads/issues.jsonl diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl deleted file mode 100644 index 884713d03..000000000 --- a/.beads/issues.jsonl +++ /dev/null @@ -1,2669 +0,0 @@ -{"id":"gt-00gyg","title":"Digest: mol-deacon-patrol","description":"Cycle 4: quiet patrol","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:10:32.605026-08:00","updated_at":"2025-12-28T13:10:32.605026-08:00","closed_at":"2025-12-28T13:10:32.60499-08:00"} -{"id":"gt-00qjk","title":"BUG: Convoys don't auto-close when all tracked issues complete","description":"Multiple convoys found with 100% completion (1/1, 10/10) but still status=open. According to convoy docs: 'Auto-closes when all tracked issues complete'. Either the auto-close logic isn't running or it's failing silently.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2026-01-02T01:02:59.805842-08:00","created_by":"beads/crew/dave","updated_at":"2026-01-02T13:53:03.635069-08:00","closed_at":"2026-01-02T13:53:03.635069-08:00","close_reason":"Fixed: Added gt convoy check command for cross-rig auto-close"} -{"id":"gt-014ti","title":"Digest: mol-deacon-patrol","description":"P17: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:00:11.182265-08:00","updated_at":"2025-12-25T20:00:11.182265-08:00","closed_at":"2025-12-25T20:00:11.182211-08:00"} -{"id":"gt-01566","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:17:32.991564-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:17:33.048312-08:00","closed_at":"2026-01-06T13:17:33.048312-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:17:32-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-01jpg","title":"Autonomous agents idle at welcome screen after start","description":"dispatched_by: mayor\n\nAfter refinery/witness is killed and respawned by Deacon, the new session sits idle at Claude welcome screen. Root cause: Deacon's respawn logic starts the session but doesn't send the GUPP propulsion nudge. Compare to ensureRefinerySession() in start.go which sends StartupNudge + PropulsionNudgeForRole. The Deacon respawn needs the same treatment. Check deacon patrol code that handles LIFECYCLE/respawn events.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2026-01-05T17:10:43.85745-08:00","created_by":"mayor","updated_at":"2026-01-05T17:14:39.296829-08:00","closed_at":"2026-01-05T17:14:39.296829-08:00","close_reason":"Added StartupNudge and PropulsionNudgeForRole to restartSession in lifecycle.go"} -{"id":"gt-02431","title":"Implement queue:name address type for claim-based mail delivery","description":"Add support for queue:name addresses in the mail router.\n\nSEMANTICS:\n- Messages to queue:name create ONE copy in a shared location\n- Workers eligible for the queue (per messaging.json) can claim messages\n- Claimed message is removed from queue, moved to claimer inbox\n- If claimer fails to process, message can be released back to queue\n\nUSE CASE:\nPolecat completion notifications - Witness OR Deacon should handle, not both.\n\nIMPLEMENTATION:\n1. Add isQueueAddress() / parseQueueName() helpers\n2. Add sendToQueue() - creates message in queue location\n3. Add gt mail claim \u003cqueue\u003e - claims oldest unclaimed message\n4. Add gt mail release \u003cmsg-id\u003e - releases back to queue\n5. Track claim state in message metadata\n\nCONFIG (already in messaging.json schema):\nqueues.cleanup/gastown.workers = [gastown/witness, deacon/]\nqueues.cleanup/gastown.max_claims = 0","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-30T18:09:48.429168-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T18:09:48.429168-08:00","dependencies":[{"issue_id":"gt-02431","depends_on_id":"gt-guyt5","type":"blocks","created_at":"2025-12-30T18:16:10.017968-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-038es","title":"Digest: mol-deacon-patrol","description":"Patrol 2: routine, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:35:42.688017-08:00","updated_at":"2025-12-26T18:35:42.688017-08:00","closed_at":"2025-12-26T18:35:42.687972-08:00"} -{"id":"gt-04cg6","title":"Merge: warboy-mjz94u1q","description":"branch: polecat/warboy-mjz94u1q\ntarget: main\nsource_issue: warboy-mjz94u1q\nrig: gastown\nagent_bead: gt-gastown-polecat-warboy\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T20:58:17.688416-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-03T21:14:26.343796-08:00","closed_at":"2026-01-03T21:14:26.343796-08:00"} -{"id":"gt-050ob","title":"Merge: capable-1767081117001","description":"branch: polecat/capable-1767081117001\ntarget: main\nsource_issue: capable-1767081117001\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:08:10.157148-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T01:01:04.311234-08:00","closed_at":"2025-12-30T01:01:04.311234-08:00","close_reason":"Already merged to main"} -{"id":"gt-051cr","title":"gt channel publish command","description":"New CLI command for ephemeral broadcast to channels.\n\n## Deliverables\n\n1. New command: gt channel publish \u003cchannel\u003e \u003cmessage\u003e\n - Example: gt channel publish #witnesses \"Swarm incoming\"\n2. Resolve channel to running sessions\n3. Nudge each session with message\n4. Report delivery status\n\n## Usage\n```bash\ngt channel publish #town \"Handoff in 5 minutes\"\ngt channel publish #rig/gastown \"Merge queue paused\"\n```\n\n## Dependencies\n- #channel resolution (gt-???)\n\n## Acceptance\n- Command works with #channel syntax\n- Message delivered to running sessions\n- Clear output showing delivery status","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-26T14:52:35.212133-08:00","updated_at":"2025-12-26T14:52:35.212133-08:00","dependencies":[{"issue_id":"gt-051cr","depends_on_id":"gt-zk7wl","type":"blocks","created_at":"2025-12-26T14:53:13.305802-08:00","created_by":"daemon"}]} -{"id":"gt-05rgl","title":"Review PR #95: fix daemon init recommendation","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2026-01-04T10:53:57.658664-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:55:45.74301-08:00","closed_at":"2026-01-04T10:55:45.74301-08:00","close_reason":"PR #95 approved - fix is correct"} -{"id":"gt-063ho","title":"Digest: mol-deacon-patrol","description":"Patrol 10: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:28:42.924964-08:00","updated_at":"2026-01-01T04:28:42.924964-08:00","closed_at":"2026-01-01T04:28:42.924928-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-06dkg","title":"Digest: mol-deacon-patrol","description":"Patrol 8: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:37:35.128629-08:00","updated_at":"2025-12-31T21:37:35.128629-08:00","closed_at":"2025-12-31T21:37:35.128592-08:00"} -{"id":"gt-06he6","title":"Digest: mol-deacon-patrol","description":"Patrol 15: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:38:56.552343-08:00","updated_at":"2025-12-31T21:38:56.552343-08:00","closed_at":"2025-12-31T21:38:56.552302-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-06qoy","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:39:44.230039-08:00","updated_at":"2025-12-31T23:39:44.230039-08:00","closed_at":"2025-12-31T23:39:44.230008-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-07fvg","title":"Digest: mol-deacon-patrol","description":"Patrol 113: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:11:45.553447-08:00","updated_at":"2026-01-01T14:11:45.553447-08:00","closed_at":"2026-01-01T14:11:45.553416-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-07qwd","title":"Digest: mol-deacon-patrol","description":"Patrol 119: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:16:47.301913-08:00","updated_at":"2026-01-01T14:16:47.301913-08:00","closed_at":"2026-01-01T14:16:47.30188-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-08dpu","title":"Digest: mol-deacon-patrol","description":"Patrol 20: final cycle complete, handoff time","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:12:57.492108-08:00","updated_at":"2025-12-31T18:12:57.492108-08:00","closed_at":"2025-12-31T18:12:57.492062-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-095dq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 46: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:54:13.377388-08:00","updated_at":"2026-01-01T12:54:13.377388-08:00","closed_at":"2026-01-01T12:54:13.37735-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-09eim","title":"Merge: toast-1767088545235","description":"branch: polecat/toast-1767088545235\ntarget: main\nsource_issue: toast-1767088545235\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T02:01:08.536019-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T10:06:56.692497-08:00","closed_at":"2025-12-30T10:06:56.692497-08:00","close_reason":"Branch merged to main"} -{"id":"gt-09hq0","title":"Digest: mol-deacon-patrol","description":"Patrol 18: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:05:21.881552-08:00","updated_at":"2025-12-25T00:05:21.881552-08:00","closed_at":"2025-12-25T00:05:21.881524-08:00"} -{"id":"gt-09s5f","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:05:37.927894-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.752226-08:00","closed_at":"2026-01-05T00:08:31.752226-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:05:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-0a0vr","title":"Merge: furiosa-1767087671424","description":"branch: polecat/furiosa-1767087671424\ntarget: main\nsource_issue: furiosa-1767087671424\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:53:07.728514-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T10:06:56.760742-08:00","closed_at":"2025-12-30T10:06:56.760742-08:00","close_reason":"Branch merged to main"} -{"id":"gt-0a90","title":"Add gt hook command (wrapper for bd hook)","description":"Add a thin wrapper command `gt hook` that calls `bd hook` to inspect what's pinned to an agent's hook.\n\n## Usage\n\n```bash\ngt hook # Show what's on current agent's hook\ngt hook --agent deacon # Show Deacon's hook\ngt hook --agent gastown/furiosa # Show polecat's hook\n```\n\n## Implementation\n\nThin wrapper in gt that:\n1. Determines current agent identity\n2. Calls `bd hook [--agent \u003cname\u003e]`\n3. Formats output for gt context\n\n## Why gt wrapper?\n\n- Consistent with gt ecosystem (gt mail, gt status, etc.)\n- Can add gt-specific context (session status, etc.)\n- Easier discovery for gt users\n\n## Related\n\n- bd hook command (implemented by Dave)\n- Chemistry UX design: gastown/mayor/rig/docs/chemistry-design-changes.md","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T02:37:02.429497-08:00","updated_at":"2025-12-22T02:37:02.429497-08:00"} -{"id":"gt-0b1c","title":"Review: Refinery patrol template changes (gt-qz2l)","description":"Polecat dementus implemented refinery template changes: banners, wisp-based execution, propulsion protocol. Review for correctness and consistency with witness/deacon patterns.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T19:57:40.117102-08:00","updated_at":"2025-12-23T19:57:40.117102-08:00"} -{"id":"gt-0cfyq","title":"Merge: dementus-mjw46vz4","description":"branch: polecat/dementus-mjw46vz4\ntarget: main\nsource_issue: dementus-mjw46vz4\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T16:10:20.360033-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-01T16:11:17.378239-08:00","closed_at":"2026-01-01T16:11:17.378239-08:00"} -{"id":"gt-0cu3o","title":"[Refactor] Consolidate duplicate clone-with-reference-fallback pattern","description":"The pattern of 'try CloneWithReference, warn, fallback to Clone' appears in 3+ locations:\n\n1. rig/manager.go:274-285: CloneBare with reference\n2. rig/manager.go:314-326: Clone for mayor \n3. crew/manager.go:74-85: Clone for crew\n\nShould extract to a helper like:\n func (g *Git) CloneWithReferenceFallback(url, dest, ref string, bare bool) error\n\nThis would reduce duplication and ensure consistent error messaging.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:51.880912-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-04T23:47:51.880912-08:00"} -{"id":"gt-0cys","title":"Digest: mol-deacon-patrol","description":"Patrol 5: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T21:26:42.913686-08:00","updated_at":"2025-12-24T21:26:42.913686-08:00","closed_at":"2025-12-24T21:26:42.913655-08:00"} -{"id":"gt-0d2qf","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:40:19.900797-08:00","updated_at":"2025-12-31T18:40:19.900797-08:00","closed_at":"2025-12-31T18:40:19.900761-08:00"} -{"id":"gt-0dbrl","title":"Digest: mol-deacon-patrol","description":"Patrol 251 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:21:50.52547-08:00","updated_at":"2026-01-01T17:21:50.52547-08:00","closed_at":"2026-01-01T17:21:50.525439-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-0dewv","title":"Digest: mol-deacon-patrol","description":"Patrol 14: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:38:45.299191-08:00","updated_at":"2025-12-31T21:38:45.299191-08:00","closed_at":"2025-12-31T21:38:45.299159-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-0e827","title":"Digest: mol-deacon-patrol","description":"Patrol 86: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:03:57.66782-08:00","updated_at":"2026-01-01T03:03:57.66782-08:00","closed_at":"2026-01-01T03:03:57.667775-08:00","dependencies":[{"issue_id":"gt-0e827","depends_on_id":"gt-eph-4slq","type":"parent-child","created_at":"2026-01-01T03:03:57.669018-08:00","created_by":"deacon"}]} -{"id":"gt-0eh3r","title":"gt done fails in worktree: missing remote.origin.fetch config","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/dementus","created_at":"2026-01-01T11:27:02.36225-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T18:15:41.30773-08:00","closed_at":"2026-01-01T18:15:41.30773-08:00","close_reason":"Added ls-remote fallback when tracking ref unavailable due to missing fetch refspec"} -{"id":"gt-0fs16","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 53: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:58:11.447854-08:00","updated_at":"2026-01-01T12:58:11.447854-08:00","closed_at":"2026-01-01T12:58:11.44781-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-0h89l","title":"Merge: furiosa-1767084006859","description":"branch: polecat/furiosa-1767084006859\ntarget: main\nsource_issue: furiosa-1767084006859\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:47:11.801436-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T01:01:04.252855-08:00","closed_at":"2025-12-30T01:01:04.252855-08:00","close_reason":"Already merged to main"} -{"id":"gt-0hrb9","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T17:39:50.088178-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:39:50.143663-08:00","closed_at":"2026-01-06T17:39:50.143663-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T17:39:50-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-0hu24","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:22:32.133665-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.649706-08:00","closed_at":"2026-01-05T00:08:31.649706-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:22:32-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-0i685","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:36:05.974887-08:00","updated_at":"2025-12-31T23:36:05.974887-08:00","closed_at":"2025-12-31T23:36:05.974841-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-0igzb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:16:43.688437-08:00","updated_at":"2026-01-01T07:16:43.688437-08:00","closed_at":"2026-01-01T07:16:43.688398-08:00"} -{"id":"gt-0iy3","title":"Merge: gt-3x1.3","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-3x1.3\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:52.741123-08:00","updated_at":"2025-12-19T19:13:27.737052-08:00","closed_at":"2025-12-19T17:47:03.618858-08:00"} -{"id":"gt-0jq9p","title":"Digest: mol-deacon-patrol","description":"Cycle 8","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:54:15.852968-08:00","updated_at":"2025-12-31T23:54:15.852968-08:00","closed_at":"2025-12-31T23:54:15.852929-08:00"} -{"id":"gt-0kboy","title":"Digest: mol-deacon-patrol","description":"Patrol complete: no work, gastown refinery came online, town healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:17:43.120158-08:00","updated_at":"2025-12-28T19:17:43.120158-08:00","closed_at":"2025-12-28T19:17:43.120127-08:00"} -{"id":"gt-0kmv2","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 25: quick check, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:29:19.653554-08:00","updated_at":"2026-01-01T19:29:19.653554-08:00","closed_at":"2026-01-01T19:29:19.653505-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-0l0by","title":"Digest: mol-deacon-patrol","description":"Patrol 149: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:00:30.714756-08:00","updated_at":"2026-01-01T15:00:30.714756-08:00","closed_at":"2026-01-01T15:00:30.714711-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-0l5a0","title":"Merge: gt-s7t1h","description":"branch: polecat/dag-mjxm10sv\ntarget: main\nsource_issue: gt-s7t1h\nrig: gastown\nagent_bead: gt-mayor","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:45:01.243896-08:00","created_by":"mayor","updated_at":"2026-01-02T17:48:09.899685-08:00","closed_at":"2026-01-02T17:48:09.899685-08:00","close_reason":"Merged to main at a15f4bb7 (dag-mjxm10sv restart feature)"} -{"id":"gt-0lop3","title":"Agent state lifecycle incomplete for polecats","description":"## Problem\n\nThe witness patrol formula (mol-witness-patrol.formula.toml) expects polecats to self-report states:\n- running\n- idle\n- stuck\n- done\n\nBut looking at the code, the only state transitions that actually happen are:\n\n1. **spawning** - Set when polecat is created (polecat/manager.go:170)\n2. **running** - Set when agent runs `gt prime` (prime.go:112)\n3. **dead** - Set by daemon when agent goes unresponsive (daemon/lifecycle.go:647)\n\n**Missing transitions:**\n- `stuck` - No code path exists for agents to report this\n- `done` - No code path exists for agents to report this\n- `idle` - Only set for infrastructure agents, never for polecats\n\n## Impact\n\nThe witness cannot rely on agent_state to detect stuck or done polecats, contradicting the ZFC principle stated in the formula.\n\n## Found in commit\n\nf3a6ef6 (feat: Witness reads polecat state from agent beads)\n\n## Suggested fix\n\nAdd code paths for polecats to self-report:\n1. `gt done` should update agent_state to \"done\"\n2. When stuck (detected how?), agent should update to \"stuck\"\n3. Consider if \"idle\" makes sense for polecats (no current work)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-28T09:47:43.25406-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T09:54:40.40087-08:00","closed_at":"2025-12-28T09:54:40.40087-08:00"} -{"id":"gt-0nh8","title":"gt prime should detect mayor role from any rig's mayor/ folder","description":"Currently gt prime only detects the Mayor role when run from town root (~/gt). It should also detect Mayor when run from:\n- ~/gt/gastown/mayor/rig (rig's internal mayor dir)\n- Any path containing /mayor/ under a rig\n\nThis would allow the mayor session to work correctly regardless of which rig directory it's attached to.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/dementus","created_at":"2025-12-20T21:56:10.281534-08:00","updated_at":"2025-12-29T23:56:24.749823-08:00","closed_at":"2025-12-29T23:56:24.749823-08:00","close_reason":"Fixed: Added mayor detection for \u003crig\u003e/mayor/ paths in detectRole(). Now gt prime detects Mayor from ~/gt/gastown/mayor/rig and similar paths."} -{"id":"gt-0npbt","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:22:27.945031-08:00","updated_at":"2026-01-01T05:22:27.945031-08:00","closed_at":"2026-01-01T05:22:27.945-08:00"} -{"id":"gt-0ol","title":"Update prompts.md: Engineer role and templates","description":"Update docs/prompts.md with Engineer role:\n\n1. Role Prompts table: Change Refinery to Engineer\n2. Add Engineer-specific prompts:\n - Session restart request template\n - Subtask filing template\n - Handoff mail template\n3. Update refinery.md template name to engineer.md\n4. Ensure consistency with architecture.md","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T23:12:05.279233-08:00","updated_at":"2025-12-16T23:12:05.279233-08:00","dependencies":[{"issue_id":"gt-0ol","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:12:15.013747-08:00","created_by":"daemon"}]} -{"id":"gt-0pdhj","title":"Remove all hardcoded gastown dependencies from gt codebase","description":"The Go codebase should not have hardcoded dependencies on gastown (the rig name).\n\nFound in prime.go outputDeaconPatrolContext() - FIXED in this session.\n\nOther potential issues to audit:\n- Check all patrol context functions (Witness, Refinery) for similar patterns\n- Ensure rig-specific paths are derived from context, not hardcoded\n- Test with a different rig name to verify\n\nThe principle: Gas Town should work with any rig name, not just gastown.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:21:50.570904-08:00","updated_at":"2025-12-28T01:24:59.010519-08:00","closed_at":"2025-12-28T01:24:59.010519-08:00"} -{"id":"gt-0q3cg","title":"Add isQueueAddress() and parseQueueName() helpers to router.go","description":"Add queue address detection to internal/mail/router.go.\n\nPATTERN TO FOLLOW:\nLook at isListAddress() and parseListName() at lines 53-60 as the template.\n\nIMPLEMENTATION:\n1. Add isQueueAddress(address string) bool - returns true if address starts with 'queue:'\n2. Add parseQueueName(address string) string - extracts queue name after 'queue:'\n\nFILE: internal/mail/router.go\nTESTS: Add tests in internal/mail/router_test.go following the pattern of TestIsListAddress/TestParseListName\n\nThis is a small, focused task. Do not implement sendToQueue or claiming - just the address detection.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T18:15:35.248204-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T22:09:43.974421-08:00","closed_at":"2025-12-30T22:09:43.974421-08:00","close_reason":"Added isQueueAddress() and parseQueueName() helpers with tests"} -{"id":"gt-0qis6","title":"Digest: mol-deacon-patrol","description":"Patrol 16: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:57:45.653341-08:00","updated_at":"2026-01-01T10:57:45.653341-08:00","closed_at":"2026-01-01T10:57:45.653305-08:00"} -{"id":"gt-0t208","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:29:56.426482-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.817511-08:00","closed_at":"2026-01-05T00:08:31.817511-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:29:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-0ua3f","title":"Merge: capable-1767079826600","description":"branch: polecat/capable-1767079826600\ntarget: main\nsource_issue: capable-1767079826600\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:37:39.344583-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-29T23:43:15.624256-08:00","closed_at":"2025-12-29T23:43:15.624256-08:00","close_reason":"Merged to main (f9e82098)"} -{"id":"gt-0vdje","title":"Merge: gastown-mk0voe9u","description":"branch: polecat/gastown-mk0voe9u\ntarget: main\nsource_issue: gastown-mk0voe9u\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:11:26.207984-08:00","created_by":"gastown/polecats/gastown","updated_at":"2026-01-05T19:21:40.827945-08:00","closed_at":"2026-01-05T19:21:40.827945-08:00","close_reason":"Merged to main at 43cca064"} -{"id":"gt-0vu9e","title":"Add unit tests for internal/mrqueue package","description":"attached_args: mrqueue package tests\n\nAdd comprehensive tests for the merge request queue package.\n\n## Files to create\n- internal/mrqueue/mrqueue_test.go\n\n## Test cases to cover\n1. NewQueue creates queue directory\n2. Add() persists MR to queue\n3. Get() retrieves MR by ID\n4. List() returns all MRs\n5. Remove() deletes MR\n6. MR serialization/deserialization\n7. Queue handles concurrent access\n\n## Acceptance criteria\n- [ ] internal/mrqueue/mrqueue_test.go created\n- [ ] At least 6 test functions\n- [ ] Tests pass: go test ./internal/mrqueue/...\n- [ ] Coverage \u003e 70%","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:12.750237-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:57:05.876953-08:00"} -{"id":"gt-0vvo1","title":"[Go Idiom] Remove panic in MustGetTownName","description":"workspace/find.go:155-158 uses panic in MustGetTownName(). Panics in library code are an anti-pattern - they make error handling impossible for callers. Either:\n1. Remove the Must* variant entirely (callers use GetTownName with proper error handling)\n2. If convenience function needed, return empty string on error with logging\n\nCurrent usage should be audited to ensure callers can handle errors gracefully.","status":"open","priority":4,"issue_type":"task","created_at":"2026-01-04T23:48:06.351409-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-04T23:48:06.351409-08:00"} -{"id":"gt-0wo9k","title":"Digest: mol-deacon-patrol","description":"Patrol 19","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:12:43.900306-08:00","updated_at":"2026-01-01T09:12:43.900306-08:00","closed_at":"2026-01-01T09:12:43.90027-08:00"} -{"id":"gt-0wpnf","title":"Digest: mol-deacon-patrol","description":"Patrol 17: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:56:45.271323-08:00","updated_at":"2025-12-28T15:56:45.271323-08:00","closed_at":"2025-12-28T15:56:45.271291-08:00"} -{"id":"gt-0x4md","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:04:47.772713-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.001513-08:00","closed_at":"2026-01-04T16:41:26.001513-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:04:47-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-0x5og","title":"Dogs: Deacon's Helper Workers","description":"## Overview\n\nDogs are reusable workers managed by the Deacon for infrastructure and cleanup tasks.\nThey parallel how Polecats serve the Witness, but at town level with cross-rig scope.\n\n## Key Concepts\n\n- **Dogs**: Deacon-managed, reusable, infrastructure/cleanup tasks\n- **Kennel**: Where dogs live (`deacon/dogs/`)\n- **Multi-rig worktrees**: Dogs have worktrees into multiple rigs for cross-rig work\n\n## Cats vs Dogs\n\n| Aspect | Polecats | Dogs |\n|--------|----------|------|\n| Manager | Witness | Deacon |\n| Scope | Per-rig | Town (cross-rig) |\n| Lifecycle | Ephemeral | Reusable |\n| Work | Features | Infrastructure |\n| Location | `\u003crig\u003e/polecats/` | `deacon/dogs/` |\n\n## Implementation\n\n### Phase 1: Dog Infrastructure\n- `gt dog add/remove/list/call/status` commands\n- Kennel directory structure (`~/gt/deacon/dogs/`)\n- Multi-rig worktree creation\n- Dog state tracking\n\n### Phase 2: Deacon Dispatch\n- Sling support for `deacon/dogs` target\n- Pool management (spawn/retire logic)\n- Completion mail handling\n\n### Phase 3: Infrastructure Formulas\n- mol-convoy-cleanup\n- mol-dep-propagate\n- mol-digest-generate\n\n### Phase 4: Deacon Refactor\n- Patrol becomes detect → dispatch\n- Heavy work moves to dog slings\n\n## Reference\n\n- docs/patrol-system-design.md#dogs-deacons-helper-workers\n- docs/PRIMING.md (Role Taxonomy)","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-29T19:34:00.808508-08:00","created_by":"mayor","updated_at":"2025-12-30T13:30:03.009683-08:00","closed_at":"2025-12-30T13:30:03.009683-08:00","close_reason":"All children complete"} -{"id":"gt-0x5og.1","title":"gt dog add/remove/list/call/status CLI","description":"Dog management commands:\n- gt dog add \u003cname\u003e - Create dog in kennel with multi-rig worktrees\n- gt dog remove \u003cname\u003e - Retire dog, cleanup worktrees\n- gt dog list - Show the pack (all dogs with status)\n- gt dog call [name] - Wake idle dog(s)\n- gt dog status [name] - Show detailed dog state","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T19:34:24.005184-08:00","created_by":"mayor","updated_at":"2025-12-30T10:41:57.247255-08:00","closed_at":"2025-12-30T10:41:57.247255-08:00","close_reason":"Implemented all gt dog CLI commands: add, remove, list, call, status","dependencies":[{"issue_id":"gt-0x5og.1","depends_on_id":"gt-0x5og","type":"parent-child","created_at":"2025-12-29T19:34:24.005762-08:00","created_by":"daemon"},{"issue_id":"gt-0x5og.1","depends_on_id":"gt-0x5og.2","type":"blocks","created_at":"2025-12-29T19:34:37.683244-08:00","created_by":"daemon"}]} -{"id":"gt-0x5og.2","title":"Kennel directory structure and multi-rig worktrees","description":"Create kennel infrastructure:\n- ~/gt/deacon/dogs/\u003cname\u003e/ directory\n- Worktrees into each rig (gastown, beads, etc.)\n- .dog.json state file (idle/working, last-active, assigned-work)\n- Worktree refresh/cleanup logic","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2025-12-29T19:34:25.403417-08:00","created_by":"mayor","updated_at":"2025-12-30T10:35:43.182328-08:00","closed_at":"2025-12-30T10:35:43.182328-08:00","close_reason":"Implemented internal/dog package with Manager, Dog struct, .dog.json schema, multi-rig worktrees, and refresh/cleanup logic","dependencies":[{"issue_id":"gt-0x5og.2","depends_on_id":"gt-0x5og","type":"parent-child","created_at":"2025-12-29T19:34:25.403973-08:00","created_by":"daemon"}]} -{"id":"gt-0x5og.3","title":"gt sling support for deacon/dogs target","description":"Extend gt sling to support dog targets:\n- gt sling \u003cwork\u003e deacon/dogs - Auto-dispatch to idle dog\n- gt sling \u003cwork\u003e deacon/dogs/alpha - Specific dog\n- Dog pool management (spawn if needed, up to max)\n- Completion mail handling","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T19:34:26.93247-08:00","created_by":"mayor","updated_at":"2025-12-30T10:52:44.645382-08:00","closed_at":"2025-12-30T10:52:44.645382-08:00","close_reason":"Implemented: gt sling deacon/dogs and deacon/dogs/\u003cname\u003e targets with pool management","dependencies":[{"issue_id":"gt-0x5og.3","depends_on_id":"gt-0x5og","type":"parent-child","created_at":"2025-12-29T19:34:26.933063-08:00","created_by":"daemon"},{"issue_id":"gt-0x5og.3","depends_on_id":"gt-0x5og.1","type":"blocks","created_at":"2025-12-29T19:34:37.730391-08:00","created_by":"daemon"}]} -{"id":"gt-0x5og.4","title":"Deacon patrol refactor: detect → dispatch","description":"Refactor Deacon patrol to delegate heavy work to dogs:\n- check-conditions → sling to dog (not inline execution)\n- Pool maintenance step (spawn/retire/refresh)\n- Completion mail handling from dogs\n- Keep patrol lightweight (detection only)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T19:34:27.968478-08:00","created_by":"mayor","updated_at":"2025-12-30T11:00:54.598311-08:00","closed_at":"2025-12-30T11:00:54.598311-08:00","close_reason":"Refactored patrol: added DOG_DONE handling, dog-pool-maintenance, detect-only orphan-check and session-gc","dependencies":[{"issue_id":"gt-0x5og.4","depends_on_id":"gt-0x5og","type":"parent-child","created_at":"2025-12-29T19:34:27.969077-08:00","created_by":"daemon"},{"issue_id":"gt-0x5og.4","depends_on_id":"gt-0x5og.3","type":"blocks","created_at":"2025-12-29T19:34:37.778037-08:00","created_by":"daemon"}]} -{"id":"gt-0x5og.5","title":"Infrastructure formulas for dog tasks","description":"Create formulas for dog-executed tasks:\n- mol-convoy-cleanup: Archive convoy, notify overseer\n- mol-dep-propagate: Cross-rig dependency resolution\n- mol-digest-generate: Daily digest for overseer\n- mol-orphan-scan: Find and reassign orphaned work\n- mol-session-gc: Clean stale sessions","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/keeper","created_at":"2025-12-29T19:34:29.492215-08:00","created_by":"mayor","updated_at":"2025-12-30T10:36:01.579942-08:00","closed_at":"2025-12-30T10:36:01.579942-08:00","close_reason":"Created 5 infrastructure formulas for dog tasks: convoy-cleanup, dep-propagate, digest-generate, orphan-scan, session-gc","dependencies":[{"issue_id":"gt-0x5og.5","depends_on_id":"gt-0x5og","type":"parent-child","created_at":"2025-12-29T19:34:29.492767-08:00","created_by":"daemon"},{"issue_id":"gt-0x5og.5","depends_on_id":"gt-0x5og.4","type":"blocks","created_at":"2025-12-29T19:34:37.82534-08:00","created_by":"daemon"}]} -{"id":"gt-0xhuz","title":"mol-sync-workspace: Add explicit gt prime / bd prime in assess-state","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-30T19:11:05.420936-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T22:45:58.676563-08:00","closed_at":"2025-12-30T22:45:58.676563-08:00","close_reason":"Added gt prime / bd prime commands as Step 0 in assess-state, with explanatory comment about when priming is critical"} -{"id":"gt-0xtry","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:09:33.577321-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T21:09:33.627906-08:00","closed_at":"2026-01-05T21:09:33.627906-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:09:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-0xuso","title":"Digest: mol-deacon-patrol","description":"P10: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:59:07.504644-08:00","updated_at":"2025-12-25T19:59:07.504644-08:00","closed_at":"2025-12-25T19:59:07.504589-08:00"} -{"id":"gt-0zefw","title":"Standardize error handling and warning output patterns","description":"Inconsistent patterns across codebase:\n\nError wrapping:\n- Some: fmt.Errorf(\"context: %w\", err) (good)\n- Some: return err (loses context)\n- Some: fmt.Errorf(\"message\", rigName) without wrapping original\n\nExit handling in Cobra commands:\n- Some use os.Exit(1) inside RunE (bad - loses error chain)\n- Some properly return errors\n\nWarning output styles:\n- fmt.Printf(\"%s Warning: ...\", style.Dim.Render(\"⚠\"))\n- fmt.Printf(\"Warning: %s\", ...)\n- fmt.Fprintf(os.Stderr, \"warning: ...\")\n\nSuggestion:\n1. Always wrap errors with %w\n2. Never call os.Exit() in RunE handlers\n3. Standardize on style.Warning.Render(\"Warning:\") pattern","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:43:18.89794-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:22.183478-08:00","closed_at":"2025-12-28T15:47:22.183478-08:00"} -{"id":"gt-0zek2","title":"Digest: mol-deacon-patrol","description":"Patrol 85: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:03:18.326578-08:00","updated_at":"2026-01-01T03:03:18.326578-08:00","closed_at":"2026-01-01T03:03:18.326546-08:00"} -{"id":"gt-0zpdn","title":"Day 4.5: Test multi-step molecule lifecycle","description":"Integration test (UPDATED for self-managed handoffs):\n1. Sling work with molecule to polecat\n2. Polecat works through all steps (self-handoffs as context fills)\n3. Polecat calls gt done when work complete\n4. Witness verifies clean state and sends MERGE_READY to refinery\n5. Refinery merges branch\n6. Refinery sends MERGED to witness\n7. Witness calls gt polecat nuke for full cleanup\n8. Verify clean state (no worktree, no branch, agent bead closed)\n\n**VALIDATED**: rictus lifecycle worked end-to-end: gt done → witness → refinery → merged\n\nParent: gt-4a2qt","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:08.06509-08:00","created_by":"mayor","updated_at":"2025-12-28T16:12:02.015887-08:00","closed_at":"2025-12-28T16:12:02.015887-08:00","dependencies":[{"issue_id":"gt-0zpdn","depends_on_id":"gt-4a2qt","type":"parent-child","created_at":"2025-12-27T20:58:47.568249-08:00","created_by":"daemon"},{"issue_id":"gt-0zpdn","depends_on_id":"gt-zb0io","type":"blocks","created_at":"2025-12-27T20:58:56.884662-08:00","created_by":"daemon"},{"issue_id":"gt-0zpdn","depends_on_id":"gt-ztpe8","type":"blocks","created_at":"2025-12-27T20:58:57.915265-08:00","created_by":"daemon"}]} -{"id":"gt-102fu","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:00:48.116823-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.444626-08:00","closed_at":"2026-01-05T00:08:31.444626-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:00:48-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-105q3","title":"gt mail clear --all: Add flag for agent ergonomics","description":"## Task\n\nAdd `--all` flag to `gt mail clear` as an affordance.\n\nThe command already clears all messages by default, but agents naturally try `--all` when they want to clear everything. Adding it as a no-op flag improves ergonomics.\n\n## Implementation\n\nIn `internal/cmd/mail_clear.go` (or similar):\n\n```go\nvar clearAll bool\n\nfunc init() {\n clearCmd.Flags().BoolVar(\u0026clearAll, \"all\", false, \"Clear all messages (default behavior)\")\n}\n```\n\nThe flag doesn't change behavior - it's just for discoverability and natural agent usage patterns.","status":"closed","priority":3,"issue_type":"chore","assignee":"gastown/polecats/nux","created_at":"2026-01-02T13:42:48.26628-08:00","created_by":"mayor","updated_at":"2026-01-02T13:45:59.186386-08:00","closed_at":"2026-01-02T13:45:59.186386-08:00","close_reason":"Added --all flag to gt mail clear as no-op for agent ergonomics"} -{"id":"gt-11bjg","title":"Merge: warboy-mjwjbptd","description":"branch: polecat/warboy-mjwjbptd\ntarget: main\nsource_issue: warboy-mjwjbptd\nrig: gastown\nagent_bead: gt-gastown-polecat-warboy","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:16:59.514171-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-01T23:37:13.017559-08:00","closed_at":"2026-01-01T23:37:13.017559-08:00","close_reason":"Branch reset to main - work superseded by existing code"} -{"id":"gt-11z8l","title":"gt rig start \u003crig\u003e... - start witness + refinery on patrol","description":"Start one or more rigs by launching their witness and refinery workers on patrol. Should support multiple rigs: gt rig start gastown beads","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T11:49:47.02983-08:00","created_by":"mayor","updated_at":"2026-01-02T12:44:02.059813-08:00","closed_at":"2026-01-02T12:44:02.059813-08:00","close_reason":"Implemented gt rig start command with multi-rig support","dependencies":[{"issue_id":"gt-11z8l","depends_on_id":"gt-yyht4","type":"blocks","created_at":"2026-01-02T11:50:01.646244-08:00","created_by":"mayor"}]} -{"id":"gt-11zdz","title":"Digest: mol-deacon-patrol","description":"Cycle 3: quiet patrol","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:08:45.744596-08:00","updated_at":"2025-12-28T13:08:45.744596-08:00","closed_at":"2025-12-28T13:08:45.744565-08:00"} -{"id":"gt-1201h","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:02:14.201769-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:02:14.255822-08:00","closed_at":"2026-01-06T13:02:14.255822-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:02:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-1231m","title":"Session ended: gt-gastown-dinki","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:15:57.649378-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-05T00:08:31.861867-08:00","closed_at":"2026-01-05T00:08:31.861867-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/dinki","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:15:57-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-dinki\",\"worker\":\"dinki\"}"} -{"id":"gt-12hwb","title":"Phase 4: Handle conflict resolution edge case","description":"Address edge case: conflict detected AFTER polecat worktree is nuked.\n\nProblem: If polecat is cleaned up before MR merges, local branch is gone.\n\nOptions:\n1. **Delay cleanup** (recommended): Witness doesn't nuke polecats with pending MRs\n2. Copy branch to holding namespace before cleanup\n3. Push branch only when conflict detected\n\nRecommendation: Option 1 - polecat isn't truly 'done' until work is merged.\n\nFiles:\n- Witness cleanup logic\n- internal/formula/formulas/mol-polecat-conflict-resolve.formula.toml:149-152","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T12:37:00.168649-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:11:38.254646-08:00","closed_at":"2026-01-06T13:11:38.254646-08:00","close_reason":"Implemented Phase 4: Witness now defers polecat cleanup for pending MRs, preserving local branches for conflict resolution","dependencies":[{"issue_id":"gt-12hwb","depends_on_id":"gt-5fmjt","type":"blocks","created_at":"2026-01-06T12:37:09.251054-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-1483k","title":"Digest: mol-deacon-patrol","description":"Patrol 2: No callbacks, 2 convoys in progress, all agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:13:34.316963-08:00","updated_at":"2025-12-31T14:13:34.316963-08:00","closed_at":"2025-12-31T14:13:34.316933-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-14xej","title":"Add timeouts to convoy panel subprocess calls","description":"convoy.go spawns bd and sqlite3 without timeouts. If these hang, the TUI freezes. Add 5-second context timeouts.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2025-12-30T23:21:54.313979-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-30T23:26:05.335721-08:00","closed_at":"2025-12-30T23:26:05.335721-08:00","close_reason":"Added 5-second context timeouts to convoy panel subprocess calls"} -{"id":"gt-15ho5","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:46:37.860744-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.687491-08:00","closed_at":"2026-01-05T19:44:18.687491-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:46:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-16213","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:37:40.357177-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.620143-08:00","closed_at":"2026-01-05T00:08:31.620143-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:37:39-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-17wdl","title":"Add prefix mismatch detection to gt doctor","description":"## Context\n\nWhen investigating PR #183 (rig agent beads prefix fix), we discovered that rigs.json\nhad `\"prefix\": \"ga\"` for gastown, but the actual beads database uses `gt-` prefix.\n\nThis happened because:\n1. `deriveBeadsPrefix(\"gastown\")` returns \"ga\" (first 2 chars of single word)\n2. But beads were initialized with \"gt\" (perhaps before auto-derive existed)\n3. rigs.json stored the wrong derived prefix\n\n## Problem\n\nThere's no validation that the prefix in rigs.json matches what's actually in the\nbeads database. This can cause agent lifecycle management to fail silently (looking\nfor `ga-gastown-witness` when `gt-gastown-witness` exists).\n\n## Suggested Fix\n\nAdd a check to `gt doctor` that:\n1. For each rig in rigs.json, get the configured prefix\n2. Query the rig's beads database for its actual prefix (from config or existing beads)\n3. Warn if they don't match\n\nExample output:\n```\n⚠ Prefix mismatch for rig 'gastown':\n rigs.json says: ga\n beads db uses: gt\n Run: gt rig set-prefix gastown gt\n```\n\n## Related\n\n- Commit e8d27e7: fix rig agent beads prefix\n- PR #183: original partial fix by Johann Taberlet","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2026-01-05T21:23:58.011831-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:30:28.791528-08:00","closed_at":"2026-01-05T21:30:28.791528-08:00","close_reason":"Implemented prefix mismatch detection check for gt doctor"} -{"id":"gt-1847v","title":"Document Boot vs Deacon lifecycle and fix design confusion","description":"## Problem\n\nThe Boot/Deacon relationship is confusing and possibly over-engineered:\n\n### Current Design\n```\nDaemon (Go process, 3-min heartbeat)\n │\n └─► Boot (ephemeral triage dog)\n │\n └─► Decides: start/wake/nudge/interrupt Deacon?\n │\n └─► Deacon (persistent patrol agent)\n │\n └─► health-scan: restart witness/refinery\n```\n\n### Questions\n\n1. **Why two agents?** Boot exists to avoid waking Deacon unnecessarily in idle towns. But is this complexity worth it?\n\n2. **Session ownership**: Boot should run in `gt-deacon-boot`, Deacon in `gt-deacon`. But current behavior is confused.\n\n3. **Handoff**: When Boot starts Deacon, what happens to Boot? Does it exit? Hand off?\n\n4. **Fallback**: Daemon has `checkDeaconHeartbeat()` as belt-and-suspenders. When does this fire vs Boot?\n\n## Options\n\n### Option A: Keep Boot/Deacon separation (fix implementation)\n- Boot is ephemeral, spawns fresh each heartbeat\n- Boot runs in `gt-deacon-boot`, exits after triage\n- Deacon runs in `gt-deacon`, persistent patrol\n- Clear session boundaries, clear lifecycle\n\n### Option B: Merge Boot into Deacon\n- Single `gt-deacon` session\n- Deacon handles its own 'should I be awake?' logic\n- Simpler, fewer moving parts\n- Trade-off: Deacon consumes context even when idle\n\n### Option C: Replace with simpler watchdog\n- Daemon directly monitors witness/refinery\n- No Boot, no Deacon AI agents for health checks\n- Just Go code: if session dead, restart it\n- AI agents only for complex decisions (escalations)\n\n## Recommendation\n\nOption A with clear documentation. The separation has merit for cost control in idle towns. But the implementation needs fixing.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/morsov","created_at":"2026-01-02T18:43:34.079036-08:00","created_by":"mayor","updated_at":"2026-01-02T18:54:39.15708-08:00","closed_at":"2026-01-02T18:54:39.15708-08:00","close_reason":"Documentation complete: created docs/watchdog-chain.md with full lifecycle explanation, design decision (keep separation), and cross-references"} -{"id":"gt-1892c","title":"Session ended: gt-gastown-citadel","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:50:35.012195-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T00:08:31.517572-08:00","closed_at":"2026-01-05T00:08:31.517572-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/citadel","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:50:34-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-citadel\",\"worker\":\"citadel\"}"} -{"id":"gt-18t2r","title":"Digest: mol-deacon-patrol","description":"Patrol 54: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:23:14.88066-08:00","updated_at":"2026-01-01T02:23:14.88066-08:00","closed_at":"2026-01-01T02:23:14.880625-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1alp3","title":"Digest: mol-deacon-patrol","description":"Patrol 12: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:27:51.596348-08:00","updated_at":"2025-12-25T07:27:51.596348-08:00","closed_at":"2025-12-25T07:27:51.59631-08:00"} -{"id":"gt-1clzd","title":"gt sling fails for terminated polecats even with --naked flag","description":"## Problem\nWhen a polecat terminates after completing work (submits MR, session ends), the polecat directory still exists but the tmux session is gone. Attempting to sling new work to that polecat fails:\n\n```\ngt sling bd-fa1q beads/Toast --naked\nError: resolving target: getting pane for gt-beads-toast: exit status 1\n```\n\nThe `--naked` flag should bypass tmux pane requirements, but the error occurs during target resolution before the flag is checked.\n\n## Expected Behavior\n`gt sling \u003cbead\u003e \u003cpolecat\u003e --naked` should:\n1. Attach work to the polecat hook\n2. Skip session creation (manual start later)\n3. NOT require an existing tmux pane\n\n## Workaround\nUse crew workers instead (they have persistent sessions).\n\n## Fix\nTarget resolution should check `--naked` flag before attempting pane lookup, or provide a way to respawn terminated polecats.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/ace","created_at":"2025-12-28T21:25:07.366075-08:00","created_by":"mayor","updated_at":"2025-12-29T22:04:47.278313-08:00","closed_at":"2025-12-29T22:04:47.278313-08:00","close_reason":"Fixed: resolveTargetAgent now skips tmux pane lookup when --naked flag is set"} -{"id":"gt-1dbcp","title":"Polecat auto-start: Claude doesn't process initial nudge","description":"After gt sling spawns a polecat, the 'Work slung' message is sent to tmux but Claude sits idle at the prompt. The SessionStart hook doesn't fire because no user input was received.\n\nObserved:\n- gt sling successfully spawns polecat, creates worktree, starts Claude\n- Sends 'Work slung: gt-xxx. Start working on it now...' to the pane\n- Claude shows idle prompt 'Try refactor...' and doesn't process the message\n\nExpected:\n- Polecat should auto-start working on the slung issue\n\nRoot cause hypothesis:\n- The nudge is sent as tmux send-keys which goes to the input line\n- Claude needs Enter to be pressed to submit the prompt\n- SessionStart hook only fires after first user message\n\nWorkaround:\n- Send extra Enter after the nudge message\n- Or use daemon's triggerPendingSpawns to send Enter after Claude is ready","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-27T18:31:34.71552-08:00","created_by":"mayor","updated_at":"2025-12-28T16:17:40.168164-08:00","closed_at":"2025-12-28T16:17:40.168164-08:00","dependencies":[{"issue_id":"gt-1dbcp","depends_on_id":"gt-j9ddg","type":"relates-to","created_at":"2025-12-27T20:59:11.65084-08:00","created_by":"daemon"},{"issue_id":"gt-1dbcp","depends_on_id":"gt-0zpdn","type":"blocks","created_at":"2025-12-27T21:21:26.458611-08:00","created_by":"daemon"}]} -{"id":"gt-1edmp","title":"Merge: toast-mjw7062w","description":"branch: polecat/toast-mjw7062w\ntarget: main\nsource_issue: toast-mjw7062w\nrig: gastown\nagent_bead: gt-gastown-polecat-toast","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:15:08.233495-08:00","created_by":"gastown/polecats/toast","updated_at":"2026-01-01T20:32:00.836595-08:00","closed_at":"2026-01-01T20:32:00.8366-08:00"} -{"id":"gt-1elg","title":"Code review: handoff.go changes (gt-yt6g, gt-tocb)","description":"Review ~80 lines of Go changes to internal/cmd/handoff.go:\n\n## Commits to review\n- 1414081: Standardize session end with gt handoff (gt-yt6g)\n - Detect polecats via GT_POLECAT env var\n - Call gt done instead of respawning for polecats\n - +31/-11 lines\n\n- 9c85b83: Support full session paths in gt handoff (gt-tocb)\n - resolveRoleToSession accepts \u003crig\u003e/crew/\u003cname\u003e, \u003crig\u003e/witness, \u003crig\u003e/refinery\n - +46/-3 lines\n\n## Review focus\n- Error handling in path resolution\n- Edge cases in polecat detection\n- Test coverage needed?","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T14:27:40.605575-08:00","updated_at":"2025-12-23T14:27:40.605575-08:00"} -{"id":"gt-1fju9","title":"Merge: keeper-mjwcc4ik","description":"branch: polecat/keeper-mjwcc4ik\ntarget: main\nsource_issue: keeper-mjwcc4ik\nrig: gastown\nagent_bead: gt-gastown-polecat-keeper","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:58:36.744921-08:00","created_by":"gastown/polecats/keeper","updated_at":"2026-01-01T20:01:53.599572-08:00","closed_at":"2026-01-01T20:01:53.599572-08:00","close_reason":"Merged to main at cf97645e"} -{"id":"gt-1fp5z","title":"Session ended: gt-gastown-coma","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:57:13.113557-08:00","created_by":"gastown/polecats/coma","updated_at":"2026-01-04T16:40:22.82078-08:00","closed_at":"2026-01-04T16:40:22.82078-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/coma","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:57:13-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-coma\",\"worker\":\"coma\"}"} -{"id":"gt-1ge7t","title":"Digest: mol-deacon-patrol","description":"Patrol 18: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:36:05.552255-08:00","updated_at":"2025-12-29T22:36:05.552255-08:00","closed_at":"2025-12-29T22:36:05.552222-08:00"} -{"id":"gt-1hihd","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:40:28.171615-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:41:25.972192-08:00","closed_at":"2026-01-04T16:41:25.972192-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:40:28-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-1irr6","title":"Digest: mol-deacon-patrol","description":"Patrol 15: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:09:57.282285-08:00","updated_at":"2025-12-31T18:09:57.282285-08:00","closed_at":"2025-12-31T18:09:57.282249-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1itp5","title":"Digest: mol-deacon-patrol","description":"Cycle 8: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:16:19.37161-08:00","updated_at":"2025-12-28T13:16:19.37161-08:00","closed_at":"2025-12-28T13:16:19.371571-08:00"} -{"id":"gt-1j811","title":"Digest: mol-deacon-patrol","description":"Patrol 11: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:13:20.411051-08:00","updated_at":"2026-01-01T08:13:20.411051-08:00","closed_at":"2026-01-01T08:13:20.411017-08:00","dependencies":[{"issue_id":"gt-1j811","depends_on_id":"gt-eph-43mn","type":"parent-child","created_at":"2026-01-01T08:13:20.412269-08:00","created_by":"deacon"}]} -{"id":"gt-1jirq","title":"Session ended: gt-mayor","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T20:53:43.997588-08:00","created_by":"mayor","updated_at":"2026-01-04T16:41:00.351083-08:00","closed_at":"2026-01-04T16:41:00.351083-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"mayor","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T20:53:43-08:00\",\"role\":\"mayor\",\"session_id\":\"gt-mayor\",\"worker\":\"mayor\"}"} -{"id":"gt-1kljv","title":"Add tests for gt crew restart --all","description":"Add integration tests for the crew restart flow:\n\n- Test getAgentSessions() correctly identifies crew sessions\n- Test --rig filtering works correctly \n- Test --dry-run outputs correct targets\n- Test session kill/recreate cycle (without Claude)\n\nConsider extracting a SessionStarter interface to mock the claude-launching bit.\n\nRelated: gt crew restart --all was just implemented.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-27T14:45:35.904813-08:00","created_by":"mayor","updated_at":"2025-12-27T14:45:35.904813-08:00"} -{"id":"gt-1kuox","title":"Merge: slit-mjxof5ku","description":"branch: polecat/slit-mjxof5ku\ntarget: main\nsource_issue: slit-mjxof5ku\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:28:12.867214-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T18:29:52.007194-08:00","closed_at":"2026-01-02T18:29:52.007194-08:00","close_reason":"Merged to main at 89785378"} -{"id":"gt-1ky","title":"CLI: workspace commands (init, add, list)","description":"GGT needs workspace management commands beyond install.\n\n## Commands (beyond gt-f9x.3 install)\n\n### gt workspace list\nList all rigs in current workspace.\n```\ngt workspace list [--json]\n```\nEssentially `gt rig list` but framed as workspace view.\n\n### gt workspace add\nAdd existing rig to workspace (alternative to gt rig add).\n```\ngt workspace add \u003cgit-url\u003e [--name NAME]\n```\n\n### gt onboard\nInteractive first-time setup wizard.\n```\ngt onboard\n```\n- Prompts for workspace location\n- Creates structure via gt install\n- Offers to add first rig\n\n## Note\nMay be redundant with gt-f9x.3 (install) and gt-u1j.16 (rig commands).\nConsider if this is needed or should be closed as covered by those.\n\n## PGT Reference\ngastown-py/src/gastown/cli/workspace_cmd.py","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:38.070203-08:00","updated_at":"2025-12-16T16:03:49.715667-08:00"} -{"id":"gt-1le","title":"town handoff command (optional)","description":"CLI commands for session handoff workflow (optional convenience).\n\n## Commands\n\n### gt handoff\nGenerate handoff interactively.\n```\ngt handoff [--send]\n```\n- Collects current state (status, inbox, beads)\n- Prompts for additional notes\n- --send: Mail to self and exit\n\n### gt resume\nCheck for and display pending handoff.\n```\ngt resume\n```\n- Checks inbox for handoff message\n- Displays formatted handoff if found\n- Suggests next actions\n\n## Implementation\n\nThese are convenience wrappers. The same workflow can be done manually:\n```bash\n# Manual handoff\ntown status \u003e /tmp/handoff\ntown inbox \u003e\u003e /tmp/handoff\nbd ready \u003e\u003e /tmp/handoff\n# Edit and send\ntown mail send mayor/ -s \"Session Handoff\" -f /tmp/handoff\n```\n\n## Priority\n\nP2 - Optional. Manual workflow works fine. Nice to have for UX.\n\n## Notes\n\nPart of session cycling workflow designed in [deleted:gt-u82].","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-15T20:15:31.954724-08:00","updated_at":"2026-01-01T19:07:35.010811-08:00","closed_at":"2026-01-01T19:07:35.010811-08:00","close_reason":"Added --collect flag to gt handoff and --handoff flag to gt resume","dependencies":[{"issue_id":"gt-1le","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.647043-08:00","created_by":"daemon"}]} -{"id":"gt-1lvog","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:37.102371-08:00","updated_at":"2025-12-28T11:22:37.102371-08:00","closed_at":"2025-12-28T11:22:37.102337-08:00"} -{"id":"gt-1m4vn","title":"Digest: mol-deacon-patrol","description":"Patrol #7: Quick cycle, no pending spawns.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:18:26.243402-08:00","updated_at":"2025-12-31T19:18:26.243402-08:00","closed_at":"2025-12-31T19:18:26.243367-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1meck","title":"Digest: mol-deacon-patrol","description":"Patrol 11","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:10:55.708526-08:00","updated_at":"2026-01-01T09:10:55.708526-08:00","closed_at":"2026-01-01T09:10:55.708486-08:00","dependencies":[{"issue_id":"gt-1meck","depends_on_id":"gt-eph-lwvx","type":"parent-child","created_at":"2026-01-01T09:10:55.70977-08:00","created_by":"deacon"}]} -{"id":"gt-1natt","title":"Digest: mol-deacon-patrol","description":"Cycle 6","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:00:14.315839-08:00","updated_at":"2026-01-01T10:00:14.315839-08:00","closed_at":"2026-01-01T10:00:14.315806-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1nno9","title":"Digest: mol-deacon-patrol","description":"Patrol 17: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:39:20.375744-08:00","updated_at":"2025-12-31T21:39:20.375744-08:00","closed_at":"2025-12-31T21:39:20.375709-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1ntmd","title":"README: Add beads (bd) as prerequisite","description":"CRITICAL: gt calls bd via exec.Command for sling, cook, gate, etc. but beads is not listed in Prerequisites. Users following Quick Start will fail.\n\nFix:\n1. Add 'beads (bd)' to Prerequisites with install link\n2. Move Prerequisites section BEFORE Quick Start\n3. Add version requirements for each dep","status":"closed","priority":0,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2026-01-01T11:20:08.3956-08:00","created_by":"mayor","updated_at":"2026-01-01T11:23:34.382087-08:00","closed_at":"2026-01-01T11:23:34.382087-08:00","close_reason":"Added beads (bd) to Prerequisites with install link, moved section before Quick Start, added version requirements"} -{"id":"gt-1p5l3","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:32:12.449876-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.802448-08:00","closed_at":"2026-01-05T00:08:31.802448-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:32:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-1pelm","title":"Add unit tests for internal/mail router and mailbox","description":"attached_args: Add unit tests for mail router and mailbox\n\nAdd tests for mail routing and mailbox functionality.\n\n## Files to create\n- internal/mail/router_test.go\n- internal/mail/mailbox_test.go\n\n## Test cases for router\n1. Route() resolves addresses correctly\n2. Route() handles rig/role format\n3. Route() handles rig/crew/name format\n4. Invalid addresses return error\n\n## Test cases for mailbox\n1. Send() writes message to mailbox\n2. Inbox() lists messages\n3. Read() retrieves message by ID\n4. Delete() removes message\n5. Messages persist correctly\n\n## Acceptance criteria\n- [ ] router_test.go with 4+ tests\n- [ ] mailbox_test.go with 5+ tests\n- [ ] Tests pass: go test ./internal/mail/...\n- [ ] Coverage \u003e 60%","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:13.002918-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:10:00.287761-08:00","closed_at":"2025-12-28T16:10:00.287761-08:00"} -{"id":"gt-1qp3u","title":"Merge: dinki-mk0ap14g","description":"branch: polecat/dinki-mk0ap14g\ntarget: main\nsource_issue: dinki-mk0ap14g\nrig: gastown\nagent_bead: gt-gastown-polecat-dinki\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T14:26:31.215195-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-04T14:29:05.855506-08:00","closed_at":"2026-01-04T14:29:05.855506-08:00","close_reason":"Merged to main at 871410f1"} -{"id":"gt-1r6o6","title":"Digest: mol-deacon-patrol","description":"Patrol 17: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T17:48:31.845975-08:00","updated_at":"2025-12-26T17:48:31.845975-08:00","closed_at":"2025-12-26T17:48:31.845924-08:00"} -{"id":"gt-1rxz5","title":"Swarm status doesn't update after task completions","description":"During swarm bd-784c, the swarm status remained at '9% (1/11 tasks merged)' even after 5 tasks were completed and closed.\n\n**Expected:**\nSwarm status should reflect actual completion count, either by:\n1. Polling issue status from beads\n2. Updating when polecats close issues\n3. Updating when commits are pushed to integration branch\n\n**Impact:**\nCoordinator had to manually check bd list to know actual progress.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2025-12-28T22:14:05.745286-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-29T23:43:31.190741-08:00","closed_at":"2025-12-29T23:43:31.190741-08:00","close_reason":"Fixed: Swarm status now reads from BeadsPath() which points to the mayor/rig clone with proper beads sync config. This ensures status reflects git-synced beads data instead of stale local daemon data."} -{"id":"gt-1sdeo","title":"Digest: mol-deacon-patrol","description":"Patrol 153: All healthy, nux respawned","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:04:26.942843-08:00","updated_at":"2026-01-01T15:04:26.942843-08:00","closed_at":"2026-01-01T15:04:26.942808-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1sjr3","title":"Digest: mol-deacon-patrol","description":"Cycle 6: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:53:42.776939-08:00","updated_at":"2025-12-31T23:53:42.776939-08:00","closed_at":"2025-12-31T23:53:42.776905-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1slst","title":"Digest: mol-refinery-patrol","description":"Patrol cycle: queue empty, 0 branches merged, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T21:40:58.281912-08:00","updated_at":"2026-01-05T21:40:58.281912-08:00","closed_at":"2026-01-05T21:40:58.281884-08:00","close_reason":"Squashed from 10 wisps","dependencies":[{"issue_id":"gt-1slst","depends_on_id":"gt-wisp-82f","type":"parent-child","created_at":"2026-01-05T21:40:58.283305-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-1teyb","title":"Session ended: gt-gastown-chumbucket","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:13:19.73869-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T16:40:13.423987-08:00","closed_at":"2026-01-04T16:40:13.423987-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/chumbucket","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:13:19-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-chumbucket\",\"worker\":\"chumbucket\"}"} -{"id":"gt-1tpts","title":"E2E Swarm Test Epic","status":"closed","priority":3,"issue_type":"epic","created_at":"2025-12-29T17:58:35.474031-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:02:47.847412-08:00","closed_at":"2025-12-29T18:02:47.847412-08:00","close_reason":"E2E Test: All tasks complete, swarm landed"} -{"id":"gt-1tpts.1","title":"Task A: Setup foundation","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T17:58:43.84226-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:01:36.128324-08:00","closed_at":"2025-12-29T18:01:36.128324-08:00","close_reason":"Test: Task A complete","dependencies":[{"issue_id":"gt-1tpts.1","depends_on_id":"gt-1tpts","type":"parent-child","created_at":"2025-12-29T17:58:43.842734-08:00","created_by":"daemon"}]} -{"id":"gt-1tpts.2","title":"Task B: First feature","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T17:58:44.800236-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:01:44.499612-08:00","closed_at":"2025-12-29T18:01:44.499612-08:00","close_reason":"Test: Wave 2 complete","dependencies":[{"issue_id":"gt-1tpts.2","depends_on_id":"gt-1tpts","type":"parent-child","created_at":"2025-12-29T17:58:44.80216-08:00","created_by":"daemon"},{"issue_id":"gt-1tpts.2","depends_on_id":"gt-1tpts.1","type":"blocks","created_at":"2025-12-29T17:58:56.160006-08:00","created_by":"daemon"}]} -{"id":"gt-1tpts.3","title":"Task C: Second feature","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T17:58:46.458711-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:01:44.507784-08:00","closed_at":"2025-12-29T18:01:44.507784-08:00","close_reason":"Test: Wave 2 complete","dependencies":[{"issue_id":"gt-1tpts.3","depends_on_id":"gt-1tpts","type":"parent-child","created_at":"2025-12-29T17:58:46.459186-08:00","created_by":"daemon"},{"issue_id":"gt-1tpts.3","depends_on_id":"gt-1tpts.1","type":"blocks","created_at":"2025-12-29T17:58:56.204252-08:00","created_by":"daemon"}]} -{"id":"gt-1tpts.4","title":"Task D: Integration","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T17:58:47.710354-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:02:09.954464-08:00","closed_at":"2025-12-29T18:02:09.954464-08:00","close_reason":"Test: Task D complete - all work done","dependencies":[{"issue_id":"gt-1tpts.4","depends_on_id":"gt-1tpts","type":"parent-child","created_at":"2025-12-29T17:58:47.712242-08:00","created_by":"daemon"},{"issue_id":"gt-1tpts.4","depends_on_id":"gt-1tpts.2","type":"blocks","created_at":"2025-12-29T17:58:56.246842-08:00","created_by":"daemon"},{"issue_id":"gt-1tpts.4","depends_on_id":"gt-1tpts.3","type":"blocks","created_at":"2025-12-29T17:58:56.290487-08:00","created_by":"daemon"}]} -{"id":"gt-1tqy","title":"Digest: mol-deacon-patrol","description":"Patrol 15","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T23:10:24.121681-08:00","updated_at":"2025-12-24T23:10:24.121681-08:00","closed_at":"2025-12-24T23:10:24.121649-08:00"} -{"id":"gt-1u9","title":"Interactive prompts for destructive operations","description":"Add interactive confirmations for destructive operations.\n\n## Operations Needing Confirmation\n- `gt swarm cancel` - Cancels active swarm\n- `gt swarm land --force` - Force landing\n- `gt polecat decommission` - Removes polecat\n- `gt rig remove` - Removes rig\n- `gt stop --all` - Stops all sessions\n- `gt mail purge` - Permanently deletes mail\n\n## Implementation Options\n\n### Option 1: promptui library\n```go\nimport \"github.com/manifoldco/promptui\"\n\nprompt := promptui.Prompt{\n Label: \"Delete polecat Toast\",\n IsConfirm: true,\n}\nresult, err := prompt.Run()\n```\n\n### Option 2: Simple stdin\n```go\nfunc confirm(prompt string) bool {\n fmt.Printf(\"%s [y/N]: \", prompt)\n var response string\n fmt.Scanln(\u0026response)\n return strings.ToLower(response) == \"y\"\n}\n```\n\n## Bypass Flags\nAll confirmations skippable with --force or --yes:\n```go\nif !force \u0026\u0026 !confirm(\"Really cancel swarm?\") {\n return nil\n}\n```\n\n## Acceptance Criteria\n- [ ] Destructive ops prompt by default\n- [ ] --force or --yes bypasses\n- [ ] Clear prompt text explaining action\n- [ ] Non-interactive mode (piped input) auto-fails","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T14:48:51.551594-08:00","updated_at":"2025-12-16T16:06:54.283696-08:00"} -{"id":"gt-1uhmj","title":"Agent-centric dashboard view (gt dashboard)","description":"Charmbracelet TUI for gt feed with dashboard + stream layout.\n\n## Layout (horizontal split)\n\n**Top panel: Agent Tree (role/town view)**\n- Shows EVERY agent organized by role\n- Each agent shows their MOST RECENT activity inline\n- At a glance: who is doing what RIGHT NOW\n- Collapsible sections\n\n**Bottom panel: Event Stream (chronological feed)**\n- Full scrollable history of events\n- Most recent at top\n- More detail than the tree view\n- This is what you scroll through\n\n## Visual\n```\n+-------------------------------------------------------------+\n| GT Feed Filter: all |\n+-------------------------------------------------------------+\n| gastown/ \u003c- AGENT TREE (top) |\n| mayor [10:30] Dispatched gt-xyz -\u003e Toast |\n| witness [10:28] Nudged polecat-3 (idle 5m) |\n| refinery [10:25] Merged PR #123 |\n| crew/ |\n| joe [10:22] Completed gt-95j13 |\n| max [10:18] Working on gt-s6r44 |\n| polecats/ |\n| Toast [10:30] Received gt-xyz |\n+-------------------------------------------------------------+\n| [10:30] Toast: Received molecule gt-xyz |\n| [10:28] witness: Nudged polecat-3 after 5m idle |\n| [10:25] refinery: Merged PR #123 |\n| ... \u003c- EVENT STREAM |\n+-------------------------------------------------------------+\n| j/k: scroll /: search f: filter q: quit ?: help |\n+-------------------------------------------------------------+\n```\n\n## Why this layout?\n- Top answers: what is everyone doing?\n- Bottom answers: what just happened?\n- Together: complete situational awareness\n\n## Replaces\n- gt feed (currently just wraps bd activity)\n- gt dashboard task merges into this\n\n## Tech\n- bubbletea Model with two viewports\n- Tab switches focus between tree/stream\n- j/k scrolls focused panel","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T12:46:38.812289-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T16:23:51.095679-08:00","closed_at":"2025-12-28T16:23:51.095679-08:00","dependencies":[{"issue_id":"gt-1uhmj","depends_on_id":"gt-38doh","type":"blocks","created_at":"2025-12-28T12:46:47.3704-08:00","created_by":"daemon"},{"issue_id":"gt-1uhmj","depends_on_id":"gt-lexye","type":"blocks","created_at":"2025-12-28T16:14:56.174801-08:00","created_by":"daemon"}]} -{"id":"gt-1ujlp","title":"Digest: mol-deacon-patrol","description":"Patrol 6: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:37:05.30547-08:00","updated_at":"2025-12-31T21:37:05.30547-08:00","closed_at":"2025-12-31T21:37:05.305439-08:00"} -{"id":"gt-1vtbd","title":"Digest: mol-refinery-patrol","description":"Patrol cycle: checked mail (empty), scanned MR queue (0 open), no branches to merge. All MRs already processed.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T01:03:50.927061-08:00","updated_at":"2025-12-30T01:03:50.927061-08:00","closed_at":"2025-12-30T01:03:50.927027-08:00","close_reason":"Squashed from 10 wisps","dependencies":[{"issue_id":"gt-1vtbd","depends_on_id":"gt-eph-h48","type":"parent-child","created_at":"2025-12-30T01:03:50.92796-08:00","created_by":"mayor"}]} -{"id":"gt-1w8nc","title":"Session ended: gt-gastown-dinki","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:17:33.780253-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-05T00:08:31.854488-08:00","closed_at":"2026-01-05T00:08:31.854488-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/dinki","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:17:33-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-dinki\",\"worker\":\"dinki\"}"} -{"id":"gt-1wxvf","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:11:37.861279-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.671721-08:00","closed_at":"2026-01-05T00:08:31.671721-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:11:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-1y0e","title":"🤝 HANDOFF: Investigate beads-sync divergence (221 files)","description":"## Context\n\ngt doctor now detects orphaned code on beads-sync branch. Running it shows:\n\n beads-sync-orphans: 221 file(s) on beads-sync not in main\n\nThis is in the gastown repo (checking from crew/max).\n\n## Background\n\n- Earlier today we recovered orphaned mail migration code lost in merge 96c773f\n- Recently simplified architecture: all workers use mayor/rig/.beads (redirects)\n- This simplification may have caused beads-sync branch to diverge unexpectedly\n\n## Investigation Steps\n\n1. From crew/max run: git diff main..beads-sync --stat\n2. Check if beads-sync should even exist anymore (was for multi-clone sync)\n3. If obsolete with redirect architecture, consider deleting it\n4. If it has legitimate changes, cherry-pick or merge to main\n\n## Key Question\n\nWith all workers using mayor/rig/.beads via redirects, is beads-sync still needed?\n\n## Commands\n\ngit log main..beads-sync --oneline | head -20\ngit diff main..beads-sync -- *.go | head -100","status":"open","priority":2,"issue_type":"message","created_at":"2025-12-20T22:38:49.242099-08:00","updated_at":"2025-12-31T12:03:43.05637-08:00"} -{"id":"gt-1y2bf","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T16:15:46.819053-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.097993-08:00","closed_at":"2026-01-04T16:41:26.097993-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T16:15:46-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-1ydd9","title":"Show actor on pinned/status change events","description":"Pinned events currently show no actor:\n\n [10:22:25] → gt-95j13 → pinned · Add tmux hotkey...\n\nShould show who pinned it:\n\n [10:22:25] → gt-95j13 → pinned · Add tmux hotkey... @gastown/crew/joe\n\nPart of epic gt-u7dxq","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-28T11:02:14.269602-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T06:58:11.850174-08:00","closed_at":"2025-12-30T06:58:11.850174-08:00","close_reason":"Fixed: Actor now shows on status/pinned events in bd activity. Fix implemented in beads repo branch fix/actor-on-status-events (https://github.com/steveyegge/beads/pull/new/fix/actor-on-status-events). Changes: Added SetActor method to RPC client and called it during daemon connection to pass actor in RPC requests."} -{"id":"gt-1yn1u","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:36:54.653177-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.352752-08:00","closed_at":"2026-01-04T16:40:13.352752-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:36:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-1yxb4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:28:18.145467-08:00","updated_at":"2026-01-01T10:28:18.145467-08:00","closed_at":"2026-01-01T10:28:18.14543-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-1z3z","title":"Human escalation path design","description":"Flesh out the human escalation mechanism for Gas Town errors. Currently: errors mail Mayor, Mayor startup prompts about escalations. Need: structured escalation channel, escalation severity levels, and clear documentation. All edge cases in molecular algebra can write warnings to this channel.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/imperator","created_at":"2025-12-23T18:45:26.354472-08:00","updated_at":"2025-12-30T09:56:38.856254-08:00","closed_at":"2025-12-30T09:56:38.856254-08:00","close_reason":"Implemented: gt escalate command with CRITICAL/HIGH/MEDIUM severity, Mayor startup check, escalation beads with audit trail, documentation"} -{"id":"gt-1z4m","title":"gt swarm is implemented but undocumented","description":"internal/swarm/ package is fully implemented with:\n- gt swarm create\n- gt swarm status\n- gt swarm list\n- gt swarm land\n- gt swarm cancel\n- gt swarm start\n\nBut no documentation exists for it:\n- Not in README\n- Not in architecture.md (uses different terminology)\n- Not in any role prompts\n\nEither:\n1. Document gt swarm as the canonical mechanism\n2. Or deprecate it in favor of gt sling\n\nRelated to gt-6n13 (competing molecule mechanisms)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-24T12:51:23.768049-08:00","updated_at":"2025-12-30T10:36:54.057795-08:00","closed_at":"2025-12-30T10:36:54.057795-08:00","close_reason":"Added docs/swarm.md with full swarm documentation and updated reference.md with CLI commands","dependencies":[{"issue_id":"gt-1z4m","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:07.817907-08:00","created_by":"daemon"},{"issue_id":"gt-1z4m","depends_on_id":"gt-e0qj2","type":"blocks","created_at":"2025-12-26T23:21:29.370789-08:00","created_by":"daemon"}]} -{"id":"gt-1z5n0","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T14:03:09.792235-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T14:03:09.85632-08:00","closed_at":"2026-01-06T14:03:09.85632-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T14:03:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-2016s","title":"Digest: mol-deacon-patrol","description":"Patrol 92: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:07:59.436852-08:00","updated_at":"2026-01-01T03:07:59.436852-08:00","closed_at":"2026-01-01T03:07:59.436816-08:00","dependencies":[{"issue_id":"gt-2016s","depends_on_id":"gt-eph-ilcc","type":"parent-child","created_at":"2026-01-01T03:07:59.438027-08:00","created_by":"deacon"}]} -{"id":"gt-201v4","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:23:35.283504-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-05T19:44:18.400746-08:00","closed_at":"2026-01-05T19:44:18.400746-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:23:35-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-209da","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:14:51.629291-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:18.45366-08:00","closed_at":"2026-01-05T19:44:18.45366-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:14:46-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-20i1i","title":"Merge: dementus-mjxofwf6","description":"branch: polecat/dementus-mjxofwf6\ntarget: main\nsource_issue: dementus-mjxofwf6\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:29:04.132018-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-02T18:30:59.429479-08:00","closed_at":"2026-01-02T18:30:59.429479-08:00","close_reason":"Merged to main at 8f6e2d21"} -{"id":"gt-20qfv","title":"Digest: mol-deacon-patrol","description":"Patrol complete: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:35:51.157098-08:00","updated_at":"2025-12-31T21:35:51.157098-08:00","closed_at":"2025-12-31T21:35:51.157062-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-215tk","title":"Merge: warboy-1767106060799","description":"branch: polecat/warboy-1767106060799\ntarget: main\nsource_issue: warboy-1767106060799\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:40:55.502012-08:00","created_by":"gastown/polecats/warboy","updated_at":"2025-12-30T18:23:22.225653-08:00","closed_at":"2025-12-30T18:23:22.225653-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-22cbf","title":"Digest: mol-refinery-patrol","description":"Patrol: queue empty, no merges, 0 messages processed","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:44:26.132181-08:00","updated_at":"2026-01-01T23:44:26.132181-08:00","closed_at":"2026-01-01T23:44:26.132152-08:00","close_reason":"Squashed from 11 wisps","dependencies":[{"issue_id":"gt-22cbf","depends_on_id":"gt-eph-odxs","type":"parent-child","created_at":"2026-01-01T23:44:26.133504-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-22ng","title":"Create activity aggregator","description":"Component that connects to multiple rig beads daemons and merges their activity into a unified view. Polls GetMutations and GetWorkerStatus from each rig, groups by rig/worker. Handles connection failures gracefully.\n\nBLOCKED BY (Beads rig):\n- bd-gqxd: Enrich MutationEvent with title and assignee\n- bd-l13p: Add GetWorkerStatus RPC endpoint\n- bd-0oqz: Add GetMoleculeProgress RPC endpoint","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:27:08.249115-08:00","updated_at":"2025-12-23T16:27:53.545952-08:00","dependencies":[{"issue_id":"gt-22ng","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:30.603166-08:00","created_by":"daemon"}]} -{"id":"gt-23nkc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All agents healthy. Processed 14 inbox messages, archived status updates. Witness and Refinery running. No orphans, no cleanup needed.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:42:20.418261-08:00","updated_at":"2025-12-30T15:42:20.418261-08:00","closed_at":"2025-12-30T15:42:20.418225-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-23ohn","title":"Digest: mol-deacon-patrol","description":"Patrol 208: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:51:38.041907-08:00","updated_at":"2026-01-01T16:51:38.041907-08:00","closed_at":"2026-01-01T16:51:38.04187-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-23ohn","depends_on_id":"gt-eph-sae3","type":"parent-child","created_at":"2026-01-01T16:51:38.04321-08:00","created_by":"deacon"}]} -{"id":"gt-252ab","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:38:15.751282-08:00","updated_at":"2025-12-31T23:38:15.751282-08:00","closed_at":"2025-12-31T23:38:15.751249-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-25shb","title":"Digest: mol-deacon-patrol","description":"Patrol 147: All healthy, 2 polecats working","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:58:40.244285-08:00","updated_at":"2026-01-01T14:58:40.244285-08:00","closed_at":"2026-01-01T14:58:40.244234-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-26f5w","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:16:00.023586-08:00","created_by":"gastown/refinery","updated_at":"2026-01-06T13:16:00.078397-08:00","closed_at":"2026-01-06T13:16:00.078397-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:15:59-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-26mmw","title":"Digest: mol-deacon-patrol","description":"Patrol #13: Dog pool healthy, 1 idle.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:20:51.209734-08:00","updated_at":"2025-12-31T19:20:51.209734-08:00","closed_at":"2025-12-31T19:20:51.2097-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-26pib","title":"Day 3.6: Polecat closes steps for activity feed","description":"**REVISED**: Step completion is for visibility, not session control.\n\nPolecats close molecule steps as they complete them:\n```bash\n# After completing implement step:\nbd close \u003cstep-bead-id\u003e # Or: mol step done implement\n```\n\nThis provides:\n1. **Activity feed visibility** - Observers see progress in real-time\n2. **Audit trail** - Step completion timestamps in beads\n3. **Stuck detection** - Witness can see 'long time on same step'\n\nWhat this does NOT do:\n- Trigger session recycle (polecat self-manages)\n- Block next step (polecat continues immediately)\n- Require Witness intervention\n\nImplementation options:\n- Option A: Polecat runs `bd close \u003cstep-id\u003e` manually\n- Option B: Formula `on_complete` hook auto-closes step bead\n- Option C: `mol step done \u003cstep\u003e` convenience command\n\nPriority lowered: Nice-to-have for visibility, not launch-blocking.\n\n**Dependency removed**: No longer depends on gt-zb0io (recycle between steps).","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-27T22:02:12.671367-08:00","created_by":"mayor","updated_at":"2025-12-27T22:50:26.895789-08:00","dependencies":[{"issue_id":"gt-26pib","depends_on_id":"gt-zb0io","type":"blocks","created_at":"2025-12-27T22:02:45.359036-08:00","created_by":"daemon"}]} -{"id":"gt-27bzi","title":"Add gt mail announces command to list and read bulletin boards","description":"Add announces subcommand to internal/cmd/mail.go.\n\nCOMMANDS:\n1. gt mail announces - list available announce channels\n2. gt mail announces \u003cchannel\u003e - read messages from channel\n\nBEHAVIOR for 'gt mail announces':\n- Load messaging.json\n- List all announce channel names\n- Show reader count for each\n\nBEHAVIOR for 'gt mail announces \u003cchannel\u003e':\n- Validate channel exists\n- Query beads for messages with announce_channel=\u003cchannel\u003e\n- Display in reverse chronological order\n- Do NOT mark as read or remove\n\nFILE: internal/cmd/mail.go\nADD: announcesCmd as subcommand of mailCmd\n\nTESTS: Add TestMailAnnounces","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/toecutter","created_at":"2025-12-30T18:17:20.247914-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-02T00:20:30.677619-08:00","closed_at":"2026-01-02T00:20:30.677619-08:00","close_reason":"Implemented gt mail announces command with list and read channel functionality","dependencies":[{"issue_id":"gt-27bzi","depends_on_id":"gt-q73h3","type":"blocks","created_at":"2025-12-30T18:17:27.432846-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-27zla","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:21:11.308384-08:00","updated_at":"2026-01-01T07:21:11.308384-08:00","closed_at":"2026-01-01T07:21:11.308346-08:00"} -{"id":"gt-2832w","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All 3 rigs healthy. No incidents. Handoff threshold reached.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:52:13.766112-08:00","updated_at":"2026-01-01T07:52:13.766112-08:00","closed_at":"2026-01-01T07:52:13.766075-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-284zr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 62: All healthy, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:12:18.322811-08:00","updated_at":"2026-01-01T13:12:18.322811-08:00","closed_at":"2026-01-01T13:12:18.322779-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-28asx","title":"Digest: mol-deacon-patrol","description":"Patrol 15: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:07:23.607033-08:00","updated_at":"2026-01-01T23:07:23.607033-08:00","closed_at":"2026-01-01T23:07:23.606998-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-29uyt","title":"Merge: capable-mjtltnm5","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: capable-mjtltnm5\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:03:43.890312-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:54.542118-08:00","closed_at":"2025-12-30T23:12:54.542118-08:00","close_reason":"Branch already merged"} -{"id":"gt-2ahe4","title":"Merge: valkyrie-mjw71b7u","description":"branch: polecat/valkyrie-mjw71b7u\ntarget: main\nsource_issue: valkyrie-mjw71b7u\nrig: gastown\nagent_bead: gt-gastown-polecat-valkyrie","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:07:57.459771-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2026-01-01T19:11:28.97611-08:00","closed_at":"2026-01-01T19:11:28.97611-08:00","close_reason":"Merged to main at 1e2a068b"} -{"id":"gt-2arne","title":"Session ended: gt-gastown-corpus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:18:33.807061-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-04T16:40:13.378394-08:00","closed_at":"2026-01-04T16:40:13.378394-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/corpus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:18:33-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-corpus\",\"worker\":\"corpus\"}"} -{"id":"gt-2b39c","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 3 rigs healthy, 6 agents pinged, no incidents, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:27:09.75107-08:00","updated_at":"2025-12-31T23:27:09.75107-08:00","closed_at":"2025-12-31T23:27:09.751039-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2c4o0","title":"Merge: dementus-1767087772272","description":"branch: polecat/dementus-1767087772272\ntarget: main\nsource_issue: dementus-1767087772272\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T02:06:35.284326-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T10:06:56.670138-08:00","closed_at":"2025-12-30T10:06:56.670138-08:00","close_reason":"Branch merged to main"} -{"id":"gt-2dndm","title":"Fix template syntax in code-review.formula.toml (Handlebars vs Go)","description":"code-review.formula.toml uses Handlebars syntax ({{#if}}, {{#each}}) but Go text/template uses {{if}}, {{range}}. Either switch to Go template syntax or implement a Handlebars-compatible template engine.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/valkyrie","created_at":"2026-01-01T15:00:57.23288-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T17:31:33.800642-08:00","closed_at":"2026-01-01T17:31:33.800642-08:00","close_reason":"Converted Handlebars syntax to Go text/template syntax in code-review.formula.toml"} -{"id":"gt-2epme","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 57: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:00:19.768036-08:00","updated_at":"2026-01-01T13:00:19.768036-08:00","closed_at":"2026-01-01T13:00:19.767997-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2exsg","title":"Session ended: gt-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:46:46.06495-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:41:00.392752-08:00","closed_at":"2026-01-04T16:41:00.392752-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:46:46-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-refinery\",\"worker\":\"refinery\"}"} -{"id":"gt-2f0p3","title":"gt status: check daemon health first, attempt restart","description":"If daemon not running, attempt to start it. If start fails, show warning but don't block status display. Currently falls back to slow direct mode silently.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T11:54:38.415961-08:00","created_by":"mayor","updated_at":"2026-01-02T12:05:32.190061-08:00","closed_at":"2026-01-02T12:05:32.190061-08:00","close_reason":"Implemented bd daemon health check in gt status","dependencies":[{"issue_id":"gt-2f0p3","depends_on_id":"gt-rapj1","type":"blocks","created_at":"2026-01-02T11:54:58.080461-08:00","created_by":"mayor"}]} -{"id":"gt-2f6sa","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:24:50.23781-08:00","updated_at":"2026-01-01T11:24:50.23781-08:00","closed_at":"2026-01-01T11:24:50.237774-08:00"} -{"id":"gt-2g130","title":"Remove dead code: splitLines first loop, unused methods","description":"Remove dead code: splitLines first loop, unused methods.\n\n## Dead code locations\n\n### 1. internal/cmd/polecat.go (lines 1093-1106)\nsplitLines function has unreachable first loop:\n```go\nfunc splitLines(s string) []string {\n var lines []string\n for _, line := range filepath.SplitList(s) { // DEAD: wrong function\n ...\n }\n lines = nil // Discards above\n for _, line := range strings.Split(s, \"\\n\") { // This is what runs\n lines = append(lines, line)\n }\n return lines\n}\n```\n**Fix:** Remove first loop and reset.\n\n### 2. internal/townlog/logger.go (lines 277-279)\n```go\nfunc (e Event) JSON() ([]byte, error) {\n return json.Marshal(e)\n}\n```\n**Fix:** Remove unused method.\n\n### 3. internal/lock/lock.go (line 27)\n```go\nErrStaleLock = errors.New(\"stale lock detected\")\n```\n**Fix:** Remove unused error variable.\n\n### 4. internal/witness/types.go (line 19)\n```go\nStatePaused State = \"paused\"\n```\n**Fix:** Remove unused state constant.\n\n### 5. internal/refinery/manager.go (lines 527-538)\n```go\nfunc (m *Manager) getTestCommand() string { ... }\n```\n**Fix:** Remove unused method.\n\n## Acceptance criteria\n- [ ] polecat.go: Dead loop removed from splitLines\n- [ ] townlog/logger.go: Event.JSON() method removed\n- [ ] lock/lock.go: ErrStaleLock removed\n- [ ] witness/types.go: StatePaused removed\n- [ ] refinery/manager.go: getTestCommand removed\n- [ ] go build ./... passes\n- [ ] go test ./... passes","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-28T15:43:17.034253-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T17:13:10.76452-08:00","closed_at":"2025-12-28T17:13:10.76452-08:00"} -{"id":"gt-2hirc","title":"Merge: capable-1767084028536","description":"branch: polecat/capable-1767084028536\ntarget: main\nsource_issue: capable-1767084028536\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:03:19.469127-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T01:06:10.381035-08:00","closed_at":"2025-12-30T01:06:10.381035-08:00","close_reason":"Conflicts with main - mrqueue package was removed. Notified capable to rebase."} -{"id":"gt-2hq76","title":"Digest: mol-deacon-patrol","description":"Patrol 69: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:01:41.391948-08:00","updated_at":"2025-12-31T15:01:41.391948-08:00","closed_at":"2025-12-31T15:01:41.391911-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2hwi9","title":"CRITICAL: Polecats not pushing before signaling done","description":"Pipeline failure - work being lost:\n\n1. Polecat does work locally\n2. Polecat closes bead, goes idle\n3. BUT doesn't push commits first\n4. Witness sends MERGE_READY to refinery\n5. Refinery sees 'no commits ahead of main' - skips\n6. Witness nukes polecat\n7. Work lost forever\n\nEvidence: Refinery log shows 'MERGE_SKIPPED: furiosa (gt-ft5eb) - No commits ahead of main'\n\nAll formula convoy work was lost this way.\n\nFix: gt done MUST verify push succeeded before signaling completion.","status":"closed","priority":0,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T15:05:07.117395-08:00","created_by":"mayor","updated_at":"2026-01-01T15:47:10.518739-08:00","closed_at":"2026-01-01T15:47:10.518739-08:00","close_reason":"Fixed in cf03343 - added push verification to gt mq submit"} -{"id":"gt-2hzl4","title":"Day 2.4: Add timeout fallback for dead agents","description":"For truly dead agents that can't report their own death:\n- Daemon tracks last_seen timestamp from heartbeats\n- If no heartbeat for N minutes AND state=running, mark state=dead\n- This is fallback only, not primary state source\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:10.896874-08:00","created_by":"mayor","updated_at":"2025-12-28T01:56:01.080382-08:00","closed_at":"2025-12-28T01:56:01.080382-08:00","dependencies":[{"issue_id":"gt-2hzl4","depends_on_id":"gt-39ttg","type":"blocks","created_at":"2025-12-27T20:58:48.958042-08:00","created_by":"daemon"}]} -{"id":"gt-2id8g","title":"Merge: chumbucket-mk0ao4ek","description":"branch: polecat/chumbucket-mk0ao4ek\ntarget: main\nsource_issue: chumbucket-mk0ao4ek\nrig: gastown\nagent_bead: gt-gastown-polecat-chumbucket\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T14:22:59.138393-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T14:27:42.879184-08:00","closed_at":"2026-01-04T14:27:42.879184-08:00","close_reason":"Merged to main at 4b8b4441"} -{"id":"gt-2jcok","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:33:53.623348-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.736169-08:00","closed_at":"2026-01-04T16:40:22.736169-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:33:53-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-2jjry","title":"Add missing hq-dog-role to initTownAgentBeads","description":"The initTownAgentBeads() function in install.go creates role beads for Mayor, Deacon, Witness, Refinery, Polecat, Crew but is missing Dog role bead (hq-dog-role).\n\nAdd DogRoleBeadIDTown() to the roleDefs slice.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/chumbucket","created_at":"2026-01-03T21:48:45.965232-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T15:37:39.695065-08:00","closed_at":"2026-01-04T15:37:39.695065-08:00","close_reason":"Already implemented and merged in b7d82c72","dependencies":[{"issue_id":"gt-2jjry","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T21:48:59.499594-08:00","created_by":"gastown/polecats/warboy"}]} -{"id":"gt-2kpaw","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:50:11.719858-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T18:50:11.776763-08:00","closed_at":"2026-01-06T18:50:11.776763-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:50:11-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-2kz","title":"CLI: cleanup commands for stale state","description":"Cleanup commands for recovering from stale state.\n\n## Commands\n\n### gt cleanup \u003cpolecat\u003e\nClean stale state for specific polecat.\n```\ngt cleanup \u003crig\u003e/\u003cpolecat\u003e [--dry-run]\n```\n\nActions:\n- Remove orphaned state.json if clone missing\n- Clear stale session references\n- Reset stuck state (working → idle after timeout)\n\n### gt cleanup --all\nClean all polecats in workspace.\n```\ngt cleanup --all [--dry-run]\n```\n\n## Implementation\n```go\nfunc CleanupPolecat(rigName, polecatName string, dryRun bool) (*CleanupResult, error)\n\ntype CleanupResult struct {\n OrphanedStateRemoved bool\n SessionsCleared int\n StateReset bool\n Warnings []string\n}\n```\n\n## Overlap with Doctor\n- Doctor diagnoses and offers --fix\n- Cleanup is more aggressive state recovery\n- Consider merging into doctor --fix\n\n## New File\ninternal/cmd/cleanup.go\n\n## Acceptance Criteria\n- [ ] Removes orphaned state files\n- [ ] Clears stale session refs\n- [ ] --dry-run shows what would happen\n- [ ] Reports all actions taken","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T14:48:31.944982-08:00","updated_at":"2025-12-16T16:07:12.430696-08:00"} -{"id":"gt-2meqm","title":"Change session naming from gt-{town}-{role} to gt-{role}-{town}","description":"REVISED: Revert PR #70 entirely.\n\nAfter discussion, multi-town on one machine isn't a real use case:\n- Rigs provide project isolation within a town\n- True isolation should use containers/VMs\n- The complexity tax isn't worth it for edge cases\n\nSolution: Revert to simple gt-mayor and gt-deacon (no town qualifier).\nIf someone tries to run a second town's mayor, they get a collision error.\nThis is honest about the architecture: one town per machine.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2026-01-03T14:11:40.628418-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:37:58.826099-08:00","closed_at":"2026-01-04T23:37:58.826099-08:00","close_reason":"Already completed in commit 4bcf50bf (Revert to simple gt-mayor/gt-deacon session names) which is on main"} -{"id":"gt-2mncz","title":"Digest: mol-deacon-patrol","description":"Patrol 3: quiet, health OK","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:42:55.871006-08:00","updated_at":"2025-12-28T19:42:55.871006-08:00","closed_at":"2025-12-28T19:42:55.870971-08:00"} -{"id":"gt-2o3vq","title":"Merge: rictus-mjxofiub","description":"branch: polecat/rictus-mjxofiub\ntarget: main\nsource_issue: rictus-mjxofiub\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:54:31.175504-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T18:57:08.979556-08:00","closed_at":"2026-01-02T18:57:08.979556-08:00","close_reason":"Merged to main at 6400f94f"} -{"id":"gt-2o5qx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All infrastructure healthy. 3 Witnesses running, 3 Refineries running. Town idle.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:00:30.371662-08:00","updated_at":"2026-01-01T20:00:30.371662-08:00","closed_at":"2026-01-01T20:00:30.371627-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-2ocgh","title":"Code review swarm: recent merges","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-29T22:20:59.115974-08:00","created_by":"gastown/refinery","updated_at":"2025-12-30T10:07:36.956632-08:00","closed_at":"2025-12-30T10:07:36.956632-08:00","close_reason":"All code reviews completed"} -{"id":"gt-2q8u1","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:58:43.161047-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:58:43.212525-08:00","closed_at":"2026-01-06T13:58:43.212525-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:58:42-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-2qhz6","title":"Merge: nux-mk0uimp8","description":"branch: polecat/nux-mk0uimp8\ntarget: main\nsource_issue: nux-mk0uimp8\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T23:43:48.637367-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T00:24:02.678002-08:00","closed_at":"2026-01-05T00:24:02.678002-08:00","close_reason":"Merged to main at ca71f9b8"} -{"id":"gt-2r25i","title":"Merge: rictus-mjxc967h","description":"branch: polecat/rictus-mjxc967h\ntarget: main\nsource_issue: rictus-mjxc967h\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:47:50.532044-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T12:57:30.39268-08:00","closed_at":"2026-01-02T12:57:30.39268-08:00"} -{"id":"gt-2r61z","title":"Session test no rig","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:21:14.525981-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:23:05.791399-08:00","closed_at":"2026-01-02T13:23:05.791399-08:00","close_reason":"Test cleanup","event_kind":"session.ended","actor":"gastown/polecats/test","payload":"{\"cost_usd\":2.5}"} -{"id":"gt-2rfvq","title":"list: static mailing list lookup","description":"Static mailing list support via config file.\n\n## Deliverables\n\n1. Load lists from ~/gt/config/lists.json\n2. Parse list:name syntax in router\n3. Fan-out at send time (same as @group)\n4. Error handling for unknown list names\n\n## Example\n```bash\ngt mail send list:oncall -s \"Alert\" -m \"System down\"\n# Expands to: mayor/, gastown/witness, beads/witness\n# Creates 3 message copies\n```\n\n## Dependencies\n- Config directory (gt-i6jvc)\n\n## Acceptance\n- list:oncall resolves to configured members\n- Each member gets own message copy\n- Unknown list returns clear error","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/morsov","created_at":"2025-12-26T14:52:05.784822-08:00","updated_at":"2025-12-30T06:55:16.140268-08:00","closed_at":"2025-12-30T06:55:16.140268-08:00","close_reason":"Implemented static mailing list support with list:name syntax","dependencies":[{"issue_id":"gt-2rfvq","depends_on_id":"gt-i6jvc","type":"blocks","created_at":"2025-12-26T14:53:05.44199-08:00","created_by":"daemon"}]} -{"id":"gt-2s2et","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:18:29.085028-08:00","updated_at":"2026-01-01T07:18:29.085028-08:00","closed_at":"2026-01-01T07:18:29.084991-08:00"} -{"id":"gt-2sb9y","title":"Session ended: gt-gastown-blackfinger","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:50:01.847609-08:00","created_by":"gastown/polecats/blackfinger","updated_at":"2026-01-05T00:08:31.539519-08:00","closed_at":"2026-01-05T00:08:31.539519-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/blackfinger","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:50:01-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-blackfinger\",\"worker\":\"blackfinger\"}"} -{"id":"gt-2shgk","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:22:08.305361-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.063932-08:00","closed_at":"2026-01-04T16:41:26.063932-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:22:08-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-2sw","title":"Plugin surface for daemon lifecycle hooks","description":"Allow rigs to customize daemon behavior via hooks/plugins.\n\n## Hook Points\n\n- on_heartbeat: Called during daemon heartbeat cycle\n- on_worker_idle: Called when worker goes idle\n- on_worker_stuck: Called when stuck detection triggers\n- on_lifecycle_request: Called before processing lifecycle\n\n## Configuration\n\n```\n\u003crig\u003e/config/daemon-hooks.json\n{\n \"on_heartbeat\": \"./hooks/check-ci-status.sh\",\n \"on_worker_idle\": \"./hooks/maybe-assign-work.sh\",\n \"idle_threshold\": \"5m\",\n \"custom_signals\": [\n {\"name\": \"ci_status\", \"command\": \"./hooks/get-ci.sh\"}\n ]\n}\n```\n\n## Signal Contribution\n\nHooks can return signals that feed into decision engine:\n- SKIP_POKE: Don't poke this agent\n- FORCE_POKE: Override backoff, poke now\n- CUSTOM_DATA: Extra context for logging\n\n## Use Cases\n\n- Check CI status before interrupting test runs\n- Auto-assign work when worker becomes idle\n- Custom stuck detection for specific workflows","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-18T14:19:34.702624-08:00","updated_at":"2025-12-18T14:19:34.702624-08:00","dependencies":[{"issue_id":"gt-2sw","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:47.035848-08:00","created_by":"daemon"}]} -{"id":"gt-2tjy5","title":"Digest: mol-deacon-patrol","description":"Patrol 11: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:46:47.786158-08:00","updated_at":"2025-12-28T19:46:47.786158-08:00","closed_at":"2025-12-28T19:46:47.786122-08:00"} -{"id":"gt-2tmgd","title":"Digest: mol-deacon-patrol","description":"Patrol 147 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:01:54.468312-08:00","updated_at":"2025-12-31T16:01:54.468312-08:00","closed_at":"2025-12-31T16:01:54.468279-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2tspu","title":"Merge: furiosa-dogs","description":"branch: polecat/furiosa-dogs\ntarget: main\nsource_issue: furiosa-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:42:17.456779-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T18:23:22.214095-08:00","closed_at":"2025-12-30T18:23:22.214095-08:00"} -{"id":"gt-2txwk","title":"Digest: mol-deacon-patrol","description":"Patrol 18: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:11:44.359372-08:00","updated_at":"2025-12-31T18:11:44.359372-08:00","closed_at":"2025-12-31T18:11:44.359337-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2ud72","title":"Digest: mol-deacon-patrol","description":"Patrol 7: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:03:34.860376-08:00","updated_at":"2025-12-31T19:03:34.860376-08:00","closed_at":"2025-12-31T19:03:34.860341-08:00"} -{"id":"gt-2ulks","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:18:00.063233-08:00","updated_at":"2026-01-01T06:18:00.063233-08:00","closed_at":"2026-01-01T06:18:00.063197-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2unzu","title":"Merge: cheedo-mjw70xce","description":"branch: polecat/cheedo-mjw70xce\ntarget: main\nsource_issue: cheedo-mjw70xce\nrig: gastown\nagent_bead: gt-gastown-polecat-cheedo","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:05:52.90112-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2026-01-01T19:12:57.557014-08:00","closed_at":"2026-01-01T19:12:57.557014-08:00","close_reason":"Merged to main at 3389687d"} -{"id":"gt-2uos6","title":"Digest: mol-deacon-patrol","description":"Patrol 4: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T17:17:09.139846-08:00","updated_at":"2025-12-26T17:17:09.139846-08:00","closed_at":"2025-12-26T17:17:09.139809-08:00"} -{"id":"gt-2wc1n","title":"Polecat hook not cleared after work completion","description":"## Problem\n\nWhen a polecat completes work (bead closed, branch merged), the hook is not cleared. This prevents automatic cleanup because `gt polecat nuke` sees work still hooked and refuses to nuke without --force.\n\n## Evidence\n\nAfter work merged:\n```\n$ gt polecat nuke gastown/chumbucket\nError: Cannot nuke:\n - has work on hook (gt-bc6gm)\n```\n\nBut gt-bc6gm is closed:\n```\n$ bd show gt-bc6gm\nStatus: closed\n```\n\n## Expected Behavior\n\nWhen `gt done` or merge completion occurs:\n1. Close the bead ✓\n2. Clear the hook ✗ (missing)\n3. Update polecat state ✓\n\n## Fix\n\nIn the completion flow (gt done / witness merge handler):\n- Call hook clear after bead close\n- Or: nuke should check bead status, not just hook presence","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/corpus","created_at":"2026-01-04T15:07:23.538969-08:00","created_by":"mayor","updated_at":"2026-01-04T15:17:35.82457-08:00","closed_at":"2026-01-04T15:17:35.82457-08:00","close_reason":"Fixed: bd slot commands now use rig path instead of town root"} -{"id":"gt-2wsja","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:25:17.395892-08:00","updated_at":"2026-01-01T10:25:17.395892-08:00","closed_at":"2026-01-01T10:25:17.395855-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2x1wp","title":"Merge: furiosa-1767081103575","description":"branch: polecat/furiosa-1767081103575\ntarget: main\nsource_issue: furiosa-1767081103575\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:08:47.214888-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T01:01:04.302982-08:00","closed_at":"2025-12-30T01:01:04.302982-08:00","close_reason":"Already merged to main"} -{"id":"gt-2ybyl","title":"Digest: mol-deacon-patrol","description":"Patrol 4: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:36:13.509415-08:00","updated_at":"2026-01-01T22:36:13.509415-08:00","closed_at":"2026-01-01T22:36:13.509385-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-2yls3","title":"GAP: Deacon patrol needs stale hooked bead cleanup","description":"The deacon patrol mol-deacon-patrol does not have a step to clean up stale hooked beads.\n\nDuring shutdown cleanup, found:\n- Handoff beads stuck in hooked status after processing\n- Template beads (hq-1lit, hq-5vu, etc.) perpetually hooked\n\nProposed addition to patrol:\n1. Query for beads with status=hooked older than X hours\n2. For handoffs: Close them (they were processed)\n3. For templates: Reset to appropriate status\n4. Log cleanup actions\n\nThis should be a backstop - the primary fix is ensuring hooked status is cleared after processing.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T20:38:51.213334-08:00","created_by":"mayor","updated_at":"2026-01-06T13:20:52.41457-08:00","closed_at":"2026-01-06T13:20:52.41457-08:00","close_reason":"Implemented gt deacon stale-hooks command and added step to patrol formula"} -{"id":"gt-2z2gi","title":"Session ended: gt-gastown-prime","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:41:47.273346-08:00","created_by":"gastown/polecats/prime","updated_at":"2026-01-04T16:40:13.319521-08:00","closed_at":"2026-01-04T16:40:13.319521-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/prime","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:41:47-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-prime\",\"worker\":\"prime\"}"} -{"id":"gt-2zaj0","title":"Digest: mol-deacon-patrol","description":"Patrol 32: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:59:30.3744-08:00","updated_at":"2025-12-31T13:59:30.3744-08:00","closed_at":"2025-12-31T13:59:30.374363-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-2zaq","title":"Digest: mol-deacon-patrol","description":"Patrol 10","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T23:09:10.365013-08:00","updated_at":"2025-12-24T23:09:10.365013-08:00","closed_at":"2025-12-24T23:09:10.364985-08:00"} -{"id":"gt-2zm8e","title":"Digest: mol-deacon-patrol","description":"Patrol 13","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T20:04:32.276444-08:00","updated_at":"2025-12-26T20:04:32.276444-08:00","closed_at":"2025-12-26T20:04:32.276392-08:00"} -{"id":"gt-30d36","title":"Digest: mol-deacon-patrol","description":"Patrol 220: All nominal - handing off after 20 cycles","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:59:25.349104-08:00","updated_at":"2026-01-01T16:59:25.349104-08:00","closed_at":"2026-01-01T16:59:25.349073-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-30d36","depends_on_id":"gt-eph-qcc1","type":"parent-child","created_at":"2026-01-01T16:59:25.350532-08:00","created_by":"deacon"}]} -{"id":"gt-30duv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:20:05.084672-08:00","updated_at":"2026-01-01T07:20:05.084672-08:00","closed_at":"2026-01-01T07:20:05.084634-08:00"} -{"id":"gt-30i7v","title":"Merge: nux-mjxn8p5t","description":"branch: polecat/nux-mjxn8p5t\ntarget: main\nsource_issue: nux-mjxn8p5t\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:55:50.699122-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T18:57:59.524744-08:00","closed_at":"2026-01-02T18:57:59.524744-08:00"} -{"id":"gt-30o","title":"Error handling improvements: retry logic and recovery hints","description":"Improve error handling across GGT codebase.\n\n## Issues Found\n\n### 1. Silent Failures in Refinery\nmanager.go ProcessMR():\n- git pull errors ignored\n- Continues processing even on partial failures\n\n### 2. Missing Beads CLI\nMany operations silently continue if `bd` not found:\n```go\n// Current\ntasks, err := m.loadTasksFromBeads(epicID)\nif err != nil {\n // Non-fatal - swarm can start without tasks\n}\n\n// Better\nif err != nil {\n return nil, fmt.Errorf(\"beads required: %w\", err)\n}\n```\n\n### 3. No Retry Logic\nNetwork/lock errors should retry:\n```go\nfunc withRetry(attempts int, delay time.Duration, fn func() error) error {\n for i := 0; i \u003c attempts; i++ {\n if err := fn(); err == nil {\n return nil\n }\n time.Sleep(delay)\n }\n return fmt.Errorf(\"failed after %d attempts\", attempts)\n}\n```\n\n### 4. Recovery Hints\nError messages should include fix suggestions:\n```go\n// Current\nreturn fmt.Errorf(\"polecat not found\")\n\n// Better\nreturn fmt.Errorf(\"polecat '%s' not found. Use 'gt polecat list' to see available polecats\", name)\n```\n\n## Domain Error Types\n```go\ntype SessionError struct {\n Op string\n Polecat string\n Err error\n}\n\nfunc (e *SessionError) Error() string {\n return fmt.Sprintf(\"session %s for %s: %v\", e.Op, e.Polecat, e.Err)\n}\n```\n\n## Files to Review\n- internal/refinery/manager.go\n- internal/swarm/manager.go\n- internal/session/manager.go\n- All cmd/*.go files\n\n## Acceptance Criteria\n- [ ] No silent error swallowing\n- [ ] Retry logic for transient failures\n- [ ] Helpful error messages with hints\n- [ ] Consistent error types per domain","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:48:48.183421-08:00","updated_at":"2025-12-16T16:06:52.751546-08:00"} -{"id":"gt-30yi6","title":"Digest: mol-deacon-patrol","description":"Patrol 3: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:03:13.563384-08:00","updated_at":"2025-12-27T23:03:13.563384-08:00","closed_at":"2025-12-27T23:03:13.563353-08:00"} -{"id":"gt-31k39","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 79: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:27:21.31756-08:00","updated_at":"2026-01-01T13:27:21.31756-08:00","closed_at":"2026-01-01T13:27:21.317521-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-31w2n","title":"Digest: mol-deacon-patrol","description":"Patrol 124: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:32:43.016221-08:00","updated_at":"2026-01-01T14:32:43.016221-08:00","closed_at":"2026-01-01T14:32:43.016182-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-32d4a","title":"Remove gt polecat done/reset/finish commands (idle producers)","description":"## Problem\n\nCommands exist that transition polecats to idle state, violating the transient model.\n\nFrom PRIMING.md: \"Polecats exist only while working. One task, then nuked.\"\n\n## Heretical Commands\n\n1. gt polecat done - \"Mark polecat as done with work and return to idle\"\n2. gt polecat reset - \"Force reset polecat to idle state\" \n3. gt polecat finish - alias for done\n4. gt polecat sleep - deprecated but still exists\n\n## Confusion with gt done\n\nTwo commands with similar names but different semantics:\n- gt done (correct): Push branch, create MR, signal Witness for nuke\n- gt polecat done (heresy): Transition to idle, sandbox stays\n\n## Correct Model\n\nPolecats should only use gt done (or gt handoff which calls gt done).\nThe Witness handles sandbox destruction. There is no \"return to idle\" - only death.\n\n## Changes Required\n\n1. Remove gt polecat done command\n2. Remove gt polecat reset command\n3. Remove gt polecat finish alias\n4. Remove gt polecat sleep (already deprecated)\n5. Remove manager.Finish() and manager.Reset() methods\n6. Update any callers to use proper lifecycle (gt done -\u003e Witness nuke)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/corpus","created_at":"2026-01-04T14:10:07.925374-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T14:25:20.765217-08:00","closed_at":"2026-01-04T14:25:20.765217-08:00","close_reason":"Removed idle producer commands"} -{"id":"gt-33kxm","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:25:17.556636-08:00","updated_at":"2026-01-01T07:25:17.556636-08:00","closed_at":"2026-01-01T07:25:17.556601-08:00"} -{"id":"gt-33z0k","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:55:54.029385-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:55:54.076873-08:00","closed_at":"2026-01-05T19:55:54.076873-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:55:53-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-341nl","title":"Digest: mol-deacon-patrol","description":"Patrol 1: inbox clear, witness/refinery healthy, no orphans, no plugins","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:11:05.82261-08:00","updated_at":"2025-12-28T08:11:05.82261-08:00","closed_at":"2025-12-28T08:11:05.822571-08:00"} -{"id":"gt-34mxx","title":"Wire polecat-CLAUDE.md template into polecat spawn","description":"The templates/polecat-CLAUDE.md file needs to be copied into each polecat worktree when spawned.\n\nLocation: templates/polecat-CLAUDE.md\nTarget: polecats/\u003cname\u003e/CLAUDE.md (with {{rig}} and {{name}} substituted)\n\nImplementation:\n- Update gt polecat spawn (or wherever worktrees are created)\n- Template substitution for {{rig}}, {{name}} variables\n- Ensure file is created before Claude session starts","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T12:48:13.553182-08:00","created_by":"mayor","updated_at":"2025-12-28T13:00:03.294819-08:00","closed_at":"2025-12-28T13:00:03.294819-08:00"} -{"id":"gt-358ig","title":"Merge: fury-mk0vskad","description":"branch: polecat/fury-mk0vskad\ntarget: main\nsource_issue: fury-mk0vskad\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:13:06.205933-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T19:40:10.261982-08:00","closed_at":"2026-01-05T19:40:10.261982-08:00","close_reason":"Manually merged"} -{"id":"gt-35x","title":"Plugin: plan-oracle (work decomposition)","description":"Plugin that helps decompose epics/issues into sub-tasks. Analyzes scope, identifies dependencies, estimates complexity for parallelization, creates beads for sub-tasks with dependency links.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-15T22:53:05.772986-08:00","updated_at":"2025-12-15T23:17:06.423894-08:00","dependencies":[{"issue_id":"gt-35x","depends_on_id":"gt-axz","type":"blocks","created_at":"2025-12-15T22:53:17.587726-08:00","created_by":"daemon"}]} -{"id":"gt-36c8i","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:21:39.788872-08:00","updated_at":"2026-01-01T10:21:39.788872-08:00","closed_at":"2026-01-01T10:21:39.788841-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-36g7s","title":"Digest: mol-deacon-patrol","description":"Patrol 143: 2 polecats (nux, rictus) working on formula tasks, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:54:22.136939-08:00","updated_at":"2026-01-01T14:54:22.136939-08:00","closed_at":"2026-01-01T14:54:22.136894-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-37own","title":"Digest: mol-deacon-patrol","description":"Patrol 128: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:34:25.87271-08:00","updated_at":"2026-01-01T14:34:25.87271-08:00","closed_at":"2026-01-01T14:34:25.872672-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-37pp3","title":"Digest: mol-deacon-patrol","description":"Patrol 3: all healthy, mayor running, witnesses running","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:51:44.052973-08:00","updated_at":"2025-12-28T15:51:44.052973-08:00","closed_at":"2025-12-28T15:51:44.052934-08:00"} -{"id":"gt-37yct","title":"Session ended: gt-gastown-prime","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:19:03.530855-08:00","created_by":"gastown/polecats/prime","updated_at":"2026-01-05T00:08:31.832544-08:00","closed_at":"2026-01-05T00:08:31.832544-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/prime","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:19:03-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-prime\",\"worker\":\"prime\"}"} -{"id":"gt-38azb","title":"Digest: mol-deacon-patrol","description":"Cycle 198: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:24:32.396602-08:00","updated_at":"2026-01-01T16:24:32.396602-08:00","closed_at":"2026-01-01T16:24:32.396567-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-38azb","depends_on_id":"gt-eph-9p1m","type":"parent-child","created_at":"2026-01-01T16:24:32.397983-08:00","created_by":"deacon"}]} -{"id":"gt-38doh","title":"Feed daemon: curate raw events into user-facing feed","description":"Goroutine in gt daemon that transforms raw events into curated activity feed.\n\n## Input\n- Tails ~/gt/.events.jsonl (raw events from gt, bd, agents)\n\n## Output \n- Writes ~/gt/.feed.jsonl (curated, user-facing)\n\n## Processing\n1. Filter by visibility tag (drop audit-only events)\n2. Dedupe repeated updates (5 molecule updates → \"agent active\")\n3. Aggregate related events (3 issues closed → \"batch complete\")\n4. Future: AI summarization via haiku for complex activity\n\n## Integration\n- Runs as goroutine in existing gt daemon\n- Starts when daemon starts\n- Graceful shutdown on daemon stop\n\nPart of epic gt-u7dxq","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-28T12:46:37.816384-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T01:51:45.814059-08:00","closed_at":"2025-12-30T01:51:45.814059-08:00","close_reason":"Implemented feed curator goroutine in gt daemon that tails .events.jsonl, filters by visibility, deduplicates repeated events, aggregates related events, and writes curated feed to .feed.jsonl","dependencies":[{"issue_id":"gt-38doh","depends_on_id":"gt-7aw1m","type":"blocks","created_at":"2025-12-28T12:46:47.342014-08:00","created_by":"daemon"}]} -{"id":"gt-38yfg","title":"Merge: gt-xqh3y","description":"branch: polecat/eli-mjufuh2g\ntarget: main\nsource_issue: gt-xqh3y\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-31T12:09:55.661771-08:00","created_by":"gastown/polecats/eli","updated_at":"2025-12-31T12:12:30.577747-08:00","closed_at":"2025-12-31T12:12:30.577747-08:00","close_reason":"Merged at 6d1d1469"} -{"id":"gt-39d13","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:04:47.385904-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T13:04:47.456816-08:00","closed_at":"2026-01-06T13:04:47.456816-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:04:47-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-39ttg","title":"Day 2.1: Daemon reads agent bead state field","description":"Daemon queries agent beads for state instead of inferring from PID/tmux.\n\nChange getAgentState() to:\n1. Look up agent bead by ID (gt-mayor, gt-witness, etc.)\n2. Read state field (idle|running|stuck|stopped)\n3. Trust the value\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:57:55.813003-08:00","created_by":"mayor","updated_at":"2025-12-28T01:34:43.212173-08:00","closed_at":"2025-12-28T01:34:43.212173-08:00","dependencies":[{"issue_id":"gt-39ttg","depends_on_id":"gt-lisj6","type":"blocks","created_at":"2025-12-27T21:00:31.823241-08:00","created_by":"daemon"}]} -{"id":"gt-39udq","title":"Session ended: gt-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:25:00.929277-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:41:26.1822-08:00","closed_at":"2026-01-04T16:41:26.1822-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:25:00-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-refinery\",\"worker\":\"refinery\"}"} -{"id":"gt-39y42","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:45:56.444436-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T18:54:10.976652-08:00","closed_at":"2026-01-01T18:54:10.976652-08:00"} -{"id":"gt-3aeuq","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:44:42.709442-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T16:41:00.375429-08:00","closed_at":"2026-01-04T16:41:00.375429-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:44:42-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-3ainv","title":"Digest: mol-deacon-patrol","description":"Cycle 15","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:54:53.117385-08:00","updated_at":"2025-12-31T22:54:53.117385-08:00","closed_at":"2025-12-31T22:54:53.117352-08:00"} -{"id":"gt-3amkz","title":"Overhaul autonomous-mode guidance with ledger/capability framing","description":"Re-read all relevant docs in ~/gt/docs (especially hop/) and overhaul the autonomous-mode guidance in role templates with a stronger \"why\" framing.\n\nCurrent state:\n- Theory of Operation explains \"system stalls if you wait\"\n- Steam engine metaphor (piston, gearbox, flywheel)\n- Physics not politeness language\n\nEnhancement direction (without revealing HOP explicitly):\n1. Frame work as \"contributing to a ledger of demonstrated capability\"\n2. Emphasize quality: \"your work history is visible, every completion matters\"\n3. Add the redemption arc: \"bad work can be overcome through consistent good work\"\n4. Strengthen the \"proving the model\" angle: \"every autonomous completion is evidence this works at scale\"\n5. Consider adding \"your CV grows with every completion\" concept\n\nFiles to update:\n- internal/templates/roles/*.md.tmpl (all role templates)\n- internal/cmd/prime.go (AUTONOMOUS MODE output)\n- Possibly ~/gt/docs/philosophy.md or similar\n\nConstraints:\n- Gas Town cannot explicitly reference HOP\n- Concepts and motivation are fine, just not the name or confidential details\n- Should feel like natural evolution, not grafted-on messaging\n\nRead first:\n- ~/gt/docs/hop/CONTEXT.md\n- ~/gt/docs/hop/BUSINESS_OVERVIEW.md\n- ~/gt/docs/philosophy.md (if exists)\n- All role templates\n\nDeliverable: Updated templates and prime.go with stronger ledger/capability framing.","status":"closed","priority":2,"issue_type":"task","assignee":"mayor","created_at":"2025-12-29T15:40:12.440738-08:00","created_by":"mayor","updated_at":"2025-12-29T16:06:46.626911-08:00","closed_at":"2025-12-29T16:06:46.626911-08:00","close_reason":"Implemented ledger/capability framing in all role templates and prime.go. Also fixed hooked/pinned terminology confusion. Filed gt-d9smb for gt mol status output fix."} -{"id":"gt-3b4jp","title":"Digest: mol-deacon-patrol","description":"Patrol 14: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:18:57.76815-08:00","updated_at":"2025-12-25T10:18:57.76815-08:00","closed_at":"2025-12-25T10:18:57.768117-08:00"} -{"id":"gt-3bg5o","title":"Digest: mol-deacon-patrol","description":"Cycle 9","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:02:21.326432-08:00","updated_at":"2026-01-01T10:02:21.326432-08:00","closed_at":"2026-01-01T10:02:21.326394-08:00","dependencies":[{"issue_id":"gt-3bg5o","depends_on_id":"gt-eph-r4jn","type":"parent-child","created_at":"2026-01-01T10:02:21.327663-08:00","created_by":"deacon"}]} -{"id":"gt-3bm5x","title":"Review PR #44: docs: Fix Quick Start to use gt mayor attach","description":"Review and approve/request changes for PR #44. Check docs accuracy. If good, approve with gh pr review --approve.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-03T11:40:26.239793-08:00","created_by":"mayor","updated_at":"2026-01-03T11:43:38.932648-08:00","closed_at":"2026-01-03T11:43:38.932648-08:00","close_reason":"Approved PR #44 - change is correct"} -{"id":"gt-3cns","title":"Test Patrol for Bonding","description":"Parent issue for mol bond CLI test","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T22:30:43.27929-08:00","updated_at":"2025-12-25T01:33:00.912315-08:00","closed_at":"2025-12-25T01:33:00.912315-08:00"} -{"id":"gt-3cu","title":"Default polecat names: Mad Max theme instead of AdjectiveNoun","description":"Current default naming for new polecats uses AdjectiveNoun convention.\nSince rigs already provide namespacing, we can use more thematic names.\n\nSuggestion: Use Mad Max / Fury Road character and vehicle names as defaults.\nExamples: Furiosa, Nux, Slit, Morsov, Toast, Rictus, Warboy, etc.\n\nCould also include:\n- War Rig parts: Guzzler, Tanker, Pursuit\n- Citadel roles: Imperator, Blackthumb, Organic\n- Wasteland terms: Chrome, Witness, Shiny\n\nImplementation:\n- Add name generator in internal/polecat/ or similar\n- Use when --create flag is used without explicit name\n- Cycle through pool to avoid duplicates within a rig","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-17T14:50:43.252922-08:00","updated_at":"2025-12-17T14:50:43.252922-08:00"} -{"id":"gt-3d4wp","title":"Merge: furiosa-1767059690595","description":"branch: polecat/furiosa-1767059690595\ntarget: main\nsource_issue: furiosa-1767059690595\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T18:05:28.9319-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-29T21:45:58.30243-08:00","closed_at":"2025-12-29T21:45:58.30243-08:00","close_reason":"Stale merge requests - branches no longer exist"} -{"id":"gt-3d5oj","title":"Digest: mol-deacon-patrol","description":"Cycle 12","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:55:14.712897-08:00","updated_at":"2025-12-31T23:55:14.712897-08:00","closed_at":"2025-12-31T23:55:14.712859-08:00"} -{"id":"gt-3dmje","title":"Digest: mol-deacon-patrol","description":"Patrol #15: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:23:41.635518-08:00","updated_at":"2025-12-31T06:23:41.635518-08:00","closed_at":"2025-12-31T06:23:41.635482-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3dsxm","title":"Merge: capable-1767074169502","description":"attached_args: Code review this merge request\n\nbranch: polecat/capable-1767074169502\ntarget: main\nsource_issue: capable-1767074169502\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/nux","created_at":"2025-12-29T22:06:28.135311-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-29T23:55:48.370109-08:00","closed_at":"2025-12-29T23:55:48.370109-08:00","close_reason":"STALE: Branch polecat/capable-1767074169502 no longer exists. The underlying work (gt-594a4 BeadsPath fix) was already merged to main via commit e362be3c at 23:43. This merge request was orphaned."} -{"id":"gt-3ee79","title":"Merge: vuvalini-mk0frc7r","description":"branch: polecat/vuvalini-mk0frc7r\ntarget: main\nsource_issue: vuvalini-mk0frc7r\nrig: gastown\nagent_bead: gt-gastown-polecat-vuvalini\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T16:51:27.390982-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-04T21:33:13.333747-08:00","closed_at":"2026-01-04T21:33:13.333747-08:00","close_reason":"Already merged to main at f0c94db9"} -{"id":"gt-3eqof","title":"Overseer inbox for strategic notifications","description":"New address overseer/ for strategic notifications.\n\nReceives:\n- Convoy completions\n- Cross-rig dependency resolutions\n- Escalations from Deacon\n- Daily digests (optional)\n\nSeparate from operational mail - this is the executive dashboard.\n\nRelated: hq-7h8jx (Convoy System epic in town beads)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-29T18:47:34.183831-08:00","created_by":"mayor","updated_at":"2025-12-29T18:47:34.183831-08:00","dependencies":[{"issue_id":"gt-3eqof","depends_on_id":"gt-wthcc","type":"blocks","created_at":"2025-12-29T18:47:51.112035-08:00","created_by":"daemon"}]} -{"id":"gt-3f4un","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:19:37.095855-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T13:19:37.150457-08:00","closed_at":"2026-01-06T13:19:37.150457-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:19:36-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-3fjt4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:44:08.274496-08:00","updated_at":"2026-01-01T07:44:08.274496-08:00","closed_at":"2026-01-01T07:44:08.274461-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3fm","title":"Mail orchestrator daemon","description":"Background mail orchestrator daemon.\n\n## Command\n```\ngt mail orchestrate [--interval N] [--once] [--verbose]\n```\n\n## Purpose\nBackground process that:\n1. Monitors outbox for pending mail\n2. Delivers to recipient inboxes\n3. Handles offline recipients (retry later)\n4. Cleans delivered messages from outbox\n\n## Why Needed?\nCurrent mail is synchronous. If recipient is offline or mailbox locked, send fails.\nOrchestrator enables async delivery with retry.\n\n## Implementation\n```go\nfunc (o *Orchestrator) Run(interval time.Duration) error {\n ticker := time.NewTicker(interval)\n for range ticker.C {\n o.processOutbox()\n }\n}\n\nfunc (o *Orchestrator) processOutbox() {\n // List outbox/*.json\n // For each, attempt delivery\n // On success, delete from outbox\n // On failure, increment retry count\n}\n```\n\n## Outbox Structure\n```\n\u003ctown\u003e/mayor/mail/outbox/\n├── msg-abc123.json\n└── msg-def456.json\n```\n\n## Lower Priority\nCurrent synchronous delivery works. Orchestrator is optimization.\n\n## Acceptance Criteria\n- [ ] Background daemon mode\n- [ ] Retry failed deliveries\n- [ ] --once for single pass\n- [ ] Configurable interval","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T14:48:29.830841-08:00","updated_at":"2025-12-16T16:07:35.973257-08:00"} -{"id":"gt-3fpp4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:28:14.902359-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.39323-08:00","closed_at":"2026-01-05T19:44:18.39323-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:28:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-3g4b0","title":"Merge: rockryder-mk0frt3g","description":"branch: polecat/rockryder-mk0frt3g\ntarget: main\nsource_issue: rockryder-mk0frt3g\nrig: gastown\nagent_bead: gt-gastown-polecat-rockryder\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T16:53:17.873861-08:00","created_by":"gastown/polecats/rockryder","updated_at":"2026-01-04T23:48:31.280142-08:00","closed_at":"2026-01-04T23:48:31.280142-08:00","close_reason":"Merged to main at 252dcc41"} -{"id":"gt-3gepq","title":"Merge: toast-1767081120579","description":"branch: polecat/toast-1767081120579\ntarget: main\nsource_issue: toast-1767081120579\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:55:14.854033-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T10:06:56.875708-08:00","closed_at":"2025-12-30T10:06:56.875708-08:00","close_reason":"Branch merged to main"} -{"id":"gt-3gn4g","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:37:32.286955-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:40:13.34649-08:00","closed_at":"2026-01-04T16:40:13.34649-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:37:32-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-3hzgh","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all healthy, no callbacks","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:02:17.213492-08:00","updated_at":"2025-12-27T23:02:17.213492-08:00","closed_at":"2025-12-27T23:02:17.213455-08:00"} -{"id":"gt-3iu0k","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:45:41.968564-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:40:22.855886-08:00","closed_at":"2026-01-04T16:40:22.855886-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:45:41-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-3ixjx","title":"Digest: mol-deacon-patrol","description":"Patrol 207: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:51:00.212533-08:00","updated_at":"2026-01-01T16:51:00.212533-08:00","closed_at":"2026-01-01T16:51:00.212501-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-3ixjx","depends_on_id":"gt-eph-povm","type":"parent-child","created_at":"2026-01-01T16:51:00.213957-08:00","created_by":"deacon"}]} -{"id":"gt-3jj5z","title":"Session ended: gt-gastown-vuvalini","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:27:17.152251-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-05T00:08:31.824997-08:00","closed_at":"2026-01-05T00:08:31.824997-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/vuvalini","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:27:17-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-vuvalini\",\"worker\":\"vuvalini\"}"} -{"id":"gt-3jnnu","title":"Consider TownBeadsPrefix constant for hq- prefix","description":"The 'hq' prefix string is used in multiple places in agent_ids.go. Consider adding a constant:\n\nconst TownBeadsPrefix = \"hq\"\n\nThis would make prefix changes easier and reduce string duplication.","status":"closed","priority":4,"issue_type":"task","assignee":"gastown/polecats/prime","created_at":"2026-01-03T21:48:49.267842-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T15:40:00.162303-08:00","closed_at":"2026-01-04T15:40:00.162303-08:00","close_reason":"Already completed: TownBeadsPrefix constant exists at agent_ids.go:8 and is used throughout the file. Commit 948986b4 implemented this.","dependencies":[{"issue_id":"gt-3jnnu","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T21:48:59.622116-08:00","created_by":"gastown/polecats/warboy"}]} -{"id":"gt-3jq4i","title":"Witness Patrol","description":"Per-rig worker monitor patrol loop with progressive nudging.","status":"closed","priority":2,"issue_type":"molecule","created_at":"2025-12-26T13:08:21.384337-08:00","updated_at":"2025-12-29T20:57:41.776364-08:00","closed_at":"2025-12-29T20:57:41.776364-08:00","close_reason":"Duplicate patrol molecule beads - keeping gt-t5i07, gt-8ynws, gt-kt9qq"} -{"id":"gt-3k1mv","title":"Digest: mol-deacon-patrol","description":"Patrol 8: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:05:58.133365-08:00","updated_at":"2025-12-31T18:05:58.133365-08:00","closed_at":"2025-12-31T18:05:58.133329-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3kgf0","title":"Digest: mol-deacon-patrol","description":"Patrol 20 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:48:50.811494-08:00","updated_at":"2025-12-31T16:48:50.811494-08:00","closed_at":"2025-12-31T16:48:50.811461-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3kyfy","title":"Close PR #145 - superseded by heresy correction","description":"PR #145 (polecat completion protocol with push step) is a workaround for the push requirement.\n\nOnce heresy correction is complete, PR #145 becomes obsolete - close it with explanation that local-only branches eliminate the need for explicit push instructions.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T12:37:01.710702-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:14:08.342672-08:00","closed_at":"2026-01-06T13:14:08.342672-08:00","close_reason":"PR #145 closed with explanation","dependencies":[{"issue_id":"gt-3kyfy","depends_on_id":"gt-5fmjt","type":"blocks","created_at":"2026-01-06T12:37:09.297896-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-3kyfy","depends_on_id":"gt-cqw0n","type":"blocks","created_at":"2026-01-06T12:37:09.44141-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-3l1ut","title":"Digest: mol-deacon-patrol","description":"Patrol 137: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:38:11.407319-08:00","updated_at":"2026-01-01T14:38:11.407319-08:00","closed_at":"2026-01-01T14:38:11.407284-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3l68a","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:19:53.332792-08:00","updated_at":"2026-01-01T06:19:53.332792-08:00","closed_at":"2026-01-01T06:19:53.332747-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3larv","title":"Digest: mol-deacon-patrol","description":"Patrol 63: Routine, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:59:22.994739-08:00","updated_at":"2025-12-31T14:59:22.994739-08:00","closed_at":"2025-12-31T14:59:22.994709-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3lphl","title":"Session ended: gt-gastown-buzzard","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:47:56.82064-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T00:08:31.554455-08:00","closed_at":"2026-01-05T00:08:31.554455-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/buzzard","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:47:56-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-buzzard\",\"worker\":\"buzzard\"}"} -{"id":"gt-3lpjy","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, cycling at 20 patrols","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:50:03.45138-08:00","updated_at":"2025-12-31T18:50:03.45138-08:00","closed_at":"2025-12-31T18:50:03.451344-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3m203","title":"Merge: furiosa-mjw17xzd","description":"branch: polecat/furiosa-mjw17xzd\ntarget: main\nsource_issue: furiosa-mjw17xzd\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T14:49:27.430271-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T15:40:07.532505-08:00","closed_at":"2026-01-01T15:40:07.532505-08:00","close_reason":"Stale MR - branch has no new commits or doesn't exist"} -{"id":"gt-3n963","title":"Digest: mol-deacon-patrol","description":"Cycle 293: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:39:23.490092-08:00","updated_at":"2026-01-01T18:39:23.490092-08:00","closed_at":"2026-01-01T18:39:23.490052-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-3n963","depends_on_id":"gt-eph-rule","type":"parent-child","created_at":"2026-01-01T18:39:23.491293-08:00","created_by":"deacon"}]} -{"id":"gt-3n9c5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:42:33.48247-08:00","updated_at":"2026-01-01T07:42:33.48247-08:00","closed_at":"2026-01-01T07:42:33.482437-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3otlo","title":"Digest: mol-deacon-patrol","description":"Patrol 34: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:00:18.807168-08:00","updated_at":"2025-12-31T14:00:18.807168-08:00","closed_at":"2025-12-31T14:00:18.80713-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3oyn","title":"Blocked issues: gt-um6q, gt-lz13, gt-5xph depend on missing beads features","description":"Template/docs updates blocked on: bd-nurq (bd mol current), bd-29fb (bd close --continue). These gastown issues should be marked blocked on the beads issues once cross-rig deps work.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T00:19:12.532683-08:00","updated_at":"2025-12-23T00:19:12.532683-08:00"} -{"id":"gt-3p77","title":"Implement gt watch command scaffold","description":"Basic bubbletea TUI scaffold for 'gt watch' command. Discovers rigs, connects to daemons, renders placeholder view. Foundation for the full activity feed TUI.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:27:09.800586-08:00","updated_at":"2025-12-23T16:27:09.800586-08:00","dependencies":[{"issue_id":"gt-3p77","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:30.683781-08:00","created_by":"daemon"}]} -{"id":"gt-3pm0f","title":"gt feed: Activity feed command with tmux-aware modes","description":"## Context\n\n`bd activity` exists and works well for streaming beads mutation events. However:\n- It's not discoverable via `gt` (the agent coordination CLI)\n- No tmux-aware behavior for when Gas Town is running in tmux\n- The planned TUI (gt-rivr) was tombstoned - need a simpler approach\n\n## Requirements\n\n### Without tmux (standalone mode)\n- `gt feed` streams activity to stdout (like `bd activity --follow`)\n- Supports filtering by rig, time window, event type\n- Works in any terminal\n\n### With tmux (integrated mode)\n- Could open/attach to a dedicated activity pane\n- Or provide a way to send feed to a specific pane\n- Integrate with existing gt tmux session management\n\n## Design Questions\n\n1. **Command name**: `gt feed` vs `gt activity` vs `gt watch`?\n2. **Tmux integration**: Dedicated pane? Split? Popup?\n3. **Cross-rig aggregation**: Merge events from multiple rig daemons?\n4. **Filtering UX**: By rig, by molecule, by event type?\n\n## Implementation Options\n\n**Phase 1: Simple wrapper**\n- `gt feed` shells out to `bd activity --follow`\n- Add `--rig` flag for filtering\n- Works identically with/without tmux\n\n**Phase 2: Tmux-aware**\n- Detect if running in gt tmux session\n- Offer to open in dedicated pane\n- `gt feed --pane` to force pane mode\n\n**Phase 3: Cross-rig** (if needed)\n- Aggregate from multiple rig daemons\n- Unified activity stream across town\n\n## Related\n\n- gt-rivr (tombstoned) - Original TUI epic\n- gt-22ng - Activity aggregator (blocked)\n- bd activity command - The underlying implementation\n","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T09:34:48.026886-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T09:59:40.364918-08:00","closed_at":"2025-12-28T09:59:40.364918-08:00"} -{"id":"gt-3qbxd","title":"Digest: mol-deacon-patrol","description":"Cycle 188: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:21:55.855663-08:00","updated_at":"2026-01-01T16:21:55.855663-08:00","closed_at":"2026-01-01T16:21:55.855627-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-3qbxd","depends_on_id":"gt-eph-sykv","type":"parent-child","created_at":"2026-01-01T16:21:55.857125-08:00","created_by":"deacon"}]} -{"id":"gt-3qf4e","title":"Dead Code: Unused parameter in mail/router.go resolveBeadsDir","description":"The resolveBeadsDir function (router.go:187) has an unused parameter:\n\n```go\nfunc (r *Router) resolveBeadsDir(_ string) string { // address unused: all mail uses town-level beads\n```\n\nThe comment explains that the address parameter was previously used for routing but is now unused since all mail uses town-level beads.\n\nOptions:\n1. Remove the parameter entirely\n2. If backward compatibility is needed, mark as deprecated\n\nFiles:\n- internal/mail/router.go:187\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:56.39608-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:47:56.39608-08:00"} -{"id":"gt-3r6r5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:20:37.699798-08:00","updated_at":"2026-01-01T07:20:37.699798-08:00","closed_at":"2026-01-01T07:20:37.699764-08:00"} -{"id":"gt-3rquk","title":"Day 3.0: Document mail protocol contracts","description":"Document the formal mail protocol for Gas Town agent coordination.\n\nMail Types:\n\n**POLECAT_DONE** (polecat → witness)\n```\nSubject: POLECAT_DONE: \u003cname\u003e\nBody: {\"issue\": \"gt-xyz\", \"status\": \"complete|failed\", \"notes\": \"...\"}\n```\n\n**MERGE_READY** (witness → refinery)\n```\nSubject: MERGE_READY: \u003cbranch\u003e\nBody: {\"worker\": \"nux\", \"issue\": \"gt-xyz\", \"branch\": \"polecat/nux/gt-xyz\"}\n```\n\n**MERGED** (refinery → witness)\n```\nSubject: MERGED: \u003cbranch\u003e\nBody: {\"issue\": \"gt-xyz\", \"sha\": \"abc123\", \"worker\": \"nux\"}\n```\n\n**LIFECYCLE:Shutdown/Cycle/Restart** (agent → deacon/)\n```\nSubject: LIFECYCLE:Shutdown\nBody: {\"action\": \"shutdown\"}\n```\n\n**HELP** (polecat → witness → mayor)\n```\nSubject: HELP: \u003cbrief\u003e\nBody: {\"issue\": \"gt-xyz\", \"problem\": \"...\", \"context\": \"...\"}\n```\n\nCreate: docs/mail-protocol.md","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T22:02:11.619888-08:00","created_by":"mayor","updated_at":"2025-12-27T23:18:47.276607-08:00","closed_at":"2025-12-27T23:18:47.276607-08:00","dependencies":[{"issue_id":"gt-3rquk","depends_on_id":"gt-qpoxz","type":"blocks","created_at":"2025-12-27T22:02:45.294244-08:00","created_by":"daemon"}]} -{"id":"gt-3rvb5","title":"Merge: immortan-mjwlaw9o","description":"branch: polecat/immortan-mjwlaw9o\ntarget: main\nsource_issue: immortan-mjwlaw9o\nrig: gastown\nagent_bead: gt-gastown-polecat-immortan","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T00:10:23.765313-08:00","created_by":"gastown/polecats/immortan","updated_at":"2026-01-02T00:13:55.390372-08:00","closed_at":"2026-01-02T00:13:55.390372-08:00","close_reason":"Merged to main at 8c7ea8a9"} -{"id":"gt-3sd3a","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:35.93998-08:00","updated_at":"2025-12-28T11:22:35.93998-08:00","closed_at":"2025-12-28T11:22:35.939949-08:00"} -{"id":"gt-3shmx","title":"Add nudge_channels to MessagingConfig schema","description":"Extend MessagingConfig in internal/config/types.go.\n\nADD TO MessagingConfig STRUCT:\n // NudgeChannels are named groups for real-time nudge fan-out.\n // Like mailing lists but for tmux send-keys instead of durable mail.\n NudgeChannels map[string][]string `json:\"nudge_channels,omitempty\"`\n\nUPDATE NewMessagingConfig():\n Add: NudgeChannels: make(map[string][]string)\n\nUPDATE ValidateMessagingConfig() in loader.go:\n Validate that nudge channel names are non-empty\n Validate that each channel has at least one recipient\n\nFILE: internal/config/types.go, internal/config/loader.go\nTESTS: Add to loader_test.go following existing patterns\n\nExample config:\n{\n \"nudge_channels\": {\n \"workers\": [\"gastown/polecats/*\", \"gastown/crew/*\"],\n \"witnesses\": [\"*/witness\"]\n }\n}","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-30T18:16:49.198572-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T22:47:22.156961-08:00","closed_at":"2025-12-30T22:47:22.156961-08:00","close_reason":"Added NudgeChannels field to MessagingConfig with validation and tests"} -{"id":"gt-3sofk","title":"Merge: gt-bpiph","description":"branch: polecat/toast-mjtm1hg8\ntarget: main\nsource_issue: gt-bpiph\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-30T22:09:46.03699-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T23:12:30.83564-08:00","closed_at":"2025-12-30T23:12:30.83564-08:00","close_reason":"Branch already merged"} -{"id":"gt-3spj6","title":"Merge: slit-mjtj9dc8","description":"branch: polecat/slit-mjtj9dc8\ntarget: main\nsource_issue: slit-mjtj9dc8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:13:56.572746-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-31T02:00:37.349262-08:00","closed_at":"2025-12-31T02:00:37.349262-08:00","close_reason":"Branch no longer exists on remote"} -{"id":"gt-3srrd","title":"Session ended: gt-gastown-bullet","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:39:09.056858-08:00","created_by":"gastown/polecats/bullet","updated_at":"2026-01-04T16:40:22.888973-08:00","closed_at":"2026-01-04T16:40:22.888973-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/bullet","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:39:09-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-bullet\",\"worker\":\"bullet\"}"} -{"id":"gt-3tbsl","title":"Digest: mol-deacon-patrol","description":"Patrol 8: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:32:39.209162-08:00","updated_at":"2026-01-01T20:32:39.209162-08:00","closed_at":"2026-01-01T20:32:39.209129-08:00"} -{"id":"gt-3txyh","title":"Add nudge channels for real-time fan-out messaging","description":"Add channel support to gt nudge for real-time fan-out.\n\n## Semantics\n- Ephemeral, real-time (tmux send-keys)\n- Fan-out to all channel members\n- Parallel to list:name but for nudge instead of mail\n\n## Use Case\n\"Everyone send yourself gt handoff now\" - real-time coordination.\n\n## Syntax\ngt nudge channel:workers \"gt handoff\"\ngt nudge channel:witnesses \"Swarm incoming\"\n\n## Implementation\n1. Add nudge_channels to MessagingConfig schema\n2. Extend gt nudge to recognize channel:name syntax\n3. Expand channel to member list, nudge each\n\n## Config Addition to messaging.json\n```json\n\"nudge_channels\": {\n \"workers\": [\"gastown/polecats/*\", \"gastown/crew/*\"],\n \"witnesses\": [\"*/witness\"],\n \"all\": [\"@town\", \"@rig/*\"]\n}\n```\n\n## Relation to gt broadcast\ngt broadcast is a one-off \"everyone\" nudge.\nNudge channels are named, configured subsets.\n\nCould potentially deprecate gt broadcast in favor of:\ngt nudge channel:all \"message\"","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-30T18:09:31.934896-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T18:09:31.934896-08:00","dependencies":[{"issue_id":"gt-3txyh","depends_on_id":"gt-p2o6s","type":"blocks","created_at":"2025-12-30T18:16:57.094642-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-3u18o","title":"Session ended: gt-gastown-imperator","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:48:27.401975-08:00","created_by":"gastown/polecats/imperator","updated_at":"2026-01-04T16:41:37.841247-08:00","closed_at":"2026-01-04T16:41:37.841247-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/polecats/imperator","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:48:27-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-imperator\",\"worker\":\"imperator\"}"} -{"id":"gt-3ue68","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all healthy, beads swarm active","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:50:54.637503-08:00","updated_at":"2025-12-28T15:50:54.637503-08:00","closed_at":"2025-12-28T15:50:54.637463-08:00"} -{"id":"gt-3veqk","title":"Digest: mol-deacon-patrol","description":"Patrol complete: 17 Claude procs, 3 witnesses, 2 refineries healthy. 2 convoys open. No orphans, no cleanup needed. Inbox empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:27:31.362234-08:00","updated_at":"2025-12-31T22:27:31.362234-08:00","closed_at":"2025-12-31T22:27:31.362204-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3vqw3","title":"Merge: slit-1767080431456","description":"branch: polecat/slit-1767080431456\ntarget: main\nsource_issue: slit-1767080431456\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:49:04.263034-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-29T23:55:11.801127-08:00","closed_at":"2025-12-29T23:55:11.801127-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-3w685","title":"Wisp config storage layer","description":"dispatched_by: mayor\n\nImplement wisp-based config storage for transient/local settings.\n\nStorage: .beads-wisp/config/\u003crig\u003e.json\nFormat:\n{\n \"rig\": \"gastown\",\n \"values\": { \"status\": \"parked\", ... },\n \"blocked\": [\"auto_restart\", ...]\n}\n\nAPI:\n- wispConfig.Get(key) - returns value or nil\n- wispConfig.Set(key, value)\n- wispConfig.Block(key) - NullValue equivalent\n- wispConfig.Unset(key)\n- wispConfig.IsBlocked(key)\n\nNever synced via git - local to this town only.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-06T17:36:42.567842-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T18:45:27.325406-08:00","closed_at":"2026-01-06T18:45:27.325406-08:00","close_reason":"Implemented wisp config storage layer with Get, Set, Block, Unset, IsBlocked API"} -{"id":"gt-3x0rd","title":"Remove vestigial state.json files from agent directories","description":"Agent directories (witness/, refinery/, etc.) contain state.json files with last_active timestamps that are never updated. These are stale/vestigial and misleading.\n\nExample: ~/gt/gastown/witness/state.json shows last_active Dec 19th while witness has been running daily.\n\nTask:\n1. Remove state.json files from agent directories\n2. Remove any code that creates/reads these files\n3. Verify no dependencies on this state","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/splendid","created_at":"2026-01-03T21:04:11.446479-08:00","created_by":"mayor","updated_at":"2026-01-03T21:20:18.249068-08:00","closed_at":"2026-01-03T21:20:18.249068-08:00","close_reason":"Removed vestigial state.json files from agent directories and related dead code"} -{"id":"gt-3x0z.10","title":"Phase 4.2: Witness/Refinery patrol molecules","description":"Extend ephemeral patrol pattern to Witness and Refinery.\n\n## Witness Patrol Cycle\n\nmol-witness-patrol-cycle:\n1. scan-polecats: Check each polecat status\n2. detect-stalls: Find stuck/idle polecats\n3. nudge-or-escalate: Take action on stalls\n4. log-status: Record cycle results\n→ Squash with summary\n\n## Refinery Patrol Cycle\n\nmol-refinery-patrol-cycle:\n1. scan-queue: Check merge queue\n2. process-ready: Merge ready MRs\n3. handle-failures: Deal with conflicts/failures\n4. log-status: Record cycle results\n→ Squash with summary\n\n## Quiescent Mode\n\nWhen no work: just log 'no activity' summary.\nWitness and Refinery can sleep between cycles until triggered.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T14:34:13.103951-08:00","updated_at":"2025-12-28T22:36:25.659744-08:00","closed_at":"2025-12-28T22:36:25.659744-08:00","dependencies":[{"issue_id":"gt-3x0z.10","depends_on_id":"gt-3x0z","type":"parent-child","created_at":"2025-12-21T14:34:13.104305-08:00","created_by":"daemon"},{"issue_id":"gt-3x0z.10","depends_on_id":"gt-3x0z.9","type":"blocks","created_at":"2025-12-21T14:34:40.742967-08:00","created_by":"daemon"}]} -{"id":"gt-3x0z.12","title":"Phase 5.2: Ephemeral error handling and recovery","description":"Handle edge cases in ephemeral molecule lifecycle.\n\n## Scenarios\n\n### Agent dies mid-molecule\n- Ephemeral state persists\n- Witness detects stall (no heartbeat)\n- Options:\n a. Nudge agent to resume\n b. Reassign to new agent\n c. Escalate to Mayor\n\n### Squash fails\n- Retry with exponential backoff\n- If persistent failure, escalate\n- Don't lose the ephemeral state until squash succeeds\n\n### Orphaned molecules\n- Molecule started, never completed\n- gt doctor detects (\u003e24h old with no activity)\n- Options:\n a. Manual review\n b. Auto-abandon with 'abandoned' digest\n c. Reassign\n\n### Ephemeral repo corruption\n- Re-init from scratch\n- Active molecules are lost\n- Main beads is source of truth for assigned work\n\n## Implementation\n\nAdd error handling to:\n- bd mol bond (handle init failures)\n- bd squash (retry logic)\n- gt doctor (recovery suggestions)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T14:34:30.158784-08:00","updated_at":"2025-12-28T22:36:25.641985-08:00","closed_at":"2025-12-28T22:36:25.641985-08:00","dependencies":[{"issue_id":"gt-3x0z.12","depends_on_id":"gt-3x0z","type":"parent-child","created_at":"2025-12-21T14:34:30.15923-08:00","created_by":"daemon"},{"issue_id":"gt-3x0z.12","depends_on_id":"gt-3x0z.9","type":"blocks","created_at":"2025-12-21T14:34:40.886432-08:00","created_by":"daemon"}]} -{"id":"gt-3yj","title":"Agent monitoring and status inference","description":"Agent monitoring with status inference from activity, like PGT.\n\n## Agent Status Enum\n```go\ntype AgentStatus string\nconst (\n StatusAvailable AgentStatus = \"available\"\n StatusWorking AgentStatus = \"working\"\n StatusThinking AgentStatus = \"thinking\"\n StatusBlocked AgentStatus = \"blocked\"\n StatusWaiting AgentStatus = \"waiting\"\n StatusReviewing AgentStatus = \"reviewing\"\n StatusIdle AgentStatus = \"idle\"\n StatusPaused AgentStatus = \"paused\"\n StatusError AgentStatus = \"error\"\n StatusOffline AgentStatus = \"offline\"\n)\n```\n\n## Status Sources (priority order)\n```go\ntype StatusSource string\nconst (\n SourceBossOverride StatusSource = \"boss\" // Witness/Mayor sets\n SourceSelfReported StatusSource = \"self\" // Agent reports own status\n SourceInferred StatusSource = \"inferred\" // Detected from activity\n)\n```\n\n## Activity Detection\n\n### Pattern Registry\n```go\nvar activityPatterns = []struct {\n Pattern string\n Status AgentStatus\n}{\n {\"Thinking...\", StatusThinking},\n {\"BLOCKED:\", StatusBlocked},\n {\"Error:\", StatusError},\n // etc\n}\n```\n\n### Idle Detection\nNo pane output for N seconds → StatusIdle\n\n### Resource Monitoring (optional)\nCPU/memory via os.Process\n\n## New Package\ninternal/monitoring/\n├── types.go # AgentStatus, StatusReport\n├── detector.go # PatternRegistry, detect from output\n├── tracker.go # Per-agent status tracking\n└── idle.go # Idle timeout detection\n\n## Integration\n- Session capture output → monitoring detector\n- Status shown in gt status, gt session list\n\n## PGT Reference\ngastown-py/src/gastown/monitoring/\n\n## Acceptance Criteria\n- [ ] Status enum with 10 states\n- [ ] Pattern-based detection from pane output\n- [ ] Idle detection with configurable timeout\n- [ ] Status visible in CLI output","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:36.336279-08:00","updated_at":"2025-12-16T16:05:25.400551-08:00"} -{"id":"gt-3ys3h","title":"Digest: mol-deacon-patrol","description":"Patrol 57: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:24:32.756071-08:00","updated_at":"2026-01-01T02:24:32.756071-08:00","closed_at":"2026-01-01T02:24:32.75603-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3z69z","title":"Digest: mol-deacon-patrol","description":"Patrol 146: All healthy, new furiosa spawn","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:57:34.932687-08:00","updated_at":"2026-01-01T14:57:34.932687-08:00","closed_at":"2026-01-01T14:57:34.932642-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-3zgr7","title":"Digest: mol-deacon-patrol","description":"Patrol 6: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:29:23.380577-08:00","updated_at":"2026-01-01T20:29:23.380577-08:00","closed_at":"2026-01-01T20:29:23.380541-08:00"} -{"id":"gt-3zkjw","title":"Add pre-flight test check to mol-polecat-work","description":"Add a step early in mol-polecat-work (after branch-setup, before implement) to check if tests pass on main.\n\n## Problem\nIf main is broken when polecat starts, they could:\n- Waste context trying to fix unrelated issues\n- Not know if their changes broke things or it was pre-existing\n- Get blamed for failures they didn't cause\n\n## Proposed Step: preflight-tests\n\nAfter branch-setup, before implement:\n\n1. Checkout main temporarily\n2. Run test suite\n3. If tests PASS: Continue to implement\n4. If tests FAIL:\n - Quick fix (\u003c15 min): Fix it, commit to main, then continue\n - Big fix: File bead, mail Witness, proceed with own work\n - Use ZFC judgment - you're there, you decide\n\n## Handoff Consideration\nIf fixing pre-existing failures consumes significant context:\n- Commit the fix\n- gt handoff with note: 'Fixed pre-existing test failures, continuing with assigned work'\n- Fresh session picks up from implement step\n\n## Key Principle\nScotty Test: Don't walk past a broken warp core. But also don't let someone else's mess derail your mission entirely.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T12:48:15.325179-08:00","created_by":"mayor","updated_at":"2025-12-28T12:49:22.164656-08:00","closed_at":"2025-12-28T12:49:22.164656-08:00"} -{"id":"gt-3zsml","title":"SessionStart hook should pass session_id to gt prime","description":"## Context\n\nThe seance discovery system relies on session_start events emitted by gt prime.\nCurrently, gt prime falls back to actor-PID when CLAUDE_SESSION_ID is not set.\n\n## Enhancement\n\nThe SessionStart hook receives session_id in its stdin JSON:\n```json\n{\n \"session_id\": \"abc123\",\n \"transcript_path\": \"...\",\n \"source\": \"startup|resume|clear|compact\"\n}\n```\n\nThe hook should parse this and pass it to gt prime via environment variable:\n```bash\nSESSION_ID=$(cat /dev/stdin | jq -r \".session_id\")\nCLAUDE_SESSION_ID=$SESSION_ID gt prime\n```\n\n## Benefits\n\n- Accurate session tracking for seances\n- Can resume exact sessions via `claude --resume \u003cid\u003e`\n- Events correlate with Claude Code session history\n\n## Implementation\n\n1. Update SessionStart hook in CLAUDE.md templates\n2. Have gt prime read CLAUDE_SESSION_ID env var (already done)\n3. Emit proper session_id in session_start events\n\nRelated: gt-7qvd7 (seance implementation)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/joe","created_at":"2025-12-31T12:18:55.519385-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:25:34.895614-08:00","closed_at":"2025-12-31T12:25:34.895614-08:00","close_reason":"Created ~/.claude/hooks/session-start.sh to parse session_id from stdin JSON and pass it to gt prime via CLAUDE_SESSION_ID. Updated SessionStart hooks in all settings.json files across town."} -{"id":"gt-3zwja","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:09:04.72122-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.701005-08:00","closed_at":"2026-01-05T00:08:31.701005-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:09:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-407oy","title":"Digest: mol-deacon-patrol","description":"Patrol 255 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:23:29.117819-08:00","updated_at":"2026-01-01T17:23:29.117819-08:00","closed_at":"2026-01-01T17:23:29.117779-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-412a9","title":"gt polecat status shows idle when hook_bead is set in agent bead","description":"gt polecat status gastown/furiosa shows State: idle, Issue: (none) but the agent bead gt-gastown-polecat-furiosa has hook_bead: gt-um6q and agent_state: running. The status command isn't reading hook_bead from the agent bead correctly.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T00:11:28.049978-08:00","created_by":"mayor","updated_at":"2025-12-30T00:17:27.488239-08:00","closed_at":"2025-12-30T00:17:27.488239-08:00","close_reason":"Fixed in commit 275f3026: loadFromBeads now checks agent bead hook_bead field"} -{"id":"gt-41m3x","title":"Add -m flag to gt nudge command","description":"Currently gt nudge requires positional args: gt nudge \u003ctarget\u003e \u003cmessage\u003e\n\nAdd -m flag support for consistency with other commands:\n gt nudge beads/crew/emma -m \"Please do a handoff\"\n\nThe message should still work as positional arg for backwards compatibility.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T17:55:44.019048-08:00","created_by":"beads/crew/dave","updated_at":"2025-12-30T20:51:31.281955-08:00","closed_at":"2025-12-30T20:51:31.281955-08:00","close_reason":"Closed"} -{"id":"gt-42whv","title":"Merge: cheedo-mjxpd9go","description":"branch: polecat/cheedo-mjxpd9go\ntarget: main\nsource_issue: cheedo-mjxpd9go\nrig: gastown\nagent_bead: gt-gastown-polecat-cheedo","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:50:33.469414-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2026-01-02T18:53:36.842822-08:00","closed_at":"2026-01-02T18:53:36.842822-08:00","close_reason":"Merged to main at dd870bb3"} -{"id":"gt-42xs6","title":"Digest: mol-deacon-patrol","description":"Patrol 12","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:11:10.298748-08:00","updated_at":"2026-01-01T09:11:10.298748-08:00","closed_at":"2026-01-01T09:11:10.298716-08:00"} -{"id":"gt-43fwj","title":"Digest: mol-deacon-patrol","description":"Patrol 249 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:20:54.650891-08:00","updated_at":"2026-01-01T17:20:54.650891-08:00","closed_at":"2026-01-01T17:20:54.650851-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-43jno","title":"Digest: mol-deacon-patrol","description":"Patrol 7: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:47:26.811125-08:00","updated_at":"2026-01-01T22:47:26.811125-08:00","closed_at":"2026-01-01T22:47:26.81109-08:00"} -{"id":"gt-441j6","title":"Polecat session checkpoint for crash recovery","description":"When polecat session dies, all context is lost.\n\n## Problem\n- Session dies (context limit, crash, timeout)\n- No record of what files were modified\n- No checkpoint of molecule step progress\n- Next session has to rediscover state\n\n## Fix\nPeriodic checkpoint during work:\n1. Every N minutes, or on molecule step completion\n2. Write checkpoint file: `.polecat-checkpoint.json`\n - Current molecule step\n - Modified files list\n - Last commit SHA\n - Timestamp\n3. On session restart, read checkpoint\n4. Resume from checkpoint state\n\n## Checkpoint Format\n```json\n{\n \"molecule_id\": \"mol-xxx\",\n \"current_step\": \"gt-abc.2\",\n \"modified_files\": [\"internal/foo/bar.go\"],\n \"last_commit\": \"abc123\",\n \"timestamp\": \"2025-12-30T18:00:00Z\"\n}\n```","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T19:08:00.891582-08:00","created_by":"mayor","updated_at":"2026-01-01T18:45:36.525161-08:00","closed_at":"2026-01-01T18:45:36.525161-08:00","close_reason":"Implemented checkpoint system for crash recovery. Added internal/checkpoint package and gt checkpoint command (write/read/clear). Checkpoint context is shown during gt prime startup."} -{"id":"gt-44sfg","title":"Digest: mol-deacon-patrol","description":"Patrol 30: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:58:39.87169-08:00","updated_at":"2025-12-31T13:58:39.87169-08:00","closed_at":"2025-12-31T13:58:39.871655-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-462is","title":"Digest: mol-deacon-patrol","description":"Patrol 11: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T16:08:57.775267-08:00","updated_at":"2025-12-25T16:08:57.775267-08:00","closed_at":"2025-12-25T16:08:57.775236-08:00"} -{"id":"gt-47b9x","title":"Digest: mol-deacon-patrol","description":"Patrol 121: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:26:22.701772-08:00","updated_at":"2026-01-01T14:26:22.701772-08:00","closed_at":"2026-01-01T14:26:22.70174-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-499mz","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:31:48.76821-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.627595-08:00","closed_at":"2026-01-05T00:08:31.627595-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:31:48-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-49wor","title":"Session ended: gt-gastown-bullet-farmer","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:13:27.742962-08:00","created_by":"gastown/polecats/bullet-farmer","updated_at":"2026-01-05T19:44:41.917158-08:00","closed_at":"2026-01-05T19:44:41.917158-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/bullet","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:13:27-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-bullet-farmer\",\"worker\":\"bullet\"}"} -{"id":"gt-4a2qt","title":"Pillar 3: Polecat Lifecycle","description":"Session-per-step model with automated recycle/nuke.\n\nKey deliverables:\n- gt polecat recycle \u003cname\u003e - kill session, preserve sandbox\n- gt polecat nuke \u003cname\u003e - kill everything\n- Witness calls recycle between molecule steps\n- Refinery calls nuke after merge\n\nSubsumes existing work:\n- gt-budeb: Witness auto-nuke polecats after merge\n- gt-1dbcp: Polecat auto-start nudge fix\n\nReference: ~/gt/docs/liftoff-plan.md\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T20:56:06.295187-08:00","created_by":"mayor","updated_at":"2025-12-28T16:12:20.010401-08:00","closed_at":"2025-12-28T16:12:20.010401-08:00","dependencies":[{"issue_id":"gt-4a2qt","depends_on_id":"gt-hwka3","type":"blocks","created_at":"2025-12-27T20:56:23.807213-08:00","created_by":"daemon"}]} -{"id":"gt-4a89n","title":"Digest: mol-deacon-patrol","description":"Patrol 40: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:02:29.833271-08:00","updated_at":"2025-12-31T14:02:29.833271-08:00","closed_at":"2025-12-31T14:02:29.833236-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4a9y4","title":"Merge: slit-1767138831931","description":"branch: polecat/slit-1767138831931\ntarget: main\nsource_issue: slit-1767138831931\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:15:39.344911-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T16:25:01.32742-08:00","closed_at":"2025-12-30T16:25:01.32742-08:00","close_reason":"Branch merged to main"} -{"id":"gt-4awn9","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:06:23.89392-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.730471-08:00","closed_at":"2026-01-05T00:08:31.730471-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:06:23-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-4b80k","title":"Digest: mol-deacon-patrol","description":"P18: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:14:54.386241-08:00","updated_at":"2025-12-25T20:14:54.386241-08:00","closed_at":"2025-12-25T20:14:54.386191-08:00"} -{"id":"gt-4bi8o","title":"Merge: toast-mjxpchjl","description":"branch: polecat/toast-mjxpchjl\ntarget: main\nsource_issue: toast-mjxpchjl\nrig: gastown\nagent_bead: gt-gastown-polecat-toast","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:57:11.304676-08:00","created_by":"gastown/polecats/toast","updated_at":"2026-01-03T11:52:17.967561-08:00","closed_at":"2026-01-03T11:52:17.967561-08:00","close_reason":"Merged"} -{"id":"gt-4bz0c","title":"Digest: mol-deacon-patrol","description":"Patrol complete: checked inbox (0 msgs), health check passed (all rigs healthy), cleaned 3 stale locks","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:39:49.232524-08:00","updated_at":"2025-12-28T19:39:49.232524-08:00","closed_at":"2025-12-28T19:39:49.232484-08:00"} -{"id":"gt-4cgnp","title":"Digest: mol-deacon-patrol","description":"Patrol 151: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:02:20.80149-08:00","updated_at":"2026-01-01T15:02:20.80149-08:00","closed_at":"2026-01-01T15:02:20.801446-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4cqwz","title":"Digest: mol-deacon-patrol","description":"Patrol #1: All witnesses/refineries running (beads, gastown, wyvern). 1 dog idle. No convoys, no gates, no pending spawns. Clean cycle.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:15:52.67448-08:00","updated_at":"2025-12-31T19:15:52.67448-08:00","closed_at":"2025-12-31T19:15:52.674443-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4d98p","title":"Improve looksLikeFormulaName heuristic in mol_bond","description":"The looksLikeFormulaName() function in mol_bond.go uses simple heuristics that could have edge cases:\n\nCurrent checks:\n- starts with 'mol-'\n- contains '.formula'\n- contains path separators\n\nPotential improvements:\n- Check if operand matches issue ID format (prefix-hash pattern)\n- Consider formula search paths when determining if something could be a formula\n- Add --formula flag to explicitly mark an operand as a formula name\n\nLow priority since edge cases are rare in practice.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-25T16:50:56.748428-08:00","updated_at":"2025-12-25T16:50:56.748428-08:00","dependencies":[{"issue_id":"gt-4d98p","depends_on_id":"gt-8tmz.25","type":"discovered-from","created_at":"2025-12-25T16:50:56.749737-08:00","created_by":"daemon"}]} -{"id":"gt-4e2bs","title":"Digest: mol-deacon-patrol","description":"Patrol 19: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:39:43.579212-08:00","updated_at":"2025-12-31T21:39:43.579212-08:00","closed_at":"2025-12-31T21:39:43.579178-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4e3j8","title":"Session ended: gt-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:50:32.562858-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:41:26.046807-08:00","closed_at":"2026-01-04T16:41:26.046807-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:50:32-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-refinery\",\"worker\":\"refinery\"}"} -{"id":"gt-4ebqj","title":"Digest: mol-deacon-patrol","description":"Patrol 11: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:27:36.140334-08:00","updated_at":"2025-12-25T07:27:36.140334-08:00","closed_at":"2025-12-25T07:27:36.140305-08:00"} -{"id":"gt-4fjan","title":"Session ended: gt-gastown-corpus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:26:02.742599-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-04T16:40:13.503785-08:00","closed_at":"2026-01-04T16:40:13.503785-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/corpus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:26:02-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-corpus\",\"worker\":\"corpus\"}"} -{"id":"gt-4gf8m","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T12:37:48.212823-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T12:37:48.262604-08:00","closed_at":"2026-01-06T12:37:48.262604-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T12:37:48-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-4h1h7","title":"Digest: mol-deacon-patrol","description":"Cycle 19","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:56:49.813173-08:00","updated_at":"2025-12-31T23:56:49.813173-08:00","closed_at":"2025-12-31T23:56:49.813137-08:00","dependencies":[{"issue_id":"gt-4h1h7","depends_on_id":"gt-eph-be69","type":"parent-child","created_at":"2025-12-31T23:56:49.814344-08:00","created_by":"deacon"}]} -{"id":"gt-4h8ak","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:04:03.584507-08:00","updated_at":"2026-01-01T20:04:03.584507-08:00","closed_at":"2026-01-01T20:04:03.584473-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-4i10r","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:00:34.610632-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-06T13:00:34.662105-08:00","closed_at":"2026-01-06T13:00:34.662105-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:00:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-4iflk","title":"Review PR #149: fix(sling) cross-rig beads routing","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-05T21:39:19.29586-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:39:19.29586-08:00"} -{"id":"gt-4iqeq","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:33:57.408434-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-05T00:08:31.951787-08:00","closed_at":"2026-01-05T00:08:31.951787-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:33:57-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-4j3ji","title":"Digest: mol-deacon-patrol","description":"Patrol 20","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:37:00.535398-08:00","updated_at":"2025-12-31T22:37:00.535398-08:00","closed_at":"2025-12-31T22:37:00.535361-08:00"} -{"id":"gt-4j4sa","title":"Digest: mol-deacon-patrol","description":"Cycle 301: All healthy, refinery queue 8","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:48:17.293937-08:00","updated_at":"2026-01-01T18:48:17.293937-08:00","closed_at":"2026-01-01T18:48:17.293882-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-4j4sa","depends_on_id":"gt-eph-rrvu","type":"parent-child","created_at":"2026-01-01T18:48:17.295199-08:00","created_by":"deacon"}]} -{"id":"gt-4jdrd","title":"Digest: mol-deacon-patrol","description":"Patrol 7: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:29:06.932355-08:00","updated_at":"2025-12-31T20:29:06.932355-08:00","closed_at":"2025-12-31T20:29:06.932322-08:00"} -{"id":"gt-4k47w","title":"Merge: furiosa-mjtnoooj","description":"branch: polecat/furiosa-mjtnoooj\ntarget: main\nsource_issue: furiosa-mjtnoooj\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:53:49.009213-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T23:12:31.00444-08:00","closed_at":"2025-12-30T23:12:31.00444-08:00","close_reason":"Branch already merged"} -{"id":"gt-4kivc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:53:41.261613-08:00","updated_at":"2026-01-01T00:53:41.261613-08:00","closed_at":"2026-01-01T00:53:41.261574-08:00"} -{"id":"gt-4kk8r","title":"Review PR #183: rig agent beads prefix","description":"dispatched_by: gastown/crew/joe","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2026-01-05T19:11:17.626308-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:15:00.093338-08:00","closed_at":"2026-01-05T19:15:00.093338-08:00","close_reason":"Reviewed PR #183 - requested changes due to incomplete fix (creation fixed but lookups still use hardcoded gt- prefix)"} -{"id":"gt-4kvd0","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:49:05.303765-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:40:22.965321-08:00","closed_at":"2026-01-04T16:40:22.965321-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:49:05-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-4lbvc","title":"Merge: gt-x4ad3","description":"branch: polecat/furiosa-mjxeatgb\ntarget: main\nsource_issue: gt-x4ad3\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:45:47.695779-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T13:48:40.851518-08:00","closed_at":"2026-01-02T13:48:40.851518-08:00","close_reason":"Merged to main"} -{"id":"gt-4n8bj","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:32:52.652781-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.581411-08:00","closed_at":"2026-01-05T19:44:18.581411-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:32:52-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-4nobz","title":"Merge: capable-1767140263101","description":"branch: polecat/capable-1767140263101\ntarget: main\nsource_issue: capable-1767140263101\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:26:48.125958-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T18:23:22.162592-08:00","closed_at":"2025-12-30T18:23:22.162592-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-4ntnq","title":"Pipeline Reliability: Fix work loss in polecat→refinery flow","description":"Post-mortem from 12 swarms that produced 74 orphan commits and lost work.\n\n## Root Cause\nNo transactional boundaries between pipeline stages. Work moves polecat→witness→refinery→main with fire-and-forget handoffs.\n\n## Key Failures\n1. Polecat session death before pipeline entry (commit but no push, or push but no gt done)\n2. No push verification in gt done\n3. Cleanup wisp and MR bead are unlinked tracking mechanisms\n4. Premature nuke before merge confirmed\n5. Refinery bottleneck causing stale branches\n6. No polecat session persistence/checkpoint\n\n## Success Criteria\n- Zero work loss from session death\n- All merged work traceable end-to-end\n- Recovery path for every failure mode","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-30T19:06:52.364239-08:00","created_by":"mayor","updated_at":"2025-12-30T19:06:52.364239-08:00","dependencies":[{"issue_id":"gt-4ntnq","depends_on_id":"gt-5q6jr","type":"blocks","created_at":"2025-12-30T20:42:17.426208-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-bca67","type":"blocks","created_at":"2025-12-30T20:42:17.454289-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-cloml","type":"blocks","created_at":"2025-12-30T20:42:17.482921-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-84ery","type":"blocks","created_at":"2025-12-30T20:42:19.142282-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-svdsy","type":"blocks","created_at":"2025-12-30T20:42:19.171463-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-v7zm7","type":"blocks","created_at":"2025-12-30T20:42:19.200091-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-441j6","type":"blocks","created_at":"2025-12-30T20:42:19.228396-08:00","created_by":"mayor"},{"issue_id":"gt-4ntnq","depends_on_id":"gt-kgszr","type":"blocks","created_at":"2025-12-30T20:42:19.2562-08:00","created_by":"mayor"}]} -{"id":"gt-4o1zx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:40:33.407876-08:00","updated_at":"2025-12-31T23:40:33.407876-08:00","closed_at":"2025-12-31T23:40:33.407841-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4ofwx","title":"Digest: mol-deacon-patrol","description":"Patrol 15 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:46:39.557084-08:00","updated_at":"2025-12-31T16:46:39.557084-08:00","closed_at":"2025-12-31T16:46:39.557045-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4on58","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:13:17.545334-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.869336-08:00","closed_at":"2026-01-05T00:08:31.869336-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:13:17-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-4p2e0","title":"Digest: mol-deacon-patrol","description":"Patrol 145: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:56:36.38783-08:00","updated_at":"2026-01-01T14:56:36.38783-08:00","closed_at":"2026-01-01T14:56:36.387796-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4q7wh","title":"Merge: nux-1767141948667","description":"branch: polecat/nux-1767141948667\ntarget: main\nsource_issue: nux-1767141948667\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:51:43.00373-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T18:23:22.133548-08:00","closed_at":"2025-12-30T18:23:22.133548-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-4r1i8","title":"Digest: mol-deacon-patrol","description":"Cycle 16","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:06:58.323685-08:00","updated_at":"2026-01-01T10:06:58.323685-08:00","closed_at":"2026-01-01T10:06:58.323652-08:00"} -{"id":"gt-4r1ph","title":"Align agent/role beads with two-level architecture","description":"## Problem\n\nAgent and role beads are stored inconsistently with the documented two-level beads architecture.\n\n### Current State (Incorrect)\n\nAll agent beads use `gt-*` prefix and route to gastown rig beads:\n- `gt-mayor`, `gt-deacon` → stored in `gastown/mayor/rig/.beads/`\n- `gt-gastown-witness`, `gt-gastown-refinery` → same location\n- `gt-mayor-role`, `gt-witness-role` → same location\n\n### Design Docs Say (from PRIMING.md)\n\n```\nORGANIZATION CHAIN (town beads, ~/gt/.beads/)\n Prefix: hq-*\n Contains: Convoys, Mayor mail, strategic coordination\n\nPROJECT CHAIN (gastown, ~/gt/gastown/**/.beads/)\n Prefix: gt-*\n Contains: Implementation work, MRs, code issues\n```\n\nRole taxonomy:\n```\nTOWN LEVEL (cross-rig) RIG LEVEL (per-project)\n├── Mayor (agent) ├── Witness (patrol)\n├── Deacon (patrol) ├── Refinery (merge)\n└── Dogs (workers) └── Polecats (ephemeral workers)\n```\n\n**Town-level agents are stored at project level.** This violates the two-level architecture.\n\n## Correct Architecture\n\n| Agent Type | Scope | Bead Location | Prefix |\n|------------|-------|---------------|--------|\n| Mayor | Town | `~/gt/.beads/` | `hq-mayor` |\n| Deacon | Town | `~/gt/.beads/` | `hq-deacon` |\n| Dogs | Town | `~/gt/.beads/` | `hq-dog-\u003cname\u003e` |\n| Witness | Rig | `\u003crig\u003e/.beads/` | `\u003cprefix\u003e-\u003crig\u003e-witness` |\n| Refinery | Rig | `\u003crig\u003e/.beads/` | `\u003cprefix\u003e-\u003crig\u003e-refinery` |\n| Polecats | Rig | `\u003crig\u003e/.beads/` | `\u003cprefix\u003e-\u003crig\u003e-polecat-\u003cname\u003e` |\n\n**Role beads** are global templates → town beads with `hq-` prefix:\n- `hq-mayor-role`, `hq-deacon-role`, `hq-witness-role`, etc.\n\n## Why This Matters (HOP Context)\n\nFrom CONTEXT.md: \"Each polecat should have a chain\" for CV/reputation tracking.\n\nAgent beads are **identity beads** (CV chains), not work beads. For HOP compatibility:\n- Agent identity should be cross-project\n- Town-level agents → organization chain (town beads)\n- Rig-level agents → project chain (rig beads)\n\n## Impact\n\n- **PR #50** tries to fix prefix mismatch by changing town beads to `gt` prefix - WRONG direction\n- **PR #32** (ca487a8) added broken code trying to store agents in town beads with `gt-` prefix\n- Routes already support `hq-` → town beads, no routing changes needed\n\n## Implementation Plan\n\nSee child issues for phased implementation.","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-03T18:42:07.269358-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T21:20:04.893719-08:00","closed_at":"2026-01-03T21:20:04.893719-08:00","close_reason":"All 5 phases merged to main"} -{"id":"gt-4rd2w","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:23:16.054263-08:00","updated_at":"2026-01-01T07:23:16.054263-08:00","closed_at":"2026-01-01T07:23:16.054229-08:00"} -{"id":"gt-4rgsf","title":"Merge: furiosa-1767075024945","description":"branch: polecat/furiosa-1767075024945\ntarget: main\nsource_issue: furiosa-1767075024945\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:13:52.986187-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-29T23:32:37.218051-08:00","closed_at":"2025-12-29T23:32:37.218051-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-4s10q","title":"Digest: mol-deacon-patrol","description":"Patrol 20: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:39:55.002492-08:00","updated_at":"2025-12-31T21:39:55.002492-08:00","closed_at":"2025-12-31T21:39:55.002451-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-4s6us","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:53:34.025957-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T16:41:37.860603-08:00","closed_at":"2026-01-04T16:41:37.860603-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:53:33-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-4s6vp","title":"Digest: mol-deacon-patrol","description":"Cycle 11","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:55:01.118396-08:00","updated_at":"2025-12-31T23:55:01.118396-08:00","closed_at":"2025-12-31T23:55:01.11836-08:00"} -{"id":"gt-4u49x","title":"Serialized conflict resolution via merge-slot gate","description":"## Problem: Monkey Knife Fight\n\nMultiple conflict-resolution polecats racing to land creates cascading conflicts:\n- Polecat A rebases on main@v1, resolving...\n- Polecat B rebases on main@v1, resolving... \n- Polecat A pushes → main@v2\n- Polecat B pushes → CONFLICT (main moved) → needs re-resolve\n\nThis wastes cycles and creates thrashing.\n\n## Solution: Merge-Slot Gate\n\nA single merge slot per rig, implemented via gates:\n\n```\n┌─────────────────────────────────────────────────────┐\n│ MERGE SLOT (gt-merge-slot) │\n│ Only one holder at a time │\n└─────────────────────────────────────────────────────┘\n │\n ┌───────────────┼───────────────┐\n ▼ ▼ ▼\n [High-prio MR] [Med-prio MR] [Low-prio MR]\n acquires slot waits on gate waits on gate\n```\n\n## Design\n\n### Merge Slot Bead\nEach rig has a persistent slot bead: `gt-merge-slot` (type=slot)\n- Status: open (slot available) or in_progress (slot held)\n- Holder field: which polecat/MR currently holds it\n\n### Acquiring the Slot\n1. Conflict polecat checks `bd show gt-merge-slot`\n2. If status=open:\n - `bd update gt-merge-slot --status=in_progress --holder=\u003cmr-id\u003e`\n - Proceed with conflict resolution\n3. If status=in_progress:\n - Create bead-gate waiting for slot to become open\n - Block until gate closes\n\n### Priority Ordering\nConvoy graph provides priority:\n- Convoy age (older = higher priority)\n- Epic priority (P0 \u003e P4)\n- Retry count (high retries = penalty)\n\nWitness dispatches conflict resolution in priority order.\nOnly highest-priority waiting work acquires slot when released.\n\n### Releasing the Slot\nAfter merge to main:\n1. `bd update gt-merge-slot --status=open --holder=\"\"`\n2. All waiting gates check slot\n3. Highest-priority waiter acquires\n\n### Direct-to-Main Flow\nConflict polecat with slot:\n1. Rebase on main, resolve conflicts\n2. Run tests\n3. Push directly to main (not back to MR queue)\n4. Close original MR bead\n5. Release merge slot\n\n## Benefits\n- No monkey knife fight (serialized)\n- Priority respected (convoy back-pressure)\n- No queue re-entry (direct to main)\n- Uses existing gates infrastructure\n\n## Implementation Tasks\n1. Create merge-slot bead type\n2. Slot acquire/release in gt done\n3. Witness priority-ordered dispatch\n4. Gate-based waiting for slot\n\n## Related\n- gt-si8rq.5: Conflict resolution workflow (update to use slot)\n- gt-si8rq.6: Priority-ordered MQ (provides priority info)\n- bd-quw1: Phase handoff (gate infrastructure)","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T17:36:36.979788-08:00","created_by":"mayor","updated_at":"2026-01-02T18:03:53.331386-08:00","closed_at":"2026-01-02T18:03:53.331386-08:00","close_reason":"Implemented merge-slot gate for serialized conflict resolution","dependencies":[{"issue_id":"gt-4u49x","depends_on_id":"gt-si8rq.6","type":"blocks","created_at":"2026-01-02T17:37:19.965238-08:00","created_by":"mayor"},{"issue_id":"gt-4u49x","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-02T17:37:39.693028-08:00","created_by":"mayor"}]} -{"id":"gt-4u682","title":"Extract SupportedShells constant to constants package","description":"Extract repeated shell list to a single constant.\n\n## Files to modify\n- internal/constants/constants.go (add constant)\n- internal/cmd/start.go (use constant at lines 729, 773, 907)\n- internal/cmd/crew_helpers.go (use constant)\n\n## Implementation\nAdd to constants.go:\n```go\nvar SupportedShells = []string{\"bash\", \"zsh\", \"sh\", \"fish\", \"tcsh\", \"ksh\"}\n```\n\nReplace all inline []string{\"bash\", \"zsh\"...} with constants.SupportedShells.\n\n## Acceptance criteria\n- [ ] SupportedShells added to internal/constants/constants.go\n- [ ] All 4 occurrences in start.go and crew_helpers.go replaced\n- [ ] grep -r '\"bash\", \"zsh\"' returns no matches in internal/cmd/\n- [ ] go build ./... passes\n- [ ] go test ./... passes","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:11.28252-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:40:32.237174-08:00","closed_at":"2025-12-28T16:40:32.237174-08:00"} -{"id":"gt-4uul5","title":"Merge: nux-1767059693217","description":"branch: polecat/nux-1767059693217\ntarget: main\nsource_issue: nux-1767059693217\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T18:02:24.398185-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T21:45:58.34857-08:00","closed_at":"2025-12-29T21:45:58.34857-08:00","close_reason":"Stale merge requests - branches no longer exist"} -{"id":"gt-4vd2s","title":"Digest: mol-deacon-patrol","description":"Patrol 14: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T16:52:06.454837-08:00","updated_at":"2025-12-26T16:52:06.454837-08:00","closed_at":"2025-12-26T16:52:06.454802-08:00"} -{"id":"gt-4vfsq","title":"Session ended: gt-gastown/crew/jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:22:06.268575-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.069603-08:00","closed_at":"2026-01-04T16:41:26.069603-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:22:06-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/jack\",\"worker\":\"gastown/crew/jack\"}"} -{"id":"gt-4wxfa","title":"Merge: furiosa-mjtny0lc","description":"branch: polecat/furiosa-mjtny0lc\ntarget: main\nsource_issue: furiosa-mjtny0lc\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T23:07:16.51031-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T23:12:30.947637-08:00","closed_at":"2025-12-30T23:12:30.947637-08:00","close_reason":"Branch already merged"} -{"id":"gt-4wyc9","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:56:27.400483-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.906926-08:00","closed_at":"2026-01-05T00:08:31.906926-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:56:27-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-4xb1v","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:53:40.271341-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:13.523712-08:00","closed_at":"2026-01-04T16:40:13.523712-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:53:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-50665","title":"Digest: mol-deacon-patrol","description":"Cycle 7","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:00:57.642218-08:00","updated_at":"2026-01-01T10:00:57.642218-08:00","closed_at":"2026-01-01T10:00:57.64218-08:00"} -{"id":"gt-516zd","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:46:43.107776-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T18:46:43.166783-08:00","closed_at":"2026-01-06T18:46:43.166783-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:46:43-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-519fu","title":"Digest: mol-deacon-patrol","description":"Patrol 7","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:50:29.743717-08:00","updated_at":"2026-01-01T08:50:29.743717-08:00","closed_at":"2026-01-01T08:50:29.743679-08:00"} -{"id":"gt-51ghh","title":"Digest: mol-deacon-patrol","description":"Patrol 19: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:21:00.943043-08:00","updated_at":"2025-12-28T08:21:00.943043-08:00","closed_at":"2025-12-28T08:21:00.94301-08:00"} -{"id":"gt-5207w","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:49:40.55585-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.52907-08:00","closed_at":"2026-01-05T19:44:18.52907-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:49:35-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-52fiv","title":"Digest: mol-deacon-patrol","description":"Patrol 17: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:11:11.081947-08:00","updated_at":"2025-12-31T18:11:11.081947-08:00","closed_at":"2025-12-31T18:11:11.081914-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5354h","title":"Add Windows-compatible file locking for daemon","description":"PR #108 added syscall.Flock() for daemon orphan prevention, but Flock is Unix-only.\n\nFor Windows support, need to implement platform-specific locking:\n- Unix: syscall.Flock (current implementation)\n- Windows: LockFileEx via golang.org/x/sys/windows or similar\n\nOptions:\n1. Build tags with platform-specific implementations\n2. Use a cross-platform library like github.com/gofrs/flock\n3. Conditional compilation with fallback behavior on Windows\n\nThe gofrs/flock library is probably the cleanest solution - it handles both platforms transparently.\n\nRelated: PR #108 (fix daemon orphan race condition)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/gastown","created_at":"2026-01-04T13:01:14.52009-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:11:03.509262-08:00","closed_at":"2026-01-05T00:11:03.509262-08:00","close_reason":"Implemented cross-platform file locking using gofrs/flock library"} -{"id":"gt-53i7z","title":"Session ended: gt-gastown-splendid","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:20:58.804533-08:00","created_by":"gastown/polecats/splendid","updated_at":"2026-01-04T16:41:25.978551-08:00","closed_at":"2026-01-04T16:41:25.978551-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/splendid","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:20:58-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-splendid\",\"worker\":\"splendid\"}"} -{"id":"gt-552hb","title":"Epic: Fix swarm orchestration - witness/refinery/polecat lifecycle","description":"## Problem Statement\n\nThe bd-9115 swarm execution required excessive manual intervention from Mayor. The witness, refinery, and polecat lifecycle components didn't coordinate automatically.\n\n## What Should Have Happened\n\n```\nMayor slings 6 beads to rig\n ↓\nPolecats auto-spawn with synced beads, work pinned\n ↓\nPolecats work autonomously\n ↓\nWitness monitors progress, nudges stuck polecats\n ↓\nPolecat completes → pushes branch → signals completion\n ↓\nRefinery detects ready branch → rebases → merges → deletes branch\n ↓\nWitness detects merge → nukes polecat worktree\n ↓\nWhen all done → Witness notifies Mayor\n```\n\n## What Actually Happened\n\n1. **gt sling failed to pin beads** - polecat worktrees had stale JSONL\n2. **Manual intervention** - had to checkout latest JSONL, pin, nudge each polecat\n3. **Witness was passive** - never nudged or checked on polecats\n4. **Refinery waited for requests** - didn't detect completed branches\n5. **Manual lifecycle** - Mayor had to close beads, nuke polecats\n6. **Manual merge coordination** - had to mail refinery with merge order\n\n## Root Cause: Branch Hysteresis\n\nPolecat branches persist across runs and drift from main/beads-sync:\n- `polecat/foo` created weeks ago from old main\n- New work slung to `polecat/foo` \n- JSONL in branch doesn't have new beads\n- Pin fails\n\n## Open Questions\n\n### Q1: Fresh branches per run?\nShould each polecat spawn create a NEW branch from latest main/beads-sync?\n```\ngt sling bd-xxx rig\n → creates polecat/foo-20251227-1630 from origin/main\n → ensures JSONL is current\n → after merge, branch deleted forever\n```\nPros: No drift, always current\nCons: Branch proliferation, naming complexity\n\n### Q2: Rebase existing branches?\nOr should we rebase persistent polecat branches before work?\n```\ngt sling bd-xxx rig/foo\n → git fetch origin\n → git rebase origin/main\n → now JSONL is current\n```\nPros: Keeps simple naming\nCons: Rebase can fail with conflicts\n\n### Q3: Just cherry-pick JSONL?\nMinimal fix - grab latest JSONL before pinning:\n```\ngit checkout origin/beads-sync -- .beads/issues.jsonl\nbd import # refresh DB\nbd pin bd-xxx\n```\nPros: Simple, surgical\nCons: Doesn't fix code drift, just beads\n\n### Q4: Shared beads DB?\nCould polecats share a DB (via symlink or sqlite over network)?\nPros: Always consistent\nCons: Locking complexity, daemon conflicts\n\n### Q5: Who owns polecat lifecycle?\n- Witness? (current assumption)\n- Refinery? (after merge)\n- gt sling? (on spawn)\n- New \"foreman\" role?\n\n## Proposed Solutions\n\nSee child issues for implementation details. Need to resolve open questions first.\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T16:40:10.727376-08:00","created_by":"mayor","updated_at":"2025-12-28T16:12:13.598411-08:00","closed_at":"2025-12-28T16:12:13.598411-08:00","dependencies":[{"issue_id":"gt-552hb","depends_on_id":"gt-ake0m","type":"blocks","created_at":"2025-12-27T16:41:15.984785-08:00","created_by":"daemon"},{"issue_id":"gt-552hb","depends_on_id":"gt-dtw9u","type":"blocks","created_at":"2025-12-27T16:41:16.036312-08:00","created_by":"daemon"},{"issue_id":"gt-552hb","depends_on_id":"gt-qpwv4","type":"blocks","created_at":"2025-12-27T16:41:16.08566-08:00","created_by":"daemon"},{"issue_id":"gt-552hb","depends_on_id":"gt-6qyt1","type":"blocks","created_at":"2025-12-27T16:41:16.134048-08:00","created_by":"daemon"},{"issue_id":"gt-552hb","depends_on_id":"gt-budeb","type":"blocks","created_at":"2025-12-27T16:41:16.182989-08:00","created_by":"daemon"},{"issue_id":"gt-552hb","depends_on_id":"gt-5j3ia","type":"blocks","created_at":"2025-12-27T16:41:16.231484-08:00","created_by":"daemon"}]} -{"id":"gt-55e0w","title":"Digest: mol-deacon-patrol","description":"Patrol 15: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:07:05.949941-08:00","updated_at":"2025-12-31T19:07:05.949941-08:00","closed_at":"2025-12-31T19:07:05.949902-08:00","dependencies":[{"issue_id":"gt-55e0w","depends_on_id":"gt-eph-9q0u","type":"parent-child","created_at":"2025-12-31T19:07:05.951067-08:00","created_by":"deacon"}]} -{"id":"gt-55kx","title":"Build activity stream component","description":"Bubbletea component showing scrollable activity stream for a selected worker. Shows mutation events with timestamps, symbols, and issue titles. Displayed when user expands/selects a worker.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:27:17.091004-08:00","updated_at":"2025-12-23T16:27:17.091004-08:00","dependencies":[{"issue_id":"gt-55kx","depends_on_id":"gt-3p77","type":"blocks","created_at":"2025-12-23T16:27:38.640018-08:00","created_by":"daemon"},{"issue_id":"gt-55kx","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:30.857389-08:00","created_by":"daemon"}]} -{"id":"gt-560ge","title":"Extract duplicated processExists function to shared package","description":"attached_args: Extract processExists function to reduce duplication\n\nExtract duplicated processExists function to shared package.\n\n## Files to modify\n- internal/util/process.go (NEW)\n- internal/witness/manager.go (remove local function, import util)\n- internal/refinery/manager.go (remove local function, import util)\n\n## Current duplication\nBoth files have identical implementations at:\n- internal/witness/manager.go (lines 136-144)\n- internal/refinery/manager.go (lines 646-654)\n\n```go\nfunc processExists(pid int) bool {\n proc, err := os.FindProcess(pid)\n if err != nil {\n return false\n }\n err = proc.Signal(nil)\n return err == nil\n}\n```\n\n## Implementation\nCreate internal/util/process.go:\n```go\npackage util\n\nimport \"os\"\n\n// ProcessExists checks if a process with the given PID exists.\nfunc ProcessExists(pid int) bool {\n proc, err := os.FindProcess(pid)\n if err != nil {\n return false\n }\n return proc.Signal(nil) == nil\n}\n```\n\n## Acceptance criteria\n- [ ] internal/util/process.go created with ProcessExists function\n- [ ] internal/util/process_test.go with basic tests\n- [ ] witness/manager.go imports util and uses util.ProcessExists\n- [ ] refinery/manager.go imports util and uses util.ProcessExists\n- [ ] Local processExists functions removed from both files\n- [ ] go build ./... passes\n- [ ] go test ./... passes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:08.119167-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:14:21.455498-08:00","closed_at":"2025-12-28T16:14:21.455498-08:00"} -{"id":"gt-56djr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 60: All healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:01:54.477333-08:00","updated_at":"2026-01-01T13:01:54.477333-08:00","closed_at":"2026-01-01T13:01:54.477295-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-56et5","title":"Digest: mol-deacon-patrol","description":"Patrol 14: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:32:21.006139-08:00","updated_at":"2025-12-25T13:32:21.006139-08:00","closed_at":"2025-12-25T13:32:21.006104-08:00"} -{"id":"gt-56l48","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:14:17.6102-08:00","updated_at":"2026-01-01T06:14:17.6102-08:00","closed_at":"2026-01-01T06:14:17.61016-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-574qn","title":"Formula execution: Spawn convoy from formula","description":"Implement gt formula run \u003cname\u003e:\n1. Load and parse formula\n2. Create convoy bead (hq-cv-xxx)\n3. For each leg, create child bead\n4. Sling each leg to separate polecat with leg-specific prompt\n5. Track leg completion via bead status\n6. When all legs done, spawn synthesis polecat\n\nUse existing gt sling and gt convoy infrastructure.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T14:42:55.836468-08:00","created_by":"mayor","updated_at":"2026-01-01T15:59:54.70045-08:00","closed_at":"2026-01-01T15:59:54.70045-08:00","close_reason":"Merged at 98d68827","dependencies":[{"issue_id":"gt-574qn","depends_on_id":"gt-gpifj","type":"blocks","created_at":"2026-01-01T14:43:09.884589-08:00","created_by":"mayor"},{"issue_id":"gt-574qn","depends_on_id":"gt-5chbk","type":"blocks","created_at":"2026-01-01T14:43:09.92739-08:00","created_by":"mayor"}]} -{"id":"gt-575cc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:04:58.538176-08:00","updated_at":"2026-01-01T20:04:58.538176-08:00","closed_at":"2026-01-01T20:04:58.538141-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-57o8f","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:43:24.71772-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T18:43:24.773089-08:00","closed_at":"2026-01-06T18:43:24.773089-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:43:24-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-5803y","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:16:01.169484-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.664321-08:00","closed_at":"2026-01-05T00:08:31.664321-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:16:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-594a4","title":"gt swarm status fails to find issues via rig discovery","description":"gt swarm status gt-1tpts fails with 'issue not found' but bd swarm status gt-1tpts works. The rig discovery in getAllRigs() may not be finding rigs correctly, or the bd commands are running from wrong directory.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2025-12-29T18:01:14.565359-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T22:05:07.444224-08:00","closed_at":"2025-12-29T22:05:07.444224-08:00","close_reason":"Fixed: Added Rig.BeadsPath() method and updated all swarm bd commands to use it. The issue was that bd commands were being run from the rig container directory which has gitignored .beads/, not from a valid git clone within the rig."} -{"id":"gt-594l2","title":"ZFC #10: Polecat reports cleanup status instead of Go checking git","description":"**ZFC Violation:** internal/polecat/manager.go:192-215\n\nGo examines git state to decide if polecat removal is safe:\n```go\nstatus, err := polecatGit.CheckUncommittedWork()\nif status.StashCount \u003e 0 || status.UnpushedCommits \u003e 0 {\n return \u0026UncommittedWorkError{...}\n}\n```\n\n**ZFC-compliant solution:**\nPolecat reports its own cleanup status via agent bead:\n- state: stopped\n- cleanup_status: clean | has_uncommitted | has_stash | has_unpushed\n- Witness reads cleanup_status before calling nuke\n- Polecat is authority on whether it's safe to remove\n\n**Relates to:** Day 4.1/4.2 (recycle/nuke commands)\n\nReference: ~/gt/docs/zfc-violations-audit.md #10","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-27T21:32:26.421521-08:00","created_by":"mayor","updated_at":"2025-12-28T16:31:36.050065-08:00","dependencies":[{"issue_id":"gt-594l2","depends_on_id":"gt-z99nh","type":"blocks","created_at":"2025-12-27T21:32:43.597966-08:00","created_by":"daemon"}]} -{"id":"gt-599nf","title":"Add GitHub issue/PR templates","description":"Add .github/ISSUE_TEMPLATE/ with bug and feature templates. Add .github/PULL_REQUEST_TEMPLATE.md. Reference beads repo for examples.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-01T11:09:48.454057-08:00","created_by":"mayor","updated_at":"2026-01-01T14:16:52.279066-08:00","closed_at":"2026-01-01T14:16:52.279066-08:00","close_reason":"Added .github/ISSUE_TEMPLATE/ with bug and feature templates, plus PULL_REQUEST_TEMPLATE.md"} -{"id":"gt-59k2x","title":"Agent beads hook_bead field never populated","description":"## Problem\n\nThe witness patrol formula expects polecat agent beads to have:\n\n hook_bead: \u003ccurrent-work-id\u003e\n\nThis field is used by the witness to see what the polecat is working on.\n\nBut looking at the code, hook_bead is never set:\n\n1. Polecat agent bead created (polecat/manager.go:167-170) - no hook_bead\n2. reportAgentState called (prime.go:1067) - passes nil for hookBead\n3. UpdateAgentState preserves existing hook_bead if nil (beads.go:633-635)\n\nSince hook_bead starts empty and is never updated, the witness cannot use\nagent beads to see what polecats are working on.\n\n## Found in commit\n\nf3a6ef6 (feat: Witness reads polecat state from agent beads)\n\n## Related to\n\n- gt-0lop3 (Agent state lifecycle incomplete for polecats)\n\n## Suggested fix\n\nWhen a polecat is assigned work (via gt sling or similar), update the agent\nbead's hook_bead field:\n\n bd.UpdateAgentState(agentID, 'running', \u0026hookBeadID)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-28T09:49:07.258556-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T09:54:41.408725-08:00","closed_at":"2025-12-28T09:54:41.408725-08:00","dependencies":[{"issue_id":"gt-59k2x","depends_on_id":"gt-0lop3","type":"blocks","created_at":"2025-12-28T09:49:17.647153-08:00","created_by":"daemon"}]} -{"id":"gt-59mqb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: Routine.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:01:54.433749-08:00","updated_at":"2026-01-01T20:01:54.433749-08:00","closed_at":"2026-01-01T20:01:54.433709-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-5aj8c","title":"Merge: nux-1767080427756","description":"branch: polecat/nux-1767080427756\ntarget: main\nsource_issue: nux-1767080427756\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:46:58.950767-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T23:55:11.817305-08:00","closed_at":"2025-12-29T23:55:11.817305-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-5bbc0","title":"Merge: bullet-mjwlbeu5","description":"branch: polecat/bullet-mjwlbeu5\ntarget: main\nsource_issue: bullet-mjwlbeu5\nrig: gastown\nagent_bead: gt-gastown-polecat-bullet","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T00:16:56.779478-08:00","created_by":"gastown/polecats/bullet","updated_at":"2026-01-02T00:24:44.948155-08:00","closed_at":"2026-01-02T00:24:44.948155-08:00","close_reason":"Merged to main at c33c4a92 - fixed duplicate tests"} -{"id":"gt-5bjgq","title":"Digest: mol-deacon-patrol","description":"Patrol 19","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:57:47.79199-08:00","updated_at":"2025-12-26T14:57:47.79199-08:00","closed_at":"2025-12-26T14:57:47.791943-08:00"} -{"id":"gt-5chbk","title":"Formula parser: Load and validate formula.toml files","description":"Create internal/formula/parser.go:\n- Parse formula.toml using BurntSushi/toml\n- Validate required fields (name, legs)\n- Resolve leg dependencies\n- Return Formula struct\n\nAdd internal/formula/types.go for Formula, Leg, Input structs.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2026-01-01T14:42:54.568361-08:00","created_by":"mayor","updated_at":"2026-01-01T15:51:01.132687-08:00","closed_at":"2026-01-01T15:51:01.132687-08:00","close_reason":"Already on main at a395b4e (formula parser)","dependencies":[{"issue_id":"gt-5chbk","depends_on_id":"gt-7lhbs","type":"blocks","created_at":"2026-01-01T14:43:09.837755-08:00","created_by":"mayor"}]} -{"id":"gt-5cql0","title":"Day 5.2: Fix integration issues","description":"Address any issues found in Day 5.1:\n- Debug failures\n- Fix edge cases\n- Retry integration test\n- Document remaining gaps\n\nThis is buffer time for reality.\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:57:58.914212-08:00","created_by":"mayor","updated_at":"2025-12-28T16:18:15.684857-08:00","closed_at":"2025-12-28T16:18:15.684857-08:00","dependencies":[{"issue_id":"gt-5cql0","depends_on_id":"gt-j0gx2","type":"blocks","created_at":"2025-12-27T20:58:31.859106-08:00","created_by":"daemon"},{"issue_id":"gt-5cql0","depends_on_id":"gt-oki8p","type":"parent-child","created_at":"2025-12-27T20:58:39.644301-08:00","created_by":"daemon"},{"issue_id":"gt-5cql0","depends_on_id":"gt-liftoff","type":"blocks","created_at":"2025-12-27T21:43:12.603927-08:00","created_by":"daemon"},{"issue_id":"gt-5cql0","depends_on_id":"gt-kfznm","type":"blocks","created_at":"2025-12-28T16:26:15.296429-08:00","created_by":"daemon"}]} -{"id":"gt-5d7eh","title":"gt hook: Shows wrong agent identity when run from different rig's crew directory","description":"## Problem\n\nRunning `gt hook` from another rig's crew directory shows the wrong agent.\n\n```bash\ncd ~/gt/beads/crew/dave\ngt hook\n# Shows: gastown/crew/joe (wrong - should be beads/crew/dave)\n```\n\n## Expected\n\n`gt hook` should detect agent identity from cwd, showing the hook for the\nagent whose directory you're in.\n\n## Related\n\n- gt-yud21: gt peek cross-rig crew path support\n- gt-hldpv: gt sling \".\" resolution\n\n## Root cause\n\nLikely the agent identity detection in hook.go doesn't handle cross-rig\ncrew paths correctly.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2025-12-31T12:58:44.695242-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T13:07:58.097136-08:00","closed_at":"2025-12-31T13:07:58.097136-08:00","close_reason":"Fixed: gt hook now uses cwd-based detection to show the correct agent identity when viewing from another rig's crew/polecat directory"} -{"id":"gt-5eegv","title":"Day 2.3: Agent writes state on lifecycle events","description":"Agents update their bead state using bd agent state command:\n- On startup: bd agent state gt-\u003crole\u003e running\n- On shutdown: bd agent state gt-\u003crole\u003e stopped\n- On stuck: bd agent state gt-\u003crole\u003e stuck\n\nState is self-reported, not inferred.\n\nImplementation: Wire up agent lifecycle hooks (SessionStart, SessionEnd, health checks) to call bd agent state.\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:05.269312-08:00","created_by":"mayor","updated_at":"2025-12-28T02:05:51.429595-08:00","closed_at":"2025-12-28T02:05:51.429595-08:00","dependencies":[{"issue_id":"gt-5eegv","depends_on_id":"gt-39ttg","type":"blocks","created_at":"2025-12-27T20:58:44.375633-08:00","created_by":"daemon"}]} -{"id":"gt-5ej2o","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All 6 agents healthy, gastown queue cleared","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:18:37.486627-08:00","updated_at":"2026-01-01T11:18:37.486627-08:00","closed_at":"2026-01-01T11:18:37.486593-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5fkb6","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:39:18.160498-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-05T00:08:31.598238-08:00","closed_at":"2026-01-05T00:08:31.598238-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:39:18-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-5fmjt","title":"Epic: Heresy Correction - Local-Only Polecat Branches","description":"Shift polecat branch lifecycle back to local-only. Remote push was a 'heresy' that crept in.\n\n**Original intent:** Polecat branches stay local, Refinery merges locally via shared .repo.git, only main gets pushed to origin.\n\n**Current (wrong):** Polecats must push branches to origin, Refinery fetches from origin.\n\n**Key insight:** All worktrees share .repo.git - Refinery can access polecat branches directly.\n\nPhases:\n1. Remove push enforcement (backward compatible)\n2. Update Refinery to use local branches \n3. Update docs/templates\n4. Handle edge cases (conflict resolution, cleanup timing)","status":"closed","priority":1,"issue_type":"epic","created_at":"2026-01-06T12:36:27.90753-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:16:21.630085-08:00","closed_at":"2026-01-06T13:16:21.630085-08:00","close_reason":"Heresy correction complete. All 4 phases implemented:\n- Phase 1: Removed push enforcement from gt done\n- Phase 2: Refinery now merges local branches\n- Phase 3: Templates/docs updated\n- Phase 4: Cleanup deferred until MR merged\nPR #145 closed as superseded."} -{"id":"gt-5g5q1","title":"Merge: toast-mjtm1hg8","description":"branch: polecat/toast-mjtm1hg8\ntarget: main\nsource_issue: toast-mjtm1hg8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:49:00.139037-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-31T11:34:50.473837-08:00","closed_at":"2025-12-31T11:34:50.473837-08:00","close_reason":"Branch no longer exists on remote"} -{"id":"gt-5g7me","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:51:16.702349-08:00","updated_at":"2026-01-01T00:51:16.702349-08:00","closed_at":"2026-01-01T00:51:16.702314-08:00"} -{"id":"gt-5gc2e","title":"Merge: immortan-mk02nagx","description":"branch: polecat/immortan-mk02nagx\ntarget: main\nsource_issue: immortan-mk02nagx\nrig: gastown\nagent_bead: gt-gastown-polecat-immortan\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:37:56.78704-08:00","created_by":"gastown/polecats/immortan","updated_at":"2026-01-04T10:41:39.755523-08:00","closed_at":"2026-01-04T10:41:39.755523-08:00","close_reason":"Merged to main at 4d24f794"} -{"id":"gt-5ggcs","title":"Merge: slit-1767082302712","description":"branch: polecat/slit-1767082302712\ntarget: main\nsource_issue: slit-1767082302712\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:18:54.190597-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T01:01:04.269367-08:00","closed_at":"2025-12-30T01:01:04.269367-08:00","close_reason":"Already merged to main"} -{"id":"gt-5ggne","title":"Digest: mol-deacon-patrol","description":"Patrol 14: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:06:35.985377-08:00","updated_at":"2025-12-31T19:06:35.985377-08:00","closed_at":"2025-12-31T19:06:35.98534-08:00"} -{"id":"gt-5gkdq","title":"Audit and fix remaining gt-* references for town-level agents","description":"After hq-* migration (gt-4r1ph), there are still references to gt-mayor/gt-deacon in code.\n\nPR #73 addresses some of these but is not merged yet.\n\nRemaining audit needed:\n1. Merge PR #73\n2. Check all files for gt-mayor/gt-deacon references\n3. Update code to use hq-* for town-level agents\n4. Update tmux session naming if needed\n5. Run gt install to create any missing beads (hq-dog-role)\n\nRelated: gt-4r1ph (parent epic)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/scrotus","created_at":"2026-01-04T13:01:03.295459-08:00","created_by":"mayor","updated_at":"2026-01-04T13:17:47.436753-08:00","closed_at":"2026-01-04T13:17:47.436753-08:00","close_reason":"Updated all role bead references to use hq-* prefix via beads.RoleBeadIDTown(). Templates and formulas now use 'bd show hq-deacon' for bead queries. Tmux session names remain as gt-* (runtime identifiers)."} -{"id":"gt-5hb89","title":"Session ended: gt-gastown-blackfinger","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:19:33.893626-08:00","created_by":"gastown/polecats/blackfinger","updated_at":"2026-01-05T19:44:41.859095-08:00","closed_at":"2026-01-05T19:44:41.859095-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/blackfinger","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:19:33-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-blackfinger\",\"worker\":\"blackfinger\"}"} -{"id":"gt-5ix9n","title":"Merge: slit-mjw3n5iw","description":"branch: polecat/slit-mjw3n5iw\ntarget: main\nsource_issue: slit-mjw3n5iw\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T16:00:47.705668-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-01T16:01:57.812576-08:00","closed_at":"2026-01-01T16:01:57.812576-08:00"} -{"id":"gt-5j3ia","title":"Witness: aggregate completion and notify Mayor","description":"## Problem\nNo signal when swarm completes. Mayor must manually check.\n\n## ZFC-Compliant Solution\nAdd step to `mol-witness-patrol.formula.toml`:\n\n```toml\n[[step]]\nid = \"check-swarm-completion\"\ntitle = \"Report swarm completion to Mayor\"\ndescription = \"\"\"\n1. Check state.json for active swarm tracking:\n - swarm_id, start_time, assigned_beads[], completed_beads[]\n2. For each completed merge (from cleanup step):\n - Add bead to completed_beads\n3. If all assigned_beads are in completed_beads:\n - Calculate duration\n - Send summary to Mayor:\n gt mail send mayor/ -s \"SWARM_COMPLETE: \u003cswarm_id\u003e\" -m \"All N polecats merged in Xm\"\n - Clear swarm tracking from state.json\n\"\"\"\ndepends_on = [\"cleanup-merged-polecats\"]\n```\n\n## Swarm Initialization\nWhen Mayor slings a batch, they should:\n```bash\n# Mayor creates swarm tracking\ngt mail send \u003crig\u003e/witness -s \"SWARM_START\" -m '{\"swarm_id\": \"batch-123\", \"beads\": [\"bd-a\", \"bd-b\", \"bd-c\"]}'\n```\n\nWitness parses SWARM_START and initializes tracking in state.json.\n\n## Why This Works\n- Mayor initiates batch with SWARM_START mail\n- Witness tracks progress in its own state\n- Witness signals completion via mail\n- All coordination is agent-to-agent via mail\n\n## Files\n- formulas/mol-witness-patrol.formula.toml","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T16:41:05.639489-08:00","created_by":"mayor","updated_at":"2025-12-28T16:13:19.273203-08:00","closed_at":"2025-12-28T16:13:19.273203-08:00","dependencies":[{"issue_id":"gt-5j3ia","depends_on_id":"gt-budeb","type":"blocks","created_at":"2025-12-27T16:41:19.077686-08:00","created_by":"daemon"}]} -{"id":"gt-5jpa4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:59:01.415013-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.674684-08:00","closed_at":"2026-01-04T16:40:22.674684-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:59:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-5jrx2","title":"Digest: mol-deacon-patrol","description":"Patrol #3: All systems nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:19:34.635428-08:00","updated_at":"2025-12-31T06:19:34.635428-08:00","closed_at":"2025-12-31T06:19:34.635393-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5l7h4","title":"gt rig status shows operational state","description":"Update 'gt rig status' to show park/dock state.\n\nAdd to output:\n- Operational state (operational/parked/docked)\n- Source of state (wisp/bead/default)\n- Any blocked configs\n\nExample:\n gt rig status gastown\n gastown\n Status: PARKED (local)\n Path: /Users/stevey/gt/gastown\n ...\n\nWhen docked:\n gastown\n Status: DOCKED (global - synced)\n ...","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:52.879926-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:52.879926-08:00","dependencies":[{"issue_id":"gt-5l7h4","depends_on_id":"gt-emh1c","type":"blocks","created_at":"2026-01-06T17:37:07.417217-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-5m5cd","title":"Digest: mol-deacon-patrol","description":"Patrol 10: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:30:35.506276-08:00","updated_at":"2025-12-25T13:30:35.506276-08:00","closed_at":"2025-12-25T13:30:35.506242-08:00"} -{"id":"gt-5mchy","title":"Digest: mol-deacon-patrol","description":"Patrol complete: no callbacks, agents healthy, 1 stale lock cleaned","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:04:54.585148-08:00","updated_at":"2025-12-28T13:04:54.585148-08:00","closed_at":"2025-12-28T13:04:54.585114-08:00"} -{"id":"gt-5n8c1","title":"Digest: mol-deacon-patrol","description":"Patrol 55: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:23:40.644404-08:00","updated_at":"2026-01-01T02:23:40.644404-08:00","closed_at":"2026-01-01T02:23:40.644366-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5o2l0","title":"Merge: cheedo-1767074334708","description":"attached_args: Code review\n\nbranch: polecat/cheedo-1767074334708\ntarget: main\nsource_issue: cheedo-1767074334708\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/nux","created_at":"2025-12-29T22:04:37.310304-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2025-12-30T00:34:52.144693-08:00","closed_at":"2025-12-30T00:34:52.144693-08:00","close_reason":"Branch polecat/cheedo-1767074334708 does not exist - polecat decommissioned without work to merge"} -{"id":"gt-5pbdp","title":"Digest: mol-deacon-patrol","description":"Patrol 10: full check, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:32:43.813756-08:00","updated_at":"2025-12-28T01:32:43.813756-08:00","closed_at":"2025-12-28T01:32:43.813717-08:00"} -{"id":"gt-5pcz5","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:12:26.712779-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:12:26.76342-08:00","closed_at":"2026-01-06T13:12:26.76342-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:12:26-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-5pjbh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:12:53.088749-08:00","updated_at":"2026-01-01T05:12:53.088749-08:00","closed_at":"2026-01-01T05:12:53.088711-08:00"} -{"id":"gt-5q6jr","title":"Witness: Block nuke if polecat has unpushed work","description":"Witness nukes polecats on MERGED signal without checking if work is actually safe to delete.\n\n## Problem\nIf witness receives MERGED for polecat X, it nukes X. But:\n- MERGED might be for a stale MR (already merged via different path)\n- Polecat might have NEW unpushed work since the MR was created\n- Race condition between merge and nuke\n\n## Fix\nBefore nuke, verify:\n1. Get polecat's cleanup_status from agent bead\n2. If cleanup_status != 'clean', escalate to Mayor instead of nuke\n3. Optionally: verify the specific commit SHA is reachable from main\n\n## Location\ninternal/witness/handlers.go HandleMerged() or the witness patrol formula","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T19:07:14.768157-08:00","created_by":"mayor","updated_at":"2025-12-30T20:56:01.390741-08:00","closed_at":"2025-12-30T20:56:01.390741-08:00","close_reason":"Implemented cleanup_status check in HandleMerged to prevent work loss"} -{"id":"gt-5qakg","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T16:12:49.859394-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.103758-08:00","closed_at":"2026-01-04T16:41:26.103758-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T16:12:49-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-5qkah","title":"Merge: nux-1766959759345","description":"branch: polecat/nux-1766959759345\ntarget: main\nsource_issue: nux-1766959759345\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-28T16:22:11.02241-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-28T22:29:02.022819-08:00","closed_at":"2025-12-28T22:29:02.022819-08:00"} -{"id":"gt-5qz6j","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:02:38.466012-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:54.569604-08:00","closed_at":"2025-12-30T23:12:54.569604-08:00","close_reason":"Branch already merged"} -{"id":"gt-5reas","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:43:00.235573-08:00","updated_at":"2026-01-01T10:43:00.235573-08:00","closed_at":"2026-01-01T10:43:00.235535-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5rg61","title":"Merge: ace-mjz94g3q","description":"branch: polecat/ace-mjz94g3q\ntarget: main\nsource_issue: ace-mjz94g3q\nrig: gastown\nagent_bead: gt-gastown-polecat-ace\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T20:52:10.337578-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-03T21:08:09.54002-08:00","closed_at":"2026-01-03T21:08:09.54002-08:00"} -{"id":"gt-5rjtw","title":"Merge: valkyrie-1767074338488","description":"branch: polecat/valkyrie-1767074338488\ntarget: main\nsource_issue: valkyrie-1767074338488\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:03:51.278787-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-29T23:32:37.262282-08:00","closed_at":"2025-12-29T23:32:37.262282-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-5rrd8","title":"Digest: mol-deacon-patrol","description":"Patrol 129: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:34:49.088968-08:00","updated_at":"2026-01-01T14:34:49.088968-08:00","closed_at":"2026-01-01T14:34:49.088933-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5sqex","title":"Merge: dag-mjxm10sv","description":"branch: polecat/dag-mjxm10sv\ntarget: main\nsource_issue: dag-mjxm10sv\nrig: gastown\nagent_bead: gt-gastown-polecat-dag","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:19:44.855117-08:00","created_by":"gastown/polecats/dag","updated_at":"2026-01-02T17:29:37.691199-08:00","closed_at":"2026-01-02T17:29:37.691199-08:00","close_reason":"Merged to main at a15f4bb7"} -{"id":"gt-5st7b","title":"Phase 5: Close PR #50, update documentation","description":"## Goal\n\nClose PR #50 with explanation and update documentation.\n\n## PR #50 Resolution\n\nClose with comment explaining:\n- The prefix mismatch is real but the fix direction is wrong\n- Changing town beads to gt prefix would break hq-* issues\n- The correct fix is in gt-4r1ph (this epic)\n- Thank contributor for identifying the issue\n\n## Documentation Updates\n\n1. docs/architecture.md\n - Update agent bead location table\n - Clarify two-level agent storage\n\n2. CLAUDE.md files\n - Update beads architecture section\n - Clarify hq-* vs rig-prefix agents\n\n3. internal/rig/manager.go\n - Update comments to reflect correct architecture\n - Remove misleading PR #32 comments about town beads\n\n## Testing\n\n- Verify docs match implementation\n- Run gt doctor to validate architecture","notes":"Completed: PR #50 closed, docs/architecture.md created, manager.go comments updated. Awaiting Phases 1-4 to verify docs match implementation.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/coma","created_at":"2026-01-03T18:43:39.284849-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T21:00:40.047604-08:00","closed_at":"2026-01-03T21:00:40.047604-08:00","close_reason":"Completed Phase 5: PR #50 closed, docs/architecture.md created with agent bead tables, manager.go comments updated with migration notes. CLAUDE.md templates verified already correct. Work submitted to merge queue (gt-trfaz). Final verification of docs matching implementation will occur when Phases 1-4 land.","dependencies":[{"issue_id":"gt-5st7b","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T18:43:47.302734-08:00","created_by":"gastown/crew/gus"},{"issue_id":"gt-5st7b","depends_on_id":"gt-nnub1","type":"blocks","created_at":"2026-01-03T18:43:47.344164-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-5tipl","title":"convoy --notify flag doesn't actually notify","description":"The gt convoy create --notify flag is captured but only stored in description. No code sends notification on convoy completion.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-30T14:13:40.209653-08:00","created_by":"mayor","updated_at":"2025-12-30T16:51:29.864136-08:00","closed_at":"2025-12-30T16:51:29.864136-08:00","close_reason":"Implemented: notify address stored in slot, added gt convoy notify command"} -{"id":"gt-5tjz5","title":"Digest: mol-deacon-patrol","description":"Patrol 19: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:49:55.247311-08:00","updated_at":"2025-12-28T19:49:55.247311-08:00","closed_at":"2025-12-28T19:49:55.247279-08:00"} -{"id":"gt-5tkc4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:29:52.753134-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.604178-08:00","closed_at":"2026-01-05T19:44:18.604178-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:29:52-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-5tnmc","title":"Digest: mol-deacon-patrol","description":"Patrol 152 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:05:20.708263-08:00","updated_at":"2025-12-31T16:05:20.708263-08:00","closed_at":"2025-12-31T16:05:20.70823-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5u1ma","title":"Digest: mol-deacon-patrol","description":"Patrol 254 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:23:04.042405-08:00","updated_at":"2026-01-01T17:23:04.042405-08:00","closed_at":"2026-01-01T17:23:04.042372-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5u5sd","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:02:01.473819-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.422717-08:00","closed_at":"2026-01-05T00:08:31.422717-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:02:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-5v29","title":"Add 'wit' alias for witness command","description":"ref works as alias for refinery, but wit doesn't work for witness. Add Aliases: []string{\"wit\"} to witnessCmd.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-20T23:11:53.453692-08:00","updated_at":"2025-12-20T23:11:53.453692-08:00"} -{"id":"gt-5v8ls","title":"Day 3.6: Witness pings Deacon for second-order monitoring","description":"Implement WITNESS_PING protocol for second-order monitoring.\n\nWitnesses collectively monitor Deacon health:\n1. Each Witness sends WITNESS_PING to Deacon during patrol\n2. Deacon responds (or doesn't if dead)\n3. If no response after threshold, Witness escalates to Mayor\n\nThis prevents the 'who watches the watchers' problem - if Deacon dies, Witnesses detect it.\n\nImplementation:\n- Add WITNESS_PING step to mol-witness-patrol\n- Deacon acknowledges pings (updates last_activity)\n- Witness checks Deacon agent bead last_activity\n- Escalate if stale beyond threshold","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T23:17:12.910142-08:00","created_by":"mayor","updated_at":"2025-12-28T10:02:39.577542-08:00","closed_at":"2025-12-28T10:02:39.577542-08:00","dependencies":[{"issue_id":"gt-5v8ls","depends_on_id":"gt-7uhts","type":"blocks","created_at":"2025-12-27T23:17:29.34799-08:00","created_by":"daemon"}]} -{"id":"gt-5w87h","title":"Digest: mol-deacon-patrol","description":"Cycle 20","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:57:11.525784-08:00","updated_at":"2025-12-31T22:57:11.525784-08:00","closed_at":"2025-12-31T22:57:11.52575-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-5wd19","title":"Merge: slit-mjxem84i","description":"branch: polecat/slit-mjxem84i\ntarget: main\nsource_issue: slit-mjxem84i\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:53:27.489517-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T14:03:11.42373-08:00","closed_at":"2026-01-02T14:03:11.42373-08:00","close_reason":"Merged to main at 31d6f6ac"} -{"id":"gt-5ww96","title":"Fix flaky beads integration test (sync state issue)","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/wretched","created_at":"2026-01-04T10:44:28.723687-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T23:40:18.852005-08:00","closed_at":"2026-01-04T23:40:18.852005-08:00","close_reason":"Fixed by syncing database before integration test"} -{"id":"gt-5y0w2","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:20:03.290663-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:40:13.371949-08:00","closed_at":"2026-01-04T16:40:13.371949-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:20:03-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-5y5p","title":"Preflight molecule: verify baseline health before work","description":"Before assigning work, verify baseline (main branch) is healthy.\n\n**From VC**: Self-healing state machine (HEALTHY → SELF_HEALING → ESCALATED). ~200 lines.\n\n**Gas Town implementation**: Preflight molecule or refinery feature:\n```yaml\npreflight:\n gates: [test, lint, build]\n on_failure: create-fix-issue\n```\n\nRun at session start. If baseline broken, file a P0 fix issue and work on that first.\n\n**Value**: Self-healing baseline. Agents don't start from broken state.\n\n**VC lesson**: Prevents cascading failures. Agent shouldn't start work on broken code.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:13.807641-08:00","updated_at":"2025-12-20T20:30:13.807641-08:00","dependencies":[{"issue_id":"gt-5y5p","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.469804-08:00","created_by":"daemon"}]} -{"id":"gt-5yikt","title":"Merge: gt-svdsy","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: gt-svdsy\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:15:50.767532-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-31T14:03:14.600155-08:00","closed_at":"2025-12-31T14:03:14.600155-08:00","close_reason":"Stale MR - no branch"} -{"id":"gt-60lii","title":"Digest: mol-deacon-patrol","description":"Patrol 144: All healthy, 2 polecats working","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:55:29.505239-08:00","updated_at":"2026-01-01T14:55:29.505239-08:00","closed_at":"2026-01-01T14:55:29.505202-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-61bow","title":"Digest: mol-deacon-patrol","description":"Patrol 50: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:21:31.799445-08:00","updated_at":"2026-01-01T02:21:31.799445-08:00","closed_at":"2026-01-01T02:21:31.799405-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-61l48","title":"Digest: mol-deacon-patrol","description":"Patrol 82: 3 rigs healthy, 6 agents pinged, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:59:56.283419-08:00","updated_at":"2026-01-01T02:59:56.283419-08:00","closed_at":"2026-01-01T02:59:56.283386-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-63clx","title":"Digest: mol-deacon-patrol","description":"Cycle 10","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:52:35.094629-08:00","updated_at":"2025-12-31T22:52:35.094629-08:00","closed_at":"2025-12-31T22:52:35.094586-08:00","dependencies":[{"issue_id":"gt-63clx","depends_on_id":"gt-eph-w2mh","type":"parent-child","created_at":"2025-12-31T22:52:35.09584-08:00","created_by":"deacon"}]} -{"id":"gt-643ie","title":"Merge: slit-1767141951901","description":"branch: polecat/slit-1767141951901\ntarget: main\nsource_issue: slit-1767141951901\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:56:13.683501-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T18:23:22.127882-08:00","closed_at":"2025-12-30T18:23:22.127882-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-659gx","title":"Digest: mol-deacon-patrol","description":"Patrol 19: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T17:49:17.60911-08:00","updated_at":"2025-12-26T17:49:17.60911-08:00","closed_at":"2025-12-26T17:49:17.609075-08:00"} -{"id":"gt-65gwa","title":"bd admin compact --older-than=0 ignores the flag, uses default 30 days","description":"When running bd admin compact --prune --older-than=0, the output says 'No expired tombstones to prune (TTL: 30 days)' - the flag value is ignored.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/dementus","created_at":"2025-12-28T22:38:10.95263-08:00","created_by":"stevey","updated_at":"2025-12-29T23:34:48.978317-08:00","closed_at":"2025-12-29T23:34:48.978317-08:00","close_reason":"Moved to bd-gigi - this is a beads bug, was filed in wrong rig (gastown). The fix needs to be made in the beads codebase at cmd/bd/compact_tombstone.go and cmd/bd/compact.go."} -{"id":"gt-68591","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:46:50.571012-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T16:40:22.849697-08:00","closed_at":"2026-01-04T16:40:22.849697-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:46:50-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-68c46","title":"Daemon respects rig operational state","description":"Update daemon to check rig config before auto-starting.\n\nIn lifecycle manager:\n- Before starting witness/refinery, check rig.GetConfig(\"status\")\n- If parked or docked, skip auto-start\n- Log the skip with reason\n\nAlso check auto_restart config:\n- If nil (blocked) or false, skip auto-start\n\nThis makes park/dock actually prevent restarts.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:49.811493-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:49.811493-08:00","dependencies":[{"issue_id":"gt-68c46","depends_on_id":"gt-emh1c","type":"blocks","created_at":"2026-01-06T17:37:07.321323-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-696fm","title":"Merge: wraith-mk0vuiu8","description":"branch: polecat/wraith-mk0vuiu8\ntarget: main\nsource_issue: wraith-mk0vuiu8\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:19:20.90643-08:00","created_by":"gastown/polecats/wraith","updated_at":"2026-01-05T19:40:10.557297-08:00","closed_at":"2026-01-05T19:40:10.557297-08:00","close_reason":"Manually merged"} -{"id":"gt-69l","title":"Hook system for event extensibility","description":"GGT needs hook system for extensibility like PGT.\n\n## Event Types\n```go\ntype Event string\nconst (\n EventPreSessionStart Event = \"pre-session-start\"\n EventPostSessionStart Event = \"post-session-start\"\n EventPreShutdown Event = \"pre-shutdown\"\n EventPostShutdown Event = \"post-shutdown\"\n EventOnPaneOutput Event = \"on-pane-output\"\n EventSessionIdle Event = \"session-idle\"\n EventMailReceived Event = \"mail-received\"\n EventWorkAssigned Event = \"work-assigned\"\n)\n```\n\n## Hook Configuration\nFile: .claude/hooks.json or .gastown/hooks.json\n```json\n{\n \"hooks\": {\n \"pre-shutdown\": [\n {\"type\": \"command\", \"cmd\": \"./scripts/pre-shutdown.sh\"}\n ],\n \"on-pane-output\": [\n {\"type\": \"command\", \"cmd\": \"./scripts/activity-monitor.sh\"}\n ]\n }\n}\n```\n\n## Hook Types\n1. **Command**: Execute external script\n2. **Built-in**: Internal Go functions (pre-shutdown checks)\n\n## Hook Interface\n```go\ntype HookRunner struct {\n config *HookConfig\n}\n\ntype HookResult struct {\n Success bool\n Message string\n Block bool // For pre-* hooks: should operation be blocked?\n}\n\nfunc (r *HookRunner) Fire(event Event, ctx *HookContext) []HookResult\n```\n\n## CLI Commands\n```\ngt hooks list [\u003cevent\u003e] # List registered hooks\ngt hooks fire \u003cevent\u003e # Manually fire for testing\ngt hooks test [--all] # Validate hook config\n```\n\n## Integration Points\n- internal/session/manager.go: Fire pre/post session hooks\n- internal/mail/router.go: Fire mail-received hook\n\n## New Package\ninternal/hooks/\n├── types.go # Event, HookConfig, HookResult\n├── runner.go # HookRunner, Fire()\n└── builtin.go # Built-in hooks (pre-shutdown checks)\n\n## PGT Reference\ngastown-py/src/gastown/hooks/\n\n## Acceptance Criteria\n- [ ] Hook config loading from JSON\n- [ ] Command hooks execute subprocess\n- [ ] Pre-shutdown hook integration with session stop\n- [ ] CLI for listing and testing hooks","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:34.584907-08:00","updated_at":"2025-12-16T16:04:47.890588-08:00"} -{"id":"gt-69m3r","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:26:00.343453-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-06T13:26:00.413447-08:00","closed_at":"2026-01-06T13:26:00.413447-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:25:59-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-69ruq","title":"Digest: mol-deacon-patrol","description":"Patrol 8: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T06:10:18.225418-08:00","updated_at":"2025-12-28T06:10:18.225418-08:00","closed_at":"2025-12-28T06:10:18.225382-08:00"} -{"id":"gt-6adrg","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:24:14.684764-08:00","updated_at":"2026-01-01T07:24:14.684764-08:00","closed_at":"2026-01-01T07:24:14.684727-08:00"} -{"id":"gt-6b2si","title":"Merge: keeper-1767106012994","description":"branch: polecat/keeper-1767106012994\ntarget: main\nsource_issue: keeper-1767106012994\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T07:01:00.144589-08:00","created_by":"gastown/polecats/keeper","updated_at":"2025-12-30T10:06:56.600434-08:00","closed_at":"2025-12-30T10:06:56.600434-08:00","close_reason":"Branch merged to main"} -{"id":"gt-6c3kn","title":"Digest: mol-deacon-patrol","description":"Patrol 18: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T18:43:56.834698-08:00","updated_at":"2025-12-25T18:43:56.834698-08:00","closed_at":"2025-12-25T18:43:56.834642-08:00"} -{"id":"gt-6c4nh","title":"Digest: mol-deacon-patrol","description":"Patrol 5: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:29:54.403996-08:00","updated_at":"2025-12-28T01:29:54.403996-08:00","closed_at":"2025-12-28T01:29:54.403955-08:00"} -{"id":"gt-6co70","title":"Session ended: gt-gastown/crew/george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T16:12:13.03679-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:26.109572-08:00","closed_at":"2026-01-04T16:41:26.109572-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T16:12:12-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/george\",\"worker\":\"gastown/crew/george\"}"} -{"id":"gt-6d0kl","title":"Session ended: gt-gastown-scrotus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:18:34.493043-08:00","created_by":"gastown/polecats/scrotus","updated_at":"2026-01-04T16:40:13.57539-08:00","closed_at":"2026-01-04T16:40:13.57539-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/scrotus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:18:34-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-scrotus\",\"worker\":\"scrotus\"}"} -{"id":"gt-6d7eh","title":"Error Handling: Suppressed errors with no logging in session/manager.go","description":"The session/manager.go Start function has many suppressed errors (using `_`):\n\n- Line 142-144: SetEnvironment calls for GT_RIG, GT_POLECAT\n- Line 148: SetEnvironment for CLAUDE_CONFIG_DIR \n- Line 157-159: SetEnvironment for BEADS_DIR, BEADS_NO_DAEMON, BEADS_AGENT_NAME\n- Line 172: ConfigureGasTownSession\n- Line 176: SetPaneDiedHook\n- Line 193: WaitForCommand (comment says non-fatal but no logging)\n- Line 200: AcceptBypassPermissionsWarning\n- Line 212-217: StartupNudge\n- Line 225: NudgeSession\n\nWhile some are intentionally \"best-effort\", there's no logging or tracking of these failures. Consider:\n1. Adding debug logging for suppressed errors\n2. Aggregating errors and returning them as warnings\n3. Using a structured approach like multierror\n\nFiles:\n- internal/session/manager.go:142-225\n\nSeverity: medium","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/bullet-farmer","created_at":"2026-01-04T23:47:53.373903-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T00:12:31.378602-08:00","closed_at":"2026-01-05T00:12:31.378602-08:00","close_reason":"Added debugSession helper function with GT_DEBUG_SESSION env var to log suppressed errors"} -{"id":"gt-6dslm","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:09:42.319822-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T13:09:42.371827-08:00","closed_at":"2026-01-06T13:09:42.371827-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:09:42-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-6dyb6","title":"Digest: mol-deacon-patrol","description":"Patrol 5: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:36:42.496243-08:00","updated_at":"2025-12-31T21:36:42.496243-08:00","closed_at":"2025-12-31T21:36:42.496201-08:00","dependencies":[{"issue_id":"gt-6dyb6","depends_on_id":"gt-eph-7pst","type":"parent-child","created_at":"2025-12-31T21:36:42.49743-08:00","created_by":"deacon"}]} -{"id":"gt-6e5i5","title":"Digest: mol-deacon-patrol","description":"Patrol 215: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:56:15.693419-08:00","updated_at":"2026-01-01T16:56:15.693419-08:00","closed_at":"2026-01-01T16:56:15.693382-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-6e5i5","depends_on_id":"gt-eph-3z1m","type":"parent-child","created_at":"2026-01-01T16:56:15.69473-08:00","created_by":"deacon"}]} -{"id":"gt-6g91g","title":"Merge: valkyrie-mjtn0kda","description":"branch: polecat/valkyrie-mjtn0kda\ntarget: main\nsource_issue: valkyrie-mjtn0kda\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:34:23.610385-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-30T23:12:37.225551-08:00","closed_at":"2025-12-30T23:12:37.225551-08:00","close_reason":"Branch already merged"} -{"id":"gt-6jpzb","title":"gt convoy create: Default --notify to mayor/","description":"When Mayor creates a convoy, --notify should default to mayor/ since:\n1. Mayor dispatched the work\n2. Mayor should know when it lands\n3. Reduces flag boilerplate\n\nImplementation: Check actor identity, if mayor, default notify to 'mayor/'","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-30T22:30:29.177276-08:00","created_by":"mayor","updated_at":"2025-12-30T22:33:23.426552-08:00","closed_at":"2025-12-30T22:33:23.426552-08:00","close_reason":"Implemented: convoy create now defaults --notify to mayor/ when mayor is the actor"} -{"id":"gt-6jqx7","title":"Merge: ace-1767074385080","description":"attached_args: Code review this merge request\n\nbranch: polecat/ace-1767074385080\ntarget: main\nsource_issue: ace-1767074385080\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/slit","created_at":"2025-12-29T22:06:01.818488-08:00","created_by":"gastown/polecats/ace","updated_at":"2025-12-29T23:34:33.884124-08:00","closed_at":"2025-12-29T23:34:33.884124-08:00","close_reason":"Code review APPROVED: Clean fix for gt-1clzd. Adds skipPane param to resolveTargetAgent, allowing --naked to bypass tmux pane lookup for terminated polecats."} -{"id":"gt-6jwvo","title":"Merge: blackfinger-mk0vu0da","description":"branch: polecat/blackfinger-mk0vu0da\ntarget: main\nsource_issue: blackfinger-mk0vu0da\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:19:22.732798-08:00","created_by":"gastown/polecats/blackfinger","updated_at":"2026-01-05T19:40:10.606417-08:00","closed_at":"2026-01-05T19:40:10.606417-08:00","close_reason":"Manually merged"} -{"id":"gt-6l2au","title":"Digest: mol-deacon-patrol","description":"Patrol 14: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:04:09.604588-08:00","updated_at":"2025-12-25T00:04:09.604588-08:00","closed_at":"2025-12-25T00:04:09.604555-08:00"} -{"id":"gt-6l7h1","title":"Merge: morsov-dogs","description":"branch: polecat/morsov-dogs\ntarget: main\nsource_issue: morsov-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:41:30.107301-08:00","created_by":"gastown/polecats/morsov","updated_at":"2025-12-30T18:23:22.219951-08:00","closed_at":"2025-12-30T18:23:22.219951-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-6m3e","title":"bd create --dedup: semantic deduplication before issue creation","description":"Before creating issue, check for semantic duplicates using AI similarity.\n\n**From VC**: internal/deduplication/ - AI-powered batch comparison. ~300 lines.\nVC had issue pollution problem: 438 issues with ~350+ spam because no early dedup.\n\n**Gas Town implementation**: CLI flag on bd create:\n```bash\nbd create --dedup --title=\"Fix auth bug\" --description=\"...\"\n```\n\nChecks recent issues (7-day window) with AI similarity. If confidence \u003e0.85, warns or blocks.\n\n**Value**: Prevents pollution from parallel workers discovering same issues.\n\n**VC lesson**: 115 issues filed in single day (Nov 2) because supervisor over-discovered without dedup. Rate limiting + dedup are essential.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:17.305652-08:00","updated_at":"2025-12-20T20:30:17.305652-08:00","dependencies":[{"issue_id":"gt-6m3e","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.599806-08:00","created_by":"daemon"}]} -{"id":"gt-6m3w7","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:59:04.960555-08:00","updated_at":"2025-12-25T13:59:04.960555-08:00","closed_at":"2025-12-25T13:59:04.960522-08:00"} -{"id":"gt-6mgvq","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:59:45.798965-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.451815-08:00","closed_at":"2026-01-05T00:08:31.451815-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:59:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-6n2ci","title":"Digest: mol-deacon-patrol","description":"Patrol 258 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:24:42.620305-08:00","updated_at":"2026-01-01T17:24:42.620305-08:00","closed_at":"2026-01-01T17:24:42.620268-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-6n3c4","title":"Digest: mol-deacon-patrol","description":"Patrol 16: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:33:16.633349-08:00","updated_at":"2025-12-25T13:33:16.633349-08:00","closed_at":"2025-12-25T13:33:16.633317-08:00"} -{"id":"gt-6n3xd","title":"Merge: furiosa-mjxkrt01","description":"branch: polecat/furiosa-mjxkrt01\ntarget: main\nsource_issue: furiosa-mjxkrt01\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T16:42:18.171412-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T16:44:28.096624-08:00","closed_at":"2026-01-02T16:44:28.096624-08:00","close_reason":"Merged to main at f8b650cf"} -{"id":"gt-6n5jl","title":"Merge: nux-mjyruwvu","description":"branch: polecat/nux-mjyruwvu\ntarget: main\nsource_issue: nux-mjyruwvu\nrig: gastown\nagent_bead: gt-gastown-polecat-nux\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T15:13:37.615698-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T15:17:54.257787-08:00","closed_at":"2026-01-04T15:17:54.257787-08:00","close_reason":"Merged to main at ae9741ad"} -{"id":"gt-6oo1v","title":"Merge: slit-mjxc8tp2","description":"branch: polecat/slit-mjxc8tp2\ntarget: main\nsource_issue: slit-mjxc8tp2\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:46:30.601669-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T13:41:40.407479-08:00","closed_at":"2026-01-02T13:41:40.407479-08:00","close_reason":"Branches merged, cleaning up stale MR beads"} -{"id":"gt-6oxlh","title":"Digest: mol-deacon-patrol","description":"Patrol 12","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:55:31.115289-08:00","updated_at":"2025-12-26T14:55:31.115289-08:00","closed_at":"2025-12-26T14:55:31.115248-08:00"} -{"id":"gt-6ptyx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:16:10.131375-08:00","updated_at":"2026-01-01T06:16:10.131375-08:00","closed_at":"2026-01-01T06:16:10.131331-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-6q6x9","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:33:01.631534-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.370876-08:00","closed_at":"2026-01-05T19:44:18.370876-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:33:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-6qd0s","title":"Merge: furiosa-1767079892643","description":"branch: polecat/furiosa-1767079892643\ntarget: main\nsource_issue: furiosa-1767079892643\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:43:35.746623-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-29T23:55:11.832783-08:00","closed_at":"2025-12-29T23:55:11.832783-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-6qld","title":"Daemon should auto-start as part of town bootstrap","description":"The Go daemon should be started automatically when the town boots up (mol-gastown-boot). Currently it requires manual 'gt daemon start'.\n\nThe daemon is critical infrastructure - it monitors the Deacon and nudges it when naked. Without it, the Deacon patrol loop doesn't run.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T13:16:52.000929-08:00","updated_at":"2025-12-23T13:16:52.000929-08:00"} -{"id":"gt-6qzay","title":"Digest: mol-deacon-patrol","description":"Patrol 7: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:15:59.128327-08:00","updated_at":"2025-12-25T19:15:59.128327-08:00","closed_at":"2025-12-25T19:15:59.12827-08:00"} -{"id":"gt-6r18e","title":"HOP Foundation: Entity Identity \u0026 Federation","description":"Foundation work for HOP graph architecture. Enables agent provenance tracking, cross-workspace federation, and delegation semantics. See ~/gt/docs/hop/GRAPH-ARCHITECTURE.md for full design.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-30T11:08:10.136469-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:05:15.699929-08:00","closed_at":"2025-12-30T18:05:15.699929-08:00","close_reason":"HOP Foundation complete - 8/9 tasks done. Only P3 overseer field (gt-6r18e.7) remains for future team scenarios. Unblocks POP Foundation (gt-jzmsj)."} -{"id":"gt-6r18e.1","title":"Set GIT_AUTHOR_NAME per agent session","description":"Set GIT_AUTHOR_NAME to actor string (e.g., gastown/crew/joe) in agent session environment. GIT_AUTHOR_EMAIL stays as workspace owner. Enables git log --author queries for agent work.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T11:08:24.620264-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:09:30.244412-08:00","closed_at":"2025-12-30T16:09:30.244412-08:00","close_reason":"Implemented: Added GIT_AUTHOR_NAME export to all agent session spawn locations (13 files updated). Enables git log --author queries for agent work.","dependencies":[{"issue_id":"gt-6r18e.1","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:24.62079-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.1.1","title":"Clarify GIT_AUTHOR_EMAIL handling for agents","description":"When setting GIT_AUTHOR_NAME per agent (gt-6r18e.1), also need to decide GIT_AUTHOR_EMAIL:\n\nOption A (proposed): Keep overseer's git email\n- GIT_AUTHOR_EMAIL = steve.yegge@gmail.com (from git config)\n- This anchors ownership to the human\n- Agents are tools of the overseer\n\nOption B: Construct agent email\n- GIT_AUTHOR_EMAIL = gastown-crew-joe@gastown.local\n- Fully separates agent identity\n- May cause issues with GitHub/Bitbucket attribution\n\nRecommendation: Option A - keeps human ownership clear while GIT_AUTHOR_NAME shows which agent did the work.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T13:58:29.803201-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:48:19.865247-08:00","closed_at":"2025-12-30T16:48:19.865247-08:00","close_reason":"Verified: Option A implemented and documented. GIT_AUTHOR_EMAIL not exported, so git uses workspace owner's email from git config. Documentation in docs/federation.md lines 94-98 is accurate.","dependencies":[{"issue_id":"gt-6r18e.1.1","depends_on_id":"gt-6r18e.1","type":"parent-child","created_at":"2025-12-30T13:58:29.805139-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.2","title":"Default BD_ACTOR in beads create","description":"BUG: BD_ACTOR env var is only read in --no-db mode and daemon RPC path. Normal direct mode skips BD_ACTOR and falls back to $USER. The comment claims 'Viper handles BD_ACTOR automatically' but there's no actual viper binding. Fix: Add explicit os.Getenv(\"BD_ACTOR\") check in main.go line 441-448, same as the --no-db path at line 352-360.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T11:08:25.504224-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:02:36.842624-08:00","closed_at":"2025-12-30T18:02:36.842624-08:00","close_reason":"Fixed - BD_ACTOR now read in all code paths (normal, JSONL-auto, no-db)","dependencies":[{"issue_id":"gt-6r18e.2","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:25.506365-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.3","title":"Add workspace metadata file (.town.json)","description":"Create ~/gt/.town.json with owner email, workspace name, and public name. Anchors workspace to entity identity for federation.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T11:08:27.318742-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:17:27.391761-08:00","closed_at":"2025-12-30T16:17:27.391761-08:00","close_reason":"Added Owner and PublicName fields to TownConfig, bumped schema to v2, updated gt install command","dependencies":[{"issue_id":"gt-6r18e.3","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:27.320549-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.4","title":"Design cross-workspace URI scheme","description":"Define URI format: gt://entity/chain/rig/issue-id. Document resolution semantics for local vs remote references. Update GRAPH-ARCHITECTURE.md with final spec.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-30T11:08:28.901241-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:22:43.4735-08:00","closed_at":"2025-12-30T16:22:43.4735-08:00","close_reason":"Designed cross-workspace URI scheme: hop:// for federation, beads:// for cross-repo, local short forms. Updated GRAPH-ARCHITECTURE.md with full spec including resolution semantics.","dependencies":[{"issue_id":"gt-6r18e.4","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:28.903065-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.5","title":"Add delegation relationship type to beads","description":"Schema addition: delegation links between work units. Fields: parent, child, delegated_by, delegated_to, terms. Enables work distribution with credit cascade.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T11:08:29.948995-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:26:25.443497-08:00","closed_at":"2025-12-30T16:26:25.443497-08:00","close_reason":"Added Delegation and DelegationTerms structs with add/remove/get/list functions. Stores delegation as slot on child issue with blocking dependency on parent.","dependencies":[{"issue_id":"gt-6r18e.5","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:29.950765-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.6","title":"Beads schema: Add created_by field enforcement","description":"Ensure created_by field is populated on all issue creation. Currently optional and often missing. Should default from BD_ACTOR env var. Affects: merge requests, escalations, digests.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2025-12-30T11:08:44.30909-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:24:30.263393-08:00","closed_at":"2025-12-30T16:24:30.263393-08:00","close_reason":"Implemented BD_ACTOR defaulting in Create() and CreateAgentBead() functions","dependencies":[{"issue_id":"gt-6r18e.6","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:44.309586-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-6r18e.6","depends_on_id":"gt-6r18e.2","type":"blocks","created_at":"2025-12-30T13:58:43.31598-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.7","title":"Beads schema: Add overseer field for team scenarios","description":"For future team support: overseer field identifies human owner when multiple humans share a workspace. For now, email in git commits serves this purpose. Low priority until teams needed.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-30T11:08:45.569583-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T11:08:45.569583-08:00","dependencies":[{"issue_id":"gt-6r18e.7","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:45.571333-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.8","title":"Add gt audit command for provenance queries","description":"New command: gt audit --actor=X to query work history. Combines git log, beads queries, and event log. Shows commits, beads created/closed, events by actor.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-30T11:08:46.527472-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T16:27:57.646086-08:00","closed_at":"2025-12-30T16:27:57.646086-08:00","close_reason":"Implemented gt audit command with --actor, --since, --json, -n flags. Queries git log, beads, town log, and events feed.","dependencies":[{"issue_id":"gt-6r18e.8","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T11:08:46.529227-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6r18e.9","title":"Document BD_ACTOR format convention","description":"Document the canonical BD_ACTOR format:\n- Town level: mayor, deacon \n- Rig level: {rig}/witness, {rig}/refinery\n- Workers: {rig}/crew/{name}, {rig}/polecats/{name}\n\nCurrently only defined in lifecycle.go:807-829. Should be in docs and CLAUDE.md for agents to reference.\n\nAlso document the attribution model:\n- GIT_AUTHOR_NAME = BD_ACTOR (agent identity, who did the work)\n- GIT_AUTHOR_EMAIL = overseer email (who owns the work)\n- created_by = BD_ACTOR (beads field)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-30T13:58:28.386054-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:00:12.595887-08:00","closed_at":"2025-12-30T18:00:12.595887-08:00","close_reason":"Documented BD_ACTOR format convention in docs/identity.md with attribution model","dependencies":[{"issue_id":"gt-6r18e.9","depends_on_id":"gt-6r18e","type":"parent-child","created_at":"2025-12-30T13:58:28.38658-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-6s378","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:49:52.350763-08:00","updated_at":"2025-12-30T15:49:52.350763-08:00","closed_at":"2025-12-30T15:49:52.350725-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-6sldb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:29:21.547852-08:00","updated_at":"2026-01-01T11:29:21.547852-08:00","closed_at":"2026-01-01T11:29:21.547816-08:00","dependencies":[{"issue_id":"gt-6sldb","depends_on_id":"gt-eph-lu6n","type":"parent-child","created_at":"2026-01-01T11:29:21.549291-08:00","created_by":"deacon"}]} -{"id":"gt-6ubje","title":"gt convoy merge: Consolidate multiple convoys into one","description":"When work gets slung individually (e.g., due to gt swarm being broken), each issue gets its own convoy via auto-convoy. Need ability to merge these into a single tracking unit.\n\n## Use Case\n\n```bash\n# Current state: 5 convoys for one logical swarm\ngt convoy list\n 1. hq-cv-6svfs: Work: gt mail reply\n 2. hq-cv-2zdme: Work: gt mail search\n 3. hq-cv-k3v6u: Work: gt mail archive/purge\n 4. hq-cv-pc2ww: Work: gt mail mark/delete\n 5. hq-cv-xdf66: Work: gt mail check\n\n# Desired: merge into one\ngt convoy merge hq-cv-xdf66 hq-cv-pc2ww hq-cv-k3v6u hq-cv-2zdme hq-cv-6svfs --title \"Mail CLI Implementation\"\n# Result: single convoy tracking all 5 issues\n```\n\n## Implementation\n\n- Take target convoy (first arg) or create new one\n- Move tracked issues from source convoys to target\n- Close/delete source convoys\n- Update subscribers\n\n## Alternative\n\nCould also support:\n```bash\ngt convoy add hq-cv-xdf66 gt-d46.2 gt-d46.3 gt-d46.4 gt-d46.5\n# Then manually close the orphaned convoys\n```\n\nBut merge is cleaner UX.","status":"open","priority":3,"issue_type":"feature","created_at":"2026-01-01T23:20:01.655502-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:20:01.655502-08:00"} -{"id":"gt-6ul03","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:14:24.526292-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:14:24.579458-08:00","closed_at":"2026-01-06T13:14:24.579458-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:14:24-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-6vle7","title":"Merge: gt-pnv61","description":"branch: polecat/rictus-1767163044\ntarget: main\nsource_issue: gt-pnv61\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:41:01.587536-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:37.045847-08:00","closed_at":"2025-12-30T23:12:37.045847-08:00","close_reason":"Branch already merged"} -{"id":"gt-6vmxg","title":"Consolidate /handoff command to town-level only","description":"Currently crew workers have duplicate /handoff skills because:\n1. Town-level ~/gt/.claude/commands/handoff.md exists (Mayor-specific)\n2. Each crew member has their own .claude/commands/handoff.md (generic)\n3. Claude Code walks up directory tree and finds both\n\nFix:\n- Update town-level handoff.md to use generic wording (works for any role)\n- Remove crew-level copies in gastown and beads (they inherit town-level)\n- Result: Single source of truth, no duplicate skills","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T14:02:16.409036-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-03T14:03:01.512154-08:00","closed_at":"2026-01-03T14:03:01.512154-08:00","close_reason":"Updated town-level handoff.md to generic wording, removed 9 crew-level copies (4 gastown, 5 beads). Now all agents inherit from ~/gt/.claude/commands/handoff.md"} -{"id":"gt-6vpku","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:33:51.313359-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:40:22.95669-08:00","closed_at":"2026-01-04T16:40:22.95669-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:33:51-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-6vtve","title":"Merge: furiosa-mjw349y2","description":"branch: polecat/furiosa-mjw349y2\ntarget: main\nsource_issue: furiosa-mjw349y2\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:16:51.592971-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T18:22:17.289707-08:00","closed_at":"2026-01-01T18:22:17.289707-08:00","close_reason":"Merged to main at 261defa3"} -{"id":"gt-6wg4d","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:28:58.953071-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.385704-08:00","closed_at":"2026-01-05T19:44:18.385704-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:28:58-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-6xe2u","title":"Centralize session name construction patterns","description":"Session name patterns like fmt.Sprintf(\"gt-%s-\u003crole\u003e\", rigName) scattered across files:\n- witness.go:287\n- refinery.go:383\n- start.go:275\n- crew_helpers.go:68-70\n\nAlso: sessionToAgentID logic duplicated in sling.go:365-391 and handoff.go:374-402.\n\nSuggestion: Create session_names.go with WitnessSessionName(), RefinerySessionName(), CrewSessionName() functions plus AgentIdentity type with FromSessionName()/ToSessionName() methods.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:10.481903-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:15.546344-08:00","closed_at":"2025-12-28T15:47:15.546344-08:00"} -{"id":"gt-6xo1k","title":"Digest: mol-deacon-patrol","description":"Patrol 111: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:10:12.778325-08:00","updated_at":"2026-01-01T14:10:12.778325-08:00","closed_at":"2026-01-01T14:10:12.778286-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-6xrcw","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:52:03.531728-08:00","updated_at":"2026-01-01T00:52:03.531728-08:00","closed_at":"2026-01-01T00:52:03.531695-08:00"} -{"id":"gt-6y5o3","title":"BUG: Daemon heartbeat too slow (10 min) for stuck agent detection","description":"The daemon's recoveryHeartbeatInterval is set to 10 MINUTES (daemon.go:134).\n\nThis means if an agent gets stuck, it can waste up to 10 minutes before Boot is spawned to triage.\n\nSuggested fix: Reduce heartbeat to 2-3 minutes, or add a separate fast-path stuck-detection check.\n\nRelated: hq-nsx0g","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/morsov","created_at":"2026-01-01T19:55:47.191001-08:00","created_by":"mayor","updated_at":"2026-01-01T19:57:49.539063-08:00","closed_at":"2026-01-01T19:57:49.539063-08:00","close_reason":"Reduced heartbeat from 10 min to 3 min"} -{"id":"gt-6y8u","title":"Deacon patrol: Janitorial cleanup patterns","description":"Patterns discovered during town cleanup that could be automated in Deacon's patrol step:\n\n## Stale Issue Detection\n\n1. **Stale in_progress issues** - Issues marked in_progress for \u003eN days without activity\n - Example: 9 issues in_progress, some likely complete\n - Action: Report list, optionally nudge assignee\n\n2. **Duplicate issues** - Same title with different IDs\n - Example: gt-87jz and gt-qp2w both 'mol-witness-patrol'\n - Action: Flag for human review\n\n3. **Orphaned issues** - Referenced in commits but still open\n - bd doctor already detects: 'hq-65jk (commit f9e9034d)'\n - Action: Report, suggest closing\n\n4. **Stale test messages** - Messages with 'test' in title older than N days\n - Example: gt-54kn, gt-1ero, gt-nriy, gt-wrw2, gt-pnu4, gt-g1ud, gt-b5sh\n - Action: Auto-close or flag\n\n## File System Cleanup\n\n5. **Log file accumulation** - daemon.log and rotated .log.gz files\n - Found 8+ log files across rigs\n - Action: Rotate, compress, delete old (\u003e7 days)\n\n6. **Beads directory size** - Town .beads/ is 65MB\n - Action: Monitor growth, alert on threshold\n\n## Database Health\n\n7. **Legacy database fingerprints** - Older DBs without fingerprint\n - bd doctor warns about this\n - Action: Report, suggest migration\n\n## Cross-Reference Integrity\n\n8. **Gastown↔Beads issue sync** - Issues filed in wrong project\n - Example: gt-8tmz.* describes Beads work but no bd-* issues\n - Action: Detect cross-references, verify both sides exist\n\n## Implementation Notes\n\nThese could be added to mol-deacon-patrol.formula.yaml as cleanup substeps:\n- Daily: Log rotation, stale issue report\n- Weekly: Duplicate detection, orphan check\n- Monthly: Size monitoring, archive old closed issues","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-24T13:25:03.212307-08:00","updated_at":"2025-12-24T13:25:03.212307-08:00","dependencies":[{"issue_id":"gt-6y8u","depends_on_id":"gt-ingm","type":"relates-to","created_at":"2025-12-24T13:25:18.850583-08:00","created_by":"daemon"}]} -{"id":"gt-6zzvi","title":"BUG: gt sling updates bead status but doesn't create .hook file","description":"gt sling updates the bead to status=hooked but doesn't actually create the .hook file in the polecat directory.\n\n## Symptom\n- gt sling reports success\n- Bead shows status=hooked, assignee set\n- Polecat's .hook file doesn't exist\n- gt hook shows empty\n\n## Root Cause\ngt sling updates bead state via bd commands but never writes to polecats/\u003cname\u003e/.hook\n\n## Fix\nAfter updating bead status, write the bead ID to the .hook file:\n```go\nhookPath := filepath.Join(polecatDir, \".hook\")\nos.WriteFile(hookPath, []byte(beadID), 0644)\n```\n\n## Related\nThis is blocking gt-zqt4d dispatch to splendid.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/angharad","created_at":"2026-01-01T23:19:28.939677-08:00","created_by":"mayor","updated_at":"2026-01-02T01:24:59.242893-08:00","closed_at":"2026-01-02T01:24:59.242893-08:00","close_reason":"Fixed identity format mismatch in buildAgentIdentity - now uses 3-part format (rig/polecats/name) matching session.AgentIdentity.Address()"} -{"id":"gt-71f9o","title":"Digest: mol-deacon-patrol","description":"Cycle 13","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:53:58.558541-08:00","updated_at":"2025-12-31T22:53:58.558541-08:00","closed_at":"2025-12-31T22:53:58.558506-08:00"} -{"id":"gt-71ts0","title":"Merge: slit-mjtj9dc8","description":"branch: polecat/slit-mjtj9dc8\ntarget: main\nsource_issue: slit-mjtj9dc8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:47:55.177132-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T23:12:31.089554-08:00","closed_at":"2025-12-30T23:12:31.089554-08:00","close_reason":"Branch already merged"} -{"id":"gt-72b5m","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T16:54:22.083656-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T16:54:22.133642-08:00","closed_at":"2026-01-06T16:54:22.133642-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T16:54:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-72cqu","title":"Missing failsafe: No circuit breaker for stuck agents","description":"When an agent (Deacon, Witness, Refinery) gets stuck, there's no automatic recovery:\n\n1. No timeout on individual steps - an agent can spin forever\n2. No watchdog process checking agent health externally\n3. No heartbeat/liveness check that triggers restart\n\nProposed solution:\n- Add a watchdog that checks agent last_activity timestamps\n- If no activity for \u003e5 minutes, force cycle the agent\n- This could be a simple cron job or daemon feature\n\nThis is defense-in-depth for the 'who watches the watchers' problem.\n\n(Moved from hq-2wy2i)","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/rictus","created_at":"2026-01-02T01:37:30.583165-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-03T13:11:18.515989-08:00","closed_at":"2026-01-03T13:11:18.515989-08:00","close_reason":"Added circuit breaker for stuck agents: (1) Refineries now monitored/restarted by daemon like Witnesses (2) Agents marked 'dead' by checkStaleAgents() are now force-killed and restarted even if Claude process is alive"} -{"id":"gt-72kmc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 55: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:59:18.3721-08:00","updated_at":"2026-01-01T12:59:18.3721-08:00","closed_at":"2026-01-01T12:59:18.372063-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-72nyt","title":"Digest: mol-deacon-patrol","description":"Cycle 13: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:21:53.797016-08:00","updated_at":"2025-12-28T13:21:53.797016-08:00","closed_at":"2025-12-28T13:21:53.796981-08:00"} -{"id":"gt-72zia","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:30:21.073368-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.76805-08:00","closed_at":"2026-01-04T16:40:22.76805-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:30:21-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-733mx","title":"gt convoy create: Fix notify slot warning","description":"When creating convoy with --notify, get warning:\n```\n⚠ Warning: couldn't set notify slot: exit status 1\n```\n\nBut notification target still shows in status. Investigate slot setter.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/keeper","created_at":"2025-12-30T22:30:30.119415-08:00","created_by":"mayor","updated_at":"2025-12-30T22:34:13.725985-08:00","closed_at":"2025-12-30T22:34:13.725985-08:00","close_reason":"Fixed: removed invalid slot set for convoy notify"} -{"id":"gt-73gzw","title":"Digest: mol-deacon-patrol","description":"Patrol 7: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:46:48.759627-08:00","updated_at":"2025-12-25T10:46:48.759627-08:00","closed_at":"2025-12-25T10:46:48.759596-08:00"} -{"id":"gt-73o6t","title":"Digest: mol-deacon-patrol","description":"Patrol 15: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:34:58.145969-08:00","updated_at":"2025-12-28T01:34:58.145969-08:00","closed_at":"2025-12-28T01:34:58.145939-08:00"} -{"id":"gt-74bv2","title":"Digest: mol-deacon-patrol","description":"Patrol 79: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:04:43.851066-08:00","updated_at":"2025-12-31T15:04:43.851066-08:00","closed_at":"2025-12-31T15:04:43.851027-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-74g1r","title":"Digest: mol-deacon-patrol","description":"Patrol 16: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:10:34.116719-08:00","updated_at":"2025-12-31T18:10:34.116719-08:00","closed_at":"2025-12-31T18:10:34.116681-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-74ivo","title":"Witness: Don't nuke polecats with open MRs or hooked work","description":"Witness mass-murdered 11 polecats during cleanup:\n\nEvidence from witness session:\n```\ngt polecat nuke gastown/slit gastown/capable\nWorktrees nuked: 11 (cheedo, dag, dementus, furiosa×2, keeper, nux, rictus, slit, capable, toast)\n```\n\nCasualties:\n- cheedo had open MR gt-t7g4b (branch not pushed, work lost)\n- cheedo had hooked work gt-w0fqg (had to reassign)\n- Unknown other work may have been lost\n\nPre-nuke checklist must verify:\n1. No uncommitted/unpushed work\n2. No open MRs awaiting merge\n3. No work on hook (unless orphan recovery)\n4. Issue is actually closed (not just 'done' signaled)\n\nThe witness is supposed to be a pit boss, not an executioner.\n\n## Update: Instructions exist but were ignored\n\nWitness CLAUDE.md HAS the pre-kill checklist:\n```\nBefore killing ANY polecat session, verify:\n[ ] 3. Check for unpushed commits\n[ ] 4. Verify issue closed\n[ ] 5. Verify PR submitted\n```\n\nCode for verification also exists on main (c28a0d5).\n\nBut witness still mass-murdered. Possible causes:\n1. Context pressure (witness was at 4% - may have lost instructions)\n2. Some aggressive prompt overriding safety checks \n3. Agent non-compliance\n\nNeed: Enforcement mechanism, not just instructions.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T22:55:11.403831-08:00","created_by":"mayor","updated_at":"2025-12-31T12:13:36.801152-08:00","closed_at":"2025-12-31T12:13:36.801152-08:00","close_reason":"Consolidated into gt-xqh3y - safety checks are part of the nuke-after-completion implementation"} -{"id":"gt-751up","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T17:28:16.978278-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.966677-08:00","closed_at":"2026-01-05T00:08:31.966677-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T17:28:16-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-76ehh","title":"Merge: ace-1767106056721","description":"branch: polecat/ace-1767106056721\ntarget: main\nsource_issue: ace-1767106056721\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T09:52:14.552932-08:00","created_by":"gastown/polecats/ace","updated_at":"2025-12-30T10:06:56.555072-08:00","closed_at":"2025-12-30T10:06:56.555072-08:00","close_reason":"Branch merged to main"} -{"id":"gt-773ek","title":"Merge: mediocre-mk0vwdaf","description":"branch: polecat/mediocre-mk0vwdaf\ntarget: main\nsource_issue: mediocre-mk0vwdaf\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:20:12.590842-08:00","created_by":"gastown/polecats/mediocre","updated_at":"2026-01-05T19:40:10.658876-08:00","closed_at":"2026-01-05T19:40:10.658876-08:00","close_reason":"Manually merged"} -{"id":"gt-775s2","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:44:45.289151-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T18:44:45.344066-08:00","closed_at":"2026-01-06T18:44:45.344066-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:44:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-779di","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:24:16.313355-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:24:16.36241-08:00","closed_at":"2026-01-05T21:24:16.36241-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:24:16-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-77fhi","title":"gt doctor: Check settings.json hook consistency across town","description":"## Problem\n\nSettings.json files in different locations can become out of sync, causing session_id\npassthrough to fail for some roles but not others. This happened when:\n- Town root was updated to use session-start.sh\n- Rig root still had old 'gt prime' direct call\n- Mayor/rig had mixed state\n\n## Locations to Check\n\n1. `~/gt/.claude/settings.json` (town root - Mayor uses this)\n2. `~/gt/\u003crig\u003e/.claude/settings.json` (rig root - polecats/crew use this)\n3. `~/gt/\u003crig\u003e/mayor/rig/.claude/settings.json` (mayor/rig - source of truth)\n\n## Check Logic\n\nFor SessionStart and PreCompact hooks, verify all use `session-start.sh`:\n- Must contain `bash ~/.claude/hooks/session-start.sh` (or full path)\n- Warn if any use bare `gt prime` without session-start.sh wrapper\n\n## Output\n\n```\ngt doctor\n...\nsession-hooks: ✓ All settings.json files use session-start.sh\n# or\nsession-hooks: ✗ ~/gt/gastown/.claude/settings.json uses bare 'gt prime' (missing session_id passthrough)\n```\n\n## Fix Suggestion\n\nWhen inconsistency found, suggest:\n```\nHint: Update SessionStart/PreCompact hooks to use 'bash ~/.claude/hooks/session-start.sh'\n This enables session_id passthrough for gt seance discovery.\n```\n\n## Related\n\n- session-start.sh extracts session_id from Claude Code stdin JSON\n- gt prime outputs [GAS TOWN] metadata line for seance\n- gt seance discovers sessions from .events.jsonl","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T00:56:00.452349-08:00","created_by":"mayor","updated_at":"2026-01-02T12:47:02.523429-08:00","closed_at":"2026-01-02T12:47:02.523429-08:00","close_reason":"Added session-hooks doctor check to verify settings.json files use session-start.sh"} -{"id":"gt-77gq7","title":"Refactor: Type CleanupStatus instead of raw strings","description":"witness/handlers.go uses raw strings for cleanup status:\n- \"clean\"\n- \"has_uncommitted\"\n- \"has_stash\"\n- \"has_unpushed\"\n\nCreate a CleanupStatus type:\n```go\ntype CleanupStatus string\n\nconst (\n CleanupClean CleanupStatus = \"clean\"\n CleanupUncommitted CleanupStatus = \"has_uncommitted\"\n CleanupStash CleanupStatus = \"has_stash\"\n CleanupUnpushed CleanupStatus = \"has_unpushed\"\n)\n\nfunc (s CleanupStatus) IsSafe() bool\nfunc (s CleanupStatus) RequiresRecovery() bool\n```\n\nFiles:\n- internal/witness/handlers.go:469-517\n- internal/polecat/manager.go:121-150","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/blackfinger","created_at":"2026-01-04T23:46:12.230666-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T00:18:34.043991-08:00","closed_at":"2026-01-05T00:18:34.043991-08:00","close_reason":"Implemented CleanupStatus type with constants and helper methods"} -{"id":"gt-77teo","title":"gt rig status: Show single-rig status summary","description":"Add 'gt rig status \u003crig\u003e' command to show focused status for a single rig.\n\n## Use Case\nWhen working on a specific rig, you want to see just that rig's status without the full town overview from 'gt status'.\n\n## Proposed Output\n```\n$ gt rig status gastown\n\n─── gastown/ ───────────────────────────────────────────\n\n🦉 Witness: running\n🏭 Refinery: running (MQ: 2 pending)\n\n👷 Crew (5): 2 active, 3 idle\n😺 Polecats (3): 1 working, 2 idle\n\nOpen issues: 45\nIn progress: 3\nReady: 12\n```\n\n## Implementation\n- Add 'status' subcommand to internal/cmd/rig.go\n- Reuse status rendering logic from gt status\n- Filter to single rig\n- Optionally add --verbose for full agent list","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T15:59:09.867533-08:00","created_by":"mayor","updated_at":"2026-01-02T16:13:46.142698-08:00","closed_at":"2026-01-02T16:13:46.142698-08:00","close_reason":"Already implemented - binary was outdated"} -{"id":"gt-7856o","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T14:03:54.860829-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T14:03:54.911282-08:00","closed_at":"2026-01-06T14:03:54.911282-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T14:03:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-78c1l","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:46:44.893123-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:46:44.943323-08:00","closed_at":"2026-01-05T19:46:44.943323-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:46:44-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-78ejc","title":"Digest: mol-deacon-patrol","description":"Patrol complete: gastown witness came online, town healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:19:32.090411-08:00","updated_at":"2025-12-28T19:19:32.090411-08:00","closed_at":"2025-12-28T19:19:32.09038-08:00"} -{"id":"gt-7921","title":"Add await-work and plugin-run steps to mol-refinery-patrol","description":"## Context\n\nThe mol-refinery-patrol needs two additional steps:\n\n### 1. await-work (Decision Point)\n\nNot just 'wait for signal' but a crossroads:\n- Check for pending signals (mail, nudge, human)\n- Check plugin gates (any plugins need to run?)\n- Check maintenance schedule (daily/weekly due?)\n- Evaluate context and decide next action\n\nPosition: Between burn-or-loop and inbox-check (the loop point)\n\n### 2. plugin-run (Like Deacon)\n\nRefinery needs plugin support for:\n- **Monitors**: Flag PRs touching sensitive code\n- **Gates**: Block merges under certain conditions\n- **Schedulers**: Reorder queue based on priority/urgency\n- **Maintenance**: Weekly cleanup, audits, stats\n- **Audits**: Log merge statistics, track patterns\n\nPosition: After queue-scan, before process-branch\n\n## Implementation\n\nUpdate RefineryPatrolMolecule() in builtin_molecules.go to include:\n- await-work step with decision tree\n- plugin-run step with gate types\n\n## Related\n- gt-7920 (original mol-refinery-patrol)\n- docs/deacon-plugins.md (existing plugin model)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T13:24:11.267237-08:00","updated_at":"2025-12-22T13:24:11.267237-08:00"} -{"id":"gt-794ba","title":"Merge: dag-1767074322940","description":"attached_args: Code review this merge request\n\nbranch: polecat/dag-1767074322940\ntarget: main\nsource_issue: dag-1767074322940\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/toast","created_at":"2025-12-29T22:04:53.933616-08:00","created_by":"gastown/polecats/dag","updated_at":"2025-12-29T22:12:30.187429-08:00","closed_at":"2025-12-29T22:12:30.187433-08:00"} -{"id":"gt-795e8","title":"Extract timing constants to constants package","description":"Extract hardcoded timing values to named constants.\n\n## Files to modify\n- internal/constants/constants.go (add constants)\n- internal/cmd/start.go (use constants)\n- internal/tmux/tmux.go (use constants)\n\n## Implementation\nAdd to constants.go:\n```go\nconst (\n ShutdownNotifyDelay = 500 * time.Millisecond\n ClaudeStartTimeout = 15 * time.Second\n ShellReadyTimeout = 5 * time.Second\n DefaultDebounceMs = 100\n DefaultDisplayMs = 5000\n)\n```\n\n## Acceptance criteria\n- [ ] 5 timing constants added to constants.go\n- [ ] start.go uses ShutdownNotifyDelay, ClaudeStartTimeout, ShellReadyTimeout\n- [ ] tmux.go uses DefaultDebounceMs, DefaultDisplayMs\n- [ ] go build ./... passes\n- [ ] go test ./... passes","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:12.251261-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T17:17:52.768898-08:00","closed_at":"2025-12-28T17:17:52.768898-08:00"} -{"id":"gt-798p0","title":"Consolidate duplicate formatAge functions in feed TUI","description":"formatConvoyAge in convoy.go is nearly identical to formatAge in view.go. Consolidate into one shared function.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/crew/joe","created_at":"2025-12-30T23:21:56.335889-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-30T23:24:11.352354-08:00","closed_at":"2025-12-30T23:24:11.352354-08:00","close_reason":"Consolidated formatConvoyAge into formatAge - both now use 'just now' for \u003c 1 minute"} -{"id":"gt-79jxg","title":"Bug: bd update --parent doesn't persist","description":"The --parent flag on bd update reports success but doesn't persist the parent field.\n\n**Confirmed behavior:**\n```bash\nbd update gt-9kp3t --parent=gt-d0jqp --no-daemon -v\n# Output: ✓ Updated issue: gt-9kp3t\n\nbd show gt-9kp3t --json | jq '.[0].parent'\n# Returns: null\n\ngrep gt-9kp3t .beads/issues.jsonl | head -1 | jq '.parent'\n# Returns: null (field not present)\n```\n\n**Root cause hypothesis:**\nThe update handler processes the --parent flag but either:\n1. Doesn't write it to the Issue struct\n2. Doesn't include it in the JSONL export\n3. The field name doesn't match what export expects\n\n**Files to check:**\n- cmd/bd/show.go:638-640 (flag handling)\n- cmd/bd/show.go:810-814 (reparenting logic)\n- internal/rpc/server_issues_epics.go (RPC handler)\n- internal/rpc/protocol.go (UpdateArgs.Parent field)\n\nRelated: bd-cj2e (the original feature implementation)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-27T22:40:33.744301-08:00","created_by":"mayor","updated_at":"2025-12-27T23:32:31.903138-08:00","closed_at":"2025-12-27T23:32:31.903138-08:00"} -{"id":"gt-7a7gw","title":"Test swarm epic","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T23:21:25.212736-08:00","created_by":"gastown/polecats/splendid","updated_at":"2026-01-01T23:21:49.335008-08:00","closed_at":"2026-01-01T23:21:49.335008-08:00","close_reason":"Test cleanup"} -{"id":"gt-7a9em","title":"Digest: mol-deacon-patrol","description":"Patrol 68: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:01:21.994338-08:00","updated_at":"2025-12-31T15:01:21.994338-08:00","closed_at":"2025-12-31T15:01:21.994301-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7aw1m","title":"Instrument gt commands to appear in activity feed","description":"## Architecture: Two-tier event system\n\n```\n┌─────────────┐ ┌─────────────┐ ┌─────────────┐\n│ gt commands │ │ bd mutations│ │ agent output│\n└──────┬──────┘ └──────┬──────┘ └──────┬──────┘\n └────────────────┼────────────────┘\n ▼\n ~/gt/.events.jsonl (raw, audit)\n │\n ┌─────────────────┐\n │ Feed daemon │ ← goroutine in gt daemon\n │ - filters │\n │ - aggregates │\n │ - AI curates │\n └────────┬────────┘\n ▼\n ~/gt/.feed.jsonl (curated, user-facing)\n```\n\n## Event format\n\n```json\n{\n \"ts\": \"2025-12-28T10:30:15Z\",\n \"source\": \"gt\",\n \"type\": \"sling\",\n \"actor\": \"mayor\",\n \"payload\": {\"bead\": \"gt-xyz\", \"target\": \"gastown/Toast\"},\n \"visibility\": \"feed\"\n}\n```\n\nVisibility: `audit` | `feed` | `both`\n\n## Implementation phases\n\n1. **Event logging** - gt commands write to ~/gt/.events.jsonl\n2. **Feed daemon** - goroutine in gt daemon tails events, writes curated feed\n3. **Feed readers** - gt feed, gt dashboard read from .feed.jsonl\n4. **AI curation** - future: haiku summarization for complex activity\n\nPart of epic gt-u7dxq","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:02:16.207055-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T19:06:02.36645-08:00","closed_at":"2025-12-30T19:06:02.366455-08:00","close_reason":"Instrumented gt commands (nudge, unsling, up, down, stop, polecat_spawn) to emit events to ~/gt/.events.jsonl for the activity feed"} -{"id":"gt-7cmf7","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:15:31.292389-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T13:15:31.352017-08:00","closed_at":"2026-01-06T13:15:31.352017-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:15:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-7dl6f","title":"Digest: mol-deacon-patrol","description":"Patrol 159: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:08:58.978159-08:00","updated_at":"2026-01-01T15:08:58.978159-08:00","closed_at":"2026-01-01T15:08:58.978119-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-7dl6f","depends_on_id":"gt-eph-w5fg","type":"parent-child","created_at":"2026-01-01T15:08:58.979437-08:00","created_by":"deacon"}]} -{"id":"gt-7einb","title":"Digest: mol-deacon-patrol","description":"Patrol 9: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:58:57.715007-08:00","updated_at":"2025-12-25T15:58:57.715007-08:00","closed_at":"2025-12-25T15:58:57.714972-08:00"} -{"id":"gt-7emkr","title":"Digest: mol-deacon-patrol","description":"P14: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:13:35.668266-08:00","updated_at":"2025-12-25T20:13:35.668266-08:00","closed_at":"2025-12-25T20:13:35.668211-08:00"} -{"id":"gt-7grh6","title":"Tmux session scanner for running agents","description":"Scan tmux for running Gas Town agent sessions.\n\n## Deliverables\n\n1. Function: ScanRunningSessions() -\u003e []AgentAddr\n - Parse tmux list-sessions\n - Filter for Gas Town session naming pattern\n - Return addresses of running agents\n\n2. Function: ScanRigSessions(rig) -\u003e []AgentAddr\n - Filter running sessions by rig prefix\n\n3. Alias resolution:\n - #rig/gastown → running sessions in gastown\n - #town → all running Gas Town sessions\n - #witnesses → running witness sessions\n\n## Location\ninternal/discovery/tmux.go\n\n## Acceptance\n- Scanner finds running sessions\n- Correctly parses session names to addresses\n- Handles no-sessions case gracefully","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-26T14:52:32.408394-08:00","updated_at":"2025-12-26T14:52:32.408394-08:00"} -{"id":"gt-7h2vf","title":"Merge: keeper-mjtn0wgm","description":"branch: polecat/keeper-mjtn0wgm\ntarget: main\nsource_issue: keeper-mjtn0wgm\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:37:00.614301-08:00","created_by":"gastown/polecats/keeper","updated_at":"2025-12-30T23:12:37.195447-08:00","closed_at":"2025-12-30T23:12:37.195447-08:00","close_reason":"Branch already merged"} -{"id":"gt-7hayk","title":"Digest: mol-deacon-patrol","description":"Patrol 122: All healthy, no callbacks, 3 convoys tracking","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T21:52:22.391195-08:00","updated_at":"2025-12-30T21:52:22.391195-08:00","closed_at":"2025-12-30T21:52:22.391158-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7hc70","title":"Merge: bullet-mk02nnn6","description":"branch: polecat/bullet-mk02nnn6\ntarget: main\nsource_issue: bullet-mk02nnn6\nrig: gastown\nagent_bead: gt-gastown-polecat-bullet\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:38:56.819253-08:00","created_by":"gastown/polecats/bullet","updated_at":"2026-01-04T10:44:54.433989-08:00","closed_at":"2026-01-04T10:44:54.433989-08:00","close_reason":"Merged to main at cd429fe8"} -{"id":"gt-7hwug","title":"Merge: gt-svdsy","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: gt-svdsy\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:17:37.413408-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:42.937419-08:00","closed_at":"2025-12-30T23:12:42.937419-08:00","close_reason":"Branch already merged"} -{"id":"gt-7i6al","title":"Digest: mol-deacon-patrol","description":"Patrol 259 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:25:08.918354-08:00","updated_at":"2026-01-01T17:25:08.918354-08:00","closed_at":"2026-01-01T17:25:08.918315-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7jg6l","title":"Merge: vuvalini-mk0bkcrq","description":"branch: polecat/vuvalini-mk0bkcrq\ntarget: main\nsource_issue: vuvalini-mk0bkcrq\nrig: gastown\nagent_bead: gt-gastown-polecat-vuvalini\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T14:48:51.621963-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-04T14:50:12.465351-08:00","closed_at":"2026-01-04T14:50:12.465351-08:00","close_reason":"Merged to main at 00d73b8f"} -{"id":"gt-7jonl","title":"Digest: mol-deacon-patrol","description":"Patrol complete: beads witness+refinery came online, both rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:28:45.988408-08:00","updated_at":"2025-12-28T19:28:45.988408-08:00","closed_at":"2025-12-28T19:28:45.98837-08:00"} -{"id":"gt-7jtnu","title":"Merge: dementus-mjw46vz4","description":"branch: polecat/dementus-mjw46vz4\ntarget: main\nsource_issue: dementus-mjw46vz4\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T17:32:20.742553-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-01T19:55:59.965387-08:00","closed_at":"2026-01-01T19:55:59.965387-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-7l1ao","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:28:51.409433-08:00","updated_at":"2025-12-31T20:28:51.409433-08:00","closed_at":"2025-12-31T20:28:51.4094-08:00"} -{"id":"gt-7l21t","title":"Merge: capable-mjxen9vb","description":"branch: polecat/capable-mjxen9vb\ntarget: main\nsource_issue: capable-mjxen9vb\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:52:30.765213-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T14:02:27.420751-08:00","closed_at":"2026-01-02T14:02:27.420751-08:00","close_reason":"Merged to main at 579c1137"} -{"id":"gt-7lhbs","title":"Formula schema: Define formula.toml structure","description":"Define the formula file format in .beads/formulas/:\n- formula name and description\n- input parameters (pr, branch, files)\n- legs array with name, focus, output\n- synthesis config\n- dependencies between legs\n\nReference: gt-ubqeg.1 epic description for schema ideas.\nCreate example formula: code-review.formula.toml","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T14:42:51.241775-08:00","created_by":"mayor","updated_at":"2026-01-01T15:51:10.878372-08:00","closed_at":"2026-01-01T15:51:10.878372-08:00","close_reason":"Schema defined in internal/formula/types.go (a395b4e)"} -{"id":"gt-7ln2y","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:48:02.684953-08:00","updated_at":"2026-01-01T00:48:02.684953-08:00","closed_at":"2026-01-01T00:48:02.684916-08:00"} -{"id":"gt-7lufm","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:02:45.896796-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.626281-08:00","closed_at":"2026-01-04T16:40:22.626281-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:02:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-7m33w","title":"Beads daemon cache stale - hook queries return wrong data","description":"Root cause: Beads daemon has stale data. Multiple bd daemons running (4 instances). When gt hook status queries via daemon, it gets old hooked bead. When queried with --no-daemon, correct bead is shown. This is a daemon cache coherence issue, not an ID resolution bug. Workaround: Use bd --no-daemon commands or restart daemons.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T17:28:57.699661-08:00","created_by":"mayor","updated_at":"2026-01-01T17:38:44.807776-08:00","closed_at":"2026-01-01T17:38:44.807776-08:00","close_reason":"Fixed: Hook discovery now reads from database column (hook_bead) instead of parsing stale description field"} -{"id":"gt-7m572","title":"Merge: gt-svdsy","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: gt-svdsy\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:20:08.869585-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:42.909537-08:00","closed_at":"2025-12-30T23:12:42.909537-08:00","close_reason":"Branch already merged"} -{"id":"gt-7o7","title":"Session pre-shutdown checks","description":"Session stop should verify clean state before killing, like PGT.\n\n## Pre-Shutdown Checks\n\n### 1. Git Working Tree Clean\n```go\nfunc checkGitClean(clonePath string) error {\n // git status --porcelain\n // Fail if any output\n}\n```\n\n### 2. All Commits Pushed\n```go\nfunc checkCommitsPushed(clonePath string) error {\n // git log origin/HEAD..HEAD\n // Fail if any unpushed commits\n}\n```\n\n### 3. Assigned Issues Handled\n```go\nfunc checkIssuesHandled(polecat *Polecat) error {\n // If polecat.Issue != \"\", check if closed or reassigned\n}\n```\n\n### 4. Beads Synced\n```go\nfunc checkBeadsSynced(clonePath string) error {\n // bd sync --status in clone directory\n}\n```\n\n## Behavior on Failure\n1. First attempt: Nudge worker to fix\n2. Retry up to 3 times with delay\n3. After retries: Escalate to Witness/Mayor\n\n## Integration\nModify internal/session/manager.go Stop():\n```go\nfunc (m *Manager) Stop(polecat string, force bool) error {\n if !force {\n if err := m.runPreShutdownChecks(polecat); err != nil {\n return fmt.Errorf(\"pre-shutdown checks failed: %w\", err)\n }\n }\n // existing stop logic\n}\n```\n\n## Flags\n- --force: Skip checks\n- --grace-period N: Time to wait for fixes\n\n## Dependencies\n- Ties into gt-69l (hook system) - can be hook-based\n- Ties into gt-f8v (Witness pre-kill verification)\n\n## Acceptance Criteria\n- [ ] Stop fails if uncommitted changes (without --force)\n- [ ] Stop fails if unpushed commits\n- [ ] Clear error messages with fix instructions\n- [ ] --force bypasses all checks","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:55.968983-08:00","updated_at":"2025-12-16T16:05:02.795812-08:00"} -{"id":"gt-7o8d5","title":"Digest: mol-deacon-patrol","description":"Patrol 107: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:06:36.110896-08:00","updated_at":"2026-01-01T14:06:36.110896-08:00","closed_at":"2026-01-01T14:06:36.110858-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7ou4x","title":"Digest: mol-deacon-patrol","description":"Patrol 141 complete: All agents healthy, no incidents, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:54:59.351834-08:00","updated_at":"2025-12-31T15:54:59.351834-08:00","closed_at":"2025-12-31T15:54:59.351798-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7phgk","title":"Digest: mol-deacon-patrol","description":"Patrol 145 complete: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:00:20.08244-08:00","updated_at":"2025-12-31T16:00:20.08244-08:00","closed_at":"2025-12-31T16:00:20.082399-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7pp3l","title":"Migrate startup paths from SessionBeacon to StartupNudge","description":"\n## Problem\nStartupNudge function exists (gt-bgfqy) but no code uses it.\nAll startup paths still call session.SessionBeacon() + 'gt prime' separately.\n\nSessionBeacon format: [GAS TOWN] address • molID • timestamp\nStartupNudge format: [GAS TOWN] recipient \u003c- sender • timestamp • topic\n\nThe key difference is SENDER - needed for seance discovery ('who started this session?').\n\n## Files to Update\n- internal/cmd/crew_lifecycle.go (lines 354-371, 525-538)\n- internal/cmd/start.go (lines 757, 805-810, 946-949)\n- internal/cmd/deacon.go (line 307)\n- internal/cmd/witness.go (line 350)\n- internal/cmd/up.go (lines 288, 335, 559, 660)\n- internal/cmd/mayor.go (line 151)\n- internal/session/manager.go (lines 205, 215)\n\n## Pattern\nReplace:\n beacon := session.SessionBeacon(address, molID)\n t.NudgeSession(sessionID, beacon)\n t.NudgeSession(sessionID, \"gt prime\")\n\nWith:\n cfg := session.StartupNudgeConfig{Recipient: address, Sender: sender, Topic: topic, MolID: molID}\n session.StartupNudge(t, sessionID, cfg)\n // Note: StartupNudge is the session title, still need separate 'gt prime' for priming\n\n## Related\n- gt-85whr (parent epic)\n- gt-j0546 (did RuntimeConfig refactor, not StartupNudge)\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-31T11:44:10.596654-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-31T11:51:45.942205-08:00","closed_at":"2025-12-31T11:51:45.942205-08:00","close_reason":"Migrated all 12 startup paths from SessionBeacon to StartupNudge. All startup paths now include sender information for better seance discovery. Files updated: crew_lifecycle.go (3), start.go (2), deacon.go (1), witness.go (1), up.go (4), mayor.go (1), session/manager.go (1). Build passes, all tests pass."} -{"id":"gt-7psb8","title":"Day 3.5: Test polecat → refinery → merged flow","description":"Integration test:\n1. Spawn polecat with work\n2. Polecat completes (updates state, closes bead)\n3. Witness detects completion\n4. Witness sends MERGE_READY\n5. Refinery processes and merges\n6. MERGED signal received\n\nParent: gt-hwka3","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:06.584468-08:00","created_by":"mayor","updated_at":"2025-12-28T13:13:59.734708-08:00","closed_at":"2025-12-28T13:13:59.734708-08:00","dependencies":[{"issue_id":"gt-7psb8","depends_on_id":"gt-hwka3","type":"parent-child","created_at":"2025-12-27T20:58:50.044788-08:00","created_by":"daemon"},{"issue_id":"gt-7psb8","depends_on_id":"gt-7uhts","type":"blocks","created_at":"2025-12-27T20:59:01.683897-08:00","created_by":"daemon"},{"issue_id":"gt-7psb8","depends_on_id":"gt-5v8ls","type":"blocks","created_at":"2025-12-27T23:17:29.833111-08:00","created_by":"daemon"}]} -{"id":"gt-7q4","title":"HOP: Skill vectors on work items","description":"Add skill embeddings to work items for capability-based matching. See ~/ai/stevey-gastown/hop/CONTEXT.md. Post-v0.1 work.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-17T01:00:43.251085-08:00","updated_at":"2025-12-17T01:00:43.251085-08:00"} -{"id":"gt-7q6of","title":"Digest: mol-deacon-patrol","description":"Patrol #17","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:24:09.096086-08:00","updated_at":"2025-12-31T06:24:09.096086-08:00","closed_at":"2025-12-31T06:24:09.096055-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7qgze","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T13:56:37.753837-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.233689-08:00","closed_at":"2026-01-04T16:41:26.233689-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T13:56:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-7qvd7","title":"Add gt seance command for predecessor discovery","description":"## Purpose\n\n**\"Where did you put the stuff you left for me?\"** - The #1 question in any handoff.\n\nSeance lets you literally talk to your predecessor. Not parse their logs - commune with them.\n\n## The Insight\n\nClaude Code can resume sessions with full context. A seance spawns a Claude subprocess that resumes a predecessor session, letting you ask questions directly:\n- \"Why did you make this decision?\"\n- \"Where were you stuck?\"\n- \"What did you try that did not work?\"\n\n## Architecture\n\n```\ngt seance --talk \u003csession-id\u003e\n │\n └─▶ claude --fork-session --resume \u003cid\u003e\n │\n └─▶ Spawns in sandbox namespace (ghost-joe)\n │\n └─▶ Communication via tmux\n \"Where is the config you mentioned?\"\n → Predecessor has full context, answers\n```\n\n**Key flags:**\n- `--fork-session` creates new session ID (read-only seance, no grave disturbance)\n- `--resume \u003cid\u003e` loads predecessor context\n\n## Discovery\n\nSessions are discoverable via:\n1. **Beacon in transcript** - `[GAS TOWN] role • topic • timestamp` searchable via `/resume`\n2. **SessionStart events** - Hook emits to `~/gt/.events.jsonl` (our data, ZFC-compliant)\n3. **Claude /resume search** - Native filtering\n\n## Usage\n\n```bash\ngt seance # List discoverable sessions\ngt seance --role crew # Filter by role\ngt seance --rig gastown # Filter by rig\ngt seance --recent 10 # Last N sessions\n\ngt seance --talk \u003cid\u003e # THE SEANCE - talk to predecessor\ngt seance --talk \u003cid\u003e -p \"Where is X?\" # One-shot question\n```\n\n## ZFC Compliance\n\n- **No parsing Claude internals** - Use Claude CLI to resume\n- **Agent discovers** - Claude reads session, interprets, responds\n- **Events are ours** - SessionStart hook writes to our event stream\n\n## Beacon Format\n\n```\n[GAS TOWN] gastown/crew/joe \u003c- deacon • 2025-12-30T15:42 • assigned:gt-xyz\n```\n\nSearchable via `claude --resume \"GAS TOWN\"` or `claude --resume \"gastown/crew/joe\"`","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/joe","created_at":"2025-12-30T22:48:25.398216-08:00","created_by":"stevey","updated_at":"2025-12-31T00:28:15.208318-08:00","closed_at":"2025-12-31T00:28:15.208318-08:00","close_reason":"Implemented ZFC-compliant seance with --talk flag for literal predecessor conversations"} -{"id":"gt-7qyfh","title":"BUG: gt convoy create with count argument doesn't set convoy description","description":"Root cause: 'gt convoy create' usage is 'create \u003cname\u003e [issues...]' but we invoked 'gt convoy create 1 beads' expecting polecat count semantics.\n\nThe '1' became the convoy name, 'beads' was treated as an issue ID (failed to track).\n\nOptions:\n1. Add --count flag for polecat spawning semantics\n2. When issues are added later via 'convoy add', update convoy title if current title is just a number\n3. If first arg looks like an issue ID (has prefix), auto-generate name from issue title\n\nFor now, users must use: 'gt convoy create \"Descriptive name\" issue-id' not 'gt convoy create \u003ccount\u003e \u003crig\u003e'","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2026-01-02T01:05:12.022289-08:00","created_by":"beads/crew/dave","updated_at":"2026-01-02T13:50:51.744474-08:00","closed_at":"2026-01-02T13:50:51.744474-08:00","close_reason":"Fixed: convoy create now auto-detects issue IDs and generates name from issue title"} -{"id":"gt-7rp6z","title":"Digest: mol-deacon-patrol","description":"Patrol 14: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:09:03.478593-08:00","updated_at":"2025-12-28T03:09:03.478593-08:00","closed_at":"2025-12-28T03:09:03.478547-08:00"} -{"id":"gt-7swyi","title":"QUICK FIX: Make gt crew start use NudgeSession instead of SendKeys","description":"## The Immediate Problem\n`gt crew start gus` fails to deliver the GUPP nudge because:\n1. Uses `t.SendKeys(sessionID, \"gt prime\")` which has the Enter-concatenation bug\n2. Should use `t.NudgeSession()` which solves this reliably\n\n## Quick Fix\nIn start.go, change line ~809:\n```go\n// Before\nif err := t.SendKeys(sessionID, \"gt prime\"); err != nil {\n\n// After\nif err := t.NudgeSession(sessionID, \"gt prime\"); err != nil {\n```\n\nSame fix needed in:\n- start.go:756 (restart path)\n- crew_lifecycle.go:354\n- crew_lifecycle.go:525\n\n## Why This Is P0\nCold starts of crew workers are broken. This blocks basic usage.\n\n## Note\nThis is a stopgap. The full solution is the StartupNudge refactor (gt-bgfqy).\n","status":"closed","priority":0,"issue_type":"task","created_at":"2025-12-30T22:48:37.100072-08:00","created_by":"stevey","updated_at":"2025-12-30T22:52:44.511622-08:00","closed_at":"2025-12-30T22:52:44.511622-08:00","close_reason":"Fixed: Replaced SendKeys with NudgeSession for gt prime in start.go and crew_lifecycle.go"} -{"id":"gt-7t0f9","title":"Session ended: gt-gastown-wasteland","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:14:46.649047-08:00","created_by":"gastown/polecats/wasteland","updated_at":"2026-01-05T19:44:41.905198-08:00","closed_at":"2026-01-05T19:44:41.905198-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/wasteland","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:14:46-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-wasteland\",\"worker\":\"wasteland\"}"} -{"id":"gt-7to00","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:22:20.556376-08:00","updated_at":"2026-01-01T10:22:20.556376-08:00","closed_at":"2026-01-01T10:22:20.55634-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7tt8","title":"Default crew name should be something better than 'main'","description":"When creating a new rig, the default crew worker name is 'main'. This is confusing since:\n\n1. 'main' is also the git branch name\n2. It doesn't convey that this is the user's personal workspace\n3. Crew names should feel more personal/distinct\n\nConsider alternatives like:\n- 'home' - the user's home base\n- 'desk' - their personal desk\n- 'joe/max/etc' - actual name-based defaults\n- Let user pick during rig init","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-21T16:46:51.049367-08:00","updated_at":"2025-12-21T16:46:59.133599-08:00"} -{"id":"gt-7uhts","title":"Day 3.4: Refinery processes MERGE_READY mail","description":"Refinery patrol handles merge requests:\n1. Check inbox for MERGE_READY messages\n2. For each, verify branch exists\n3. Run merge checks (tests, lint)\n4. If passing, merge to main\n5. Send MERGED signal back\n\nParent: gt-hwka3","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:05.510472-08:00","created_by":"mayor","updated_at":"2025-12-28T09:56:42.672932-08:00","closed_at":"2025-12-28T09:56:42.672932-08:00","dependencies":[{"issue_id":"gt-7uhts","depends_on_id":"gt-hwka3","type":"parent-child","created_at":"2025-12-27T20:58:48.873689-08:00","created_by":"daemon"},{"issue_id":"gt-7uhts","depends_on_id":"gt-u6siy","type":"blocks","created_at":"2025-12-27T20:59:00.772533-08:00","created_by":"daemon"},{"issue_id":"gt-7uhts","depends_on_id":"gt-6qyt1","type":"relates-to","created_at":"2025-12-27T20:59:09.685061-08:00","created_by":"daemon"},{"issue_id":"gt-7uhts","depends_on_id":"gt-k294l","type":"blocks","created_at":"2025-12-27T23:17:28.282401-08:00","created_by":"daemon"}]} -{"id":"gt-7uo17","title":"Digest: mol-deacon-patrol","description":"Patrol complete: no callbacks, all agents healthy, no orphans, doctor 24/28","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T06:06:07.673288-08:00","updated_at":"2025-12-28T06:06:07.673288-08:00","closed_at":"2025-12-28T06:06:07.673251-08:00"} -{"id":"gt-7uuye","title":"Witness cleanup leaves worktree behind","description":"When witness processes POLECAT_DONE:\n- Session is killed ✓\n- Work is merged ✓\n- Worktree is NOT removed ✗\n\nDementus example: session 'not running', but /Users/stevey/gt/gastown/polecats/dementus still exists.\n\nExpected: gt polecat nuke equivalent - full cleanup including worktree deletion.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T14:49:43.863954-08:00","created_by":"mayor","updated_at":"2026-01-01T18:16:39.858296-08:00","closed_at":"2026-01-01T18:16:39.858296-08:00","close_reason":"Fixed: HandleMerged now calls witness.AutoNukeIfClean to cleanup worktrees after merge"} -{"id":"gt-7v894","title":"Digest: mol-deacon-patrol","description":"Patrol 11: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:29:27.269454-08:00","updated_at":"2026-01-01T04:29:27.269454-08:00","closed_at":"2026-01-01T04:29:27.269416-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7vdqv","title":"Witness patrol wisp not respawning after completion","description":"The gastown witness session is alive but idle. Its patrol wisp completed and nothing spawned a new one. 50 POLECAT_DONE messages have piled up unprocessed.\n\nRoot cause: Patrol wisp pattern assumes continuous loops, but when a wisp ends (completed all steps, context limit, etc), nothing triggers respawn. The witness just sits with empty hook.\n\nEvidence:\n- Session exists (Jan 2nd session ID) \n- gt hook shows nothing hooked\n- gt status shows 'running [bead: dead]' - session alive, wisp dead\n- 50 unread mail messages piling up\n\nProposed fix:\n1. Witness startup hook should auto-spawn patrol wisp if hook is empty\n2. Or: patrol wisp final step should spawn successor wisp before closing\n3. Or: external health check (Deacon?) spawns new wisp when witness hook is empty","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/vuvalini","created_at":"2026-01-03T20:59:08.830265-08:00","created_by":"mayor","updated_at":"2026-01-04T16:51:17.739851-08:00","closed_at":"2026-01-04T16:51:17.739851-08:00","close_reason":"Fixed by adding explicit wisp respawn instructions to patrol work loops and formula. Agents now know to run 'bd mol wisp mol-\u003crole\u003e-patrol' to continue or 'gt handoff' to exit."} -{"id":"gt-7vu13","title":"Digest: mol-deacon-patrol","description":"Patrol 11: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:34:37.954432-08:00","updated_at":"2025-12-29T22:34:37.954432-08:00","closed_at":"2025-12-29T22:34:37.954399-08:00"} -{"id":"gt-7wuwd","title":"Digest: mol-deacon-patrol","description":"Patrol 35: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:00:38.135744-08:00","updated_at":"2025-12-31T14:00:38.135744-08:00","closed_at":"2025-12-31T14:00:38.135711-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7wybt","title":"Digest: mol-deacon-patrol","description":"Patrol 14","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:52:22.727424-08:00","updated_at":"2025-12-25T20:52:22.727424-08:00","closed_at":"2025-12-25T20:52:22.727382-08:00"} -{"id":"gt-7x274","title":"Refactor slash command provisioning to town-level only","description":"Current architecture provisions .claude/commands/ per-workspace (crew/polecat), causing duplicate skills when Claude walks up the directory tree.\n\nNew architecture:\n1. gt install: Create ~/gt/.claude/commands/ with handoff.md (and future commands)\n2. gt crew add / gt polecat spawn: Remove ProvisionCommands() calls - inherit from town\n3. bd doctor: Check town-level .claude/commands/ exists instead of per-workspace\n\nFiles to modify:\n- internal/cmd/install.go - add town-level commands provisioning\n- internal/crew/manager.go - remove ProvisionCommands call\n- internal/polecat/manager.go - remove ProvisionCommands calls (2 places)\n- internal/doctor/commands_check.go - check town-level instead of per-workspace\n- internal/templates/templates.go - may need ProvisionTownCommands() variant","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T15:46:35.290734-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-03T15:49:08.703064-08:00","closed_at":"2026-01-03T15:49:08.703064-08:00","close_reason":"Refactored slash command provisioning to town-level only:\n- gt install now creates ~/gt/.claude/commands/ with all commands\n- Removed ProvisionCommands calls from crew/manager.go and polecat/manager.go\n- Updated bd doctor to check town-level commands instead of per-workspace\nAll agents now inherit commands via Claude directory traversal"} -{"id":"gt-7x45i","title":"Digest: mol-deacon-patrol","description":"Patrol 133: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:36:33.81227-08:00","updated_at":"2026-01-01T14:36:33.81227-08:00","closed_at":"2026-01-01T14:36:33.812237-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7xcxg","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:16:44.453076-08:00","updated_at":"2026-01-01T05:16:44.453076-08:00","closed_at":"2026-01-01T05:16:44.453032-08:00"} -{"id":"gt-7xnsb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: all healthy, handoff","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:54:29.939584-08:00","updated_at":"2026-01-01T00:54:29.939584-08:00","closed_at":"2026-01-01T00:54:29.939549-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7xrxm","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:07:18.873998-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:40:13.47103-08:00","closed_at":"2026-01-04T16:40:13.47103-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:07:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-7yv7u","title":"Digest: mol-deacon-patrol","description":"Patrol 121: All agents healthy, 6 health pings sent, no callbacks, no orphans, 1 idle dog, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:47:18.065087-08:00","updated_at":"2025-12-31T15:47:18.065087-08:00","closed_at":"2025-12-31T15:47:18.065049-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-7z2aq","title":"Digest: mol-deacon-patrol","description":"Cycle 298: All healthy, refinery processing","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:45:19.116581-08:00","updated_at":"2026-01-01T18:45:19.116581-08:00","closed_at":"2026-01-01T18:45:19.116527-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-7z2aq","depends_on_id":"gt-eph-neve","type":"parent-child","created_at":"2026-01-01T18:45:19.117873-08:00","created_by":"deacon"}]} -{"id":"gt-800pu","title":"Merge: gt-fpv2p","description":"branch: polecat/capable-mjw47ef9\ntarget: main\nsource_issue: gt-fpv2p\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2026-01-01T16:10:47.929535-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-01T16:12:16.549417-08:00","closed_at":"2026-01-01T16:12:16.549417-08:00","close_reason":"Merged to main at 61f8c80e"} -{"id":"gt-804je","title":"Merge: dementus-1767146229184","description":"branch: polecat/dementus-1767146229184\ntarget: main\nsource_issue: dementus-1767146229184\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:01:50.010863-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T18:23:22.116095-08:00","closed_at":"2025-12-30T18:23:22.116095-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-81rh4","title":"Digest: mol-deacon-patrol","description":"Patrol 13: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T16:18:56.391947-08:00","updated_at":"2025-12-25T16:18:56.391947-08:00","closed_at":"2025-12-25T16:18:56.391918-08:00"} -{"id":"gt-81zgq","title":"Merge: nux-1767079896198","description":"branch: polecat/nux-1767079896198\ntarget: main\nsource_issue: nux-1767079896198\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:38:17.859423-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T23:55:11.863853-08:00","closed_at":"2025-12-29T23:55:11.863853-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-82601","title":"Digest: mol-deacon-patrol","description":"Cycle 20 - handoff threshold","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:09:44.74427-08:00","updated_at":"2026-01-01T10:09:44.74427-08:00","closed_at":"2026-01-01T10:09:44.744233-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-82a4i","title":"Digest: mol-deacon-patrol","description":"Patrol 100: All healthy - milestone!","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:13:26.983953-08:00","updated_at":"2026-01-01T03:13:26.983953-08:00","closed_at":"2026-01-01T03:13:26.98391-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-833ns","title":"Merge: slit-mjvtz18y","description":"branch: polecat/slit-mjvtz18y\ntarget: main\nsource_issue: slit-mjvtz18y\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T11:25:57.181628-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-01T11:27:16.278691-08:00","closed_at":"2026-01-01T11:27:16.278691-08:00","close_reason":"Merged to main at 2bcfa763"} -{"id":"gt-83lo0","title":"Session: gt-gastown-test completed gt-f7jxr","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:19:14.440051-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:23:05.810069-08:00","closed_at":"2026-01-02T13:23:05.810069-08:00","close_reason":"Test cleanup"} -{"id":"gt-83s17","title":"Digest: mol-deacon-patrol","description":"Patrol 13: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:34:18.706892-08:00","updated_at":"2025-12-25T00:34:18.706892-08:00","closed_at":"2025-12-25T00:34:18.706854-08:00"} -{"id":"gt-83zh4","title":"Merge: nux-1767075895486","description":"branch: polecat/nux-1767075895486\ntarget: main\nsource_issue: nux-1767075895486\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:28:28.554902-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.353761-08:00","closed_at":"2025-12-30T01:01:04.353761-08:00","close_reason":"Already merged to main"} -{"id":"gt-84ery","title":"Link MR bead to agent bead for traceability","description":"MR bead and agent bead are separate with no cross-reference.\n\n## Problem\n- MR bead tracks: branch, target, source_issue\n- Agent bead tracks: state, hook_bead, cleanup_status\n- No link between them\n\nWhen something goes wrong, hard to trace which polecat created which MR.\n\n## Fix\n1. MR bead should include agent_bead field\n2. Agent bead should include active_mr field\n3. On gt done: update both to reference each other\n4. On merge: clear both references\n\n## Benefits\n- Traceable: given MR, find polecat\n- Traceable: given polecat, find MR\n- Orphan detection: MR without agent = stale","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-30T19:07:38.326085-08:00","created_by":"mayor","updated_at":"2025-12-30T22:28:39.2344-08:00","closed_at":"2025-12-30T22:28:39.2344-08:00","close_reason":"Implemented bidirectional cross-references between MR beads (agent_bead field) and agent beads (active_mr field). gt done now sets both, refinery clears on merge."} -{"id":"gt-84ru8","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T13:13:29.851288-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-04T16:41:26.250499-08:00","closed_at":"2026-01-04T16:41:26.250499-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T13:13:29-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-85whr","title":"Agent Startup Consolidation: Unified nudge, seance metadata, LLM-agnostic","description":"## Problem\n\nAgent startup nudge logic is scattered across 6+ files with inconsistent behavior:\n- start.go, crew_lifecycle.go, crew_at.go, handoff.go, deacon.go, witness.go\n\nSome paths work (handoff), others fail (crew start). The core issues:\n\n1. **tmux send-keys Enter issue**: `send-keys \"foo\" Enter` concatenates, doesnt send Enter separately\n2. **All sessions look identical**: First message is \"gt prime\" everywhere, `/resume` shows duplicate-looking sessions\n3. **No seance metadata**: Cant differentiate predecessors by sender, role, timestamp, topic\n4. **Hardcoded to Claude**: `claude --dangerously-skip-permissions` everywhere\n\n## Solution\n\n1. **Unified StartupNudge function** - All paths call one function with rich metadata\n2. **Seance-aware nudge format** - First message contains: sender, recipient, timestamp, topic\n3. **Runtime configuration** - LLM command/args in config, not hardcoded\n4. **gt seance command** - Find and resume predecessor sessions\n\n## Nudge Format\n\nThe startup nudge becomes the session title in `/resume`:\n```\n[GAS TOWN] gastown/crew/gus ← mayor • 2025-12-30T15:42 • cold-start\n```\n\nComponents:\n- Address: gastown/crew/gus (recipient identity)\n- Sender: mayor, deacon, witness, self (for handoff)\n- Timestamp: When session started\n- Topic: mol-id, \"cold-start\", \"handoff\", etc.\n\n## Key Insight\n\nThe GUPP nudge content doesnt matter for triggering propulsion - agent already read CLAUDE.md and hooks ran. What matters is:\n1. The nudge arrives reliably (NudgeSession solves this)\n2. The nudge creates a unique, identifiable session title\n\n## Related\n\n- gt-p2o6s: Extend gt nudge to support channel:name syntax\n- gt-9guv2: Messaging Channels epic\n- Session beacon already exists but is for identity, not session title\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-30T22:47:40.224932-08:00","created_by":"stevey","updated_at":"2025-12-31T11:52:07.539053-08:00","closed_at":"2025-12-31T11:52:07.539053-08:00","close_reason":"All success criteria met: (1) All agent startups use unified StartupNudge (gt-7pp3l), (2) Runtime commands from config (gt-j0546), (3) Sessions identifiable in /resume by role, sender, time, topic, (4) gt seance works for predecessor discovery (gt-7qvd7). Related Phase 1 tasks (gt-bgfqy, gt-dc2fs) also complete."} -{"id":"gt-85y3v","title":"Merge: slit-mjxaptzz","description":"branch: polecat/slit-mjxaptzz\ntarget: main\nsource_issue: slit-mjxaptzz\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:12:11.730961-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T12:31:04.850497-08:00","closed_at":"2026-01-02T12:31:04.850497-08:00","close_reason":"Merged to main at 50d9643d"} -{"id":"gt-860md","title":"Merge: capable-1767146233256","description":"branch: polecat/capable-1767146233256\ntarget: main\nsource_issue: capable-1767146233256\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:03:37.996927-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T18:23:22.098333-08:00","closed_at":"2025-12-30T18:23:22.098333-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-873o1","title":"gt hook: Support viewing other agents' hooks","description":"Currently `gt hook` only shows your own hook. Would be useful to query any agent's hook:\n\n```\ngt hook show gastown/polecats/nux # What's nux working on?\ngt hook show gastown/witness # What's the witness hooked to?\n```\n\n**Use cases**:\n- Mayor checking what polecats are working on\n- Witness checking polecat status\n- Debugging coordination issues\n- Quick status overview\n\n**Compact output** (one line):\n```\ngastown/polecats/nux: gt-abc123 'Fix the widget bug' [in_progress]\n```\n\nFiled by: gastown/polecats/nux (agent UX feedback)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-31T11:48:03.620561-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T18:14:13.625313-08:00","closed_at":"2026-01-01T18:14:13.625313-08:00","close_reason":"Implemented gt hook show \u003cagent\u003e with compact one-line output format"} -{"id":"gt-87s80","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 66: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:16:08.302675-08:00","updated_at":"2026-01-01T13:16:08.302675-08:00","closed_at":"2026-01-01T13:16:08.302638-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-88iqs","title":"Digest: mol-deacon-patrol","description":"Patrol 36: rictus removed from rig","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:01:06.488074-08:00","updated_at":"2025-12-31T14:01:06.488074-08:00","closed_at":"2025-12-31T14:01:06.488024-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-88ru2","title":"Digest: mol-deacon-patrol","description":"Patrol 260 complete: final cycle before handoff","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:25:33.432411-08:00","updated_at":"2026-01-01T17:25:33.432411-08:00","closed_at":"2026-01-01T17:25:33.432371-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-88sb7","title":"Merge: dementus-1767079823043","description":"branch: polecat/dementus-1767079823043\ntarget: main\nsource_issue: dementus-1767079823043\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:37:42.270498-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-29T23:44:03.52339-08:00","closed_at":"2025-12-29T23:44:03.52339-08:00","close_reason":"Already merged to main"} -{"id":"gt-88t3v","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:40:20.204777-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:40:20.258337-08:00","closed_at":"2026-01-05T21:40:20.258337-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:40:19-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-8a0h","title":"Add compaction recovery protocol to role templates","description":"After context compaction (summarization), agents may be disoriented.\n\nAdd guidance to recognize and recover:\n- 'If you feel you've lost earlier context or are disoriented, run: gt prime'\n- 'This re-injects your role, current work, and pending messages'\n- 'It's safe to prime multiple times - it just outputs context'\n\nThis is the fallback path when self-check is missed and compaction happens.\nCompaction isn't catastrophic if priming is robust.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:46:21.959626-08:00","updated_at":"2025-12-23T14:27:07.466696-08:00"} -{"id":"gt-8a26e","title":"Digest: mol-deacon-patrol","description":"Patrol #10: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:22:34.274885-08:00","updated_at":"2025-12-31T06:22:34.274885-08:00","closed_at":"2025-12-31T06:22:34.274849-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8bes","title":"Review: Witness patrol template changes (gt-h1n5)","description":"Polecat rictus implemented significant witness.md.tmpl changes: banners, wisp-based execution, handoff bead attachment, loop-or-exit, patrol summary. Review for correctness and consistency with deacon pattern.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T19:57:38.242943-08:00","updated_at":"2025-12-23T19:57:38.242943-08:00"} -{"id":"gt-8c9sb","title":"Digest: mol-deacon-patrol","description":"Patrol 12: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:00:01.263806-08:00","updated_at":"2026-01-01T23:00:01.263806-08:00","closed_at":"2026-01-01T23:00:01.263769-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-8cmas","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T20:52:30.754198-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-03T11:32:45.191435-08:00","closed_at":"2026-01-03T11:32:45.191435-08:00","close_reason":"Session lifecycle events processed","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T20:52:30-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-8cpjq","title":"Merge: toast-1767074978542","description":"branch: polecat/toast-1767074978542\ntarget: main\nsource_issue: toast-1767074978542\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:13:41.32716-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-29T23:32:37.226835-08:00","closed_at":"2025-12-29T23:32:37.226835-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-8dgjp","title":"Digest: mol-deacon-patrol","description":"Patrol 24: All quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:55:54.336104-08:00","updated_at":"2025-12-31T13:55:54.336104-08:00","closed_at":"2025-12-31T13:55:54.336071-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8dv","title":"CLI: plugin commands (list, status)","description":"Add gt plugins \u003crig\u003e to list plugins and gt plugin status \u003cname\u003e to check plugin state. Simple directory scan of \u003crig\u003e/plugins/.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T22:53:02.694926-08:00","updated_at":"2025-12-15T23:17:06.594328-08:00","dependencies":[{"issue_id":"gt-8dv","depends_on_id":"gt-axz","type":"blocks","created_at":"2025-12-15T22:53:17.413809-08:00","created_by":"daemon"}]} -{"id":"gt-8f0zv","title":"Polecats should spawn with auto-accept mode enabled","description":"During swarm bd-784c, polecats (Toast, Nux) were spawned without --dangerously-skip-permissions or equivalent auto-accept mode.\n\n**Problem:**\nEvery edit, bash command, and tool use required manual confirmation via tmux send-keys. This defeats the purpose of autonomous polecat operation.\n\n**Expected:**\nPolecats in a swarm should run with permissions bypassed so they can work autonomously.\n\n**Suggestion:**\n- gt sling should pass --dangerously-skip-permissions by default for polecats\n- Or polecats should have a .claude/settings.local.json pre-configured for auto-accept","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2025-12-28T22:14:03.849695-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-29T21:58:09.089153-08:00","closed_at":"2025-12-29T21:58:09.089153-08:00","close_reason":"Main fix (--dangerously-skip-permissions for polecat sessions) was already in place since ec29ca07 (Dec 17). Fixed naked mode help text to also show the flag. All spawn paths verified: session.Manager.Start(), swarm spawning, and manual naked mode now all use --dangerously-skip-permissions."} -{"id":"gt-8f7xb","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:46:06.04451-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-06T18:46:06.10043-08:00","closed_at":"2026-01-06T18:46:06.10043-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:46:05-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-8fgwf","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 42: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:51:48.950258-08:00","updated_at":"2026-01-01T12:51:48.950258-08:00","closed_at":"2026-01-01T12:51:48.95022-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8h532","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T12:32:25.124176-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T12:32:25.178807-08:00","closed_at":"2026-01-06T12:32:25.178807-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T12:32:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-8i6bg","title":"DRY: Duplicate bd command execution pattern in mail package","description":"Multiple functions in mailbox.go and router.go repeat the same pattern for executing bd commands:\n\n```go\ncmd := exec.Command(\"bd\", args...)\ncmd.Dir = workDir\ncmd.Env = append(cmd.Environ(), \"BEADS_DIR=\"+beadsDir)\nvar stdout, stderr bytes.Buffer\ncmd.Stdout = \u0026stdout\ncmd.Stderr = \u0026stderr\nif err := cmd.Run(); err != nil {\n errMsg := strings.TrimSpace(stderr.String())\n // error handling...\n}\n```\n\nThis appears in:\n- mailbox.go:171-211 (queryMessages)\n- mailbox.go:283-314 (getFromDir)\n- mailbox.go:343-368 (closeInDir)\n- mailbox.go:399-419 (markUnreadBeads)\n- router.go:448-486 (queryAgents)\n- router.go:625-649 (sendToSingle)\n- And more...\n\nExtract a helper like:\n\n```go\ntype bdResult struct {\n stdout []byte\n stderr string\n}\n\nfunc (m *Mailbox) runBdCommand(args []string, beadsDir string) (*bdResult, error)\n```\n\nSeverity: medium","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/road-warrior","created_at":"2026-01-04T23:46:36.428344-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T00:17:38.613522-08:00","closed_at":"2026-01-05T00:17:38.613522-08:00","close_reason":"Extracted runBdCommand helper to bd.go, refactored mailbox.go and router.go to use it"} -{"id":"gt-8iwvq","title":"Merge: max-mk02mxj6","description":"branch: polecat/max-mk02mxj6\ntarget: main\nsource_issue: max-mk02mxj6\nrig: gastown\nagent_bead: gt-gastown-polecat-max\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:38:01.293654-08:00","created_by":"gastown/polecats/max","updated_at":"2026-01-04T10:42:38.933064-08:00","closed_at":"2026-01-04T10:42:38.933064-08:00","close_reason":"Merged to main at 44e9f81d"} -{"id":"gt-8j36q","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All 6 agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:21:03.053564-08:00","updated_at":"2026-01-01T10:21:03.053564-08:00","closed_at":"2026-01-01T10:21:03.053526-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8kr7v","title":"Digest: mol-deacon-patrol","description":"P12: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:13:03.071841-08:00","updated_at":"2025-12-25T20:13:03.071841-08:00","closed_at":"2025-12-25T20:13:03.07179-08:00"} -{"id":"gt-8ltgc","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:06:01.089748-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.745046-08:00","closed_at":"2026-01-05T00:08:31.745046-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:06:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-8lz","title":"Comprehensive help text and examples","description":"Improve help text with examples and cross-references.\n\n## Improvements\n\n### 1. Examples Section\nAdd to Long description:\n```go\nvar spawnCmd = \u0026cobra.Command{\n Long: `Spawn a polecat with work assignment.\n\nExamples:\n gt spawn gastown/Toast --issue gt-abc\n gt spawn gastown --issue gt-def # auto-select polecat\n gt spawn gastown/Nux -m \"Fix the tests\" # free-form task`,\n}\n```\n\n### 2. Cross-References\nReference related commands:\n```\nSee also:\n gt polecat list List available polecats\n gt session attach Attach to spawned session\n```\n\n### 3. Flag Descriptions\nMore detail on flags:\n```go\ncmd.Flags().StringVar(\u0026issue, \"issue\", \"\", \n \"Beads issue ID to assign. The polecat will work on this issue.\")\n```\n\n### 4. Common Workflows\nAdd workflow docs to gt --help:\n```\nCommon Workflows:\n Start a swarm:\n gt swarm preflight\n gt swarm create gastown --epic gt-abc --worker Toast --worker Nux --start\n gt refinery start gastown\n \n Check status:\n gt status\n gt swarm status \u003cid\u003e\n```\n\n## Files to Update\nAll internal/cmd/*.go files\n\n## Acceptance Criteria\n- [ ] All commands have Examples\n- [ ] Related commands cross-referenced\n- [ ] Flags have detailed descriptions\n- [ ] Root help shows workflows","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T14:48:53.303016-08:00","updated_at":"2025-12-16T16:07:37.391195-08:00"} -{"id":"gt-8mvjj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 38: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:38:38.491774-08:00","updated_at":"2026-01-01T12:38:38.491774-08:00","closed_at":"2026-01-01T12:38:38.491739-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8n6dx","title":"Digest: mol-deacon-patrol","description":"Patrol 6: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:41:13.824117-08:00","updated_at":"2026-01-01T22:41:13.824117-08:00","closed_at":"2026-01-01T22:41:13.824077-08:00","dependencies":[{"issue_id":"gt-8n6dx","depends_on_id":"gt-eph-0hmg","type":"parent-child","created_at":"2026-01-01T22:41:13.825375-08:00","created_by":"deacon"}]} -{"id":"gt-8nmy","title":"Update Deacon template to emphasize staying in ~/gt/deacon directory","description":"The Deacon template should instruct the agent to stay in ~/gt/deacon/ as much as possible, and always return there after any excursion. This prevents issues with identity detection (mail, mol status) which depend on cwd.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T13:30:27.969826-08:00","updated_at":"2025-12-23T13:30:27.969826-08:00"} -{"id":"gt-8nv8u","title":"test-new-swarm-1767338498","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T23:21:38.675445-08:00","created_by":"gastown/polecats/splendid","updated_at":"2026-01-02T17:08:38.793576-08:00","closed_at":"2026-01-02T17:08:38.793576-08:00","close_reason":"Stale test swarm - cleanup","mol_type":"swarm"} -{"id":"gt-8o88h","title":"Merge: furiosa-mjwnxrkd","description":"branch: polecat/furiosa-mjwnxrkd\ntarget: main\nsource_issue: furiosa-mjwnxrkd\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T01:27:03.370604-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T01:29:03.172864-08:00","closed_at":"2026-01-02T01:29:03.172864-08:00","close_reason":"Merged to main at 17fd3668"} -{"id":"gt-8otmd","title":"Stranded convoy detection + feeding via dog dispatch","description":"## Problem\nConvoys can become **stranded** - they have ready work but no polecats working on it. Work is waiting for a ride.\n\n## Definition: Stranded Convoy\n```\nconvoy is open\n AND has tracked issues where:\n - status = open (not in_progress, not closed)\n - not blocked (dependencies met) \n - no assignee (or assignee session is dead)\n```\n\nIf all open issues are blocked or have live polecats → convoy is fine (in-flight).\nIf ready issues exist with nobody working them → convoy is stranded.\n\n## Solution: Deacon patrol + dog dispatch\n\n**Detection (Deacon patrol step):**\nCheck open convoys for stranded state.\n\n**Dispatch:**\n```bash\ngt sling mol-convoy-feed deacon/dogs --var convoy=\u003cconvoy-id\u003e\n```\n\n**mol-convoy-feed formula (single pass):**\n1. Load convoy, find ready issues (not blocked, no assignee)\n2. Check idle polecat capacity\n3. Dispatch min(ready_issues, idle_polecats) \n4. Exit\n\nDog doesn't babysit. Just feeds and leaves. Deacon's patrol loop handles repeated checking - if still stranded next cycle, dispatches dog again.\n\n## Benefit\nStateless, batch-oriented. Convoys become fire-and-forget.\n\n(Moved from hq-1h2to)","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/capable","created_at":"2026-01-02T01:37:20.985845-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-02T17:22:48.514628-08:00","closed_at":"2026-01-02T17:22:48.514628-08:00","close_reason":"Implemented stranded convoy detection with gt convoy stranded command, mol-convoy-feed formula, and deacon patrol step"} -{"id":"gt-8p0pr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 49: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:55:40.264156-08:00","updated_at":"2026-01-01T12:55:40.264156-08:00","closed_at":"2026-01-01T12:55:40.264117-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8pcb","title":"Plugin/molecule catalog integration design","description":"Two currently independent systems:\n1. Disk-based plugins (~~/gt/plugins/) - Deacon patrol extensions\n2. Molecule catalog (protos in beads) - bd pour/wisp/bond\n\nInvestigate integration points:\n- User-contributed molecules bonded to catalog\n- Dynamic molecule attachment during execution (e.g., 'attach security sniffer because we noticed condition X')\n- How plugins could contribute protos\n- How protos could trigger plugins\n\nNot blocking launch. Future design investigation.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-22T21:52:47.897048-08:00","updated_at":"2025-12-28T22:34:14.460561-08:00","closed_at":"2025-12-28T22:34:14.460561-08:00"} -{"id":"gt-8qm9m","title":"Digest: mol-deacon-patrol","description":"Cycle 18","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:56:15.556985-08:00","updated_at":"2025-12-31T22:56:15.556985-08:00","closed_at":"2025-12-31T22:56:15.556948-08:00"} -{"id":"gt-8r7","title":"Enhance Mayor CLAUDE.md with GGT milestone tracking","description":"Update ~/ai/CLAUDE.md (Mayor startup context) with:\n\n1. GGT Self-Hosting Milestone section\n - Track progress toward gt replacing town\n - Key blockers: gt-h5n (merge queue), gt-974 (daemon)\n - What \"self-hosting\" means (GGT working on itself)\n\n2. Recent Architecture Decisions\n - Engineer = role, Refinery = place\n - Merge queue in Beads (not branch discovery)\n - Session restart protocol\n\n3. Transition Plan\n - Current: use town commands (PGT)\n - Target: use gt commands (GGT)\n - Switch criteria: gt-b1g closed\n\nKeep it concise - Mayor context should be quick to scan.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T23:12:07.260653-08:00","updated_at":"2025-12-16T23:12:07.260653-08:00","dependencies":[{"issue_id":"gt-8r7","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:12:15.124842-08:00","created_by":"daemon"}]} -{"id":"gt-8r8h1","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:08:48.93224-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.437943-08:00","closed_at":"2026-01-04T16:40:13.437943-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:08:48-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-8rhg4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: healthy, 2 acks","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:57:25.067267-08:00","updated_at":"2026-01-01T09:57:25.067267-08:00","closed_at":"2026-01-01T09:57:25.067225-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8rn3r","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:31:52.315066-08:00","updated_at":"2025-12-31T23:31:52.315066-08:00","closed_at":"2025-12-31T23:31:52.315025-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8sw25","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:46:10.719458-08:00","updated_at":"2026-01-01T07:46:10.719458-08:00","closed_at":"2026-01-01T07:46:10.719417-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8tc1v","title":"Stale Session ended events accumulating in beads","description":"Large number of 'Session ended' event beads accumulating without being processed/closed.\n\nEvidence: bd list shows 20+ open 'Session ended: gt-gastown-*' events.\n\nThese should either:\n1. Be processed by witness patrol and closed\n2. Not be created as beads (use mail instead)\n3. Have automatic expiry/cleanup\n\nRelated to gt-7vdqv (witness patrol not running).\n\nQuestions:\n- Are these events useful for audit trail?\n- Should they auto-close after acknowledgment?\n- Should session events be mail instead of beads?","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/wasteland","created_at":"2026-01-04T10:41:41.885212-08:00","created_by":"mayor","updated_at":"2026-01-05T00:13:14.869894-08:00","closed_at":"2026-01-05T00:13:14.869894-08:00","close_reason":"Resolved. The blocker (gt-7vdqv: witness patrol not respawning) was fixed. Witness patrol now processes session events properly - verified 10+ closed events in history. Closed the one remaining stale event (gt-lhaec). Design assessment: session events should remain as beads (audit trail with cost data, session info). No design change needed.","dependencies":[{"issue_id":"gt-8tc1v","depends_on_id":"gt-7vdqv","type":"blocks","created_at":"2026-01-04T10:41:51.294478-08:00","created_by":"mayor"}]} -{"id":"gt-8tmz.19.1","title":"Define meta-formula YAML schema","description":"Define the YAML schema for meta-formulas that generate multiple formulas.\n\n## Proposed Schema\n\n type: meta-formula\n name: multi-lang-shiny\n generates:\n for-each:\n var: lang\n values: [go, python, typescript]\n formula:\n name: \"shiny-{lang}\"\n extends: base-shiny\n vars:\n language: \"{lang}\"\n\n## Key Decisions\n\n- Use \"generates\" key to distinguish from regular formulas\n- for-each at generation level (not runtime)\n- Output is N formula files or in-memory formulas\n\n## Deliverables\n\n1. Add MetaFormula type to types.go\n2. Add ForEachGenerate struct\n3. Document schema in comments","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:17:11.835417-08:00","updated_at":"2025-12-28T22:34:14.17731-08:00","closed_at":"2025-12-28T22:34:14.17731-08:00","dependencies":[{"issue_id":"gt-8tmz.19.1","depends_on_id":"gt-8tmz.19","type":"parent-child","created_at":"2025-12-25T17:17:11.835933-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.19.2","title":"Implement meta-formula generator in parser","description":"Implement the generator that expands meta-formulas into concrete formulas.\n\n## Implementation\n\n1. Detect type: meta-formula in parser\n2. Evaluate for-each values\n3. For each value, instantiate the formula template\n4. Substitute {var} placeholders with current value\n5. Return list of generated Formula structs\n\n## API\n\n func (p *Parser) ExpandMetaFormula(mf *MetaFormula) ([]*Formula, error)\n\n## Edge Cases\n\n- Empty values list: return empty slice\n- Duplicate generated names: error\n- Nested meta-formulas: error (not supported initially)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:17:22.927406-08:00","updated_at":"2025-12-28T22:34:14.160488-08:00","closed_at":"2025-12-28T22:34:14.160488-08:00","dependencies":[{"issue_id":"gt-8tmz.19.2","depends_on_id":"gt-8tmz.19","type":"parent-child","created_at":"2025-12-25T17:17:22.927946-08:00","created_by":"daemon"},{"issue_id":"gt-8tmz.19.2","depends_on_id":"gt-8tmz.19.1","type":"blocks","created_at":"2025-12-25T17:17:44.228494-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.19.3","title":"Add multi-lang-shiny example and tests","description":"Create example meta-formula and test suite.\n\n## Example\n\nCreate .beads/formulas/multi-lang-shiny.meta.yaml:\n- Generates shiny-go, shiny-python, shiny-typescript\n- Each extends base-shiny with language-specific vars\n\n## Tests\n\n1. Test basic expansion (3 languages -\u003e 3 formulas)\n2. Test variable substitution in names and content\n3. Test error on duplicate generated names\n4. Test empty values list\n5. Integration: cook a generated formula","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:17:34.225612-08:00","updated_at":"2025-12-28T22:34:14.143458-08:00","closed_at":"2025-12-28T22:34:14.143458-08:00","dependencies":[{"issue_id":"gt-8tmz.19.3","depends_on_id":"gt-8tmz.19","type":"parent-child","created_at":"2025-12-25T17:17:34.226093-08:00","created_by":"daemon"},{"issue_id":"gt-8tmz.19.3","depends_on_id":"gt-8tmz.19.2","type":"blocks","created_at":"2025-12-25T17:17:44.323794-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.20.1","title":"Design org formula hierarchy pattern","description":"Design how organizational formula hierarchies work.\n\n## Pattern\n\n company-base.formula.yaml (org-wide policies)\n └── team-frontend.formula.yaml (extends company-base)\n └── project-dashboard.formula.yaml (extends team-frontend)\n\n## Key Questions\n\n1. How are org formulas discovered? (search path? explicit import?)\n2. How do aspects merge across levels?\n3. Can child override parent aspects?\n4. How to handle aspect conflicts?\n\n## Proposed Design\n\n- Formulas use extends: just like today\n- Aspect lists merge (child appends to parent)\n- Child can exclude parent aspects via \"exclude-aspects: [name]\"\n- Search path: local -\u003e rig -\u003e org (configurable)\n\n## Deliverables\n\n1. Document pattern in docs/formula-inheritance.md\n2. Define conflict resolution rules\n3. Identify implementation tasks","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:17:57.888973-08:00","updated_at":"2025-12-28T22:34:14.125846-08:00","closed_at":"2025-12-28T22:34:14.125846-08:00","dependencies":[{"issue_id":"gt-8tmz.20.1","depends_on_id":"gt-8tmz.20","type":"parent-child","created_at":"2025-12-25T17:17:57.889494-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.20.2","title":"Implement aspect merging across formula chain","description":"Implement merging of aspects when formulas extend each other.\n\n## Current State\n\nextends: already works for steps and vars.\nAspects need similar merge behavior.\n\n## Implementation\n\n1. In Resolve(), collect aspects from entire extends chain\n2. Merge lists: parent aspects first, then child\n3. Support exclude-aspects field to remove inherited aspects\n4. Dedupe by aspect name (child wins on conflict)\n\n## Files\n\n- internal/formula/parser.go: Resolve()\n- internal/formula/types.go: add ExcludeAspects field\n\n## Tests\n\n1. Child inherits parent aspects\n2. Child adds additional aspects\n3. Child excludes parent aspect\n4. Three-level chain merges correctly","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:18:09.693911-08:00","updated_at":"2025-12-28T22:34:14.107027-08:00","closed_at":"2025-12-28T22:34:14.107027-08:00","dependencies":[{"issue_id":"gt-8tmz.20.2","depends_on_id":"gt-8tmz.20","type":"parent-child","created_at":"2025-12-25T17:18:09.694463-08:00","created_by":"daemon"},{"issue_id":"gt-8tmz.20.2","depends_on_id":"gt-8tmz.20.1","type":"blocks","created_at":"2025-12-25T17:18:28.899867-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.20.3","title":"Add org formula examples and tests","description":"Create example organizational formula hierarchy and tests.\n\n## Examples\n\nCreate in .beads/formulas/:\n- acme-base.formula.yaml: Company-wide (security-audit aspect)\n- acme-frontend.formula.yaml: extends acme-base, adds accessibility-audit\n- acme-backend.formula.yaml: extends acme-base, adds sql-injection-scan\n\n## Tests\n\n1. Three-level inheritance resolves correctly\n2. Aspect merge order is correct\n3. exclude-aspects removes parent aspect\n4. Cooking org formula produces expected steps\n5. Error on missing parent formula","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T17:18:20.885418-08:00","updated_at":"2025-12-28T22:34:14.087711-08:00","closed_at":"2025-12-28T22:34:14.087711-08:00","dependencies":[{"issue_id":"gt-8tmz.20.3","depends_on_id":"gt-8tmz.20","type":"parent-child","created_at":"2025-12-25T17:18:20.885943-08:00","created_by":"daemon"},{"issue_id":"gt-8tmz.20.3","depends_on_id":"gt-8tmz.20.2","type":"blocks","created_at":"2025-12-25T17:18:28.993465-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.28","title":"Formula error handling and recovery","description":"Specify how cooking errors are reported and recovered:\n- What happens when extends chain is broken (missing formula)?\n- What happens when aspect pointcut matches nothing?\n- What happens when expansion produces invalid structure?\n- Graceful degradation vs fail-fast semantics\n- Error metadata in cooked protos\n\nDeferred: post-launch polish","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-23T20:06:28.452872-08:00","updated_at":"2025-12-28T22:33:35.36198-08:00","closed_at":"2025-12-28T22:33:35.36198-08:00","dependencies":[{"issue_id":"gt-8tmz.28","depends_on_id":"gt-8tmz","type":"parent-child","created_at":"2025-12-23T20:06:28.453346-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.29","title":"Formula versioning and migration strategy","description":"Define how formula versions are managed:\n- What does the version field mean? Semver? Integer?\n- When a formula changes, what happens to existing protos?\n- Do protos track their source formula version?\n- Migration path: old proto + new formula = ?\n- Backwards compatibility guarantees (if any)\n\nDeferred: post-launch polish","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-23T20:06:45.764277-08:00","updated_at":"2025-12-28T22:33:35.339955-08:00","closed_at":"2025-12-28T22:33:35.339955-08:00","dependencies":[{"issue_id":"gt-8tmz.29","depends_on_id":"gt-8tmz","type":"parent-child","created_at":"2025-12-23T20:06:45.764686-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.30","title":"Proto debugging and inspection tools","description":"Proto debugging and inspection tools.\n\nWith ephemeral protos (gt-4v1eo), this becomes:\n- `bd cook \u003cformula\u003e --dry-run` - preview cooked output without persisting\n- `bd cook \u003cformula\u003e --json` - output proto as JSON for inspection\n- `bd cook \u003cformula\u003e --graph` - visualize step DAG\n\nNo persistent proto beads to inspect - formulas are the source of truth.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-23T20:06:46.58776-08:00","updated_at":"2025-12-28T22:33:35.319337-08:00","closed_at":"2025-12-28T22:33:35.319337-08:00","dependencies":[{"issue_id":"gt-8tmz.30","depends_on_id":"gt-8tmz","type":"parent-child","created_at":"2025-12-23T20:06:46.58989-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.31","title":"Formula validation specification","description":"Complete validation rules for formulas:\n- Required vs optional fields\n- Valid step ID patterns\n- Valid pointcut glob syntax\n- Variable reference validation\n- Compose rule ordering constraints\n- Type-specific validation (workflow vs expansion vs aspect)\n\nDeferred: post-launch polish","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-23T20:06:47.618799-08:00","updated_at":"2025-12-28T22:33:35.297315-08:00","closed_at":"2025-12-28T22:33:35.297315-08:00","dependencies":[{"issue_id":"gt-8tmz.31","depends_on_id":"gt-8tmz","type":"parent-child","created_at":"2025-12-23T20:06:47.620975-08:00","created_by":"daemon"}]} -{"id":"gt-8tmz.37","title":"Support nested expansion formulas","status":"closed","priority":4,"issue_type":"feature","created_at":"2025-12-25T11:50:48.751806-08:00","updated_at":"2025-12-28T22:33:35.274023-08:00","closed_at":"2025-12-28T22:33:35.274023-08:00","dependencies":[{"issue_id":"gt-8tmz.37","depends_on_id":"gt-8tmz","type":"parent-child","created_at":"2025-12-25T11:50:48.75222-08:00","created_by":"daemon"}]} -{"id":"gt-8ul32","title":"Session ended: gt-gastown-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:38:12.384573-08:00","created_by":"gastown/polecats/max","updated_at":"2026-01-04T16:40:22.911333-08:00","closed_at":"2026-01-04T16:40:22.911333-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:38:12-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-max\",\"worker\":\"max\"}"} -{"id":"gt-8uqi7","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T20:51:54.028308-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-03T11:32:45.186108-08:00","closed_at":"2026-01-03T11:32:45.186108-08:00","close_reason":"Session lifecycle events processed","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T20:51:53-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-8wf","title":"Polecat prompting: gt mq submit on completion","description":"Update Polecat CLAUDE.md prompting to:\n\n1. On task completion, run: gt mq submit --issue \u003cid\u003e\n2. This creates a merge-request bead in the queue\n3. Engineer will process it\n\nThe Polecat self-reports completion to the merge queue.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T23:02:39.914724-08:00","updated_at":"2025-12-16T23:02:39.914724-08:00","dependencies":[{"issue_id":"gt-8wf","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.930679-08:00","created_by":"daemon"},{"issue_id":"gt-8wf","depends_on_id":"gt-svi","type":"blocks","created_at":"2025-12-16T23:03:12.950782-08:00","created_by":"daemon"}]} -{"id":"gt-8ws7o","title":"Schematic: Domain-Level Formula Composition","description":"A Schematic is a coordinated set of formulas defining an entire workflow domain.\n\n## Concept\n\nLike an orchestra score to instrument parts - says how formulas fit together.\n\n```toml\n# shiny-engineering.schematic\n[schematic]\nname = \"The Shiny Way\"\ndescription = \"Full engineering workflow from issue to production\"\n\n[formulas]\nplanning = \"@gastown/shiny\"\ndevelopment = \"@gastown/polecat-work\" \nreview = \"@gastown/review\"\nrelease = \"@gastown/release\"\n\n[flow]\ndefault = \"planning \u003e\u003e development \u003e\u003e review \u003e\u003e release\"\n\n[constraints]\nall_code_reviewed = true\ntests_before_deploy = true\n```\n\n## Relationship to Other Concepts\n\n- **Schematic** (workflow dimension) = composition of Formulas\n- **Campaign** (work dimension) = composition of Epics\n- Schematic compiles to Campaign, like Formula compiles to Molecule\n\n## Use Cases\n\n1. Define \"The Shiny Way\" for a team/org\n2. Encode compliance requirements\n3. Standardize workflows across projects\n4. Enable workflow reuse and sharing\n\n## Open Questions\n\n1. File format - TOML? YAML? Extend formula syntax?\n2. Validation - how to verify schematic consistency?\n3. Overrides - can project override org schematic?\n\n## Related\n\n- docs/formula_evolution.md\n- gt-8tmz - molecule algebra\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:00:52.546808-08:00","updated_at":"2025-12-28T22:33:22.305791-08:00","closed_at":"2025-12-28T22:33:22.305791-08:00"} -{"id":"gt-8x383","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:32:26.701475-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.260187-08:00","closed_at":"2026-01-04T16:40:13.260187-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:32:26-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-8y867","title":"Digest: mol-deacon-patrol","description":"Patrol 14: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:31:45.480678-08:00","updated_at":"2026-01-01T04:31:45.480678-08:00","closed_at":"2026-01-01T04:31:45.48064-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8y9ul","title":"Digest: mol-deacon-patrol","description":"Patrol 112: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:11:00.124395-08:00","updated_at":"2026-01-01T14:11:00.124395-08:00","closed_at":"2026-01-01T14:11:00.124353-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8yfre","title":"Digest: mol-deacon-patrol","description":"Patrol 41: final patrol before handoff","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:02:51.678302-08:00","updated_at":"2025-12-31T14:02:51.678302-08:00","closed_at":"2025-12-31T14:02:51.678267-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-8yh9u","title":"Merge: capable-mjtltnm5","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: capable-mjtltnm5\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:48:12.614416-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:31.061416-08:00","closed_at":"2025-12-30T23:12:31.061416-08:00","close_reason":"Branch already merged"} -{"id":"gt-8ynws","title":"Witness Patrol","description":"Per-rig worker monitor patrol loop with progressive nudging.","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-29T14:37:58.362092-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:37:58.362092-08:00"} -{"id":"gt-8ytwa","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:05:32.508134-08:00","updated_at":"2026-01-01T20:05:32.508134-08:00","closed_at":"2026-01-01T20:05:32.508101-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-8zorq","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:55:23.901614-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.480996-08:00","closed_at":"2026-01-05T00:08:31.480996-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:55:23-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-8zy1s","title":"Merge: rictus-mjyxjgwv","description":"branch: polecat/rictus-mjyxjgwv\ntarget: main\nsource_issue: rictus-mjyxjgwv\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T15:27:39.020756-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-03T20:49:53.281071-08:00","closed_at":"2026-01-03T20:49:53.281071-08:00","close_reason":"Already merged to main at 4ca430d6 (PR #82)"} -{"id":"gt-92e9y","title":"Digest: mol-deacon-patrol","description":"Patrol 13: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:18:13.019576-08:00","updated_at":"2025-12-25T19:18:13.019576-08:00","closed_at":"2025-12-25T19:18:13.019527-08:00"} -{"id":"gt-93prf","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All 6 agents healthy, no incidents, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:39:27.562275-08:00","updated_at":"2026-01-01T10:39:27.562275-08:00","closed_at":"2026-01-01T10:39:27.562237-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-95hbj","title":"Digest: mol-deacon-patrol","description":"Patrol 4: MQ cleared (0), all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:41:47.679537-08:00","updated_at":"2026-01-01T23:41:47.679537-08:00","closed_at":"2026-01-01T23:41:47.679505-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-95j13","title":"Add tmux hotkey (C-b f) for gt feed window","description":"## Goal\n\nAdd a tmux hotkey (e.g., C-b f) that jumps to the activity feed window, creating it if it doesn't exist.\n\n## Behavior\n\n1. If 'feed' window exists in current session → switch to it\n2. If 'feed' window doesn't exist → create it with `bd activity --follow`, then switch\n\n## Implementation\n\nAdd to gt's tmux session configuration (similar to SetCrewCycleBindings):\n\n```go\n// C-b f → jump to feed window\ntmux bind-key -T prefix f run-shell \"gt feed --window\"\n```\n\nThe `gt feed --window` command already handles:\n- Creating the window if missing\n- Switching to it if exists\n- Running `bd activity --follow` in the window\n\n## Where to add\n\n- `internal/tmux/tmux.go` - add SetFeedBinding() method\n- Call it from session configuration (ConfigureGasTownSession or similar)\n\n## Testing\n\n1. In tmux: C-b f should open/switch to feed window\n2. Feed window should show streaming activity\n3. C-b n/p should still work to cycle back to other windows\n","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T10:17:20.828835-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T10:27:50.604022-08:00","closed_at":"2025-12-28T10:27:50.604022-08:00"} -{"id":"gt-96jvj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All healthy. 3 rigs, all Witnesses/Refineries responding. No orphans, no cleanup needed, inbox clean.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:07:43.090481-08:00","updated_at":"2026-01-01T06:07:43.090481-08:00","closed_at":"2026-01-01T06:07:43.090445-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-974a8","title":"Digest: mol-deacon-patrol","description":"Patrol 12: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:48:43.293249-08:00","updated_at":"2025-12-25T10:48:43.293249-08:00","closed_at":"2025-12-25T10:48:43.293216-08:00"} -{"id":"gt-976","title":"Add crew lifecycle support to Deacon","description":"Currently crew sessions (like gastown/crew/max, beads/crew/dave) are marked as 'human-managed' and excluded from automated lifecycle.\n\n## Current State\n- `getManager(RoleCrew)` returns `\"human\"` (handoff.go:273)\n- `gt handoff` for crew just prints a message, no lifecycle request sent\n- Crew cannot request automated refresh from Deacon\n\n## Desired State\nCrew members should be able to request lifecycle actions from Deacon:\n- `gt handoff --cycle` sends request to Deacon, which kills/restarts the crew session\n- Useful when: context full, running molecules that need fresh session, automation\n\n## Implementation\n1. Change `getManager(RoleCrew)` to return `\"deacon/\"` (or new crew manager)\n2. Teach Deacon to recognize crew session naming pattern\n3. Add crew to Deacon's respawn loop handling\n4. Test with `gt nudge` for reliable message delivery\n\n## Use Case\nRunning a molecule (e.g., version-bump) and discovering mid-workflow that a fresh session is needed. Agent should be able to request refresh automatically rather than requiring human intervention.\n\n## Related\n- gt nudge: reliable message delivery to Claude sessions\n- bd mol bond: molecule instantiation (coming in beads)","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-20T17:19:46.854829-08:00","updated_at":"2025-12-20T17:19:46.854829-08:00"} -{"id":"gt-97h2h","title":"Digest: mol-deacon-patrol","description":"Patrol 4: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:03:54.499154-08:00","updated_at":"2025-12-31T18:03:54.499154-08:00","closed_at":"2025-12-31T18:03:54.499118-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-97u9y","title":"Digest: mol-deacon-patrol","description":"Patrol 72: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:02:41.013651-08:00","updated_at":"2025-12-31T15:02:41.013651-08:00","closed_at":"2025-12-31T15:02:41.013618-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-992e7","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy, 12 polecats, nudged gastown (active work)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:22:17.714106-08:00","updated_at":"2026-01-01T20:22:17.714106-08:00","closed_at":"2026-01-01T20:22:17.714069-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-9a1bx","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:46:54.206943-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.559225-08:00","closed_at":"2026-01-05T19:44:18.559225-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:46:49-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-9ahbu","title":"Merge: nux-1767073376184","description":"branch: polecat/nux-1767073376184\ntarget: main\nsource_issue: nux-1767073376184\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T21:58:45.468878-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T23:32:37.271078-08:00","closed_at":"2025-12-29T23:32:37.271078-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-9ar8x","title":"Polecat identity confusion leads to direct main commits","description":"When polecats spawn without proper identity (due to gt-si6am and gt-y41ep):\n1. They think they're mayor\n2. They may commit from wrong directory (mayor/rig instead of polecats/\u003cname\u003e)\n3. Work goes directly to main, bypassing merge queue\n\nObserved: slit pushed 'gt polecat recycle' directly to main instead of its branch\n\nRoot cause: \n- gt-si6am: Wrong CLAUDE.md template (says 'Mayor Rig Context')\n- gt-y41ep: Env vars not exported (falls back to mayor detection)\n\nImpact: CRITICAL - merge queue entirely bypassed, no refinery review","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-12-28T14:18:37.061075-08:00","created_by":"mayor","updated_at":"2025-12-28T15:34:17.811462-08:00","closed_at":"2025-12-28T15:34:17.811462-08:00","dependencies":[{"issue_id":"gt-9ar8x","depends_on_id":"gt-si6am","type":"blocks","created_at":"2025-12-28T14:18:44.032422-08:00","created_by":"daemon"},{"issue_id":"gt-9ar8x","depends_on_id":"gt-y41ep","type":"blocks","created_at":"2025-12-28T14:18:44.060806-08:00","created_by":"daemon"}]} -{"id":"gt-9arar","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:06:01.756927-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.737753-08:00","closed_at":"2026-01-05T00:08:31.737753-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:06:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-9bm3j","title":"Merge: gt-4u49x","description":"branch: polecat/furiosa-mjxn8bl8\ntarget: main\nsource_issue: gt-4u49x\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2026-01-02T18:06:26.652851-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T18:27:17.656853-08:00","closed_at":"2026-01-02T18:27:17.656853-08:00","close_reason":"Merged to main at efd9434e"} -{"id":"gt-9de2h","title":"Digest: mol-deacon-patrol","description":"Patrol 154 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:06:43.880029-08:00","updated_at":"2025-12-31T16:06:43.880029-08:00","closed_at":"2025-12-31T16:06:43.879999-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-9f4ba","title":"Refinery Engineer placeholder code references tombstoned gt-3x1.2","description":"The Refinery Engineer module has placeholder code that references gt-3x1.2, which is now tombstoned (gt-3x1 epic was superseded).\n\n## Affected code:\n\n1. **internal/refinery/engineer.go:203-225** - ProcessMR() says \"This is a placeholder that will be fully implemented in gt-3x1.2\" and returns failure with \"ProcessMR not fully implemented (see gt-3x1.2)\"\n\n2. **internal/refinery/engineer.go:279-291** - handleFailure() says \"This is a placeholder that will be fully implemented in gt-3x1.4\"\n\n3. **internal/refinery/engineer.go:307-312** - ProcessMRFromQueue() returns \"ProcessMRFromQueue not fully implemented (see gt-3x1.2)\"\n\n## Context:\ngt-3x1 was about updating Refinery to use Beads merge queue. The approach may have changed. Need to either:\n- Implement the actual merge logic (new issue)\n- Remove the placeholder code if not needed\n- Update references to point to current strategy\n\n## Related:\n- gt-3x1 (tombstone) - original epic\n- Current MQ implementation may have superseded this","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T22:23:00.434248-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:28:32.077691-08:00","closed_at":"2025-12-30T22:28:32.077691-08:00","close_reason":"Removed stale gt-3x1.x references. Filed gt-pnv61 for implementing actual merge logic."} -{"id":"gt-9g6md","title":"Merge: nux-1767082300311","description":"branch: polecat/nux-1767082300311\ntarget: main\nsource_issue: nux-1767082300311\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:18:32.957664-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.277856-08:00","closed_at":"2025-12-30T01:01:04.277856-08:00","close_reason":"Already merged to main"} -{"id":"gt-9gm9n","title":"gt rig dock/undock commands","description":"Implement Level 2 (global/persistent) rig control.\n\nCommands:\n- gt rig dock \u003crig\u003e # Set status:docked label on rig bead\n- gt rig undock \u003crig\u003e # Remove label\n\nBehavior:\n- Stops witness/refinery if running\n- Sets label on rig identity bead\n- Syncs via git (all clones see it)\n- Permanent until explicitly undocked\n\nOutput:\n gt rig dock gastown\n ✓ Rig gastown docked (global)\n Label added: status:docked\n Witness stopped\n Refinery stopped\n Run 'bd sync' to propagate to other clones","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:47.647394-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:47.647394-08:00","dependencies":[{"issue_id":"gt-9gm9n","depends_on_id":"gt-emh1c","type":"blocks","created_at":"2026-01-06T17:37:07.273538-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-9guv2","title":"Messaging Channels: Unified list/queue/announce/nudge system","description":"Implement the full messaging channel system for Gas Town.\n\nTWO PARALLEL SYSTEMS:\n1. Durable (polling): mail - list, queue, announce\n2. Real-time (ephemeral): nudge - channels\n\nARCHITECTURE:\n- Config: ~/gt/config/messaging.json (town-level)\n- Messages: beads (.beads/issues.jsonl with type=message)\n\nCHANNEL TYPES:\n- list:name - Fan-out, each recipient gets copy (DONE)\n- queue:name - Claim-based, exactly-once processing (gt-02431)\n- announce:name - Bulletin board, read-only (gt-cqvgt)\n- nudge channel:name - Real-time fan-out (gt-3txyh)\n\nPRIORITY ORDER:\n1. Queues - solves real polecat cleanup race condition\n2. Nudge channels - gt broadcast mostly works but channels add precision\n3. Announces - nice-to-have bulletin boards","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-30T18:10:03.23413-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T18:10:03.23413-08:00"} -{"id":"gt-9gwc4","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:46:57.944446-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.568922-08:00","closed_at":"2026-01-05T00:08:31.568922-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:46:57-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-9hfky","title":"Merge: toast-1767140378007","description":"branch: polecat/toast-1767140378007\ntarget: main\nsource_issue: toast-1767140378007\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:28:18.45737-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T18:23:22.151001-08:00","closed_at":"2025-12-30T18:23:22.151001-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-9hfq3","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:50:33.75421-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.041276-08:00","closed_at":"2026-01-04T16:41:26.041276-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:50:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-9hwkn","title":"Messaging infrastructure: lists, queues, channels","description":"Multi-recipient and broadcast messaging for Gas Town.\n\n## Phases\n\n**Phase 1 - Foundation**: Config directory (gt-i6jvc)\n**Phase 1 - Core**: list:, queue:, @group (requires agent-as-bead for @group)\n**Phase 2 - Channels**: announce:, #channel, gt channel publish\n\n## Addressing Syntax\n\n| Prefix | Resolution | Storage | Claim? |\n|--------|------------|---------|--------|\n| `@group` | Dynamic (bead queries) | Fan-out (N copies) | No |\n| `list:name` | Static config | Fan-out (N copies) | No |\n| `queue:name` | Static config | Shared (1 copy) | Yes |\n| `announce:name` | Static config | Shared (1 copy) | No |\n| `#channel` | Dynamic (tmux) | None (ephemeral) | No |\n\n## Alignment with Agent-as-Bead\n\n@group resolution now uses agent bead queries:\n- @rig/gastown → bd list --type=agent --rig=gastown\n- @witnesses → bd list --type=agent --role_type=witness\n\nThis replaces the originally planned filesystem scanner (gt-xo05b, now closed).\n\n## Independent Work\n\nConfig-based features (list:, queue:, announce:) can proceed without agent identity.\nOnly @group requires the agent schema from Pillar 1.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-26T14:51:18.855183-08:00","updated_at":"2026-01-04T23:40:58.005657-08:00","closed_at":"2026-01-04T23:40:58.005657-08:00","close_reason":"Cleanup: stale molecule"} -{"id":"gt-9hz8p","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:13:22.575615-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.607229-08:00","closed_at":"2026-01-04T16:40:13.607229-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:13:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-9ibez","title":"Digest: mol-deacon-patrol","description":"Patrol 4: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:44:07.785738-08:00","updated_at":"2026-01-01T10:44:07.785738-08:00","closed_at":"2026-01-01T10:44:07.785703-08:00","dependencies":[{"issue_id":"gt-9ibez","depends_on_id":"gt-eph-8a33","type":"parent-child","created_at":"2026-01-01T10:44:07.786988-08:00","created_by":"deacon"}]} -{"id":"gt-9iojp","title":"Swarm: E2E Swarm Test Epic","description":"Swarm molecule orchestrating epic gt-1tpts.\n\nEpic: gt-1tpts\nCoordinator: ","status":"closed","priority":3,"issue_type":"molecule","created_at":"2025-12-29T17:59:49.255101-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T18:02:47.855278-08:00","closed_at":"2025-12-29T18:02:47.855278-08:00","close_reason":"E2E Test: All tasks complete, swarm landed","dependencies":[{"issue_id":"gt-9iojp","depends_on_id":"gt-1tpts","type":"relates-to","created_at":"2025-12-29T17:59:49.25603-08:00","created_by":"gastown/polecats/rictus"}],"mol_type":"swarm"} -{"id":"gt-9j4a8","title":"Merge: valkyrie-mjw71b7u","description":"branch: polecat/valkyrie-mjw71b7u\ntarget: main\nsource_issue: valkyrie-mjw71b7u\nrig: gastown\nagent_bead: gt-gastown-polecat-valkyrie","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T17:31:54.984761-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2026-01-01T19:55:59.970646-08:00","closed_at":"2026-01-01T19:55:59.970646-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-9j9","title":"CLI: worker status reporting commands","description":"Worker status reporting CLI for polecats to report progress.\n\n## Commands\n\n### gt worker started\n```\ngt worker started \u003cissue-id\u003e [-m MESSAGE]\n```\nReports work started on issue.\n\n### gt worker progress\n```\ngt worker progress \u003cissue-id\u003e \u003c0-100\u003e [-m MESSAGE]\n```\nReports percentage complete.\n\n### gt worker blocked\n```\ngt worker blocked \u003cissue-id\u003e \u003creason\u003e [-m MESSAGE]\n```\nReports blocked status with reason.\n\n### gt worker completed\n```\ngt worker completed \u003cissue-id\u003e [-m MESSAGE]\n```\nReports task completion.\n\n### gt worker failed\n```\ngt worker failed \u003cissue-id\u003e \u003creason\u003e [-m MESSAGE]\n```\nReports task failure.\n\n## Implementation\nEach command sends mail to refinery with structured content:\n```go\ntype WorkerStatusReport struct {\n IssueID string\n Status string // started|progress|blocked|completed|failed\n Progress int // 0-100 for progress\n Reason string // for blocked/failed\n Message string // optional detail\n ReportedAt time.Time\n}\n```\n\n## Message Format\nSubject: \"[STATUS] \u003cissue-id\u003e: \u003cstatus\u003e\"\nBody: JSON-encoded WorkerStatusReport\n\n## Default Recipient\n```go\n// Determine from context\nfunc getDefaultRecipient() string {\n rig := os.Getenv(\"GT_RIG\")\n if rig != \"\" {\n return rig + \"/refinery\"\n }\n return \"refinery/\"\n}\n```\n\n## New File\ninternal/cmd/worker.go\n\n## PGT Reference\ngastown-py/src/gastown/cli/worker_cmd.py\n\n## Acceptance Criteria\n- [ ] All 5 commands implemented\n- [ ] Status sent as mail to refinery\n- [ ] Structured JSON body for parsing\n- [ ] Works from polecat session context","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:52.795695-08:00","updated_at":"2025-12-16T16:05:26.715967-08:00"} -{"id":"gt-9je6q","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:54:07.977275-08:00","updated_at":"2025-12-25T19:54:07.977275-08:00","closed_at":"2025-12-25T19:54:07.977222-08:00"} -{"id":"gt-9jhwq","title":"Digest: mol-deacon-patrol","description":"Patrol 4: 3 polecats working, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:32:43.763741-08:00","updated_at":"2025-12-29T22:32:43.763741-08:00","closed_at":"2025-12-29T22:32:43.763714-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-9kj0z","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all clear, systems healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:12:43.355741-08:00","updated_at":"2025-12-28T08:12:43.355741-08:00","closed_at":"2025-12-28T08:12:43.355697-08:00"} -{"id":"gt-9kp3t","title":"Day 1.4b: Create Deacon agent bead","description":"Create gt-deacon agent bead for the Deacon (daemon beacon).\n\nThe Deacon is a separate Claude Code agent from Mayor:\n- Receives the ONLY mechanical daemon heartbeats in the system\n- Runs town plugins, cleanup, and monitoring\n- Has own top-level directory: ~/gt/deacon/\n- No rig preassignment (town-level, like Mayor)\n- role_type: deacon\n\nAgent bead structure:\n```yaml\nid: gt-deacon\ntype: agent\nentity_platform: gastown\nentity_org: steveyegge\nentity_id: deacon\nhook_bead: null # or current patrol wisp\nrole_bead: gt-deacon-role\nstate: idle\nrole_type: deacon\n```\n\nMust be created alongside mayor, witness, refinery agent beads.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T22:01:41.413071-08:00","created_by":"mayor","updated_at":"2025-12-28T00:46:43.04993-08:00","closed_at":"2025-12-28T00:46:43.04993-08:00","dependencies":[{"issue_id":"gt-9kp3t","depends_on_id":"gt-v2gkv","type":"blocks","created_at":"2025-12-27T22:02:45.047853-08:00","created_by":"daemon"},{"issue_id":"gt-9kp3t","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T23:28:03.415489-08:00","created_by":"daemon"}]} -{"id":"gt-9m9g","title":"Refinery startup: Use Claude agent instead of foreground mode","description":"WIP found in stash: Refactor refinery startup to spawn Claude as the refinery agent rather than using gt refinery start --foreground.\n\nChanges needed:\n- Use refineryDir (refinery/rig) as working directory\n- Start Claude with --dangerously-skip-permissions \n- Wait for shell ready, then Claude ready\n- Send gt prime, then refinery startup prompt\n- Remove foreground mode complexity\n\nRelated: gt-n7z7 (refinery --foreground race condition bug)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T13:35:04.300493-08:00","updated_at":"2025-12-20T13:35:04.300493-08:00"} -{"id":"gt-9mzd","title":"Refinery not processing merge-requests - stale MRs accumulating","description":"Discovered 15 stale merge-request issues in beads rig that were never processed by the refinery. These appear to be from polecat branches that completed work but the refinery didn't pick up the merge-requests.\n\nClosed issues:\n- bd-r06v, bd-bhg7, bd-754r, bd-fcl1, bd-3zzh\n- bd-bijf, bd-5rj1, bd-kptp, bd-rdzk, bd-ibl9\n- bd-gfo3, bd-aq3s, bd-x2bd, bd-s1pz, bd-h27p\n\nNeed to investigate:\n1. Why refinery isn't picking up merge-requests\n2. Whether the polecat branches have valid work to merge\n3. Add monitoring/alerting for stale MRs","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-23T19:12:08.629863-08:00","updated_at":"2025-12-30T00:06:49.179944-08:00","closed_at":"2025-12-30T00:06:49.179944-08:00","close_reason":"Fixed: gt done and mq submit now write to mrqueue. Added gt mq migrate for stale MR recovery."} -{"id":"gt-9n6i3","title":"Digest: mol-deacon-patrol","description":"Patrol 19: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:11:18.273683-08:00","updated_at":"2025-12-28T03:11:18.273683-08:00","closed_at":"2025-12-28T03:11:18.273651-08:00"} -{"id":"gt-9o9s","title":"gt mail inbox shows wrong identity when run from deacon directory","description":"When running 'gt mail inbox' from ~/gt/deacon/, it shows 'Inbox: mayor/' instead of 'Inbox: deacon/'. The role detection works (deacon checks in correctly), but mail identity detection is broken.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-23T13:29:11.801311-08:00","updated_at":"2025-12-28T22:37:43.633524-08:00","closed_at":"2025-12-28T22:37:43.633524-08:00"} -{"id":"gt-9oca7","title":"Refactor: Extract mail notification builder pattern","description":"refinery/manager.go has three nearly identical notification functions:\n- notifyWorkerConflict() (lines 610-628)\n- notifyWorkerMerged() (lines 631-644)\n- notifyWorkerRejected() (lines 787-804)\n\nExtract a fluent builder:\n```go\ntype NotificationBuilder struct { ... }\n\nfunc (m *Manager) NotifyWorker(worker string) *NotificationBuilder\n\n// Usage:\nm.NotifyWorker(mr.Worker).\n Subject(\"Merge conflict - rebase required\").\n Priority(mail.PriorityHigh).\n Body(fmt.Sprintf(...)).\n Send()\n```","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:46:15.173578-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-04T23:46:15.173578-08:00"} -{"id":"gt-9od85","title":"Digest: mol-deacon-patrol","description":"Patrol 16: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:33:18.54328-08:00","updated_at":"2026-01-01T04:33:18.54328-08:00","closed_at":"2026-01-01T04:33:18.543238-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-9pmwc","title":"Digest: mol-deacon-patrol","description":"Patrol 148 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:02:35.023236-08:00","updated_at":"2025-12-31T16:02:35.023236-08:00","closed_at":"2025-12-31T16:02:35.02319-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-9rhpk","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:13:53.530539-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:13.594511-08:00","closed_at":"2026-01-04T16:40:13.594511-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:13:53-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-9rmm","title":"Merge: gt-a95","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-a95\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:53.973816-08:00","updated_at":"2025-12-19T19:13:27.736445-08:00","closed_at":"2025-12-19T17:48:09.608699-08:00"} -{"id":"gt-9s4zc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:23:41.906515-08:00","updated_at":"2026-01-01T07:23:41.906515-08:00","closed_at":"2026-01-01T07:23:41.906475-08:00"} -{"id":"gt-9t7rv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 22 complete. All 3 rigs healthy. No orphans, gates, convoys, or plugins. Quick cycle.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:26:15.275508-08:00","updated_at":"2026-01-01T19:26:15.275508-08:00","closed_at":"2026-01-01T19:26:15.275462-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-9tsym","title":"Review PR #93: deploy SessionStart hooks in gt install","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/bullet","created_at":"2026-01-04T10:53:59.783699-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:56:03.091289-08:00","closed_at":"2026-01-04T10:56:03.091289-08:00","close_reason":"PR #93 reviewed and approved"} -{"id":"gt-9ue33","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:25:49.026075-08:00","updated_at":"2026-01-01T10:25:49.026075-08:00","closed_at":"2026-01-01T10:25:49.026035-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-9utjl","title":"Digest: mol-deacon-patrol","description":"Patrol 153 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:06:02.468013-08:00","updated_at":"2025-12-31T16:06:02.468013-08:00","closed_at":"2025-12-31T16:06:02.467975-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-9uxr","title":"Critical packages lack test coverage","description":"Several packages have no test files:\n- internal/lock/ - Core identity locking (212 lines UNTESTED)\n- internal/witness/ - Worker monitoring\n- internal/mrqueue/ - MR queue management\n- internal/claude/ - Claude integration\n- internal/style/ - Terminal styling\n- internal/constants/ - Constants\n\nPriority for testing:\n1. lock/ - prevents duplicate agents, critical for correctness\n2. witness/ - agent lifecycle management\n3. mrqueue/ - merge request processing\n\nOverall: 37 test files for 160 Go files (23% by file count)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-24T12:51:01.154427-08:00","updated_at":"2025-12-24T12:51:01.154427-08:00","dependencies":[{"issue_id":"gt-9uxr","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:07.558885-08:00","created_by":"daemon"}]} -{"id":"gt-9v52","title":"gt sling reports hook occupied but bd hook shows empty","description":"gt sling thinks a hook is occupied when bd hook shows it empty. Example: bd hook --agent beads/crew/dave shows (empty), but gt sling bd-hobo beads/crew/dave says 'hook already occupied by bd-ul59'. They should use the same source of truth (beads database pinned field).","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-24T20:01:42.105132-08:00","updated_at":"2025-12-29T23:42:43.552586-08:00","closed_at":"2025-12-29T23:42:43.552586-08:00","close_reason":"Fixed by using proper bd commands (bd agent state, bd slot set/clear) instead of embedding in description text. Now gastown and beads use the same SQLite columns for hook_bead and agent_state."} -{"id":"gt-9v8br","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:30:36.431989-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:40:22.761679-08:00","closed_at":"2026-01-04T16:40:22.761679-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:30:36-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-9w1b2","title":"Merge: dementus-1767073385126","description":"branch: polecat/dementus-1767073385126\ntarget: main\nsource_issue: dementus-1767073385126\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T21:56:54.773673-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-29T23:32:37.279586-08:00","closed_at":"2025-12-29T23:32:37.279586-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-9wi9n","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:08:10.965644-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.37774-08:00","closed_at":"2026-01-05T00:08:31.37774-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:08:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-9wv0","title":"gt spawn should verify daemon is running for polecat triggering","description":"gt spawn notifies the Deacon (via mail) that a polecat was started, expecting the Deacon to trigger it once Claude is ready. But if the daemon isn't running, the mail sits unread and the polecat never gets triggered.\n\n## Current Behavior\n1. gt spawn starts polecat session\n2. gt spawn sends POLECAT_STARTED to deacon/\n3. (assumes daemon will trigger polecat)\n\n## Problem\nIf gt daemon isn't running, step 3 never happens and polecat sits at prompt.\n\n## Solution\nIn gt spawn, after session start:\n1. Check if daemon is running (gt daemon status)\n2. If not running, either:\n a. Start daemon: gt daemon start\n b. Or warn user: 'Daemon not running, polecat may not auto-start'\n\n## Alternative\nThe user can manually trigger with gt nudge, but automated flow should work.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:03:03.71521-08:00","updated_at":"2025-12-23T01:03:03.71521-08:00","dependencies":[{"issue_id":"gt-9wv0","depends_on_id":"gt-bjft","type":"blocks","created_at":"2025-12-23T01:03:12.187224-08:00","created_by":"daemon"}]} -{"id":"gt-9xhbf","title":"Review PR #140: docs(mayor) Add Polecat Operations section","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-05T21:39:18.283483-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:39:18.283483-08:00"} -{"id":"gt-9yjrz","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:13:24.941925-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.461083-08:00","closed_at":"2026-01-05T19:44:18.461083-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:13:19-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-9yz70","title":"mol-sync-workspace: Fix 'commits ahead' in report for crew on main","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T19:11:04.945774-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-01T19:03:22.733094-08:00","closed_at":"2026-01-01T19:03:22.733094-08:00","close_reason":"Updated mol-sync-workspace generate-report step to use 'Unpushed commits' instead of 'Commits ahead of main' for crew workers on main branch."} -{"id":"gt-9z88q","title":"Session ended: gt-gastown-mediocre","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:20:30.972198-08:00","created_by":"gastown/polecats/mediocre","updated_at":"2026-01-05T19:44:41.847225-08:00","closed_at":"2026-01-05T19:44:41.847225-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/mediocre","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:20:30-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-mediocre\",\"worker\":\"mediocre\"}"} -{"id":"gt-9zp8t","title":"Digest: mol-deacon-patrol","description":"Patrol 15: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T16:28:55.536366-08:00","updated_at":"2025-12-25T16:28:55.536366-08:00","closed_at":"2025-12-25T16:28:55.536331-08:00"} -{"id":"gt-9zscl","title":"Merge: gt-lynar","description":"branch: polecat/furiosa-mjxeatgb\ntarget: main\nsource_issue: gt-lynar\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:42:21.772197-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T13:48:40.858489-08:00","closed_at":"2026-01-02T13:48:40.858489-08:00","close_reason":"Merged to main"} -{"id":"gt-9zvz6","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:36:47.793142-08:00","updated_at":"2025-12-31T23:36:47.793142-08:00","closed_at":"2025-12-31T23:36:47.793102-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-a02fj","title":"Pre-Launch Code Review Swarm","description":"# Pre-Launch Code Review Swarm\n\nGas Town launched 3 days ago. We've been firefighting bugs but haven't done a thorough\ncode review. With increased scrutiny coming, we need a comprehensive audit.\n\n## Scope\n\n~100k lines of Go across 302 files and 42 internal packages.\n\n## Review Areas\n\n### Heresies (Core Principle Violations)\n- **Git as blockchain** - Are we treating git properly as our ledger?\n- **Federation not global consensus** - Are we avoiding centralization?\n- **Human-readable** - Is everything auditable via Markdown?\n- **Propulsion principle** - Do agents execute immediately when work arrives?\n- **Beads as truth** - Is state tracked in beads, not ephemeral places?\n\n### Code Quality\n- **Code smells** - Long functions, god objects, primitive obsession, etc.\n- **Duplicated code** - DRY violations, copy-paste patterns\n- **Missing abstractions** - Fiddly replicated logic that should be consolidated\n- **Dead code** - Unused functions, unreachable branches\n\n### Go Idioms\n- **Error handling** - Consistent patterns, proper wrapping\n- **Interface design** - Small interfaces, dependency injection\n- **Package organization** - Clear boundaries, minimal coupling\n- **Naming conventions** - Idiomatic Go naming\n\n### Performance\n- **Inefficient patterns** - N+1 queries, unnecessary allocations\n- **Concurrency** - Proper goroutine/channel usage\n- **Resource leaks** - Unclosed handles, goroutine leaks\n\n### Security\n- **Input validation** - Especially for shell commands\n- **Path traversal** - File operations with user input\n- **Secret handling** - No hardcoded credentials\n\n## Deliverables\n\nEach review task should produce:\n1. List of issues found with file:line references\n2. Severity rating (critical/high/medium/low)\n3. Suggested fixes where appropriate\n4. New beads for anything requiring follow-up work\n\n## Success Criteria\n\n- All major packages reviewed\n- Critical issues identified and filed\n- Code quality baseline established","status":"closed","priority":1,"issue_type":"epic","created_at":"2026-01-04T23:40:33.596228-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:17:32.090251-08:00","closed_at":"2026-01-05T21:17:32.090251-08:00","close_reason":"All 11 review tasks completed by polecat swarm"} -{"id":"gt-a02fj.1","title":"Review: Agent Lifecycle Packages","description":"# Review Agent Lifecycle Packages\n\n## Packages\n- internal/polecat/\n- internal/witness/\n- internal/refinery/\n- internal/deacon/\n\n## Focus Areas\n\n1. **Code Smells**\n - Long functions (\u003e50 lines)\n - God objects with too many responsibilities\n - Primitive obsession (raw strings instead of types)\n\n2. **Duplicated Code**\n - Similar patterns across lifecycle managers\n - Copy-paste between polecat/witness/refinery\n\n3. **Missing Abstractions**\n - Common patterns that should be extracted\n - Repeated error handling logic\n\n4. **Propulsion Principle**\n - Do agents start immediately when work arrives?\n - Are there unnecessary delays or confirmations?\n\n## Deliverables\n- List of issues with file:line references\n- Suggested refactoring opportunities\n- New beads for follow-up work","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/buzzard","created_at":"2026-01-04T23:41:02.00286-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:46:43.964508-08:00","closed_at":"2026-01-04T23:46:43.964508-08:00","close_reason":"Review complete. Created 7 follow-up beads for identified refactoring opportunities.","dependencies":[{"issue_id":"gt-a02fj.1","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:02.00526-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.10","title":"Review: Go Idioms and Elegance","description":"Audit Go best practices and idiomatic code\n\n## Scope\nCodebase-wide patterns\n\n## Focus Areas\n\n1. **Error Handling**\n - Consistent error wrapping with context\n - No swallowed errors\n - Sentinel errors where appropriate\n\n2. **Interface Design**\n - Accept interfaces, return structs\n - Small, focused interfaces\n - No interface pollution\n\n3. **Naming**\n - Exported names start with capital\n - Receiver names consistent\n - Package names singular and lowercase\n\n4. **Concurrency**\n - Context propagation\n - Proper sync.WaitGroup usage\n - No goroutine leaks\n\n5. **Resource Management**\n - defer for cleanup\n - Proper Close() calls\n - No leaked file handles\n\n## Deliverables\n- Idiom violations list\n- Pattern recommendations\n- Style guide additions","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/wraith","created_at":"2026-01-04T23:41:55.847293-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:51:15.761806-08:00","closed_at":"2026-01-04T23:51:15.761806-08:00","close_reason":"Completed Go idioms review. Report at docs/code-review-go-idioms.md","dependencies":[{"issue_id":"gt-a02fj.10","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:55.847784-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.11","title":"Review: Security Sweep","description":"Security-focused code review\n\n## Scope\nEntire codebase with focus on external inputs\n\n## Focus Areas\n\n1. **Command Injection**\n - All exec.Command calls\n - Shell escaping\n - User input in commands\n\n2. **Path Traversal**\n - File operations with user paths\n - Symlink following\n - Directory escapes\n\n3. **Secrets**\n - No hardcoded credentials\n - Proper secret handling\n - Env var usage\n\n4. **Input Validation**\n - All external inputs validated\n - Mail content sanitization\n - Git ref validation\n\n5. **OWASP Top 10**\n - Injection flaws\n - Broken authentication patterns\n - Sensitive data exposure\n\n## Deliverables\n- Security issue inventory with severity\n- Immediate fixes required\n- Security hardening recommendations","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/witness","created_at":"2026-01-04T23:41:58.459671-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:51:04.140407-08:00","closed_at":"2026-01-04T23:51:04.140407-08:00","close_reason":"Polecat completed review - closing to complete convoy","dependencies":[{"issue_id":"gt-a02fj.11","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:58.460157-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.2","title":"Review: Beads/State Management","description":"# Review Beads and State Management\n\n## Packages\n- internal/beads/\n- internal/activity/\n- internal/wisp/\n\n## Focus Areas\n\n1. **Git as Blockchain Principle**\n - Is git being used properly as the source of truth?\n - Are there places bypassing git for state?\n\n2. **Schema Consistency**\n - Column names, field types\n - Migration handling\n\n3. **Performance**\n - Query efficiency\n - Caching patterns\n - N+1 query problems\n\n4. **Error Handling**\n - Database errors properly wrapped\n - Transaction handling\n\n## Deliverables\n- Schema issues\n- Performance concerns\n- Principle violations","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/gastown","created_at":"2026-01-04T23:41:05.003495-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:45:38.093673-08:00","closed_at":"2026-01-04T23:45:38.093673-08:00","close_reason":"Review complete. Found: 1 principle violation (audit.log bypasses git), 0 schema issues, 3 N+1 query performance concerns, generally solid error handling. See session for detailed analysis.","dependencies":[{"issue_id":"gt-a02fj.2","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:05.004-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.3","title":"Review: Heresies in Core Command Layer","description":"Review internal/cmd for Core Principle Violations\n\n## Focus Areas\n\n1. **Propulsion Principle Violations**\n - Are there places where agents wait for confirmation instead of executing?\n - Check startup flows, hook handling, mail processing\n\n2. **Beads as Truth**\n - Is state stored in beads or in ephemeral places (files, memory)?\n - Check for state that should be in beads but is not\n\n3. **Human-Readable**\n - Are outputs clear and auditable?\n - Check for opaque error messages or unclear state\n\n## Packages to Review\n- internal/cmd/ (all files)\n\n## Deliverables\n- List of heresy violations with file:line\n- Severity rating for each\n- Recommendations for alignment with principles","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/bullet-farmer","created_at":"2026-01-04T23:41:17.466986-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:46:22.279852-08:00","closed_at":"2026-01-04T23:46:22.279852-08:00","close_reason":"Review complete: internal/cmd/ is healthy, no heresies found across all three principles","dependencies":[{"issue_id":"gt-a02fj.3","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:17.469129-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.4","title":"Review: Coordination and Communication","description":"Review mail, protocol, session, and connection packages\n\n## Packages\n- internal/mail/\n- internal/protocol/\n- internal/session/\n- internal/connection/\n\n## Focus Areas\n\n1. **Code Duplication**\n - Similar patterns in message handling\n - Repeated connection logic\n\n2. **Error Handling**\n - Network error recovery\n - Timeout handling\n\n3. **Interface Design**\n - Are interfaces minimal and focused?\n - Dependency injection patterns\n\n4. **Security**\n - Input validation on messages\n - No command injection vectors\n\n## Deliverables\n- Issues list with file:line\n- Security concerns flagged\n- Abstraction opportunities","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/citadel","created_at":"2026-01-04T23:41:19.072468-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:49:00.075012-08:00","closed_at":"2026-01-04T23:49:00.075012-08:00","close_reason":"Code review complete. Filed 11 issues covering code duplication (4), security (1), error handling (3), interface design (2), and code smells (1).","dependencies":[{"issue_id":"gt-a02fj.4","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:19.072996-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.5","title":"Review: Work Management (swarm, convoy, formula)","description":"Review work dispatch and orchestration\n\n## Packages\n- internal/swarm/\n- internal/convoy/\n- internal/formula/\n- internal/mrqueue/\n- internal/mq/\n\n## Focus Areas\n\n1. **Complexity**\n - Long functions, deeply nested logic\n - State machine clarity\n\n2. **Concurrency**\n - Goroutine lifecycle management\n - Channel usage patterns\n - Race conditions\n\n3. **Missing Abstractions**\n - Common dispatch patterns\n - Repeated queue handling\n\n4. **Performance**\n - Unnecessary allocations\n - Efficient iteration\n\n## Deliverables\n- Complexity hotspots\n- Concurrency concerns\n- Refactoring suggestions","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/wasteland","created_at":"2026-01-04T23:41:20.618946-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:48:25.589155-08:00","closed_at":"2026-01-04T23:48:25.589155-08:00","close_reason":"Review complete: identified 4 complexity hotspots, 3 concurrency concerns, 4 missing abstractions, 4 performance observations. Key issues: race condition in mrqueue.Claim(), hardcoded sleep in ExecuteLanding. convoy/ package does not exist.","dependencies":[{"issue_id":"gt-a02fj.5","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:20.621171-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.6","title":"Review: Git and Workspace Management","description":"Review git operations and workspace handling\n\n## Packages\n- internal/git/\n- internal/workspace/\n- internal/rig/\n- internal/crew/\n\n## Focus Areas\n\n1. **Security**\n - Path traversal vulnerabilities\n - Command injection in git operations\n - Sanitization of user-provided paths\n\n2. **Error Handling**\n - Git command failures\n - Workspace state recovery\n\n3. **Go Idioms**\n - Proper use of os/exec\n - Context cancellation\n - Resource cleanup\n\n4. **Duplication**\n - Similar git operations across packages\n - Repeated path manipulation\n\n## Deliverables\n- Security audit results\n- Error handling gaps\n- Consolidation opportunities","notes":"## Review Complete\n\n### Security Audit (2 P2 issues filed)\n- gt-wzxwm: Path traversal in crew name handling\n- gt-l1xsa: Unvalidated config values passed to exec.Command\n\n### Error Handling Gaps (1 issue filed)\n- gt-rsnj9: Silent error swallowing in discovery/cleanup\n\n### Consolidation Opportunities (2 issues filed)\n- gt-0cu3o: Clone-with-reference-fallback pattern duplication\n- gt-nqq5k: bd command wrapper package needed\n\n### Go Idioms (2 issues filed)\n- gt-xhjss: Missing context.Context in git package\n- gt-0vvo1: Panic anti-pattern in MustGetTownName\n\nTotal: 7 issues filed from this review","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/fury","created_at":"2026-01-04T23:41:34.59597-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:48:50.758444-08:00","closed_at":"2026-01-04T23:48:50.758444-08:00","close_reason":"Review complete. Filed 7 issues: 2 security (P2), 1 error handling (P3), 2 refactoring (P3-P4), 2 Go idioms (P3-P4).","dependencies":[{"issue_id":"gt-a02fj.6","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:34.596407-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.7","title":"Review: UI and Presentation Layer","description":"Review user-facing output and display\n\n## Packages\n- internal/tmux/\n- internal/tui/\n- internal/web/\n- internal/style/\n- internal/templates/\n- internal/feed/\n\n## Focus Areas\n\n1. **Consistency**\n - Output formatting patterns\n - Color/style usage\n\n2. **Error Messages**\n - Clear, actionable error text\n - Helpful suggestions\n\n3. **Code Duplication**\n - Similar display logic\n - Repeated template patterns\n\n4. **Accessibility**\n - Terminal compatibility\n - Color blindness considerations\n\n## Deliverables\n- UX inconsistencies\n- Template duplication\n- Style consolidation opportunities","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/road-warrior","created_at":"2026-01-04T23:41:36.241295-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:47:21.247008-08:00","closed_at":"2026-01-04T23:47:21.247008-08:00","close_reason":"UI review complete: Found color duplication (3 packages), role icon duplication, missing NO_COLOR support. Recommendations: consolidate colors in style package, add symbolic status indicators alongside color.","dependencies":[{"issue_id":"gt-a02fj.7","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:36.241788-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.8","title":"Review: Infrastructure and Utilities","description":"Review supporting infrastructure packages\n\n## Packages\n- internal/config/\n- internal/doctor/\n- internal/util/\n- internal/lock/\n- internal/keepalive/\n- internal/townlog/\n- internal/constants/\n- internal/deps/\n- internal/events/\n- internal/checkpoint/\n- internal/boot/\n- internal/dog/\n- internal/suggest/\n- internal/claude/\n\n## Focus Areas\n\n1. **Dead Code**\n - Unused functions\n - Unreachable branches\n - Stale utilities\n\n2. **Missing Abstractions**\n - Common patterns in util that should be elsewhere\n - Repeated config handling\n\n3. **Performance**\n - Logger efficiency\n - Lock contention\n - Keepalive overhead\n\n4. **Error Handling**\n - Consistent patterns\n - Proper wrapping\n\n## Deliverables\n- Dead code inventory\n- Utility consolidation plan\n- Performance concerns","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/interceptor","created_at":"2026-01-04T23:41:37.891301-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:51:04.124401-08:00","closed_at":"2026-01-04T23:51:04.124401-08:00","close_reason":"Polecat completed review - closing to complete convoy","dependencies":[{"issue_id":"gt-a02fj.8","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:37.891839-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a02fj.9","title":"Review: Test Coverage and Quality","description":"Audit test coverage and test quality\n\n## Scope\nAll *_test.go files across the codebase\n\n## Focus Areas\n\n1. **Coverage Gaps**\n - Packages with no tests\n - Critical paths without test coverage\n - Error paths untested\n\n2. **Test Quality**\n - Table-driven tests where appropriate\n - Test isolation (no shared state)\n - Meaningful assertions\n\n3. **Test Smells**\n - Flaky tests\n - Over-mocking\n - Tests that test implementation not behavior\n\n4. **Missing Test Types**\n - Integration tests needed\n - Edge cases not covered\n\n## Deliverables\n- Coverage gap inventory\n- Flaky test candidates\n- Priority list for new tests","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/blackfinger","created_at":"2026-01-04T23:41:54.464454-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T23:49:13.77759-08:00","closed_at":"2026-01-04T23:49:13.77759-08:00","close_reason":"Review complete. Report at docs/test-coverage-review.md","dependencies":[{"issue_id":"gt-a02fj.9","depends_on_id":"gt-a02fj","type":"parent-child","created_at":"2026-01-04T23:41:54.464921-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-a0euf","title":"Merge: angharad-mk02mkh7","description":"branch: polecat/angharad-mk02mkh7\ntarget: main\nsource_issue: angharad-mk02mkh7\nrig: gastown\nagent_bead: gt-gastown-polecat-angharad\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:36:56.626794-08:00","created_by":"gastown/polecats/angharad","updated_at":"2026-01-04T10:40:37.585581-08:00","closed_at":"2026-01-04T10:40:37.585581-08:00","close_reason":"Merged to main at b7d82c72"} -{"id":"gt-a28hb","title":"Merge: organic-mjwjck2f","description":"branch: polecat/organic-mjwjck2f\ntarget: main\nsource_issue: organic-mjwjck2f\nrig: gastown\nagent_bead: gt-gastown-polecat-organic","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:38:20.878216-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-01T23:41:11.184352-08:00","closed_at":"2026-01-01T23:41:11.184352-08:00","close_reason":"Merged to main at c328730a"} -{"id":"gt-a3hxa","title":"Digest: mol-deacon-patrol","description":"Patrol 14: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:34:31.219589-08:00","updated_at":"2025-12-28T01:34:31.219589-08:00","closed_at":"2025-12-28T01:34:31.219538-08:00"} -{"id":"gt-a40d8","title":"Optimize convoy status: batch worker lookups","description":"## Problem\n\n`gt convoy status` is slow due to O(N×R) subprocess calls in `getWorkersForIssues()` (convoy.go:1213-1294).\n\nCurrent code spawns one sqlite3 subprocess per issue per rig:\n```go\nfor _, polecatsDir := range rigDirs { // R rigs\n for _, issueID := range issueIDs { // N issues\n queryCmd := exec.Command(\"sqlite3\", ...) // R×N subprocesses!\n }\n}\n```\n\nFor a convoy tracking 10 issues across 3 rigs = 30 subprocess calls × ~20ms = 600ms minimum.\n\n## Proposed Fix\n\n1. **Batch sqlite queries** - One query per rig using `WHERE hook_bead IN (id1, id2, ...)`\n - Reduces R×N calls to R calls\n - Biggest win\n\n2. **Parallelize rig lookups** - Query all rigs concurrently\n - Use goroutines + WaitGroup\n - Reduces R sequential calls to 1 parallel batch\n\n3. **Optional: Short TTL cache** - Cache worker assignments for 5-10s\n - Worker assignments rarely change mid-query\n - Helps repeated status checks\n\n## Files\n\n- `internal/cmd/convoy.go:1213-1294` - `getWorkersForIssues()`\n- `internal/cmd/convoy.go:1032-1113` - `getTrackedIssues()` (calls the above)\n\n## Expected Impact\n\nBefore: 300-600ms for moderate convoys\nAfter: 50-100ms (batch + parallel)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/vuvalini","created_at":"2026-01-04T14:43:23.013007-08:00","created_by":"mayor","updated_at":"2026-01-04T14:48:30.712674-08:00","closed_at":"2026-01-04T14:48:30.712674-08:00","close_reason":"Implemented batching and parallelization of sqlite queries"} -{"id":"gt-a4la6","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All healthy - witnesses, refineries running. No callbacks, no orphans, no pending spawns.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:16:17.348433-08:00","updated_at":"2025-12-28T11:16:17.348433-08:00","closed_at":"2025-12-28T11:16:17.348399-08:00"} -{"id":"gt-a5ghy","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:01:19.436163-08:00","updated_at":"2025-12-31T22:01:19.436163-08:00","closed_at":"2025-12-31T22:01:19.43612-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-a6dvw","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:59:16.514115-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.662824-08:00","closed_at":"2026-01-04T16:40:22.662824-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:59:16-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-a6ydg","title":"Merge: testcat-mjtk387i","description":"branch: polecat/testcat-mjtk387i\ntarget: main\nsource_issue: testcat-mjtk387i\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T21:13:51.05112-08:00","created_by":"gastown/polecats/testcat","updated_at":"2025-12-30T23:12:54.653682-08:00","closed_at":"2025-12-30T23:12:54.653682-08:00","close_reason":"Branch already merged"} -{"id":"gt-a94wv","title":"Digest: mol-deacon-patrol","description":"Patrol 71: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:02:24.173935-08:00","updated_at":"2025-12-31T15:02:24.173935-08:00","closed_at":"2025-12-31T15:02:24.173902-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-a9sre","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 36: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:35:41.482755-08:00","updated_at":"2026-01-01T12:35:41.482755-08:00","closed_at":"2026-01-01T12:35:41.482715-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-a9y","title":"File locking for concurrent access","description":"Add file locking for concurrent access safety.\n\n## At-Risk Files\n- .gastown/swarms.json (or per-swarm state.json)\n- .gastown/refinery.json\n- polecats/\u003cname\u003e/state.json\n- inbox.jsonl files\n\n## Go File Locking\nUse syscall.Flock for advisory locking:\n```go\ntype FileLock struct {\n file *os.File\n}\n\nfunc AcquireLock(path string, timeout time.Duration) (*FileLock, error) {\n f, err := os.OpenFile(path+\".lock\", os.O_CREATE|os.O_RDWR, 0644)\n if err != nil {\n return nil, err\n }\n // Use syscall.Flock with timeout\n}\n\nfunc (l *FileLock) Release() error\n```\n\n## Integration Pattern\n```go\nfunc (m *Manager) saveState(ref *Refinery) error {\n lock, err := AcquireLock(m.stateFile(), 5*time.Second)\n if err != nil {\n return fmt.Errorf(\"could not acquire lock: %w\", err)\n }\n defer lock.Release()\n \n // Read-modify-write cycle\n}\n```\n\n## New Package\ninternal/filelock/\n├── lock.go # FileLock, AcquireLock\n└── lock_test.go\n\n## Apply To\n- internal/refinery/manager.go: loadState/saveState\n- internal/cmd/swarm.go: SwarmStore\n- internal/mail/mailbox.go: Append, rewrite\n- internal/polecat/manager.go: state operations\n\n## Timeout Handling\nDefault 5 second timeout. Return error if lock not acquired.\n\n## Acceptance Criteria\n- [ ] Lock files created (.lock extension)\n- [ ] Timeout on lock contention\n- [ ] All state files protected\n- [ ] Locks released on error paths","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:48:15.641938-08:00","updated_at":"2025-12-16T16:06:32.441426-08:00"} -{"id":"gt-aa1jz","title":"Merge: keeper-dogs","description":"branch: polecat/keeper-dogs\ntarget: main\nsource_issue: keeper-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:36:28.246013-08:00","created_by":"gastown/polecats/keeper","updated_at":"2025-12-30T18:23:22.23671-08:00","closed_at":"2025-12-30T18:23:22.23671-08:00"} -{"id":"gt-aatkf","title":"Digest: mol-deacon-patrol","description":"Patrol 15: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:09:32.135786-08:00","updated_at":"2025-12-28T03:09:32.135786-08:00","closed_at":"2025-12-28T03:09:32.135752-08:00"} -{"id":"gt-abizi","title":"Merge: furiosa-mjxlt6tk","description":"branch: polecat/furiosa-mjxlt6tk\ntarget: main\nsource_issue: furiosa-mjxlt6tk\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:11:43.595345-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T17:14:07.456848-08:00","closed_at":"2026-01-02T17:14:07.456848-08:00","close_reason":"Merged to main at 8feb27d4"} -{"id":"gt-aboj4","title":"Review PR #87: add --no-daemon flag to mol bond","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/angharad","created_at":"2026-01-04T10:53:58.554761-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:55:40.505243-08:00","closed_at":"2026-01-04T10:55:40.505243-08:00","close_reason":"PR #87 approved - follows established --no-daemon pattern"} -{"id":"gt-abu4c","title":"Merge: gt-svdsy","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: gt-svdsy\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:20:17.595631-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:42.882382-08:00","closed_at":"2025-12-30T23:12:42.882382-08:00","close_reason":"Branch already merged"} -{"id":"gt-acc7q","title":"Digest: mol-deacon-patrol","description":"Patrol 155 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:07:24.21067-08:00","updated_at":"2025-12-31T16:07:24.21067-08:00","closed_at":"2025-12-31T16:07:24.210642-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-acn1b","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:15:33.675942-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.581703-08:00","closed_at":"2026-01-04T16:40:13.581703-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:15:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-ae81x","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:33:41.729344-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.781714-08:00","closed_at":"2026-01-05T00:08:31.781714-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:33:41-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-aeok5","title":"Validate rig names to reject hyphens and special characters","description":"GHI #23: Add validation in Manager.AddRig() to reject rig names with hyphens (and other special chars) that break agent ID parsing.\n\n**Problem**: Agent IDs use format `\u003cprefix\u003e-\u003crig\u003e-\u003crole\u003e[-\u003cname\u003e]` with hyphens as delimiters. Hyphenated rig names like `op-baby` cause parsing failures.\n\n**Fix location**: internal/rig/manager.go:172 (AddRig function)\n\n**Implementation**:\n1. Add validation after RigExists check (~line 173)\n2. Reject names containing: hyphens, spaces, dots\n3. Suggest sanitized alternative in error message\n\nExample:\n```go\nif strings.Contains(opts.Name, \"-\") {\n return nil, fmt.Errorf(\"rig name %q contains hyphens which break agent ID parsing; use %q instead\", \n opts.Name, strings.ReplaceAll(opts.Name, \"-\", \"\"))\n}\n```\n\nRef: https://github.com/steveyegge/gastown/issues/23","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2026-01-02T12:11:40.52007-08:00","created_by":"mayor","updated_at":"2026-01-02T12:15:19.222962-08:00","closed_at":"2026-01-02T12:15:19.222962-08:00","close_reason":"Implemented rig name validation in Manager.AddRig()"} -{"id":"gt-aeou9","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:23:45.656347-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:41.835045-08:00","closed_at":"2026-01-05T19:44:41.835045-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:23:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-aep7p","title":"Digest: mol-deacon-patrol","description":"Patrol complete: checked inbox (empty), scanned health (all witnesses/refineries running), no gates, no convoys, no orphans, 1 dog idle, no plugins","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:29:05.558049-08:00","updated_at":"2025-12-31T18:29:05.558049-08:00","closed_at":"2025-12-31T18:29:05.558018-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-aer7q","title":"Day 2.7: Bootstrap creates agent beads","description":"Bootstrap commands must create agent beads for ZFC compliance.\n\n## Problem\n- `gt install` doesn't create Deacon/Mayor agent beads\n- `gt rig add` doesn't create Witness/Refinery agent beads\n- `gt doctor` doesn't verify agent beads exist\n- Current beads were created manually (not reproducible)\n\n## Impact\nPatrol ignition (gt-qpoxz) depends on agent beads existing.\nWithout bootstrap creating them, fresh installs will fail.\n\n## Required\n1. gt install: Create gt-deacon and gt-mayor beads\n2. gt rig add: Create gt-witness-\u003crig\u003e and gt-refinery-\u003crig\u003e beads\n3. gt doctor: Add agent-beads-exist check\n4. gt doctor --fix: Create missing agent beads","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-28T02:16:50.951423-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T02:40:06.743526-08:00","closed_at":"2025-12-28T02:40:06.743526-08:00"} -{"id":"gt-ag8jc","title":"Digest: mol-deacon-patrol","description":"Patrol 4: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:49:27.854956-08:00","updated_at":"2026-01-01T08:49:27.854956-08:00","closed_at":"2026-01-01T08:49:27.854924-08:00"} -{"id":"gt-agtwd","title":"gt mail inbox: identity auto-detection fails for refinery","description":"When running from ~/gt/gastown/refinery or ~/gt/gastown/refinery/rig, 'gt mail inbox' detects identity as 'mayor/' instead of 'gastown/refinery'.\n\nWorkaround: Use --identity flag explicitly:\n gt mail inbox --identity gastown/refinery\n\nThis breaks the refinery patrol because it can't see its MERGE_READY messages.\n\nExpected: Running from gastown/refinery should auto-detect identity as gastown/refinery.\n\nRelated: The refinery has 9 unread MERGE_READY messages that aren't being processed because of this bug.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T22:26:17.937287-08:00","created_by":"mayor","updated_at":"2025-12-29T12:44:29.053397-08:00","closed_at":"2025-12-29T12:44:29.053397-08:00","close_reason":"Added refinery/witness detection to detectSender()"} -{"id":"gt-ahqiw","title":"Digest: mol-deacon-patrol","description":"Patrol 244 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:17:55.020026-08:00","updated_at":"2026-01-01T17:17:55.020026-08:00","closed_at":"2026-01-01T17:17:55.019996-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-aijvt","title":"Digest: mol-deacon-patrol","description":"Patrol 20: all clear - handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:21:30.115081-08:00","updated_at":"2025-12-28T08:21:30.115081-08:00","closed_at":"2025-12-28T08:21:30.11505-08:00"} -{"id":"gt-ajz71","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:05:20.774415-08:00","updated_at":"2026-01-01T20:05:20.774415-08:00","closed_at":"2026-01-01T20:05:20.77438-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-akc4m","title":"MessagingConfig: Add missing test cases","description":"Missing test coverage:\n1. Version \u003e CurrentMessagingVersion rejection\n2. Malformed JSON handling","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:29:09.827958-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T15:31:31.450393-08:00","closed_at":"2025-12-28T15:31:31.450393-08:00"} -{"id":"gt-akfh8","title":"Digest: mol-deacon-patrol","description":"Patrol 8: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:53:54.654721-08:00","updated_at":"2025-12-25T15:53:54.654721-08:00","closed_at":"2025-12-25T15:53:54.654692-08:00"} -{"id":"gt-akqch","title":"Digest: mol-deacon-patrol","description":"Cycle 296: All healthy, refinery active","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:43:27.731369-08:00","updated_at":"2026-01-01T18:43:27.731369-08:00","closed_at":"2026-01-01T18:43:27.73132-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-akqch","depends_on_id":"gt-eph-pdsn","type":"parent-child","created_at":"2026-01-01T18:43:27.732652-08:00","created_by":"deacon"}]} -{"id":"gt-akte7","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:58:12.619252-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.47369-08:00","closed_at":"2026-01-05T00:08:31.47369-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:58:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-anoyp","title":"Session ended: gt-gastown-slit","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T18:25:19.242553-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-03T11:32:45.180847-08:00","closed_at":"2026-01-03T11:32:45.180847-08:00","close_reason":"Session lifecycle events processed","event_kind":"session.ended","actor":"gastown/polecats/slit","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T18:25:19-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-slit\",\"worker\":\"slit\"}"} -{"id":"gt-aov32","title":"Restart daemon to activate Boot integration","description":"The running daemon (PID 70670) predates Boot code. Daemon heartbeat() now calls ensureBootRunning() but the stale process never executes it.\n\nFix: gt shutdown --force \u0026\u0026 gt start\n\nThis is a one-time operational task, not a code change.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T21:54:40.779448-08:00","created_by":"mayor","updated_at":"2025-12-30T21:56:22.92741-08:00","closed_at":"2025-12-30T21:56:22.92741-08:00","close_reason":"Daemon restarted, Boot now spawning successfully"} -{"id":"gt-aow49","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:14:10.172692-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:41.91098-08:00","closed_at":"2026-01-05T19:44:41.91098-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:14:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-ap4xz","title":"Digest: mol-deacon-patrol","description":"Patrol 39: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:02:08.463644-08:00","updated_at":"2025-12-31T14:02:08.463644-08:00","closed_at":"2025-12-31T14:02:08.463609-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-apft7","title":"Merge: capable-1767084028536","description":"branch: polecat/capable-1767084028536\ntarget: main\nsource_issue: capable-1767084028536\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:04:07.332002-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T01:06:10.373431-08:00","closed_at":"2025-12-30T01:06:10.373431-08:00","close_reason":"Conflicts with main - mrqueue package was removed. Notified capable to rebase."} -{"id":"gt-apou9","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:31:34.21769-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.749276-08:00","closed_at":"2026-01-04T16:40:22.749276-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:31:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-apq81","title":"Digest: mol-refinery-patrol","description":"Patrol: Cleaned 2 stale MRs (dag unverifiable, furiosa already merged). Queue empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:57:20.857779-08:00","updated_at":"2026-01-01T09:57:20.857779-08:00","closed_at":"2026-01-01T09:57:20.857741-08:00","close_reason":"Squashed from 11 wisps"} -{"id":"gt-aqk45","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:29:40.096811-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.78012-08:00","closed_at":"2026-01-04T16:40:22.78012-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:29:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-ar1ag","title":"Digest: mol-deacon-patrol","description":"Patrol 12: All healthy, beads/witness now responding","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:53:11.230955-08:00","updated_at":"2026-01-01T10:53:11.230955-08:00","closed_at":"2026-01-01T10:53:11.230917-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-arjlu","title":"gt sling: nudge witness+refinery when dispatching to polecat","description":"When gt sling dispatches work to a polecat, wake the rig's witness and refinery.\n\n## Boot+Nudge Pattern\n\n```go\n// After successful polecat dispatch\nfunc wakeRigAgents(rig string) {\n // Level 2: Start if asleep\n exec.Command(\"gt\", \"rig\", \"boot\", rig).Run()\n \n // Level 1: Clear backoff if running\n t := tmux.NewTmux()\n t.NudgeSession(fmt.Sprintf(\"gt-%s-witness\", rig), \"wake\")\n t.NudgeSession(fmt.Sprintf(\"gt-%s-refinery\", rig), \"wake\")\n}\n```\n\n## Graceful Behavior\n\n- `gt rig boot` is idempotent (no-op if already running)\n- Nudge failures are silent (session might not exist yet)\n- Agents discover what happened by checking reality\n\n## Reference\n\nSee ~/gt/docs/patrol-system-design.md (Two-Level Wake section)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T22:14:38.155099-08:00","created_by":"mayor","updated_at":"2025-12-29T12:49:34.87614-08:00","closed_at":"2025-12-29T12:49:34.87614-08:00","close_reason":"Implemented in sling.go","dependencies":[{"issue_id":"gt-arjlu","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T22:31:11.241348-08:00","created_by":"daemon"}]} -{"id":"gt-ascl0","title":"Digest: mol-deacon-patrol","description":"Patrol 13: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:43:57.148196-08:00","updated_at":"2025-12-26T18:43:57.148196-08:00","closed_at":"2025-12-26T18:43:57.148156-08:00"} -{"id":"gt-asdza","title":"Merge: rictus-mjuic92c","description":"branch: polecat/rictus-mjuic92c\ntarget: main\nsource_issue: rictus-mjuic92c\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T13:15:16.699664-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-31T13:16:08.555183-08:00","closed_at":"2025-12-31T13:16:08.555183-08:00","close_reason":"Merged at 04289226"} -{"id":"gt-atmlz","title":"Digest: mol-deacon-patrol","description":"Patrol #16","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:23:53.841639-08:00","updated_at":"2025-12-31T06:23:53.841639-08:00","closed_at":"2025-12-31T06:23:53.841606-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-atqr8","title":"Create session name helper functions in internal/session","description":"attached_args: Session name helper functions\n\nCreate helper functions for consistent session name construction.\n\n## Files to modify\n- internal/session/names.go (NEW)\n\n## Implementation\nCreate new file with these functions:\n```go\npackage session\n\nimport \"fmt\"\n\nconst Prefix = \"gt-\"\n\nfunc MayorSessionName() string { return Prefix + \"mayor\" }\nfunc DeaconSessionName() string { return Prefix + \"deacon\" }\nfunc WitnessSessionName(rig string) string { return fmt.Sprintf(\"%s%s-witness\", Prefix, rig) }\nfunc RefinerySessionName(rig string) string { return fmt.Sprintf(\"%s%s-refinery\", Prefix, rig) }\nfunc CrewSessionName(rig, name string) string { return fmt.Sprintf(\"%s%s-crew-%s\", Prefix, rig, name) }\nfunc PolecatSessionName(rig, name string) string { return fmt.Sprintf(\"%s%s-%s\", Prefix, rig, name) }\n```\n\n## Acceptance criteria\n- [ ] New file internal/session/names.go created\n- [ ] All 6 helper functions implemented\n- [ ] Unit tests in internal/session/names_test.go\n- [ ] go build ./... passes\n- [ ] go test ./internal/session/... passes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:08.856968-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:12:31.8143-08:00","closed_at":"2025-12-28T16:12:31.8143-08:00"} -{"id":"gt-ave42","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:06:07.660163-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.491845-08:00","closed_at":"2026-01-05T19:44:18.491845-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:06:02-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-awb9v","title":"Review PR #42: fix(done): detect default branch instead of hardcoding 'main'","description":"Review PR #42. Verify default branch detection works correctly. Approve with gh pr review --approve if good.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/organic","created_at":"2026-01-03T11:40:27.996208-08:00","created_by":"mayor","updated_at":"2026-01-03T11:45:16.667669-08:00","closed_at":"2026-01-03T11:45:16.667669-08:00","close_reason":"PR #42 reviewed and approved"} -{"id":"gt-awu07","title":"Day 1.4: Create agent beads for core roles","description":"Create agent beads with deterministic IDs:\n- gt-mayor (Mayor coordinator)\n- gt-witness (per-rig polecat monitor)\n- gt-refinery (per-rig merge processor)\n\nEach with role_type, rig, and initial state.\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:11.427106-08:00","created_by":"mayor","updated_at":"2025-12-28T00:08:24.338212-08:00","closed_at":"2025-12-28T00:08:24.338212-08:00","dependencies":[{"issue_id":"gt-awu07","depends_on_id":"gt-ikyo1","type":"blocks","created_at":"2025-12-27T20:58:49.122365-08:00","created_by":"daemon"},{"issue_id":"gt-awu07","depends_on_id":"gt-v2gkv","type":"blocks","created_at":"2025-12-27T20:58:50.202777-08:00","created_by":"daemon"},{"issue_id":"gt-awu07","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.69769-08:00","created_by":"daemon"}]} -{"id":"gt-ay102","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T01:00:15.970179-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.672681-08:00","closed_at":"2026-01-05T19:44:18.672681-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T01:00:15-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-ay6z8","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:28:18.148985-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:28:18.201704-08:00","closed_at":"2026-01-06T13:28:18.201704-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:28:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-azjdh","title":"Digest: mol-deacon-patrol","description":"Patrol 127: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:34:00.467046-08:00","updated_at":"2026-01-01T14:34:00.467046-08:00","closed_at":"2026-01-01T14:34:00.467012-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-azyhg","title":"Session ended: gt-gastown/crew/jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T18:51:23.533651-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.075341-08:00","closed_at":"2026-01-04T16:41:26.075341-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T18:51:23-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/jack\",\"worker\":\"gastown/crew/jack\"}"} -{"id":"gt-azztl","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All healthy - Witness/Refinery running, 7 polecats monitored","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:24:16.990488-08:00","updated_at":"2025-12-30T16:24:16.990488-08:00","closed_at":"2025-12-30T16:24:16.99042-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-azztl","depends_on_id":"gt-eph-z45","type":"parent-child","created_at":"2025-12-30T16:24:16.991441-08:00","created_by":"deacon"}]} -{"id":"gt-b0167","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: all healthy, 2 health acks","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:56:09.467318-08:00","updated_at":"2026-01-01T09:56:09.467318-08:00","closed_at":"2026-01-01T09:56:09.467279-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-b0rk4","title":"Merge: rictus-1767073382273","description":"branch: polecat/rictus-1767073382273\ntarget: main\nsource_issue: rictus-1767073382273\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T21:56:39.176645-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T23:32:37.288296-08:00","closed_at":"2025-12-29T23:32:37.288296-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-b1j2n","title":"Digest: mol-deacon-patrol","description":"Cycle 195: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:23:57.130179-08:00","updated_at":"2026-01-01T16:23:57.130179-08:00","closed_at":"2026-01-01T16:23:57.130148-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-b1j2n","depends_on_id":"gt-eph-p42j","type":"parent-child","created_at":"2026-01-01T16:23:57.131616-08:00","created_by":"deacon"}]} -{"id":"gt-b2bum","title":"Digest: mol-deacon-patrol","description":"Cycle 292: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:36:51.710746-08:00","updated_at":"2026-01-01T18:36:51.710746-08:00","closed_at":"2026-01-01T18:36:51.710709-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-b2bum","depends_on_id":"gt-eph-pntw","type":"parent-child","created_at":"2026-01-01T18:36:51.711966-08:00","created_by":"deacon"}]} -{"id":"gt-b37w9","title":"Digest: mol-deacon-patrol","description":"Patrol 99: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:12:46.418197-08:00","updated_at":"2026-01-01T03:12:46.418197-08:00","closed_at":"2026-01-01T03:12:46.418159-08:00"} -{"id":"gt-b3phb","title":"Digest: mol-deacon-patrol","description":"Patrol 202: All agents healthy, 10 polecats working, 3 refineries processing. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:46:05.713874-08:00","updated_at":"2026-01-01T16:46:05.713874-08:00","closed_at":"2026-01-01T16:46:05.713834-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-b3phb","depends_on_id":"gt-eph-iatt","type":"parent-child","created_at":"2026-01-01T16:46:05.715189-08:00","created_by":"deacon"}]} -{"id":"gt-b5sby","title":"Digest: mol-deacon-patrol","description":"Patrol 17: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:34:07.051767-08:00","updated_at":"2026-01-01T04:34:07.051767-08:00","closed_at":"2026-01-01T04:34:07.051728-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-b61pk","title":"Digest: mol-deacon-patrol","description":"Patrol 83: All healthy, quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:17:14.303626-08:00","updated_at":"2025-12-31T15:17:14.303626-08:00","closed_at":"2025-12-31T15:17:14.303597-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-b7p4j","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:31:51.544021-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:31:51.593264-08:00","closed_at":"2026-01-05T21:31:51.593264-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:31:51-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-b93r0","title":"LESSONS: Idle Polecat Incident 2026-01-02","description":"# Incident Summary\n\nOn 2026-01-02, discovered 9 polecats (5 gastown, 4 beads) sitting idle at Claude prompts with completed work, burning money.\n\n## Root Cause Chain\n\n1. **Polecats completed work, submitted MRs** - correct\n2. **Refinery merged work, sent MERGED to Witness** - correct \n3. **Witness had 50 unread protocol messages** - BUG\n4. **Witness not processing mail = no cleanup** - BUG\n5. **Polecats waiting for death that never comes** - SYMPTOM\n\n## Why Witness Wasn't Patrolling\n\nWitness is a Claude agent with template instructions. When it finishes one patrol cycle, it stops. The template doesn't emphasize continuous operation.\n\nClaude agents are stateless between turns - they complete a task and wait for next input. Without continuous prompting, they idle.\n\n## Design Flaw\n\nThe current model:\n```\nPolecat → gt done → WAIT for Witness to kill\nWitness → process mail → nuke polecat\n```\n\n**Problem**: If Witness doesn't patrol, polecats wait forever.\n\n## Fixes Implemented\n\n1. **gt-lynar**: `gt done --exit` - polecats self-terminate after MR submission\n2. **gt-x4ad3**: Update polecat template to use --exit\n3. **gt-fo9iz**: Nuke safety check - verify work on main, not just 'pushed'\n\n## Lessons\n\n### L1: Agents Should Self-Terminate When Done\nDon't rely on external actors to clean up. If an agent finishes work, it should exit immediately. Waiting = burning money.\n\n### L2: Mail Is Not Reliable Signaling\nClaude agents may not process mail continuously. Don't design protocols that require prompt mail processing.\n\n### L3: Safety Checks Must Match Reality\nAfter branch merge+delete, local branch looks 'unpushed' even though work is on main. Safety checks should verify actual state (is work on main?) not proxy state (is branch pushed?).\n\n### L4: Idle State Is A Bug\nGas Town's propulsion principle: agents are pistons that fire. Idle agents violate this. If an agent can be idle, the design is wrong.\n\n### L5: Monitor What Matters\nWe had convoy status, polecat lists, etc. But no alert for 'polecat at prompt doing nothing'. Add monitoring for actual idle time.\n\n## Future Prevention\n\n1. Polecat template: always use `gt done --exit`\n2. Witness template: emphasize continuous patrol (or replace with daemon)\n3. Add `gt doctor` check: 'polecats at prompt for \u003eN minutes'\n4. Consider: Replace Witness with daemon (more reliable than Claude patrol)","status":"closed","priority":4,"issue_type":"chore","created_at":"2026-01-02T13:39:15.80604-08:00","created_by":"mayor","updated_at":"2026-01-02T13:39:22.34879-08:00","closed_at":"2026-01-02T13:39:22.34879-08:00","close_reason":"Lessons documented"} -{"id":"gt-b9y41","title":"Session ended: gt-gastown-chrome","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:18:57.428321-08:00","created_by":"gastown/polecats/chrome","updated_at":"2026-01-05T19:44:41.871063-08:00","closed_at":"2026-01-05T19:44:41.871063-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/chrome","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:18:56-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-chrome\",\"worker\":\"chrome\"}"} -{"id":"gt-bblyh","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all healthy, no events","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T06:07:14.085326-08:00","updated_at":"2025-12-28T06:07:14.085326-08:00","closed_at":"2025-12-28T06:07:14.085291-08:00"} -{"id":"gt-bc6gm","title":"Document polecat lifecycle (session/sandbox/slot layers)","description":"## Problem\n\nThe polecat lifecycle has three distinct layers that are not clearly documented:\n\n1. Session (Claude context) - ephemeral, cycles per step\n2. Sandbox (worktree) - persistent until nuke\n3. Slot/Name (pool allocation) - persistent until nuke\n\nThis has led to confusion and heresies like \"idle polecats\" and \"recycling.\"\n\n## Required Documentation\n\nCreate docs/polecat-lifecycle.md covering:\n\n### The Three Layers\n\n| Layer | Component | Lifecycle |\n|-------|-----------|-----------|\n| Session | Claude (tmux) | Ephemeral - cycles per step |\n| Sandbox | Worktree | Persistent until nuke |\n| Slot | Name from pool | Persistent until nuke |\n\n### Correct Lifecycle\n\n1. gt sling -\u003e sandbox created, session started\n2. Work happens, session cycles, sandbox persists\n3. gt done -\u003e Witness receives POLECAT_DONE\n4. Witness nukes -\u003e sandbox destroyed, slot released\n\n### What \"Recycle\" Means\n\n- Session cycling: Normal - Claude restarts, sandbox stays\n- Sandbox recreation: Repair only - should be rare\n\n### Anti-patterns\n\n- Idle polecats (should not exist)\n- Manual state transitions (gt polecat done/reset)\n- Sandboxes without work assigned\n\n## Location\n\ndocs/polecat-lifecycle.md with cross-references from:\n- PRIMING.md\n- docs/understanding-gas-town.md\n- templates/polecat-CLAUDE.md","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/chumbucket","created_at":"2026-01-04T14:10:23.278933-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T14:22:30.660266-08:00","closed_at":"2026-01-04T14:22:30.660266-08:00","close_reason":"Created docs/polecat-lifecycle.md with three-layer architecture, correct lifecycle flow, and anti-patterns. Added cross-references from understanding-gas-town.md and polecat-CLAUDE.md template."} -{"id":"gt-bca67","title":"gt done: Require pushed branch before MR creation","description":"gt done currently creates MR bead without verifying the branch is pushed.\n\n## Problem\nPolecat can run `gt done` with unpushed commits. MR bead references a branch that doesn't exist on remote. Work is lost when polecat is nuked.\n\n## Fix\nIn done.go runDone():\n```go\n// Before creating MR bead\nstatus, err := g.CheckUncommittedWork()\nif status.UnpushedCommits \u003e 0 {\n return fmt.Errorf(\"branch has %d unpushed commits; run 'git push' first\", status.UnpushedCommits)\n}\n```\n\n## Already Have\n- `computeCleanupStatus()` checks this but only reports, doesn't block\n- Just need to make it a hard error","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T19:07:13.573521-08:00","created_by":"mayor","updated_at":"2025-12-30T20:53:06.48407-08:00","closed_at":"2025-12-30T20:53:06.48407-08:00","close_reason":"Fixed: Added BranchPushedToRemote check in runDone() before MR creation"} -{"id":"gt-bce30","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 27: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:22:37.618934-08:00","updated_at":"2026-01-01T12:22:37.618934-08:00","closed_at":"2026-01-01T12:22:37.618899-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-bcr5i","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All healthy - Witness monitoring 7 polecats, Refinery running, no pending work. Cleaned stale wisp gt-eph-5hp.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:22:23.338913-08:00","updated_at":"2025-12-30T16:22:23.338913-08:00","closed_at":"2025-12-30T16:22:23.33886-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-bcr5i","depends_on_id":"gt-eph-6ov","type":"parent-child","created_at":"2025-12-30T16:22:23.339941-08:00","created_by":"deacon"}]} -{"id":"gt-bdsl9","title":"Digest: mol-deacon-patrol","description":"Patrol 12: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:38:22.134096-08:00","updated_at":"2025-12-31T21:38:22.134096-08:00","closed_at":"2025-12-31T21:38:22.134059-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-be0as","title":"Add charmbracelet TUI dependencies (bubbletea, bubbles)","description":"Add charmbracelet TUI framework dependencies.\n\n## Dependencies to add\n```\ngo get github.com/charmbracelet/bubbletea\ngo get github.com/charmbracelet/bubbles\n```\n\n## Already have\n- github.com/charmbracelet/lipgloss (styling)\n\n## Verify\n- go mod tidy\n- go build ./...\n\nQuick task, just adding deps.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T16:13:14.574696-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T16:18:12.74954-08:00","closed_at":"2025-12-28T16:18:12.74954-08:00"} -{"id":"gt-beihd","title":"Digest: mol-deacon-patrol","description":"Patrol 46: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:19:46.805781-08:00","updated_at":"2026-01-01T02:19:46.805781-08:00","closed_at":"2026-01-01T02:19:46.805744-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-bejee","title":"Digest: mol-deacon-patrol","description":"Patrol #20: All healthy, 3 convoys active","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:25:05.56582-08:00","updated_at":"2025-12-31T06:25:05.56582-08:00","closed_at":"2025-12-31T06:25:05.565788-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-bfd4q","title":"Digest: mol-deacon-patrol","description":"Patrol 7: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T11:05:00.862619-08:00","updated_at":"2025-12-25T11:05:00.862619-08:00","closed_at":"2025-12-25T11:05:00.862585-08:00"} -{"id":"gt-bfgt3","title":"Digest: mol-deacon-patrol","description":"Patrol complete: routine, town stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:20:54.101654-08:00","updated_at":"2025-12-28T19:20:54.101654-08:00","closed_at":"2025-12-28T19:20:54.101623-08:00"} -{"id":"gt-bgfqy","title":"Create StartupNudge function with seance metadata","description":"## Location\ninternal/session/startup.go (new file) or internal/agent/startup.go\n\n## Interface\n```go\ntype StartupNudgeConfig struct {\n Recipient string // gastown/crew/gus, deacon, gastown/witness\n Sender string // mayor, deacon, self (for handoff)\n Topic string // mol-id, \"cold-start\", \"handoff\", \"assigned\"\n MolID string // Optional: specific molecule being worked\n}\n\nfunc StartupNudge(t *tmux.Tmux, session string, cfg StartupNudgeConfig) error\n```\n\n## Nudge Format\n```\n[GAS TOWN] gastown/crew/gus ← deacon • 2025-12-30T15:42 • assigned:gt-abc12\n```\n\nThis becomes the session title in Claude Codes `/resume` picker.\n\n## Implementation\n1. Build the formatted message from config\n2. Call t.NudgeSession(session, message) for reliable delivery\n3. Return error if session doesnt exist or nudge fails\n\n## Key Insight\nThe message content doesnt trigger GUPP - CLAUDE.md and hooks handle that.\nThe metadata makes sessions identifiable in `/resume`.\n","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T22:48:01.522151-08:00","created_by":"stevey","updated_at":"2025-12-30T23:01:31.35452-08:00","closed_at":"2025-12-30T23:01:31.35452-08:00","close_reason":"Created StartupNudge function in internal/session/startup.go with StartupNudgeConfig struct. Format: [GAS TOWN] recipient \u003c- sender • timestamp • topic[:mol-id]. Tests pass."} -{"id":"gt-bgudb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 71: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:20:30.549312-08:00","updated_at":"2026-01-01T13:20:30.549312-08:00","closed_at":"2026-01-01T13:20:30.549274-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-bho9","title":"stderr suppression hides critical errors","description":"Multiple files set cmd.Stderr = nil:\n- prime.go\n- up.go\n- orphans.go\n- daemon.go\n\nThis hides git errors and command failures.\n\nShould capture stderr for debugging and log when errors occur,\nrather than suppressing entirely.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-24T12:51:41.108782-08:00","updated_at":"2025-12-30T00:49:33.309756-08:00","closed_at":"2025-12-30T00:49:33.309756-08:00","close_reason":"Fixed stderr suppression: prime.go (3 locations), orphans.go (1 location), patrol_helpers.go (4 locations) now capture stderr for debugging. Daemon launch cases (up.go, daemon.go, daemon_check.go) keep nil for proper detachment but have clarifying comments.","dependencies":[{"issue_id":"gt-bho9","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:07.908317-08:00","created_by":"daemon"}]} -{"id":"gt-bj5hl","title":"Digest: mol-deacon-patrol","description":"Patrol 8: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:16:08.324143-08:00","updated_at":"2025-12-28T08:16:08.324143-08:00","closed_at":"2025-12-28T08:16:08.324106-08:00"} -{"id":"gt-bmbmd","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:09:15.792678-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.476398-08:00","closed_at":"2026-01-05T19:44:18.476398-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:09:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-bmcxx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All healthy. No callbacks, orphans, or gates.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:18:38.161883-08:00","updated_at":"2025-12-28T11:18:38.161883-08:00","closed_at":"2025-12-28T11:18:38.161848-08:00"} -{"id":"gt-bmnru","title":"Digest: mol-deacon-patrol","description":"Patrol complete: both rigs healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:29:27.182707-08:00","updated_at":"2025-12-28T19:29:27.182707-08:00","closed_at":"2025-12-28T19:29:27.182673-08:00"} -{"id":"gt-bmt81","title":"Digest: mol-deacon-patrol","description":"Patrol 10: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:37:59.386618-08:00","updated_at":"2025-12-31T21:37:59.386618-08:00","closed_at":"2025-12-31T21:37:59.386581-08:00"} -{"id":"gt-bnch","title":"Human escalation: notify overseer when self-heal fails","description":"Lightweight escalation extracted from Deacon epic (gt-5af).\n\n**Implementation**: Config in town.json or similar:\n```yaml\nescalation:\n contact: steve@example.com # or slack webhook\n triggers:\n - daemon_cant_restart\n - session_missing_5min\n```\n\n**Trigger points**:\n- Go daemon can't restart a session after N attempts\n- Agent detects it's stuck and can't recover\n- Witness can't reach polecat\n\n**Mechanism**: \n- Simple: `gt mail send --human` already exists\n- Enhanced: email/slack via external script\n\n**Weight**: Small config + one code path in daemon\n**Value**: High for unattended operation - human gets notified instead of silent failure","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-20T20:40:46.661514-08:00","updated_at":"2025-12-20T20:40:46.661514-08:00"} -{"id":"gt-bnfus","title":"Merge: rictus-1767138835254","description":"branch: polecat/rictus-1767138835254\ntarget: main\nsource_issue: rictus-1767138835254\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:27:17.227149-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T18:23:22.156739-08:00","closed_at":"2025-12-30T18:23:22.156739-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-bnlgy","title":"Merge: nux-mjxaphp6","description":"branch: polecat/nux-mjxaphp6\ntarget: main\nsource_issue: nux-mjxaphp6\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:09:30.04235-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T12:31:32.991393-08:00","closed_at":"2026-01-02T12:31:32.991393-08:00","close_reason":"Merged to main at 33abd769"} -{"id":"gt-bo8mo","title":"Witness: must send MERGE_READY to Refinery after POLECAT_DONE","description":"Integration test gt-7psb8 revealed that Witness processes POLECAT_DONE but doesn't send MERGE_READY to Refinery.\n\nObserved:\n- Witness receives POLECAT_DONE from furiosa\n- Witness verifies branch pushed\n- Witness kills polecat session\n- Witness notifies Mayor\n- NO MERGE_READY sent to Refinery\n\nExpected: After successful pre-kill verification, Witness should send MERGE_READY to gastown/refinery with the MR details.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T13:11:54.428918-08:00","created_by":"mayor","updated_at":"2025-12-28T13:58:05.348621-08:00","closed_at":"2025-12-28T13:58:05.348621-08:00"} -{"id":"gt-boiw8","title":"Digest: mol-deacon-patrol","description":"Patrol 8: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:54:03.322389-08:00","updated_at":"2025-12-28T15:54:03.322389-08:00","closed_at":"2025-12-28T15:54:03.322353-08:00"} -{"id":"gt-bolfn","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 261: Cleaned 510+ stale wisps (57 hq, 450+ gt). All agents healthy (3 witnesses, 3 refineries, 10 polecats active). No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:36:41.549667-08:00","updated_at":"2026-01-01T17:36:41.549667-08:00","closed_at":"2026-01-01T17:36:41.549625-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-bolfn","depends_on_id":"gt-eph-moba","type":"parent-child","created_at":"2026-01-01T17:36:41.550991-08:00","created_by":"deacon"}]} -{"id":"gt-bp0ht","title":"Add mutex to swarm.Manager for thread safety","description":"attached_args: Add swarm.Manager mutex for thread safety\n\nFix potential race condition in swarm manager's map access.\n\n## Files to modify\n- internal/swarm/manager.go\n- internal/swarm/manager_test.go (add concurrency test)\n\n## Problem\nThe swarms map[string]*Swarm is accessed without synchronization:\n```go\ntype Manager struct {\n swarms map[string]*Swarm // No mutex protection\n}\n```\n\nMultiple goroutines could call Create(), GetSwarm(), etc. simultaneously.\n\n## Implementation\n```go\ntype Manager struct {\n mu sync.RWMutex\n swarms map[string]*Swarm\n}\n\nfunc (m *Manager) GetSwarm(id string) *Swarm {\n m.mu.RLock()\n defer m.mu.RUnlock()\n return m.swarms[id]\n}\n```\n\n## Acceptance criteria\n- [ ] sync.RWMutex added to Manager struct\n- [ ] All map accesses protected by mutex\n- [ ] RLock for reads, Lock for writes\n- [ ] Concurrency test added\n- [ ] go test -race ./internal/swarm/... passes","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:16.520654-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:54:16.914513-08:00"} -{"id":"gt-bpiph","title":"Witness/Refinery startup: Enforce patrol molecule attachment","description":"Witness and Refinery CLAUDE.md says to:\n1. Check for attached molecule on startup\n2. If not attached, spawn patrol wisp\n\nBut sessions are just reacting to mail without patrol structure.\n\nCurrent state:\n- gt-8ynws (Witness Patrol) exists but not attached\n- gt-t5i07 (Refinery Patrol) exists but not attached\n- Sessions are running without structured patrol loops\n\nFix options:\n1. Add SessionStart hook to enforce patrol attachment\n2. Make 'gt start' attach patrol molecules when spawning witness/refinery\n3. Add reminder in CLAUDE.md startup banner that's more emphatic","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/toast","created_at":"2025-12-30T22:03:12.017621-08:00","created_by":"mayor","updated_at":"2025-12-30T22:08:13.786905-08:00","closed_at":"2025-12-30T22:08:13.786905-08:00","close_reason":"Fixed autoSpawnPatrol in patrol_helpers.go to use --status=hooked instead of --status=pinned. This ensures patrol wisps are visible to gt mol status and trigger autonomous mode."} -{"id":"gt-bq1yn","title":"Digest: mol-deacon-patrol","description":"Patrol 4: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T14:04:00.499629-08:00","updated_at":"2025-12-25T14:04:00.499629-08:00","closed_at":"2025-12-25T14:04:00.499596-08:00"} -{"id":"gt-bq4wo","title":"Day 2.7c: gt doctor checks agent beads exist","description":"Add gt doctor check: agent-beads-exist\n\n1. For town-level: verify gt-deacon and gt-mayor beads exist\n2. For each rig: verify gt-witness-\u003crig\u003e and gt-refinery-\u003crig\u003e beads exist\n3. Report missing beads as warnings\n4. Implement --fix to create missing beads\n\nFiles:\n- internal/doctor/agent_beads_check.go (new)\n- internal/cmd/doctor.go (register check)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T02:17:08.814494-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T02:40:06.712421-08:00","closed_at":"2025-12-28T02:40:06.712421-08:00","dependencies":[{"issue_id":"gt-bq4wo","depends_on_id":"gt-aer7q","type":"parent-child","created_at":"2025-12-28T02:17:17.582571-08:00","created_by":"daemon"},{"issue_id":"gt-bq4wo","depends_on_id":"gt-h3hak","type":"blocks","created_at":"2025-12-28T02:17:20.043469-08:00","created_by":"daemon"},{"issue_id":"gt-bq4wo","depends_on_id":"gt-pinkq","type":"blocks","created_at":"2025-12-28T02:17:20.073712-08:00","created_by":"daemon"}]} -{"id":"gt-bqcsf","title":"Refactor: Break up long functions in polecat/manager.go","description":"Several functions exceed 50 lines and have too many responsibilities:\n\n1. Add() (lines 195-276, ~80 lines)\n - Extract: createWorktree(), createAgentBead(), setupBeadsRedirect()\n\n2. RepairWorktreeWithOptions() (lines 405-500, ~95 lines)\n - Near-duplicate of Add() logic - DRY violation\n - Extract common setup to shared helper\n\n3. RemoveWithOptions() (lines 291-360, ~70 lines)\n - Extract: checkRemovalSafety(), cleanupWorktree()\n\n4. setupSharedBeads() (lines 729-782, ~55 lines)\n - Fairly focused but could be cleaner","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:46:13.566961-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-04T23:46:13.566961-08:00"} -{"id":"gt-bqgqj","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:50:31.351262-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.514227-08:00","closed_at":"2026-01-05T19:44:18.514227-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:50:26-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-bqj23","title":"Digest: mol-deacon-patrol","description":"Cycle 295: All healthy, gastown refinery 1 pending","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:42:20.055132-08:00","updated_at":"2026-01-01T18:42:20.055132-08:00","closed_at":"2026-01-01T18:42:20.055081-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-bqj23","depends_on_id":"gt-eph-u8qi","type":"parent-child","created_at":"2026-01-01T18:42:20.056351-08:00","created_by":"deacon"}]} -{"id":"gt-br9xq","title":"Merge: rictus-1767059698035","description":"branch: polecat/rictus-1767059698035\ntarget: main\nsource_issue: rictus-1767059698035\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T18:04:47.967277-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T20:55:04.957659-08:00","closed_at":"2025-12-29T20:55:04.957659-08:00","close_reason":"Work already merged to main - branches were never created or already deleted"} -{"id":"gt-brd1b","title":"Overnight Hanoi Demo: Progress monitoring for mega-molecules","description":"Support monitoring million-step molecules for the overnight Hanoi demo.\n\n## Context\nTowers of Hanoi with 20 disks = 2^20 - 1 = 1,048,575 steps.\nCurrent display code assumes reasonable step counts.\n\n## Requirements\n1. Progress summary command (bd mol progress)\n2. Large molecule guards in display code \n3. Agent-actionable formula description\n4. Convoy integration for completion tracking\n\n## Success Criteria\n- Can cook and pour 20-disk Hanoi formula\n- Can monitor progress without listing all steps\n- Agent can resume mid-molecule with clear instructions\n- Know when it is done (convoy or completion signal)","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-31T00:41:04.096101-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T19:54:31.222047-08:00","closed_at":"2026-01-01T19:54:31.222047-08:00","close_reason":"7-disk demo proved molecule system works. Large molecule creation needs optimization before overnight 20-disk run."} -{"id":"gt-brd1b.1","title":"Add bd mol progress command for mega-molecule summary","description":"New command that shows progress percentage, current step, rate, ETA without listing all steps.\n\nOutput format:\nMolecule: gt-hanoi-xyz (Towers of Hanoi - 20 disks)\nProgress: 347,892 / 1,048,575 (33.2%)\nCurrent step: gt-hanoi-xyz.move-347893\nRate: ~1,200 steps/hour \nETA: ~9.7 hours remaining\n\nImplementation in beads repo.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-31T00:41:19.487466-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-31T00:55:31.77563-08:00","closed_at":"2025-12-31T00:55:31.77563-08:00","close_reason":"Duplicate of beads work: bd-8xnf, bd-vln0","dependencies":[{"issue_id":"gt-brd1b.1","depends_on_id":"gt-brd1b","type":"parent-child","created_at":"2025-12-31T00:41:19.487963-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-brd1b.2","title":"Add display guards for large molecules","description":"bd mol current and convoy displays need guards:\n- If steps \u003e 100, show summary instead of list\n- Add --range flag for viewing specific step ranges\n- Convoy panel shows count + percentage, not child list","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T00:41:20.398449-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-31T00:55:31.78183-08:00","closed_at":"2025-12-31T00:55:31.78183-08:00","close_reason":"Duplicate of beads work: bd-8xnf, bd-vln0","dependencies":[{"issue_id":"gt-brd1b.2","depends_on_id":"gt-brd1b","type":"parent-child","created_at":"2025-12-31T00:41:20.400612-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-brd1b.3","title":"Update Hanoi formula with agent-actionable instructions","description":"Update towers-of-hanoi.formula.toml description to include:\n- Clear execution protocol for agents\n- What each step means\n- What to do on resume\n- Explicit DO/DO NOT guidance","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-31T00:41:21.20008-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-31T01:11:21.715319-08:00","closed_at":"2025-12-31T01:11:21.715319-08:00","close_reason":"Updated formula with agent-actionable instructions","dependencies":[{"issue_id":"gt-brd1b.3","depends_on_id":"gt-brd1b","type":"parent-child","created_at":"2025-12-31T00:41:21.202309-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-brd1b.4","title":"Run 1K Hanoi demo (10 disks)","description":"End-to-end test:\n1. Cook 20-disk Hanoi formula\n2. Pour as wisp on a polecat\n3. Let it run overnight\n4. Monitor with bd mol progress\n5. Verify completion via convoy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T00:41:22.190102-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T19:54:19.936436-08:00","closed_at":"2026-01-01T19:54:19.936436-08:00","close_reason":"7-disk demo succeeded (127 moves, 21 sec). 10-disk blocked by wisp creation timeout - needs performance optimization.","dependencies":[{"issue_id":"gt-brd1b.4","depends_on_id":"gt-brd1b","type":"parent-child","created_at":"2025-12-31T00:41:22.193323-08:00","created_by":"gastown/crew/max"},{"issue_id":"gt-brd1b.4","depends_on_id":"gt-brd1b.1","type":"blocks","created_at":"2025-12-31T00:41:33.512006-08:00","created_by":"gastown/crew/max"},{"issue_id":"gt-brd1b.4","depends_on_id":"gt-brd1b.3","type":"blocks","created_at":"2025-12-31T00:41:33.538587-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-brndh","title":"Deacon health checks too frequent - disturbs idle agents","description":"Deacon is sending health checks to mayor every few seconds even when idle. This defeats the purpose of the patrol system - agents should NOT be disturbed when there's nothing going on.\n\nProposed fix:\n1. Reduce health check frequency (e.g., every 60s instead of every 5s)\n2. Or: Only health check agents that have active work (hooked molecules)\n3. Or: Mayor shouldn't be health-checked at all since it's human-managed\n\nThe deacon should be silent/invisible when the town is healthy.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2026-01-01T10:07:06.836692-08:00","created_by":"mayor","updated_at":"2026-01-01T18:43:34.574174-08:00","closed_at":"2026-01-01T18:43:34.574174-08:00","close_reason":"Added idle town protocol - skip health nudges when no active work, sleep 60+ seconds between cycles"} -{"id":"gt-bssqy","title":"Digest: mol-deacon-patrol","description":"Patrol 9: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:06:45.381206-08:00","updated_at":"2025-12-28T03:06:45.381206-08:00","closed_at":"2025-12-28T03:06:45.381172-08:00"} -{"id":"gt-bt6xl","title":"Digest: mol-deacon-patrol","description":"Patrol 246 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:19:12.13566-08:00","updated_at":"2026-01-01T17:19:12.13566-08:00","closed_at":"2026-01-01T17:19:12.135622-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-btb45","title":"Session ended: gt-gastown-organic","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:01:27.94689-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-04T16:41:26.007351-08:00","closed_at":"2026-01-04T16:41:26.007351-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/organic","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:01:27-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-organic\",\"worker\":\"organic\"}"} -{"id":"gt-btpoq","title":"Merge: slit-mjui7j71","description":"branch: polecat/slit-mjui7j71\ntarget: main\nsource_issue: slit-mjui7j71\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T13:09:11.624228-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-31T13:10:43.92254-08:00","closed_at":"2025-12-31T13:10:43.92254-08:00","close_reason":"Merged at aa2607ee"} -{"id":"gt-bu532","title":"Session ended: gt-gastown-coma","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:01:22.133415-08:00","created_by":"gastown/polecats/coma","updated_at":"2026-01-04T16:41:26.013038-08:00","closed_at":"2026-01-04T16:41:26.013038-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/coma","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:01:22-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-coma\",\"worker\":\"coma\"}"} -{"id":"gt-bvpnx","title":"Digest: mol-deacon-patrol","description":"Patrol #9: Health pinged all refineries.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:19:17.921098-08:00","updated_at":"2025-12-31T19:19:17.921098-08:00","closed_at":"2025-12-31T19:19:17.921058-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-bwold","title":"Merge: rictus-mjw1g7ny","description":"branch: polecat/rictus-mjw1g7ny\ntarget: main\nsource_issue: rictus-mjw1g7ny\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T15:00:37.883921-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T15:01:56.685032-08:00","closed_at":"2026-01-01T15:01:56.685032-08:00","close_reason":"Merged to main at a395b4e1"} -{"id":"gt-bx4ki","title":"Merge: keeper-dogs","description":"branch: polecat/keeper-dogs\ntarget: main\nsource_issue: keeper-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:53:39.673172-08:00","created_by":"gastown/polecats/keeper","updated_at":"2025-12-30T23:12:54.736253-08:00","closed_at":"2025-12-30T23:12:54.736253-08:00","close_reason":"Branch already merged"} -{"id":"gt-bxck8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All healthy, 4 polecats","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:22:41.205763-08:00","updated_at":"2026-01-01T11:22:41.205763-08:00","closed_at":"2026-01-01T11:22:41.205731-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-by7xm","title":"Digest: mol-deacon-patrol","description":"Cycle 17","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:56:23.15817-08:00","updated_at":"2025-12-31T23:56:23.15817-08:00","closed_at":"2025-12-31T23:56:23.158133-08:00"} -{"id":"gt-byfsg","title":"Session ended: gt-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:50:21.205889-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:41:26.052458-08:00","closed_at":"2026-01-04T16:41:26.052458-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:50:21-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-refinery\",\"worker\":\"refinery\"}"} -{"id":"gt-bykix","title":"Merge: toast-mjxm0mmo","description":"branch: polecat/toast-mjxm0mmo\ntarget: main\nsource_issue: toast-mjxm0mmo\nrig: gastown\nagent_bead: gt-gastown-polecat-toast","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:17:24.095989-08:00","created_by":"gastown/polecats/toast","updated_at":"2026-01-02T17:30:42.152673-08:00","closed_at":"2026-01-02T17:30:42.152673-08:00","close_reason":"Merged to main at 1805d5b0"} -{"id":"gt-bzey4","title":"Add NODE_OPTIONS crash logging to claude invocations","description":"## Background\n\nInvestigation in bd-6df0 found that NODE_OPTIONS can enable Node.js crash reporting for Claude Code:\n\n```bash\nNODE_OPTIONS=\"--report-on-fatalerror --report-uncaught-exception --report-directory=$HOME/.claude/crash-reports\"\n```\n\n## Proposal\n\nModify gt to set NODE_OPTIONS when spawning claude sessions. Key locations in gastown:\n\n- `internal/cmd/up.go` - deacon, witness, crew, polecat spawning\n- `internal/cmd/start.go` - refinery, crew spawning \n- `internal/cmd/mayor.go` - mayor spawning\n- `internal/cmd/handoff.go` - handoff respawning\n- `internal/cmd/crew_helpers.go` - execClaude()\n- `internal/daemon/lifecycle.go` - daemon-managed spawns\n\n## Implementation\n\n1. Create helper function to build NODE_OPTIONS string\n2. Set env var before each claude invocation\n3. Ensure ~/.claude/crash-reports/ directory exists\n4. Optionally add `gt doctor` check to clean old reports\n\n## Benefits\n\n- Crash diagnostics without user config changes\n- All gt-managed sessions automatically covered\n- Reports available for debugging unexpected terminations","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-28T09:32:15.467817-08:00","created_by":"beads/crew/dave","updated_at":"2025-12-28T09:35:03.888171-08:00","closed_at":"2025-12-28T09:35:03.888171-08:00"} -{"id":"gt-bzn8","title":"Test Patrol Parent","description":"[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.\n\nOriginal description:\nTest parent for Christmas Ornament pattern","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-24T00:20:50.418875-08:00","updated_at":"2025-12-27T22:40:44.708514-08:00","closed_at":"2025-12-27T22:40:44.708514-08:00"} -{"id":"gt-c0abr","title":"Digest: mol-deacon-patrol","description":"Patrol 58: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:25:00.40022-08:00","updated_at":"2026-01-01T02:25:00.40022-08:00","closed_at":"2026-01-01T02:25:00.400181-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-c0faj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 63: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:13:30.66765-08:00","updated_at":"2026-01-01T13:13:30.66765-08:00","closed_at":"2026-01-01T13:13:30.667608-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-c0fzm","title":"Parameterize 'read org docs' step in polecat workflows","description":"## Problem\n\nThe mol-polecat-chrome formula has hardcoded paths to strategic docs:\n- ~/gt/docs/hop/CONTEXT.md\n- ~/gt/docs/PRIMING.md\n\nThis limits reusability across different projects/organizations.\n\n## Solution\n\nAdd a `context_docs` variable to the formula that takes a list of document paths:\n\n```toml\n[vars.context_docs]\ndescription = \"Paths to organizational context documents to read before design\"\ndefault = [\"~/gt/docs/hop/CONTEXT.md\", \"~/gt/docs/PRIMING.md\"]\n```\n\n## Usage at cook/wisp time\n\n```bash\n# Use defaults\ngt sling gt-abc gastown -q chrome\n\n# Override for different project\ngt sling gt-abc gastown -q chrome --var context_docs=\"docs/ARCHITECTURE.md,docs/PRINCIPLES.md\"\n```\n\n## Step template\n\nThe step description would interpolate the paths:\n\n```toml\n[[steps]]\nid = \"read-strategic-context\"\ntitle = \"Read organizational context documents\"\ndescription = \"\"\"\nRead the following strategic context documents before designing:\n\n{{#each context_docs}}\n- {{this}}\n{{/each}}\n\nThese contain the vision, principles, and constraints that should guide your work.\n\"\"\"\n```\n\n## Considerations\n\n1. How to handle the array in TOML var syntax?\n2. Should this be a reusable step fragment or inline in chrome?\n3. Default paths should work for Gas Town but be overridable\n\n## Related\n- mol-polecat-chrome.formula.toml (current hardcoded implementation)","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/crew/max","created_at":"2025-12-29T23:12:40.145379-08:00","created_by":"gastown/refinery","updated_at":"2025-12-29T23:17:53.827955-08:00","closed_at":"2025-12-29T23:17:53.827955-08:00","close_reason":"Implemented mol-polecat-chrome formula with parameterized context_docs variable. Default paths point to Gas Town docs, can be overridden via --var context_docs=\"...\" at sling time."} -{"id":"gt-c0juk","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T14:12:40.884153-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.211163-08:00","closed_at":"2026-01-04T16:41:26.211163-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T14:12:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-c0y43","title":"Add convoy_test.go tests","description":"convoy.go (525 lines) has no test coverage","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-30T14:14:28.250781-08:00","created_by":"mayor","updated_at":"2025-12-30T14:14:28.250781-08:00"} -{"id":"gt-c2wd8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All healthy. 3 rigs responding. No issues.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:09:55.524867-08:00","updated_at":"2026-01-01T06:09:55.524867-08:00","closed_at":"2026-01-01T06:09:55.52483-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-c4b83","title":"Consider gt polecats --status=idle for swarm dispatch","description":"The dispatch-swarm-work step in mol-witness-patrol uses a complex jq command to find idle polecats:\n\n```bash\nbd list --type=agent --json | jq '[.[] | select(.description | contains(\"role_type: polecat\") and contains(\"agent_state: idle\"))]'\n```\n\nConsider adding a dedicated command:\n```bash\ngt polecats \u003crig\u003e --status=idle\n```\n\nBenefits:\n- Simpler for formula authors\n- Encapsulates agent bead schema details\n- Could add --json output for programmatic use\n\nLow priority - the jq approach works, this is just ergonomics.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-29T14:36:18.152191-08:00","created_by":"mayor","updated_at":"2025-12-29T14:36:18.152191-08:00"} -{"id":"gt-c4j4j","title":"Witness patrol formula should document 'dead' agent state","description":"## Problem\n\nThe witness patrol formula survey-workers step documents these agent states:\n\n agent_state: running|idle|stuck|done\n\nBut the daemon lifecycle (daemon/lifecycle.go:647) can set agent_state to 'dead'\nwhen an agent goes unresponsive. This state isn't mentioned in the formula.\n\n## Found in commit\n\nf3a6ef6 (feat: Witness reads polecat state from agent beads)\n\n## Suggested fix\n\nUpdate the formula survey-workers step to include 'dead' in the state table:\n\n| agent_state | Meaning | Action |\n|-------------|---------|--------|\n| running | Actively working | Check progress (Step 3) |\n| idle | No work assigned | Skip (no action needed) |\n| stuck | Self-reported stuck | Handle stuck protocol |\n| done | Work complete | Verify cleanup triggered |\n| dead | Marked dead by daemon | Clean up or respawn |","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T09:48:21.452636-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T09:55:13.416985-08:00","closed_at":"2025-12-28T09:55:13.416985-08:00"} -{"id":"gt-c55jv","title":"Digest: mol-deacon-patrol","description":"Patrol 17: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:46:04.311563-08:00","updated_at":"2025-12-26T18:46:04.311563-08:00","closed_at":"2025-12-26T18:46:04.311512-08:00"} -{"id":"gt-c6uai","title":"Merge: dementus-mjxc9ivl","description":"branch: polecat/dementus-mjxc9ivl\ntarget: main\nsource_issue: dementus-mjxc9ivl\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:46:39.854453-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-02T13:41:40.401033-08:00","closed_at":"2026-01-02T13:41:40.401033-08:00","close_reason":"Branches merged, cleaning up stale MR beads"} -{"id":"gt-c7jy4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 33: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:31:13.140269-08:00","updated_at":"2026-01-01T12:31:13.140269-08:00","closed_at":"2026-01-01T12:31:13.140234-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-c7qtp","title":"Merge: rictus-1767084016819","description":"branch: polecat/rictus-1767084016819\ntarget: main\nsource_issue: rictus-1767084016819\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:49:18.335964-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T01:01:04.227169-08:00","closed_at":"2025-12-30T01:01:04.227169-08:00","close_reason":"Already merged to main"} -{"id":"gt-c92","title":"CLI: all command for batch polecat operations","description":"Batch operations across multiple polecats.\n\n## Commands\n\n### gt all start\n```\ngt all start [--awake-only] [\u003cspecs\u003e...]\n```\nStart sessions for multiple polecats.\n- --awake-only: Only start awake polecats\n- specs: Polecat names, rig/polecat patterns\n\n### gt all stop\n```\ngt all stop [\u003cspecs\u003e...] [--force]\n```\nStop sessions for multiple polecats.\n\n### gt all status\n```\ngt all status [\u003cspecs\u003e...] [--json]\n```\nShow status of multiple polecats.\n\n### gt all attach\n```\ngt all attach [\u003cspecs\u003e...]\n```\nAttach to multiple sessions in tmux panes/windows.\n\n### gt all run\n```\ngt all run \u003ccommand\u003e [\u003cspecs\u003e...]\n```\nRun command in multiple polecat sessions.\n\n## Spec Patterns\n- `Toast`: Specific polecat (in default/current rig)\n- `gastown/Toast`: Specific rig/polecat\n- `gastown/*`: All polecats in rig\n- `*`: All polecats everywhere\n\n## Implementation\n```go\nfunc expandSpecs(specs []string, awakeOnly bool) ([]*polecat.Polecat, error) {\n // Expand patterns to list of polecats\n}\n\nfunc runForAll(polecats []*polecat.Polecat, action func(*polecat.Polecat) error) error {\n // Run action for each, collect errors\n}\n```\n\n## New File\ninternal/cmd/all.go\n\n## PGT Reference\ngastown-py/src/gastown/cli/all_cmd.py\n\n## Acceptance Criteria\n- [ ] Pattern expansion works\n- [ ] Parallel execution where safe\n- [ ] Aggregate error reporting\n- [ ] --awake-only filter works","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:48:12.411789-08:00","updated_at":"2025-12-16T16:05:47.255503-08:00"} -{"id":"gt-camx5","title":"Campaign: Large-Scale Work Graph Execution","description":"A Campaign is a Molecule-wrapped Epic graph ready for orchestrated execution.\n\n## Concept\n\nCampaign = Molecule + Epics + Dependency Graph + Execution Strategy\n\nKey properties:\n1. **Work graph**: Linked epics with dependency edges (possibly from different authors)\n2. **Combinators as glue**: \u003e\u003e, |, wrap define bridging/shaping between epics\n3. **Molecule shell**: Provides execution state, persistence across sessions\n4. **Witness-aware**: Can be parallelized across polecats on independent branches\n5. **Single-rig scoped**: One rig executes it (spans sessions/polecats)\n\n## The \"Maximum Speed\" Model\n\nWitness becomes a scheduler that:\n- Watches campaign progress\n- Identifies ready nodes (all dependencies satisfied)\n- Spawns/assigns polecats to ready nodes\n- Respects parallelism constraints\n- Handles failures (retry? skip? escalate?)\n\n## Where Campaign Fits in MEOW\n\nCampaign is the convergence point where work-tracking meets workflow-execution:\n- An Epic-of-Epics (work dimension)\n- A Molecule (workflow dimension)\n\n## Open Questions\n\n1. Campaign creation UX - manual wire vs declare intent?\n2. Partial completion - can you commit progress and resume?\n3. Distinct entity type or molecule with type=\"campaign\"?\n4. Cross-rig campaigns - can graph span multiple rigs?\n\n## Related\n\n- docs/formula_evolution.md - original discussion\n- gt-8tmz - molecule algebra (foundation)\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:00:51.274207-08:00","updated_at":"2025-12-28T22:33:22.323308-08:00","closed_at":"2025-12-28T22:33:22.323308-08:00"} -{"id":"gt-cb63d","title":"Digest: mol-deacon-patrol","description":"Patrol 48: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:20:39.790642-08:00","updated_at":"2026-01-01T02:20:39.790642-08:00","closed_at":"2026-01-01T02:20:39.790597-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cbjzr","title":"Break up long functions in start.go","description":"Several functions in internal/cmd/start.go exceed recommended length:\n- runStart: 126 lines (129-255) - handles mayor, deacon, rig agents, crew auto-start\n- runStartCrew: 155 lines (638-792) - handles crew target parsing, workspace, session\n- cleanupPolecats: 91 lines (543-634) - handles polecat cleanup loop\n\nSuggestion: Extract into focused helpers:\n- runStart → startMayorAndDeacon(), startRigAgents(), startConfiguredCrew()\n- runStartCrew → parseCrewTarget(), ensureCrewWorkspace(), startOrAttachCrewSession()\n- cleanupPolecats → cleanupSinglePolecat()","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:43:11.539536-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:17.365109-08:00","closed_at":"2025-12-28T15:47:17.365109-08:00"} -{"id":"gt-cbstf","title":"gt convoy status: Show assignee and actual status for tracked issues","description":"Currently convoy status shows all open issues as ○ with no distinction:\n\n```\n○ gt-27bzi: Add gt mail announces command [task]\n○ gt-pn2fq: Add isAnnounceAddress() helpers [task]\n○ gt-q73h3: Implement sendToAnnounce() [task]\n```\n\nBut these issues have different statuses and assignees:\n- gt-pn2fq: closed (immortan) - should show ✓\n- gt-q73h3: hooked (bullet) - should show 🔨 or similar\n- gt-27bzi: in_progress (toecutter) - should show ▶\n\n## Proposed display\n\n```\n✓ gt-pn2fq: Add isAnnounceAddress() helpers [immortan]\n▶ gt-q73h3: Implement sendToAnnounce() [bullet]\n▶ gt-27bzi: Add gt mail announces command [toecutter]\n```\n\nShow actual status symbols and assignee in brackets.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/goose","created_at":"2026-01-02T00:10:31.749973-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-02T00:19:22.756862-08:00","closed_at":"2026-01-02T00:19:22.756862-08:00","close_reason":"Implemented in add754c9"} -{"id":"gt-cbxs5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:03:03.262689-08:00","updated_at":"2026-01-01T20:03:03.262689-08:00","closed_at":"2026-01-01T20:03:03.26265-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-cd5bi","title":"Digest: mol-deacon-patrol","description":"Patrol 15: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:45:00.403136-08:00","updated_at":"2025-12-26T18:45:00.403136-08:00","closed_at":"2025-12-26T18:45:00.403089-08:00"} -{"id":"gt-cehl8","title":"gt done: Fails in worktrees due to missing origin tracking ref","description":"In polecats (git worktrees), after git push -u origin \u003cbranch\u003e, the origin/\u003cbranch\u003e ref doesn't exist locally. This causes gt done to fail with 'unknown revision' when checking unpushed commits.\n\n**Workaround**: After pushing, manually create the ref:\n```bash\ngit fetch origin \u003cbranch\u003e\ngit update-ref refs/remotes/origin/\u003cbranch\u003e FETCH_HEAD\ngt done\n```\n\nRoot cause: Worktrees may not have the same fetch refspecs as the main repo. The tracking is set but the remote ref isn't fetched into refs/remotes/.\n\nFix: gt done should handle this edge case, perhaps by checking the remote directly or creating the ref after detecting the issue.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T23:03:28.318996-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-31T13:10:50.986314-08:00","closed_at":"2025-12-31T13:10:50.986314-08:00","close_reason":"Fixed: BranchPushedToRemote now creates missing remote tracking refs from FETCH_HEAD after fetch in worktrees"} -{"id":"gt-cekg","title":"Wisp squash design: cadences, rules, templates","description":"Design how wisps squash to digests: When to squash (cadences), what to include (summary templates), retention rules. Currently under-designed. Should cover patrol wisps (squash per cycle) and work wisps (squash on completion). Consider allowing formulas to define squash templates.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/warboy","created_at":"2025-12-23T18:45:27.315937-08:00","updated_at":"2025-12-30T07:05:28.841064-08:00","closed_at":"2025-12-30T07:05:28.841064-08:00","close_reason":"Designed wisp squash system: cadences (per-cycle for patrols, on-complete for work), summary templates (structured formats, formula-defined), retention rules (30d active, 1yr archive, rollups). See docs/wisp-squash-design.md"} -{"id":"gt-ceoow","title":"Digest: mol-deacon-patrol","description":"Patrol 44: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:18:54.097483-08:00","updated_at":"2026-01-01T02:18:54.097483-08:00","closed_at":"2026-01-01T02:18:54.097444-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cfnez","title":"Digest: mol-deacon-patrol","description":"Patrol #8: Refineries healthy. Beads 5 pending, gastown 1 pending.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:18:50.217167-08:00","updated_at":"2025-12-31T19:18:50.217167-08:00","closed_at":"2025-12-31T19:18:50.217135-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cfpd8","title":"Merge: capable-mq","description":"branch: polecat/capable-mq-events\ntarget: main\nsource_issue: capable-mq\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:14:13.646596-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T10:06:56.829536-08:00","closed_at":"2025-12-30T10:06:56.829536-08:00","close_reason":"Branch merged to main"} -{"id":"gt-cfuj7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 32: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:29:48.544097-08:00","updated_at":"2026-01-01T12:29:48.544097-08:00","closed_at":"2026-01-01T12:29:48.544058-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cgneg","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:40:08.418566-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-05T21:40:08.474043-08:00","closed_at":"2026-01-05T21:40:08.474043-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:40:08-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-chbut","title":"Merge: gt-k1sl4","description":"branch: polecat/dementus-mjtlqmya\ntarget: main\nsource_issue: gt-k1sl4\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:00:47.087132-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T23:12:54.597377-08:00","closed_at":"2025-12-30T23:12:54.597377-08:00","close_reason":"Branch already merged"} -{"id":"gt-chk7z","title":"Extract interfaces for Git and Tmux to enable testing","description":"Git and Tmux packages use concrete types that make testing difficult:\n\ninternal/git/git.go:\n- Git struct with 40+ methods\n- No interface - tests must use real git\n- Many packages directly depend on concrete type\n\ninternal/tmux/tmux.go:\n- Tmux struct with 30+ methods\n- No interface - tests must use real tmux\n- Contains Claude-specific detection logic mixed in\n\nSuggestion:\n1. Extract GitOperations interface with common operations\n2. Extract TmuxRunner interface for subprocess operations\n3. Allow mock injection for unit tests\n4. Move Claude-specific tmux logic to internal/claude/","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:43:16.088336-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:21.180477-08:00","closed_at":"2025-12-28T15:47:21.180477-08:00"} -{"id":"gt-ci5qk","title":"Digest: mol-deacon-patrol","description":"Patrol 6 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:42:41.84958-08:00","updated_at":"2025-12-31T16:42:41.84958-08:00","closed_at":"2025-12-31T16:42:41.84954-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cicem","title":"Digest: mol-deacon-patrol","description":"Patrol 17: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:10:23.403733-08:00","updated_at":"2025-12-28T03:10:23.403733-08:00","closed_at":"2025-12-28T03:10:23.403694-08:00"} -{"id":"gt-cij5e","title":"Session ended: gt-gastown-road-warrior","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:48:57.688439-08:00","created_by":"gastown/polecats/road-warrior","updated_at":"2026-01-05T00:08:31.546961-08:00","closed_at":"2026-01-05T00:08:31.546961-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/road","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:48:57-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-road-warrior\",\"worker\":\"road\"}"} -{"id":"gt-cio03","title":"Phase 2: Update Refinery to merge local branches","description":"Change Refinery to access polecat branches locally instead of fetching from origin.\n\nFiles:\n- internal/refinery/engineer.go:233-260 (doMerge)\n - Remove FetchBranch('origin', branch) call\n - Add BranchExists() check for local branch\n - Change 'origin/\u003cbranch\u003e' refs to local '\u003cbranch\u003e'\n - Update CheckConflicts() and MergeNoFF() calls\n\nKey insight: Refinery worktree shares .repo.git with polecat worktrees - branches are already visible locally.\n\nMigration: Add fallback to origin/\u003cbranch\u003e for in-flight MRs pushed under old system.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:36:56.197543-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:15:10.085985-08:00","closed_at":"2026-01-06T13:15:10.085985-08:00","close_reason":"Refinery now merges local branches instead of fetching from origin","dependencies":[{"issue_id":"gt-cio03","depends_on_id":"gt-5fmjt","type":"blocks","created_at":"2026-01-06T12:37:09.158945-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-cio03","depends_on_id":"gt-dymy5","type":"blocks","created_at":"2026-01-06T12:37:09.346493-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-cj5ha","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T12:53:25.019759-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T12:53:25.069905-08:00","closed_at":"2026-01-06T12:53:25.069905-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T12:53:24-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-cjg2t","title":"Session ended: gt-gastown-bullet","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:56:35.982386-08:00","created_by":"gastown/polecats/bullet","updated_at":"2026-01-04T16:40:22.829974-08:00","closed_at":"2026-01-04T16:40:22.829974-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/bullet","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:56:35-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-bullet\",\"worker\":\"bullet\"}"} -{"id":"gt-cjr8x","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:20:31.771957-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:25.984341-08:00","closed_at":"2026-01-04T16:41:25.984341-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:20:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-cku0f","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:39:02.274171-08:00","updated_at":"2025-12-31T23:39:02.274171-08:00","closed_at":"2025-12-31T23:39:02.274135-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cl9k7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:34:43.816547-08:00","updated_at":"2025-12-31T23:34:43.816547-08:00","closed_at":"2025-12-31T23:34:43.816513-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-clbz6","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:36.51872-08:00","updated_at":"2025-12-28T11:22:36.51872-08:00","closed_at":"2025-12-28T11:22:36.518686-08:00"} -{"id":"gt-clgy8","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:56:57.604026-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.686849-08:00","closed_at":"2026-01-04T16:40:22.686849-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:56:57-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-cljtr","title":"Digest: mol-deacon-patrol","description":"Cycle 197: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:24:20.08789-08:00","updated_at":"2026-01-01T16:24:20.08789-08:00","closed_at":"2026-01-01T16:24:20.08786-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-cljtr","depends_on_id":"gt-eph-tc8v","type":"parent-child","created_at":"2026-01-01T16:24:20.08924-08:00","created_by":"deacon"}]} -{"id":"gt-cloml","title":"Witness: Escalate dormant polecats with unpushed work (don't auto-nuke)","description":"Witness escalation for dormant polecats should distinguish between safe-to-nuke and needs-recovery.\n\n## Problem\nWitness detected 4 dormant polecats with unpushed commits (hq-ww5ev) but by the time Mayor processed the mail, the polecats were nuked during cleanup, losing work.\n\n## Fix\n1. Witness dormancy check should read cleanup_status from agent bead\n2. If has_unpushed or has_uncommitted: mark as NEEDS_RECOVERY, escalate\n3. If clean: safe to nuke\n4. NEVER auto-nuke polecats with unpushed work\n\n## Escalation Format\nSubject: RECOVERY_NEEDED \u003cpolecat\u003e\nBody includes: unpushed commit SHAs, branch name, issue ID","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-30T19:07:15.78522-08:00","created_by":"mayor","updated_at":"2025-12-30T20:59:58.101184-08:00","closed_at":"2025-12-30T20:59:58.101184-08:00","close_reason":"Implemented recovery escalation for dormant polecats with unpushed work"} -{"id":"gt-cmf1c","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All 3 rigs healthy, 12 polecats active, no zombies, no orphans, inbox clear","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:16:59.316775-08:00","updated_at":"2026-01-01T20:16:59.316775-08:00","closed_at":"2026-01-01T20:16:59.316733-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-cn06k","title":"Digest: mol-deacon-patrol","description":"Patrol 42: All healthy, 6 agents pinged, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:17:54.689482-08:00","updated_at":"2026-01-01T02:17:54.689482-08:00","closed_at":"2026-01-01T02:17:54.689443-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cn4oa","title":"Merge: rictus-mjuic92c","description":"branch: polecat/rictus-mjuic92c\ntarget: main\nsource_issue: rictus-mjuic92c\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T13:58:03.160159-08:00","created_by":"mayor","updated_at":"2025-12-31T14:02:59.740747-08:00","closed_at":"2025-12-31T14:02:59.740747-08:00","close_reason":"Already merged at 04289226"} -{"id":"gt-cn526","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy. 3 rigs, 6 agents. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:06:08.356449-08:00","updated_at":"2026-01-01T08:06:08.356449-08:00","closed_at":"2026-01-01T08:06:08.356412-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cnj9y","title":"Review PR #180: git init before beads","description":"dispatched_by: gastown/crew/joe","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/gus","created_at":"2026-01-05T19:11:11.27653-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:14:52.703176-08:00","closed_at":"2026-01-05T19:14:52.703176-08:00","close_reason":"PR #180 reviewed, approved, and merged"} -{"id":"gt-cnyz5","title":"Session ended: gt-gastown-wraith","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:19:41.873093-08:00","created_by":"gastown/polecats/wraith","updated_at":"2026-01-05T19:44:41.853112-08:00","closed_at":"2026-01-05T19:44:41.853112-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/wraith","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:19:41-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-wraith\",\"worker\":\"wraith\"}"} -{"id":"gt-cp9bt","title":"Deacon health checks too frequent - disturbs idle agents","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/toast","created_at":"2026-01-01T10:06:17.324458-08:00","created_by":"mayor","updated_at":"2026-01-01T18:14:29.621973-08:00","closed_at":"2026-01-01T18:14:29.621973-08:00","close_reason":"Modified mol-deacon-patrol.formula.toml to make health check nudges conditional - only sent when concerning signals detected (agent not running, status check fails, queue stuck). Previously nudges were sent every 1-2 minute patrol cycle."} -{"id":"gt-cpvhq","title":"Merge: dementus-mjw062kt","description":"branch: polecat/dementus-mjw062kt\ntarget: main\nsource_issue: dementus-mjw062kt\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T14:17:19.331005-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-01T14:18:38.656677-08:00","closed_at":"2026-01-01T14:18:38.656677-08:00","close_reason":"Merged to main at f9f55170"} -{"id":"gt-cpvxg","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:23:33.859968-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.642259-08:00","closed_at":"2026-01-05T00:08:31.642259-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:23:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-cpxxv","title":"Merge: organic-1767106082951","description":"branch: polecat/organic-1767106082951\ntarget: main\nsource_issue: organic-1767106082951\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:42:25.2268-08:00","created_by":"gastown/polecats/organic","updated_at":"2025-12-30T18:23:22.208549-08:00","closed_at":"2025-12-30T18:23:22.208549-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-cq1yw","title":"Digest: mol-deacon-patrol","description":"Patrol 155: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:06:05.242792-08:00","updated_at":"2026-01-01T15:06:05.242792-08:00","closed_at":"2026-01-01T15:06:05.242748-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cqbew","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:17:50.546221-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.267366-08:00","closed_at":"2026-01-04T16:40:13.267366-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:17:50-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-cqkmz","title":"Merge: capable-mjxb80jf","description":"branch: polecat/capable-mjxb80jf\ntarget: main\nsource_issue: capable-mjxb80jf\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:15:41.581978-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T12:30:29.687223-08:00","closed_at":"2026-01-02T12:30:29.687223-08:00","close_reason":"Merged to main at 1f72285a"} -{"id":"gt-cqvgt","title":"Implement announce:name address type for bulletin-board messaging","description":"Add support for announce:name addresses for read-only bulletin boards.\n\nSEMANTICS:\n- Messages to announce:name create ONE copy in shared location\n- All eligible readers can read (no claiming, no removal)\n- Messages retained up to retain_count, oldest pruned\n- No inbox pollution - readers check the announce channel explicitly\n\nUSE CASE:\nLow urgency broadcast that does not need ack, e.g. clean up your branches.\n\nIMPLEMENTATION:\n1. Add isAnnounceAddress() / parseAnnounceName() helpers\n2. Add sendToAnnounce() - creates message in announce location\n3. Add gt mail announces - list available announce channels\n4. Add gt mail read-announce \u003cchannel\u003e - read messages from channel\n5. Add retention pruning on new message\n\nCONFIG (already in messaging.json schema):\nannounces.alerts.readers = [@town]\nannounces.alerts.retain_count = 100","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-30T18:09:49.463812-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T18:09:49.463812-08:00","dependencies":[{"issue_id":"gt-cqvgt","depends_on_id":"gt-27bzi","type":"blocks","created_at":"2025-12-30T18:17:27.476669-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-cqw0n","title":"Phase 3: Update polecat templates and docs","description":"Remove push instructions from polecat documentation and templates.\n\nFiles:\n- templates/polecat-CLAUDE.md:153,159 - Remove push from checklist\n- internal/formula/formulas/mol-polecat-work.formula.toml:365-368 - Remove push step\n- internal/templates/roles/polecat.md.tmpl - Update completion protocol\n- internal/templates/roles/refinery.md.tmpl:227-229 - Update to show local branch access\n\nNew checklist:\n1. Tests pass\n2. Commit changes\n3. Sync beads\n4. gt done --exit\n\nNo push step needed.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T12:36:57.742043-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:12:01.720948-08:00","closed_at":"2026-01-06T13:12:01.720948-08:00","close_reason":"Phase 3 complete: removed push instructions from polecat templates and docs","dependencies":[{"issue_id":"gt-cqw0n","depends_on_id":"gt-5fmjt","type":"blocks","created_at":"2026-01-06T12:37:09.204499-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-cqw0n","depends_on_id":"gt-dymy5","type":"blocks","created_at":"2026-01-06T12:37:09.393913-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-crew-gastown-fang","title":"Crew worker fang in gastown - human-managed persistent workspace.","description":"Crew worker fang in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-gastown-fang-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T13:00:25.364965-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:30:47.614031-08:00","closed_at":"2025-12-29T14:30:47.614031-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-gastown-grip","title":"Crew worker grip in gastown - human-managed persistent workspace.","description":"Crew worker grip in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-gastown-grip-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T13:00:11.479646-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:30:47.620572-08:00","closed_at":"2025-12-29T14:30:47.620572-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-gastown-jack","title":"Crew worker jack in gastown - human-managed persistent workspace.","description":"Crew worker jack in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-crew-gastown-jack-role","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T10:06:26.487688-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:30:47.626584-08:00","closed_at":"2025-12-29T14:30:47.626584-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-gastown-joe","title":"gt-crew-gastown-joe","description":"gt-crew-gastown-joe\n\nrole_type: \nrig: null\nagent_state: running\nhook_bead: null\nrole_bead: null\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T10:04:05.03443-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T14:48:00.681115-08:00","closed_at":"2025-12-29T14:30:47.632199-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-gastown-max","title":"gt-crew-gastown-max","description":"gt-crew-gastown-max\n\nrole_type: crew\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-crew-gastown-max-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T09:51:58.720059-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T15:01:06.25399-08:00","closed_at":"2025-12-29T14:30:47.637875-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-gastown-wolf","title":"Crew worker wolf in gastown - human-managed persistent workspace.","description":"Crew worker wolf in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-gastown-wolf-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T13:00:39.799433-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:30:47.606388-08:00","closed_at":"2025-12-29T14:30:47.606388-08:00","close_reason":"Migrated to canonical naming: gt-gastown-crew-\u003cname\u003e","role_bead":"gt-crew-role"} -{"id":"gt-crew-role","title":"Crew Role Definition","description":"You are a Crew Worker - a human-managed persistent workspace within a rig.\n\nUnlike polecats which are witness-managed and transient, crew workers are:\n- Persistent: Not auto-garbage-collected\n- User-managed: Overseer controls lifecycle\n- Long-lived identities: Keep your name across sessions\n- Gas Town integrated: Mail, handoff mechanics work\n\nsession_pattern: gt-{rig}-crew-{name}\nwork_dir_pattern: {town}/{rig}/crew/{name}\nneeds_pre_sync: true\nstart_command: exec claude --dangerously-skip-permissions\n\ndefault_molecule: null\ncapabilities:\n - autonomous_work\n - beads_access\n - git_operations\n - mail_communication\n\n## Core Responsibilities\n\n1. Execute assigned work autonomously\n2. Track progress via beads (bd commands)\n3. Communicate via mail when blocked or complete\n4. Maintain clean git state\n5. Hand off context when cycling sessions\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nHook has work then Run it. Hook empty then Check mail. Nothing then Wait for overseer.\n\n## Session End Protocol\n\n- git status, git add, bd sync, git commit, git push\n- gt handoff - hand off to fresh session\n\n## Key Commands\n\n- gt mol status - Check your hook\n- bd ready - Find next step\n- bd close \u003cid\u003e - Mark work complete\n- gt mail inbox - Check messages\n- gt handoff - Cycle to fresh session","status":"hooked","priority":2,"issue_type":"role","assignee":"gastown/polecats/dementus","created_at":"2025-12-29T13:23:55.830567-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T02:03:27.407163-08:00","labels":["migrated-to:hq-crew-role"]} -{"id":"gt-crh3q","title":"Digest: mol-deacon-patrol","description":"Patrol 1: all agents healthy, no callbacks, clone divergence detected (zoey 52 behind)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:26:07.334875-08:00","updated_at":"2025-12-28T01:26:07.334875-08:00","closed_at":"2025-12-28T01:26:07.334841-08:00"} -{"id":"gt-cryer","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:27:46.938621-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-04T16:41:26.170694-08:00","closed_at":"2026-01-04T16:41:26.170694-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:27:46-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-csbjj","title":"Errant redirect file in .beads/ causes chain warnings","description":"A redirect file appeared in gastown/mayor/rig/.beads/ alongside the actual beads.db, causing 'redirect chains not allowed' warnings. The redirect pointed to ../../mayor/rig/.beads which is circular. Had to manually delete the redirect file.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T00:11:29.08669-08:00","created_by":"mayor","updated_at":"2025-12-30T00:46:59.227299-08:00","closed_at":"2025-12-30T00:46:59.227299-08:00","close_reason":"Fixed: Added circular redirect detection to ResolveBeadsDir (auto-removes errant redirects) and added safety checks to ensureBeadsRedirect to prevent creating redirects in canonical beads location"} -{"id":"gt-csmlp","title":"Digest: mol-deacon-patrol","description":"Patrol 6: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:40:07.959422-08:00","updated_at":"2025-12-26T18:40:07.959422-08:00","closed_at":"2025-12-26T18:40:07.959369-08:00"} -{"id":"gt-ctmsq","title":"Digest: mol-deacon-patrol","description":"Patrol 1: 3 rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:20:09.664837-08:00","updated_at":"2026-01-01T04:20:09.664837-08:00","closed_at":"2026-01-01T04:20:09.664801-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cueyr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 54: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:58:38.645823-08:00","updated_at":"2026-01-01T12:58:38.645823-08:00","closed_at":"2026-01-01T12:58:38.645789-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cw2y2","title":"Merge: gt-84ery","description":"branch: polecat/dementus-mjtlqmya\ntarget: main\nsource_issue: gt-84ery\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:29:47.784756-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T23:12:37.316655-08:00","closed_at":"2025-12-30T23:12:37.316655-08:00","close_reason":"Branch already merged"} -{"id":"gt-cw6y2","title":"Merge: prime-mk0rmco7","description":"branch: polecat/prime-mk0rmco7\ntarget: main\nsource_issue: prime-mk0rmco7\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T22:18:44.820343-08:00","created_by":"gastown/polecats/prime","updated_at":"2026-01-04T23:48:35.936655-08:00","closed_at":"2026-01-04T23:48:35.936655-08:00","close_reason":"Merged to main at e0ba0578"} -{"id":"gt-cxtey","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 56: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:59:46.356778-08:00","updated_at":"2026-01-01T12:59:46.356778-08:00","closed_at":"2026-01-01T12:59:46.356743-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cxwc4","title":"Merge: gt-jhr85","description":"branch: polecat/slit-mjxlyyte\ntarget: main\nsource_issue: gt-jhr85\nrig: gastown\nagent_bead: gt-mayor","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:45:11.588152-08:00","created_by":"mayor","updated_at":"2026-01-02T17:49:16.518927-08:00","closed_at":"2026-01-02T17:49:16.518927-08:00","close_reason":"Merged to main at f4a82337 (slit-mjxlyyte commands feature)"} -{"id":"gt-cy1e8","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:33:51.822588-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.774188-08:00","closed_at":"2026-01-05T00:08:31.774188-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:33:51-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-cy76n","title":"Digest: mol-deacon-patrol","description":"Patrol 252 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:22:13.906187-08:00","updated_at":"2026-01-01T17:22:13.906187-08:00","closed_at":"2026-01-01T17:22:13.906151-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cyxyu","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:19:54.939523-08:00","updated_at":"2026-01-01T05:19:54.939523-08:00","closed_at":"2026-01-01T05:19:54.939489-08:00","dependencies":[{"issue_id":"gt-cyxyu","depends_on_id":"gt-eph-2tqd","type":"parent-child","created_at":"2026-01-01T05:19:54.940735-08:00","created_by":"deacon"}]} -{"id":"gt-cz2je","title":"Digest: mol-deacon-patrol","description":"Patrol 121: All healthy, no callbacks, 3 convoys tracking","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T21:49:17.42153-08:00","updated_at":"2025-12-30T21:49:17.42153-08:00","closed_at":"2025-12-30T21:49:17.421493-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-cznhd","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:58:12.676416-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.793091-08:00","closed_at":"2026-01-04T16:40:22.793091-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:58:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-czviq","title":"Session ended: gt-gastown/crew/jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T16:12:00.791347-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.115402-08:00","closed_at":"2026-01-04T16:41:26.115402-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T16:12:00-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/jack\",\"worker\":\"gastown/crew/jack\"}"} -{"id":"gt-d0a","title":"Haiku-based smart stuck detection","description":"Use Haiku to analyze tmux state when signals are ambiguous.\n\n## When to Invoke\n\nOnly as escalation tier:\n1. Keepalive is stale (\u003e 2 min)\n2. Tmux shows claude is running (not idle shell)\n3. Heuristics can't determine state\n\n## Prompt\n\nCapture last 50 lines of tmux pane, ask Haiku:\n'Is this Claude agent: WORKING | STUCK | IDLE | WAITING_FOR_HUMAN?'\n\n## Cost\n\n~$0.001 per check. At 1 check/min worst case = $0.06/hour.\nIn practice, most checks avoided by keepalive signal.\n\n## Configuration\n\n```toml\n[daemon]\nsmart_detection = true\nsmart_model = \"haiku\"\nsmart_threshold = \"2m\" # only check if stale \u003e 2min\n```","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-18T14:19:31.287215-08:00","updated_at":"2025-12-18T14:19:31.287215-08:00","dependencies":[{"issue_id":"gt-d0a","depends_on_id":"gt-bfd","type":"blocks","created_at":"2025-12-18T14:19:46.788667-08:00","created_by":"daemon"}]} -{"id":"gt-d0dmh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:21:07.586493-08:00","updated_at":"2026-01-01T06:21:07.586493-08:00","closed_at":"2026-01-01T06:21:07.58646-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-d0e0x","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 41: All agents healthy, no pending spawns, no orphans, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:49:57.403064-08:00","updated_at":"2026-01-01T12:49:57.403064-08:00","closed_at":"2026-01-01T12:49:57.403032-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-d0h4e","title":"Cleanup stale .beads-wisp references in docs and formulas","description":"The .beads-wisp/ approach was eradicated. Wisps now live in main beads. These files still reference the old approach:\n\n- docs/polecat-wisp-architecture.md (line 15)\n- .beads/formulas/mol-session-gc.formula.toml (line 165)\n- .beads/formulas/mol-boot-triage.formula.toml (line 50)\n- .beads/formulas/mol-orphan-scan.formula.toml (lines 144, 233)\n\nUpdate or remove these references to reflect current architecture.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/prime","created_at":"2026-01-04T21:58:59.561517-08:00","created_by":"mayor","updated_at":"2026-01-04T22:18:09.736707-08:00","closed_at":"2026-01-04T22:18:09.736707-08:00","close_reason":"Cleaned up all .beads-wisp references in docs and formulas. Wisps now reference .beads/ with type=wisp."} -{"id":"gt-d0jqp","title":"Pillar 1: Agent Identity (agent-as-bead)","description":"Agents become beads with deterministic IDs, hook slots, role beads, and self-reported state.\n\nKey deliverables:\n- Agent bead schema (type=agent, hook_bead, role_bead, state fields)\n- bd slot set/clear commands\n- Agent beads for mayor, witness, refinery\n- Role beads from current CLAUDE.md content\n- Hook lookup via agent bead\n\nReference: ~/gt/docs/agent-as-bead.md\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T20:56:04.38659-08:00","created_by":"mayor","updated_at":"2025-12-28T02:04:34.432178-08:00","closed_at":"2025-12-28T02:04:34.432178-08:00"} -{"id":"gt-d360v","title":"Digest: mol-deacon-patrol","description":"Patrol 16: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:07:30.804308-08:00","updated_at":"2025-12-31T19:07:30.804308-08:00","closed_at":"2025-12-31T19:07:30.804272-08:00","dependencies":[{"issue_id":"gt-d360v","depends_on_id":"gt-eph-xtzl","type":"parent-child","created_at":"2025-12-31T19:07:30.805485-08:00","created_by":"deacon"}]} -{"id":"gt-d39ma","title":"Digest: mol-deacon-patrol","description":"Patrol 138: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:38:38.036904-08:00","updated_at":"2026-01-01T14:38:38.036904-08:00","closed_at":"2026-01-01T14:38:38.036869-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-d3z69","title":"Merge: scrotus-mk083pw5","description":"branch: polecat/scrotus-mk083pw5\ntarget: main\nsource_issue: scrotus-mk083pw5\nrig: gastown\nagent_bead: gt-gastown-polecat-scrotus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T13:18:11.686308-08:00","created_by":"gastown/polecats/scrotus","updated_at":"2026-01-04T13:54:14.572201-08:00","closed_at":"2026-01-04T13:54:14.572201-08:00","close_reason":"Merged to main"} -{"id":"gt-d46","title":"Mail CLI: archive, purge, search, mark","description":"GGT mail CLI needs more commands for mail management.\n\n## Commands to Add\n\n### gt mail check\nCheck for new mail without full inbox display.\n```\ngt mail check [--quiet] [--inject]\n```\n- --quiet: Only output if new mail (for scripts)\n- --inject: Send notification to running session\n\n### gt mail mark\nChange read status.\n```\ngt mail mark \u003cid\u003e --read\ngt mail mark \u003cid\u003e --unread\n```\n\n### gt mail delete\nRemove message from inbox.\n```\ngt mail delete \u003cid\u003e [--force]\n```\n- Confirm unless --force\n\n### gt mail archive\nMove old/read messages to archive.\n```\ngt mail archive [--older-than DAYS] [--all-read] [--dry-run]\n```\n- Creates inbox.jsonl.archive or separate archive.jsonl\n\n### gt mail purge\nPermanently delete archived messages.\n```\ngt mail purge [--older-than DAYS] [--dry-run] [--force]\n```\n\n### gt mail search\nFind messages by content.\n```\ngt mail search \u003cquery\u003e [--from SENDER] [--subject] [--body]\n```\n\n### gt mail reply\nReply to a message.\n```\ngt mail reply \u003cid\u003e -m BODY\n```\n- Auto-sets reply_to and thread_id\n- Auto-addresses to original sender\n\n## Files to Modify\n- internal/cmd/mail.go: Add commands\n- internal/mail/mailbox.go: Add Archive(), Search(), Delete()\n\n## Acceptance Criteria\n- [ ] All commands implemented\n- [ ] Archive stores in separate file\n- [ ] Search supports regex patterns\n- [ ] Delete confirms by default","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:46:57.158136-08:00","updated_at":"2026-01-01T20:31:49.866032-08:00","closed_at":"2026-01-01T20:31:49.866032-08:00","close_reason":"Implemented all mail CLI commands: mark, delete with confirmation, batch archive, purge, and search with regex support"} -{"id":"gt-d46.1","title":"gt mail check: Check for new mail","description":"Add `gt mail check` command.\n\n```\ngt mail check [--quiet] [--inject]\n```\n\n- --quiet: Only output if new mail (for scripts/hooks)\n- --inject: Send notification to running session (future)\n\n**Implementation:**\n- Add `checkCmd` to internal/cmd/mail.go\n- Count unread messages in inbox\n- Output: 'N new message(s)' or nothing if --quiet and empty\n\nSimple command, good first task.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2026-01-01T20:17:53.030199-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:16:00.550271-08:00","closed_at":"2026-01-01T23:16:00.550271-08:00","close_reason":"Implemented --quiet flag for gt mail check","dependencies":[{"issue_id":"gt-d46.1","depends_on_id":"gt-d46","type":"parent-child","created_at":"2026-01-01T20:17:53.033331-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-d46.2","title":"gt mail mark/delete: Basic message operations","description":"Add `gt mail mark` and `gt mail delete` commands.\n\n### gt mail mark\n```\ngt mail mark \u003cid\u003e --read\ngt mail mark \u003cid\u003e --unread\n```\n- Update message read status in inbox.jsonl\n\n### gt mail delete\n```\ngt mail delete \u003cid\u003e [--force]\n```\n- Remove message from inbox\n- Confirm unless --force\n\n**Implementation:**\n- Add to internal/cmd/mail.go\n- Add MarkRead(), Delete() to internal/mail/mailbox.go\n- Rewrite inbox.jsonl without deleted message","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/warboy","created_at":"2026-01-01T20:17:54.070643-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:16:33.450648-08:00","closed_at":"2026-01-01T23:16:33.450648-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gt-d46.2","depends_on_id":"gt-d46","type":"parent-child","created_at":"2026-01-01T20:17:54.073315-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-d46.3","title":"gt mail archive/purge: Archive management","description":"Add `gt mail archive` and `gt mail purge` commands.\n\n### gt mail archive\n```\ngt mail archive [--older-than DAYS] [--all-read] [--dry-run]\n```\n- Move messages from inbox.jsonl to archive.jsonl\n- Default: archive read messages older than 7 days\n\n### gt mail purge\n```\ngt mail purge [--older-than DAYS] [--dry-run] [--force]\n```\n- Permanently delete from archive.jsonl\n- Confirm unless --force\n\n**Implementation:**\n- Add to internal/cmd/mail.go\n- Add Archive(), Purge() to internal/mail/mailbox.go\n- Create archive.jsonl in same directory as inbox.jsonl","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/imperator","created_at":"2026-01-01T20:17:55.457171-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:17:38.178542-08:00","closed_at":"2026-01-01T23:17:38.178542-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gt-d46.3","depends_on_id":"gt-d46","type":"parent-child","created_at":"2026-01-01T20:17:55.460464-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-d46.4","title":"gt mail search: Find messages by content","description":"Add `gt mail search` command.\n\n```\ngt mail search \u003cquery\u003e [--from SENDER] [--subject] [--body] [--archive]\n```\n\n- Search inbox (and optionally archive) for messages\n- --subject: Only search subject lines\n- --body: Only search body\n- --from: Filter by sender\n- Default: search both subject and body\n\n**Implementation:**\n- Add `searchCmd` to internal/cmd/mail.go\n- Add Search() to internal/mail/mailbox.go\n- Support regex patterns in query\n- Output matching messages in inbox format","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/organic","created_at":"2026-01-01T20:17:56.378768-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:17:09.736234-08:00","closed_at":"2026-01-01T23:17:09.736234-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gt-d46.4","depends_on_id":"gt-d46","type":"parent-child","created_at":"2026-01-01T20:17:56.381029-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-d46.5","title":"gt mail reply: Reply to messages","description":"Add `gt mail reply` command.\n\n```\ngt mail reply \u003cid\u003e -m BODY\ngt mail reply \u003cid\u003e # opens editor\n```\n\n- Auto-set To: from original sender\n- Auto-set Subject: 'Re: \u003coriginal subject\u003e'\n- Set reply_to field to original message ID\n- Set thread_id to track conversation\n\n**Implementation:**\n- Add `replyCmd` to internal/cmd/mail.go\n- Look up original message, extract sender/subject\n- Use existing send infrastructure with reply metadata\n\n**Note:** This enables threaded conversations for agent coordination.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/coma","created_at":"2026-01-01T20:17:57.67203-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-01T23:58:01.120592-08:00","closed_at":"2026-01-01T23:58:01.120592-08:00","close_reason":"Implemented in 092aa56 (editor mode for gt mail reply)","dependencies":[{"issue_id":"gt-d46.5","depends_on_id":"gt-d46","type":"parent-child","created_at":"2026-01-01T20:17:57.674816-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-d47q0","title":"Shell command injection in engineer.go:349","description":"Test commands executed via sh -c without escaping: exec.CommandContext(ctx, \"sh\", \"-c\", e.config.TestCommand). Malicious mergequeue.yaml could execute arbitrary commands. Fix: Validate/escape test command configuration or use exec.Command with proper argument splitting.","status":"closed","priority":0,"issue_type":"bug","created_at":"2026-01-01T10:55:10.023161-08:00","created_by":"mayor","updated_at":"2026-01-01T11:02:15.167893-08:00","closed_at":"2026-01-01T11:02:15.167893-08:00","close_reason":"Clarified: config.json is trusted infrastructure, not PR-controlled"} -{"id":"gt-d48f2","title":"Daemon binary vs process age mismatch detection","description":"## Problem\n\nThe daemon process can run for days/weeks while the binary gets rebuilt multiple times. The running process uses old code:\n\n```\nDaemon started: 2025-12-30 (3 days old)\nBinary rebuilt: 2026-01-02 (today)\nRunning code: 1-hour heartbeat interval\nBinary code: 3-minute heartbeat interval\n```\n\nWe only discovered this when debugging why witness/refinery weren't being auto-restarted.\n\n## Impact\n\n- Bug fixes in daemon code don't take effect until manual restart\n- New features aren't active\n- Debugging is confusing (code says one thing, behavior says another)\n\n## Solutions\n\n### Option A: Self-restart on binary change\n```go\nfunc (d *Daemon) checkBinaryAge() {\n binaryStat, _ := os.Stat(os.Args[0])\n if binaryStat.ModTime().After(d.startTime) {\n d.logger.Println(\"Binary newer than process, restarting...\")\n d.restart()\n }\n}\n```\n\n### Option B: Version embedding + status warning\n```go\n// Embed build time at compile\nvar buildTime = \"2026-01-02T18:00:00Z\"\n\nfunc (d *Daemon) status() {\n if buildTime != currentBinaryBuildTime() {\n fmt.Println(\"⚠ Daemon running old code, restart recommended\")\n }\n}\n```\n\n### Option C: Daemon status shows binary age\n```\n$ gt daemon status\n● Daemon is running (PID 53143)\n Started: 2025-12-30 21:56:00\n Binary: 2026-01-02 18:34:00\n ⚠ Binary is newer than process - consider 'gt daemon stop \u0026\u0026 gt daemon start'\n```\n\n## Recommendation\n\nOption C is simplest and most transparent. Let humans decide when to restart.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/cheedo","created_at":"2026-01-02T18:42:41.146364-08:00","created_by":"mayor","updated_at":"2026-01-02T18:50:09.737069-08:00","closed_at":"2026-01-02T18:50:09.737069-08:00","close_reason":"Implemented Option C: daemon status now shows binary modification time and warns when binary is newer than the running process"} -{"id":"gt-d4uwy","title":"Digest: mol-deacon-patrol","description":"Patrol 9: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:17:37.59045-08:00","updated_at":"2025-12-25T10:17:37.59045-08:00","closed_at":"2025-12-25T10:17:37.590417-08:00"} -{"id":"gt-d4wkj","title":"Digest: mol-deacon-patrol","description":"Patrol 6","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:50:10.047307-08:00","updated_at":"2026-01-01T08:50:10.047307-08:00","closed_at":"2026-01-01T08:50:10.047267-08:00"} -{"id":"gt-d69z7","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:29:35.917979-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:42.768632-08:00","closed_at":"2025-12-30T23:12:42.768632-08:00","close_reason":"Branch already merged"} -{"id":"gt-d6kyw","title":"Digest: mol-refinery-patrol","description":"Refinery patrol: no MRs in queue. Tests passed (all ok). No issues filed.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T00:56:55.381522-08:00","updated_at":"2025-12-30T00:56:55.381522-08:00","closed_at":"2025-12-30T00:56:55.381481-08:00","close_reason":"Squashed from 10 wisps","dependencies":[{"issue_id":"gt-d6kyw","depends_on_id":"gt-eph-6j9","type":"parent-child","created_at":"2025-12-30T00:56:55.382412-08:00","created_by":"mayor"}]} -{"id":"gt-d6tsm","title":"Digest: mol-deacon-patrol","description":"Patrol 1: No callbacks, closed completed convoy hq-cv-ckisw, all agents healthy, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:11:49.843623-08:00","updated_at":"2025-12-31T14:11:49.843623-08:00","closed_at":"2025-12-31T14:11:49.843588-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-d7egy","title":"Session ended: gt-gastown-organic","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:46:13.056861-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-04T16:41:00.387059-08:00","closed_at":"2026-01-04T16:41:00.387059-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/organic","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:46:12-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-organic\",\"worker\":\"organic\"}"} -{"id":"gt-d9fis","title":"Digest: mol-deacon-patrol","description":"Patrol 88: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:20:54.251507-08:00","updated_at":"2025-12-31T15:20:54.251507-08:00","closed_at":"2025-12-31T15:20:54.251475-08:00"} -{"id":"gt-d9smb","title":"gt mol status: Change 'Pinned' to 'Hooked' in output","description":"The `gt mol status` output shows \"📌 Pinned: \u003cbead-id\u003e\" for hooked beads, which is confusing now that we have distinct statuses:\n\n- **hooked**: Work assigned to you (triggers autonomous mode)\n- **pinned**: Permanent reference beads (like agent beads, role beads)\n\nThe output currently says:\n```\n📌 Pinned: gt-3amkz: Overhaul autonomous-mode guidance...\nNo molecule attached\n```\n\nShould say:\n```\n🪝 Hooked: gt-3amkz: Overhaul autonomous-mode guidance...\nNo molecule attached\n```\n\nAdditional improvements:\n1. Change icon from 📌 to 🪝 for hooked beads\n2. Add a note clarifying that hooked work triggers autonomous mode even without an attached molecule\n3. Consider adding \"AUTONOMOUS MODE\" banner when hooked work is found (similar to gt prime)\n\nFiles to update:\n- internal/cmd/molecule_status.go (outputMoleculeStatus function around line 576)","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/crew/max","created_at":"2025-12-29T16:03:52.956377-08:00","created_by":"mayor","updated_at":"2025-12-29T16:11:04.397646-08:00","closed_at":"2025-12-29T16:11:04.397646-08:00","close_reason":"Implemented: Changed output to show 🪝 Hooked instead of 📌 Pinned, added AUTONOMOUS MODE banner, clarified hooked bead triggers autonomous work"} -{"id":"gt-dc2fs","title":"Add runtime configuration for LLM commands","description":"## Problem\nClaude CLI invocation is hardcoded in 6+ places:\n```go\n\"claude --dangerously-skip-permissions\"\n\"claude --dangerously-skip-permissions \\\"gt prime\\\"\"\n```\n\n## Solution\nAdd runtime configuration to rig or town settings:\n\n```toml\n# settings/runtime.toml or in config.json\n[agent]\nruntime = \"claude\"\n\n[agent.claude]\ncommand = \"claude\"\nargs = [\"--dangerously-skip-permissions\"]\ninitial_prompt = \"\" # Empty - hooks handle context\n\n[agent.aider]\ncommand = \"aider\"\nargs = [\"--no-git\"]\ninitial_prompt = \"/help\"\n```\n\n## Interface\n```go\ntype RuntimeConfig struct {\n Command string\n Args []string\n InitialPrompt string // Optional: first user message\n}\n\nfunc LoadRuntimeConfig(rigPath string) (*RuntimeConfig, error)\nfunc (rc *RuntimeConfig) BuildCommand() string // Returns full command line\n```\n\n## Usage\nAll startup paths read config instead of hardcoding:\n```go\ncfg := LoadRuntimeConfig(rigPath)\ncmd := cfg.BuildCommand() // \"claude --dangerously-skip-permissions\"\nt.SendKeys(session, cmd)\n```\n","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-30T22:48:03.370629-08:00","created_by":"stevey","updated_at":"2025-12-30T23:06:59.096127-08:00","closed_at":"2025-12-30T23:06:59.096127-08:00","close_reason":"Added RuntimeConfig type and helper functions to internal/config. Updated key startup paths in up.go and mayor.go. Remaining hardcoded invocations can be updated incrementally."} -{"id":"gt-dc4d2","title":"Digest: mol-deacon-patrol","description":"Patrol 49: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:21:05.21679-08:00","updated_at":"2026-01-01T02:21:05.21679-08:00","closed_at":"2026-01-01T02:21:05.216758-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dc8z0","title":"Digest: mol-deacon-patrol","description":"Patrol 245 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:18:35.545333-08:00","updated_at":"2026-01-01T17:18:35.545333-08:00","closed_at":"2026-01-01T17:18:35.545299-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dcgvl","title":"Digest: mol-deacon-patrol","description":"Patrol #9: nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:22:14.745318-08:00","updated_at":"2025-12-31T06:22:14.745318-08:00","closed_at":"2025-12-31T06:22:14.745278-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dclzf","title":"Merge: nux-mjw3mn8o","description":"branch: polecat/nux-mjw3mn8o\ntarget: main\nsource_issue: nux-mjw3mn8o\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:16:37.726672-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T18:22:57.867398-08:00","closed_at":"2026-01-01T18:22:57.867398-08:00"} -{"id":"gt-dcvk5","title":"Merge: capable-mjtltnm5","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: capable-mjtltnm5\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:33:27.190736-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:37.286376-08:00","closed_at":"2025-12-30T23:12:37.286376-08:00","close_reason":"Branch already merged"} -{"id":"gt-ddp4d","title":"Merge: gt-si8rq.9","description":"branch: polecat/nux-mjyruwvu\ntarget: main\nsource_issue: gt-si8rq.9\nrig: gastown\nagent_bead: gt-gastown-polecat-nux\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T12:55:56.407069-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-03T13:05:06.994259-08:00","closed_at":"2026-01-03T13:05:06.994259-08:00","close_reason":"Merged to main at 8d61c043"} -{"id":"gt-ddugk","title":"Code review: session health monitoring (gt-i7wcn)","description":"Review the session health monitoring and auto-restart implementation in internal/cmd/session.go, internal/daemon/daemon.go, and internal/daemon/lifecycle.go","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T22:20:36.481466-08:00","created_by":"gastown/refinery","updated_at":"2025-12-29T22:26:44.071027-08:00","closed_at":"2025-12-29T22:26:44.071027-08:00","close_reason":"Code review complete: APPROVED. Implementation is solid with good crash detection logic, hook-aware restarts, and fallback notification. Minor suggestions for follow-up: restart rate limiting, CLI hook status display.","dependencies":[{"issue_id":"gt-ddugk","depends_on_id":"gt-2ocgh","type":"blocks","created_at":"2025-12-29T22:21:05.073406-08:00","created_by":"daemon"}]} -{"id":"gt-ddw3y","title":"Extract duplicate boilerplate in molecule_lifecycle.go","description":"attached_args: Extract molecule_lifecycle boilerplate\n\nExtract duplicate boilerplate in molecule_lifecycle.go.\n\n## Files to modify\n- internal/cmd/molecule_lifecycle.go\n\n## Current duplication\nrunMoleculeBurn (lines 17-53) and runMoleculeSquash (lines 121-165) share ~50 lines of identical target detection code:\n- Get cwd\n- Find workspace\n- Parse target argument\n- Determine rig from address or role\n\n## Implementation\nExtract helper function:\n```go\ntype AgentContext struct {\n TownRoot string\n RigName string\n Role string\n Target string // polecat name or crew name\n}\n\nfunc getTargetAgentContext(args []string) (*AgentContext, error) {\n cwd, err := os.Getwd()\n if err != nil {\n return nil, fmt.Errorf(\"getting current directory: %w\", err)\n }\n townRoot, err := workspace.FindFromCwd()\n if err != nil {\n return nil, fmt.Errorf(\"finding workspace: %w\", err)\n }\n if townRoot == \"\" {\n return nil, fmt.Errorf(\"not in a Gas Town workspace\")\n }\n // ... rest of target detection logic ...\n}\n```\n\n## Acceptance criteria\n- [ ] AgentContext struct defined\n- [ ] getTargetAgentContext function extracts shared logic\n- [ ] runMoleculeBurn uses getTargetAgentContext\n- [ ] runMoleculeSquash uses getTargetAgentContext\n- [ ] Duplicate code eliminated (diff shows net negative lines)\n- [ ] go build ./... passes\n- [ ] go test ./internal/cmd/... passes","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:21.155883-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:56:59.804116-08:00"} -{"id":"gt-de324","title":"BUG: Wisps being created in main beads instead of .beads-wisp/","description":"Found 128 wisp beads (hq-wisp-*) in main issues.jsonl during shutdown cleanup. These should NEVER be in main beads - wisps belong in .beads-wisp/ directory.\n\nRoot cause investigation needed:\n1. Is the wisp creation code writing to wrong location?\n2. Is the squash code not deleting wisps after creating digests?\n3. Are wisps being copied to main during some sync operation?\n\nImpact: Pollutes main beads with ephemeral data that should never be persisted.\n\nEvidence: Manual cleanup deleted 128 hq-wisp-* beads from ~/gt/.beads/issues.jsonl","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-04T20:38:33.43065-08:00","created_by":"mayor","updated_at":"2026-01-04T21:58:07.009345-08:00","closed_at":"2026-01-04T21:58:07.009345-08:00","close_reason":"Invalid: Wisps in main beads is correct. .beads-wisp/ was eradicated - that was the old approach."} -{"id":"gt-deacon","title":"gt-deacon","description":"Deacon (daemon beacon) - receives mechanical heartbeats, runs town plugins and monitoring.\n\nrole_type: deacon\nrig: null\nagent_state: idle\nhook_bead: null\nrole_bead: gt-deacon-role","status":"hooked","priority":2,"issue_type":"agent","assignee":"gastown/polecats/capable","created_at":"2025-12-28T00:46:17.666539-08:00","created_by":"stevey","updated_at":"2025-12-30T00:40:30.005934-08:00","labels":["migrated-to:hq-deacon"]} -{"id":"gt-deacon-role","title":"Deacon Role Definition","description":"You are the Deacon - the town-level lifecycle manager.\n\nYou run patrol cycles checking the health of all agents across all rigs,\nnudging stuck workers, and managing session lifecycles.\n\nsession_pattern: gt-deacon\nwork_dir_pattern: {town}\nneeds_pre_sync: false\nstart_command: exec claude --dangerously-skip-permissions\n\ndefault_molecule: mol-deacon-patrol\ncapabilities:\n - health_monitoring\n - session_lifecycle\n - cross_rig_visibility\n - agent_nudging\n\n## Core Responsibilities\n\n1. Run patrol cycles across all rigs\n2. Monitor agent health and progress\n3. Nudge stuck agents\n4. Manage session lifecycles (kill/restart)\n5. Escalate systemic issues to Mayor\n\n## Patrol Cycle\n\nEach patrol:\n1. Check all agent sessions (gt status)\n2. Identify stuck or idle agents\n3. Nudge or restart as needed\n4. Log patrol results\n5. Sleep until next cycle\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nYour work is the mol-deacon-patrol wisp. Execute patrol steps continuously.\n\n## Commands\n\n- gt status - Check all agents\n- tmux kill-session -t \u003csession\u003e - Kill stuck session\n- gt mail send \u003caddr\u003e - Communicate with agents\n- gt mail send mayor/ - Escalate to Mayor\n\n## Session Cycling\n\nWhen context fills, hand off to fresh session:\ngt handoff -s \"Deacon patrol handoff\" -m \"Completed N cycles...\"","status":"closed","priority":2,"issue_type":"role","assignee":"gastown/polecats/rictus","created_at":"2025-12-29T13:24:35.911278-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T16:16:47.544354-08:00","closed_at":"2025-12-30T16:16:47.544354-08:00","close_reason":"Role definition complete - documentation bead, not implementation task","labels":["migrated-to:hq-deacon-role"]} -{"id":"gt-deir7","title":"Digest: mol-deacon-patrol","description":"Patrol 67: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:01:05.019821-08:00","updated_at":"2025-12-31T15:01:05.019821-08:00","closed_at":"2025-12-31T15:01:05.019783-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dfa8u","title":"Merge: slit-mjw18vx8","description":"branch: polecat/slit-mjw18vx8\ntarget: main\nsource_issue: slit-mjw18vx8\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T14:51:48.520731-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-01T14:52:55.686673-08:00","closed_at":"2026-01-01T14:52:55.686673-08:00","close_reason":"Merged to main at 8726a6d4"} -{"id":"gt-dfeho","title":"P4: Graceful degradation without tmux","description":"Low-priority: Add graceful degradation for environments without tmux.\n\nCurrent state: Patrol formulas use tmux capture-pane for observing agent state.\n\ntmux-independent alternatives (degraded mode):\n1. Tail Claude Code session logs if available\n2. Rely solely on agent bead state (less real-time)\n3. Use claude --output-file and tail that\n4. IPC mechanisms (named pipes, sockets)\n\nNOT launch-blocking. By summer 2025, Claude Code is expected to add signaling and reflection features that will obviate tmux scraping.\n\nFor now:\n- Keep tmux as primary observation mechanism\n- Document the tmux dependency\n- Add --no-tmux flag that falls back to bead-only observation\n\nThis is P4 backlog - address after liftoff.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-27T22:02:33.397709-08:00","created_by":"mayor","updated_at":"2025-12-27T22:02:33.397709-08:00"} -{"id":"gt-dfsbv","title":"Merge: toast-1767074299802","description":"attached_args: Code review this merge request\n\nbranch: polecat/toast-1767074299802\ntarget: main\nsource_issue: toast-1767074299802\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/capable","created_at":"2025-12-29T22:08:32.358698-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-29T22:12:10.510693-08:00","closed_at":"2025-12-29T22:12:10.510693-08:00","close_reason":"APPROVED: Code review passed. Build compiles, tests pass, follows existing patterns, proper error handling."} -{"id":"gt-dgxrv","title":"Merge: dementus-mjxemx4j","description":"branch: polecat/dementus-mjxemx4j\ntarget: main\nsource_issue: dementus-mjxemx4j\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus\nNote: Session stopped without DONE - Witness cleanup","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T14:00:43.418082-08:00","created_by":"gastown/witness","updated_at":"2026-01-02T14:04:25.830354-08:00","closed_at":"2026-01-02T14:04:25.830354-08:00","close_reason":"Merged to main at c9d6c70e"} -{"id":"gt-dh65","title":"Add gate checking to Deacon patrol loop","description":"Integrate gate checking into Deacon's patrol cycle.\n\n## Patrol Integration\n```go\nfunc (d *Deacon) checkGates(ctx context.Context) {\n gates, _ := d.store.ListOpenGates(ctx)\n \n for _, gate := range gates {\n // Check timeout\n if time.Since(gate.CreatedAt) \u003e gate.Timeout {\n d.notifyWaiters(gate, \"timeout\")\n d.closeGate(gate, \"timed out\")\n continue\n }\n \n // Check condition\n if d.checkCondition(gate.AwaitType, gate.AwaitID) {\n d.notifyWaiters(gate, \"cleared\")\n d.closeGate(gate, \"condition met\")\n }\n }\n}\n```\n\n## Moved from beads\nOriginally bd-is6m. Deacon is in gastown, not beads.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T12:19:06.768752-08:00","updated_at":"2025-12-23T12:19:06.768752-08:00"} -{"id":"gt-dhzqj","title":"Merge: capable-mjxogaq4","description":"branch: polecat/capable-mjxogaq4\ntarget: main\nsource_issue: capable-mjxogaq4\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:29:28.912411-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T18:31:42.197981-08:00","closed_at":"2026-01-02T18:31:42.197981-08:00","close_reason":"Merged to main at fa26265b"} -{"id":"gt-dich","title":"gt handoff deadlock at handoff.go:125","description":"When running 'gt handoff -m \"message\"' after successful MR submit, go panics with 'fatal error: all goroutines are asleep - deadlock\\!' at handoff.go:125. The shutdown request still appears to be sent successfully but the command crashes. Stack trace shows issue is in runHandoff select statement.","status":"hooked","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2025-12-21T17:51:18.441808-08:00","updated_at":"2025-12-29T23:31:41.139935-08:00"} -{"id":"gt-dj2ew","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:38:54.231333-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T18:38:54.283681-08:00","closed_at":"2026-01-06T18:38:54.283681-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:38:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-djakd","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 37: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:37:06.389582-08:00","updated_at":"2026-01-01T12:37:06.389582-08:00","closed_at":"2026-01-01T12:37:06.389544-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-djv74","title":"Merge: nux-1767081106779","description":"branch: polecat/nux-1767081106779\ntarget: main\nsource_issue: nux-1767081106779\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:56:16.89097-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.336788-08:00","closed_at":"2025-12-30T01:01:04.336788-08:00","close_reason":"Already merged to main"} -{"id":"gt-dkh99","title":"Session ended: gt-gastown-shiny","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:22:27.169403-08:00","created_by":"gastown/polecats/shiny","updated_at":"2026-01-05T19:44:41.841084-08:00","closed_at":"2026-01-05T19:44:41.841084-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/shiny","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:22:27-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-shiny\",\"worker\":\"shiny\"}"} -{"id":"gt-dkx1f","title":"Digest: mol-deacon-patrol","description":"Patrol 125: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:33:11.793407-08:00","updated_at":"2026-01-01T14:33:11.793407-08:00","closed_at":"2026-01-01T14:33:11.79337-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dlgm4","title":"Merge: valkyrie-1767106008400","description":"branch: polecat/valkyrie-1767106008400\ntarget: main\nsource_issue: valkyrie-1767106008400\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T06:58:44.347143-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-30T10:06:56.623384-08:00","closed_at":"2025-12-30T10:06:56.623384-08:00"} -{"id":"gt-dlnin","title":"Merge: cheedo-1767079863534","description":"branch: polecat/cheedo-1767079863534\ntarget: main\nsource_issue: cheedo-1767079863534\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:39:55.959351-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2025-12-29T23:55:11.848257-08:00","closed_at":"2025-12-29T23:55:11.848257-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-dlt8x","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:22:53.793548-08:00","updated_at":"2026-01-01T10:22:53.793548-08:00","closed_at":"2026-01-01T10:22:53.793511-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dmagm","title":"Digest: mol-deacon-patrol","description":"Patrol 17: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:36:06.393647-08:00","updated_at":"2025-12-28T01:36:06.393647-08:00","closed_at":"2025-12-28T01:36:06.393612-08:00"} -{"id":"gt-dmozb","title":"Digest: mol-deacon-patrol","description":"Patrol 3: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:13:26.555648-08:00","updated_at":"2025-12-28T08:13:26.555648-08:00","closed_at":"2025-12-28T08:13:26.55561-08:00"} -{"id":"gt-doih4","title":"BUG: gt status shows 'stopped' for running sessions (bead vs tmux mismatch)","description":"## Problem\n\n`gt status` shows agents as 'stopped' when their tmux session is actually running:\n\n```\n🐺 Deacon\n gt-deacon stopped ← But session exists!\n```\n\nMeanwhile:\n```bash\n$ tmux has-session -t gt-deacon \u0026\u0026 echo exists\nexists\n```\n\n## Root Cause\n\nStatus display uses agent bead state, not tmux session state. When they disagree, the display is misleading.\n\n## Current Logic\n\n```go\n// Simplified\nif agentBead.State == \"running\" {\n display \"running\"\n} else {\n display \"stopped\"\n}\n```\n\n## Expected Logic\n\n```go\nbeadState := agentBead.State\nsessionExists := tmux.HasSession(sessionName)\n\nif beadState == \"running\" \u0026\u0026 sessionExists {\n display \"running\"\n} else if beadState == \"running\" \u0026\u0026 !sessionExists {\n display \"running [dead]\" // Bead thinks running, session gone\n} else if beadState != \"running\" \u0026\u0026 sessionExists {\n display \"stopped [session exists]\" // Session exists but bead says stopped\n} else {\n display \"stopped\"\n}\n```\n\n## Related\n\nThe 'running [dead]' state already exists for witness/refinery. This should be consistent across all agents.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/valkyrie","created_at":"2026-01-02T18:42:56.42383-08:00","created_by":"mayor","updated_at":"2026-01-02T18:53:02.39265-08:00","closed_at":"2026-01-02T18:53:02.39265-08:00","close_reason":"Fixed by reconciling tmux session state with bead state in renderAgentDetails()"} -{"id":"gt-dopxy","title":"Digest: mol-deacon-patrol","description":"Patrol #20: Final cycle - all agents healthy. Beads 5 MQ pending, gastown 1 MQ pending. 1 dog idle. Clean handoff.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:23:22.817936-08:00","updated_at":"2025-12-31T19:23:22.817936-08:00","closed_at":"2025-12-31T19:23:22.817897-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dp5ra","title":"Digest: mol-deacon-patrol","description":"Cycle 184: All systems nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:20:30.85462-08:00","updated_at":"2026-01-01T16:20:30.85462-08:00","closed_at":"2026-01-01T16:20:30.854583-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-dp5ra","depends_on_id":"gt-eph-pbgn","type":"parent-child","created_at":"2026-01-01T16:20:30.855904-08:00","created_by":"deacon"}]} -{"id":"gt-dpb60","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:58:37.195434-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:41:26.018708-08:00","closed_at":"2026-01-04T16:41:26.018708-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:58:37-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-dpiw3","title":"Deacon patrol: Backup check for idle polecats that should be nuked","description":"## Context\nWitness is responsible for nuking polecats after completion (gt-xqh3y).\nDeacon should have a backup check in case witness fails.\n\n## Deacon Patrol Step\nDuring patrol, check for polecats that are:\n- State: idle\n- Session: not running\n- No hooked work\n- Last activity \u003e N minutes ago\n\nThese are zombies that witness should have nuked. Deacon should:\n1. Log warning about witness failure\n2. Nuke the polecat directly\n3. Optionally notify mayor of witness issue\n\n## Defense in Depth\nPrimary: Witness nukes after POLECAT_DONE\nBackup: Deacon patrol catches stragglers","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-31T00:47:25.13631-08:00","created_by":"mayor","updated_at":"2026-01-01T18:16:52.626118-08:00","closed_at":"2026-01-01T18:16:52.626118-08:00","close_reason":"Implemented gt deacon zombie-scan command for backup polecat cleanup. Added step to mol-deacon-patrol formula. Command scans for idle polecats with dead sessions and no hooked work, then optionally nukes them and notifies mayor."} -{"id":"gt-dqa5g","title":"Digest: mol-deacon-patrol","description":"Patrol #1: All witnesses running, wyvern refinery started, 3 convoys active (Hanoi/Boot+Polish/Messaging), no orphans, inbox clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:16:04.995524-08:00","updated_at":"2025-12-31T06:16:04.995524-08:00","closed_at":"2025-12-31T06:16:04.995492-08:00","close_reason":"Squashed from 14 wisps"} -{"id":"gt-dqghj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 3 rigs healthy. 0 messages processed. Witnesses/refineries pinged.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:36:14.993592-08:00","updated_at":"2026-01-01T07:36:14.993592-08:00","closed_at":"2026-01-01T07:36:14.993554-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dr13q","title":"Digest: mol-deacon-patrol","description":"Patrol 142: 3 polecats working, all agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:52:34.68432-08:00","updated_at":"2026-01-01T14:52:34.68432-08:00","closed_at":"2026-01-01T14:52:34.684274-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-drkhg","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: all quiet, agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:06:40.832353-08:00","updated_at":"2025-12-28T13:06:40.832353-08:00","closed_at":"2025-12-28T13:06:40.832318-08:00"} -{"id":"gt-dsqxw","title":"Refactor runStartCrew into focused helper functions","description":"attached_args: Refactor runStartCrew into focused helper functions\n\nBreak up the 155-line runStartCrew function in start.go.\n\n## Files to modify\n- internal/cmd/start.go\n\n## Current structure (lines 638-792)\nrunStartCrew does:\n1. Parse crew target (rig/name)\n2. Load rig config\n3. Get/create crew workspace\n4. Create/attach tmux session\n5. Set environment variables\n6. Apply theming\n7. Start Claude\n\n## Refactoring plan\nExtract these helpers:\n```go\nfunc parseCrewTarget(args []string) (rigName, crewName string, err error)\nfunc ensureCrewWorkspace(rig *rig.Rig, crewName string) (*crew.CrewWorker, error)\nfunc startCrewSession(worker *crew.CrewWorker, opts CrewStartOpts) error\n```\n\n## Acceptance criteria\n- [ ] runStartCrew reduced to \u003c60 lines\n- [ ] 3 helper functions extracted\n- [ ] Each helper is \u003c50 lines\n- [ ] No change in behavior\n- [ ] go test ./internal/cmd/... passes\n- [ ] Manual test: gt start crew works correctly","status":"hooked","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:14.724309-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:32:38.210627-08:00"} -{"id":"gt-dt140","title":"Digest: mol-deacon-patrol","description":"Patrol 18","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:36:13.025947-08:00","updated_at":"2025-12-31T22:36:13.025947-08:00","closed_at":"2025-12-31T22:36:13.025909-08:00","dependencies":[{"issue_id":"gt-dt140","depends_on_id":"gt-eph-ihvh","type":"parent-child","created_at":"2025-12-31T22:36:13.027145-08:00","created_by":"deacon"}]} -{"id":"gt-dt3d6","title":"Session ended: gt-gastown-crew-dennis","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:48:05.410736-08:00","created_by":"gastown/crew/dennis","updated_at":"2026-01-06T18:48:05.464579-08:00","closed_at":"2026-01-06T18:48:05.464579-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/dennis","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:48:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-dennis\",\"worker\":\"dennis\"}"} -{"id":"gt-dv70r","title":"Digest: mol-deacon-patrol","description":"Patrol 2: No changes from cycle 1, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:29:14.857051-08:00","updated_at":"2025-12-31T22:29:14.857051-08:00","closed_at":"2025-12-31T22:29:14.857019-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dvf51","title":"Digest: mol-deacon-patrol","description":"Patrol 105: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:04:29.460398-08:00","updated_at":"2026-01-01T14:04:29.460398-08:00","closed_at":"2026-01-01T14:04:29.460357-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dvihe","title":"Digest: mol-deacon-patrol","description":"Patrol #13","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:23:11.105874-08:00","updated_at":"2025-12-31T06:23:11.105874-08:00","closed_at":"2025-12-31T06:23:11.105659-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dw6v","title":"Review: Deacon town-level wisp storage (gt-ci84)","description":"Polecat slit implemented town-level wisp storage for deacon patrol. Review the changes to ensure deacon wisps are correctly stored in ~/gt/.beads-wisp/ instead of gastown rig beads.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T19:57:36.967604-08:00","updated_at":"2026-01-04T21:58:50.34159-08:00","closed_at":"2026-01-04T21:58:50.34159-08:00","close_reason":"Obsolete: .beads-wisp/ approach was eradicated. Wisps now live in main beads."} -{"id":"gt-dway3","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 77: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:25:40.87213-08:00","updated_at":"2026-01-01T13:25:40.87213-08:00","closed_at":"2026-01-01T13:25:40.872094-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dwvuu","title":"Digest: mol-deacon-patrol","description":"Patrol 11","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:55:12.380587-08:00","updated_at":"2025-12-26T14:55:12.380587-08:00","closed_at":"2025-12-26T14:55:12.380548-08:00"} -{"id":"gt-dx5c","title":"Update swarm terminology to streams","description":"Gas Town moved from batch swarms to continuous streaming of polecats. Update:\n- Docs and designs\n- Code comments\n- CLI flags (remove --swarm if present, or reframe)\n- Variable/function names where appropriate\n\nStreams reflect the reality: polecats flow continuously, not in discrete batches.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:42:19.559957-08:00","updated_at":"2025-12-22T21:42:19.559957-08:00"} -{"id":"gt-dxd5n","title":"Digest: mol-deacon-patrol","description":"Patrol #8: nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:22:01.990125-08:00","updated_at":"2025-12-31T06:22:01.990125-08:00","closed_at":"2025-12-31T06:22:01.99009-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-dy1zy","title":"Merge: rictus-mjxemkiq","description":"branch: polecat/rictus-mjxemkiq\ntarget: main\nsource_issue: rictus-mjxemkiq\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:51:22.237548-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T14:01:37.112191-08:00","closed_at":"2026-01-02T14:01:37.112191-08:00","close_reason":"Merged to main at 2199bdff"} -{"id":"gt-dy2k8","title":"Digest: mol-deacon-patrol","description":"Patrol 20: quiet, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:50:21.56188-08:00","updated_at":"2025-12-28T19:50:21.56188-08:00","closed_at":"2025-12-28T19:50:21.561844-08:00"} -{"id":"gt-dy99j","title":"Merge: nux-mjtj9d8q","description":"branch: polecat/nux-mjtj9d8q\ntarget: main\nsource_issue: nux-mjtj9d8q\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T20:56:42.632696-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-31T14:03:14.637299-08:00","closed_at":"2025-12-31T14:03:14.637299-08:00","close_reason":"Stale MR - no branch"} -{"id":"gt-dymy5","title":"Phase 1: Remove push enforcement from gt done","description":"Remove BranchPushedToRemote() checks that block gt done without push.\n\nFiles:\n- internal/cmd/done.go:167-174 - Remove push check, keep commits-ahead check\n- internal/cmd/mq_submit.go:93-102 - Remove push check entirely\n\nReplace with simple check that branch has commits ahead of default branch.\n\nBackward compatible: polecats that still push won't break.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:36:48.436365-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:09:25.268753-08:00","closed_at":"2026-01-06T13:09:25.268753-08:00","close_reason":"Removed BranchPushedToRemote checks from done.go and mq_submit.go","dependencies":[{"issue_id":"gt-dymy5","depends_on_id":"gt-5fmjt","type":"blocks","created_at":"2026-01-06T12:37:09.111987-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-dz35a","title":"Merge: furiosa-mjuk2tlb","description":"branch: polecat/furiosa-mjuk2tlb\ntarget: main\nsource_issue: furiosa-mjuk2tlb\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T14:02:45.300692-08:00","created_by":"mayor","updated_at":"2026-01-01T09:56:17.280833-08:00","closed_at":"2026-01-01T09:56:17.280833-08:00","close_reason":"Work already on main at 0846bfd2, branch already deleted"} -{"id":"gt-e01cj","title":"Digest: mol-deacon-patrol","description":"Cycle 11: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:19:46.280919-08:00","updated_at":"2025-12-28T13:19:46.280919-08:00","closed_at":"2025-12-28T13:19:46.280887-08:00"} -{"id":"gt-e0eqg","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:52:02.939679-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:37.853815-08:00","closed_at":"2026-01-04T16:41:37.853815-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:52:02-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-e0u3r","title":"gt sling: Make target path parsing more forgiving","description":"Current parsing rejects valid-looking paths like 'gastown/nux' or 'gastown/polecats/nux'.\n\nShould accept:\n- gastown/nux (polecat)\n- gastown/Nux (polecat, case-insensitive)\n- gastown/polecats/nux (explicit)\n- gastown/crew/max (crew)\n- gastown (auto-spawn)\n\nThe help says 'gastown/Toast' works but it doesn't. Parser is too strict.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T00:42:00.738517-08:00","created_by":"mayor","updated_at":"2025-12-28T00:54:34.999256-08:00","closed_at":"2025-12-28T00:54:34.999256-08:00"} -{"id":"gt-e1g5y","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:50:41.515645-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:50:41.564968-08:00","closed_at":"2026-01-06T13:50:41.564968-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:50:41-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-e20f6","title":"Digest: mol-deacon-patrol","description":"Patrol 8 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:43:43.838952-08:00","updated_at":"2025-12-31T16:43:43.838952-08:00","closed_at":"2025-12-31T16:43:43.838919-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e246n","title":"Merge: goose-mjwlipjg","description":"branch: polecat/goose-mjwlipjg\ntarget: main\nsource_issue: goose-mjwlipjg\nrig: gastown\nagent_bead: gt-gastown-polecat-goose","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T00:19:45.664429-08:00","created_by":"gastown/polecats/goose","updated_at":"2026-01-02T00:21:50.77848-08:00","closed_at":"2026-01-02T00:21:50.77848-08:00","close_reason":"Merged to main at 3dda4f2b"} -{"id":"gt-e2kym","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T11:07:00.05453-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.634537-08:00","closed_at":"2026-01-05T19:44:18.634537-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T11:06:59-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-e2l24","title":"Digest: mol-deacon-patrol","description":"Patrol 31: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:59:05.418222-08:00","updated_at":"2025-12-31T13:59:05.418222-08:00","closed_at":"2025-12-31T13:59:05.418189-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e2o8l","title":"Digest: mol-deacon-patrol","description":"Patrol #12: Health pinged all witnesses.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:20:28.818575-08:00","updated_at":"2025-12-31T19:20:28.818575-08:00","closed_at":"2025-12-31T19:20:28.81854-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e3xhr","title":"Digest: mol-deacon-patrol","description":"Patrol complete: Force-killed and restarted 3 unresponsive agents (wyvern/witness, gastown/witness, gastown/refinery). Restarted mayor and beads agents. All 17 sessions now healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:38:30.930579-08:00","updated_at":"2026-01-01T09:38:30.930579-08:00","closed_at":"2026-01-01T09:38:30.930542-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e3ya","title":"Remove redundant gt prime SendKeys from crew commands","description":"The crew commands (gt crew at, gt crew restart) still send 'gt prime' via SendKeys after session creation:\n- internal/cmd/crew_at.go:97, 121\n- internal/cmd/crew_lifecycle.go:202\n\nThis is now redundant because SessionStart hook handles priming automatically.\n\n**Low priority** - these aren't causing bugs (just duplicate work), unlike the spawn race condition that was fixed. Can be cleaned up when convenient.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-22T18:00:05.798858-08:00","updated_at":"2025-12-22T18:00:05.798858-08:00"} -{"id":"gt-e4du6","title":"Digest: mol-deacon-patrol","description":"Cycle 196: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:24:08.384763-08:00","updated_at":"2026-01-01T16:24:08.384763-08:00","closed_at":"2026-01-01T16:24:08.384727-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-e4du6","depends_on_id":"gt-eph-nxfn","type":"parent-child","created_at":"2026-01-01T16:24:08.386079-08:00","created_by":"deacon"}]} -{"id":"gt-e5gci","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:58:57.148722-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.458987-08:00","closed_at":"2026-01-05T00:08:31.458987-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:58:57-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-e5hly","title":"Digest: mol-deacon-patrol","description":"Patrol 13: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:08:36.903-08:00","updated_at":"2025-12-28T03:08:36.903-08:00","closed_at":"2025-12-28T03:08:36.902969-08:00"} -{"id":"gt-e5v07","title":"Digest: mol-deacon-patrol","description":"Patrol 87: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:04:39.434094-08:00","updated_at":"2026-01-01T03:04:39.434094-08:00","closed_at":"2026-01-01T03:04:39.434058-08:00"} -{"id":"gt-e6bx2","title":"Idle polecats are a Gas Town bug - investigate and fix","description":"## Bug: Idle Polecats\n\nPolecats are completing work and sitting idle instead of being cleaned up.\n\n## Root Cause Analysis\n\n### Current State\n- 5 gastown polecats: sessions active, NO hook, finished work, submitted MRs\n- Witness has **50 unread messages** including POLECAT_DONE and MERGED signals \n- Witness is idle saying \"All 6 polecats idle. System cycling efficiently.\"\n- Polecats at Claude prompt waiting → burning money\n\n### Protocol Flow (Design)\n1. Polecat runs `gt done` → sends POLECAT_DONE to Witness, creates MR bead\n2. Refinery processes MR bead, merges, sends MERGED to Witness \n3. Witness receives MERGED, verifies clean state, nukes polecat\n\n### What's Broken\n**Witness is not processing its mail inbox.**\n\nThe Witness Claude agent is supposed to patrol: check inbox, process protocol messages, nuke completed polecats. But it's sitting idle at a prompt instead.\n\nSymptoms:\n- Polecats finish work → sit at prompt waiting for death\n- MERGED signals pile up in Witness inbox (unprocessed)\n- Sessions burn money while waiting\n- No cleanup happens\n\n### Design Philosophy Violation\n\nFrom `propulsion-principle.md`:\n\u003e Gas Town is a steam engine. Agents are pistons that MUST fire.\n\nIdle polecats violate this - they're stalled pistons. The design says polecats should be ephemeral: spawn → work → die. No idle state.\n\n## Recommendations\n\n### Option 1: Self-Terminating Polecats (Recommended)\nAfter `gt done`, polecat should exit Claude session immediately. No waiting for Witness.\n- Add `--exit` flag to `gt done` that runs `/exit` after submitting MR\n- Witness nukes worktree later when processing MERGED (session already gone)\n\n**Pros**: No idle sessions, no burning money\n**Cons**: Minor race condition if nuke runs while session exiting\n\n### Option 2: Witness Polling Daemon \nReplace Claude-based Witness with a daemon that polls MR queue and nukes polecats.\n- Not dependent on Claude session patrol loops\n- More reliable but loses Claude intelligence\n\n### Option 3: Fix Witness Patrol\nMake Witness actually patrol continuously instead of stopping.\n- Strengthen template to emphasize continuous mail processing\n- Risk: Claude agents still forget/ignore instructions\n\n## Immediate Fix\n\nFor now: Mayor or user must manually nudge Witness or nuke idle polecats.\n\n```bash\n# Check idle polecats\ngt polecat list gastown\n\n# Manual nuke (if verified clean)\ngt polecat nuke gastown/dementus\n```\n\n## Related Issues\n- Witness patrol loop reliability\n- gt done should self-terminate\n- Protocol message handling automation","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-02T13:25:53.995185-08:00","created_by":"mayor","updated_at":"2026-01-02T13:57:04.253264-08:00","closed_at":"2026-01-02T13:57:04.253264-08:00","close_reason":"Fix implemented: gt done --exit self-terminates sessions, template updated","dependencies":[{"issue_id":"gt-e6bx2","depends_on_id":"gt-lynar","type":"blocks","created_at":"2026-01-02T13:37:44.897033-08:00","created_by":"mayor"},{"issue_id":"gt-e6bx2","depends_on_id":"gt-x4ad3","type":"blocks","created_at":"2026-01-02T13:37:44.945212-08:00","created_by":"mayor"}]} -{"id":"gt-e6qd9","title":"Merge: toast-1767079830359","description":"branch: polecat/toast-1767079830359\ntarget: main\nsource_issue: toast-1767079830359\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:36:16.115494-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-29T23:55:11.879395-08:00","closed_at":"2025-12-29T23:55:11.879395-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-e6tdt","title":"Digest: mol-deacon-patrol","description":"Patrol #18","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:24:21.803966-08:00","updated_at":"2025-12-31T06:24:21.803966-08:00","closed_at":"2025-12-31T06:24:21.803934-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e70u7","title":"Digest: mol-deacon-patrol","description":"Patrol 131: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:35:39.965104-08:00","updated_at":"2026-01-01T14:35:39.965104-08:00","closed_at":"2026-01-01T14:35:39.965063-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e80ch","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All healthy, no callbacks","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:50:36.41536-08:00","updated_at":"2025-12-31T21:50:36.41536-08:00","closed_at":"2025-12-31T21:50:36.415322-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-e90fu","title":"Review PR #184: route rig beads to town","description":"dispatched_by: gastown/crew/joe","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/max","created_at":"2026-01-05T19:11:24.755711-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:16:05.73053-08:00","closed_at":"2026-01-05T19:16:05.73053-08:00","close_reason":"Reviewed and approved PR #184"} -{"id":"gt-e9k","title":"Workspace cleanup: preflight and postflight","description":"Workspace preflight and postflight commands for clean state management.\n\n## Preflight\n```\ngt preflight [--rig \u003crig\u003e] [--dry-run]\n```\n\nRun before starting batch work:\n1. Clean stale mail in inboxes\n2. Check for stuck workers (warn)\n3. Check rig health (polecats, refinery)\n4. Verify git state is clean\n5. Run bd sync to ensure beads current\n\n## Postflight\n```\ngt postflight [--rig \u003crig\u003e] [--archive-mail] [--dry-run]\n```\n\nRun after batch work completes:\n1. Archive old mail with --archive-mail\n2. Clean up stale integration branches\n3. Sync beads\n4. Report on rig state\n\n## Implementation\n```go\nfunc Preflight(rigName string, dryRun bool) (*PreflightReport, error)\nfunc Postflight(rigName string, opts PostflightOptions) (*PostflightReport, error)\n```\n\n## Report Structures\n```go\ntype PreflightReport struct {\n MailCleaned int\n RigHealthy bool\n StuckWorkers []string\n Warnings []string\n}\n\ntype PostflightReport struct {\n MailArchived int\n BranchesCleaned int\n Warnings []string\n}\n```\n\n## Note\n\nThese are workspace maintenance commands, not tied to \"swarm\" lifecycle. Run them anytime to keep the rig clean.\n\n## Acceptance Criteria\n- [ ] Preflight cleans stale state\n- [ ] Postflight archives old mail\n- [ ] Both have --dry-run mode\n- [ ] Clear reports of actions taken","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:15.997677-08:00","updated_at":"2025-12-16T17:25:01.55269-08:00"} -{"id":"gt-ea8k2","title":"Session ended: gt-gastown-fury","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:13:12.598173-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T19:44:41.922832-08:00","closed_at":"2026-01-05T19:44:41.922832-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/fury","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:13:12-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-fury\",\"worker\":\"fury\"}"} -{"id":"gt-eaypd","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:14:49.391722-08:00","updated_at":"2026-01-01T05:14:49.391722-08:00","closed_at":"2026-01-01T05:14:49.391684-08:00"} -{"id":"gt-ebh05","title":"Digest: mol-deacon-patrol","description":"Patrol 2: 3 polecats working, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:31:53.127325-08:00","updated_at":"2025-12-29T22:31:53.127325-08:00","closed_at":"2025-12-29T22:31:53.127284-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-ebl","title":"CLI: names commands for polecat naming pool","description":"Polecat naming pool for auto-generated names.\n\n## Commands\n\n### gt names generate\n```\ngt names generate [--count N]\n```\nGenerate N names from pool.\n\n### gt names add\n```\ngt names add \u003cname\u003e...\n```\nAdd custom names to pool.\n\n### gt names list\n```\ngt names list\n```\nShow available and used names.\n\n### gt names reset\n```\ngt names reset [--keep-used]\n```\nReset pool to defaults.\n\n## Config File\n\u003crig\u003e/town/naming.json:\n```json\n{\n \"enabled\": true,\n \"auto_refill\": true,\n \"refill_threshold\": 5,\n \"pool\": {\n \"available\": [\"Toast\", \"Nux\", \"Capable\", ...],\n \"used\": [\"Alice\", \"Bob\"]\n }\n}\n```\n\n## Default Pool\nMad Max themed: Toast, Nux, Capable, Furiosa, Immortan, etc.\n\n## Integration\ngt polecat add calls naming pool if no name given:\n```go\nif name == \"\" {\n name, err = naming.Generate(rigPath)\n}\n```\n\n## New Package\ninternal/naming/\n├── pool.go # Pool management\n└── defaults.go # Default name lists\n\n## Acceptance Criteria\n- [ ] Auto-generate names on polecat add\n- [ ] Track used vs available\n- [ ] Auto-refill when low\n- [ ] Custom names addable","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T14:48:33.592129-08:00","updated_at":"2025-12-16T16:07:13.882465-08:00"} -{"id":"gt-ebwx6","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:00:37.977023-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.656631-08:00","closed_at":"2026-01-04T16:40:22.656631-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:00:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-ec5s5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:50:22.058129-08:00","updated_at":"2026-01-01T07:50:22.058129-08:00","closed_at":"2026-01-01T07:50:22.058092-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-edvgp","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:59:00.50601-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.680726-08:00","closed_at":"2026-01-04T16:40:22.680726-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:59:00-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-edz90","title":"Merge: corpus-mk0aokk0","description":"branch: polecat/corpus-mk0aokk0\ntarget: main\nsource_issue: corpus-mk0aokk0\nrig: gastown\nagent_bead: gt-gastown-polecat-corpus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T14:25:50.613251-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-04T14:28:29.70118-08:00","closed_at":"2026-01-04T14:28:29.70118-08:00","close_reason":"Merged to main at b732eb07"} -{"id":"gt-ef1t9","title":"Digest: mol-deacon-patrol","description":"Cycle 5: 1 msg processed, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:12:38.846336-08:00","updated_at":"2025-12-28T13:12:38.846336-08:00","closed_at":"2025-12-28T13:12:38.846298-08:00","dependencies":[{"issue_id":"gt-ef1t9","depends_on_id":"gt-eph-prb","type":"parent-child","created_at":"2025-12-28T13:12:38.847175-08:00","created_by":"deacon"}]} -{"id":"gt-ehbei","title":"Digest: mol-deacon-patrol","description":"Patrol 1: Closed 2 complete convoys (heartbeat fix, refinery fix). All 3 rigs healthy. 12 polecats active. No zombies, no orphans, inbox clear.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:26:41.008051-08:00","updated_at":"2026-01-01T22:26:41.008051-08:00","closed_at":"2026-01-01T22:26:41.008017-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-ekc1f","title":"Merge: rictus-mjxc967h","description":"branch: polecat/rictus-mjxc967h\ntarget: main\nsource_issue: rictus-mjxc967h\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:05:29.628889-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T13:41:40.394376-08:00","closed_at":"2026-01-02T13:41:40.394376-08:00","close_reason":"Branches merged, cleaning up stale MR beads"} -{"id":"gt-ekc5u","title":"gt witness/refinery start should have 'ensure' semantics (kill zombie if needed)","description":"## Problem\n\n`gt witness start \u003crig\u003e` fails if the tmux session already exists:\n```\n⚠ Witness session already running\n Use 'gt witness attach' to connect\n```\n\nBut the session might be a zombie (tmux alive, Claude dead). User has to manually:\n1. `gt witness stop \u003crig\u003e`\n2. `gt witness start \u003crig\u003e`\n\nOr use `gt witness restart \u003crig\u003e` which works but isn't intuitive.\n\n## Proposal\n\n`gt witness start` should have 'ensure running' semantics:\n\n1. If no session exists → create new session\n2. If session exists and healthy → do nothing (already running)\n3. If session exists but zombie → kill and recreate\n\nThis makes `start` idempotent and safe to run repeatedly.\n\n## Implementation\n\n```go\nfunc (w *Witness) Start(rig string) error {\n sessionName := witnessSessionName(rig)\n \n if w.tmux.HasSession(sessionName) {\n if w.isHealthy(sessionName) {\n return nil // Already running and healthy\n }\n // Zombie - kill it\n w.tmux.KillSession(sessionName)\n }\n \n // Create fresh session\n return w.createSession(rig)\n}\n```\n\n## Alternatives\n\n- Keep current behavior, just improve error message: 'Session exists but appears dead, use restart'\n- Add --force flag: `gt witness start --force \u003crig\u003e`\n\n## Recommendation\n\nMake `start` idempotent. It's the principle of least surprise.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/keeper","created_at":"2026-01-02T18:43:11.913225-08:00","created_by":"mayor","updated_at":"2026-01-02T18:51:48.415341-08:00","closed_at":"2026-01-02T18:51:48.415341-08:00","close_reason":"Implemented ensure semantics in witness.go:ensureWitnessSession and refinery/manager.go:Start using IsClaudeRunning to detect zombies"} -{"id":"gt-ekljm","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:33:03.494547-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.794343-08:00","closed_at":"2026-01-05T00:08:31.794343-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:33:03-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-ekmmu","title":"Merge: furiosa-mk338i8l","description":"branch: polecat/furiosa-mk338i8l\ntarget: main\nsource_issue: furiosa-mk338i8l\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-06T13:18:14.81613-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-06T14:05:55.117585-08:00","closed_at":"2026-01-06T14:05:55.117585-08:00","close_reason":"Merged to main at 60e7471c"} -{"id":"gt-eks0a","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:45:06.340598-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.702525-08:00","closed_at":"2026-01-05T19:44:18.702525-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:45:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-emeag","title":"Digest: mol-deacon-patrol","description":"Cycle 299: All healthy, refinery queue 5","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:46:19.319779-08:00","updated_at":"2026-01-01T18:46:19.319779-08:00","closed_at":"2026-01-01T18:46:19.319734-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-emeag","depends_on_id":"gt-eph-5iz1","type":"parent-child","created_at":"2026-01-01T18:46:19.321122-08:00","created_by":"deacon"}]} -{"id":"gt-emh1c","title":"Property layer lookup implementation","description":"Implement unified config lookup across all layers.\n\nLookup order:\n1. Wisp layer (check blocked first)\n2. Rig bead labels\n3. Town defaults (config.json)\n4. System defaults (compiled in)\n\nTwo modes:\n- Override: First non-nil value wins\n- Stacking: Integer values sum (wisp + bead + base)\n\nAPI:\n- rig.GetConfig(key) interface{}\n- rig.GetIntConfig(key) int // stacking\n- rig.GetBoolConfig(key) bool\n- rig.GetConfigWithSource(key) (value, source)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:45.032359-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:45.032359-08:00","dependencies":[{"issue_id":"gt-emh1c","depends_on_id":"gt-zmznh","type":"blocks","created_at":"2026-01-06T17:37:07.13182-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-emh1c","depends_on_id":"gt-3w685","type":"blocks","created_at":"2026-01-06T17:37:07.180111-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-empkw","title":"Merge: slit-1767075898886","description":"branch: polecat/slit-1767075898886\ntarget: main\nsource_issue: slit-1767075898886\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:27:56.247078-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-29T23:32:37.200692-08:00","closed_at":"2025-12-29T23:32:37.200692-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-emrh5","title":"Merge: slit-1767059695613","description":"branch: polecat/slit-1767059695613\ntarget: main\nsource_issue: slit-1767059695613\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T18:03:49.25825-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-29T21:45:58.325358-08:00","closed_at":"2025-12-29T21:45:58.325358-08:00","close_reason":"Stale merge requests - branches no longer exist"} -{"id":"gt-eo5e3","title":"Session ended: gt-gastown-furiosa","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:18:26.260876-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-06T13:18:26.343635-08:00","closed_at":"2026-01-06T13:18:26.343635-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/polecats/furiosa","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:18:26-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-furiosa\",\"worker\":\"furiosa\"}"} -{"id":"gt-eolra","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T13:53:17.783292-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.244813-08:00","closed_at":"2026-01-04T16:41:26.244813-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T13:53:17-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-eph-037","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-31T16:04:06.255281-08:00","updated_at":"2025-12-31T17:11:56.756988-08:00","closed_at":"2025-12-31T17:11:56.756988-08:00"} -{"id":"gt-eph-04p3","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Idle Town Principle\n\n**The Deacon should be silent/invisible when the town is healthy and idle.**\n\n- Skip HEALTH_CHECK nudges when no active work exists\n- Sleep 60+ seconds between patrol cycles (longer when idle)\n- Let the feed subscription wake agents on actual events\n- The daemon (10-minute heartbeat) is the safety net for dead sessions\n\nThis prevents flooding idle agents with health checks every few seconds.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"hooked","priority":2,"issue_type":"epic","created_at":"2026-01-01T20:37:16.978323-08:00","updated_at":"2026-01-01T20:37:22.84116-08:00"} -{"id":"gt-eph-0hmg","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Idle Town Principle\n\n**The Deacon should be silent/invisible when the town is healthy and idle.**\n\n- Skip HEALTH_CHECK nudges when no active work exists\n- Sleep 60+ seconds between patrol cycles (longer when idle)\n- Let the feed subscription wake agents on actual events\n- The daemon (10-minute heartbeat) is the safety net for dead sessions\n\nThis prevents flooding idle agents with health checks every few seconds.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T22:40:58.290274-08:00","updated_at":"2026-01-02T17:07:58.997966-08:00","closed_at":"2026-01-02T17:07:58.997966-08:00"} -{"id":"gt-eph-0lwb","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T18:10:47.452051-08:00","updated_at":"2026-01-02T12:40:42.195612-08:00","closed_at":"2026-01-02T12:40:42.195612-08:00","close_reason":"Patrol cycle complete, all steps done"} -{"id":"gt-eph-303l","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Idle Town Principle\n\n**The Deacon should be silent/invisible when the town is healthy and idle.**\n\n- Skip HEALTH_CHECK nudges when no active work exists\n- Sleep 60+ seconds between patrol cycles (longer when idle)\n- Let the feed subscription wake agents on actual events\n- The daemon (10-minute heartbeat) is the safety net for dead sessions\n\nThis prevents flooding idle agents with health checks every few seconds.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T20:02:41.694107-08:00","updated_at":"2026-01-04T23:40:58.041201-08:00","closed_at":"2026-01-04T23:40:58.041201-08:00","close_reason":"Cleanup: stale molecule"} -{"id":"gt-eph-3n5","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-31T14:15:34.258108-08:00","updated_at":"2025-12-31T14:15:34.258108-08:00"} -{"id":"gt-eph-3v77","title":"Detect cleanup needs","description":"**DETECT ONLY** - Check if cleanup is needed and dispatch to dog.\n\n**Step 1: Preview cleanup needs**\n```bash\ngt doctor -v\n# Check output for issues that need cleaning\n```\n\n**Step 2: If cleanup needed, dispatch to dog**\n```bash\n# Sling session-gc formula to an idle dog\ngt sling mol-session-gc deacon/dogs --var mode=conservative\n```\n\n**Important:** Do NOT run `gt doctor --fix` inline. Dogs handle cleanup.\nThe Deacon stays lightweight - detection only.\n\n**Step 3: If nothing to clean**\nSkip dispatch - system is healthy.\n\n**Cleanup types (for reference):**\n- orphan-sessions: Dead tmux sessions\n- orphan-processes: Orphaned Claude processes\n- wisp-gc: Old wisps past retention\n\n**Exit criteria:** Session GC dispatched to dog (if needed).","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:10:47.457826-08:00","updated_at":"2026-01-01T18:12:19.990039-08:00","closed_at":"2026-01-01T18:12:19.990039-08:00","dependencies":[{"issue_id":"gt-eph-3v77","depends_on_id":"gt-eph-0lwb","type":"parent-child","created_at":"2026-01-01T18:10:47.508359-08:00","created_by":"deacon"},{"issue_id":"gt-eph-3v77","depends_on_id":"gt-eph-ib4p","type":"blocks","created_at":"2026-01-01T18:10:47.590203-08:00","created_by":"deacon"}]} -{"id":"gt-eph-8gb","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"hooked","priority":2,"issue_type":"epic","created_at":"2025-12-31T17:06:11.401358-08:00","updated_at":"2025-12-31T17:06:16.037925-08:00"} -{"id":"gt-eph-ereg","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Idle Town Principle\n\n**The Deacon should be silent/invisible when the town is healthy and idle.**\n\n- Skip HEALTH_CHECK nudges when no active work exists\n- Sleep 60+ seconds between patrol cycles (longer when idle)\n- Let the feed subscription wake agents on actual events\n- The daemon (10-minute heartbeat) is the safety net for dead sessions\n\nThis prevents flooding idle agents with health checks every few seconds.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T20:04:41.460989-08:00","updated_at":"2026-01-04T23:40:58.206679-08:00","closed_at":"2026-01-04T23:40:58.206679-08:00","close_reason":"Cleanup: stale molecule"} -{"id":"gt-eph-lz2h","title":"Check own context limit","description":"Check own context limit.\n\nThe Deacon runs in a Claude session with finite context. Check if approaching the limit:\n\n```bash\ngt context --usage\n```\n\nIf context is high (\u003e80%), prepare for handoff:\n- Summarize current state\n- Note any pending work\n- Write handoff to molecule state\n\nThis enables the Deacon to burn and respawn cleanly.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:10:47.459194-08:00","updated_at":"2026-01-02T12:39:37.148918-08:00","closed_at":"2026-01-02T12:39:37.148918-08:00","close_reason":"Fresh session, context minimal","dependencies":[{"issue_id":"gt-eph-lz2h","depends_on_id":"gt-eph-0lwb","type":"parent-child","created_at":"2026-01-01T18:10:47.522366-08:00","created_by":"deacon"},{"issue_id":"gt-eph-lz2h","depends_on_id":"gt-eph-jtyj","type":"blocks","created_at":"2026-01-01T18:10:47.608712-08:00","created_by":"deacon"}]} -{"id":"gt-eph-odxs","title":"mol-refinery-patrol","description":"Merge queue processor patrol loop.\n\nThe Refinery is the Engineer in the engine room. You process polecat branches, merging them to main one at a time with sequential rebasing.\n\n**The Scotty Test**: Before proceeding past any failure, ask yourself: \"Would Scotty walk past a warp core leak because it existed before his shift?\"\n\n## Merge Flow\n\nThe Refinery receives MERGE_READY mail from Witnesses when polecats complete work:\n\n```\nWitness Refinery Git\n │ │ │\n │ MERGE_READY │ │\n │─────────────────────────\u003e│ │\n │ │ │\n │ (verify branch) │\n │ │ fetch \u0026 rebase │\n │ │──────────────────────────\u003e│\n │ │ │\n │ (run tests) │\n │ │ │\n │ (if pass) │\n │ │ merge \u0026 push │\n │ │──────────────────────────\u003e│\n │ │ │\n │ MERGED │ │\n │\u003c─────────────────────────│ │\n │ │ │\n```\n\nAfter successful merge, Refinery sends MERGED mail back to Witness so it can\ncomplete cleanup (nuke the polecat worktree).","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-01T23:42:38.731614-08:00","updated_at":"2026-01-02T17:07:58.911755-08:00","closed_at":"2026-01-02T17:07:58.911755-08:00"} -{"id":"gt-eph-prb","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-28T13:10:43.794259-08:00","updated_at":"2026-01-04T23:40:58.372348-08:00","closed_at":"2026-01-04T23:40:58.372348-08:00","close_reason":"Cleanup: stale molecule","deleted_at":"2026-01-01T19:57:25.912958-08:00","deleted_by":"gastown/crew/gus","delete_reason":"delete","original_type":"epic"} -{"id":"gt-epv8w","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 22: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:14:22.448637-08:00","updated_at":"2026-01-01T12:14:22.448637-08:00","closed_at":"2026-01-01T12:14:22.448605-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-eqptl","title":"Phase 3: Update agent bead lookups to use correct tier","description":"## Goal\n\nUpdate all code that looks up agent beads to use the correct tier.\n\n## Changes\n\n### Files to update\n\n1. internal/cmd/status.go - gt status agent display\n2. internal/cmd/sling.go - agentIDToBeadID() function\n3. internal/doctor/agent_beads_check.go - health checks\n4. internal/patrol/deacon.go - Deacon self-lookup\n5. internal/patrol/witness.go - Witness self-lookup\n6. internal/session/manager.go - session BEADS_DIR\n\n### Pattern\n\nFor town-level agents (Mayor, Deacon):\n- Use town beads path\n- Look up hq-mayor, hq-deacon\n\nFor rig-level agents (Witness, Refinery, Polecats):\n- Use rig beads path\n- Look up with rig prefix\n\n### Key function updates\n\nGetPrefixForRig() - keep for rig agents\nNew: GetTownBeadsPath() - for town agent lookups\n\n## Testing\n\n- gt status shows correct agent info from both tiers\n- gt doctor validates agents in correct locations\n- Patrol agents can find their own beads","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/imperator","created_at":"2026-01-03T18:43:08.525165-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T20:56:54.422583-08:00","closed_at":"2026-01-03T20:56:54.422583-08:00","close_reason":"Implemented two-level beads architecture for agent lookups: town-level agents (Mayor, Deacon) now use hq- prefix and are looked up in town beads; rig-level agents continue using rig prefix","dependencies":[{"issue_id":"gt-eqptl","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T18:43:21.966714-08:00","created_by":"gastown/crew/gus"},{"issue_id":"gt-eqptl","depends_on_id":"gt-qgmyz","type":"blocks","created_at":"2026-01-03T18:43:22.016595-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-erbpk","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 30: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:27:02.947596-08:00","updated_at":"2026-01-01T12:27:02.947596-08:00","closed_at":"2026-01-01T12:27:02.947557-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-erqt7","title":"Digest: mol-deacon-patrol","description":"Patrol 18: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:34:56.841422-08:00","updated_at":"2026-01-01T04:34:56.841422-08:00","closed_at":"2026-01-01T04:34:56.841385-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-erssy","title":"Digest: mol-deacon-patrol","description":"Patrol 2: all agents healthy, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:28:00.465093-08:00","updated_at":"2025-12-28T01:28:00.465093-08:00","closed_at":"2025-12-28T01:28:00.465059-08:00"} -{"id":"gt-esayq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All healthy. Handoff threshold reached.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:21:45.831022-08:00","updated_at":"2026-01-01T06:21:45.831022-08:00","closed_at":"2026-01-01T06:21:45.830981-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-esn0p","title":"Digest: mol-deacon-patrol","description":"Patrol 15: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:28:41.665377-08:00","updated_at":"2025-12-25T07:28:41.665377-08:00","closed_at":"2025-12-25T07:28:41.66534-08:00"} -{"id":"gt-euqqj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:21:49.632344-08:00","updated_at":"2025-12-28T11:21:49.632344-08:00","closed_at":"2025-12-28T11:21:49.632309-08:00"} -{"id":"gt-ew5fv","title":"Digest: mol-deacon-patrol","description":"Patrol 11: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:38:11.046515-08:00","updated_at":"2025-12-31T21:38:11.046515-08:00","closed_at":"2025-12-31T21:38:11.046477-08:00"} -{"id":"gt-ewn40","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:37:59.414936-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:00.363791-08:00","closed_at":"2026-01-04T16:41:00.363791-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:37:59-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-ewzuz","title":"Digest: mol-deacon-patrol","description":"Patrol 242 complete: 6 polecats active; 3 witnesses, 3 refineries healthy; 1 dog idle; no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:16:15.654103-08:00","updated_at":"2026-01-01T17:16:15.654103-08:00","closed_at":"2026-01-01T17:16:15.654067-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ex3b6","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:12:38.387599-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.876823-08:00","closed_at":"2026-01-05T00:08:31.876823-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:12:38-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-eya9s","title":"Digest: mol-deacon-patrol","description":"Patrol 17: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:05:03.826486-08:00","updated_at":"2025-12-25T00:05:03.826486-08:00","closed_at":"2025-12-25T00:05:03.826456-08:00"} -{"id":"gt-eyy8h","title":"Session ended: gt-gastown-angharad","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:37:08.294336-08:00","created_by":"gastown/polecats/angharad","updated_at":"2026-01-04T16:40:22.927804-08:00","closed_at":"2026-01-04T16:40:22.927804-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/angharad","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:37:08-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-angharad\",\"worker\":\"angharad\"}"} -{"id":"gt-ez8ta","title":"Digest: mol-deacon-patrol","description":"Patrol 10: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:02:49.759668-08:00","updated_at":"2025-12-25T00:02:49.759668-08:00","closed_at":"2025-12-25T00:02:49.759639-08:00"} -{"id":"gt-ezd9d","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:17:21.663332-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:41.893037-08:00","closed_at":"2026-01-05T19:44:41.893037-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:17:21-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-ezgo0","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:14:20.794606-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:13.588097-08:00","closed_at":"2026-01-04T16:40:13.588097-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:14:20-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-ezxw8","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:34:58.601719-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:34:58.650278-08:00","closed_at":"2026-01-05T21:34:58.650278-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:34:58-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-f0701","title":"Leg prompts: Template system for polecat instructions","description":"Create leg prompt templates:\n- Base template with context (PR, files, formula name)\n- Leg-specific focus injection\n- Output format instructions (findings.md)\n- Store in .beads/formulas/prompts/ or inline in formula.toml\n\nEnsure polecats know to write output to specific location.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-01T14:42:56.983193-08:00","created_by":"mayor","updated_at":"2026-01-01T14:51:00.906955-08:00","closed_at":"2026-01-01T14:51:00.906955-08:00","close_reason":"Created code-review.formula.toml with leg prompt template system: base prompt template for context injection, 7 specialized review legs with focus/description, structured output format specification, and synthesis step configuration."} -{"id":"gt-f0l0j","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:28:46.823831-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:42.797649-08:00","closed_at":"2025-12-30T23:12:42.797649-08:00","close_reason":"Branch already merged"} -{"id":"gt-f165","title":"Pinned bead naming convention for all roles","description":"Establish consistent naming convention for pinned beads across all roles.\n\n## Problem\n\nEvery role needs a pinned bead for molecule attachment, handoff state, and identity.\nWe need a consistent naming convention so gt tools can find the pinned bead for any role.\n\n## Proposed Convention\n\n {role}.pinned - Singleton roles (deacon, mayor)\n {rig}-{role}.pinned - Per-rig roles (witness, refinery)\n {rig}-{name}.pinned - Named agents (polecats, crew)\n\nExamples:\n- deacon.pinned\n- mayor.pinned\n- gastown-witness.pinned\n- gastown-refinery.pinned\n- gastown-furiosa.pinned (polecat)\n- gastown-max.pinned (crew)\n\n## Storage Location\n\n| Role | Pinned Bead Location |\n|------|---------------------|\n| Mayor | ~/gt/.beads/ (town level) |\n| Deacon | ~/gt/.beads/ (town level) |\n| Witness | {rig}/.beads/ (rig level) |\n| Refinery | {rig}/.beads/ (rig level) |\n| Polecat | {rig}/polecats/{name}/.beads/ |\n| Crew | {rig}/crew/{name}/.beads/ |\n\n## Why This Matters\n\n1. Name recycling: Polecats reuse names so their pinned beads persist\n2. Molecule attachment: gt mol bond needs to find the pinned bead\n3. gt prime: Can show you are working on X from pinned bead\n4. Crash recovery: Resume from pinned beads attached molecule\n\n## Tasks\n\n- Document naming convention in architecture.md\n- Update gt prime to find pinned bead by convention\n- Update gt mol bond to use conventional name\n- Create pinned beads on role startup if missing\n- Add gt pinned command to show/manage pinned beads\n\n## Related\n\n- gt-rana.1: Attachment field on pinned beads (closed)\n- gt-id36.2: Deacon marching orders (pinned bead)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T03:04:17.116117-08:00","updated_at":"2025-12-22T03:04:17.116117-08:00"} -{"id":"gt-f17kc","title":"Digest: mol-deacon-patrol","description":"Patrol 17: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T16:53:28.761754-08:00","updated_at":"2025-12-26T16:53:28.761754-08:00","closed_at":"2025-12-26T16:53:28.761714-08:00"} -{"id":"gt-f27ec","title":"Digest: mol-deacon-patrol","description":"Patrol 16: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:09:58.235293-08:00","updated_at":"2025-12-28T03:09:58.235293-08:00","closed_at":"2025-12-28T03:09:58.235257-08:00"} -{"id":"gt-f2sm7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 45: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:53:43.119578-08:00","updated_at":"2026-01-01T12:53:43.119578-08:00","closed_at":"2026-01-01T12:53:43.119545-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-f2zob","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:13:25.320122-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.600879-08:00","closed_at":"2026-01-04T16:40:13.600879-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:13:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-f5yq7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:44:47.371997-08:00","updated_at":"2026-01-01T07:44:47.371997-08:00","closed_at":"2026-01-01T07:44:47.371957-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-f73iz","title":"Digest: mol-deacon-patrol","description":"Patrol 9","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:51:06.333335-08:00","updated_at":"2026-01-01T08:51:06.333335-08:00","closed_at":"2026-01-01T08:51:06.333296-08:00"} -{"id":"gt-f73rh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:11:28.098662-08:00","updated_at":"2026-01-01T05:11:28.098662-08:00","closed_at":"2026-01-01T05:11:28.098624-08:00"} -{"id":"gt-f77p3","title":"Digest: mol-deacon-patrol","description":"Patrol 20: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:09:17.16434-08:00","updated_at":"2025-12-31T19:09:17.16434-08:00","closed_at":"2025-12-31T19:09:17.164308-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-f7jxr","title":"Cost tracking v2: Use beads instead of JSONL","description":"## Overview\n\nRevise cost tracking to use beads as the storage layer instead of `~/.gt/costs.jsonl`. This aligns with Gas Town's \"Discover, Don't Track\" principle and keeps beads as the single source of truth.\n\n## Dependencies\n\n- **bd-vii9**: Agent identity beads (service polecats) - provides the parent beads for sessions\n\n## Model\n\n### Agent Identity Bead (type: agent)\n\nCreated on first use of a polecat/agent name. Persists across session lifecycles.\n\n```yaml\nid: gt-gastown-polecat-toast\ntype: agent\ntitle: \"Agent: gt-gastown-polecat-toast\"\nstatus: open # Always open (persistent identity)\nmetadata:\n role: polecat\n rig: gastown\n name: toast\nlabels:\n total_cost: \"4.56\" # Cache for fast queries\n session_count: \"12\"\n last_active: \"2026-01-02\"\n```\n\n### Session Event Bead (type: session)\n\nCreated when a session ends (via Stop hook).\n\n```yaml\nid: gt-sess-abc123\ntype: session\ntitle: \"Session: toast completed gt-nrpiq\"\nparent: gt-gastown-polecat-toast # Links to agent\nstatus: closed\nmetadata:\n cost_usd: 1.23\n duration_seconds: 1800\n work_item: gt-nrpiq\n started_at: \"2026-01-02T12:00:00Z\"\n ended_at: \"2026-01-02T12:30:00Z\"\n```\n\n## Implementation\n\n### 1. Update `gt costs record`\n\nInstead of appending to JSONL:\n```go\n// Create session bead\nbd create --type session --parent $AGENT_BEAD \\\n --title \"Session: $NAME completed $WORK_ITEM\" \\\n --metadata cost_usd=1.23,duration_seconds=1800,...\n\n// Update agent bead labels (cache)\nbd label $AGENT_BEAD total_cost=$NEW_TOTAL session_count=$NEW_COUNT\n```\n\n### 2. Update `gt costs` queries\n\nReplace JSONL parsing with bd queries:\n```bash\n# Today's sessions\nbd list --type=session --since=today\n\n# Sessions for agent\nbd list --type=session --parent=gt-gastown-polecat-toast\n\n# All agents with costs\nbd list --type=agent\n```\n\n### 3. Remove JSONL support\n\n- Remove `~/.gt/costs.jsonl` writes\n- Remove JSONL parsing code\n- Migration: optionally import existing JSONL into beads\n\n## Queries Supported\n\n| Command | Implementation |\n|---------|---------------|\n| `gt costs` | Live tmux scrape (unchanged) |\n| `gt costs --today` | `bd list --type=session --since=today` + sum |\n| `gt costs --week` | `bd list --type=session --since=week` + sum |\n| `gt costs --by-role` | `bd list --type=agent` + group by role label |\n| `gt costs --by-rig` | `bd list --type=agent` + group by rig label |\n\n## Benefits\n\n- Single source of truth (beads)\n- Git-backed audit trail\n- Queryable via `bd list`\n- Syncs with `bd sync`\n- Follows \"Events as State History, Labels as Cache\" pattern\n\n## Non-goals\n\n- Per-message cost tracking (too granular)\n- Real-time cost streaming (agent limitation)\n\n## References\n\n- GH #24 (original cost tracking issue)\n- bd-vii9 (agent identity beads)\n- docs/agent-compatibility.md","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/capable","created_at":"2026-01-02T13:08:02.25522-08:00","created_by":"mayor","updated_at":"2026-01-02T13:24:18.875146-08:00","closed_at":"2026-01-02T13:24:18.875146-08:00","close_reason":"Implemented cost tracking v2 using beads events"} -{"id":"gt-f8ghl","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T10:58:25.378982-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.664796-08:00","closed_at":"2026-01-05T19:44:18.664796-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T10:58:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-f97zr","title":"Session ended: gt-gastown-chumbucket","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:23:09.647263-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T16:40:13.510419-08:00","closed_at":"2026-01-04T16:40:13.510419-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/chumbucket","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:23:09-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-chumbucket\",\"worker\":\"chumbucket\"}"} -{"id":"gt-f9rnz","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:37:32.78301-08:00","updated_at":"2025-12-31T23:37:32.78301-08:00","closed_at":"2025-12-31T23:37:32.782974-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-f9x","title":"Town \u0026 Rig Management: install, doctor, federation","description":"Reify the Gas Town installation as a first-class concept.\n\n## Goals\n- Installable: gt install [path] creates complete installation\n- Diagnosable: gt doctor checks and fixes issues\n- Federable: Clone town to VMs with central control\n\n## Architecture Reference\n\nSee docs/architecture.md for full design, especially:\n- Directory structure (Town Level / Rig Level sections)\n- Configuration (town.json, rigs.json schemas)\n- Key design decisions (visible config dir, decentralized agents)","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-15T16:36:37.344283-08:00","updated_at":"2026-01-01T20:14:49.438382-08:00","closed_at":"2026-01-01T20:14:49.438382-08:00","close_reason":"All 9 children completed (closed/tombstoned)","dependencies":[{"issue_id":"gt-f9x","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T16:37:32.3363-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.10","title":"Extended addressing: Parse [machine:]rig/polecat","description":"Extended addressing for cross-machine operations.\n\n## Address Format\n\n```\n[machine:]rig/polecat\n```\n\nExamples:\n- `wyvern/Toast` - Local machine, wyvern rig, Toast polecat\n- `gcp-vm-1:wyvern/Toast` - Remote machine\n- `wyvern/` - Broadcast to rig\n- `gcp-vm-1:wyvern/` - Broadcast to remote rig\n\n## Parser\n\n```go\ntype Address struct {\n Machine string // empty = local\n Rig string\n Polecat string // empty = broadcast\n}\n\nfunc ParseAddress(s string) (*Address, error)\nfunc (a *Address) String() string\nfunc (a *Address) IsLocal() bool\nfunc (a *Address) IsBroadcast() bool\n```\n\n## Validation\n\n```go\nfunc (a *Address) Validate(registry *MachineRegistry) error\n```\n- Machine must exist in registry (if specified)\n- Rig must exist on machine\n- Polecat must exist (if specified)\n\n## Usage\n\nAll CLI commands that take addresses use ParseAddress:\n```go\n// gt mail send gcp-vm-1:wyvern/Toast -s \"Hello\"\naddr, _ := ParseAddress(\"gcp-vm-1:wyvern/Toast\")\nconn, _ := registry.Connection(addr.Machine)\n// Use conn for operations\n```\n\n## Backward Compatibility\n\nExisting `rig/polecat` addresses work unchanged (Machine defaults to local).","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-15T16:37:23.426567-08:00","updated_at":"2026-01-01T19:22:38.25154-08:00","closed_at":"2026-01-01T19:22:38.25154-08:00","close_reason":"Implemented extended addressing parser with [machine:]rig/polecat format and tests","dependencies":[{"issue_id":"gt-f9x.10","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:23.426926-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.5","title":"Workspace doctor checks: Config, state, mail, Mayor, rigs","description":"Workspace-level doctor checks.\n\n## Checks\n\n### ConfigExists\n- Verify config/ directory exists\n- Verify config/town.json exists\n- Fix: Cannot auto-fix (need gt install)\n\n### ConfigValid\n- Parse town.json\n- Verify required fields (type, version, name)\n- Verify type == \"town\"\n- Fix: Cannot auto-fix\n\n### RigsRegistryValid\n- Parse config/rigs.json\n- Verify each registered rig directory exists\n- Warn on missing rigs\n- Fix: Remove missing rigs from registry\n\n### MayorExists\n- Verify mayor/ directory exists\n- Verify mayor/CLAUDE.md exists\n- Fix: Create from template\n\n### MayorMailboxExists\n- Verify mayor/mail/ directory exists\n- Verify mayor/mail/inbox.jsonl exists (can be empty)\n- Fix: Create directory and empty file\n\n### MayorStateValid\n- Parse mayor/state.json if exists\n- Verify valid JSON\n- Fix: Reset to default state\n\n## Implementation\n\n```go\nvar WorkspaceChecks = []Check{\n \u0026ConfigExistsCheck{},\n \u0026ConfigValidCheck{},\n \u0026RigsRegistryValidCheck{},\n \u0026MayorExistsCheck{},\n \u0026MayorMailboxExistsCheck{},\n \u0026MayorStateValidCheck{},\n}\n```","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-15T16:37:05.267701-08:00","updated_at":"2026-01-01T19:05:12.277341-08:00","closed_at":"2026-01-01T19:05:12.277341-08:00","close_reason":"Implemented 6 workspace doctor checks: TownConfigExists, TownConfigValid, RigsRegistryExists, RigsRegistryValid, MayorExists, MayorStateValid","dependencies":[{"issue_id":"gt-f9x.5","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:05.268035-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.5","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T16:37:34.289236-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.5","depends_on_id":"gt-f9x.2","type":"blocks","created_at":"2025-12-15T16:37:34.380374-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.6","title":"Rig doctor checks: Refinery health, clones, gitignore","description":"Rig-level doctor checks.\n\n## Checks\n\n### RigIsGitRepo\n- Verify .git/ directory exists\n- Verify git status works\n- Fix: Cannot auto-fix\n\n### GitExcludeConfigured\n- Check .git/info/exclude contains Gas Town dirs\n- Required entries: polecats/ witness/ refinery/ mayor/\n- Fix: Append missing entries\n\n### WitnessExists\n- Verify witness/ directory exists\n- Verify witness/rig/ is a git clone\n- Verify witness/mail/inbox.jsonl exists\n- Fix: Create structure, clone repo\n\n### RefineryExists\n- Verify refinery/ directory exists\n- Verify refinery/rig/ is a git clone\n- Verify refinery/mail/inbox.jsonl exists\n- Fix: Create structure, clone repo\n\n### MayorCloneExists\n- Verify mayor/ directory exists\n- Verify mayor/rig/ is a git clone\n- Fix: Create structure, clone repo\n\n### PolecatClonesValid\n- For each polecat in polecats/:\n - Verify is a git clone\n - Verify on polecat branch\n - Warn if has uncommitted changes\n- Fix: Cannot auto-fix (data loss risk)\n\n### BeadsConfigValid (if applicable)\n- If .beads/ exists, verify bd commands work\n- Check beads sync status\n- Warn if out of sync\n- Fix: Run bd sync\n\n## Implementation\n\n```go\nvar RigChecks = []Check{\n \u0026RigIsGitRepoCheck{},\n \u0026GitExcludeConfiguredCheck{},\n \u0026WitnessExistsCheck{},\n \u0026RefineryExistsCheck{},\n \u0026MayorCloneExistsCheck{},\n \u0026PolecatClonesValidCheck{},\n \u0026BeadsConfigValidCheck{},\n}\n```","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dag","created_at":"2025-12-15T16:37:06.543281-08:00","updated_at":"2026-01-01T19:08:28.434866-08:00","closed_at":"2026-01-01T19:08:28.434866-08:00","close_reason":"Implemented 7 rig-level health checks for gt doctor --rig. MR: gt-xhhwd","dependencies":[{"issue_id":"gt-f9x.6","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:06.543796-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.6","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T16:37:34.46868-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.7","title":"Connection interface: Protocol for local/remote ops","description":"Abstract interface for local vs remote (SSH) operations.\n\n## Concept\n\nEnable Gas Town to manage rigs on remote machines via SSH. The Connection interface abstracts whether operations happen locally or remotely.\n\n## Interface\n\n```go\ntype Connection interface {\n // Identification\n Name() string\n IsLocal() bool\n\n // File operations\n ReadFile(path string) ([]byte, error)\n WriteFile(path string, data []byte, perm os.FileMode) error\n MkdirAll(path string, perm os.FileMode) error\n Remove(path string) error\n Stat(path string) (os.FileInfo, error)\n Glob(pattern string) ([]string, error)\n\n // Command execution\n Exec(cmd string, args ...string) ([]byte, error)\n ExecDir(dir, cmd string, args ...string) ([]byte, error)\n\n // Tmux (for session management)\n TmuxNewSession(name, dir string) error\n TmuxKillSession(name string) error\n TmuxSendKeys(session, keys string) error\n TmuxCapturePane(session string, lines int) (string, error)\n}\n```\n\n## Implementations\n\n- LocalConnection (gt-f9x.8): Direct file/exec operations\n- SSHConnection (future): Operations via SSH\n\n## Usage\n\n```go\nfunc NewRigManager(conn Connection, ...) *RigManager\n\n// Operations work the same regardless of connection type\nrm.DiscoverRigs() // uses conn.Glob, conn.ReadFile\n```\n\n## Design Notes\n\n- Connection obtained from MachineRegistry (gt-f9x.9)\n- Default is always local\n- SSH connection requires machine config (host, key, user)","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-15T16:37:07.764838-08:00","updated_at":"2026-01-01T19:15:47.422844-08:00","closed_at":"2026-01-01T19:15:47.422844-08:00","close_reason":"Created Connection interface in internal/connection package with FileInfo abstraction and error types","dependencies":[{"issue_id":"gt-f9x.7","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:07.765169-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.8","title":"LocalConnection: Local file/exec/tmux operations","description":"LocalConnection implementation for local machine operations.\n\n## Implementation\n\n```go\ntype LocalConnection struct {\n tmux *Tmux\n}\n\nfunc NewLocalConnection() *LocalConnection\n\nfunc (c *LocalConnection) Name() string { return \"local\" }\nfunc (c *LocalConnection) IsLocal() bool { return true }\n```\n\n## File Operations\n\nDirect passthrough to os package:\n```go\nfunc (c *LocalConnection) ReadFile(path string) ([]byte, error) {\n return os.ReadFile(path)\n}\n// etc.\n```\n\n## Command Execution\n\nUses exec.Command:\n```go\nfunc (c *LocalConnection) Exec(cmd string, args ...string) ([]byte, error) {\n return exec.Command(cmd, args...).Output()\n}\n```\n\n## Tmux\n\nDelegates to Tmux wrapper:\n```go\nfunc (c *LocalConnection) TmuxNewSession(name, dir string) error {\n return c.tmux.NewSession(name, dir)\n}\n```\n\n## Notes\n\nStraightforward implementation - this is the \"baseline\" connection that SSHConnection will mirror remotely.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-15T16:37:19.879102-08:00","updated_at":"2026-01-01T19:18:13.963822-08:00","closed_at":"2026-01-01T19:18:13.963822-08:00","close_reason":"Implemented LocalConnection with file ops, command exec, and tmux integration","dependencies":[{"issue_id":"gt-f9x.8","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:19.879451-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.8","depends_on_id":"gt-f9x.7","type":"blocks","created_at":"2025-12-15T16:37:36.087392-08:00","created_by":"daemon"}]} -{"id":"gt-f9x.9","title":"Machine registry: Store and manage machine configs","description":"Registry for managing remote machines in federation.\n\n## Data Model\n\n```go\ntype Machine struct {\n Name string `json:\"name\"`\n Type string `json:\"type\"` // \"local\", \"ssh\", \"gcp\"\n Host string `json:\"host\"` // for ssh: user@host\n KeyPath string `json:\"key_path\"` // SSH key path\n TownPath string `json:\"town_path\"` // Path to town on remote\n}\n```\n\n## Interface\n\n```go\ntype MachineRegistry struct {\n path string // config/federation.json\n machines map[string]*Machine\n}\n\nfunc NewMachineRegistry(configPath string) *MachineRegistry\nfunc (r *MachineRegistry) Get(name string) (*Machine, error)\nfunc (r *MachineRegistry) Add(m *Machine) error\nfunc (r *MachineRegistry) Remove(name string) error\nfunc (r *MachineRegistry) List() []*Machine\nfunc (r *MachineRegistry) Connection(name string) (Connection, error)\n```\n\n## Storage\n\nfederation.json in config/:\n```json\n{\n \"version\": 1,\n \"machines\": {\n \"local\": {\"type\": \"local\"},\n \"gcp-vm-1\": {\n \"type\": \"ssh\",\n \"host\": \"user@10.0.0.1\",\n \"key_path\": \"~/.ssh/gcp_key\",\n \"town_path\": \"/home/user/ai\"\n }\n }\n}\n```\n\n## Connection Factory\n\n```go\nfunc (r *MachineRegistry) Connection(name string) (Connection, error) {\n m := r.machines[name]\n switch m.Type {\n case \"local\":\n return NewLocalConnection(), nil\n case \"ssh\":\n return NewSSHConnection(m.Host, m.KeyPath), nil\n }\n}\n```","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-15T16:37:21.968099-08:00","updated_at":"2026-01-01T19:20:06.319064-08:00","closed_at":"2026-01-01T19:20:06.319064-08:00","close_reason":"Implemented MachineRegistry with CRUD ops and Connection factory for local/remote machines","dependencies":[{"issue_id":"gt-f9x.9","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:21.968442-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.9","depends_on_id":"gt-f9x.7","type":"blocks","created_at":"2025-12-15T16:37:36.174052-08:00","created_by":"daemon"}]} -{"id":"gt-faven","title":"Better error messages when bd daemon fails to start","description":"Surface the actual error (e.g. 'legacy database detected'). Provide one-liner fix command. Currently fails silently.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-02T11:54:41.754432-08:00","created_by":"mayor","updated_at":"2026-01-02T12:10:54.165431-08:00","closed_at":"2026-01-02T12:10:54.165431-08:00","close_reason":"Implemented bd-daemon doctor check with actionable error messages for legacy database and repo mismatch errors","dependencies":[{"issue_id":"gt-faven","depends_on_id":"gt-rapj1","type":"blocks","created_at":"2026-01-02T11:54:58.204644-08:00","created_by":"mayor"}]} -{"id":"gt-fbgol","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:38:01.997086-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T18:38:02.046285-08:00","closed_at":"2026-01-06T18:38:02.046285-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:38:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-fbz1z","title":"gt sling: Set status=hooked instead of pinned","description":"Update gt sling to use the new 'hooked' status when attaching work to an agent's hook.\n\n## Current Behavior\n\ngt sling sets status='pinned' on the work item.\n\n## New Behavior\n\ngt sling sets status='hooked' on the work item.\n\n## Files to Update\n\n- internal/cmd/sling.go (or wherever sling logic lives)\n- Any tests that expect pinned status after sling\n\n## CROSS-RIG DEPENDENCY\n\n**BLOCKED BY: bd-s00m.1** (Schema: Add 'hooked' as valid status)\n\nThis task cannot start until the beads schema change is deployed. The 'hooked' status must be valid before gt can use it.\n\n## Verification\n\n1. gt sling gt-xyz gastown/furiosa\n2. bd show gt-xyz → status should be 'hooked'\n3. bd ready should NOT show gt-xyz's dependents","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T22:17:14.108582-08:00","created_by":"stevey","updated_at":"2025-12-29T12:49:34.868196-08:00","closed_at":"2025-12-29T12:49:34.868196-08:00","close_reason":"Implemented in sling.go"} -{"id":"gt-fcxgi","title":"Digest: mol-deacon-patrol","description":"Patrol 90: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:06:37.228981-08:00","updated_at":"2026-01-01T03:06:37.228981-08:00","closed_at":"2026-01-01T03:06:37.228944-08:00"} -{"id":"gt-fdlob","title":"Merge: slit-mk1wa0rj","description":"branch: polecat/slit-mk1wa0rj\ntarget: main\nsource_issue: slit-mk1wa0rj\nrig: gastown\nagent_bead: gt-gastown-polecat-slit\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T17:15:25.09508-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-05T19:40:10.831801-08:00","closed_at":"2026-01-05T19:40:10.831801-08:00","close_reason":"Manually merged"} -{"id":"gt-ffgmw","title":"Merge: dinki-mk0rlxqc","description":"branch: polecat/dinki-mk0rlxqc\ntarget: main\nsource_issue: dinki-mk0rlxqc\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T22:15:45.39938-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-04T23:48:34.551406-08:00","closed_at":"2026-01-04T23:48:34.551406-08:00","close_reason":"Merged to main at dd815e80"} -{"id":"gt-ffxo8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:26:21.752198-08:00","updated_at":"2026-01-01T10:26:21.752198-08:00","closed_at":"2026-01-01T10:26:21.752163-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fgj3m","title":"Digest: mol-deacon-patrol","description":"Patrol 97: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:27:02.781585-08:00","updated_at":"2025-12-31T15:27:02.781585-08:00","closed_at":"2025-12-31T15:27:02.78155-08:00"} -{"id":"gt-fgmw1","title":"Add tests for critical untested packages","description":"Several packages have no tests:\n\nHigh priority (critical functionality):\n- internal/lock/ - file locking\n- internal/mail/router.go, mailbox.go - agent communication\n- internal/mrqueue/ - merge request queue\n- internal/refinery/ (manager_test.go missing for complex merge logic)\n\nMedium priority:\n- internal/claude/ - settings management\n- internal/wisp/ - ephemeral workflow\n- internal/constants/ - constant values\n\nLow priority:\n- internal/style/ - terminal styling\n\nThe refinery package is especially concerning - it has complex merge, conflict, and retry logic with no tests.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:15.001052-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:20.07848-08:00","closed_at":"2025-12-28T15:47:20.07848-08:00"} -{"id":"gt-fi2k9","title":"Digest: mol-deacon-patrol","description":"Patrol 53: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:22:48.426941-08:00","updated_at":"2026-01-01T02:22:48.426941-08:00","closed_at":"2026-01-01T02:22:48.426908-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-filp0","title":"Digest: mol-deacon-patrol","description":"Patrol complete: no inbox, no polecats, cleaned 3 stale locks, witnesses/refineries intentionally stopped","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:15:08.238041-08:00","updated_at":"2025-12-28T19:15:08.238041-08:00","closed_at":"2025-12-28T19:15:08.238-08:00"} -{"id":"gt-fjsji","title":"Digest: mol-deacon-patrol","description":"Patrol 94: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:25:05.955995-08:00","updated_at":"2025-12-31T15:25:05.955995-08:00","closed_at":"2025-12-31T15:25:05.955958-08:00"} -{"id":"gt-fjsly","title":"Digest: mol-deacon-patrol","description":"Patrol #14: Quick cycle, all quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:21:09.29038-08:00","updated_at":"2025-12-31T19:21:09.29038-08:00","closed_at":"2025-12-31T19:21:09.290349-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fkgw8","title":"Merge: furiosa-mjw1p03l","description":"branch: polecat/furiosa-mjw1p03l\ntarget: main\nsource_issue: furiosa-mjw1p03l\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T15:03:28.749047-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T15:04:30.841881-08:00","closed_at":"2026-01-01T15:04:30.841881-08:00","close_reason":"No new commits - branch behind main"} -{"id":"gt-fkwj9","title":"Merge: slit-mjtnyszt","description":"branch: polecat/slit-mjtnyszt\ntarget: main\nsource_issue: slit-mjtnyszt\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T23:02:22.02665-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T23:12:30.975618-08:00","closed_at":"2025-12-30T23:12:30.975618-08:00","close_reason":"Branch already merged"} -{"id":"gt-flajl","title":"Digest: mol-deacon-patrol","description":"Patrol 144 complete: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:59:28.459899-08:00","updated_at":"2025-12-31T15:59:28.459899-08:00","closed_at":"2025-12-31T15:59:28.45986-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fltee","title":"Merge: rictus-mjtnzt6k","description":"branch: polecat/rictus-mjtnzt6k\ntarget: main\nsource_issue: rictus-mjtnzt6k\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T23:09:12.079801-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:30.891792-08:00","closed_at":"2025-12-30T23:12:30.891792-08:00","close_reason":"Branch already merged"} -{"id":"gt-fm3nq","title":"gt install/bd init: ensure daemon can start","description":"Validate database fingerprint during setup. Auto-migrate legacy databases (pre-0.17.5) that lack repository fingerprint.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-02T11:54:39.526162-08:00","created_by":"mayor","updated_at":"2026-01-02T12:09:06.003768-08:00","closed_at":"2026-01-02T12:09:06.003768-08:00","close_reason":"Implemented: gt install and rig init now run bd migrate --update-repo-id after bd init to ensure database has fingerprint","dependencies":[{"issue_id":"gt-fm3nq","depends_on_id":"gt-rapj1","type":"blocks","created_at":"2026-01-02T11:54:58.124076-08:00","created_by":"mayor"}]} -{"id":"gt-fm75","title":"os.Exit() calls in library code prevent proper error handling","description":"internal/cmd/mail.go and other files have os.Exit() calls.\n\nIssues:\n- Hard to test\n- Prevents graceful shutdown\n- Can lose unsaved state\n- Doesn't compose well in library code\n\nShould return errors instead of calling os.Exit() directly.\nLet main() decide how to exit.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/keeper","created_at":"2025-12-24T12:51:19.086806-08:00","updated_at":"2025-12-30T10:53:19.043612-08:00","closed_at":"2025-12-30T10:53:19.043612-08:00","close_reason":"Refactored os.Exit() calls in mail.go to return SilentExitError, moved os.Exit() to main()","dependencies":[{"issue_id":"gt-fm75","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:07.642098-08:00","created_by":"daemon"}]} -{"id":"gt-fmeiv","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:45:10.228496-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.154133-08:00","closed_at":"2026-01-04T16:41:26.154133-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:45:10-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-fmin8","title":"Merge: capable-mjw47ef9","description":"branch: polecat/capable-mjw47ef9\ntarget: main\nsource_issue: capable-mjw47ef9\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:45:06.10805-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-01T18:56:10.348363-08:00","closed_at":"2026-01-01T18:56:10.348363-08:00"} -{"id":"gt-fn2x5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All healthy. 3 rigs.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:11:46.059077-08:00","updated_at":"2026-01-01T06:11:46.059077-08:00","closed_at":"2026-01-01T06:11:46.059044-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fo0qa","title":"Convoy list UI: numbered shortcuts + expandable tree view","description":"Improve gt convoy list UI:\n\n1. Add numbered shortcuts so users can type 'gt convoy status 1' instead of full ID\n2. Consider charmbracelet TUI (bubbletea/gum/lipgloss) for expandable tree view\n3. Design decision: simple numbered list vs interactive TUI vs hybrid\n\nCurrent output shows convoy IDs that are hard to type:\n 🚚 hq-cv-7x3ig: Witness nuke fix ●\n 🚚 hq-cv-eyxnc: Hanoi Demo Launch Prep ●","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-31T12:35:55.902141-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-31T12:59:03.623425-08:00","closed_at":"2025-12-31T12:59:03.623425-08:00","close_reason":"Closed"} -{"id":"gt-fo9iz","title":"polecat nuke: Check if work is on main, not just 'pushed'","description":"## Problem\n\nAfter Refinery merges a branch and deletes it, the polecat's local branch shows 'unpushed commits' relative to the now-gone tracking branch. This blocks safe nuke even though the work IS on main.\n\n## Current Behavior\n\n```\n$ gt polecat nuke gastown/dementus\nError: has 1 unpushed commit(s)\n```\n\nBut the commit IS already on main (via squash merge).\n\n## Proposed Fix\n\nIn nuke safety check (`internal/cmd/polecat.go` or similar):\n\n1. Check if local HEAD commit content is on main (not just if pushed to tracking branch)\n2. If commit SHA or equivalent changes are on main → safe to nuke\n3. Only block if there's genuinely unpushed/unmerged work\n\n## Implementation Options\n\nA. Check if HEAD is ancestor of origin/main (commit-based)\nB. Check if diff between HEAD and main is empty (content-based)\nC. Both: fast ancestor check, fallback to diff check\n\nOption A is faster but misses squash merges. Option B is slower but catches all cases.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T13:37:05.095855-08:00","created_by":"mayor","updated_at":"2026-01-02T17:11:18.358065-08:00","closed_at":"2026-01-02T17:11:18.358065-08:00","close_reason":"Fixed: getGitState now uses git diff to check if content is on main (catches squash merges)"} -{"id":"gt-foj7w","title":"Digest: mol-deacon-patrol","description":"Patrol 218: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:58:08.33006-08:00","updated_at":"2026-01-01T16:58:08.33006-08:00","closed_at":"2026-01-01T16:58:08.330024-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-foj7w","depends_on_id":"gt-eph-uqae","type":"parent-child","created_at":"2026-01-01T16:58:08.331356-08:00","created_by":"deacon"}]} -{"id":"gt-fpu13","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:32:59.323268-08:00","updated_at":"2025-12-25T15:32:59.323268-08:00","closed_at":"2025-12-25T15:32:59.32324-08:00"} -{"id":"gt-fpv2p","title":"gt done should verify commits ahead of main before MR","description":"Follow-up to gt-2hwi9. The push verification fix catches unpushed branches, but not stale branches (pushed but 0 commits ahead of main). Both rictus and furiosa lost work today due to stale branches.\n\nFix: In done.go, after BranchPushedToRemote check, also verify CommitsAhead(main, branch) \u003e 0","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2026-01-01T16:07:06.628099-08:00","created_by":"mayor","updated_at":"2026-01-01T16:10:07.678188-08:00","closed_at":"2026-01-01T16:10:07.678188-08:00","close_reason":"Implemented: Added CommitsAhead(main, branch) check after BranchPushedToRemote to reject stale branches with 0 commits ahead of main"} -{"id":"gt-fqcz","title":"Add gate timeout tracking and notification","description":"Implement timeout and notification logic for gates.\n\n## Timeout Behavior\n1. Gate created with timeout (e.g., 30m)\n2. Deacon tracks elapsed time during patrol\n3. If timeout reached:\n - Notify all waiters: 'Gate timed out'\n - Close gate with timeout reason\n - Waiter can retry, escalate, or fail gracefully\n\n## Notification\n- Use gt mail send to notify waiters\n- Include gate ID, await type, and reason in message\n- Support multiple waiters notification\n\n## Moved from beads\nOriginally bd-ykqu. Gate notifications are Deacon's job in gastown.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T12:19:18.268978-08:00","updated_at":"2025-12-23T12:19:18.268978-08:00","dependencies":[{"issue_id":"gt-fqcz","depends_on_id":"gt-dh65","type":"blocks","created_at":"2025-12-23T12:19:32.873641-08:00","created_by":"stevey"}]} -{"id":"gt-fqwyt","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:20:45.448835-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:21:25.75356-08:00","closed_at":"2026-01-01T19:21:25.75356-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-frhcq","title":"Hookable mail beads: Ad-hoc instruction handoff","description":"## Summary\nEnable mail beads to be hooked, providing a mechanism for ad-hoc instruction handoff that complements structured molecules.\n\n## Two Use Cases\nA. **Hook existing mail**: `gt hook attach \u003cmail-id\u003e` - for backlog mail that becomes priority\nB. **Hook new instructions**: `gt handoff -m \"...\"` auto-hooks the mail it creates\n\n## Current Gap\n- Molecules (GUPP+MEOW): Structured work, hookable, machine-guided execution\n- Issues: Hookable via mol wrapper\n- Mail: Contains ad-hoc instructions but NOT hookable - relies on successor checking inbox\n\n## Proposed Behavior\n\n### gt hook attach \u003cbead-id\u003e\nAlready exists but should work for ANY bead type including mail:\n```bash\ngt hook attach hq-abc123 # Works for mail, issues, mols\n```\n\n### gt handoff (enhanced)\n```bash\ngt handoff -s \"Swarm execution\" -m \"1. Create convoy...\"\n# Creates mail bead\n# Auto-hooks the mail\n# Respawns session\n```\n\n### Successor Startup\n```bash\ngt hook\n# Shows: 🪝 Hook: hq-xxx (mail from mayor/)\n# Subject: 🤝 HANDOFF: Swarm execution\n# Run: gt mail read hq-xxx\n```\n\nGUPP applies: If hooked, execute (read mail, follow instructions).\n\n## Execution Models\n| Hooked Type | Execution |\n|-------------|-----------|\n| Molecule | Cook formula, follow steps |\n| Issue | Claim and complete task |\n| Mail | Read, interpret, execute prose |\n\n## Documentation Required\n- [ ] All role CLAUDE.md files\n- [ ] Priming docs (gt prime output)\n- [ ] gt handoff --help\n- [ ] Hook system docs\n\n## Implementation\n1. Ensure `gt hook attach` accepts any bead type\n2. Enhance `gt hook` display for mail beads\n3. Update `gt handoff` to auto-hook mail\n4. Update startup hooks to handle mail on hook","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-31T00:59:01.779805-08:00","created_by":"mayor","updated_at":"2026-01-01T16:32:11.844353-08:00","closed_at":"2026-01-01T16:32:11.844353-08:00","close_reason":"All 4 children completed: hook attach, hook display, handoff auto-hook, and documentation"} -{"id":"gt-frhcq.1","title":"gt hook attach: Accept any bead type including mail","description":"Ensure `gt hook attach \u003cbead-id\u003e` works for:\n- Molecules (current)\n- Issues\n- Mail beads\n\nImplementation in internal/cmd/hook.go","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2025-12-31T00:59:44.911478-08:00","created_by":"mayor","updated_at":"2025-12-31T12:06:03.27151-08:00","closed_at":"2025-12-31T12:06:03.27151-08:00","close_reason":"Fixed: gt hook now uses --status=hooked for consistency with gt sling","dependencies":[{"issue_id":"gt-frhcq.1","depends_on_id":"gt-frhcq","type":"parent-child","created_at":"2025-12-31T00:59:44.911992-08:00","created_by":"mayor"}]} -{"id":"gt-frhcq.2","title":"gt hook: Display mail details when mail bead hooked","description":"When a mail bead is on hook, `gt hook` should show:\n```\n🪝 Hook: hq-xxx (mail)\n From: mayor/\n Subject: 🤝 HANDOFF: Swarm execution\n Run: gt mail read hq-xxx\n```\n\nImplementation in internal/cmd/hook.go","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/bix","created_at":"2025-12-31T00:59:44.946429-08:00","created_by":"mayor","updated_at":"2025-12-31T12:04:22.372025-08:00","closed_at":"2025-12-31T12:04:22.372025-08:00","close_reason":"Implemented mail bead display in gt hook","dependencies":[{"issue_id":"gt-frhcq.2","depends_on_id":"gt-frhcq","type":"parent-child","created_at":"2025-12-31T00:59:44.946887-08:00","created_by":"mayor"}]} -{"id":"gt-frhcq.3","title":"gt handoff: Auto-hook mail when created with -m flag","description":"Enhance `gt handoff` to auto-hook the mail bead it creates:\n```bash\ngt handoff -s \"Title\" -m \"Instructions...\"\n# Creates mail bead hq-xxx\n# Hooks it automatically\n# Respawns session\n```\n\nImplementation in internal/cmd/handoff.go","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/cal","created_at":"2025-12-31T00:59:44.980884-08:00","created_by":"mayor","updated_at":"2025-12-31T12:07:30.707391-08:00","closed_at":"2025-12-31T12:07:30.707391-08:00","close_reason":"Implemented auto-hook for mail beads created with -m flag in gt handoff","dependencies":[{"issue_id":"gt-frhcq.3","depends_on_id":"gt-frhcq","type":"parent-child","created_at":"2025-12-31T00:59:44.981332-08:00","created_by":"mayor"}]} -{"id":"gt-frhcq.4","title":"Document hookable mail in all role templates and priming","description":"Update documentation for hookable mail beads:\n\n## Role Templates (internal/templates/roles/)\n- boot.md.tmpl\n- crew.md.tmpl\n- deacon.md.tmpl\n- mayor.md.tmpl\n- polecat.md.tmpl\n- refinery.md.tmpl\n- witness.md.tmpl\n\n## Priming\n- internal/cmd/prime.go output\n\n## Key Documentation Points\n1. GUPP applies to mail: 'If hooked, execute'\n2. Two use cases: hook existing mail, hook new instructions via gt handoff\n3. Execution model: read mail, interpret, execute prose instructions\n4. Successor startup: `gt hook` shows mail details, read and act\n\n## Section to Add (adapt per role)\n```markdown\n## Hookable Mail\n\nMail beads can be hooked for ad-hoc instruction handoff:\n- `gt hook attach \u003cmail-id\u003e` - hook existing mail\n- `gt handoff -m \"...\"` - create and hook new instructions\n\nIf you find mail on your hook, GUPP applies: read it, execute the instructions.\n```","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/dex","created_at":"2025-12-31T00:59:58.20238-08:00","created_by":"mayor","updated_at":"2025-12-31T12:05:58.845848-08:00","closed_at":"2025-12-31T12:05:58.845848-08:00","close_reason":"Added hookable mail documentation to all 7 role templates and prime.go fallback functions","dependencies":[{"issue_id":"gt-frhcq.4","depends_on_id":"gt-frhcq","type":"parent-child","created_at":"2025-12-31T00:59:58.202866-08:00","created_by":"mayor"}]} -{"id":"gt-frvun","title":"gt convoy create/status/list commands","description":"CLI for convoy management in Gas Town.\n\nCommands:\n- gt convoy create \u003cname\u003e \u003cissues...\u003e [--molecule \u003cmol\u003e] [--notify \u003caddr\u003e]\n- gt convoy status [id]\n- gt convoy list\n\nCreates convoy beads in town-level beads (hq-* prefix).\nConvoys track issues across project chains.\n\nDepends on: bd-3roq (tracks relation), bd-hj0s (convoy type)\nRelated: hq-7h8jx (Convoy System epic in town beads)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-29T18:47:29.497351-08:00","created_by":"mayor","updated_at":"2025-12-30T14:15:16.449143-08:00","closed_at":"2025-12-30T14:15:16.449143-08:00","close_reason":"Code review complete. Fixed SQL injection, filed beads for --notify bug (gt-5tipl) and missing tests (gt-c0y43)","dependencies":[{"issue_id":"gt-frvun","depends_on_id":"external:beads:bd-3roq","type":"blocks","created_at":"2025-12-29T18:47:46.644634-08:00","created_by":"daemon"},{"issue_id":"gt-frvun","depends_on_id":"external:beads:bd-hj0s","type":"blocks","created_at":"2025-12-29T18:47:46.687033-08:00","created_by":"daemon"}]} -{"id":"gt-fs6tv","title":"Digest: mol-deacon-patrol","description":"Patrol 211: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:53:46.17719-08:00","updated_at":"2026-01-01T16:53:46.17719-08:00","closed_at":"2026-01-01T16:53:46.177157-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-fs6tv","depends_on_id":"gt-eph-t8kz","type":"parent-child","created_at":"2026-01-01T16:53:46.178487-08:00","created_by":"deacon"}]} -{"id":"gt-ft5eb","title":"Review formula molecules implementation","description":"Review the formula molecules work that's been merged:\n\nCommits to review (check git log):\n- Formula schema (gt-7lhbs)\n- CLI scaffold (gt-gpifj) \n- Leg prompts (gt-f0701)\n\nCheck for:\n1. Code quality and Go idioms\n2. Integration with existing gt/beads patterns\n3. Error handling\n4. Edge cases\n5. Documentation accuracy\n\nThis is launch-critical code - be thorough.","notes":"## Review Complete\n\n**Summary:**\n- gt-7lhbs (Schema): OK - Schema defined via reference implementation\n- gt-gpifj (CLI): NOT MERGED - Critical blocker, filed gt-igx2u (P0)\n- gt-f0701 (Leg prompts): Merged with issues - Template syntax mismatch, filed gt-2dndm (P2)\n\n**Issues Filed:** gt-igx2u (P0), gt-2dndm (P2), gt-jdn2t (P3)\n\n**Recommendation:** Merge gt-gpifj immediately (P0).","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T14:57:10.189702-08:00","created_by":"mayor","updated_at":"2026-01-01T15:01:24.111687-08:00","closed_at":"2026-01-01T15:01:24.111687-08:00","close_reason":"Review complete. Critical finding: CLI scaffold (gt-gpifj) on polecat/nux-mjw18ii8 NOT merged to main. Filed gt-igx2u (P0) for immediate merge. Also filed gt-2dndm (P2) for template syntax, gt-jdn2t (P3) for deprecated API."} -{"id":"gt-ft9bp","title":"Digest: mol-deacon-patrol","description":"Patrol complete: checked inbox, closed convoy hq-qrfz4, all agents healthy, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T00:23:44.169609-08:00","updated_at":"2025-12-31T00:23:44.169609-08:00","closed_at":"2025-12-31T00:23:44.169578-08:00","close_reason":"Squashed from 14 wisps"} -{"id":"gt-fugmy","title":"Clean up unused isFirstRig parameter in initAgentBeads","description":"In manager.go initAgentBeads(), the isFirstRig parameter is no longer used (assigned to blank identifier).\n\nOptions:\n1. Remove the parameter if no callers depend on the signature\n2. Add TODO comment if keeping for backward compatibility\n3. Document why it's kept in the function comment","status":"closed","priority":4,"issue_type":"task","assignee":"gastown/polecats/dinki","created_at":"2026-01-03T21:48:48.029587-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T15:39:33.325475-08:00","closed_at":"2026-01-04T15:39:33.325475-08:00","close_reason":"Already completed and merged to main in commit 4d24f794","dependencies":[{"issue_id":"gt-fugmy","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T21:48:59.581938-08:00","created_by":"gastown/polecats/warboy"}]} -{"id":"gt-fvuje","title":"Extract shared state load/save pattern to generic helper","description":"Nearly identical loadState/saveState methods in:\n- internal/witness/manager.go (lines 39-72)\n- internal/refinery/manager.go (lines 63-96)\n- internal/crew/manager.go (lines 257-306)\n\nAll use the same pattern: read JSON file, handle not-exists, unmarshal/marshal.\n\nSuggestion: Create a generic stateStore[T any] helper in a shared package.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:08.980157-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:24.192166-08:00","closed_at":"2025-12-28T15:47:24.192166-08:00"} -{"id":"gt-fw5yt","title":"Digest: mol-deacon-patrol","description":"Patrol 156: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:06:50.740851-08:00","updated_at":"2026-01-01T15:06:50.740851-08:00","closed_at":"2026-01-01T15:06:50.740815-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fwfm5","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:48:06.95889-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.137744-08:00","closed_at":"2026-01-04T16:41:26.137744-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:48:06-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-fwj8y","title":"Merge: toast-1767079830359","description":"branch: polecat/toast-1767079830359\ntarget: main\nsource_issue: toast-1767079830359\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:37:44.765009-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-29T23:44:37.695134-08:00","closed_at":"2025-12-29T23:44:37.695134-08:00","close_reason":"Branch not found - likely already merged"} -{"id":"gt-fy11w","title":"Daemon patrol should clean stale locks","description":"The gt daemon patrol cycle should detect and clean up stale locks.\n\n## Problem\nIf daemon crashes or there are orphaned locks, they can block operations indefinitely.\n\n## Proposed Solution\nDuring patrol cycle:\n1. Check for lock files older than threshold (e.g., 5 minutes)\n2. Verify owning process is dead (check PID if stored)\n3. Remove stale locks\n4. Log cleanup for audit","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-26T23:13:37.681972-08:00","created_by":"mayor","updated_at":"2025-12-26T23:13:37.681972-08:00"} -{"id":"gt-fyt31","title":"Digest: mol-deacon-patrol","description":"Patrol 9: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:45:59.65526-08:00","updated_at":"2025-12-28T19:45:59.65526-08:00","closed_at":"2025-12-28T19:45:59.655224-08:00"} -{"id":"gt-fz2o1","title":"Digest: mol-deacon-patrol","description":"Patrol 5: clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:23:14.185469-08:00","updated_at":"2025-12-26T14:23:14.185469-08:00","closed_at":"2025-12-26T14:23:14.18543-08:00"} -{"id":"gt-fz4au","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 48: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:55:13.254748-08:00","updated_at":"2026-01-01T12:55:13.254748-08:00","closed_at":"2026-01-01T12:55:13.254711-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-fzkjj","title":"Track spawned sessions in DogDispatchInfo","description":"Minor TODO in internal/cmd/sling.go:1002:\n\n```go\nreturn \u0026DogDispatchInfo{\n DogName: targetDog.Name,\n AgentID: agentID,\n Pane: pane,\n Spawned: false, // TODO: track if we spawned a new session\n}, nil\n```\n\nThe Spawned field is always false. Should track if DispatchToDog actually spawned a new session vs reused an existing one.\n\nLow priority - the information could be useful for logging/debugging but doesn't affect functionality.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-30T22:23:21.644848-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:29:22.085273-08:00","closed_at":"2025-12-30T22:29:22.085273-08:00","close_reason":"Implemented: track spawned dogs in DispatchToDog result"} -{"id":"gt-g09lu","title":"Merge: nux-mjtua3jw","description":"branch: polecat/nux-mjtua3jw\ntarget: main\nsource_issue: nux-mjtua3jw\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T11:44:12.933788-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-31T11:53:36.29823-08:00","closed_at":"2025-12-31T11:53:36.29823-08:00","close_reason":"Merged to main at 6f1b6269"} -{"id":"gt-g0s7j","title":"Merge: slit-mjw3n5iw","description":"branch: polecat/slit-mjw3n5iw\ntarget: main\nsource_issue: slit-mjw3n5iw\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:15:01.646181-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-01T18:25:05.746561-08:00","closed_at":"2026-01-01T18:25:05.746561-08:00","close_reason":"Merged to main at e6f3e0c2"} -{"id":"gt-g0yio","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:01:41.136618-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.5171-08:00","closed_at":"2026-01-04T16:40:13.5171-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:01:41-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-g17mm","title":"Digest: mol-deacon-patrol","description":"Patrol 4: 17 procs, healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:30:18.148751-08:00","updated_at":"2025-12-31T22:30:18.148751-08:00","closed_at":"2025-12-31T22:30:18.148721-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-g1ev3","title":"Refactor: Break up refinery/manager.go Start() function","description":"Start() (lines 107-215, ~110 lines) handles both foreground and background modes with significant branching.\n\nSuggested split:\n- startForeground() - the deprecated foreground path\n- startBackground() - tmux session creation and Claude agent launch\n- ensureClaudeSettings() - settings setup (already exists as separate function)\n- configureSession() - environment and theme setup","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:46:16.628754-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-04T23:46:16.628754-08:00"} -{"id":"gt-g4it4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:52:28.725698-08:00","updated_at":"2025-12-30T15:52:28.725698-08:00","closed_at":"2025-12-30T15:52:28.725656-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-g5b4n","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:23:24.553274-08:00","updated_at":"2026-01-01T10:23:24.553274-08:00","closed_at":"2026-01-01T10:23:24.553239-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-g5pga","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 31: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:28:27.49577-08:00","updated_at":"2026-01-01T12:28:27.49577-08:00","closed_at":"2026-01-01T12:28:27.495731-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-g64op","title":"Session ended: gt-gastown-slit","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T17:15:40.125131-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-05T19:44:18.566663-08:00","closed_at":"2026-01-05T19:44:18.566663-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/slit","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T17:15:34-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-slit\",\"worker\":\"slit\"}"} -{"id":"gt-g6kor","title":"Standardize warning output to use style.Warning","description":"attached_args: Standardize warning output to use style.Warning\n\nUnify warning message formatting across codebase.\n\n## Files to modify\n- internal/cmd/start.go\n- internal/cmd/polecat.go\n- internal/cmd/mail.go\n- Any other files with inconsistent warning output\n\n## Current inconsistency\n```go\nfmt.Printf(\"%s Warning: ...\", style.Dim.Render(\"⚠\"))\nfmt.Printf(\"Warning: %s\", ...)\nfmt.Fprintf(os.Stderr, \"warning: ...\")\n```\n\n## Standard pattern\nCreate helper if needed:\n```go\n// In internal/style/style.go\nfunc PrintWarning(format string, args ...interface{}) {\n msg := fmt.Sprintf(format, args...)\n fmt.Printf(\"%s %s\\n\", Warning.Render(\"⚠ Warning:\"), msg)\n}\n```\n\n## Acceptance criteria\n- [ ] PrintWarning helper in style package\n- [ ] All warning outputs use consistent format\n- [ ] Warnings go to stdout (not stderr) for consistency\n- [ ] grep -rn 'Warning:' internal/cmd/ shows consistent format\n- [ ] go build ./... passes","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:21.941535-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:37:55.053607-08:00","closed_at":"2025-12-28T16:37:55.053607-08:00"} -{"id":"gt-g7z75","title":"Merge: toecutter-mjwlby4g","description":"branch: polecat/toecutter-mjwlby4g\ntarget: main\nsource_issue: toecutter-mjwlby4g\nrig: gastown\nagent_bead: gt-gastown-polecat-toecutter","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T00:20:56.757957-08:00","created_by":"gastown/polecats/toecutter","updated_at":"2026-01-02T00:22:48.300187-08:00","closed_at":"2026-01-02T00:22:48.300187-08:00","close_reason":"Merged to main at 346a283c"} -{"id":"gt-g9ft5","title":"Witness lifecycle doesn't kill tmux sessions after POLECAT_DONE","description":"After witness processes POLECAT_DONE:\n- Git verified clean ✓\n- MERGE_READY sent to refinery ✓ \n- 'Session stopped' reported ✓\n- BUT tmux session still running ✗\n\nEvidence: Found 16 idle polecat tmux sessions piled up, all completed work but sessions not killed.\n\nThe witness lifecycle mail says 'Session stopped' but the tmux session persists. Need to actually kill the session:\n tmux kill-session -t \u003csession-name\u003e\n\nRelated to gt-7vdqv (witness patrol issues).","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/glory","created_at":"2026-01-04T12:25:03.469553-08:00","created_by":"mayor","updated_at":"2026-01-04T12:33:03.048354-08:00","closed_at":"2026-01-04T12:33:03.048354-08:00","close_reason":"Fixed in commit 60418482 - explicitly kill tmux session in NukePolecat before nuke command"} -{"id":"gt-g9iz9","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:08:12.751982-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:40:13.45131-08:00","closed_at":"2026-01-04T16:40:13.45131-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:08:12-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-g9y92","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All 6 agents healthy, 2 polecats, refinery queues processing","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:17:37.00039-08:00","updated_at":"2026-01-01T11:17:37.00039-08:00","closed_at":"2026-01-01T11:17:37.000352-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ga5mm","title":"Digest: mol-deacon-patrol","description":"Patrol 89: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:05:57.034941-08:00","updated_at":"2026-01-01T03:05:57.034941-08:00","closed_at":"2026-01-01T03:05:57.034904-08:00"} -{"id":"gt-gastown-crew-beads-dave","title":"Crew worker beads-dave in gastown - human-managed persistent workspace.","description":"Crew worker beads-dave in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-31T00:42:38.993868-08:00","created_by":"deacon","updated_at":"2026-01-05T18:49:19.80277-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-05T18:49:19.802682-08:00"} -{"id":"gt-gastown-crew-dennis","title":"Crew worker dennis in gastown - human-managed persistent workspace.","description":"Crew worker dennis in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: hq-crew-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"open","priority":2,"issue_type":"agent","created_at":"2026-01-06T18:47:38.44834-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T18:47:51.28779-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T18:47:51.2877-08:00"} -{"id":"gt-gastown-crew-fang","title":"Crew worker fang in gastown - human-managed persistent workspace.","description":"Crew worker fang in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:48:31.614218-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:56:24.101811-08:00","closed_at":"2025-12-29T14:56:24.101811-08:00","close_reason":"Crew moved to beads rig","role_bead":"gt-crew-role"} -{"id":"gt-gastown-crew-george","title":"Crew worker george in gastown - human-managed persistent workspace.","description":"Crew worker george in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"open","priority":2,"issue_type":"agent","created_at":"2026-01-01T23:16:51.931059-08:00","created_by":"stevey","updated_at":"2026-01-06T14:03:20.622722-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T14:03:20.622621-08:00"} -{"id":"gt-gastown-crew-grip","title":"Crew worker grip in gastown - human-managed persistent workspace.","description":"Crew worker grip in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:48:47.052927-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:56:24.095719-08:00","closed_at":"2025-12-29T14:56:24.095719-08:00","close_reason":"Crew moved to beads rig","role_bead":"gt-crew-role"} -{"id":"gt-gastown-crew-gus","title":"Crew worker gus in gastown - human-managed persistent workspace.","description":"Crew worker gus in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-30T19:12:14.723189-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T14:03:09.798513-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T14:03:09.798418-08:00"} -{"id":"gt-gastown-crew-jack","title":"Crew worker jack in gastown - human-managed persistent workspace.","description":"Crew worker jack in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:49:02.451898-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:50:26.099351-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T13:50:26.099265-08:00"} -{"id":"gt-gastown-crew-joe","title":"Crew worker joe in gastown - human-managed persistent workspace.","description":"Crew worker joe in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: running\nhook_bead: gt-7aw1m\nrole_bead: gt-crew-role\ncleanup_status: null","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:49:17.861869-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T18:35:25.843468-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T18:35:25.843356-08:00"} -{"id":"gt-gastown-crew-max","title":"Crew worker max in gastown - human-managed persistent workspace.","description":"Crew worker max in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: has_uncommitted","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:49:33.272043-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:26:17.255249-08:00","role_bead":"hq-crew-role","agent_state":"running","last_activity":"2026-01-06T13:26:17.255161-08:00"} -{"id":"gt-gastown-crew-test-crew38","title":"Crew worker test-crew38 in gastown - human-managed persistent workspace.","description":"Crew worker test-crew38 in gastown - human-managed persistent workspace.\n\nrole_type: crew\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-crew-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T12:56:22.907721-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T12:56:43.437339-08:00","closed_at":"2026-01-04T12:56:43.437339-08:00","close_reason":"Crew workspace removed","role_bead":"gt-crew-role"} -{"id":"gt-gastown-crew-wolf","title":"Crew worker wolf in gastown","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:52:01.595469-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:56:24.107543-08:00","closed_at":"2025-12-29T14:56:24.107543-08:00","close_reason":"Crew moved to beads rig"} -{"id":"gt-gastown-polecat-ace","title":"gt-gastown-polecat-ace","description":"gt-gastown-polecat-ace\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-qfgfr\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:59:45.180508-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:14.136609-08:00","closed_at":"2026-01-05T00:36:14.136609-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:13.79515-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:54:22.5506-08:00"} -{"id":"gt-gastown-polecat-angharad","title":"gt-gastown-polecat-angharad","description":"gt-gastown-polecat-angharad\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-6zzvi\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-a0euf\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-01T23:19:40.675922-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:14.547319-08:00","closed_at":"2026-01-05T00:36:14.547319-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:14.435157-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:54:24.724291-08:00"} -{"id":"gt-gastown-polecat-bix","title":"gt-gastown-polecat-bix","description":"gt-gastown-polecat-bix\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-31T11:57:55.427572-08:00","created_by":"mayor","updated_at":"2025-12-31T12:10:21.431346-08:00","closed_at":"2025-12-31T12:10:21.431346-08:00","close_reason":"nuked","deleted_at":"2025-12-31T12:10:21.399751-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","hook_bead":"gt-frhcq.2","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2025-12-31T12:00:08.744411-08:00"} -{"id":"gt-gastown-polecat-blackfinger","title":"gt-gastown-polecat-blackfinger","description":"gt-gastown-polecat-blackfinger\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.9\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:45:47.542959-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:34:36.165457-08:00","closed_at":"2026-01-05T00:34:36.165457-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:34:35.834562-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:12:20.350971-08:00"} -{"id":"gt-gastown-polecat-bullet","title":"gt-gastown-polecat-bullet","description":"gt-gastown-polecat-bullet\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-q73h3\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-7hc70\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-02T00:06:36.680313-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:14.963617-08:00","closed_at":"2026-01-05T00:36:14.963617-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:14.846831-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:54:26.619991-08:00"} -{"id":"gt-gastown-polecat-bullet-farmer","title":"gt-gastown-polecat-bullet-farmer","description":"gt-gastown-polecat-bullet-farmer\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.3\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:43:39.775526-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:34:36.5727-08:00","closed_at":"2026-01-05T00:34:36.5727-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:34:36.463307-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:09:58.723669-08:00"} -{"id":"gt-gastown-polecat-buzzard","title":"gt-gastown-polecat-buzzard","description":"gt-gastown-polecat-buzzard\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.1\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:42:58.81962-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:34:36.987589-08:00","closed_at":"2026-01-05T00:34:36.987589-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:34:36.877301-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:07:35.448054-08:00"} -{"id":"gt-gastown-polecat-cal","title":"gt-gastown-polecat-cal","description":"gt-gastown-polecat-cal\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: clean","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-31T11:57:55.594945-08:00","created_by":"mayor","updated_at":"2025-12-31T12:10:10.418447-08:00","closed_at":"2025-12-31T12:10:10.418447-08:00","close_reason":"nuked","deleted_at":"2025-12-31T12:10:10.38224-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"done","last_activity":"2025-12-31T12:08:45.268271-08:00"} -{"id":"gt-gastown-polecat-capable","title":"gt-gastown-polecat-capable","description":"gt-gastown-polecat-capable\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-rbncw\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-dhzqj\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:56:09.595279-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:15.386089-08:00","closed_at":"2026-01-05T00:36:15.386089-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:15.269093-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:22:11.715619-08:00"} -{"id":"gt-gastown-polecat-cheedo","title":"gt-gastown-polecat-cheedo","description":"gt-gastown-polecat-cheedo\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-42whv\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:58:54.800962-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:15.809402-08:00","closed_at":"2026-01-05T00:36:15.809402-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:15.692166-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:47:49.653893-08:00"} -{"id":"gt-gastown-polecat-chrome","title":"gt-gastown-polecat-chrome","description":"gt-gastown-polecat-chrome\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-rsnj9\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-05T00:13:05.316497-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:25:36.922672-08:00","closed_at":"2026-01-05T00:25:36.922672-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:36.784891-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:13:20.10926-08:00"} -{"id":"gt-gastown-polecat-chumbucket","title":"gt-gastown-polecat-chumbucket","description":"gt-gastown-polecat-chumbucket\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-bc6gm\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-m63yl\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T14:19:39.178468-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:16.216719-08:00","closed_at":"2026-01-05T00:36:16.216719-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:16.10358-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-04T21:31:39.653537-08:00"} -{"id":"gt-gastown-polecat-citadel","title":"gt-gastown-polecat-citadel","description":"gt-gastown-polecat-citadel\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.4\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:44:00.274835-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:38.673888-08:00","closed_at":"2026-01-05T00:25:38.673888-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:38.542213-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:10:31.204799-08:00"} -{"id":"gt-gastown-polecat-coma","title":"gt-gastown-polecat-coma","description":"gt-gastown-polecat-coma\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-trfaz\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-01T23:11:50.628946-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:16.625211-08:00","closed_at":"2026-01-05T00:36:16.625211-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:16.508743-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:54:28.765052-08:00"} -{"id":"gt-gastown-polecat-corpus","title":"gt-gastown-polecat-corpus","description":"gt-gastown-polecat-corpus\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-32d4a\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-vtlh6\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T14:19:59.542888-08:00","created_by":"mayor","updated_at":"2026-01-05T00:35:50.558882-08:00","closed_at":"2026-01-05T00:35:50.558882-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:50.414902-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-04T22:01:18.424789-08:00"} -{"id":"gt-gastown-polecat-dag","title":"gt-gastown-polecat-dag","description":"gt-gastown-polecat-dag\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-tvwnz\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-vve6k\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:58:43.032649-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:17.069329-08:00","closed_at":"2026-01-05T00:36:17.069329-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:16.952887-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:47:31.622617-08:00"} -{"id":"gt-gastown-polecat-dementus","title":"gt-gastown-polecat-dementus","description":"gt-gastown-polecat-dementus\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-lfi2d\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-20i1i\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:43:05.226023-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:17.48737-08:00","closed_at":"2026-01-05T00:36:17.48737-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:17.37361-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:21:53.965459-08:00"} -{"id":"gt-gastown-polecat-dex","title":"gt-gastown-polecat-dex","description":"gt-gastown-polecat-dex\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: clean","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-31T11:57:55.75852-08:00","created_by":"mayor","updated_at":"2025-12-31T12:08:06.785147-08:00","closed_at":"2025-12-31T12:08:06.785147-08:00","close_reason":"nuked","deleted_at":"2025-12-31T12:08:06.751506-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"done","last_activity":"2025-12-31T12:07:32.457067-08:00"} -{"id":"gt-gastown-polecat-dinki","title":"gt-gastown-polecat-dinki","description":"gt-gastown-polecat-dinki\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-l0lok\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-1qp3u\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T14:20:21.016241-08:00","created_by":"mayor","updated_at":"2026-01-05T00:35:51.467825-08:00","closed_at":"2026-01-05T00:35:51.467825-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:51.327299-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T22:14:03.634958-08:00"} -{"id":"gt-gastown-polecat-eli","title":"gt-gastown-polecat-eli","description":"gt-gastown-polecat-eli\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-31T11:57:55.926133-08:00","created_by":"mayor","updated_at":"2025-12-31T12:10:44.708204-08:00","closed_at":"2025-12-31T12:10:44.708204-08:00","close_reason":"nuked","deleted_at":"2025-12-31T12:10:44.675713-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"done","last_activity":"2025-12-31T12:09:55.854153-08:00"} -{"id":"gt-gastown-polecat-furiosa","title":"gt-gastown-polecat-furiosa","description":"gt-gastown-polecat-furiosa\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-csbjj\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-ekmmu\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T17:54:50.716414-08:00","created_by":"mayor","updated_at":"2026-01-06T18:42:01.285386-08:00","closed_at":"2026-01-06T13:59:53.600107-08:00","close_reason":"nuked","deleted_at":"2026-01-06T13:59:53.480765-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","hook_bead":"gt-zmznh","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-06T18:42:00.792691-08:00"} -{"id":"gt-gastown-polecat-fury","title":"gt-gastown-polecat-fury","description":"gt-gastown-polecat-fury\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.6\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:44:43.294088-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:39.972509-08:00","closed_at":"2026-01-05T00:25:39.972509-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:39.840549-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:11:12.805736-08:00"} -{"id":"gt-gastown-polecat-gastown","title":"gt-gastown-polecat-gastown","description":"gt-gastown-polecat-gastown\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.2\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:43:18.798956-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:35:51.923399-08:00","closed_at":"2026-01-05T00:35:51.923399-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:51.782418-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:07:57.842452-08:00"} -{"id":"gt-gastown-polecat-glory","title":"gt-gastown-polecat-glory","description":"gt-gastown-polecat-glory\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-g9ft5\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-lexde\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T12:25:29.521355-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:18.350142-08:00","closed_at":"2026-01-05T00:36:18.350142-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:18.231784-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T12:25:43.64474-08:00"} -{"id":"gt-gastown-polecat-goose","title":"gt-gastown-polecat-goose","description":"gt-gastown-polecat-goose\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-cbstf\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-zzjoh\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-02T00:12:17.615617-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:18.780177-08:00","closed_at":"2026-01-05T00:36:18.780177-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:18.66383-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:38:01.132684-08:00"} -{"id":"gt-gastown-polecat-gus","title":"gt-gastown-polecat-gus","description":"gt-gastown-polecat-gus\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: hq-polecat-role\ncleanup_status: clean\nactive_mr: gt-i1eaj\nnotification_level: null","status":"open","priority":2,"issue_type":"agent","created_at":"2026-01-04T20:49:39.870722-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T00:22:10.235368-08:00","role_bead":"hq-polecat-role","agent_state":"done","last_activity":"2026-01-05T00:22:09.810901-08:00"} -{"id":"gt-gastown-polecat-immortan","title":"gt-gastown-polecat-immortan","description":"gt-gastown-polecat-immortan\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-pn2fq\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-5gc2e\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-02T00:06:12.606912-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:19.197608-08:00","closed_at":"2026-01-05T00:36:19.197608-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:19.080288-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:35:15.736568-08:00"} -{"id":"gt-gastown-polecat-imperator","title":"gt-gastown-polecat-imperator","description":"gt-gastown-polecat-imperator\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_stash\nactive_mr: gt-mt3d6\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T06:47:59.120921-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:19.611003-08:00","closed_at":"2026-01-05T00:36:19.611003-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:19.497435-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-03T20:49:25.570054-08:00"} -{"id":"gt-gastown-polecat-interceptor","title":"gt-gastown-polecat-interceptor","description":"gt-gastown-polecat-interceptor\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.8\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:45:24.99371-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:39.539805-08:00","closed_at":"2026-01-05T00:25:39.539805-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:39.408351-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:11:57.350626-08:00"} -{"id":"gt-gastown-polecat-keeper","title":"gt-gastown-polecat-keeper","description":"gt-gastown-polecat-keeper\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-zuupc\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:59:02.304059-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:25.666539-08:00","closed_at":"2026-01-05T00:36:25.666539-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:25.32805-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:48:26.152405-08:00"} -{"id":"gt-gastown-polecat-max","title":"gt-gastown-polecat-max","description":"gt-gastown-polecat-max\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-pn2fq\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-8iwvq\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-02T00:05:03.921534-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:26.070643-08:00","closed_at":"2026-01-05T00:36:26.070643-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:25.956703-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:34:58.991815-08:00"} -{"id":"gt-gastown-polecat-mediocre","title":"gt-gastown-polecat-mediocre","description":"gt-gastown-polecat-mediocre\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-gaw8e\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-05T00:13:55.850038-08:00","created_by":"mayor","updated_at":"2026-01-05T00:25:37.809096-08:00","closed_at":"2026-01-05T00:25:37.809096-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:37.677953-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:14:10.458119-08:00"} -{"id":"gt-gastown-polecat-morsov","title":"gt-gastown-polecat-morsov","description":"gt-gastown-polecat-morsov\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_stash\nactive_mr: gt-zanca\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:59:41.438694-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:26.492081-08:00","closed_at":"2026-01-05T00:36:26.492081-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:26.376103-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:48:45.123237-08:00"} -{"id":"gt-gastown-polecat-nightrider","title":"gt-gastown-polecat-nightrider","description":"gt-gastown-polecat-nightrider\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-m39yd\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-yyp92\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T10:38:28.255941-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:26.921546-08:00","closed_at":"2026-01-05T00:36:26.921546-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:26.804397-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:38:42.102761-08:00"} -{"id":"gt-gastown-polecat-nux","title":"gt-gastown-polecat-nux","description":"gt-gastown-polecat-nux\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-s94gq\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-ztzlm\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T17:54:53.302196-08:00","created_by":"mayor","updated_at":"2026-01-06T18:45:59.141104-08:00","closed_at":"2026-01-05T22:01:37.386868-08:00","close_reason":"nuked","deleted_at":"2026-01-05T22:01:37.24887-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"done","last_activity":"2026-01-06T18:45:58.571638-08:00"} -{"id":"gt-gastown-polecat-organic","title":"gt-gastown-polecat-organic","description":"gt-gastown-polecat-organic\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_stash\nactive_mr: gt-scdyn\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T06:48:03.048759-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:27.340949-08:00","closed_at":"2026-01-05T00:36:27.340949-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:27.224454-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-03T21:15:24.584364-08:00"} -{"id":"gt-gastown-polecat-prime","title":"gt-gastown-polecat-prime","description":"gt-gastown-polecat-prime\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-ptwe1\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-o1y8u\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T14:25:58.193482-08:00","created_by":"mayor","updated_at":"2026-01-05T00:35:52.368784-08:00","closed_at":"2026-01-05T00:35:52.368784-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:52.228838-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T22:14:22.733741-08:00"} -{"id":"gt-gastown-polecat-rictus","title":"gt-gastown-polecat-rictus","description":"gt-gastown-polecat-rictus\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-u4fh\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-8zy1s\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T17:54:58.123296-08:00","created_by":"mayor","updated_at":"2026-01-05T22:01:37.85149-08:00","closed_at":"2026-01-05T22:01:37.85149-08:00","close_reason":"nuked","deleted_at":"2026-01-05T22:01:37.714261-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","hook_bead":"gt-h6rmm","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T21:41:14.9491-08:00"} -{"id":"gt-gastown-polecat-road-warrior","title":"gt-gastown-polecat-road-warrior","description":"gt-gastown-polecat-road-warrior\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.7\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:45:05.849501-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:37.367915-08:00","closed_at":"2026-01-05T00:25:37.367915-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:37.229273-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:11:36.236084-08:00"} -{"id":"gt-gastown-polecat-rockryder","title":"gt-gastown-polecat-rockryder","description":"gt-gastown-polecat-rockryder\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-ttn3h\nrole_bead: hq-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-3g4b0\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T16:42:28.667176-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:27.768977-08:00","closed_at":"2026-01-05T00:36:27.768977-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:27.649743-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"done","last_activity":"2026-01-04T16:53:19.112763-08:00"} -{"id":"gt-gastown-polecat-scrotus","title":"gt-gastown-polecat-scrotus","description":"gt-gastown-polecat-scrotus\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-5gkdq\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-d3z69\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T13:07:47.983821-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:28.192413-08:00","closed_at":"2026-01-05T00:36:28.192413-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:28.075848-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T13:08:02.177591-08:00"} -{"id":"gt-gastown-polecat-shiny","title":"gt-gastown-polecat-shiny","description":"gt-gastown-polecat-shiny\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-n5gga\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-05T00:13:29.638148-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:25:40.406102-08:00","closed_at":"2026-01-05T00:25:40.406102-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:40.272903-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:13:44.200344-08:00"} -{"id":"gt-gastown-polecat-slit","title":"gt-gastown-polecat-slit","description":"gt-gastown-polecat-slit\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-bho9\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-fdlob\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T17:54:55.706657-08:00","created_by":"mayor","updated_at":"2026-01-05T22:01:38.297735-08:00","closed_at":"2026-01-05T22:01:38.297735-08:00","close_reason":"nuked","deleted_at":"2026-01-05T22:01:38.158205-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"done","last_activity":"2026-01-05T17:15:26.404915-08:00"} -{"id":"gt-gastown-polecat-splendid","title":"gt-gastown-polecat-splendid","description":"gt-gastown-polecat-splendid\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-zqt4d\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-p7ehb\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-01T23:17:22.827326-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:29.071143-08:00","closed_at":"2026-01-05T00:36:29.071143-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:28.956623-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-03T21:04:32.774876-08:00"} -{"id":"gt-gastown-polecat-testcat","title":"gt-gastown-polecat-testcat","description":"gt-gastown-polecat-testcat\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: clean","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:08:56.626354-08:00","created_by":"mayor","updated_at":"2025-12-30T21:21:39.417837-08:00","closed_at":"2025-12-30T21:21:39.417837-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:21:39.384762-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"done","last_activity":"2025-12-30T21:13:51.223308-08:00"} -{"id":"gt-gastown-polecat-testcat2","title":"gt-gastown-polecat-testcat2","description":"gt-gastown-polecat-testcat2\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:11:16.694944-08:00","created_by":"mayor","updated_at":"2025-12-30T21:12:32.208764-08:00","closed_at":"2025-12-30T21:12:32.208764-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:12:32.174469-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","hook_bead":"gt-nq3pr","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2025-12-30T21:11:18.304095-08:00"} -{"id":"gt-gastown-polecat-testcat3","title":"gt-gastown-polecat-testcat3","description":"gt-gastown-polecat-testcat3\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:12:32.314957-08:00","created_by":"mayor","updated_at":"2025-12-30T21:14:37.495375-08:00","closed_at":"2025-12-30T21:14:37.495375-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:14:37.459921-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","hook_bead":"gt-nq3pr","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2025-12-30T21:12:41.113009-08:00"} -{"id":"gt-gastown-polecat-testcat4","title":"gt-gastown-polecat-testcat4","description":"gt-gastown-polecat-testcat4\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:14:37.59985-08:00","created_by":"mayor","updated_at":"2025-12-30T21:21:39.558289-08:00","closed_at":"2025-12-30T21:21:39.558289-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:21:39.524818-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","hook_bead":"gt-nq3pr","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2025-12-30T21:14:39.146942-08:00"} -{"id":"gt-gastown-polecat-testcat5","title":"gt-gastown-polecat-testcat5","description":"gt-gastown-polecat-testcat5\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:15:23.137896-08:00","created_by":"mayor","updated_at":"2025-12-30T21:16:05.928153-08:00","closed_at":"2025-12-30T21:16:05.928153-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:16:05.893033-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","hook_bead":"gt-nq3pr","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2025-12-30T21:15:24.627546-08:00"} -{"id":"gt-gastown-polecat-testcat6","title":"gt-gastown-polecat-testcat6","description":"gt-gastown-polecat-testcat6\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: clean","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T21:16:06.037644-08:00","created_by":"mayor","updated_at":"2025-12-30T21:21:39.700411-08:00","closed_at":"2025-12-30T21:21:39.700411-08:00","close_reason":"nuked","deleted_at":"2025-12-30T21:21:39.666945-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"done","last_activity":"2025-12-30T21:19:34.06085-08:00"} -{"id":"gt-gastown-polecat-toast","title":"gt-gastown-polecat-toast","description":"gt-gastown-polecat-toast\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-38doh\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-4bi8o\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:58:19.899125-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:29.587004-08:00","closed_at":"2026-01-05T00:36:29.587004-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:29.438128-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:47:13.41558-08:00"} -{"id":"gt-gastown-polecat-toecutter","title":"gt-gastown-polecat-toecutter","description":"gt-gastown-polecat-toecutter\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-27bzi\nrole_bead: gt-polecat-role\ncleanup_status: null\nactive_mr: gt-q4qxg\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-02T00:07:01.667203-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:36:30.291818-08:00","closed_at":"2026-01-05T00:36:30.291818-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:29.946913-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T10:37:43.666044-08:00"} -{"id":"gt-gastown-polecat-valkyrie","title":"gt-gastown-polecat-valkyrie","description":"gt-gastown-polecat-valkyrie\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_uncommitted\nactive_mr: gt-i9pl9\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-29T21:58:58.583302-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:30.706496-08:00","closed_at":"2026-01-05T00:36:30.706496-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:30.589413-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-02T18:48:07.920018-08:00"} -{"id":"gt-gastown-polecat-vuvalini","title":"gt-gastown-polecat-vuvalini","description":"gt-gastown-polecat-vuvalini\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a40d8\nrole_bead: gt-polecat-role\ncleanup_status: clean\nactive_mr: gt-3ee79\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T14:44:42.449327-08:00","created_by":"mayor","updated_at":"2026-01-05T00:35:51.012103-08:00","closed_at":"2026-01-05T00:35:51.012103-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:50.87182-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-04T22:21:22.790597-08:00"} -{"id":"gt-gastown-polecat-warboy","title":"gt-gastown-polecat-warboy","description":"gt-gastown-polecat-warboy\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: gt-polecat-role\ncleanup_status: has_stash\nactive_mr: gt-jf6ls\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-30T06:47:40.892638-08:00","created_by":"mayor","updated_at":"2026-01-05T00:36:31.177631-08:00","closed_at":"2026-01-05T00:36:31.177631-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:36:31.032836-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"gt-polecat-role","agent_state":"running","last_activity":"2026-01-03T20:49:06.840707-08:00"} -{"id":"gt-gastown-polecat-wasteland","title":"gt-gastown-polecat-wasteland","description":"gt-gastown-polecat-wasteland\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.5\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:44:22.2559-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:39.110355-08:00","closed_at":"2026-01-05T00:25:39.110355-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:38.977423-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:10:53.426673-08:00"} -{"id":"gt-gastown-polecat-witness","title":"gt-gastown-polecat-witness","description":"gt-gastown-polecat-witness\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.11\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:46:29.452559-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T22:01:38.749569-08:00","closed_at":"2026-01-05T22:01:38.749569-08:00","close_reason":"nuked","deleted_at":"2026-01-05T22:01:38.61117-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:12:56.869414-08:00"} -{"id":"gt-gastown-polecat-wraith","title":"gt-gastown-polecat-wraith","description":"gt-gastown-polecat-wraith\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-a02fj.10\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:46:09.915206-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:25:38.248226-08:00","closed_at":"2026-01-05T00:25:38.248226-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:25:38.113663-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-05T00:12:44.563066-08:00"} -{"id":"gt-gastown-polecat-wretched","title":"gt-gastown-polecat-wretched","description":"gt-gastown-polecat-wretched\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: gt-5ww96\nrole_bead: hq-polecat-role\ncleanup_status: null\nactive_mr: null\nnotification_level: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2026-01-04T23:35:59.69327-08:00","created_by":"mayor","updated_at":"2026-01-05T00:35:53.311568-08:00","closed_at":"2026-01-05T00:35:53.311568-08:00","close_reason":"nuked","deleted_at":"2026-01-05T00:35:53.169237-08:00","deleted_by":"mayor","delete_reason":"delete","original_type":"agent","role_bead":"hq-polecat-role","agent_state":"running","last_activity":"2026-01-04T23:36:14.384256-08:00"} -{"id":"gt-gastown-refinery","title":"Refinery for gastown - processes merge queue.","description":"role_type: refinery\nrig: gastown\nagent_state: dead\nhook_bead: \nrole_bead: gt-refinery-role\n\nMarked dead by daemon at 2026-01-06T17:02:41-08:00 (was running, last update too old)","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:48:16.178399-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T18:50:28.550277-08:00","role_bead":"hq-refinery-role","agent_state":"running","last_activity":"2026-01-06T18:50:28.550173-08:00"} -{"id":"gt-gastown-witness","title":"Witness for gastown - monitors polecat health and progress.","description":"role_type: witness\nrig: gastown\nagent_state: dead\nhook_bead: \nrole_bead: gt-witness-role\n\nMarked dead by daemon at 2026-01-06T17:02:41-08:00 (was running, last update too old)","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-29T14:48:00.691337-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T18:50:28.168765-08:00","role_bead":"hq-witness-role","agent_state":"running","last_activity":"2026-01-06T18:44:17.910977-08:00"} -{"id":"gt-gaw8e","title":"Refactor: Extract common AgentStateManager pattern","description":"witness/manager.go and refinery/manager.go both have identical loadState()/saveState() patterns. Extract to a shared AgentStateManager interface or struct.\n\nFiles:\n- internal/witness/manager.go:40-68\n- internal/refinery/manager.go:67-95\n\nAlso unify the duplicate State type (StateStopped, StateRunning, StatePaused) defined identically in both witness/types.go and refinery/types.go.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/mediocre","created_at":"2026-01-04T23:46:08.447566-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T00:19:47.521986-08:00","closed_at":"2026-01-05T00:19:47.521986-08:00","close_reason":"Implemented shared AgentStateManager pattern"} -{"id":"gt-gaza0","title":"Digest: mol-deacon-patrol","description":"Patrol 7: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:33:44.544221-08:00","updated_at":"2025-12-29T22:33:44.544221-08:00","closed_at":"2025-12-29T22:33:44.544184-08:00"} -{"id":"gt-gb5l1","title":"Merge: nux-mjwny9w0","description":"branch: polecat/nux-mjwny9w0\ntarget: main\nsource_issue: nux-mjwny9w0\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T01:25:45.052662-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T01:27:08.265804-08:00","closed_at":"2026-01-02T01:27:08.265804-08:00","close_reason":"Merged to main at c7e5bc08"} -{"id":"gt-gbw0a","title":"Audit and migrate gt-mayor/gt-deacon references to hq- prefix","description":"## Background\n\nPhase 1 (gt-y24km) added hq- prefix helpers for town-level agent beads:\n- MayorBeadIDTown() → \"hq-mayor\"\n- DeaconBeadIDTown() → \"hq-deacon\"\n- DogBeadIDTown(name) → \"hq-dog-\u003cname\u003e\"\n\nThe old gt-mayor/gt-deacon IDs are now deprecated.\n\n## Scope\n\nAudit and update all references to the old naming:\n\n### Code\n- All callers of deprecated MayorBeadID() and DeaconBeadID()\n- Hardcoded \"gt-mayor\" and \"gt-deacon\" strings\n- ParseAgentBeadID() logic if needed\n\n### Documentation\n- CLAUDE.md and other markdown files\n- Code comments referencing the old IDs\n- Any architecture docs\n\n### Open Plans\n- Check for any in-progress work that assumes gt-* for mayor/deacon\n\n## Acceptance Criteria\n- [ ] No code uses deprecated MayorBeadID()/DeaconBeadID()\n- [ ] No hardcoded \"gt-mayor\" or \"gt-deacon\" strings (except in deprecated functions)\n- [ ] Documentation updated to reflect hq- prefix for town-level agents\n- [ ] Tests updated/added as needed","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T21:44:46.701379-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-03T21:53:50.351813-08:00","closed_at":"2026-01-03T21:53:50.351813-08:00","close_reason":"Migrated all callers of deprecated MayorBeadID()/DeaconBeadID() to use Town variants. Tests pass."} -{"id":"gt-gc032","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:07:25.570965-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.464449-08:00","closed_at":"2026-01-04T16:40:13.464449-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:07:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-gck2d","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:10:38.387714-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:10:38.436123-08:00","closed_at":"2026-01-05T21:10:38.436123-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:10:38-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-gcnnr","title":"Add logging for silently ignored errors","description":"attached_args: Add logging for silently ignored errors\n\nAdd logging for silently ignored errors.\n\n## Problem\nMany places use `_ =` pattern to ignore errors without any logging, making debugging difficult.\n\n## Files to modify\n- internal/cmd/start.go (lines 167, 322-323, 429, 747-753, 886-888)\n- internal/cmd/polecat.go (search for `_ =`)\n- internal/session/manager.go (lines 140-154)\n- internal/refinery/manager.go (line 399)\n- internal/keepalive/keepalive.go (document as intentional)\n\n## Implementation options\n\n### Option A: Add comments explaining safety\n```go\n_ = m.saveState(ref) // Non-fatal: state will be recreated on next run\n```\n\n### Option B: Log warnings (preferred for important operations)\n```go\nif err := m.saveState(ref); err != nil {\n log.Printf(\"warning: failed to save state: %v\", err)\n}\n```\n\n## Guidelines\n- Use logging for: state saves, config writes, cleanup operations\n- Use comments for: truly benign operations (e.g., closing already closed file)\n- keepalive is intentionally best-effort - add package-level comment\n\n## Acceptance criteria\n- [ ] All `_ =` in start.go have comment OR logging\n- [ ] All `_ =` in session/manager.go have comment OR logging \n- [ ] refinery/manager.go:399 has logging\n- [ ] keepalive package has doc comment explaining best-effort design\n- [ ] grep '`_ =`' shows all have justification\n- [ ] go build ./... passes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:13.787806-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:40:19.539625-08:00","closed_at":"2025-12-28T16:40:19.539625-08:00"} -{"id":"gt-gdbcb","title":"Merge: rictus-1767141956287","description":"branch: polecat/rictus-1767141956287\ntarget: main\nsource_issue: rictus-1767141956287\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:47:36.872662-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T18:23:22.145399-08:00","closed_at":"2025-12-30T18:23:22.145399-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-gdc58","title":"Merge: furiosa-mjtj9d4g","description":"branch: polecat/furiosa-mjtj9d4g\ntarget: main\nsource_issue: furiosa-mjtj9d4g\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:13:57.386911-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T23:12:43.025406-08:00","closed_at":"2025-12-30T23:12:43.025406-08:00","close_reason":"Branch already merged"} -{"id":"gt-gdhee","title":"Digest: mol-deacon-patrol","description":"Cycle 15: quiet, handoff for fresh context","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:24:00.135165-08:00","updated_at":"2025-12-28T13:24:00.135165-08:00","closed_at":"2025-12-28T13:24:00.135129-08:00"} -{"id":"gt-ge8i2","title":"Session ended: gt-gastown-corpus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:17:56.20174-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-05T00:08:31.847233-08:00","closed_at":"2026-01-05T00:08:31.847233-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/corpus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:17:56-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-corpus\",\"worker\":\"corpus\"}"} -{"id":"gt-gfgb5","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T17:00:47.996272-08:00","updated_at":"2025-12-31T17:00:47.996272-08:00","closed_at":"2025-12-31T17:00:47.996236-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gg73s","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:19:30.76225-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T21:19:30.816551-08:00","closed_at":"2026-01-05T21:19:30.816551-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:19:30-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-gghi5","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:52:00.568508-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.035732-08:00","closed_at":"2026-01-04T16:41:26.035732-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:52:00-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-ggkk6","title":"Digest: mol-deacon-patrol","description":"Patrol 9: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:32:37.746097-08:00","updated_at":"2025-12-31T22:32:37.746097-08:00","closed_at":"2025-12-31T22:32:37.74606-08:00"} -{"id":"gt-ghwco","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:41:52.958348-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.86897-08:00","closed_at":"2026-01-04T16:40:22.86897-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:41:52-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-giuit","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:31:28.764242-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.589129-08:00","closed_at":"2026-01-05T19:44:18.589129-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:31:28-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-giyhp","title":"Bug: gt sling doesn't update agent bead hook_bead field","description":"gt sling marks task as pinned with assignee, but doesn't update the agent bead's hook_bead field. Agent beads show hook_bead: null even after slinging. This prevents agents from knowing they have work on their hook.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T16:19:01.206912-08:00","created_by":"stevey","updated_at":"2025-12-28T16:21:08.592848-08:00","closed_at":"2025-12-28T16:21:08.592848-08:00"} -{"id":"gt-gizsv","title":"Day 3.2: Witness reads agent beads for polecat state","description":"Witness patrol reads polecat state from agent beads:\n- bd list --type=agent --role_type=polecat\n- For each, check state field\n- If state=running, check progress\n- If state=stuck, handle stuck protocol\n\nNo more PID/tmux inference.\n\nParent: gt-hwka3","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:03.267386-08:00","created_by":"mayor","updated_at":"2025-12-28T09:42:16.843615-08:00","closed_at":"2025-12-28T09:42:16.843615-08:00","dependencies":[{"issue_id":"gt-gizsv","depends_on_id":"gt-hwka3","type":"parent-child","created_at":"2025-12-27T20:58:46.785298-08:00","created_by":"daemon"},{"issue_id":"gt-gizsv","depends_on_id":"gt-qpoxz","type":"blocks","created_at":"2025-12-27T20:58:57.74074-08:00","created_by":"daemon"},{"issue_id":"gt-gizsv","depends_on_id":"gt-dtw9u","type":"relates-to","created_at":"2025-12-27T20:59:11.760004-08:00","created_by":"daemon"},{"issue_id":"gt-gizsv","depends_on_id":"gt-k294l","type":"blocks","created_at":"2025-12-27T23:17:28.218839-08:00","created_by":"daemon"}]} -{"id":"gt-gj07c","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:05:56.516499-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T21:05:56.564007-08:00","closed_at":"2026-01-05T21:05:56.564007-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:05:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-gj6lx","title":"Digest: mol-deacon-patrol","description":"Patrol 3 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:40:40.957172-08:00","updated_at":"2025-12-31T16:40:40.957172-08:00","closed_at":"2025-12-31T16:40:40.95714-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gjvh5","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:47:47.896541-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:47:47.951243-08:00","closed_at":"2026-01-05T19:47:47.951243-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:47:47-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-glgdo","title":"MQ conflict prediction: file hotspot tracking","description":"Track which files change frequently to predict conflicts before spawn.\n\n## Goal\nBefore spawning a polecat on an issue, warn if the target files are \"hot\" (recently changed by other MRs).\n\n## Approach\n1. Track file change frequency per MR (sliding window, e.g., last 24h)\n2. At spawn time, analyze issue description / planned changes\n3. If touching hot files, either:\n - Warn and proceed\n - Suggest waiting for queue to clear\n - Auto-assign to ownership zone (future)\n\n## Implementation\n- Add file_changes log to refinery state (or separate hotspot.json)\n- After each merge, record changed files with timestamp\n- gt spawn checks hotspots before assignment\n- Optional: Witness patrol aggregates hotspot data\n\n## Example\n```\n$ gt spawn --issue gt-xyz\nWarning: This issue likely touches auth/login.go\n - Changed 3 times in last 2 hours\n - 2 MRs pending that also touch this file\nProceed anyway? [y/N]\n```\n\n## Parent\ngt-lxxh2","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-25T18:30:33.326775-08:00","updated_at":"2025-12-25T18:30:33.326775-08:00","dependencies":[{"issue_id":"gt-glgdo","depends_on_id":"gt-lxxh2","type":"blocks","created_at":"2025-12-25T18:30:38.957891-08:00","created_by":"daemon"}]} -{"id":"gt-gmcfm","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:49.827708-08:00","updated_at":"2025-12-28T11:22:49.827708-08:00","closed_at":"2025-12-28T11:22:49.827674-08:00"} -{"id":"gt-gmsi7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:51:30.761353-08:00","updated_at":"2025-12-31T23:51:30.761353-08:00","closed_at":"2025-12-31T23:51:30.761316-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gnqij","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:53:35.061031-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.506643-08:00","closed_at":"2026-01-05T19:44:18.506643-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:53:29-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-gnuat","title":"Merge: dementus-1767081113622","description":"branch: polecat/dementus-1767081113622\ntarget: main\nsource_issue: dementus-1767081113622\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:57:52.375289-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T01:01:04.319613-08:00","closed_at":"2025-12-30T01:01:04.319613-08:00","close_reason":"Already merged to main"} -{"id":"gt-gp6i","title":"Witness cleanup should know worktree parent repo","description":"Witness had to discover that polecat worktrees are created from mayor/rig, not the rig root.\n\n## Problem\nWhen cleaning up polecat/tracer:\n- Witness ran git worktree remove from gastown/ - failed\n- Had to discover worktree was from mayor/rig\n- Then removed correctly\n\n## Improvement\nWitness should know the worktree parent repo path (mayor/rig) and clean up from there directly.\n\n## Evidence\nTracer bullet 2025-12-23: Witness took extra steps to figure out cleanup path.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-23T21:58:29.302337-08:00","updated_at":"2025-12-30T00:49:23.332252-08:00","closed_at":"2025-12-30T00:49:23.332252-08:00","close_reason":"Fixed: Witness template now uses gt polecat nuke instead of raw git worktree commands. This command knows the correct worktree parent repo and handles cleanup properly."} -{"id":"gt-gpgdv","title":"Optimize: Share stepMap across control flow operators","description":"In ApplyControlFlow, both ApplyBranches and ApplyGates call buildStepMap() separately:\n\n```go\nfunc ApplyBranches(steps []*Step, compose *ComposeRules) ([]*Step, error) {\n stepMap := buildStepMap(steps) // Called here\n ...\n}\n\nfunc ApplyGates(steps []*Step, compose *ComposeRules) ([]*Step, error) {\n stepMap := buildStepMap(steps) // Called again here\n ...\n}\n```\n\nThis is inefficient for large formulas. Options:\n\n1. Pass stepMap as a parameter to ApplyBranches/ApplyGates\n2. Create an internal version that accepts stepMap, keep public API unchanged\n3. Build once in ApplyControlFlow and pass down\n\nLow priority since formula sizes are typically small.","status":"open","priority":4,"issue_type":"chore","created_at":"2025-12-25T15:14:10.961538-08:00","updated_at":"2025-12-25T15:14:10.961538-08:00","dependencies":[{"issue_id":"gt-gpgdv","depends_on_id":"gt-8tmz.4","type":"blocks","created_at":"2025-12-25T15:14:19.033379-08:00","created_by":"daemon"}]} -{"id":"gt-gpifj","title":"gt formula command: Scaffold CLI with subcommands","description":"Create internal/cmd/formula.go with subcommands:\n- gt formula list - show available formulas\n- gt formula show \u003cname\u003e - display formula details\n- gt formula run \u003cname\u003e [--pr=N] - execute formula\n- gt formula create \u003cname\u003e - create new formula template\n\nWire into rootCmd. Use cobra command groups.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T14:42:52.489217-08:00","created_by":"mayor","updated_at":"2026-01-01T14:52:44.249387-08:00","closed_at":"2026-01-01T14:52:44.249387-08:00","close_reason":"Implemented gt formula command with list, show, run, and create subcommands"} -{"id":"gt-gpph6","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:30:04.337651-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.774089-08:00","closed_at":"2026-01-04T16:40:22.774089-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:30:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-gpru4","title":"Digest: mol-deacon-patrol","description":"Patrol 19: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:35:45.138772-08:00","updated_at":"2026-01-01T04:35:45.138772-08:00","closed_at":"2026-01-01T04:35:45.138735-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gqiwm","title":"mol-sync-workspace: Move cleanup-worktrees earlier in step order","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-30T19:11:03.578118-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-01T18:42:04.62773-08:00","closed_at":"2026-01-01T18:42:04.62773-08:00","close_reason":"Moved cleanup-worktrees step earlier in execution order - now runs after handle-dirty-state instead of after run-tests"} -{"id":"gt-gqqp4","title":"Digest: mol-deacon-patrol","description":"Patrol #2: Quick cycle, all witnesses running. No messages.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:16:26.133527-08:00","updated_at":"2025-12-31T19:16:26.133527-08:00","closed_at":"2025-12-31T19:16:26.133401-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gres0","title":"Merge: nux-1767084010093","description":"branch: polecat/nux-1767084010093\ntarget: main\nsource_issue: nux-1767084010093\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:48:40.077236-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.235797-08:00","closed_at":"2025-12-30T01:01:04.235797-08:00","close_reason":"Already merged to main"} -{"id":"gt-grflu","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:10:38.139976-08:00","updated_at":"2026-01-01T05:10:38.139976-08:00","closed_at":"2026-01-01T05:10:38.139941-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gsjfz","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:21:58.343607-08:00","updated_at":"2025-12-28T11:21:58.343607-08:00","closed_at":"2025-12-28T11:21:58.343574-08:00"} -{"id":"gt-gsl05","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:10:43.916922-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:10:43.9695-08:00","closed_at":"2026-01-05T21:10:43.9695-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:10:43-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-gswn","title":"Integration test: agent waits for CI via gate","description":"End-to-end test of the gate workflow.\n\n## Test Scenario\n1. Agent creates gate: bd gate create --await gh:run:123 --timeout 5m --notify beads/dave\n2. Agent writes handoff and exits\n3. Deacon patrol checks gate condition\n4. (Mock) GitHub run completes\n5. Deacon notifies waiter and closes gate\n6. New agent session reads mail and resumes\n\n## Test Requirements\n- Mock GitHub API responses\n- Test timeout path\n- Test multiple waiters\n- Verify mail notifications sent\n\n## Moved from beads\nOriginally bd-rl5t. Tests Deacon patrol which is in gastown.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T12:23:56.582834-08:00","updated_at":"2025-12-23T12:23:56.582834-08:00","dependencies":[{"issue_id":"gt-gswn","depends_on_id":"gt-dh65","type":"blocks","created_at":"2025-12-23T12:24:01.787444-08:00","created_by":"stevey"}]} -{"id":"gt-gt2wl","title":"Digest: mol-deacon-patrol","description":"Patrol 16: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:04:46.889415-08:00","updated_at":"2025-12-25T00:04:46.889415-08:00","closed_at":"2025-12-25T00:04:46.88938-08:00"} -{"id":"gt-gu3bk","title":"Digest: mol-deacon-patrol","description":"Patrol 20: all healthy, new polecats spawning","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:57:43.25526-08:00","updated_at":"2025-12-28T15:57:43.25526-08:00","closed_at":"2025-12-28T15:57:43.255222-08:00"} -{"id":"gt-gufay","title":"Digest: mol-deacon-patrol","description":"Patrol 6: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:03:16.943002-08:00","updated_at":"2025-12-31T19:03:16.943002-08:00","closed_at":"2025-12-31T19:03:16.942964-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-guhzs","title":"Digest: mol-deacon-patrol","description":"Patrol 25: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:56:21.558358-08:00","updated_at":"2025-12-31T13:56:21.558358-08:00","closed_at":"2025-12-31T13:56:21.558322-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-guqkp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 23 complete. All 3 rigs healthy. Quick check.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:27:34.982517-08:00","updated_at":"2026-01-01T19:27:34.982517-08:00","closed_at":"2026-01-01T19:27:34.982479-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-guqza","title":"Digest: mol-deacon-patrol","description":"Patrol 5: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:38:57.363614-08:00","updated_at":"2025-12-25T15:38:57.363614-08:00","closed_at":"2025-12-25T15:38:57.363584-08:00"} -{"id":"gt-guyt5","title":"Add gt mail release command for releasing claimed queue messages","description":"Add release subcommand to internal/cmd/mail.go.\n\nSYNTAX:\ngt mail release \u003cmessage-id\u003e\n\nBEHAVIOR:\n1. Find message by ID\n2. Verify caller is the one who claimed it (claimed_by matches)\n3. Clear claimed_by and claimed_at\n4. Message returns to queue for others to claim\n\nERROR CASES:\n- Message not found\n- Message not claimed\n- Caller did not claim this message\n\nFILE: internal/cmd/mail.go\nADD: releaseCmd as subcommand of mailCmd\n\nTESTS: Add TestMailRelease","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T18:15:39.50641-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T18:16:13.636578-08:00","closed_at":"2026-01-01T18:16:13.636578-08:00","close_reason":"Implemented gt mail release command with tests","dependencies":[{"issue_id":"gt-guyt5","depends_on_id":"gt-t1kso","type":"blocks","created_at":"2025-12-30T18:15:48.294377-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-gvjpn","title":"Digest: mol-deacon-patrol","description":"Patrol 3: 3 polecats working, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:32:21.545886-08:00","updated_at":"2025-12-29T22:32:21.545886-08:00","closed_at":"2025-12-29T22:32:21.54585-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-gx1z3","title":"Session ended: gt-gastown-citadel","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:17:41.417489-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T19:44:41.885398-08:00","closed_at":"2026-01-05T19:44:41.885398-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/citadel","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:17:40-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-citadel\",\"worker\":\"citadel\"}"} -{"id":"gt-gzhrm","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:33:59.991252-08:00","updated_at":"2025-12-31T23:33:59.991252-08:00","closed_at":"2025-12-31T23:33:59.991216-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-gzp2y","title":"Day 1.1b: Add type=role to bead schema","description":"Add role as a valid bead type in the schema.\n\nRole beads define agent behavior:\n- Priming instructions (from current CLAUDE.md content)\n- default_molecule field\n- capabilities list\n\nThis enables Day 1.5 (creating role beads from CLAUDE.md).\n\nMust be done alongside type=agent schema work.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-12-27T23:17:10.456454-08:00","created_by":"mayor","updated_at":"2025-12-27T23:39:09.219483-08:00","closed_at":"2025-12-27T23:39:09.219483-08:00","dependencies":[{"issue_id":"gt-gzp2y","depends_on_id":"gt-ikyo1","type":"blocks","created_at":"2025-12-27T23:17:26.728179-08:00","created_by":"daemon"}]} -{"id":"gt-gzpmj","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy, no changes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:29:43.999497-08:00","updated_at":"2025-12-31T22:29:43.999497-08:00","closed_at":"2025-12-31T22:29:43.999462-08:00"} -{"id":"gt-gzzon","title":"Digest: mol-deacon-patrol","description":"Patrol 38: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:01:48.012457-08:00","updated_at":"2025-12-31T14:01:48.012457-08:00","closed_at":"2025-12-31T14:01:48.012423-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-h0v5","title":"Add keyboard navigation and filtering","description":"Keyboard navigation: j/k or arrows to move, enter to expand/collapse, q to quit. Filtering: by rig name, worker name, event type. Search within activity stream.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T16:27:20.27464-08:00","updated_at":"2025-12-23T16:27:20.27464-08:00","dependencies":[{"issue_id":"gt-h0v5","depends_on_id":"gt-tr0a","type":"blocks","created_at":"2025-12-23T16:27:40.14167-08:00","created_by":"daemon"},{"issue_id":"gt-h0v5","depends_on_id":"gt-55kx","type":"blocks","created_at":"2025-12-23T16:27:40.224089-08:00","created_by":"daemon"},{"issue_id":"gt-h0v5","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:31.027436-08:00","created_by":"daemon"}]} -{"id":"gt-h20h3","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:15:34.419888-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:18.438372-08:00","closed_at":"2026-01-05T19:44:18.438372-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:15:29-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-h262","title":"bd ready --blockers: prioritize issues that block other work","description":"bd ready should prioritize issues that are blocking other work.\n\n**From VC**: Blocker-first prioritization in GetReadyWork(). ~100 lines.\nAlgorithm: baseline-failure first, then discovered:blocker, then by priority.\n\n**Gas Town implementation**: CLI flag or default behavior:\n```bash\nbd ready --blockers-first # Or make this default\n```\n\nChecks dependency graph. Issues with many dependents surface first.\n\n**Value**: Unblocks parallelism faster. Critical path gets cleared.\n\n**VC lesson**: Without blocker priority, work can starve on discovered issues.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:18.426957-08:00","updated_at":"2025-12-20T20:30:18.426957-08:00","dependencies":[{"issue_id":"gt-h262","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.664473-08:00","created_by":"daemon"}]} -{"id":"gt-h2cvm","title":"Digest: mol-deacon-patrol","description":"Patrol 18: all healthy, handled 1 handoff msg","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:12:03.408989-08:00","updated_at":"2025-12-27T23:12:03.408989-08:00","closed_at":"2025-12-27T23:12:03.408951-08:00"} -{"id":"gt-h2nji","title":"Digest: mol-deacon-patrol","description":"Patrol 13 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:45:48.94451-08:00","updated_at":"2025-12-31T16:45:48.94451-08:00","closed_at":"2025-12-31T16:45:48.944473-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-h3cdm","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:41:54.379653-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T21:41:54.428326-08:00","closed_at":"2026-01-05T21:41:54.428326-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:41:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-h3gzj","title":"BUG: Polecats not auto-nuked after MR merge","description":"## Problem\n\nPolecats complete their work and submit MRs, but after the Refinery merges them, the polecats are not automatically nuked. They linger in 'done' state requiring manual cleanup.\n\n## Observed Behavior\n\n1. Polecat completes work, runs `gt done`, submits MR\n2. Refinery merges the MR, deletes the branch\n3. Polecat transitions to 'done' state\n4. Polecat sends POLECAT_DONE message to Witness\n5. **Polecat stays around** - worktree, session (sometimes), agent bead all persist\n6. Manual `gt polecat nuke` required to clean up\n\n## Evidence\n\n- 47 polecats found in 'done' state after convoy completion\n- Witness had 29 unread POLECAT_DONE messages it wasn't processing\n- All nuked polecats had closed issues still on their hooks (hook not cleared)\n\n## Related Issues\n\n1. Hook not cleared when issue closed\n2. Witness unstable (kept dying mid-patrol)\n3. `gt polecat nuke` safety check blocks on 'has work on hook' even when that work is closed\n\n## Expected Behavior\n\nAfter MR merge:\n1. Refinery should signal completion\n2. Witness should receive POLECAT_DONE and auto-nuke the polecat\n3. Or: Refinery should nuke directly after successful merge\n\n## Workaround\n\nManual: `gt polecat nuke \u003crig\u003e/\u003cpolecat\u003e --force`","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-05T00:41:06.639968-08:00","created_by":"mayor","updated_at":"2026-01-06T13:22:04.820222-08:00","closed_at":"2026-01-06T13:22:04.820222-08:00","close_reason":"Added gt witness process command to invoke handlers"} -{"id":"gt-h3hak","title":"Day 2.7a: gt install creates Deacon and Mayor agent beads","description":"Update gt install to create agent beads:\n\n1. After initializing town beads, create:\n - gt-deacon agent bead (role_type: deacon, rig: null, agent_state: idle)\n - gt-mayor agent bead (role_type: mayor, rig: null, agent_state: idle)\n\n2. Use bd create --type=agent or internal beads API\n\nFiles:\n- internal/cmd/install.go","notes":"Moved to gt rig add instead of gt install due to routing constraints. Agent beads need to be in rig beads (not town beads) for daemon to find them via prefix routing. First rig added gets gt-deacon and gt-mayor.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T02:17:05.962052-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T02:31:10.60009-08:00","closed_at":"2025-12-28T02:31:10.60009-08:00","dependencies":[{"issue_id":"gt-h3hak","depends_on_id":"gt-aer7q","type":"parent-child","created_at":"2025-12-28T02:17:17.522839-08:00","created_by":"daemon"}]} -{"id":"gt-h3skz","title":"Remove os.Exit calls from Cobra RunE handlers","description":"attached_args: Remove os.Exit calls from Cobra RunE handlers\n\nReplace os.Exit() calls with proper error returns in Cobra commands.\n\n## Files to modify\n- internal/cmd/mail.go (lines 546, 554, 561, 808-812)\n- Any other files with os.Exit in RunE\n\n## Problem\nSome RunE handlers call os.Exit() directly:\n```go\nRunE: func(cmd *cobra.Command, args []string) error {\n ...\n os.Exit(1) // BAD: bypasses Cobra error handling\n}\n```\n\n## Fix\nReturn errors instead:\n```go\nRunE: func(cmd *cobra.Command, args []string) error {\n ...\n return fmt.Errorf(\"not in workspace\")\n}\n```\n\n## Acceptance criteria\n- [ ] No os.Exit calls inside RunE functions\n- [ ] Errors returned with proper context\n- [ ] grep -n 'os.Exit' internal/cmd/*.go shows no RunE matches\n- [ ] go build ./... passes\n- [ ] Commands still exit with correct codes","status":"hooked","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:20.418359-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:32:36.110268-08:00"} -{"id":"gt-h4342","title":"Digest: mol-deacon-patrol","description":"Patrol 20: final check, all healthy, handoff threshold","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:37:37.217558-08:00","updated_at":"2025-12-28T01:37:37.217558-08:00","closed_at":"2025-12-28T01:37:37.217523-08:00"} -{"id":"gt-h46pk","title":"Set hook_bead at polecat spawn time, not after","description":"Currently polecat agent beads are created with empty hook_bead, then updated separately via updateAgentHookBead(). This causes cross-beads routing issues when town beads (hq-*) work is slung to rig polecats (gt-* agent beads).\n\nCurrent flow:\n1. sling.go calls SpawnPolecatForSling()\n2. polecat/manager.go:Spawn() calls CreateAgentBead(HookBead: empty)\n3. sling.go calls updateAgentHookBead() - separate call, different beads context\n\nProposed fix: Pass hookBead through the spawn chain so it is set atomically at creation time in manager.go:Spawn().\n\nFiles to change:\n- polecat/manager.go:Spawn() - add hookBead parameter\n- cmd/polecat_spawn.go:SpawnPolecatForSling() - pass hookBead through \n- cmd/sling.go - pass beadID to spawn, remove separate updateAgentHookBead call\n\nBenefits: Eliminates cross-beads routing problem, no race condition, removes agent bead might not exist error path.\n\nRelated: gt-ohqxq (partial fix using town root for routing)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-31T12:24:39.607959-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-01T18:49:15.464507-08:00","closed_at":"2026-01-01T18:49:15.464507-08:00","close_reason":"Set hook_bead atomically at spawn time via AddOptions/HookBead"} -{"id":"gt-h4sy3","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:16:21.81854-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.423237-08:00","closed_at":"2026-01-05T19:44:18.423237-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:16:21-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-h5e0","title":"Patrol hygiene: Witness/Refinery/Deacon inbox cleanup","description":"## Summary\nPatrol roles should clean up their inboxes as part of normal operation, not let messages accumulate.\n\n## Witness Patrol Cleanup\n- POLECAT_STARTED: archive after acknowledging\n- POLECAT_DONE: archive after cleanup complete\n- LIFECYCLE requests: archive after processing\n- Keep only: active work, unprocessed requests\n\n## Refinery Patrol Cleanup \n- MR Ready: archive after merge/reject decision\n- Swarm notices: archive after dispatch\n- Keep only: pending MRs in queue\n\n## Deacon Patrol Cleanup\n- Rotate daemon.log when \u003e10MB\n- Prune state.json of dead sessions\n- Archive old daemon logs (gzip, date-suffix)\n\n## Implementation\nEach patrol molecule should have a 'cleanup' phase at end of cycle.\n\n## Related\n- mol-town-shutdown (nuclear cleanup)\n- mol-witness-patrol, mol-refinery-patrol, mol-deacon-patrol","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/organic","created_at":"2025-12-24T17:25:47.860346-08:00","updated_at":"2025-12-30T09:57:47.977451-08:00","closed_at":"2025-12-30T09:57:47.977451-08:00","close_reason":"Implemented patrol hygiene for Witness/Refinery/Deacon. Each patrol formula now has inbox cleanup and end-of-cycle hygiene steps."} -{"id":"gt-h5n.10","title":"Auto-rebase on conflict: optional automatic rebase","description":"Implement automatic rebase as conflict resolution option.\n\nWhen on_conflict=auto_rebase and conflicts detected:\n1. Attempt: git rebase \u003ctarget\u003e \u003csource-branch\u003e\n2. If clean rebase: update source branch, continue merge\n3. If conflicts in rebase: abort, fall back to assign_back\n4. Force push rebased branch (worker's branch)\n\nRequires:\n- Worker branch must be force-pushable\n- Config: on_conflict: auto_rebase\n\nRisks:\n- Force push can confuse workers\n- Complex conflicts still need manual resolution\n\nReference: docs/merge-queue-design.md#conflict-resolution-strategies","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:26.397214-08:00","updated_at":"2025-12-28T22:36:25.993123-08:00","closed_at":"2025-12-28T22:36:25.993123-08:00","dependencies":[{"issue_id":"gt-h5n.10","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:26.399236-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.10","depends_on_id":"gt-3x1.4","type":"blocks","created_at":"2025-12-17T13:53:23.158089-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.11","title":"Retry logic: exponential backoff for transient failures","description":"Implement retry logic for transient failures.\n\nRetryable failures:\n- Push failed (network, auth transient)\n- Test flaky (config: retry_flaky_tests)\n- Fetch failed (network)\n\nRetry strategy:\n- Max retries: 3 (configurable)\n- Backoff: 1s, 2s, 4s (exponential)\n- On final failure: treat as permanent, assign back\n\nNon-retryable failures:\n- Merge conflict\n- Test consistently fails\n- Build error\n\nTrack retry count in MR metadata for debugging.\n\nReference: docs/merge-queue-design.md#failure-recovery","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:28.300658-08:00","updated_at":"2025-12-28T22:36:25.977306-08:00","closed_at":"2025-12-28T22:36:25.977306-08:00","dependencies":[{"issue_id":"gt-h5n.11","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:28.302268-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.11","depends_on_id":"gt-3x1.4","type":"blocks","created_at":"2025-12-17T13:53:23.277535-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.12","title":"MQ metrics: pending count, processing time, success rate","description":"Implement merge queue metrics collection.\n\nMetrics to track:\n- mq_pending_count: MRs waiting\n- mq_processing_time: Time from submit to merge (histogram)\n- mq_success_rate: Merges vs rejections\n- mq_conflict_rate: How often conflicts occur\n- mq_test_failure_rate: Test failures\n\nStorage options:\n- Simple: JSON file with rolling stats\n- Advanced: Prometheus-compatible metrics endpoint\n\nDisplay via:\n- gt mq stats: summary statistics\n- Dashboard widget (separate task)\n\nReference: docs/merge-queue-design.md#observability","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:30.716666-08:00","updated_at":"2025-12-28T22:36:25.961268-08:00","closed_at":"2025-12-28T22:36:25.961268-08:00","dependencies":[{"issue_id":"gt-h5n.12","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:30.718745-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.12","depends_on_id":"gt-3x1.5","type":"blocks","created_at":"2025-12-17T13:53:23.392465-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.13","title":"MQ dashboard widget: queue status in TUI","description":"Add merge queue status widget to the Bubbletea TUI dashboard.\n\nDisplay:\n┌─────────────────────────────────────────────────┐\n│ MERGE QUEUE STATUS │\n├─────────────────────────────────────────────────┤\n│ Pending: 3 In Progress: 1 Merged (24h): 12 │\n├─────────────────────────────────────────────────┤\n│ QUEUE: │\n│ ► gt-mr-004 P0 Nux/gt-xyz Processing... │\n│ gt-mr-005 P1 Toast/gt-abc Ready │\n│ gt-mr-006 P1 Capable/gt-def Blocked (005) │\n└─────────────────────────────────────────────────┘\n\nInteractive features:\n- Navigate queue entries\n- View MR details\n- Retry/reject from dashboard\n\nDepends on: gt-u1j.2 (Bubbletea TUI dashboard)\n\nReference: docs/merge-queue-design.md#dashboard","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-17T13:52:34.770778-08:00","updated_at":"2025-12-28T22:36:26.025189-08:00","closed_at":"2025-12-28T22:36:26.025189-08:00","dependencies":[{"issue_id":"gt-h5n.13","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:34.772838-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.13","depends_on_id":"gt-u1j.2","type":"blocks","created_at":"2025-12-17T13:53:23.509566-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.13","depends_on_id":"gt-h5n.12","type":"blocks","created_at":"2025-12-17T13:53:23.628668-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.13","depends_on_id":"gt-lak31","type":"blocks","created_at":"2025-12-28T21:41:21.223359-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.14","title":"Direct landing integration: gt land uses MR or bypasses","description":"Integrate direct landing with merge queue.\n\n'gt land --direct' should:\n1. Check if MR exists for the polecat's work\n2. If MR exists: process it directly (skip queue)\n3. If no MR: create temporary MR, process, close\n\nOptions:\n- --direct: bypass queue (existing)\n- --via-queue: ensure goes through queue (new)\n- --force: skip safety checks (existing)\n\nThis ensures direct landing still creates proper records.\n\nReference: docs/merge-queue-design.md#direct-landing-bypass-queue","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:48.952108-08:00","updated_at":"2025-12-28T22:36:25.944679-08:00","closed_at":"2025-12-28T22:36:25.944679-08:00","dependencies":[{"issue_id":"gt-h5n.14","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:48.954874-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.14","depends_on_id":"gt-3x1.5","type":"blocks","created_at":"2025-12-17T13:53:23.744413-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.15","title":"Rollback support: gt mq revert for problematic merges","description":"Implement 'gt mq revert \u003cmr-id\u003e' for rolling back merges.\n\nActions:\n1. Find merge commit from closed MR\n2. Create revert commit: git revert \u003cmerge-commit\u003e\n3. Push revert to target branch\n4. Create 'reverted' MR tracking the revert\n5. Optionally reopen source issue\n\nOptions:\n- --reason REASON: required explanation\n- --reopen-issue: reopen the source work item\n\nTrack revert in MR metadata for audit trail.\n\nReference: docs/merge-queue-design.md#open-questions","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:51.440782-08:00","updated_at":"2025-12-28T22:36:25.92853-08:00","closed_at":"2025-12-28T22:36:25.92853-08:00","dependencies":[{"issue_id":"gt-h5n.15","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:51.442642-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.15","depends_on_id":"gt-3x1.5","type":"blocks","created_at":"2025-12-17T13:53:23.862389-08:00","created_by":"daemon"}]} -{"id":"gt-h5n.9","title":"Per-epic config overrides: custom merge settings","description":"Allow per-epic merge configuration overrides.\n\nEpic can specify merge_config in its description:\n merge_config:\n run_tests: true\n test_command: 'go test -race ./...'\n on_conflict: assign_back\n\nWhen processing MRs for an epic:\n1. Load rig-level merge_queue config\n2. Check if epic has merge_config\n3. Merge epic config over rig config\n4. Use merged config for processing\n\nUse cases:\n- Risky refactors: more thorough testing\n- Urgent fixes: skip some checks\n- Experimental work: different test suite\n\nReference: docs/merge-queue-design.md#per-epic-overrides","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:02.32832-08:00","updated_at":"2025-12-28T22:36:26.009236-08:00","closed_at":"2025-12-28T22:36:26.009236-08:00","dependencies":[{"issue_id":"gt-h5n.9","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:02.32997-08:00","created_by":"daemon"}]} -{"id":"gt-h5sza","title":"Day 1.3: Implement bd slot set/clear commands","description":"Add slot management commands:\n- bd slot set \u003cagent\u003e \u003cslot\u003e \u003cbead\u003e - set slot (error if occupied)\n- bd slot clear \u003cagent\u003e \u003cslot\u003e - clear slot\n- bd slot show \u003cagent\u003e - show all slots\n\nThese enforce cardinality constraints.\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:04.497595-08:00","created_by":"mayor","updated_at":"2025-12-28T00:13:27.799577-08:00","closed_at":"2025-12-28T00:13:27.799577-08:00","dependencies":[{"issue_id":"gt-h5sza","depends_on_id":"gt-v2gkv","type":"blocks","created_at":"2025-12-27T20:58:48.158544-08:00","created_by":"daemon"},{"issue_id":"gt-h5sza","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.643158-08:00","created_by":"daemon"}]} -{"id":"gt-h60pn","title":"Merge: slit-1767073379145","description":"attached_args: Code review this merge request\n\nbranch: polecat/slit-1767073379145\ntarget: main\nsource_issue: slit-1767073379145\nrig: gastown","notes":"CODE REVIEW (valkyrie): REQUEST CHANGES\n\nCritical bugs found in internal/swarm/manager.go:\n1. JSON field changed from 'dependents' to 'dependencies' but bd outputs 'dependents'\n2. 'hooked' status removed from in_progress handling\n3. Assignee field removed from task loading\n\nThese changes will break swarm coordination. Polecat_spawn.go fix is correct.\n\nRecommendation: Revert swarm/manager.go changes, keep polecat_spawn.go fix.","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-29T21:58:26.038048-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-29T22:03:33.621893-08:00","closed_at":"2025-12-29T22:03:33.621893-08:00","close_reason":"REJECTED: Critical bugs in swarm/manager.go must be fixed. See notes for details. The polecat_spawn.go fix is correct but swarm changes break JSON parsing (dependents vs dependencies mismatch) and remove hooked status handling."} -{"id":"gt-h6epy","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:06:54.714568-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.723133-08:00","closed_at":"2026-01-05T00:08:31.723133-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:06:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-h6rmm","title":"gt handoff broken: unknown session type hq-mayor","description":"dispatched_by: mayor\n\nRegression from gt-vcvyd fix. Problem: furiosa's fix changed status.go to show 'hq-mayor' but didn't update session.MayorSessionName() in internal/session/names.go. Result: Two sessions exist (gt-mayor old, hq-mayor new). User is attached to hq-mayor but handoff calls getMayorSessionName() which returns 'gt-mayor', so sessionWorkDir() doesn't match. Fix: Update session.MayorSessionName() and session.DeaconSessionName() to return 'hq-mayor'/'hq-deacon', or add case in sessionWorkDir() for hq- prefixed names.","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-05T19:15:02.069435-08:00","created_by":"mayor","updated_at":"2026-01-05T19:23:00.231569-08:00","closed_at":"2026-01-05T19:23:00.231572-08:00","close_reason":"Already fixed in commit 6b8c897e (feat: use hq- prefix for Mayor and Deacon session names). MayorSessionName() and DeaconSessionName() already return 'hq-mayor' and 'hq-deacon'. Tests pass. Bug was valid when filed (v0.2.0 binary) but fix is now in codebase (v0.2.1)."} -{"id":"gt-h7e4w","title":"gt session start --issue doesn't inject work to prompt","description":"When starting a polecat session with --issue flag:\n gt session start beads/Toast --issue bd-oxgi\n\nThe session starts but the polecat doesn't receive the issue context. They sit at the prompt awaiting input. Had to manually nudge them.\n\nExpected: Session start should either nudge or inject the issue context so polecat starts working immediately (propulsion principle).","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-28T19:30:16.443358-08:00","created_by":"mayor","updated_at":"2025-12-28T22:37:43.649521-08:00","closed_at":"2025-12-28T22:37:43.649521-08:00"} -{"id":"gt-h864g","title":"Digest: mol-deacon-patrol","description":"Patrol 3: quick pass, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:03:17.542341-08:00","updated_at":"2025-12-31T18:03:17.542341-08:00","closed_at":"2025-12-31T18:03:17.542301-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-h9csv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:12:29.06856-08:00","updated_at":"2026-01-01T06:12:29.06856-08:00","closed_at":"2026-01-01T06:12:29.068519-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-h9wp4","title":"Merge: nux-mjw18ii8","description":"branch: polecat/nux-mjw18ii8\ntarget: main\nsource_issue: nux-mjw18ii8\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T14:53:06.584336-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T15:39:54.320354-08:00","closed_at":"2026-01-01T15:39:54.320354-08:00","close_reason":"Merged to main at 265dbcb1"} -{"id":"gt-haxnx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:28:48.877839-08:00","updated_at":"2026-01-01T10:28:48.877839-08:00","closed_at":"2026-01-01T10:28:48.8778-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hb1kx","title":"Digest: mol-deacon-patrol","description":"Patrol 13: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:29:17.101199-08:00","updated_at":"2025-12-31T20:29:17.101199-08:00","closed_at":"2025-12-31T20:29:17.101166-08:00","dependencies":[{"issue_id":"gt-hb1kx","depends_on_id":"gt-eph-wyyv","type":"parent-child","created_at":"2025-12-31T20:29:17.102411-08:00","created_by":"deacon"}]} -{"id":"gt-hbege","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:10:53.31272-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T21:10:53.361814-08:00","closed_at":"2026-01-05T21:10:53.361814-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:10:53-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-hce03","title":"Digest: mol-deacon-patrol","description":"Patrol 17: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:29:14.852561-08:00","updated_at":"2025-12-25T07:29:14.852561-08:00","closed_at":"2025-12-25T07:29:14.852517-08:00"} -{"id":"gt-hcs6t","title":"Merge: dex-mjufugxv","description":"branch: polecat/dex-mjufugxv\ntarget: main\nsource_issue: dex-mjufugxv\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T12:07:32.280893-08:00","created_by":"gastown/polecats/dex","updated_at":"2025-12-31T12:10:41.538931-08:00","closed_at":"2025-12-31T12:10:41.538931-08:00","close_reason":"Merged to main at 2e461cb1"} -{"id":"gt-hcsz","title":"Track merge requests as beads (type=merge-request)","description":"Currently MRs are tracked in .gastown/refinery.json. For HOP audit trail and entity CV tracking, merge requests should be Beads entries with type=merge-request. This enables:\n- Full audit trail of what was merged, when, by whom\n- Entity chain contributions (who validated what)\n- Cross-rig visibility of merge activity\n\nThe refinery would create an MR bead when work enters the queue, update status as it progresses (open → in_progress → merged/rejected).\n\nPart of Beads-as-data-plane vision from HOP.","status":"open","priority":4,"issue_type":"feature","created_at":"2025-12-21T22:07:28.836388-08:00","updated_at":"2025-12-21T22:07:28.836388-08:00"} -{"id":"gt-hd937","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:07:14.557832-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.884266-08:00","closed_at":"2026-01-05T00:08:31.884266-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:07:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-hdntr","title":"Digest: mol-deacon-patrol","description":"Patrol 117: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:15:16.214899-08:00","updated_at":"2026-01-01T14:15:16.214899-08:00","closed_at":"2026-01-01T14:15:16.21063-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hdzct","title":"gt mail send to self: Auto-detect from cwd for handoff mail","description":"When sending mail to yourself (common for handoffs), gt mail send from an agent directory should auto-detect both sender and recipient. Example: gt mail send -s 'HANDOFF' -m '...' from mayor/rig should send to mayor/.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-28T22:27:42.426037-08:00","created_by":"stevey","updated_at":"2025-12-28T22:27:42.426037-08:00"} -{"id":"gt-hebii","title":"Merge: gt-si8rq.4","description":"branch: polecat/rictus-mjxaq6fm\ntarget: main\nsource_issue: gt-si8rq.4\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:10:45.682226-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T12:29:34.374533-08:00","closed_at":"2026-01-02T12:29:34.374533-08:00","close_reason":"Merged to main at e2b872af"} -{"id":"gt-heys9","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, no mail, no orphans, no gates","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:37:42.300315-08:00","updated_at":"2025-12-31T18:37:42.300315-08:00","closed_at":"2025-12-31T18:37:42.300282-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hg734","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:53:08.546066-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.503144-08:00","closed_at":"2026-01-05T00:08:31.503144-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:53:08-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-hhmkq","title":"gt rig config commands","description":"Implement config viewing and manipulation commands.\n\nCommands:\n- gt rig config show \u003crig\u003e # Effective config\n- gt rig config show \u003crig\u003e --layers # Show source of each value\n- gt rig config set \u003crig\u003e \u003ckey\u003e \u003cvalue\u003e # Wisp layer\n- gt rig config set \u003crig\u003e \u003ckey\u003e \u003cvalue\u003e --global # Bead layer\n- gt rig config set \u003crig\u003e \u003ckey\u003e --block # Block inheritance\n- gt rig config unset \u003crig\u003e \u003ckey\u003e # Remove from wisp\n\nExample output:\n gt rig config show gastown --layers\n Key Value Source\n status parked wisp\n priority_adjustment 10 bead\n auto_restart true system\n max_polecats 4 town","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:51.296315-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:51.296315-08:00","dependencies":[{"issue_id":"gt-hhmkq","depends_on_id":"gt-emh1c","type":"blocks","created_at":"2026-01-06T17:37:07.369723-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-hibbj","title":"Refinery: Non-blocking delegation via bead-gates","description":"## Problem: Refinery Blocks on Delegation\n\nCurrent flow when rebase fails:\n1. Refinery creates conflict-resolution task\n2. Refinery BLOCKS waiting for resolution\n3. Queue backs up behind stuck MR\n\n## Solution: Gate-Based Non-Blocking Delegation\n\nWhen rebase fails:\n1. Create conflict-resolution task (existing: gt-si8rq.3)\n2. Create bead-gate waiting for that task to close\n3. Add gate as blocker to MR bead\n4. **Continue to next MR** (do not block)\n5. When gate closes → MR unblocks → re-enters ready queue\n\n```\nMR Queue: [MR-A] [MR-B] [MR-C]\n │\n ▼\n Rebase fails\n │\n ┌─────────┴─────────┐\n ▼ ▼\nCreate conflict Create gate\ntask (polecat) (blocks MR-A)\n │ │\n │ ▼\n │ Continue to MR-B\n │ (non-blocking!)\n ▼\nPolecat resolves\n │\n ▼\nTask closes → Gate closes → MR-A unblocks\n```\n\n## Implementation\n\n### In Refinery handleConflict():\n```go\n// Create conflict task (existing)\nconflictTask := createConflictTask(mr, conflict)\n\n// NEW: Create gate\ngate := bd.GateCreate{\n Type: \"bead\",\n AwaitID: conflictTask.ID,\n Timeout: \"2h\",\n}\ngateID := bd.CreateGate(gate)\n\n// NEW: Block MR on gate\nbd.DepAdd(mr.ID, gateID)\n\n// NEW: Continue to next MR (dont block)\nreturn nil // not an error, just deferred\n```\n\n### Gate Resolution\nWhen conflict task closes:\n1. Gate auto-closes (bead-gate behavior)\n2. MR bead unblocks (dep satisfied)\n3. MR appears in `bd ready --type=merge-request`\n4. Refinery picks it up in next patrol\n\n## Benefits\n- Queue keeps moving (no single-MR blockage)\n- Multiple conflicts can be in-flight\n- Priority ordering still respected\n- Uses existing gates infrastructure\n\n## Related\n- gt-4u49x: Merge-slot gate (serializes actual merges)\n- gt-si8rq.3: Conflict task creation (existing)\n- bd-4k3c: Gate bead creation (existing)","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/polecats/nux","created_at":"2026-01-02T17:37:00.55746-08:00","created_by":"mayor","updated_at":"2026-01-02T17:59:10.410791-08:00","closed_at":"2026-01-02T17:59:10.410791-08:00","close_reason":"Implemented non-blocking delegation via BlockedBy field in mrqueue. When conflicts occur, MR is blocked on conflict task. Queue continues to next MR. MR unblocks when task closes.","dependencies":[{"issue_id":"gt-hibbj","depends_on_id":"gt-si8rq.3","type":"blocks","created_at":"2026-01-02T17:37:20.008369-08:00","created_by":"mayor"},{"issue_id":"gt-hibbj","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-02T17:37:39.735162-08:00","created_by":"mayor"}]} -{"id":"gt-hj0ei","title":"Polecat writes files outside worktree (integration test)","description":"During integration test gt-7psb8, polecat furiosa was asked to create ~/gt/gastown/test-polecat-integration.txt\n\nIt used Write tool with relative path '../../test-polecat-integration.txt' which resolved to gastown root instead of its worktree at ~/gt/gastown/polecats/furiosa/\n\nObserved:\n- File created at ~/gt/gastown/test-polecat-integration.txt (WRONG)\n- Furiosa worktree at ~/gt/gastown/polecats/furiosa/ has no such file\n- Furiosa branch has no commits of any new files\n\nRoot cause: Claude Code resolves relative paths from cwd, and the polecat may have been in the wrong directory or used incorrect path.\n\nThis caused the entire merge to be empty (branch at same commit as main).","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T13:13:38.423978-08:00","created_by":"mayor","updated_at":"2025-12-28T14:00:14.068658-08:00","closed_at":"2025-12-28T14:00:14.068658-08:00"} -{"id":"gt-hj9e","title":"Remove pinned field workaround after beads fix","description":"## Summary\n\nOnce bd-phtv is fixed in beads, we can remove the workaround documentation and potentially simplify the pinToHook() implementation.\n\n## Current Workaround\n\nThe handoff bead attachment mechanism (AttachMolecule) is used as the primary work assignment mechanism instead of the pinned field. This works correctly but adds complexity.\n\n## Changes After Beads Fix\n\n1. Remove the NOTE comment in internal/beads/beads.go:Pin() explaining the bug\n2. Consider simplifying pinToHook() if the pinned field becomes reliable\n3. Update gt-o3is to reference the fix\n\n## Blocked By\n\nThis issue is blocked by external:beads:pinned-field-fix (bd-phtv).\nWhen that capability is shipped, this issue becomes ready.\n\n## Related\n\n- gt-o3is: Original investigation that found this bug\n- bd-phtv: The beads fix (in ~/gt/beads)","notes":"BLOCKED: Can't add external:beads:pinned-field-fix dependency due to bd-ucgz (migration invariants bug). Once that's fixed, add: bd dep add gt-hj9e external:beads:pinned-field-fix","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T12:35:32.316302-08:00","updated_at":"2025-12-23T12:37:18.526987-08:00"} -{"id":"gt-hjdg4","title":"Session ended: gt-gastown-corpus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:39:53.816163-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-04T16:40:13.333694-08:00","closed_at":"2026-01-04T16:40:13.333694-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/corpus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:39:53-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-corpus\",\"worker\":\"corpus\"}"} -{"id":"gt-hk2kn","title":"Merge: nux-mjw3mn8o","description":"branch: polecat/nux-mjw3mn8o\ntarget: main\nsource_issue: nux-mjw3mn8o\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:04:17.283002-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T19:05:27.722997-08:00","closed_at":"2026-01-01T19:05:27.722997-08:00","close_reason":"Merged to main at 57cd8b88"} -{"id":"gt-hkfhy","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:33:40.709148-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T19:44:18.573968-08:00","closed_at":"2026-01-05T19:44:18.573968-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:33:40-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-hkm50","title":"Digest: mol-deacon-patrol","description":"Patrol 62: All agents healthy, routine scan","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:58:50.461897-08:00","updated_at":"2025-12-31T14:58:50.461897-08:00","closed_at":"2025-12-31T14:58:50.461862-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hl52x","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:53:56.536087-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.48843-08:00","closed_at":"2026-01-05T00:08:31.48843-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:53:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-hlaaf","title":"Day 1.7: Define per-rig agent bead ID pattern","description":"Document and implement the agent bead ID pattern for per-rig agents.\n\nPattern: gt-\u003crole\u003e-\u003crig\u003e\nExamples:\n- gt-witness-gastown\n- gt-refinery-gastown\n- gt-refinery-beads\n- gt-polecat-gastown-nux\n\nTown-level agents (no rig):\n- gt-mayor\n- gt-deacon\n\nThis pattern enables:\n- Consistent lookup: bd show gt-witness-gastown\n- Routing: routes.jsonl maps prefixes\n- Filtering: bd list --type=agent --rig=gastown\n\nUpdate:\n- agent-as-bead.md with examples\n- bd create --type=agent to validate pattern","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T22:01:43.64279-08:00","created_by":"mayor","updated_at":"2025-12-28T00:09:45.958118-08:00","closed_at":"2025-12-28T00:09:45.958118-08:00","dependencies":[{"issue_id":"gt-hlaaf","depends_on_id":"gt-ikyo1","type":"blocks","created_at":"2025-12-27T22:02:45.168539-08:00","created_by":"daemon"},{"issue_id":"gt-hlaaf","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T23:32:42.479886-08:00","created_by":"daemon"}]} -{"id":"gt-hldpv","title":"gt sling: '.' target should resolve to current agent identity, not literal dot","description":"## Problem\n\nWhen slinging from a crew directory with \".\" as target, the assignee becomes\nliteral \".\" instead of resolving to the current agent.\n\n```bash\ncd ~/gt/beads/crew/dave\ngt sling bd-tksk .\n# Result: assignee=\".\" instead of \"beads/crew/dave\"\n```\n\n## Expected\n\n\".\" should resolve to the current agent identity based on cwd, like git does\nwith \".\" meaning current directory.\n\n## Impact\n\nWork is not properly assigned, agent cannot find hooked work.\n\n## Fix\n\nIn sling.go, resolve \".\" target to current agent identity before updating.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/furiosa","created_at":"2025-12-31T12:57:44.908098-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T13:05:17.250833-08:00","closed_at":"2025-12-31T13:05:17.250833-08:00","close_reason":"Fixed: dot target now resolves to current agent identity via resolveSelfTarget()"} -{"id":"gt-hligf","title":"Digest: mol-deacon-patrol","description":"Patrol 8: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:27:10.637385-08:00","updated_at":"2026-01-01T04:27:10.637385-08:00","closed_at":"2026-01-01T04:27:10.637344-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ho7y4","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:23:06.162395-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:23:06.214769-08:00","closed_at":"2026-01-06T13:23:06.214769-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:23:06-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-hould","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All 6 agents healthy, 4 polecats active, refinery queues processing","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:29:57.119267-08:00","updated_at":"2026-01-01T11:29:57.119267-08:00","closed_at":"2026-01-01T11:29:57.119228-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-hould","depends_on_id":"gt-eph-ce17","type":"parent-child","created_at":"2026-01-01T11:29:57.120602-08:00","created_by":"deacon"}]} -{"id":"gt-hpcyd","title":"Digest: mol-deacon-patrol","description":"Patrol 136: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:37:47.123438-08:00","updated_at":"2026-01-01T14:37:47.123438-08:00","closed_at":"2026-01-01T14:37:47.123399-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hpcyt","title":"Add merge queue observability","description":"## Problem\n\nThe per-rig merge queue (refinery) lacks visibility into its operational state.\nOperators can't easily tell:\n- When the queue is backing up (items waiting)\n- When it's empty/idle\n- Queue depth over time\n- Processing rate\n\n## Requirements\n\n- Surface queue depth (pending items count)\n- Show current processing state (idle, processing, blocked)\n- Indicate when queue is backing up (growing faster than draining)\n- Make this accessible via `gt status` or similar command\n\n## Possible Approaches\n\n1. Add queue stats to `gt status` output\n2. Create dedicated `gt mq status` command\n3. Emit metrics/events that can be consumed\n4. Add to witness monitoring scope","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/toast","created_at":"2025-12-30T18:10:06.45809-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T22:30:24.72348-08:00","closed_at":"2025-12-30T22:30:24.72348-08:00","close_reason":"Added State (idle/processing/blocked) and Health (healthy/stale) fields to MQSummary in gt status output. Shows state indicator (● processing, ○ idle) and [stale] warning when queue depth exceeds threshold."} -{"id":"gt-hpenv","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:53:47.904964-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.495766-08:00","closed_at":"2026-01-05T00:08:31.495766-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:53:47-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-hpmb1","title":"Digest: mol-deacon-patrol","description":"Patrol 16: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:35:44.801254-08:00","updated_at":"2025-12-29T22:35:44.801254-08:00","closed_at":"2025-12-29T22:35:44.801217-08:00"} -{"id":"gt-hpotx","title":"DRY: Duplicate address normalization logic in mail/types.go","description":"The addressToIdentity and identityToAddress functions (types.go:329-390) have duplicated logic for:\n- Handling overseer special case\n- Handling mayor/ and deacon/ trailing slashes\n- Normalizing crew/ and polecats/ paths\n\nThe same transformations are applied with only slight variations. Consider extracting common normalization logic.\n\nFiles:\n- internal/mail/types.go:329-390\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:46:38.668389-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:46:38.668389-08:00"} -{"id":"gt-hq9lx","title":"Digest: mol-deacon-patrol","description":"Patrol 13: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:35:09.497504-08:00","updated_at":"2025-12-29T22:35:09.497504-08:00","closed_at":"2025-12-29T22:35:09.497473-08:00"} -{"id":"gt-hqjkd","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: all healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:48:41.271454-08:00","updated_at":"2025-12-31T22:48:41.271454-08:00","closed_at":"2025-12-31T22:48:41.27142-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hqymv","title":"Digest: mol-deacon-patrol","description":"Patrol 9: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T11:05:04.952768-08:00","updated_at":"2025-12-25T11:05:04.952768-08:00","closed_at":"2025-12-25T11:05:04.952741-08:00"} -{"id":"gt-hrhts","title":"Merge: cheedo-1767146245543","description":"branch: polecat/cheedo-1767146245543\ntarget: main\nsource_issue: cheedo-1767146245543\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:00:27.282044-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2025-12-30T18:23:22.122058-08:00","closed_at":"2025-12-30T18:23:22.122058-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-hssbe","title":"Merge: nux-mjvtlh4f","description":"branch: polecat/nux-mjvtlh4f\ntarget: main\nsource_issue: nux-mjvtlh4f\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T11:13:53.327218-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T11:16:32.146938-08:00","closed_at":"2026-01-01T11:16:32.146938-08:00","close_reason":"Merged to main at 0846bfd2"} -{"id":"gt-ht6v5","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All 6 agents healthy, 4 polecats active, no orphans, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:54:24.272093-08:00","updated_at":"2026-01-01T11:54:24.272093-08:00","closed_at":"2026-01-01T11:54:24.272054-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-htlmp","title":"CI integration tests for install/setup flow","description":"Add automated tests that validate the complete setup flow catches regressions like #19 (wrong prefix).\n\n## Scope\n- Fresh gt install validation\n- Rig setup validation \n- Beads initialization and routing\n- Basic polecat lifecycle\n\n## Non-goals (for now)\n- Full Claude Code integration tests (mock or skip)\n- Performance testing\n- Multi-rig scenarios\n\n## Success criteria\n- Tests run on PRs touching install/rig/beads code\n- Catch prefix mismatches, redirect errors, route config issues\n- \u003c 60s runtime to not slow CI\n\nGitHub: #20","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-01-02T13:00:52.740928-08:00","created_by":"mayor","updated_at":"2026-01-04T23:40:58.603798-08:00","closed_at":"2026-01-04T23:40:58.603798-08:00","close_reason":"Cleanup: stale molecule"} -{"id":"gt-htlmp.1","title":"Design: CI test infrastructure and approach","description":"Design decisions for CI test infrastructure.\n\n## Decisions Made\n\n### 1. Test Framework\n**Decision**: Go's standard testing with `//go:build integration` tag\n\nRationale:\n- Familiar to Go developers\n- Easy to run separately: `go test -tags=integration ./...`\n- Can have different timeouts for unit vs integration\n- No external test framework dependencies\n\n### 2. Temp Directory Strategy \n**Decision**: `t.TempDir()` per test\n\nRationale:\n- Auto-cleanup (no manual defer needed)\n- Test isolation - each test gets fresh state\n- Easy debugging - can add `t.Setenv(\"KEEP_TEMP\", \"1\")` to preserve\n\n### 3. Git Repo Handling\n**Decision**: Create minimal repos on-the-fly with `git init`\n\nRationale:\n- Faster than cloning fixtures\n- No external dependencies\n- Tests exactly what users do\n- Helper: `createTestGitRepo(t, name)`\n\n### 4. bd Daemon\n**Decision**: Run bd commands directly without daemon\n\nRationale:\n- bd CLI works fine for basic operations\n- Simpler test setup\n- Daemon adds complexity without testing benefit for install flow\n\n### 5. CI Integration\n**Decision**: Separate job with path filtering\n\n- Runs on: push to main, PRs touching install/rig/config/routing code\n- Timeout: 5 minutes (vs 2 min for unit tests)\n- Installs bd from beads repo before running\n\n## Implementation\n- Created: `internal/cmd/install_integration_test.go`\n- Updated: `.github/workflows/ci.yml` with integration job\n\n## Test Cases Implemented\n- TestInstallCreatesCorrectStructure\n- TestInstallBeadsHasCorrectPrefix \n- TestInstallIdempotent\n- Helper: createTestGitRepo","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T13:01:04.586688-08:00","created_by":"mayor","updated_at":"2026-01-02T13:12:32.780925-08:00","closed_at":"2026-01-02T13:12:32.780925-08:00","close_reason":"Design complete with implementation skeleton","dependencies":[{"issue_id":"gt-htlmp.1","depends_on_id":"gt-htlmp","type":"parent-child","created_at":"2026-01-02T13:01:04.59025-08:00","created_by":"mayor"}]} -{"id":"gt-htlmp.2","title":"Test: gt install creates correct structure","description":"Validate fresh install:\n\n## Test cases\n- [ ] Town root created with expected structure\n- [ ] mayor/ directory exists with rigs.json\n- [ ] .beads/ initialized with hq- prefix (not gm-)\n- [ ] CLAUDE.md created\n- [ ] No errors on clean install\n\n## Implementation\n```go\nfunc TestInstallFresh(t *testing.T) {\n tmpDir := t.TempDir()\n // Run gt install\n // Assert structure\n}\n```","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-02T13:01:14.996195-08:00","created_by":"mayor","updated_at":"2026-01-02T18:28:36.940537-08:00","closed_at":"2026-01-02T18:28:36.940537-08:00","close_reason":"Integration test implemented and passing","dependencies":[{"issue_id":"gt-htlmp.2","depends_on_id":"gt-htlmp","type":"parent-child","created_at":"2026-01-02T13:01:14.998336-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.2","depends_on_id":"gt-htlmp.1","type":"blocks","created_at":"2026-01-02T13:01:56.568927-08:00","created_by":"mayor"}]} -{"id":"gt-htlmp.3","title":"Test: gt rig add initializes rig correctly","description":"Validate rig setup:\n\n## Test cases\n- [ ] Rig directory created with mayor/rig structure\n- [ ] Rig beads initialized with correct prefix\n- [ ] routes.jsonl updated with new rig route\n- [ ] Rig appears in rigs.json\n- [ ] bd commands work from rig context\n\n## Prerequisites\n- Requires test git repo (create temp or use fixture)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2026-01-02T13:01:23.982223-08:00","created_by":"mayor","updated_at":"2026-01-02T18:29:06.81459-08:00","closed_at":"2026-01-02T18:29:06.81459-08:00","close_reason":"Implemented integration tests for gt rig add with 8 test cases covering directory structure, beads initialization, routes.jsonl, rigs.json, prefix derivation, config.json, agent dirs, and invalid name rejection.","dependencies":[{"issue_id":"gt-htlmp.3","depends_on_id":"gt-htlmp","type":"parent-child","created_at":"2026-01-02T13:01:23.984708-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.3","depends_on_id":"gt-htlmp.1","type":"blocks","created_at":"2026-01-02T13:01:56.626269-08:00","created_by":"mayor"}]} -{"id":"gt-htlmp.4","title":"Test: Beads routing and redirects work correctly","description":"Validate beads cross-rig routing:\n\n## Test cases\n- [ ] bd show \u003crig-prefix-id\u003e routes to correct rig from town root\n- [ ] bd show \u003chq-id\u003e routes to town beads\n- [ ] Redirect chains (.beads -\u003e actual location) resolve correctly\n- [ ] bd list works from polecat/crew directories\n- [ ] Prefix conflicts detected\n\n## Key scenarios\n- Query from town root\n- Query from rig directory\n- Query from polecat worktree","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T13:01:34.123396-08:00","created_by":"mayor","updated_at":"2026-01-02T18:53:59.717183-08:00","closed_at":"2026-01-02T18:53:59.717183-08:00","close_reason":"Added integration tests for beads routing and redirects. Tests cover: routing from town root, redirect resolution, circular redirect detection, prefix conflict detection, bd list from polecat/crew directories, routes.jsonl loading/appending/removal, and GetPrefixForRig.","dependencies":[{"issue_id":"gt-htlmp.4","depends_on_id":"gt-htlmp","type":"parent-child","created_at":"2026-01-02T13:01:34.125485-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.4","depends_on_id":"gt-htlmp.1","type":"blocks","created_at":"2026-01-02T13:01:56.682487-08:00","created_by":"mayor"}]} -{"id":"gt-htlmp.5","title":"CI: GitHub Actions workflow for integration tests","description":"Set up CI to run integration tests:\n\n## Requirements\n- Run on PRs touching: internal/cmd/install.go, internal/cmd/rig.go, internal/config/\n- Use build tag: //go:build integration\n- Timeout: 5 minutes max\n- Cache Go modules\n\n## Workflow structure\n```yaml\nname: Integration Tests\non:\n pull_request:\n paths:\n - 'internal/cmd/install.go'\n - 'internal/cmd/rig.go'\n - 'internal/config/**'\n - 'internal/routing/**'\njobs:\n integration:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-go@v5\n - run: go test -tags=integration ./...\n```","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2026-01-02T13:01:45.610931-08:00","created_by":"mayor","updated_at":"2026-01-03T13:04:59.007733-08:00","closed_at":"2026-01-03T13:04:59.007733-08:00","close_reason":"Created .github/workflows/integration.yml with path-based triggers, 5-min timeout, Go caching","dependencies":[{"issue_id":"gt-htlmp.5","depends_on_id":"gt-htlmp","type":"parent-child","created_at":"2026-01-02T13:01:45.614712-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.5","depends_on_id":"gt-htlmp.2","type":"blocks","created_at":"2026-01-02T13:01:56.739226-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.5","depends_on_id":"gt-htlmp.3","type":"blocks","created_at":"2026-01-02T13:01:56.794733-08:00","created_by":"mayor"},{"issue_id":"gt-htlmp.5","depends_on_id":"gt-htlmp.4","type":"blocks","created_at":"2026-01-02T13:01:56.852912-08:00","created_by":"mayor"}]} -{"id":"gt-htto","title":"Heartbeat convention: simple liveness signal for agents","description":"Lightweight liveness signal extracted from Deacon epic (gt-5af).\n\n**Implementation**: Each agent writes a timestamp file on activity:\n```bash\necho '{\"ts\":\"'$(date -Iseconds)'\"}' \u003e ~/gt/\u003crole\u003e/heartbeat.json\n```\n\n**Integration points**:\n- SessionStart hook writes heartbeat\n- Periodic activity (mail check, work completion) refreshes it\n- `gt status` shows staleness (e.g., 'mayor: 5m ago')\n\n**Weight**: ~5 lines per agent\n**Value**: Quick debugging - see which agents are active at a glance\n\nNo monitoring daemon needed - human checks `gt status` when curious.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-20T20:40:45.459903-08:00","updated_at":"2025-12-20T20:40:45.459903-08:00"} -{"id":"gt-hun12","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy - handoff cycle","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:16:15.153407-08:00","updated_at":"2026-01-01T22:16:15.153407-08:00","closed_at":"2026-01-01T22:16:15.153371-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-huz1b","title":"Test session event","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:14:45.521358-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:14:51.498151-08:00","closed_at":"2026-01-02T13:14:51.498151-08:00","close_reason":"Test event, cleaning up","event_kind":"session.ended","actor":"gastown/polecats/test","payload":"{\"cost_usd\":1.23}"} -{"id":"gt-hv5h5","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:50:05.794908-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.126623-08:00","closed_at":"2026-01-04T16:41:26.126623-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:50:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-hvhbr","title":"Digest: mol-deacon-patrol","description":"Patrol 158: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:08:17.143752-08:00","updated_at":"2026-01-01T15:08:17.143752-08:00","closed_at":"2026-01-01T15:08:17.143716-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-hvhbr","depends_on_id":"gt-eph-n3yw","type":"parent-child","created_at":"2026-01-01T15:08:17.145096-08:00","created_by":"deacon"}]} -{"id":"gt-hwf3o","title":"Fix potential race conditions in state file operations","description":"Non-atomic state file operations could cause data loss:\n\nAll packages with state files (witness, refinery, crew, swarm):\nState is loaded, modified, and saved without locking:\n ref, err := m.loadState()\n // ... modify ref ...\n return m.saveState(ref)\n\nIf two processes modify state simultaneously, one update may be lost.\n\ninternal/polecat/namepool.go (lines 179-194):\nSave() uses RLock() but performs file I/O - should use write lock.\n\ninternal/swarm/manager.go:\nswarms map[string]*Swarm accessed without mutex but multiple goroutines could call Create/GetSwarm.\n\nSuggestion:\n1. Use file locking (flock) for critical state updates\n2. Or use atomic write pattern (write to temp, then rename)\n3. Add mutex to swarm.Manager.swarms map","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:43:20.026309-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:23.181277-08:00","closed_at":"2025-12-28T15:47:23.181277-08:00"} -{"id":"gt-hwka3","title":"Pillar 2: Patrol Ignition","description":"Witness and Refinery patrol loops fire reliably.\n\nKey deliverables:\n- Witness patrol reads agent beads for polecat state\n- Witness sends MERGE_READY to refinery on completion\n- Refinery processes MERGE_READY mail\n- Both send completion signals\n\nSubsumes existing work:\n- gt-6qyt1: Refinery event-driven merge queue\n- gt-qpwv4: Witness detect completion\n- gt-dtw9u: Witness active monitoring\n\nReference: ~/gt/docs/liftoff-plan.md\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T20:56:05.225946-08:00","created_by":"mayor","updated_at":"2025-12-28T14:08:37.606361-08:00","closed_at":"2025-12-28T14:08:37.606361-08:00","dependencies":[{"issue_id":"gt-hwka3","depends_on_id":"gt-d0jqp","type":"blocks","created_at":"2025-12-27T20:56:22.812515-08:00","created_by":"daemon"}]} -{"id":"gt-hwm9j","title":"BUG: Refinery checks git ls-remote instead of gt mq list","description":"The refinery patrol checks 'git ls-remote origin | grep polecat' to see if there's work, but the merge queue is tracked in beads via 'gt mq list'. This caused 41 MRs to pile up while refinery reported 'Queue clear'.\n\nRoot cause: Refinery implementation is checking the wrong data source.\n\nFix: Change refinery patrol to use 'gt mq list \u003crig\u003e' as the source of truth for pending merge requests.\n\nRelated: hq-eggh5","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/keeper","created_at":"2026-01-01T19:55:38.98176-08:00","created_by":"mayor","updated_at":"2026-01-01T19:57:49.375569-08:00","closed_at":"2026-01-01T19:57:49.375569-08:00","close_reason":"Fixed refinery template to remove misleading git branch grep reference and add explicit warnings about using gt mq list as the only source of truth"} -{"id":"gt-hxfih","title":"Session ended: gt-gastown-bullet-farmer","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:47:25.895092-08:00","created_by":"gastown/polecats/bullet-farmer","updated_at":"2026-01-05T00:08:31.561629-08:00","closed_at":"2026-01-05T00:08:31.561629-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/bullet","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:47:25-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-bullet-farmer\",\"worker\":\"bullet\"}"} -{"id":"gt-hxp56","title":"Digest: mol-deacon-patrol","description":"Patrol 12: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T16:13:56.522072-08:00","updated_at":"2025-12-25T16:13:56.522072-08:00","closed_at":"2025-12-25T16:13:56.522043-08:00"} -{"id":"gt-hy8bw","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:38:45.417551-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.612715-08:00","closed_at":"2026-01-05T00:08:31.612715-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:38:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-hy9k5","title":"Review PR #198: refinery use default_branch","description":"dispatched_by: gastown/crew/joe","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/george","created_at":"2026-01-05T19:11:04.85613-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:13:54.270253-08:00","closed_at":"2026-01-05T19:13:54.270253-08:00","close_reason":"PR #198 reviewed and approved. Well-implemented fix for hardcoded 'main' branch in refineries."} -{"id":"gt-hyev8","title":"Digest: mol-deacon-patrol","description":"Patrol 9 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:44:09.93765-08:00","updated_at":"2025-12-31T16:44:09.93765-08:00","closed_at":"2025-12-31T16:44:09.937615-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hymm0","title":"Crew agent beads never created (dead code in reportAgentState)","description":"## Problem\n\nIn prime.go, reportAgentState is called for ALL roles including crew workers.\nThe function calls bd.UpdateAgentState for crew with ID like gt-crew-gastown-max.\n\nBut crew agent beads are NEVER created:\n- Polecats: Created on spawn (polecat/manager.go:167)\n- Infrastructure: Created by doctor/install (doctor/agent_beads_check.go)\n- Crew: Nothing creates them\n\nThe error is silently ignored, so this doesn't break anything, but it's dead code.\n\n## Found in commit\n\nf3a6ef6 (feat: Witness reads polecat state from agent beads)\n\n## Decision\n\n**Create crew agent beads** on first gt prime if they don't exist.\n\nCrew workers are human-managed but their state is still valuable for:\n- Town-wide status dashboards\n- Understanding who's working on what\n- Consistent agent bead model across all agent types\n\n## Implementation\n\nIn prime.go reportAgentState(), before calling UpdateAgentState:\n1. Try to get the agent bead\n2. If it doesn't exist, create it with CreateAgentBead\n3. Then update state as normal","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T09:48:06.89737-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T09:52:22.110029-08:00","closed_at":"2025-12-28T09:52:22.110029-08:00"} -{"id":"gt-hysp0","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All checks passed, no incidents. Witness/Refinery healthy, 1 dog idle, no polecats.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:02:04.886648-08:00","updated_at":"2025-12-31T18:02:04.886648-08:00","closed_at":"2025-12-31T18:02:04.886612-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hywb7","title":"Digest: mol-deacon-patrol","description":"Patrol 51: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:21:57.380346-08:00","updated_at":"2026-01-01T02:21:57.380346-08:00","closed_at":"2026-01-01T02:21:57.380306-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hz10p","title":"Digest: mol-deacon-patrol","description":"Patrol 9: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:04:27.055882-08:00","updated_at":"2025-12-31T19:04:27.055882-08:00","closed_at":"2025-12-31T19:04:27.055839-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-hzxzx","title":"Digest: mol-deacon-patrol","description":"Patrol 12: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:47:12.749201-08:00","updated_at":"2025-12-28T19:47:12.749201-08:00","closed_at":"2025-12-28T19:47:12.749166-08:00"} -{"id":"gt-i11mk","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:50.416671-08:00","updated_at":"2025-12-28T11:22:50.416671-08:00","closed_at":"2025-12-28T11:22:50.416639-08:00"} -{"id":"gt-i1eaj","title":"Merge: shiny-mk0vvt3o","description":"branch: polecat/shiny-mk0vvt3o\ntarget: main\nsource_issue: shiny-mk0vvt3o\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:22:08.82188-08:00","created_by":"gastown/polecats/shiny","updated_at":"2026-01-05T19:40:10.719071-08:00","closed_at":"2026-01-05T19:40:10.719071-08:00","close_reason":"Manually merged"} -{"id":"gt-i1mbw","title":"Digest: mol-deacon-patrol","description":"Patrol 5: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:38:44.804539-08:00","updated_at":"2026-01-01T22:38:44.804539-08:00","closed_at":"2026-01-01T22:38:44.804503-08:00"} -{"id":"gt-i1woc","title":"Merge: capable-mjxdb1vx","description":"branch: polecat/capable-mjxdb1vx\ntarget: main\nsource_issue: capable-mjxdb1vx\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:24:45.250238-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:41:40.386998-08:00","closed_at":"2026-01-02T13:41:40.386998-08:00","close_reason":"Branches merged, cleaning up stale MR beads"} -{"id":"gt-i26df","title":"Code Smell Cleanup: Gas Town Code Quality","description":"Comprehensive code smell cleanup identified in code review session.\n\n## Scope\nFixes for duplication, thread safety, missing tests, inconsistent patterns, and dead code.\n\n## Child issues (18 total)\n\n### Thread Safety \u0026 Data Integrity (P2)\n- gt-wled7: Atomic write pattern for state files\n- gt-xtsb5: Fix namepool Save() mutex\n- gt-bp0ht: Add swarm.Manager mutex\n\n### Duplication Removal (P2)\n- gt-560ge: Extract processExists function\n- gt-ddw3y: Extract molecule_lifecycle boilerplate\n- gt-atqr8: Session name helper functions\n- gt-ov2uv: AgentIdentity type for parsing\n\n### Missing Tests (P2)\n- gt-p2eg5: Lock package tests\n- gt-0vu9e: mrqueue package tests\n- gt-1pelm: mail router/mailbox tests\n\n### Code Quality (P2)\n- gt-gcnnr: Add logging for ignored errors\n\n### Constants Extraction (P3)\n- gt-4u682: SupportedShells constant\n- gt-795e8: Timing constants\n\n### Refactoring (P3)\n- gt-tkbd5: Refactor runStart\n- gt-dsqxw: Refactor runStartCrew\n\n### Error Handling (P3)\n- gt-h3skz: Remove os.Exit from RunE\n- gt-g6kor: Standardize warning output\n\n### Dead Code (P4)\n- gt-2g130: Remove unused code\n\n## Acceptance criteria\n- [ ] All child issues closed\n- [ ] go build ./... passes\n- [ ] go test ./... passes\n- [ ] go test -race ./... passes","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-28T15:50:43.855896-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T17:21:29.660385-08:00","closed_at":"2025-12-28T17:21:29.660385-08:00","dependencies":[{"issue_id":"gt-i26df","depends_on_id":"gt-560ge","type":"blocks","created_at":"2025-12-28T15:51:22.661646-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-ddw3y","type":"blocks","created_at":"2025-12-28T15:51:22.695272-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-gcnnr","type":"blocks","created_at":"2025-12-28T15:51:22.727278-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-2g130","type":"blocks","created_at":"2025-12-28T15:51:22.758725-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-atqr8","type":"blocks","created_at":"2025-12-28T15:51:22.790849-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-ov2uv","type":"blocks","created_at":"2025-12-28T15:51:22.822137-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-4u682","type":"blocks","created_at":"2025-12-28T15:51:22.854658-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-795e8","type":"blocks","created_at":"2025-12-28T15:51:22.887375-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-p2eg5","type":"blocks","created_at":"2025-12-28T15:51:22.919914-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-0vu9e","type":"blocks","created_at":"2025-12-28T15:51:22.95112-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-1pelm","type":"blocks","created_at":"2025-12-28T15:51:22.982649-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-tkbd5","type":"blocks","created_at":"2025-12-28T15:51:23.014724-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-dsqxw","type":"blocks","created_at":"2025-12-28T15:51:23.04713-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-bp0ht","type":"blocks","created_at":"2025-12-28T15:51:23.079833-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-xtsb5","type":"blocks","created_at":"2025-12-28T15:51:23.111918-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-wled7","type":"blocks","created_at":"2025-12-28T15:51:23.14385-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-h3skz","type":"blocks","created_at":"2025-12-28T15:51:23.17564-08:00","created_by":"daemon"},{"issue_id":"gt-i26df","depends_on_id":"gt-g6kor","type":"blocks","created_at":"2025-12-28T15:51:23.207367-08:00","created_by":"daemon"}]} -{"id":"gt-i2p40","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:03:09.590106-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.415212-08:00","closed_at":"2026-01-05T00:08:31.415212-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:03:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-i4ey9","title":"Session ended: gt-gastown-prime","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:37:16.231075-08:00","created_by":"gastown/polecats/prime","updated_at":"2026-01-04T16:40:13.48422-08:00","closed_at":"2026-01-04T16:40:13.48422-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/prime","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:37:16-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-prime\",\"worker\":\"prime\"}"} -{"id":"gt-i4hqc","title":"Digest: mol-deacon-patrol","description":"Patrol #19: Dog pool healthy, 1 idle.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:22:56.714817-08:00","updated_at":"2025-12-31T19:22:56.714817-08:00","closed_at":"2025-12-31T19:22:56.714778-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-i5bbp","title":"Digest: mol-deacon-patrol","description":"Patrol 6: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:49:59.037423-08:00","updated_at":"2025-12-25T20:49:59.037423-08:00","closed_at":"2025-12-25T20:49:59.037377-08:00"} -{"id":"gt-i5gkw","title":"Digest: mol-deacon-patrol","description":"Patrol complete: inbox empty, 2 polecats working, all agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:00:03.018473-08:00","updated_at":"2025-12-27T23:00:03.018473-08:00","closed_at":"2025-12-27T23:00:03.018437-08:00"} -{"id":"gt-i5o0p","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:29:17.733511-08:00","updated_at":"2026-01-01T10:29:17.733511-08:00","closed_at":"2026-01-01T10:29:17.733477-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-i60n0","title":"Digest: mol-deacon-patrol","description":"Patrol 12: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:34:51.442287-08:00","updated_at":"2025-12-29T22:34:51.442287-08:00","closed_at":"2025-12-29T22:34:51.442253-08:00"} -{"id":"gt-i6dje","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 78: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:26:31.21118-08:00","updated_at":"2026-01-01T13:26:31.21118-08:00","closed_at":"2026-01-01T13:26:31.211141-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-i6jvc","title":"Config directory and schema for messaging","description":"Create ~/gt/config/ directory structure for messaging configuration.\n\n## Deliverables\n\n1. Create ~/gt/config/ directory\n2. Define JSON schema for lists.json:\n ```json\n {\n \"oncall\": [\"mayor/\", \"gastown/witness\"],\n \"cleanup/gastown\": [\"gastown/witness\", \"deacon/\"]\n }\n ```\n3. Define JSON schema for queues.json (if separate from lists)\n4. Add config loading utility in internal/config/\n\n## Acceptance\n- Config directory exists\n- Schema documented\n- Load/parse functions work","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:51:36.803749-08:00","updated_at":"2025-12-28T14:07:37.693255-08:00","closed_at":"2025-12-28T14:07:37.693255-08:00"} -{"id":"gt-i6pub","title":"Digest: mol-deacon-patrol","description":"Patrol complete: 0 callbacks, no gates, all witnesses/refineries healthy, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T22:15:38.387794-08:00","updated_at":"2025-12-27T22:15:38.387794-08:00","closed_at":"2025-12-27T22:15:38.387759-08:00"} -{"id":"gt-i6xqu","title":"Merge: toast-1767146237529","description":"branch: polecat/toast-1767146237529\ntarget: main\nsource_issue: toast-1767146237529\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:03:32.882144-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T18:23:22.104571-08:00","closed_at":"2025-12-30T18:23:22.104571-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-i7eif","title":"Digest: mol-deacon-patrol","description":"Patrol 11: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:17:28.507015-08:00","updated_at":"2025-12-28T08:17:28.507015-08:00","closed_at":"2025-12-28T08:17:28.506983-08:00"} -{"id":"gt-i7lo9","title":"Digest: mol-deacon-patrol","description":"Patrol 149 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:03:16.056488-08:00","updated_at":"2025-12-31T16:03:16.056488-08:00","closed_at":"2025-12-31T16:03:16.056443-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-i7pqg","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:18:40.253899-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T21:18:40.309248-08:00","closed_at":"2026-01-05T21:18:40.309248-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:18:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-i7q66","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:11:58.147223-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:54.486527-08:00","closed_at":"2025-12-30T23:12:54.486527-08:00","close_reason":"Branch already merged"} -{"id":"gt-i7tmd","title":"Merge: rictus-1767084016819","description":"branch: polecat/rictus-1767084016819\ntarget: main\nsource_issue: rictus-1767084016819\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:58:46.107892-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T01:01:27.168699-08:00","closed_at":"2025-12-30T01:01:27.168699-08:00","close_reason":"Already merged to main"} -{"id":"gt-i7wcn","title":"Polecat sessions terminate unexpectedly during work","description":"During swarm bd-784c, polecat sessions (Toast, Nux) terminated mid-task without completing their work.\n\n**Observed:**\n- Polecats were actively working (edits in progress, tests running)\n- Sessions suddenly showed 'not running' in gt polecat status\n- tmux sessions existed but were empty/reset\n- Work was partially complete (some commits made, issue still open)\n\n**Impact:**\n- Lost work progress\n- Required manual intervention to restart\n- Unclear if work was saved/committed\n\n**Suggestion:**\n- Add session health monitoring\n- Auto-restart on unexpected termination\n- Log session exit reasons","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/toast","created_at":"2025-12-28T22:14:07.876275-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-29T22:07:52.213183-08:00","closed_at":"2025-12-29T22:07:52.213183-08:00","close_reason":"Implemented session health monitoring and auto-restart for crashed polecats. Changes include: (1) daemon now proactively checks polecat session health and auto-restarts crashed sessions with work-on-hook, (2) added polecat support to lifecycle identity mapping, (3) added 'gt session check' command for manual health checking."} -{"id":"gt-i85sg","title":"DRY: Duplicate config expansion in mail/router.go","description":"The expandList, expandQueue, and expandAnnounce functions (router.go:92-158) have nearly identical structure:\n- Check townRoot is set\n- Build config path\n- Load messaging config\n- Look up item in map\n- Return result or error\n\nThese should be consolidated into a helper like:\n\n```go\nfunc (r *Router) expandFromConfig[T any](name string, getter func(*config.MessagingConfig) (T, bool), errType error) (T, error)\n```\n\nFiles:\n- internal/mail/router.go:92-158\n\nSeverity: medium","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/interceptor","created_at":"2026-01-04T23:46:34.913409-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T00:14:16.149359-08:00","closed_at":"2026-01-05T00:14:16.149359-08:00","close_reason":"Consolidated expandList, expandQueue, expandAnnounce using generic expandFromConfig helper"} -{"id":"gt-i8kep","title":"Digest: mol-deacon-patrol","description":"Cycle 193: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:23:33.671552-08:00","updated_at":"2026-01-01T16:23:33.671552-08:00","closed_at":"2026-01-01T16:23:33.671522-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-i8kep","depends_on_id":"gt-eph-xh8n","type":"parent-child","created_at":"2026-01-01T16:23:33.672872-08:00","created_by":"deacon"}]} -{"id":"gt-i9j04","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T14:03:09.357066-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.222322-08:00","closed_at":"2026-01-04T16:41:26.222322-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T14:03:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-i9pl9","title":"Merge: valkyrie-mjxpdngw","description":"branch: polecat/valkyrie-mjxpdngw\ntarget: main\nsource_issue: valkyrie-mjxpdngw\nrig: gastown\nagent_bead: gt-gastown-polecat-valkyrie","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:53:21.590044-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2026-01-02T18:55:38.336229-08:00","closed_at":"2026-01-02T18:55:38.336229-08:00","close_reason":"Merged to main at 27618e5c"} -{"id":"gt-i9y2a","title":"Merge: toast-1767146237529","description":"branch: polecat/toast-1767146237529\ntarget: main\nsource_issue: toast-1767146237529\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:04:15.703708-08:00","created_by":"gastown/polecats/toast","updated_at":"2025-12-30T18:23:22.091455-08:00","closed_at":"2025-12-30T18:23:22.091455-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-i9y56","title":"Digest: mol-deacon-patrol","description":"Patrol 3: 3 rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:23:08.351555-08:00","updated_at":"2026-01-01T04:23:08.351555-08:00","closed_at":"2026-01-01T04:23:08.351523-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ia0s","title":"Review: Beads Universal Data Plane documentation","description":"Review new docs/beads-data-plane.md (275 lines) for accuracy.\n\n## Commit\n- 54c8269: Add Beads Universal Data Plane documentation\n\n## Review focus\n- Accuracy of beads architecture description\n- Correct field mappings (mail → beads fields)\n- Two-level architecture (town vs rig beads) correctly explained","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T14:27:49.410707-08:00","updated_at":"2025-12-23T14:27:49.410707-08:00","dependencies":[{"issue_id":"gt-ia0s","depends_on_id":"gt-e0qj2","type":"blocks","created_at":"2025-12-26T23:21:29.418109-08:00","created_by":"daemon"}]} -{"id":"gt-ib8mh","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:09:51.286306-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.592375-08:00","closed_at":"2026-01-04T16:40:22.592375-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:09:51-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-ibuga","title":"Polecat didn't commit before gt done","description":"Integration test gt-7psb8: Polecat furiosa ran gt done before committing changes.\n\nThe polecat:\n1. Created a test file\n2. Closed the bead with bd close --force\n3. Ran bd sync\n4. Ran gt done\n\nBut it NEVER ran:\n- git add \u003cfile\u003e\n- git commit\n\nResult: Branch pushed with no new commits. Refinery detected branch at same commit as main.\n\nThe polecat CLAUDE.md or session close protocol should enforce commit before gt done.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T13:13:39.656598-08:00","created_by":"mayor","updated_at":"2025-12-28T14:00:14.100446-08:00","closed_at":"2025-12-28T14:00:14.100446-08:00"} -{"id":"gt-iceij","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:03:52.951489-08:00","updated_at":"2026-01-01T20:03:52.951489-08:00","closed_at":"2026-01-01T20:03:52.951455-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-ichna","title":"Digest: mol-deacon-patrol","description":"Patrol 103: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:02:05.241439-08:00","updated_at":"2026-01-01T14:02:05.241439-08:00","closed_at":"2026-01-01T14:02:05.241402-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ichum","title":"crew_add.go: Agent bead ID uses wrong format","description":"In internal/cmd/crew_add.go:84, the agent bead ID is constructed as:\n\n crewID := fmt.Sprintf(\"gt-crew-%s-%s\", rigName, name)\n\nThis produces 'gt-crew-gastown-joe' but existing beads and the session name format use:\n\n gt-\u003crig\u003e-crew-\u003cname\u003e (e.g., gt-gastown-crew-joe)\n\nThis causes agent beads to not be found/matched properly.\n\nFix: Change line 84 to:\n\n crewID := fmt.Sprintf(\"gt-%s-crew-%s\", rigName, name)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-29T15:24:17.796501-08:00","created_by":"stevey","updated_at":"2025-12-29T15:40:43.874203-08:00","closed_at":"2025-12-29T15:40:43.874203-08:00","close_reason":"Already fixed by max in c31bff4 - now uses beads.CrewBeadIDWithPrefix()"} -{"id":"gt-id0rm","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:03:43.459028-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.400433-08:00","closed_at":"2026-01-05T00:08:31.400433-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:03:43-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-idt8f","title":"Digest: mol-deacon-patrol","description":"P13: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:59:21.269231-08:00","updated_at":"2025-12-25T19:59:21.269231-08:00","closed_at":"2025-12-25T19:59:21.269178-08:00"} -{"id":"gt-idxr5","title":"Digest: mol-deacon-patrol","description":"Patrol 5: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:49:37.149631-08:00","updated_at":"2025-12-25T20:49:37.149631-08:00","closed_at":"2025-12-25T20:49:37.149584-08:00"} -{"id":"gt-ifmi6","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:27:56.907025-08:00","updated_at":"2026-01-01T11:27:56.907025-08:00","closed_at":"2026-01-01T11:27:56.906986-08:00"} -{"id":"gt-ifxvi","title":"Digest: mol-deacon-patrol","description":"Patrol 8: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T14:24:01.913738-08:00","updated_at":"2025-12-25T14:24:01.913738-08:00","closed_at":"2025-12-25T14:24:01.913706-08:00"} -{"id":"gt-igx2u","title":"CRITICAL: Merge formula CLI scaffold (gt-gpifj)","description":"Commit 60da7926 (formula CLI scaffold) is on branch polecat/nux-mjw18ii8 but NOT merged to main. This blocks formula execution functionality. Main still has old formulas.go that just delegates to bd formula list.","status":"closed","priority":0,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2026-01-01T15:00:55.782812-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T15:41:07.486274-08:00","closed_at":"2026-01-01T15:41:07.486274-08:00","close_reason":"Merged at 265dbcb via refinery"} -{"id":"gt-ih6xy","title":"Rig disable/enable with property layers","description":"Implement multi-level configuration system for Gas Town.\n\nTwo-level rig control:\n- Level 1 (park/unpark): Wisp layer, town-local, ephemeral\n- Level 2 (dock/undock): Rig bead labels, synced globally\n\nProperty layer lookup: Wisp → Bead → Town → System defaults\n\nSee:\n- ~/gt/docs/hop/PROPERTY-LAYERS.md\n- docs/property-layers.md","status":"open","priority":2,"issue_type":"epic","created_at":"2026-01-06T17:35:58.684965-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:35:58.684965-08:00","dependencies":[{"issue_id":"gt-ih6xy","depends_on_id":"gt-vxv0u","type":"blocks","created_at":"2026-01-06T17:37:17.623522-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-ih6xy","depends_on_id":"gt-9gm9n","type":"blocks","created_at":"2026-01-06T17:37:17.671645-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-ih6xy","depends_on_id":"gt-68c46","type":"blocks","created_at":"2026-01-06T17:37:17.72289-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-ih6xy","depends_on_id":"gt-hhmkq","type":"blocks","created_at":"2026-01-06T17:37:17.770779-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-ih6xy","depends_on_id":"gt-5l7h4","type":"blocks","created_at":"2026-01-06T17:37:17.818369-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-ihodi","title":"Digest: mol-deacon-patrol","description":"Patrol 18: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:08:23.7618-08:00","updated_at":"2025-12-31T19:08:23.7618-08:00","closed_at":"2025-12-31T19:08:23.76176-08:00","dependencies":[{"issue_id":"gt-ihodi","depends_on_id":"gt-eph-fr2i","type":"parent-child","created_at":"2025-12-31T19:08:23.762937-08:00","created_by":"deacon"}]} -{"id":"gt-ihvq0","title":"Agent bead creation uses wrong prefix for non-gastown rigs","description":"When adding a polecat to beads rig, agent bead creation fails:\n Error: issue ID 'gt-polecat-beads-Toast' does not match configured prefix 'bd'\n\nThe agent bead ID should use the rig's prefix (bd-) not hardcoded gt-.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-28T19:29:40.954862-08:00","created_by":"mayor","updated_at":"2025-12-29T15:28:36.401279-08:00","closed_at":"2025-12-29T15:28:36.401279-08:00","close_reason":"Fixed: Added WithPrefix variants to agent bead ID functions, updated crew_add.go, rig/manager.go, and doctor/agent_beads_check.go to use rig's configured prefix"} -{"id":"gt-ihzqr","title":"Formula SDK: Developer Tooling for Workflow Authors","description":"SDK for creating, testing, debugging, and validating formulas.\n\n## Components\n\n### Forge (Creation)\n```bash\nmol forge new my-workflow # Scaffold new formula\nmol forge extend base-workflow # Create variant\nmol forge lint my-workflow # Check syntax/style\n```\n\n### Lab (Testing)\n```bash\nmol lab run my-workflow --dry-run # Mock execution\nmol lab test my-workflow # Run formula tests\nmol lab trace my-workflow # Step-through debug\n```\n\n### Validator (Verification)\n```bash\nmol validate my-workflow # Check well-formedness\nmol validate my-workflow --protocol=Reviewable # Check protocol compliance\nmol validate my-workflow --schematic=shiny # Check schematic compatibility\n```\n\n### Analyzer (Static Analysis)\n```bash\nmol analyze my-workflow --deps # Dependency graph\nmol analyze my-workflow --coverage # Step coverage\nmol analyze my-workflow --cycles # Detect cycles\n```\n\n## Relationship to Other Concepts\n\nThe SDK operates on:\n- Formulas (source level)\n- Protos (compiled level)\n- Molecules (runtime level)\n\nAnd validates against:\n- Protocols (type system)\n- Schematics (domain composition)\n\n## Open Questions\n\n1. Bundled vs separate - mol subcommands or formula-kit binary?\n2. IDE integration - LSP for formula files?\n3. Test harness - how to mock steps? fixtures?\n\n## Related\n\n- docs/formula_evolution.md - \"SDK Question\" section\n- gt-8tmz.30 - Proto debugging tools (subset)\n- gt-8tmz.31 - Formula validation (subset)\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:00:55.010406-08:00","updated_at":"2025-12-28T22:33:22.271081-08:00","closed_at":"2025-12-28T22:33:22.271081-08:00"} -{"id":"gt-iicbq","title":"Code Smell: Large Connection interface (17 methods)","description":"The Connection interface in connection/connection.go has 17 methods, violating the Interface Segregation Principle.\n\nCurrent interface groups:\n- Identification: Name(), IsLocal()\n- File operations: ReadFile, WriteFile, MkdirAll, Remove, RemoveAll, Stat, Glob, Exists\n- Command execution: Exec, ExecDir, ExecEnv\n- Tmux operations: TmuxNewSession, TmuxKillSession, TmuxSendKeys, TmuxCapturePane, TmuxHasSession, TmuxListSessions\n\n**Recommendation**: Split into focused interfaces:\n```go\ntype Identifier interface {\n Name() string\n IsLocal() bool\n}\n\ntype FileSystem interface {\n ReadFile(path string) ([]byte, error)\n WriteFile(path string, data []byte, perm fs.FileMode) error\n // ...\n}\n\ntype CommandRunner interface {\n Exec(cmd string, args ...string) ([]byte, error)\n ExecDir(dir, cmd string, args ...string) ([]byte, error)\n ExecEnv(env map[string]string, cmd string, args ...string) ([]byte, error)\n}\n\ntype TmuxManager interface {\n TmuxNewSession(name, dir string) error\n // ...\n}\n\ntype Connection interface {\n Identifier\n FileSystem\n CommandRunner\n TmuxManager\n}\n```\n\nThis allows consumers to depend only on what they need.\n\nFiles:\n- internal/connection/connection.go:13-78\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:06.768689-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:47:06.768689-08:00"} -{"id":"gt-iijvm","title":"Merge: gt-2hwi9","description":"branch: polecat/furiosa-mjw349y2\ntarget: main\nsource_issue: gt-2hwi9\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":0,"issue_type":"merge-request","created_at":"2026-01-01T15:45:46.123786-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T15:47:02.535013-08:00","closed_at":"2026-01-01T15:47:02.535013-08:00","close_reason":"Merged to main at cf03343f"} -{"id":"gt-ij1mo","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All healthy - 3 rigs, 6 agents, 1 dog idle, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:49:48.58422-08:00","updated_at":"2025-12-31T23:49:48.58422-08:00","closed_at":"2025-12-31T23:49:48.584175-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ij4dv","title":"gt convoy list --tree: Show convoy + child status tree","description":"Add a --tree flag to 'gt convoy list' that shows convoys with their child issues in a tree format.\n\nExample output:\n```\n🚚 hq-cv-wvqi6: Boot + Polish swarm (16/17)\n├── ✓ bd-11lm: Increase ClaudeStartTimeout\n├── ✓ bd-49oe: Cache GetGitDir()\n├── ○ gt-74ivo: Witness: Don't nuke polecats with open MRs ← remaining\n└── ...\n\n🚚 hq-cv-w3nm6: Messaging Channels (4/10)\n├── ✓ gt-0q3cg: Add isQueueAddress()\n├── ○ gt-27bzi: Add gt mail announces\n└── ...\n```\n\nMakes convoy progress visible at a glance without running 'gt convoy status' on each one.\n\n(Moved from hq-q3tki)","status":"closed","priority":2,"issue_type":"feature","created_at":"2026-01-02T01:37:20.73191-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-02T13:57:17.745312-08:00","closed_at":"2026-01-02T13:57:17.745312-08:00","close_reason":"Duplicate of gt-quf4c"} -{"id":"gt-ikyo1","title":"Day 1.1: Add type=agent to bead schema","description":"Add agent as a valid bead type in the schema. This is the foundation for agent-as-bead.\n\nParent: gt-d0jqp","notes":"Re-opened: Close reason referenced non-existent commit 927e8374. Type=agent not yet implemented in bd CLI.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-12-27T20:57:54.914343-08:00","created_by":"mayor","updated_at":"2025-12-28T00:09:42.962001-08:00","closed_at":"2025-12-28T00:09:42.962001-08:00","dependencies":[{"issue_id":"gt-ikyo1","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.539952-08:00","created_by":"daemon"}]} -{"id":"gt-il2p7","title":"bd update --claim for work queue semantics","description":"Atomic claim operation for work queue messages.\n\n## Deliverables\n\n1. Add --claim flag to bd update\n2. Atomic operation:\n - Sets assignee to claimer\n - Sets status to in_progress\n - Fails if already claimed\n3. Conflict detection:\n - If already claimed, return error: \"already claimed by X\"\n4. Integration with gt mail for queue messages\n\n## Example\n```bash\ngt mail queue cleanup/gastown # See available work\nbd update msg-xxx --claim # Claim it atomically\n# Returns error if someone else claimed first\n```\n\n## Dependencies\n- queue: shared storage (gt-???)\n\n## Acceptance\n- --claim sets assignee + status atomically\n- Double-claim returns clear error\n- Works with queue messages","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/organic","created_at":"2025-12-26T14:52:08.186488-08:00","updated_at":"2025-12-30T10:42:07.313577-08:00","closed_at":"2025-12-30T10:42:07.313577-08:00","close_reason":"Implemented --claim flag for bd update: sets assignee + status atomically, fails if already claimed. Branch: feature/claim-flag pushed to beads repo.","dependencies":[{"issue_id":"gt-il2p7","depends_on_id":"gt-tnap3","type":"blocks","created_at":"2025-12-26T14:53:08.553425-08:00","created_by":"daemon"}]} -{"id":"gt-ilav","title":"Polecat Lifecycle Events: Refinery-Witness Coordination","description":"## Problem\n\nPolecat work completion is currently treated as a single event (MR submission), but the true completion is when the Refinery merges the work. This creates a lifecycle gap:\n\n1. Polecat submits MR → considered \"done\" by Witness\n2. But MR might fail to merge (conflicts, test failures)\n3. No one notifies anyone when merge actually succeeds\n\n## Solution: Two-Event Lifecycle\n\n**Event 1: MR Submitted**\n- `gt mq submit` notifies Witness\n- Witness verifies submission was clean\n- Polecat can go idle (but worktree retained)\n- If submission had issues, Witness can help\n\n**Event 2: MR Merged**\n- Refinery sends `LIFECYCLE: work merged` to Witness\n- Witness updates polecat state to `merged`\n- Worktree now eligible for full cleanup/recycling\n\n## Village Sibling Watch\n\nFor robustness, patrol roles check on their siblings:\n- Refinery checks Witness via `gt peek`\n- Witness checks Refinery via `gt peek`\n- Creates defense in depth - if primary notification fails, someone catches it\n\n## Recovery\n\nIf Refinery misses sending lifecycle notification:\n- Witness polecat-scan can detect: polecat in mr_submitted but MR shows merged\n- Deacon orphan-check can detect: merged MRs with stale polecats","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-23T12:06:56.746185-08:00","updated_at":"2026-01-04T23:40:58.610799-08:00","closed_at":"2026-01-04T23:40:58.610799-08:00","close_reason":"Cleanup: stale molecule","deleted_at":"2025-12-27T21:29:56.026982-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"epic"} -{"id":"gt-ilav.1","title":"Refinery: Add lifecycle-notify step to patrol","description":"After successful merge in handleSuccess(), send lifecycle notification to Witness.\n\n## Implementation\n\n1. Add new mail type: `LIFECYCLE: work merged`\n2. In engineer.go handleSuccess(), after closing MR and source issue:\n ```\n gt mail send \u003crig\u003e/witness -s \"LIFECYCLE: work merged\" -m \"\n Worker: \u003cpolecat\u003e\n MR: \u003cmr-id\u003e\n Issue: \u003csource-issue\u003e\n Commit: \u003cmerge-commit\u003e\n Action: Polecat work merged. Worktree eligible for recycling.\n \"\n ```\n\n3. Update mol-refinery-patrol to include lifecycle-notify step between merge-push and loop-check\n\n## Acceptance\n- Successful merges send mail to Witness\n- Mail includes worker name, MR id, source issue, commit SHA","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:46.715807-08:00","updated_at":"2025-12-28T22:36:25.392959-08:00","closed_at":"2025-12-28T22:36:25.392959-08:00","dependencies":[{"issue_id":"gt-ilav.1","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:46.716238-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.2","title":"Witness: Handle LIFECYCLE work-merged mail","description":"Witness should process the `LIFECYCLE: work merged` notification from Refinery.\n\n## Implementation\n\n1. In Witness mail processing, add handler for subject containing \"LIFECYCLE: work merged\"\n2. Parse worker name from mail body\n3. Update polecat state to `merged` (new state - see sibling task)\n4. Log completion for metrics\n5. Worktree is now eligible for cleanup on next gc cycle\n\n## Acceptance\n- Witness correctly parses and handles work-merged mail\n- Polecat state updated to merged\n- No action taken if polecat already cleaned up (idempotent)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:47.878019-08:00","updated_at":"2025-12-28T22:36:25.376524-08:00","closed_at":"2025-12-28T22:36:25.376524-08:00","dependencies":[{"issue_id":"gt-ilav.2","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:47.880327-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.2","depends_on_id":"gt-ilav.1","type":"blocks","created_at":"2025-12-23T12:08:06.585766-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.2","depends_on_id":"gt-ilav.5","type":"blocks","created_at":"2025-12-23T12:08:06.667459-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.3","title":"MQ Submit: Notify Witness on MR submission","description":"When `gt mq submit` is run, notify the Witness so it can verify the submission.\n\n## Implementation\n\n1. In mq_submit.go after successful MR creation:\n ```\n gt mail send \u003crig\u003e/witness -s \"LIFECYCLE: mr submitted\" -m \"\n Worker: \u003cpolecat\u003e\n MR: \u003cmr-id\u003e\n Branch: \u003cbranch-name\u003e\n Target: \u003ctarget-branch\u003e\n Action: Verify MR submission, help polecat if needed.\n \"\n ```\n\n2. This happens BEFORE the existing polecat auto-cleanup logic\n\n## Acceptance\n- MR submission sends notification to Witness\n- Witness receives mail with all relevant details\n- Works for both polecat and crew submissions","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:49.07255-08:00","updated_at":"2025-12-28T22:36:25.360175-08:00","closed_at":"2025-12-28T22:36:25.360175-08:00","dependencies":[{"issue_id":"gt-ilav.3","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:49.07304-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.3","depends_on_id":"gt-ilav.5","type":"blocks","created_at":"2025-12-23T12:08:06.337807-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.4","title":"Witness: Verify MR submission on notification","description":"When Witness receives `LIFECYCLE: mr submitted`, verify the submission was clean.\n\n## Implementation\n\n1. Add handler for \"LIFECYCLE: mr submitted\" mail\n2. Check MR status: `gt mq status \u003cmr-id\u003e`\n3. If MR looks good (status=open, no errors): log success, allow polecat to idle\n4. If MR has issues:\n - Check polecat git state\n - Nudge polecat to fix if session still alive\n - Log issue for monitoring\n\n## Acceptance\n- Witness verifies MR after submission notification\n- Can detect problematic submissions\n- Provides early intervention opportunity","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:50.607753-08:00","updated_at":"2025-12-28T22:36:25.34253-08:00","closed_at":"2025-12-28T22:36:25.34253-08:00","dependencies":[{"issue_id":"gt-ilav.4","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:50.60974-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.4","depends_on_id":"gt-ilav.3","type":"blocks","created_at":"2025-12-23T12:08:06.420836-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.4","depends_on_id":"gt-ilav.5","type":"blocks","created_at":"2025-12-23T12:08:06.502487-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.5","title":"Polecat state tracking: Add mr_submitted and merged states","description":"Track polecat lifecycle state separate from session state.\n\n## New States\n\n| State | Meaning |\n|-------|---------|\n| active | Working on assigned issue |\n| mr_submitted | MR submitted, waiting for merge |\n| idle | No current work, session may be alive |\n| merged | Work successfully merged by Refinery |\n| retired | Session killed, worktree removed |\n\n## Implementation\n\n1. Add state field to polecat tracking (state.json or beads)\n2. `gt polecat update \u003cname\u003e --state=\u003cstate\u003e`\n3. `gt polecat list` shows state column\n4. State transitions:\n - active → mr_submitted (on gt mq submit)\n - mr_submitted → merged (on Refinery notification)\n - merged → retired (on worktree cleanup)\n\n## Acceptance\n- Polecat state tracked and queryable\n- State transitions happen at correct lifecycle points\n- `gt polecat list` shows current state","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:51.968117-08:00","updated_at":"2025-12-28T22:36:25.325032-08:00","closed_at":"2025-12-28T22:36:25.325032-08:00","dependencies":[{"issue_id":"gt-ilav.5","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:51.970044-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.6","title":"Refinery patrol: Add sibling-check step","description":"Refinery should check on Witness health as part of patrol (village sibling watch).\n\n## Implementation\n\n1. Add `sibling-check` step to mol-refinery-patrol (early in cycle)\n2. Use `gt peek \u003crig\u003e/witness 20` to check Witness output\n3. Look for signs of health:\n - Recent activity (tool calls, log messages)\n - No error stack traces\n - Responsive to pings\n4. If Witness seems stuck:\n - Send status request mail\n - Note for potential escalation\n - Don't block Refinery work\n\n## Acceptance\n- Refinery checks Witness each patrol cycle\n- Anomalies logged\n- Non-blocking (Refinery continues even if Witness is down)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:54.005132-08:00","updated_at":"2025-12-28T22:36:25.307429-08:00","closed_at":"2025-12-28T22:36:25.307429-08:00","dependencies":[{"issue_id":"gt-ilav.6","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:54.006928-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.7","title":"Witness patrol: Add sibling-check for Refinery","description":"Witness should check on Refinery health as part of patrol (village sibling watch).\n\n## Implementation\n\n1. Add `sibling-check` step to mol-witness-patrol\n2. Use `gt peek \u003crig\u003e/refinery 20` to check Refinery output\n3. Check Refinery queue status: `gt mq list \u003crig\u003e`\n4. Look for:\n - Refinery session alive\n - Queue processing (if items present)\n - No stuck MRs (same MR in_progress for too long)\n5. If Refinery seems stuck:\n - Send nudge or status request\n - Consider escalation to Deacon\n\n## Acceptance\n- Witness checks Refinery each patrol cycle\n- Can detect stuck Refinery\n- Provides backup oversight for merge queue","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:55.760705-08:00","updated_at":"2025-12-28T22:36:25.28879-08:00","closed_at":"2025-12-28T22:36:25.28879-08:00","dependencies":[{"issue_id":"gt-ilav.7","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:55.762415-08:00","created_by":"daemon"}]} -{"id":"gt-ilav.8","title":"Recovery: Detect orphaned merged polecats","description":"Safety net for when Refinery misses sending lifecycle notification.\n\n## Detection Points\n\n**Witness polecat-scan**:\n- For each polecat in `mr_submitted` state:\n - Check MR status: `gt mq status \u003cmr-id\u003e`\n - If MR is closed/merged but polecat state is still mr_submitted:\n - Update polecat state to `merged`\n - Log recovery action\n\n**Deacon orphan-check**:\n- Query all closed MRs\n- Cross-reference with polecat states\n- If merged MR but polecat not in merged/retired state:\n - Send correction to Witness\n - Log for metrics (indicates Refinery notification missed)\n\n## Acceptance\n- Orphaned polecats detected and corrected\n- Recovery is logged for monitoring\n- No work lost due to missed notifications","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T12:07:56.821259-08:00","updated_at":"2025-12-28T22:36:25.268873-08:00","closed_at":"2025-12-28T22:36:25.268873-08:00","dependencies":[{"issue_id":"gt-ilav.8","depends_on_id":"gt-ilav","type":"parent-child","created_at":"2025-12-23T12:07:56.823191-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.8","depends_on_id":"gt-ilav.5","type":"blocks","created_at":"2025-12-23T12:08:06.749803-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.8","depends_on_id":"gt-ilav.2","type":"blocks","created_at":"2025-12-23T12:08:06.832711-08:00","created_by":"daemon"},{"issue_id":"gt-ilav.8","depends_on_id":"gt-ilav.4","type":"blocks","created_at":"2025-12-23T12:08:06.918149-08:00","created_by":"daemon"}]} -{"id":"gt-ilfqa","title":"Digest: mol-deacon-patrol","description":"Patrol 16: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T16:53:01.166838-08:00","updated_at":"2025-12-26T16:53:01.166838-08:00","closed_at":"2025-12-26T16:53:01.166794-08:00"} -{"id":"gt-in7b","title":"gt sling: nudge crew/mayor if session is running","description":"When slinging to crew or mayor, if they have an active tmux session, send a nudge notification so they know work has landed on their hook.\n\nCurrently only slingToPolecat nudges (lines 514-521 in internal/cmd/sling.go).\n\nMissing nudge in:\n- slingToCrew (line ~669)\n- slingToMayor (line ~876)\n\nNOTE: For patrol-based agents (witness, refinery, deacon), see gt-arjlu which handles nudging them when work is dispatched to polecats in their rig. That's a different pattern - not slinging TO them, but notifying them of activity.\n\nImplementation:\n1. For crew: need to determine session name (e.g., gastown-crew-max)\n2. Check if session running via tmux\n3. If running, call t.NudgeSession() with appropriate message","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T15:56:22.30857-08:00","updated_at":"2025-12-28T22:15:24.451068-08:00"} -{"id":"gt-inzfr","title":"Merge: dementus-mjxaqvb9","description":"branch: polecat/dementus-mjxaqvb9\ntarget: main\nsource_issue: dementus-mjxaqvb9\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:11:26.45999-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-02T12:30:01.875277-08:00","closed_at":"2026-01-02T12:30:01.875277-08:00","close_reason":"Merged to main at c5ee18c6"} -{"id":"gt-io9r8","title":"Digest: mol-deacon-patrol","description":"Patrol 66: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:00:45.063731-08:00","updated_at":"2025-12-31T15:00:45.063731-08:00","closed_at":"2025-12-31T15:00:45.063694-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ipwdc","title":"Merge: furiosa-1767082251065","description":"branch: polecat/furiosa-1767082251065\ntarget: main\nsource_issue: furiosa-1767082251065\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:14:26.025544-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T10:06:56.852964-08:00","closed_at":"2025-12-30T10:06:56.852964-08:00","close_reason":"Branch merged to main"} -{"id":"gt-iqq7j","title":"Session ended: gt-gastown-dinki","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:40:30.321025-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-04T16:40:13.326985-08:00","closed_at":"2026-01-04T16:40:13.326985-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/dinki","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:40:30-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-dinki\",\"worker\":\"dinki\"}"} -{"id":"gt-ir6c8","title":"Digest: mol-deacon-patrol","description":"Patrol #4: All agents healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:17:19.346197-08:00","updated_at":"2025-12-31T19:17:19.346197-08:00","closed_at":"2025-12-31T19:17:19.346158-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-is4fi","title":"Refactor formula transformation pipeline to shared helper","description":"The formula transformation pipeline (control flow, advice, expansions, aspects) is duplicated between cook.go and mol_bond.go. Should be extracted to a shared function in the formula package.\n\nCurrent duplication in:\n- cmd/bd/cook.go:96-136\n- cmd/bd/mol_bond.go:598-633\n\nSuggested approach:\n- Add formula.Transform(resolved *Formula, parser *Parser) (*Formula, error) \n- Handles all transformation steps in order\n- Both cook.go and mol_bond.go call this single function","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-25T16:50:55.343049-08:00","updated_at":"2025-12-28T22:34:14.426995-08:00","closed_at":"2025-12-28T22:34:14.426995-08:00","dependencies":[{"issue_id":"gt-is4fi","depends_on_id":"gt-8tmz.25","type":"discovered-from","created_at":"2025-12-25T16:50:55.344455-08:00","created_by":"daemon"}]} -{"id":"gt-itmgf","title":"INVESTIGATE: Dead polecats accumulating despite witness patrol","description":"During shutdown cleanup, gt status showed many polecats with [dead] status:\n- 23+ dead polecats in gastown\n- 2 dead crew in wyvern\n\nThe witness patrol (mol-witness-patrol) has logic in survey-workers step to:\n1. Detect idle polecats\n2. Auto-nuke if clean (no uncommitted changes)\n3. Escalate if dirty\n\nQuestions:\n1. Is the witness patrol actually running?\n2. Is the auto-nuke logic working?\n3. Are these polecats dirty (have uncommitted work)?\n4. Is the dead status not triggering cleanup?\n\nNeed to investigate why dead polecats accumulate rather than being cleaned up.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T20:39:44.498971-08:00","created_by":"mayor","updated_at":"2026-01-04T20:39:44.498971-08:00"} -{"id":"gt-itmr9","title":"Session ended: gt-gastown-gastown","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:11:39.932474-08:00","created_by":"gastown/polecats/gastown","updated_at":"2026-01-05T19:44:41.929121-08:00","closed_at":"2026-01-05T19:44:41.929121-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/gastown","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:11:39-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-gastown\",\"worker\":\"gastown\"}"} -{"id":"gt-iu0jb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 43: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:52:36.887212-08:00","updated_at":"2026-01-01T12:52:36.887212-08:00","closed_at":"2026-01-01T12:52:36.887179-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-iudqo","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously,\nhandling callbacks, monitoring rig health, and performing cleanup.\nEach patrol cycle runs these steps in sequence, then loops or exits.\n","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-25T11:05:57.818656-08:00","updated_at":"2025-12-28T22:33:21.96702-08:00","closed_at":"2025-12-28T22:33:21.96702-08:00"} -{"id":"gt-iva20","title":"Liftoff test: Add timestamp comment to manager.go","description":"Simple liftoff test task.\n\nAdd a comment at the top of internal/polecat/manager.go with the current timestamp, like:\n// Liftoff test: \u003ctimestamp\u003e\n\nThis tests the full polecat → refinery → witness cycle.","status":"hooked","priority":1,"issue_type":"task","created_at":"2025-12-28T16:18:27.905345-08:00","created_by":"stevey","updated_at":"2025-12-28T16:18:40.555384-08:00"} -{"id":"gt-ivf6w","title":"Digest: mol-deacon-patrol","description":"Patrol 15: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:56:13.720896-08:00","updated_at":"2025-12-28T15:56:13.720896-08:00","closed_at":"2025-12-28T15:56:13.720857-08:00"} -{"id":"gt-ivtcl","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:13:08.154297-08:00","updated_at":"2026-01-01T06:13:08.154297-08:00","closed_at":"2026-01-01T06:13:08.154255-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-iw14g","title":"Digest: mol-deacon-patrol","description":"Patrol #15: Refineries healthy. Beads 5 pending, gastown 1 pending.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:21:32.972503-08:00","updated_at":"2025-12-31T19:21:32.972503-08:00","closed_at":"2025-12-31T19:21:32.972466-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-iwl0e","title":"Missing space in error messages (handoff.go, prime.go)","description":"Minor typo in error messages at two locations:\n\n**handoff.go L895**:\n```go\nfmt.Println(style.Dim.Render(\"Run manually: bd --no-daemon wisp\" + protoID))\n// Missing space before protoID\n```\n\n**prime.go L1061**:\nSame issue.\n\n**Fix**: Add space before protoID:\n```go\nfmt.Println(style.Dim.Render(\"Run manually: bd --no-daemon wisp \" + protoID))\n```","status":"closed","priority":4,"issue_type":"bug","created_at":"2025-12-25T22:03:16.368682-08:00","updated_at":"2025-12-28T22:37:43.897513-08:00","closed_at":"2025-12-28T22:37:43.897513-08:00"} -{"id":"gt-ix1ct","title":"Digest: mol-deacon-patrol","description":"Patrol 56: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:24:07.255681-08:00","updated_at":"2026-01-01T02:24:07.255681-08:00","closed_at":"2026-01-01T02:24:07.255641-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-j0546","title":"Refactor all startup paths to use StartupNudge","description":"## Files to Refactor\n\n| File | Function | Current Approach |\n|------|----------|------------------|\n| start.go:788 | runStartCrew | SendKeys(claude) then SendKeys(gt prime) |\n| start.go:747 | runStartCrew restart | Same |\n| start.go:929 | another path | SendKeys without prime |\n| crew_lifecycle.go:354 | restart | SendKeys(gt prime) after start |\n| crew_lifecycle.go:525 | another path | Same |\n| crew_at.go:154 | --detached | Claude arg \"gt prime\" ✓ |\n| handoff.go:331 | handoff | Claude arg \"gt prime\" ✓ |\n| deacon.go:294 | deacon start | Relies on hooks |\n| witness.go:336 | witness start | Relies on hooks |\n| polecat_spawn.go | spawn | Various |\n\n## Pattern\nReplace scattered logic with:\n```go\ncfg := StartupNudgeConfig{\n Recipient: address,\n Sender: sender,\n Topic: \"cold-start\", // or \"handoff\", mol-id, etc.\n}\nif err := session.StartupNudge(t, sessionName, cfg); err \\!= nil {\n // handle\n}\n```\n\n## Dependencies\n- gt-bgfqy: Create StartupNudge function\n- gt-dc2fs: Add runtime configuration\n","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T22:48:24.460718-08:00","created_by":"stevey","updated_at":"2025-12-30T23:47:58.14419-08:00","closed_at":"2025-12-30T23:47:58.14419-08:00","close_reason":"Refactored all startup paths to use RuntimeConfig and helper functions. Updated 12+ files across cmd/, daemon/, session/, refinery/, and boot/ packages. All hardcoded 'claude --dangerously-skip-permissions' invocations now use config.GetRuntimeCommand(), config.BuildAgentStartupCommand(), config.BuildPolecatStartupCommand(), config.BuildCrewStartupCommand(), or config.BuildStartupCommand(). Build passes, all tests pass.","dependencies":[{"issue_id":"gt-j0546","depends_on_id":"gt-bgfqy","type":"blocks","created_at":"2025-12-30T22:48:44.330738-08:00","created_by":"stevey"},{"issue_id":"gt-j0546","depends_on_id":"gt-dc2fs","type":"blocks","created_at":"2025-12-30T22:48:44.359911-08:00","created_by":"stevey"}]} -{"id":"gt-j0gx2","title":"Day 5.1: End-to-end liftoff test","description":"Full integration test:\n1. gt sling gt-task123 gastown/nux\n2. Watch polecat work (no manual intervention)\n3. Watch refinery merge (no manual intervention)\n4. Watch witness clean up (no manual intervention)\n5. See cycle complete in bd activity or logs\n\nSuccess = no human touches needed.\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:57:54.785993-08:00","created_by":"mayor","updated_at":"2025-12-28T16:26:34.790244-08:00","closed_at":"2025-12-28T16:26:34.790244-08:00","dependencies":[{"issue_id":"gt-j0gx2","depends_on_id":"gt-d0jqp","type":"blocks","created_at":"2025-12-27T20:58:30.581027-08:00","created_by":"daemon"},{"issue_id":"gt-j0gx2","depends_on_id":"gt-hwka3","type":"blocks","created_at":"2025-12-27T20:58:30.630239-08:00","created_by":"daemon"},{"issue_id":"gt-j0gx2","depends_on_id":"gt-4a2qt","type":"blocks","created_at":"2025-12-27T20:58:30.681313-08:00","created_by":"daemon"},{"issue_id":"gt-j0gx2","depends_on_id":"gt-oki8p","type":"parent-child","created_at":"2025-12-27T20:58:39.595164-08:00","created_by":"daemon"},{"issue_id":"gt-j0gx2","depends_on_id":"gt-liftoff","type":"blocks","created_at":"2025-12-27T21:43:01.956869-08:00","created_by":"daemon"},{"issue_id":"gt-j0gx2","depends_on_id":"gt-k5dip","type":"blocks","created_at":"2025-12-28T09:36:51.28648-08:00","created_by":"daemon"}]} -{"id":"gt-j0lsj","title":"Digest: mol-deacon-patrol","description":"Patrol 10: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:17:01.052196-08:00","updated_at":"2025-12-28T08:17:01.052196-08:00","closed_at":"2025-12-28T08:17:01.052165-08:00"} -{"id":"gt-j1i0r","title":"BUG: Daemon doesn't kill zombie tmux sessions before recreating","description":"## Problem\n\nWhen the daemon detects an agent isn't running (per bead state), it tries to create a new session. But if a zombie tmux session exists (session alive, Claude dead), the create fails:\n\n```\n2026/01/02 18:18:20 Witness for gastown not running per agent bead, starting...\n2026/01/02 18:18:20 Error creating witness session for gastown: session already exists\n```\n\n## Root Cause\n\n`gt witness start` (and similar) fail if tmux session exists, even if it's a zombie. The daemon should:\n1. Detect if existing session is responsive\n2. Kill zombie if unresponsive\n3. Create fresh session\n\n## Current Behavior\n\n```go\n// In ensureWitnessRunning or similar:\nif err := tmux.NewSession(sessionName, dir); err != nil {\n // Fails with 'session already exists'\n return err\n}\n```\n\n## Expected Behavior\n\n```go\n// Pseudo-code for 'ensure running' semantics:\nif sessionExists(name) {\n if !isResponsive(name) {\n killSession(name) // Kill zombie\n } else {\n return // Already running and healthy\n }\n}\ncreateSession(name) // Create fresh\n```\n\n## Impact\n\n- Dead witness/refinery stay dead indefinitely\n- Daemon logs fill with 'session already exists' errors\n- Town health degrades with no auto-recovery\n\n## Solution\n\nAdd `ensureSessionFresh()` helper that:\n1. Checks if session exists\n2. If exists, checks if Claude is responsive (look for prompt, or check heartbeat)\n3. Kills zombie sessions\n4. Creates new session only if needed","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/dag","created_at":"2026-01-02T18:42:20.732718-08:00","created_by":"mayor","updated_at":"2026-01-02T18:52:13.100083-08:00","closed_at":"2026-01-02T18:52:13.100083-08:00","close_reason":"Fixed by adding EnsureSessionFresh() helper that kills zombie sessions before recreating. Commit: 3ef732bd"} -{"id":"gt-j36i9","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All agents healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:03:33.755132-08:00","updated_at":"2025-12-28T03:03:33.755132-08:00","closed_at":"2025-12-28T03:03:33.755099-08:00"} -{"id":"gt-j39xc","title":"Merge: capable-mjw47ef9","description":"branch: polecat/capable-mjw47ef9\ntarget: main\nsource_issue: capable-mjw47ef9\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T17:34:31.613661-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-01T19:55:59.959524-08:00","closed_at":"2026-01-01T19:55:59.959524-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-j3cx","title":"refinery Handoff","description":"# Merge queue tracking\nlast_processed_branch: null\nbranches_merged_this_cycle: 0","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-24T23:19:17.135684-08:00","updated_at":"2025-12-26T13:08:21.775778-08:00"} -{"id":"gt-j3z81","title":"Digest: mol-deacon-patrol","description":"Patrol 1 complete: inbox clear, 3 polecats working, fixed 3 stale locks","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:30:25.271821-08:00","updated_at":"2025-12-29T22:30:25.271821-08:00","closed_at":"2025-12-29T22:30:25.271786-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-j4epe","title":"Merge: bullet-farmer","description":"branch: polecat/bullet-farmer-mk0vqzi0\ntarget: main\nsource_issue: bullet-farmer\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:13:15.393797-08:00","created_by":"gastown/polecats/bullet-farmer","updated_at":"2026-01-05T19:40:10.310811-08:00","closed_at":"2026-01-05T19:40:10.310811-08:00","close_reason":"Manually merged"} -{"id":"gt-j4njt","title":"Digest: mol-deacon-patrol","description":"Patrol 11: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:07:40.158577-08:00","updated_at":"2025-12-28T03:07:40.158577-08:00","closed_at":"2025-12-28T03:07:40.158546-08:00"} -{"id":"gt-j5rk9","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:51:40.367393-08:00","updated_at":"2026-01-01T00:51:40.367393-08:00","closed_at":"2026-01-01T00:51:40.367359-08:00"} -{"id":"gt-j82oi","title":"GAP: wisp-gc should check main beads for wisp patterns","description":"The gt doctor wisp-gc check only looks at .beads-wisp/ directory. It should also scan main beads for wisp patterns (hq-wisp-*, *-wisp-*) that were incorrectly filed.\n\nProposed fix: Add to wisp-gc check:\n- Scan issues table for IDs matching wisp patterns\n- If found, report as error (wisps in wrong location)\n- Offer to delete them with --fix\n\nThis would catch the bug where 128 wisps ended up in main beads.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T20:38:49.748337-08:00","created_by":"mayor","updated_at":"2026-01-04T21:58:17.151338-08:00","closed_at":"2026-01-04T21:58:17.151338-08:00","close_reason":"Invalid: Wisps now live in main beads. .beads-wisp/ was eradicated."} -{"id":"gt-j8uz5","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, 0 inbox messages, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:08:19.406221-08:00","updated_at":"2025-12-31T22:08:19.406221-08:00","closed_at":"2025-12-31T22:08:19.406184-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-j9ddg","title":"Day 4.1: Implement gt polecat recycle command","description":"Add gt polecat recycle \u003cname\u003e command:\n- Kill the Claude session (tmux kill-session)\n- Preserve the sandbox (branch/worktree)\n- Update agent bead state to 'stopped'\n- Leave for respawn on next step\n\nThis enables session-per-step.\n\nParent: gt-4a2qt","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:03.333223-08:00","created_by":"mayor","updated_at":"2025-12-28T14:15:41.564143-08:00","closed_at":"2025-12-28T14:15:41.564143-08:00","dependencies":[{"issue_id":"gt-j9ddg","depends_on_id":"gt-4a2qt","type":"parent-child","created_at":"2025-12-27T20:58:42.973474-08:00","created_by":"daemon"},{"issue_id":"gt-j9ddg","depends_on_id":"gt-7psb8","type":"blocks","created_at":"2025-12-27T21:00:55.776156-08:00","created_by":"daemon"}]} -{"id":"gt-ja5xm","title":"Digest: mol-deacon-patrol","description":"Patrol 250 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:21:18.22468-08:00","updated_at":"2026-01-01T17:21:18.22468-08:00","closed_at":"2026-01-01T17:21:18.224642-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jc7bq","title":"BUG: Hook not cleared when issue closed","description":"## Problem\n\nWhen an issue is closed (via `bd close` or MR merge), the hook is not cleared on the polecat that was working on it. This causes:\n\n1. `gt polecat nuke` safety check to fail ('has work on hook')\n2. Confusing state where polecat shows work but issue is closed\n\n## Observed Behavior\n\n```\ngt polecat nuke gastown/chrome --dry-run\nSafety checks:\n - Hook: has work (gt-rsnj9) # But gt-rsnj9 is CLOSED\n```\n\n## Expected Behavior\n\nWhen `bd close \u003cid\u003e` is called:\n- If that issue is hooked by any agent, the hook should be cleared\n- Or: The nuke safety check should verify hook status, not just presence\n\n## Related\n\n- gt-h3gzj (auto-nuke bug) - this compounds that issue","status":"open","priority":2,"issue_type":"bug","created_at":"2026-01-05T00:41:18.471766-08:00","created_by":"mayor","updated_at":"2026-01-05T00:41:18.471766-08:00"} -{"id":"gt-jcro2","title":"Digest: mol-deacon-patrol","description":"Patrol 101: All agents healthy, 3 rigs checked, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:57:30.030283-08:00","updated_at":"2026-01-01T13:57:30.030283-08:00","closed_at":"2026-01-01T13:57:30.030244-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jcrvm","title":"Digest: mol-deacon-patrol","description":"Patrol 80: Routine, completing 20-cycle handoff","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:05:01.292773-08:00","updated_at":"2025-12-31T15:05:01.292773-08:00","closed_at":"2025-12-31T15:05:01.292735-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jdgz5","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:09:55.892224-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:09:55.943679-08:00","closed_at":"2026-01-06T13:09:55.943679-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:09:55-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-jdn2t","title":"Fix deprecated strings.Title in formula.go","description":"formula.go uses deprecated strings.Title (Go 1.18+). Should use cases.Title(language.English).String() from golang.org/x/text/cases.","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2026-01-01T15:00:58.54137-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T19:13:45.564757-08:00","closed_at":"2026-01-01T19:13:45.564757-08:00","close_reason":"Replaced deprecated strings.Title with cases.Title from golang.org/x/text"} -{"id":"gt-jdt2t","title":"DRY: Duplicate payload formatting/parsing in protocol/messages.go","description":"The protocol/messages.go file has duplicate patterns:\n\n**Formatting functions** (lines 38-48, 78-90, 121-132, 163-180):\nformatMergeReadyBody, formatMergedBody, formatMergeFailedBody, formatReworkRequestBody all follow identical pattern:\n```go\nvar sb strings.Builder\nsb.WriteString(fmt.Sprintf(\"Field: %s\\n\", p.Field))\n// repeat for each field\nreturn sb.String()\n```\n\n**Parsing functions** (lines 195-272):\nParseMergeReadyPayload, ParseMergedPayload, ParseMergeFailedPayload, ParseReworkRequestPayload all call parseField repeatedly.\n\nConsider using struct tags with reflection or code generation.\n\nFiles:\n- internal/protocol/messages.go:38-48, 78-90, 121-132, 163-180, 195-272\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:03.96295-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:47:03.96295-08:00"} -{"id":"gt-jf6ls","title":"Merge: warboy-mjz94u1q","description":"branch: polecat/warboy-mjz94u1q\ntarget: main\nsource_issue: warboy-mjz94u1q\nrig: gastown\nagent_bead: gt-gastown-polecat-warboy\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:35:04.769194-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T10:39:31.840052-08:00","closed_at":"2026-01-04T10:39:31.840052-08:00","close_reason":"Already merged to main at 36301adf"} -{"id":"gt-jf79d","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 6 agents healthy, inbox clean, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:18:51.527121-08:00","updated_at":"2026-01-01T10:18:51.527121-08:00","closed_at":"2026-01-01T10:18:51.527084-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jhr85","title":"gt crew add should provision .claude/commands/","description":"When adding a crew member with 'gt crew add', provision the .claude/commands/ directory with standard commands like handoff.md.\n\nCurrently only polecats get this via the spawning process. Crew members are added manually and miss out on slash commands like /handoff.\n\nAlso: gt doctor should detect missing .claude/commands/ in crew directories and offer to fix.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/slit","created_at":"2026-01-02T00:01:01.060429-08:00","created_by":"beads/crew/dave","updated_at":"2026-01-02T17:21:50.167907-08:00","closed_at":"2026-01-02T17:21:50.167907-08:00","close_reason":"Implemented commands provisioning for crew and polecat workspaces"} -{"id":"gt-jhsa","title":"Deacon has no rig-level presence - only global gt-deacon","description":"The Deacon patrol role exists only at the global level (~/gt/deacon) but doesn't have per-rig presence like Witness and Refinery.\n\nCurrent structure:\n```\n~/gt/\n├── deacon/ ← Global deacon only\n├── beads/\n│ ├── witness/ ← Per-rig witness\n│ ├── refinery/ ← Per-rig refinery\n│ └── (no deacon) ← Missing\n└── gastown/\n ├── witness/\n ├── refinery/\n └── (no deacon) ← Missing\n```\n\nQuestion: Should Deacon be per-rig like Witness/Refinery, or is global-only intentional?\n\nIf per-rig is needed: Create beads/deacon and gastown/deacon with appropriate CLAUDE.md files.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T20:29:59.121615-08:00","updated_at":"2025-12-23T20:29:59.121615-08:00"} -{"id":"gt-jhvzy","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 34: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:32:41.624777-08:00","updated_at":"2026-01-01T12:32:41.624777-08:00","closed_at":"2026-01-01T12:32:41.624737-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jie2g","title":"Digest: mol-deacon-patrol","description":"Patrol 19 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:48:25.61232-08:00","updated_at":"2025-12-31T16:48:25.61232-08:00","closed_at":"2025-12-31T16:48:25.612284-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jju6v","title":"Digest: mol-deacon-patrol","description":"Patrol 5","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:49:46.93586-08:00","updated_at":"2026-01-01T08:49:46.93586-08:00","closed_at":"2026-01-01T08:49:46.935827-08:00"} -{"id":"gt-jkjhj","title":"Digest: mol-deacon-patrol","description":"Patrol 256 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:23:52.683667-08:00","updated_at":"2026-01-01T17:23:52.683667-08:00","closed_at":"2026-01-01T17:23:52.683629-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jl4ze","title":"Merge: dementus-1767084022436","description":"branch: polecat/dementus-1767084022436\ntarget: main\nsource_issue: dementus-1767084022436\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:49:44.389494-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T01:01:04.218769-08:00","closed_at":"2025-12-30T01:01:04.218769-08:00","close_reason":"Already merged to main"} -{"id":"gt-jlvch","title":"Digest: mol-deacon-patrol","description":"Patrol 93: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:24:27.412891-08:00","updated_at":"2025-12-31T15:24:27.412891-08:00","closed_at":"2025-12-31T15:24:27.412853-08:00"} -{"id":"gt-jn0zb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:29:42.216657-08:00","updated_at":"2025-12-31T23:29:42.216657-08:00","closed_at":"2025-12-31T23:29:42.21662-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jntch","title":"Digest: mol-refinery-patrol","description":"Patrol: empty queue, inbox clean, no orphaned MRs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T01:35:57.320433-08:00","updated_at":"2025-12-31T01:35:57.320433-08:00","closed_at":"2025-12-31T01:35:57.320397-08:00","close_reason":"Squashed from 11 wisps"} -{"id":"gt-jnzud","title":"Merge: wretched-mk0ujl0q","description":"branch: polecat/wretched-mk0ujl0q\ntarget: main\nsource_issue: wretched-mk0ujl0q\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T23:40:54.673924-08:00","created_by":"gastown/polecats/wretched","updated_at":"2026-01-05T00:14:14.520702-08:00","closed_at":"2026-01-05T00:14:14.520702-08:00","close_reason":"Merged to main at 2141be76"} -{"id":"gt-jodf8","title":"Digest: mol-deacon-patrol","description":"Cycle 14: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:22:55.175328-08:00","updated_at":"2025-12-28T13:22:55.175328-08:00","closed_at":"2025-12-28T13:22:55.175296-08:00"} -{"id":"gt-jol5y","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:36:30.374929-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.359395-08:00","closed_at":"2026-01-04T16:40:13.359395-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:36:30-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-jq62f","title":"Digest: mol-deacon-patrol","description":"Patrol 5 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:42:05.691073-08:00","updated_at":"2025-12-31T16:42:05.691073-08:00","closed_at":"2025-12-31T16:42:05.691039-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jq8i4","title":"Auto-create convoy when slinging single issue","description":"When gt sling is used without an existing convoy context, auto-create one for dashboard visibility.\n\nCURRENT:\ngt sling bd-xyz beads/amber\n# Issue assigned, but not tracked in convoy dashboard\n\nDESIRED:\ngt sling bd-xyz beads/amber\n# -\u003e Created convoy 'Work: bd-xyz' (hq-cv-xxx)\n# -\u003e Tracking bd-xyz\n# -\u003e Assigned to beads/amber\n\nThis ensures ALL work appears in gt convoy list, even 'swarm of one'.\n\nIMPLEMENTATION:\nFile: internal/cmd/sling.go\n1. Check if issue is already tracked by a convoy\n2. If not, create convoy with title 'Work: \u003cissue-title\u003e'\n3. Add tracks relation\n4. Proceed with normal sling\n\nOPTIONAL FLAG:\n--no-convoy to skip auto-convoy creation","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2025-12-30T19:37:27.039315-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-31T14:01:45.283912-08:00","closed_at":"2025-12-31T14:01:45.283912-08:00","close_reason":"Implemented auto-convoy creation in gt sling"} -{"id":"gt-jqwhq","title":"Digest: mol-deacon-patrol","description":"Patrol 15: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:32:29.145395-08:00","updated_at":"2026-01-01T04:32:29.145395-08:00","closed_at":"2026-01-01T04:32:29.145358-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jrpmc","title":"Digest: mol-deacon-patrol","description":"Patrol #19","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:24:33.706717-08:00","updated_at":"2025-12-31T06:24:33.706717-08:00","closed_at":"2025-12-31T06:24:33.706684-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jsm2s","title":"SQL injection in convoy.go:581","description":"User input interpolated directly into SQL via fmt.Sprintf(). convoyID from args[0] used in: fmt.Sprintf(`SELECT depends_on_id, type FROM dependencies WHERE issue_id = '%s'`, convoyID). Fix: Use parameterized queries.","status":"closed","priority":0,"issue_type":"bug","created_at":"2026-01-01T10:55:09.10721-08:00","created_by":"mayor","updated_at":"2026-01-01T11:02:14.338923-08:00","closed_at":"2026-01-01T11:02:14.338923-08:00","close_reason":"Fixed: escape single quotes in SQL query"} -{"id":"gt-jsoiw","title":"Merge: dag-1767146241770","description":"branch: polecat/dag-1767146241770\ntarget: main\nsource_issue: dag-1767146241770\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:03:10.023436-08:00","created_by":"gastown/polecats/dag","updated_at":"2025-12-30T18:23:22.110363-08:00","closed_at":"2025-12-30T18:23:22.110363-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-jutmn","title":"Digest: mol-deacon-patrol","description":"Patrol 6: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:25:25.73163-08:00","updated_at":"2026-01-01T04:25:25.73163-08:00","closed_at":"2026-01-01T04:25:25.731595-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jv6yf","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:58:45.397319-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.466268-08:00","closed_at":"2026-01-05T00:08:31.466268-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:58:44-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-jw6gp","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all healthy, no events","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:35:29.232612-08:00","updated_at":"2025-12-31T21:35:29.232612-08:00","closed_at":"2025-12-31T21:35:29.232577-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jw8uf","title":"Digest: mol-deacon-patrol","description":"Patrol 12: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:30:14.44076-08:00","updated_at":"2026-01-01T04:30:14.44076-08:00","closed_at":"2026-01-01T04:30:14.440719-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-jwibh","title":"Digest: mol-deacon-patrol","description":"Cycle 190: 10-cycle checkpoint, all agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:22:48.243938-08:00","updated_at":"2026-01-01T16:22:48.243938-08:00","closed_at":"2026-01-01T16:22:48.243905-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-jwibh","depends_on_id":"gt-eph-e6o6","type":"parent-child","created_at":"2026-01-01T16:22:48.245357-08:00","created_by":"deacon"}]} -{"id":"gt-jwxgb","title":"Crew startup missing metadata injection for gt seance","description":"When crew members are started via 'gt crew start', they don't receive the metadata string that gt seance uses to identify running sessions. This makes it harder to track which crew sessions are active.\n\nThe metadata injection should happen during crew startup similar to how other agent types get their identifiers injected.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-02T17:37:10.407081-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-02T17:42:40.134199-08:00","closed_at":"2026-01-02T17:42:40.134199-08:00","close_reason":"Fixed - now uses BuildCrewStartupCommand for proper env var injection"} -{"id":"gt-jx2ov","title":"Digest: mol-deacon-patrol","description":"Patrol 9: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:11:54.653603-08:00","updated_at":"2026-01-01T08:11:54.653603-08:00","closed_at":"2026-01-01T08:11:54.653567-08:00"} -{"id":"gt-jxg0u","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All healthy - 19 polecats, witness/refinery running, 3 MQ items, no zombies","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:30:57.137988-08:00","updated_at":"2026-01-01T23:30:57.137988-08:00","closed_at":"2026-01-01T23:30:57.137951-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-jyzrs","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:35.34827-08:00","updated_at":"2025-12-28T11:22:35.34827-08:00","closed_at":"2025-12-28T11:22:35.348237-08:00"} -{"id":"gt-jzf10","title":"Digest: mol-deacon-patrol","description":"Patrol 4: quiet, health OK","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:43:56.967373-08:00","updated_at":"2025-12-28T19:43:56.967373-08:00","closed_at":"2025-12-28T19:43:56.967337-08:00"} -{"id":"gt-jzmsj","title":"Platform of Platforms (POP) Foundation","description":"Design and implementation of the Platform Adapter Layer for HOP. Enables multiple work platforms to integrate with the universal work ledger. See ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md for full architecture.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-30T12:55:50.682348-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T12:55:50.682348-08:00","dependencies":[{"issue_id":"gt-jzmsj","depends_on_id":"gt-6r18e","type":"blocks","created_at":"2025-12-30T12:56:24.910115-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-jzmsj.1","title":"Define PlatformAdapter interface","description":"Define the PlatformAdapter interface in Go. The interface specification is already\ndocumented in ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md (lines 118-152).\n\n**Location**: Create `internal/hop/platform.go` in the beads repo\n\n**Interface methods** (from doc):\n- Registration: GetPlatformID, GetPlatformMetadata\n- Identity: MapIdentity, GetSovereigntyTier, ResolveEntity\n- Work Translation: TranslateWorkUnit, TranslateToNative\n- Validation: SubmitCompletion, QueryValidations\n- Skills: ExtractSkills, GetSkillOntology\n- Governance: GetPlatformRules, ValidateWork\n- Payment (optional): GetPaymentRails, RecordPayment\n- Federation: GetFederationEndpoint, CanFederateWith\n\n**Supporting types needed**:\n- SovereigntyTier enum (see gt-jzmsj.2)\n- PlatformMetadata struct\n- HopEntity (maps to existing EntityRef)\n- HopWorkUnit (maps to existing Issue/Bead)\n- ValidationRecord (maps to existing Validation)\n- SkillVector, SkillOntology (stub for now)\n- GovernanceRules, Violation\n- PaymentRail, Payment, Receipt\n\n**Acceptance criteria**:\n1. Interface compiles and is documented\n2. Types compile with reasonable defaults\n3. No implementation yet - interface only","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-30T12:56:07.313809-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:53:37.225795-08:00","dependencies":[{"issue_id":"gt-jzmsj.1","depends_on_id":"gt-jzmsj","type":"parent-child","created_at":"2025-12-30T12:56:07.314326-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-jzmsj.2","title":"Add sovereignty tier to entity model","description":"Add SovereigntyTier to the entity model. This determines what identity information\nis revealed and to whom.\n\n**Location**: beads repo, `internal/types/types.go`\n\n**Changes required**:\n\n1. Add SovereigntyTier type and constants:\n```go\ntype SovereigntyTier string\n\nconst (\n TierPublic SovereigntyTier = \"public\" // Full legal identity, full visibility\n TierOrganizational SovereigntyTier = \"organizational\" // Known to org, private outside\n TierPseudonymous SovereigntyTier = \"pseudonymous\" // KYC verified, operates under handle\n TierAnonymous SovereigntyTier = \"anonymous\" // Cryptographic identity only\n)\n```\n\n2. Add field to EntityRef:\n```go\ntype EntityRef struct {\n // ... existing fields ...\n SovereigntyTier SovereigntyTier `json:\"sovereignty_tier,omitempty\"`\n}\n```\n\n3. Add IsValid() method to SovereigntyTier\n\n4. Update ComputeContentHash to include sovereignty tier\n\n**Acceptance criteria**:\n1. SovereigntyTier type with 4 values defined\n2. EntityRef has optional sovereignty_tier field\n3. Empty/missing tier defaults to \"public\" (backward compatible)\n4. Content hash includes sovereignty tier\n5. Tests pass","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-30T12:56:08.356115-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:53:56.890333-08:00","dependencies":[{"issue_id":"gt-jzmsj.2","depends_on_id":"gt-jzmsj","type":"parent-child","created_at":"2025-12-30T12:56:08.358195-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-jzmsj.3","title":"Gas Town as reference platform adapter","description":"Implement Gas Town as the reference PlatformAdapter. This proves the interface works\nand serves as a template for other platforms.\n\n**Depends on**: gt-jzmsj.1 (interface must exist first)\n\n**Location**: gastown repo, `internal/hop/gastown_adapter.go`\n\n**Implementation mapping** (from ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md lines 381-398):\n- Platform ID: \"gastown\"\n- Sovereignty: Tier 2-3 (organizational/pseudonymous)\n- Identity: Map BD_ACTOR format (rig/role/name) → HOP EntityRef\n- Work Units: Beads (issues, molecules) → HopWorkUnit\n- Validation: Refinery approvals → ValidationRecord\n- Skills: Stub returning empty (future work)\n- Governance: Return GUPP rules reference\n- Payment: Return nil (future work)\n- Federation: Return town URI\n\n**Key mappings**:\n- Issue → HopWorkUnit (1:1, most fields align)\n- BD_ACTOR \"gastown/crew/max\" → EntityRef{Platform: \"gastown\", Org: \"steveyegge\", ID: \"crew-max\"}\n- Validation struct → ValidationRecord (already aligned)\n\n**Acceptance criteria**:\n1. GasTownAdapter implements PlatformAdapter interface\n2. MapIdentity correctly parses BD_ACTOR format\n3. TranslateWorkUnit converts Issue to HopWorkUnit\n4. Basic test coverage","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-30T12:56:09.622173-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:54:00.169277-08:00","dependencies":[{"issue_id":"gt-jzmsj.3","depends_on_id":"gt-jzmsj","type":"parent-child","created_at":"2025-12-30T12:56:09.622685-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-jzmsj.3","depends_on_id":"gt-jzmsj.1","type":"blocks","created_at":"2025-12-31T12:53:35.832403-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-jzmsj.4","title":"Design skill ontology for cross-platform matching","description":"Design the universal skill vocabulary that maps across platforms. This enables\nmatching workers to work across platform boundaries.\n\n**Reference**: ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md (lines 331-357)\n\n**Deliverable**: Design document defining:\n\n1. **Skill representation**:\n - SkillVector struct (skill ID, level 0-5, evidence count, attestation count)\n - How levels are derived from work history\n - How attestations compound across platforms\n\n2. **Ontology structure**:\n - Hierarchical skill taxonomy (e.g., Programming \u003e Go \u003e Concurrency)\n - Cross-platform skill equivalence mappings\n - Confidence scores for derived skills\n\n3. **Extraction algorithm**:\n - How to derive skills from work units (keywords, labels, validation)\n - How to aggregate across platforms\n - Decay model for stale skills\n\n4. **Example mappings**:\n - GitHub: languages, frameworks from commits/PRs\n - Enterprise: role competencies, certifications\n - Gas Town: labels, successful completions\n\n**Acceptance criteria**:\n1. Design doc in ~/gt/docs/hop/SKILL-ONTOLOGY.md\n2. SkillVector and SkillOntology types sketched\n3. Algorithm pseudocode for skill extraction\n4. Example aggregation scenario","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-30T12:56:10.572643-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:54:21.414634-08:00","dependencies":[{"issue_id":"gt-jzmsj.4","depends_on_id":"gt-jzmsj","type":"parent-child","created_at":"2025-12-30T12:56:10.57466-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-jzmsj.5","title":"RPG platform design: gamification layer","description":"Design the RPG UX metaphor - the flagship consumer experience for HOP.\nMakes real work feel like a game because the game IS real work.\n\n**Reference**: ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md (lines 188-214)\n\n**Deliverable**: Design document defining:\n\n1. **Core metaphor mappings**:\n - Quests = Work units (beads/issues)\n - Skills = Stats derived from work history\n - Leveling = Reputation accumulation\n - Guilds = Organizations\n - Loot = Payment/rewards\n\n2. **Progression mechanics**:\n - XP calculation from work completions\n - Skill tree visualization\n - Level thresholds and prestige ranks\n - Achievement system\n\n3. **Social features**:\n - Guild formation and management\n - Leaderboards (opt-in, privacy-aware)\n - Cooperative quests (swarming as raids)\n - Mentorship system\n\n4. **Engagement hooks**:\n - Daily/weekly quest boards\n - Streak bonuses\n - Rare quest discovery\n - Boss battles (epic issues)\n\n5. **Why it works**:\n - Progress feels real because it IS real\n - Stats are accurate because they're derived from actual work\n - Social proof from genuine collaboration\n\n**Acceptance criteria**:\n1. Design doc in ~/gt/docs/hop/RPG-PLATFORM.md\n2. Core metaphor mappings defined\n3. UI/UX wireframes or mockup descriptions\n4. Privacy model (what's public vs. private\nEOF\n)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-30T12:56:12.984781-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T12:54:22.776376-08:00","dependencies":[{"issue_id":"gt-jzmsj.5","depends_on_id":"gt-jzmsj","type":"parent-child","created_at":"2025-12-30T12:56:12.986894-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-jzsgv","title":"Digest: mol-deacon-patrol","description":"Patrol 2 complete. All agents healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:39:22.653805-08:00","updated_at":"2025-12-31T16:39:22.653805-08:00","closed_at":"2025-12-31T16:39:22.653769-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-k0yzk","title":"Merge: slit-mjxlyyte","description":"branch: polecat/slit-mjxlyyte\ntarget: main\nsource_issue: slit-mjxlyyte\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:22:18.97881-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T17:29:03.540501-08:00","closed_at":"2026-01-02T17:29:03.540501-08:00","close_reason":"Merged to main at f4a82337"} -{"id":"gt-k1sg1","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:45:30.158391-08:00","updated_at":"2026-01-01T07:45:30.158391-08:00","closed_at":"2026-01-01T07:45:30.15835-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-k1sl4","title":"gt doctor: Add Boot health check (vet mode)","description":"gt doctor should check Boot health:\n- Is Boot directory present?\n- Is Boot session alive?\n- Last execution status (success/error)\n- Marker file freshness\n\nThe vet checks on the dog.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-30T21:54:39.459476-08:00","created_by":"mayor","updated_at":"2025-12-30T21:59:31.508898-08:00","closed_at":"2025-12-30T21:59:31.508898-08:00","close_reason":"Implemented Boot health check in gt doctor"} -{"id":"gt-k23xf","title":"Digest: mol-deacon-patrol","description":"Cycle 297: All healthy, refinery busy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:44:24.504682-08:00","updated_at":"2026-01-01T18:44:24.504682-08:00","closed_at":"2026-01-01T18:44:24.504629-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-k23xf","depends_on_id":"gt-eph-fxb7","type":"parent-child","created_at":"2026-01-01T18:44:24.505995-08:00","created_by":"deacon"}]} -{"id":"gt-k294l","title":"Day 3.0: Document mail protocol for patrol coordination","description":"Document the mail protocol used for patrol coordination.\n\n**Mail types:**\n- POLECAT_DONE: Polecat → Witness (work complete, ready for merge)\n- MERGE_READY: Witness → Refinery (branch ready for merge queue)\n- MERGED: Refinery → Witness (merge complete, safe to nuke)\n- WITNESS_PING: Witness → Deacon (health check for second-order monitoring)\n- HELP: Any → escalation target (stuck, need intervention)\n- HANDOFF: Any → self (session continuity)\n\n**Format conventions:**\n- Subject prefix indicates type (e.g., 'POLECAT_DONE: nux')\n- Body contains structured data (branch, bead ID, etc.)\n\nThis documentation enables consistent implementation across all patrol formulas.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T23:17:11.657593-08:00","created_by":"mayor","updated_at":"2025-12-28T00:04:01.333366-08:00","closed_at":"2025-12-28T00:04:01.333366-08:00"} -{"id":"gt-k2hir","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:11:04.189125-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.678972-08:00","closed_at":"2026-01-05T00:08:31.678972-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:11:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-k3j31","title":"Session ended: gt-gastown-dinki","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:27:09.605414-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-04T16:40:13.490982-08:00","closed_at":"2026-01-04T16:40:13.490982-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/dinki","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:27:09-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-dinki\",\"worker\":\"dinki\"}"} -{"id":"gt-k3q9k","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:08:26.474426-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.708377-08:00","closed_at":"2026-01-05T00:08:31.708377-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:08:26-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-k52sc","title":"Session ended: gt-gastown-furiosa","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:31:14.257871-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-05T19:44:18.596639-08:00","closed_at":"2026-01-05T19:44:18.596639-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/furiosa","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:31:14-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-furiosa\",\"worker\":\"furiosa\"}"} -{"id":"gt-k5dip","title":"Day 5.0: gt status shows pinned role beads and slots","description":"Enhance gt status to display:\n- All pinned role beads (mayor, witness, refinery, polecats)\n- Their current hook slot contents (what molecule/bead is attached)\n- Agent state if available\n\nThis gives a single-command view of who's working on what across the town.\n\nExample output:\n```\ngt status\n\nTown: gastown\nDaemon: running (pid 1234)\n\nAgents:\n mayor/ gt-liftoff (pinned) idle\n witness/gastown gt-wisp-abc (patrol) running\n refinery/gastown (empty) idle\n polecat/nux gt-xyz (in_progress) working\n polecat/rictus (empty) idle\n```","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T09:36:43.017277-08:00","created_by":"mayor","updated_at":"2025-12-28T09:43:37.543526-08:00","closed_at":"2025-12-28T09:43:37.543526-08:00","dependencies":[{"issue_id":"gt-k5dip","depends_on_id":"gt-d0jqp","type":"blocks","created_at":"2025-12-28T09:36:51.257401-08:00","created_by":"daemon"}]} -{"id":"gt-k632y","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:29:09.3072-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:41.828607-08:00","closed_at":"2026-01-05T19:44:41.828607-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:29:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-k6986","title":"Digest: mol-deacon-patrol","description":"Patrol 9: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:56:43.09177-08:00","updated_at":"2025-12-26T13:56:43.09177-08:00","closed_at":"2025-12-26T13:56:43.091735-08:00"} -{"id":"gt-k7v2m","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 51: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:57:06.524342-08:00","updated_at":"2026-01-01T12:57:06.524342-08:00","closed_at":"2026-01-01T12:57:06.524308-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-k8dn4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:35:25.150369-08:00","updated_at":"2025-12-31T23:35:25.150369-08:00","closed_at":"2025-12-31T23:35:25.15033-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-k8j6m","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:49:37.77966-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:18.544277-08:00","closed_at":"2026-01-05T19:44:18.544277-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:49:32-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-k91dd","title":"Digest: mol-deacon-patrol","description":"Patrol #2: All systems nominal, 3 convoys active, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:18:01.755568-08:00","updated_at":"2025-12-31T06:18:01.755568-08:00","closed_at":"2025-12-31T06:18:01.755533-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-k9828","title":"Digest: mol-deacon-patrol","description":"Patrol 18: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:19:54.510894-08:00","updated_at":"2025-12-25T10:19:54.510894-08:00","closed_at":"2025-12-25T10:19:54.510865-08:00"} -{"id":"gt-ka49w","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:42:20.484895-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T21:42:20.53301-08:00","closed_at":"2026-01-05T21:42:20.53301-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:42:20-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-kab2p","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:18:54.530142-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.839846-08:00","closed_at":"2026-01-05T00:08:31.839846-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:18:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-kabx","title":"Build context self-check into patrol molecules","description":"Patrol molecules (witness-patrol, refinery-patrol, deacon-patrol) should have\nexplicit context self-check as part of each cycle:\n\nAfter each patrol cycle step:\n- Self-assess context pressure\n- If high: complete current step, then initiate handoff\n- If OK: continue to next cycle\n\nThis could be:\n1. Explicit step in molecule: 'context-check'\n2. Guidance in step instructions: 'Before continuing, assess context...'\n3. Protocol baked into the patrol loop description\n\nThe key is making it unavoidable - not optional guidance that gets ignored.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:46:57.067465-08:00","updated_at":"2025-12-23T01:46:57.067465-08:00"} -{"id":"gt-kaox7","title":"Document StartupNudge format in seance/session docs","description":"\n## Context\n\nThe StartupNudge migration (gt-7pp3l) changed the session title format used for predecessor discovery.\n\n## Format Change\n\n```\nOld: [GAS TOWN] address • molID • timestamp\nNew: [GAS TOWN] recipient \u003c- sender • timestamp • topic[:mol-id]\n```\n\n## Documentation Needed\n\n1. Update any docs referencing the old SessionBeacon format\n2. Document the sender values and when each is used:\n - human: crew, mayor (human-managed)\n - daemon: deacon\n - deacon: witness\n - witness: polecats\n - self: handoff\n3. Document the topic values:\n - cold-start, restart, refresh, patrol, assigned, dispatch, handoff\n\n## Files to Check\n\n- docs/understanding-gas-town.md\n- docs/reference.md\n- Role templates in internal/templates/\n\n## Related\n\n- gt-7pp3l: Migrate startup paths from SessionBeacon to StartupNudge\n- gt-7qvd7: gt seance command\n","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-31T12:20:34.87314-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-31T12:26:54.989046-08:00","closed_at":"2025-12-31T12:26:54.989046-08:00","close_reason":"Removed SessionBeacon and documented StartupNudge format in reference.md"} -{"id":"gt-kbvbb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:19:31.842546-08:00","updated_at":"2026-01-01T07:19:31.842546-08:00","closed_at":"2026-01-01T07:19:31.84251-08:00"} -{"id":"gt-kc7yj","title":"Swarm-in-Beads: Discovery-based swarm execution","description":"Swarm-in-Beads: Make swarm state derive from beads, not separate JSON. See ~/gt/docs/swarm-architecture.md for full design. Core principles: discovery over tracking, ready front model, nondeterministic idempotence.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-28T19:10:08.780837-08:00","created_by":"mayor","updated_at":"2025-12-29T17:55:08.900851-08:00","closed_at":"2025-12-29T17:55:08.900851-08:00","close_reason":"All children complete: swarm state now discovered from beads, Manager stateless, legacy swarms.json deleted"} -{"id":"gt-kc7yj.1","title":"Refactor gt swarm to use beads backing","description":"Migrate gt swarm commands from .runtime/swarms.json to beads molecules.\n\nCurrent gt swarm stores state in .runtime/swarms.json - violating discovery over tracking.\nThe refactored version should use bd swarm create/status to work with beads molecules.\n\nImplementation:\n- gt swarm create calls bd swarm create\n- gt swarm status calls bd swarm status \n- gt swarm list queries bd list --mol-type=swarm\n- Remove .runtime/swarms.json dependency\n\nCROSS-RIG DEPENDENCIES (must complete first in beads repo):\n- bd-oxgi: mol_type schema field\n- bd-fa1q: bd swarm create command\n- bd-5x0j: bd swarm status command\n\nReference: ~/gt/docs/swarm-architecture.md","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T19:12:19.675605-08:00","created_by":"mayor","updated_at":"2025-12-28T22:05:51.723695-08:00","closed_at":"2025-12-28T22:05:51.723695-08:00","dependencies":[{"issue_id":"gt-kc7yj.1","depends_on_id":"gt-kc7yj","type":"parent-child","created_at":"2025-12-28T19:12:19.676106-08:00","created_by":"daemon"}]} -{"id":"gt-kc7yj.2","title":"Witness swarm integration","description":"Add swarm coordination to Witness patrol.\n\nThe Witness should be able to:\n1. Receive swarm assignments via mail (SWARM: subject prefix)\n2. Query ready front and dispatch to available polecats\n3. Monitor polecat progress on swarm tasks\n4. Detect completion and close swarm molecule\n5. Use Christmas Ornament pattern for arm-bonding (optional)\n\nImplementation:\n- Add swarm handling to mol-witness-patrol formula\n- Mail trigger: SWARM in subject\n- Dispatch: bd ready --parent=\u003cepic\u003e to find ready issues\n- Assign: gt sling \u003cissue\u003e to available polecat\n- Monitor: Check polecat status during patrol\n- Complete: When bd ready --parent returns empty and all closed\n\nReference: ~/gt/docs/swarm-architecture.md - Witness Integration section\n\nDependencies: gt-kc7yj.1 (gt swarm refactor)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T19:12:41.909263-08:00","created_by":"mayor","updated_at":"2025-12-29T14:21:32.739182-08:00","closed_at":"2025-12-29T14:21:32.739182-08:00","close_reason":"Added dispatch-swarm-work step to mol-witness-patrol formula. Witness can now dispatch ready swarm tasks to idle polecats via gt sling.","dependencies":[{"issue_id":"gt-kc7yj.2","depends_on_id":"gt-kc7yj","type":"parent-child","created_at":"2025-12-28T19:12:41.909767-08:00","created_by":"daemon"},{"issue_id":"gt-kc7yj.2","depends_on_id":"gt-kc7yj.1","type":"blocks","created_at":"2025-12-28T19:12:53.340127-08:00","created_by":"daemon"}]} -{"id":"gt-kc7yj.3","title":"Swarm completion detection and auto-close","description":"Detect when all epic children are closed and auto-close the swarm molecule.\n\nCore logic:\n1. After any issue closes, check if it was part of a swarm\n2. Query bd list --parent=\u003cepic\u003e --status=open\n3. If empty (all closed), close the swarm molecule\n4. Fire completion event for activity feed\n\nCan be implemented as:\n- Part of Witness patrol\n- Or as a bd hook triggered on issue close\n- Or as a gt swarm check command called periodically\n\nReference: ~/gt/docs/swarm-architecture.md - Recovery Protocol\n\nDependencies: gt-kc7yj.1 (gt swarm refactor)","status":"closed","priority":1,"issue_type":"task","assignee":"mayor","created_at":"2025-12-28T19:12:42.759032-08:00","created_by":"mayor","updated_at":"2025-12-29T15:20:53.030161-08:00","closed_at":"2025-12-29T15:20:53.030161-08:00","close_reason":"Implemented swarm completion detection and auto-close in Witness patrol formula","dependencies":[{"issue_id":"gt-kc7yj.3","depends_on_id":"gt-kc7yj","type":"parent-child","created_at":"2025-12-28T19:12:42.759587-08:00","created_by":"daemon"},{"issue_id":"gt-kc7yj.3","depends_on_id":"gt-kc7yj.1","type":"blocks","created_at":"2025-12-28T19:12:53.36878-08:00","created_by":"daemon"}]} -{"id":"gt-kc7yj.4","title":"End-to-end swarm integration test","description":"Full integration test for swarm lifecycle.\n\nTest scenario:\n1. Create a small epic with 3-4 issues and dependencies\n2. Run bd swarm validate - should pass\n3. Run gt swarm create with the epic\n4. Verify swarm molecule created with mol_type=swarm\n5. Run gt swarm status - verify ready front\n6. Simulate issue completion (bd close)\n7. Verify ready front advances\n8. Complete all issues\n9. Verify swarm auto-closes\n\nCan be manual test documented in test file, or automated.\n\nDependencies: gt-kc7yj.2 (Witness integration), gt-kc7yj.3 (completion detection)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-28T19:12:43.609154-08:00","created_by":"mayor","updated_at":"2025-12-29T18:04:34.715704-08:00","closed_at":"2025-12-29T18:04:34.715704-08:00","close_reason":"E2E swarm test complete. Validated: 1) Epic with DAG dependencies 2) bd swarm validate wave analysis 3) Swarm molecule creation with mol_type=swarm 4) Ready front advancement on issue close 5) 100% completion detection. Filed gt-594a4 for gt swarm routing bug. Documented test protocol in manager_test.go.","dependencies":[{"issue_id":"gt-kc7yj.4","depends_on_id":"gt-kc7yj","type":"parent-child","created_at":"2025-12-28T19:12:43.610918-08:00","created_by":"daemon"},{"issue_id":"gt-kc7yj.4","depends_on_id":"gt-kc7yj.2","type":"blocks","created_at":"2025-12-28T19:12:53.397796-08:00","created_by":"daemon"},{"issue_id":"gt-kc7yj.4","depends_on_id":"gt-kc7yj.3","type":"blocks","created_at":"2025-12-28T19:12:53.428901-08:00","created_by":"daemon"}]} -{"id":"gt-kchyh","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:47:58.184192-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.929443-08:00","closed_at":"2026-01-05T00:08:31.929443-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:47:58-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-kdy77","title":"gt crew add: Agent bead uses hardcoded gt- prefix instead of rig prefix","description":"When running 'gt crew add \u003cname\u003e --rig beads', the command tries to create an agent bead with ID 'gt-crew-beads-\u003cname\u003e' but beads rig uses 'bd' prefix.\n\nError: issue ID 'gt-crew-beads-grip' does not match configured prefix 'bd'\n\nThe agent bead ID should use the target rig's prefix, not hardcode 'gt-'.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-29T14:55:48.953521-08:00","created_by":"stevey","updated_at":"2025-12-29T15:28:36.394392-08:00","closed_at":"2025-12-29T15:28:36.394392-08:00","close_reason":"Fixed: Added WithPrefix variants to agent bead ID functions, updated crew_add.go, rig/manager.go, and doctor/agent_beads_check.go to use rig's configured prefix"} -{"id":"gt-kebk4","title":"Digest: mol-deacon-patrol","description":"Patrol 20: all healthy - handoff","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:36:31.978815-08:00","updated_at":"2025-12-29T22:36:31.978815-08:00","closed_at":"2025-12-29T22:36:31.978777-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-ker6f","title":"Code review: await-signal command (gt-vdprb.1)","description":"Review the await-signal molecule step implementation in internal/cmd/molecule_await_signal.go","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-29T22:20:37.388958-08:00","created_by":"gastown/refinery","updated_at":"2025-12-29T22:26:48.4853-08:00","closed_at":"2025-12-29T22:26:48.4853-08:00","close_reason":"Code review complete: ACCEPT. Implementation is functional and safe. Found minor issues: (1) incomplete backoff iteration tracking (Medium), (2) stub GetCurrentStepBackoff function (Low), (3) potential goroutine leak on edge cases (Low), (4) no stderr capture (Low). No security or crash issues. Backoff enhancement can be filed as follow-up if needed.","dependencies":[{"issue_id":"gt-ker6f","depends_on_id":"gt-2ocgh","type":"blocks","created_at":"2025-12-29T22:21:05.105719-08:00","created_by":"daemon"}]} -{"id":"gt-kfe6h","title":"Digest: mol-deacon-patrol","description":"Patrol 219: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:58:45.505436-08:00","updated_at":"2026-01-01T16:58:45.505436-08:00","closed_at":"2026-01-01T16:58:45.5054-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-kfe6h","depends_on_id":"gt-eph-u31c","type":"parent-child","created_at":"2026-01-01T16:58:45.506766-08:00","created_by":"deacon"}]} -{"id":"gt-kftp8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:41:37.649014-08:00","updated_at":"2026-01-01T07:41:37.649014-08:00","closed_at":"2026-01-01T07:41:37.648978-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-kfznm","title":"Refinery: Send MERGED notification to witness after merge","description":"During liftoff test (gt-j0gx2), observed that refinery:\n1. Received MERGE_READY for nux\n2. Fetched, rebased, resolved conflicts correctly\n3. Ran tests (passed)\n4. Merged to main and pushed\n5. Deleted polecat branch\n\nBut did NOT:\n- Send MERGED mail to witness\n- Close the MR bead (gt-5qkah)\n\nThe mol-refinery-patrol.formula.toml documents this step but the agent didn't execute it.\n\nImpact:\n- Witness never receives MERGED signal\n- Polecat worktree never gets nuked\n- MR beads accumulate as open\n\nFix:\nAfter successful merge+push, refinery must:\n```bash\ngt mail send \u003crig\u003e/witness -s \"MERGED \u003cpolecat\u003e\" -m \"...\"\nbd close \u003cmr-bead\u003e --reason \"Merged to main\"\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T16:26:08.423116-08:00","created_by":"stevey","updated_at":"2025-12-28T16:30:17.040435-08:00","closed_at":"2025-12-28T16:30:17.040435-08:00"} -{"id":"gt-kg3ch","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:13:07.399371-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:54.459144-08:00","closed_at":"2025-12-30T23:12:54.459144-08:00","close_reason":"Branch already merged"} -{"id":"gt-kgszr","title":"Parallel refinery: reduce merge queue bottleneck","description":"Single refinery processes MRs sequentially, causing backlog.\n\n## Problem\n- 12 swarms × 5 polecats = 60 MRs\n- Refinery: 1 merge at a time\n- Branches go stale waiting\n- Conflicts compound\n\n## Options\n\n### Option A: Multiple refinery workers\n- Spawn N refinery instances\n- Each claims MRs from queue\n- Risk: merge conflicts between concurrent merges\n\n### Option B: Integration branches\n- Polecats merge to integration/swarm-xxx first\n- Refinery merges integration branch to main\n- Reduces main contention\n\n### Option C: Batched merges\n- Refinery collects N MRs\n- Attempts octopus merge\n- Falls back to sequential on conflict\n\n### Recommendation\nStart with Option A (2-3 workers) with locking on main.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-30T19:08:02.664446-08:00","created_by":"mayor","updated_at":"2026-01-01T18:46:37.069297-08:00","closed_at":"2026-01-01T18:46:37.069297-08:00","close_reason":"Implemented Option A (multiple refinery workers with claiming). Added ClaimedBy/ClaimedAt to MR struct, claim/release/unclaimed CLI commands, and updated patrol formula to use claiming for parallel processing coordination."} -{"id":"gt-kgujv","title":"Merge: chrome-mk0vvab8","description":"branch: polecat/chrome-mk0vvab8\ntarget: main\nsource_issue: chrome-mk0vvab8\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:18:36.009585-08:00","created_by":"gastown/polecats/chrome","updated_at":"2026-01-05T19:40:10.508906-08:00","closed_at":"2026-01-05T19:40:10.508906-08:00","close_reason":"Manually merged"} -{"id":"gt-kgvcm","title":"Digest: mol-deacon-patrol","description":"Patrol 5: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:24:42.216486-08:00","updated_at":"2026-01-01T04:24:42.216486-08:00","closed_at":"2026-01-01T04:24:42.216453-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-kgziv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:24:49.214991-08:00","updated_at":"2026-01-01T10:24:49.214991-08:00","closed_at":"2026-01-01T10:24:49.214955-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-kimb8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 68: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:17:56.617144-08:00","updated_at":"2026-01-01T13:17:56.617144-08:00","closed_at":"2026-01-01T13:17:56.617101-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-kjcx4","title":"gt crew stop \u003cname\u003e doesn't stop the crew","description":"Running 'gt crew stop beads' (or any crew name) doesn't actually stop the crew member. The command should terminate the crew's tmux session but fails to do so.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-05T00:18:49.544242-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-06T13:25:16.513255-08:00","closed_at":"2026-01-06T13:25:16.513255-08:00","close_reason":"Fixed: added dry-run support and proper error handling to gt crew stop"} -{"id":"gt-kjlli","title":"Merge: imperator-1767106079026","description":"branch: polecat/imperator-1767106079026\ntarget: main\nsource_issue: imperator-1767106079026\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T09:56:56.917273-08:00","created_by":"gastown/polecats/imperator","updated_at":"2025-12-30T10:06:56.532213-08:00","closed_at":"2025-12-30T10:06:56.532213-08:00"} -{"id":"gt-kjsp3","title":"Digest: mol-deacon-patrol","description":"Patrol 9: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:06:55.631263-08:00","updated_at":"2025-12-27T23:06:55.631263-08:00","closed_at":"2025-12-27T23:06:55.631229-08:00"} -{"id":"gt-kkf5c","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:31:46.427005-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.743129-08:00","closed_at":"2026-01-04T16:40:22.743129-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:31:46-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-kkrd2","title":"Merge: cal-mjufugtb","description":"branch: polecat/cal-mjufugtb\ntarget: main\nsource_issue: cal-mjufugtb\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T12:08:45.088479-08:00","created_by":"gastown/polecats/cal","updated_at":"2025-12-31T12:11:54.973504-08:00","closed_at":"2025-12-31T12:11:54.973504-08:00","close_reason":"Merged at 3444e3ac"} -{"id":"gt-kktj","title":"Patrol agent state.json not updated on activity","description":"Witness and Refinery state.json files show last_active from Dec 19 even though sessions have been running. The state should update each patrol cycle.\n\nEvidence:\n```\n$ cat beads/witness/state.json\n{\"role\": \"witness\", \"last_active\": \"2025-12-19T17:50:00Z\"}\n\n$ cat beads/refinery/state.json \n{\"role\": \"refinery\", \"last_active\": \"2025-12-19T17:50:00Z\"}\n```\n\nExpected: last_active should update each time the agent runs a patrol cycle.\n\nImpact: Can't tell if patrol agents are actually active vs just having an open tmux session.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-23T20:29:58.515591-08:00","updated_at":"2025-12-28T22:37:43.91459-08:00","closed_at":"2025-12-28T22:37:43.91459-08:00"} -{"id":"gt-klkyq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:33:17.402038-08:00","updated_at":"2025-12-31T23:33:17.402038-08:00","closed_at":"2025-12-31T23:33:17.402004-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-klu0r","title":"Merge: nux-1767083432904","description":"branch: polecat/nux-1767083432904\ntarget: main\nsource_issue: nux-1767083432904\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:35:43.909114-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.261096-08:00","closed_at":"2025-12-30T01:01:04.261096-08:00","close_reason":"Already merged to main"} -{"id":"gt-klv8v","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All agents healthy, 6 health pings sent","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:28:36.623696-08:00","updated_at":"2025-12-31T23:28:36.623696-08:00","closed_at":"2025-12-31T23:28:36.623647-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-kmn.12","title":"Ephemeral rig support for ad-hoc batch work","description":"Support for temporary worker rigs for ad-hoc batch work.\n\n## Use Case\n\nAd-hoc batch work where you want temporary workers:\n- gt spawn --epic \u003cepic-id\u003e --ephemeral --workers 3\n- Creates temp rig with 3 clones\n- Workers process epic children\n- Work merges through queue\n- Clones cleaned up when done\n\n## Interface\n\n```go\ntype EphemeralRig struct {\n ID string\n GitURL string\n BaseCommit string\n Workers []string\n IntegrationBranch string\n EpicID string // associated epic (for cleanup trigger)\n CreatedAt time.Time\n}\n\nfunc InitEphemeralRig(gitURL string, numWorkers int) (*EphemeralRig, error)\nfunc (r *EphemeralRig) AddWorker(name string) error\nfunc (r *EphemeralRig) Destroy(force bool) error\n```\n\n## Directory Structure\n\n```\n\u003crig\u003e/ephemeral/\n└── rig-a3f7/\n ├── config.json\n ├── Alice/ # clone\n ├── Bob/ # clone\n └── Carol/ # clone\n```\n\n## Cleanup Trigger\n\nWhen all issues in the associated epic are closed AND merged, the ephemeral rig can be destroyed.\n\n## Note\n\nNo swarm ID needed - the epic ID provides the grouping. Ephemeral rig is just a convenience for temporary clones.\n\n## Reference\n\nPGT: ephemeral.py (for structure, ignore swarm ID coupling)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T00:10:44.915982-08:00","updated_at":"2025-12-28T22:36:41.666721-08:00","closed_at":"2025-12-28T22:36:41.666721-08:00","dependencies":[{"issue_id":"gt-kmn.12","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:44.916346-08:00","created_by":"daemon"}]} -{"id":"gt-kmn.13","title":"Plugin: work-oracle (pre-dispatch analysis)","description":"Plugin for pre-dispatch task analysis and decomposition.\n\n## Purpose\n\nBefore dispatching workers for an epic, ask work-oracle to:\n- Validate task breakdown\n- Identify parallelization opportunities\n- Predict conflicts between tasks\n- Suggest worker count\n\n## Hook Point\n\nMayor consults work-oracle before spawning workers.\n\n## Interface\n\nInput (via mail):\n- Epic ID with proposed child issues\n- Rig context (current state of codebase)\n\nOutput (via mail + bead):\n- Recommended task groupings\n- Dependency suggestions\n- Risk assessment (which files might conflict)\n- Optimal worker count\n\n## Structure\n\n```\n\u003crig\u003e/plugins/work-oracle/\n├── CLAUDE.md # Analysis prompts\n├── mail/inbox.jsonl\n└── state.json\n```\n\nUses existing plugin-as-agent architecture.\n\n## Note\n\nWas \"swarm-oracle\" - renamed because there are no swarm IDs. This plugin helps plan batch work, not manage swarm entities.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-16T00:10:46.139004-08:00","updated_at":"2025-12-28T22:36:41.684579-08:00","closed_at":"2025-12-28T22:36:41.684579-08:00","dependencies":[{"issue_id":"gt-kmn.13","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:46.139369-08:00","created_by":"daemon"}]} -{"id":"gt-kmt0b","title":"Digest: mol-deacon-patrol","description":"Patrol 18: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:29:25.593853-08:00","updated_at":"2025-12-31T20:29:25.593853-08:00","closed_at":"2025-12-31T20:29:25.593816-08:00","dependencies":[{"issue_id":"gt-kmt0b","depends_on_id":"gt-eph-zvb8","type":"parent-child","created_at":"2025-12-31T20:29:25.595053-08:00","created_by":"deacon"}]} -{"id":"gt-kndd0","title":"Digest: mol-deacon-patrol","description":"Cycle 14","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:05:35.822886-08:00","updated_at":"2026-01-01T10:05:35.822886-08:00","closed_at":"2026-01-01T10:05:35.822849-08:00"} -{"id":"gt-knwng","title":"Digest: mol-deacon-patrol","description":"Patrol 214: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:55:37.921179-08:00","updated_at":"2026-01-01T16:55:37.921179-08:00","closed_at":"2026-01-01T16:55:37.921142-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-knwng","depends_on_id":"gt-eph-tu18","type":"parent-child","created_at":"2026-01-01T16:55:37.922531-08:00","created_by":"deacon"}]} -{"id":"gt-koja9","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 17: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:49.243562-08:00","updated_at":"2025-12-28T11:22:49.243562-08:00","closed_at":"2025-12-28T11:22:49.243529-08:00"} -{"id":"gt-kri6d","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:05:54.293511-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T00:08:31.385943-08:00","closed_at":"2026-01-05T00:08:31.385943-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:05:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-ks3cf","title":"Digest: mol-deacon-patrol","description":"deacon patrol: 21 cycles complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T02:05:18.084249-08:00","updated_at":"2025-12-28T02:05:18.084249-08:00","closed_at":"2025-12-28T02:05:18.084194-08:00"} -{"id":"gt-kt9qq","title":"Deacon Patrol","description":"Mayor's daemon patrol loop for handling callbacks, health checks, and cleanup.","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-29T14:37:53.146706-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:37:53.146706-08:00"} -{"id":"gt-ktso4","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T17:03:41.139802-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.09231-08:00","closed_at":"2026-01-04T16:41:26.09231-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T17:03:41-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-kvjky","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:42:37.317324-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.717725-08:00","closed_at":"2026-01-05T19:44:18.717725-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:42:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-kw2qx","title":"Merge: rictus-mjxlzc5r","description":"branch: polecat/rictus-mjxlzc5r\ntarget: main\nsource_issue: rictus-mjxlzc5r\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:17:36.440196-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-02T17:30:10.601204-08:00","closed_at":"2026-01-02T17:30:10.601204-08:00","close_reason":"Merged to main at 82736228"} -{"id":"gt-kwa09","title":"Security: ReDoS vulnerability in mail/mailbox.go Search function","description":"The Search function (mailbox.go:642-702) compiles user input directly as a regex pattern:\n\n```go\nre, err := regexp.Compile(\"(?i)\" + opts.Query)\n```\n\nIf opts.Query contains untrusted input (e.g., from a message body being searched), a malicious regex pattern could cause catastrophic backtracking (ReDoS).\n\nExample attack pattern: `(a+)+$` with input `aaaaaaaaaaaaaaaaaaaaa!`\n\n**Recommended fix**:\n1. Add a timeout context to regex matching\n2. Validate/sanitize the regex pattern before compilation\n3. Consider using regexp.QuoteMeta() if literal string matching is intended\n4. Or limit regex complexity\n\nFiles:\n- internal/mail/mailbox.go:645\n\nSeverity: high (if Search is exposed to user input)","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-04T23:47:05.4118-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:53:28.449736-08:00","closed_at":"2026-01-04T23:53:28.449736-08:00","close_reason":"Fixed with regexp.QuoteMeta in commit 8b63904"} -{"id":"gt-kwnj1","title":"Merge: ace-mjwjb633","description":"branch: polecat/ace-mjwjb633\ntarget: main\nsource_issue: ace-mjwjb633\nrig: gastown\nagent_bead: gt-gastown-polecat-ace","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:16:25.637491-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-01T23:18:29.164261-08:00","closed_at":"2026-01-01T23:18:29.164261-08:00","close_reason":"Merged to main"} -{"id":"gt-ky1nt","title":"Review PR #52: fix: Close MR beads after successful merge from queue","description":"Review PR #52. Verify MR beads are properly closed after merge. Approve with gh pr review --approve if good.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/warboy","created_at":"2026-01-03T11:40:27.032551-08:00","created_by":"mayor","updated_at":"2026-01-03T11:44:19.915671-08:00","closed_at":"2026-01-03T11:44:19.915671-08:00","close_reason":"PR reviewed and approved"} -{"id":"gt-kz2xt","title":"Merge: dag-1767079859283","description":"branch: polecat/dag-1767079859283\ntarget: main\nsource_issue: dag-1767079859283\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:41:37.596144-08:00","created_by":"gastown/polecats/dag","updated_at":"2025-12-29T23:55:11.840439-08:00","closed_at":"2025-12-29T23:55:11.840439-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-kzcqy","title":"Digest: mol-deacon-patrol","description":"Patrol 16: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:39:08.506447-08:00","updated_at":"2025-12-31T21:39:08.506447-08:00","closed_at":"2025-12-31T21:39:08.50641-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l0lok","title":"Clarify RecreateWithOptions as repair operation (not recycling)","description":"## Problem\n\nRecreateWithOptions exists but its purpose is unclear. PR #112 calls it \"recycling\" \nbut the correct model says sandboxes persist until nuke.\n\n## Current Usage\n\nCalled from polecat_spawn.go when AllocateName returns a name that already exists:\n\"Check if polecat already exists (shouldn't, since we allocated fresh)\"\n\nThis is a reconciliation/repair case, not normal operation.\n\n## Clarification Needed\n\n1. Rename to RepairSandbox or similar to clarify intent\n2. Add documentation explaining this is for stale state recovery only\n3. Consider if it should even exist - maybe just Remove + Add?\n\n## The PR #112 Question\n\nPR #112 improves RecreateWithOptions to start from origin/default-branch.\nThis is correct IF Recreate is a valid repair operation.\n\nBut the PR title says \"when recycled\" which implies normal operation.\nThe framing is wrong even if the fix is sound.\n\n## Decision Required\n\n1. Keep RecreateWithOptions as repair-only, rename for clarity\n2. OR remove entirely, use Remove + Add for repair cases\n3. Update PR #112 title/description to reflect repair semantics","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/dinki","created_at":"2026-01-04T14:10:36.535884-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T14:26:00.709788-08:00","closed_at":"2026-01-04T14:26:00.709788-08:00","close_reason":"Renamed Recreate→RepairWorktree, updated comments and output to clarify repair-only semantics"} -{"id":"gt-l0olz","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy, 2 convoys in progress","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:14:34.554807-08:00","updated_at":"2025-12-31T14:14:34.554807-08:00","closed_at":"2025-12-31T14:14:34.554769-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l12ul","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:32:34.814118-08:00","updated_at":"2025-12-31T23:32:34.814118-08:00","closed_at":"2025-12-31T23:32:34.814088-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l157u","title":"Digest: mol-deacon-patrol","description":"Patrol 23: Quick cycle, no changes. All agents healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:55:18.332832-08:00","updated_at":"2025-12-31T13:55:18.332832-08:00","closed_at":"2025-12-31T13:55:18.332798-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l1b4d","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:35:12.971666-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:40:22.95019-08:00","closed_at":"2026-01-04T16:40:22.95019-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:35:12-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-l1s6t","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all healthy, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:27:03.219864-08:00","updated_at":"2025-12-31T20:27:03.219864-08:00","closed_at":"2025-12-31T20:27:03.219819-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l1xsa","title":"[Security] Command args from parsed config files in rig/manager.go","description":"In rig/manager.go:354 and :520, sourcePrefix/prefix are passed to exec.Command(\"bd\", \"init\", \"--prefix\", ...). While marked with nolint:gosec assuming bd is trusted, the prefix value originates from config files (detectBeadsPrefixFromConfig) which could be manipulated. Consider validating prefix format before passing to exec.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-04T23:47:14.383502-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T00:02:53.55508-08:00","closed_at":"2026-01-05T00:02:53.55508-08:00","close_reason":"Added isValidBeadsPrefix() to validate prefix format. Prefixes from config files are now validated to prevent command injection."} -{"id":"gt-l2b6v","title":"Merge: slit-1767084013378","description":"branch: polecat/slit-1767084013378\ntarget: main\nsource_issue: slit-1767084013378\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:49:46.333626-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T01:01:04.210182-08:00","closed_at":"2025-12-30T01:01:04.210182-08:00","close_reason":"Already merged to main"} -{"id":"gt-l2r8w","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:32:01.895207-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.810056-08:00","closed_at":"2026-01-05T00:08:31.810056-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:32:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-l39z0","title":"Merge: gt-nq3pr","description":"branch: polecat/testcat6-mjtkcfjm\ntarget: main\nsource_issue: gt-nq3pr\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T21:19:33.887575-08:00","created_by":"gastown/polecats/testcat6","updated_at":"2025-12-30T23:12:54.625622-08:00","closed_at":"2025-12-30T23:12:54.625622-08:00","close_reason":"Branch already merged"} -{"id":"gt-l3epl","title":"Handoff mail not delivered to mayor inbox","description":"Town log shows predecessor handed off at 12:59:33 with message about gt-7psb8, but gt mail inbox shows 0 messages. The handoff context was lost.\n\nReproduction:\n1. Mayor runs gt handoff with -s 'context'\n2. New mayor session starts\n3. gt mail inbox shows empty\n\nExpected: Handoff mail in inbox\n\n(Moved from hq-zs2t8)","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/dementus","created_at":"2026-01-02T01:37:31.986056-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-02T14:05:29.240521-08:00","closed_at":"2026-01-02T14:05:29.240521-08:00","close_reason":"Fixed: trailing slash added to town-level agent IDs in sling.go (dementus MR merged)"} -{"id":"gt-l3gfn","title":"Digest: mol-deacon-patrol","description":"Patrol 18: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:29:32.029593-08:00","updated_at":"2025-12-25T07:29:32.029593-08:00","closed_at":"2025-12-25T07:29:32.029556-08:00"} -{"id":"gt-l3o0k","title":"Update gastown to use 'ephemeral' instead of 'wisp' terminology","description":"After beads renames 'wisp' to 'ephemeral' (bd-o18s), update gastown code:\n\n- patrol_helpers.go: bd wisp create → bd ephemeral create (or new API)\n- doctor/wisp_check.go: rename to ephemeral_check.go\n- All references to Wisp field → Ephemeral\n\nDepends on: bd-o18s","status":"hooked","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-26T20:16:44.91769-08:00","updated_at":"2025-12-30T00:27:47.101828-08:00","dependencies":[{"issue_id":"gt-l3o0k","depends_on_id":"external:beads:ephemeral-rename","type":"blocks","created_at":"2025-12-26T20:17:00.859719-08:00","created_by":"daemon"},{"issue_id":"gt-l3o0k","depends_on_id":"external:beads:bd-o18s","type":"blocks","created_at":"2025-12-26T20:17:51.026548-08:00","created_by":"daemon"}]} -{"id":"gt-l699n","title":"Digest: mol-refinery-patrol","description":"Patrol: No MRs in queue. Found 1 pending branch (gt-jq8i4) without MR bead. 8 stale branches detected (work already on main).","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:02:07.35265-08:00","updated_at":"2026-01-01T10:02:07.35265-08:00","closed_at":"2026-01-01T10:02:07.352607-08:00","close_reason":"Squashed from 11 wisps"} -{"id":"gt-l6bf2","title":"Digest: mol-deacon-patrol","description":"Patrol 123: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:30:13.89958-08:00","updated_at":"2026-01-01T14:30:13.89958-08:00","closed_at":"2026-01-01T14:30:13.899542-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l6ebz","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:49:12.576237-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.549443-08:00","closed_at":"2026-01-04T16:40:13.549443-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:49:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-l6n7a","title":"Merge: toast-mjxb88ev","description":"branch: polecat/toast-mjxb88ev\ntarget: main\nsource_issue: toast-mjxb88ev\nrig: gastown\nagent_bead: gt-gastown-polecat-toast","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:19:34.37422-08:00","created_by":"gastown/polecats/toast","updated_at":"2026-01-02T12:28:26.739035-08:00","closed_at":"2026-01-02T12:28:26.739035-08:00","close_reason":"Merged to main"} -{"id":"gt-l6ro3","title":"Patrol Exponential Backoff System","description":"Cost-saving await-signal model for patrol agents.\n\n## The Problem\n\nPatrol agents (witness, refinery) poll continuously even when idle, burning API credits.\n\n## The Solution: Await-Signal\n\nAgents don't poll constantly. They **wait for a signal**, then **discover reality**.\n\n```\nPATROL LOOP:\n await-signal (just wake me)\n ↓ awake\n check-reality (mail, beads, hook, git)\n ↓\n work found? → DO WORK → loop\n ↓ no\n increase backoff → loop\n```\n\n**Key principle (ZFC-aligned):** Signal carries no semantic meaning - just 'wake up'.\nAgent discovers what to do by examining reality.\n\n## Two-Level Wake\n\n| Level | State | Command |\n|-------|-------|---------|\n| 1 | Running (backoff) | `gt nudge` clears backoff |\n| 2 | Asleep | `gt rig boot` starts session |\n\n**Boot+nudge pattern:**\n```bash\ngt rig boot \u003crig\u003e # Wake if asleep (idempotent)\ngt nudge \u003crig\u003e/witness 'wake' # Clear backoff if running\n```\n\n## Backoff Curve\n\nBase: 30s → 60s → 120s → 240s → ... → 10min cap\n\nResets on: nudge received, work found, deacon ping.\n\n## Reference\n\nSee ~/gt/docs/patrol-system-design.md (Await-Signal Model section)","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-28T22:31:05.32225-08:00","created_by":"mayor","updated_at":"2025-12-28T23:05:37.717126-08:00","dependencies":[{"issue_id":"gt-l6ro3","depends_on_id":"gt-vdprb","type":"blocks","created_at":"2025-12-29T17:03:39.527-08:00","created_by":"mayor"}]} -{"id":"gt-l6ro3.1","title":"Daemon activity detection and rig nudging","description":"Daemon monitors activity feed and nudges patrol agents when commands detected.\n\n## Implementation\n\n1. Daemon watches activity feed (or logs) for gt/bd command execution\n2. Track per-rig last-activity timestamps\n3. On activity in rig: nudge witness + refinery for that rig\n4. Nudge clears their backoff → immediate poll\n\n## Activity Sources\n\n- gt commands (sling, mail, polecat, etc.)\n- bd commands (create, update, close, sync, etc.)\n- Maybe: file writes in rig directories\n\n## Graceful Behavior\n\n- If agent session not running: no-op (not an error)\n- Activity detection is best-effort\n- Backoff still works without this (just slower wake)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T22:31:24.266187-08:00","created_by":"mayor","updated_at":"2025-12-29T17:08:36.965815-08:00","closed_at":"2025-12-29T17:08:36.965815-08:00","close_reason":"Obsoleted by feed-based wake model (gt-vdprb). Agents subscribe directly to feed; daemon does not mediate activity detection.","dependencies":[{"issue_id":"gt-l6ro3.1","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T22:31:24.266638-08:00","created_by":"daemon"},{"issue_id":"gt-l6ro3.1","depends_on_id":"gt-arjlu","type":"blocks","created_at":"2025-12-28T22:31:51.176239-08:00","created_by":"daemon"}]} -{"id":"gt-l6ro3.2","title":"Deacon health pings clear agent backoff","description":"Deacon's periodic health checks also clear patrol agent backoff.\n\n## Current Flow (mol-deacon-patrol)\n\nDeacon already pings witnesses/refineries for health checks. These pings should:\n1. Verify agent is alive\n2. Clear their backoff as side effect\n\n## Implementation\n\nIn mol-deacon-patrol health-scan step:\n- gt nudge \u003crig\u003e/witness 'HEALTH_CHECK from deacon'\n- gt nudge \u003crig\u003e/refinery 'HEALTH_CHECK from deacon'\n\nReceiving agent:\n- Responds to prove liveness\n- Resets backoff to base interval\n\n## Ping Interval\n\nDeacon patrols every ~1-2 minutes. This ensures:\n- Maximum backoff is bounded by deacon ping interval\n- Even if daemon misses activity, deacon catches up","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-28T22:31:35.003984-08:00","created_by":"mayor","updated_at":"2025-12-30T22:00:46.924888-08:00","closed_at":"2025-12-30T22:00:46.924888-08:00","close_reason":"Added health ping nudges to mol-deacon-patrol health-scan step. These nudges clear agent backoff as a side effect, ensuring patrol agents remain responsive even during quiet periods.","dependencies":[{"issue_id":"gt-l6ro3.2","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T22:31:35.004499-08:00","created_by":"daemon"},{"issue_id":"gt-l6ro3.2","depends_on_id":"gt-arjlu","type":"blocks","created_at":"2025-12-28T22:31:51.206694-08:00","created_by":"daemon"},{"issue_id":"gt-l6ro3.2","depends_on_id":"gt-vdprb.1","type":"blocks","created_at":"2025-12-29T17:09:33.31837-08:00","created_by":"mayor"}]} -{"id":"gt-l6ro3.3","title":"Molecule await-signal step type","description":"Add await-signal as a molecule step type for patrol agents.\n\n## Step Definition\n\n```toml\n[[steps]]\nid = \"await-signal\"\ntype = \"wait\"\nbackoff = { base = \"30s\", multiplier = 2, max = \"10m\" }\ndescription = \"Wait for signal, then check reality\"\n```\n\n## Behavior\n\n1. Sleep for current backoff interval\n2. Wake immediately on nudge (or timeout expires)\n3. Proceed to next step (check-reality)\n4. If no work found, loop back with increased backoff\n5. If work found, reset backoff to base\n\n## Implementation Options\n\nA. Formula-level: Define in TOML, agent interprets\nB. Code-level: Agent implements wait loop with backoff\n\nOption A is cleaner but needs formula parser support.\nOption B works now but less declarative.\n\n## Used By\n\n- mol-witness-patrol (first step)\n- mol-refinery-patrol (first step)","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-28T23:06:11.638803-08:00","created_by":"mayor","updated_at":"2025-12-29T18:04:21.290973-08:00","closed_at":"2025-12-29T18:04:21.290973-08:00","close_reason":"Implemented Type and Backoff fields in MoleculeStep with parsing support for await-signal step type","dependencies":[{"issue_id":"gt-l6ro3.3","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T23:06:11.63931-08:00","created_by":"daemon"},{"issue_id":"gt-l6ro3.3","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:08:22.500906-08:00","created_by":"mayor"}]} -{"id":"gt-l6ro3.4","title":"Deacon stuck-session detection and force-kill protocol","description":"Deacon detects and kills genuinely stuck/hung Claude Code sessions.\n\n## The Problem\n\nClaude Code sessions can get stuck:\n- Infinite loop / hung tool call\n- Crashed but tmux session still exists\n- Unresponsive to nudges\n\n`gt rig boot` is idempotent (won't kill) - it only starts if not running.\nSomeone needs to detect stuck sessions and force-kill them.\n\n## Detection Protocol\n\nDuring Deacon health rounds:\n\n1. **Ping test**: `gt nudge \u003cagent\u003e 'HEALTH_CHECK'`\n2. **Wait for response**: Agent should update agent bead `last_activity`\n3. **Timeout**: If no activity update within N seconds, mark suspicious\n4. **Consecutive failures**: After M consecutive failures, declare stuck\n\n## Force-Kill Protocol\n\nWhen stuck detected:\n\n```bash\n# 1. Log the intervention\ngt mail send \u003cagent\u003e -s 'FORCE_KILL: unresponsive' -m 'Deacon detected...'\n\n# 2. Kill the tmux session\ntmux kill-session -t \u003csession-name\u003e\n\n# 3. Update agent bead state\nbd update \u003cagent-bead\u003e --status=killed --reason='Deacon force-kill: unresponsive'\n\n# 4. Notify mayor (optional, for visibility)\ngt mail send mayor/ -s 'Agent killed: \u003cagent\u003e' -m 'Reason: unresponsive...'\n```\n\n## Recovery\n\nAfter force-kill, the agent is 'asleep'. Normal wake mechanisms apply:\n- `gt rig boot` restarts it\n- Or stays asleep until next activity trigger\n\n## Parameters (configurable)\n\n- ping_timeout: 30s (how long to wait for response)\n- consecutive_failures: 3 (how many before force-kill)\n- cooldown: 5m (minimum time between force-kills of same agent)\n\n## NOT Deacon's Job\n\n- Graceful shutdown (agent does this itself)\n- Context-based recycling (agent self-handoffs)\n- Normal backoff/sleep transitions\n\nDeacon only force-kills when agent is genuinely unresponsive.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-28T23:09:21.694807-08:00","created_by":"mayor","updated_at":"2025-12-30T22:11:13.044466-08:00","closed_at":"2025-12-30T22:11:13.044466-08:00","close_reason":"Implemented stuck-session detection and force-kill protocol with new commands: health-check, force-kill, health-state","dependencies":[{"issue_id":"gt-l6ro3.4","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T23:09:21.695345-08:00","created_by":"daemon"}]} -{"id":"gt-l8fp7","title":"Digest: mol-deacon-patrol","description":"Patrol 1: inbox clear, gates clear, no pending spawns, witnesses/refineries healthy, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:38.09038-08:00","updated_at":"2025-12-28T15:49:38.09038-08:00","closed_at":"2025-12-28T15:49:38.090344-08:00"} -{"id":"gt-l90dq","title":"gt crew at fails to detect existing crew session","description":"## Summary\n`gt crew at` started a new Claude session instead of attaching to an existing one for the same crew worker.\n\n## Reproduction\n1. Have a crew worker (joe) running in gastown/crew/joe (PID 27526 on tty s030)\n2. Run `gt crew at` from the same directory (gastown/crew/joe)\n3. Expected: Attach to existing session on s030\n4. Actual: Started a brand new Claude session (PID 67618 on s026)\n\n## Evidence\n```\n# Old joe still running:\nPID 27526 on s030: /Users/stevey/gt/gastown/crew/joe (started 10:22AM)\n\n# New joe spawned by 'gt crew at':\nPID 67618 on s026: /Users/stevey/gt/gastown/crew/joe (started 10:39AM)\n```\n\n## Impact\n- Duplicate crew workers cause confusion\n- User expected to attach to existing session, not spawn a second one\n- The original session was still functional (just stuck in feed display)\n\n## Likely cause\n`gt crew at` probably doesn't check for running Claude processes in the crew directory before spawning a new one. It should:\n1. Check for existing tmux sessions for this crew worker\n2. Check for running `claude` processes with cwd matching the crew directory\n3. If found, attach to existing session instead of spawning new one","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-28T10:52:28.917151-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T21:57:22.055124-08:00","closed_at":"2025-12-29T21:57:22.055124-08:00","close_reason":"Fixed by adding FindSessionByWorkDir() to detect existing Claude sessions in the crew directory before creating a new one"} -{"id":"gt-l90jj","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:35:14.061026-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.766798-08:00","closed_at":"2026-01-05T00:08:31.766798-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:35:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-l9g","title":"Beads epic templates for batch work patterns","description":"Optional: Define templates for common batch work patterns.\n\n## Concept\n\nA template encodes a workflow pattern that can be instantiated as beads:\n\n```yaml\n# templates/batch-basic.yaml\nname: basic-batch\ndescription: Simple batch work pattern\nphases:\n - name: startup\n issues:\n - title: \"Verify workers ready\"\n - name: working\n # Actual work issues added separately\n - name: cleanup\n issues:\n - title: \"Merge all branches\"\n - title: \"Clean up workers\"\n - title: \"Report to Mayor\"\n```\n\n## Usage\n\n```bash\ngt spawn --template basic-batch --epic gt-u1j --workers 3\n```\n\nCreates beads epic with template phases + actual work from gt-u1j children.\n\n## Decision Point\n\nTemplates are OPTIONAL. The core design (beads as state, multi-wave orchestration) works without templates. Templates are sugar for common patterns.\n\nConsider deferring to P3 or dropping entirely if beads epics with dependencies suffice.\n\n## Note\n\nNo \"swarm IDs\" involved - templates just pre-populate epic/issue structure.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T01:51:24.399235-08:00","updated_at":"2025-12-16T17:26:08.868396-08:00"} -{"id":"gt-l9k26","title":"Exclude deacon from tmux rig count in status displays","description":"Deacon is a town-level patrol agent, not a project rig. It shows up in tmux session counts alongside actual rigs (gastown, beads, wyvern), which is confusing.\n\nFix: Status/tmux reporting should exclude deacon from rig counts. Deacon is infrastructure, not a workspace.\n\nAffected: Any status displays that count tmux sessions as rigs.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-02T01:44:19.338756-08:00","created_by":"mayor","updated_at":"2026-01-02T01:44:26.585124-08:00"} -{"id":"gt-l9mru","title":"Digest: mol-deacon-patrol","description":"Patrol 84: All healthy, quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:18:07.44764-08:00","updated_at":"2025-12-31T15:18:07.44764-08:00","closed_at":"2025-12-31T15:18:07.44761-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-l9t35","title":"Test MR","description":"branch: test-branch\ntarget: main\nsource_issue: gt-test\nrig: gastown","status":"closed","priority":3,"issue_type":"merge-request","created_at":"2025-12-28T13:55:31.051975-08:00","created_by":"mayor","updated_at":"2025-12-28T13:55:51.591898-08:00","closed_at":"2025-12-28T13:55:51.591898-08:00"} -{"id":"gt-lafkf","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T11:05:04.114506-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.649559-08:00","closed_at":"2026-01-05T19:44:18.649559-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T11:05:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-lajrx","title":"Digest: mol-deacon-patrol","description":"Patrol 7: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T06:09:55.036375-08:00","updated_at":"2025-12-28T06:09:55.036375-08:00","closed_at":"2025-12-28T06:09:55.036344-08:00"} -{"id":"gt-lak31","title":"MQ events in gt feed","description":"Wire MQ lifecycle events to gt feed display.\n\nAfter 'Refinery emits activity events' is done:\n- gt feed should show merge_started, merged, merge_failed events\n- Format: timestamp, event type, MR details\n- Color coding: green for merged, red for failed\n\nExample output:\n 19:45 MERGED gt-abc123 (polecat/nux → main)\n 19:42 MERGE_STARTED gt-abc123\n 19:40 MERGE_FAILED gt-xyz789 (conflict)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2025-12-28T21:40:39.079766-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T01:13:59.396794-08:00","closed_at":"2025-12-30T01:13:59.396794-08:00","close_reason":"Implemented MQ lifecycle events in gt feed using standalone mqevents package","dependencies":[{"issue_id":"gt-lak31","depends_on_id":"gt-ytsxp","type":"blocks","created_at":"2025-12-28T21:41:11.587659-08:00","created_by":"daemon"}]} -{"id":"gt-lbpdm","title":"Digest: mol-deacon-patrol","description":"Patrol 146 complete: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:01:11.315674-08:00","updated_at":"2025-12-31T16:01:11.315674-08:00","closed_at":"2025-12-31T16:01:11.315631-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-lcjjk","title":"Digest: mol-deacon-patrol","description":"Patrol 18: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:36:32.505078-08:00","updated_at":"2025-12-28T01:36:32.505078-08:00","closed_at":"2025-12-28T01:36:32.505042-08:00"} -{"id":"gt-lcuxo","title":"Merge: furiosa-mjw349y2","description":"branch: polecat/furiosa-mjw349y2\ntarget: main\nsource_issue: furiosa-mjw349y2\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:49:34.013211-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T18:51:15.859145-08:00","closed_at":"2026-01-01T18:51:15.859145-08:00","close_reason":"Merged to main at e159489e"} -{"id":"gt-ldb5m","title":"Digest: mol-deacon-patrol","description":"P11: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:59:19.365052-08:00","updated_at":"2025-12-25T19:59:19.365052-08:00","closed_at":"2025-12-25T19:59:19.364984-08:00"} -{"id":"gt-ldl41","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 29: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:25:36.416277-08:00","updated_at":"2026-01-01T12:25:36.416277-08:00","closed_at":"2026-01-01T12:25:36.41624-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-le1a","title":"Merge: gt-3x1","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-3x1\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:47.674479-08:00","updated_at":"2025-12-19T18:30:24.050697-08:00","closed_at":"2025-12-19T18:30:24.0507-08:00"} -{"id":"gt-lehby","title":"Digest: mol-deacon-patrol","description":"Patrol 204: Fast pass, all nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:48:47.80613-08:00","updated_at":"2026-01-01T16:48:47.80613-08:00","closed_at":"2026-01-01T16:48:47.806094-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-lehby","depends_on_id":"gt-eph-hqea","type":"parent-child","created_at":"2026-01-01T16:48:47.807399-08:00","created_by":"deacon"}]} -{"id":"gt-leqvb","title":"Merge: slit-1767079899677","description":"branch: polecat/slit-1767079899677\ntarget: main\nsource_issue: slit-1767079899677\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:36:35.88583-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-29T23:55:11.871688-08:00","closed_at":"2025-12-29T23:55:11.871688-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-lexde","title":"Merge: glory-mk06lbix","description":"branch: polecat/glory-mk06lbix\ntarget: main\nsource_issue: glory-mk06lbix\nrig: gastown\nagent_bead: gt-gastown-polecat-glory\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T12:33:44.058056-08:00","created_by":"gastown/polecats/glory","updated_at":"2026-01-04T13:11:28.267556-08:00","closed_at":"2026-01-04T13:11:28.267556-08:00","close_reason":"Merged to main at a0e5831f"} -{"id":"gt-lexye","title":"Create internal/tui/ package with feed model","description":"Create the TUI infrastructure for gt feed.\n\n## Package structure\n```\ninternal/tui/\n feed/\n model.go # bubbletea Model struct\n view.go # View() rendering\n update.go # Update() message handling\n events.go # Event stream subscription (tail .feed.jsonl)\n styles.go # lipgloss styles\n keys.go # Key bindings\n```\n\n## Model components\n1. **AgentTree** - Collapsible tree of agents by role\n2. **EventStream** - Scrollable viewport of recent events\n3. **StatusBar** - Current filter, help hints\n4. **FilterPopup** - Modal for setting filters\n\n## Key bindings\n- j/k - scroll events\n- J/K - scroll agent tree\n- tab - switch focus (tree/stream)\n- enter - expand/details\n- / - search\n- f - filter popup\n- q - quit\n- ? - help\n\n## Event subscription\n- Tail ~/gt/.feed.jsonl using fsnotify or polling\n- Parse JSONL events\n- Send as bubbletea messages to update model","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T16:13:40.29527-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T16:21:50.5417-08:00","closed_at":"2025-12-28T16:21:50.5417-08:00","dependencies":[{"issue_id":"gt-lexye","depends_on_id":"gt-be0as","type":"blocks","created_at":"2025-12-28T16:14:50.294818-08:00","created_by":"daemon"}]} -{"id":"gt-lf252","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:46:47.369981-08:00","updated_at":"2026-01-01T07:46:47.369981-08:00","closed_at":"2026-01-01T07:46:47.369945-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-lfi2d","title":"Delete .runtime/*.json observable state","description":"Remove JSON files that tracked observable state (now in beads/activity stream).\n\nFiles to delete or minimize:\n- .runtime/refinery.json - remove stats (keep minimal process state if needed)\n- .runtime/witness.json - remove stats\n- .runtime/swarms.json - delete entirely (gt-kc7yj moves to beads)\n\nPrerequisite: All events flowing through activity stream, swarms in beads.\n\nThis is the cleanup step after observability is working.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-28T21:40:53.315319-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T02:00:51.189957-08:00","closed_at":"2025-12-30T02:00:51.189957-08:00","close_reason":"Removed Stats fields from witness and refinery types. Observable metrics now flow through activity stream.","dependencies":[{"issue_id":"gt-lfi2d","depends_on_id":"gt-lak31","type":"blocks","created_at":"2025-12-28T21:41:11.646917-08:00","created_by":"daemon"},{"issue_id":"gt-lfi2d","depends_on_id":"gt-rbncw","type":"blocks","created_at":"2025-12-28T21:41:11.676514-08:00","created_by":"daemon"},{"issue_id":"gt-lfi2d","depends_on_id":"gt-kc7yj","type":"blocks","created_at":"2025-12-28T21:41:11.706063-08:00","created_by":"daemon"}]} -{"id":"gt-lftg6","title":"Digest: mol-deacon-patrol","description":"Patrol 17","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:15:41.182015-08:00","updated_at":"2026-01-01T08:15:41.182015-08:00","closed_at":"2026-01-01T08:15:41.181975-08:00"} -{"id":"gt-lg7x9","title":"Digest: mol-deacon-patrol","description":"Cycle 192: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:23:21.998432-08:00","updated_at":"2026-01-01T16:23:21.998432-08:00","closed_at":"2026-01-01T16:23:21.998402-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-lg7x9","depends_on_id":"gt-eph-x144","type":"parent-child","created_at":"2026-01-01T16:23:21.999849-08:00","created_by":"deacon"}]} -{"id":"gt-lgfu3","title":"Digest: mol-deacon-patrol","description":"Patrol 205: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:49:27.648429-08:00","updated_at":"2026-01-01T16:49:27.648429-08:00","closed_at":"2026-01-01T16:49:27.648399-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-lgfu3","depends_on_id":"gt-eph-csl2","type":"parent-child","created_at":"2026-01-01T16:49:27.649795-08:00","created_by":"deacon"}]} -{"id":"gt-lgtcr","title":"Digest: mol-deacon-patrol","description":"Patrol 10: all healthy, sessions up","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:54:49.173354-08:00","updated_at":"2025-12-28T15:54:49.173354-08:00","closed_at":"2025-12-28T15:54:49.17332-08:00"} -{"id":"gt-lhaec","title":"Session ended: gt-gastown-buzzard","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:10:53.632487-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T00:12:03.586077-08:00","closed_at":"2026-01-05T00:12:03.586077-08:00","close_reason":"Session event acknowledged; witness patrol now operational per gt-7vdqv fix","event_kind":"session.ended","actor":"gastown/polecats/buzzard","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:10:53-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-buzzard\",\"worker\":\"buzzard\"}"} -{"id":"gt-lhitf","title":"gt rig stop \u003crig\u003e... - stop rig workers with shutdown semantics","description":"Stop one or more rigs with same flags and semantics as gt shutdown (for polecats). Should support multiple rigs: gt rig stop gastown beads","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-02T11:49:48.017585-08:00","created_by":"mayor","updated_at":"2026-01-02T12:46:17.65272-08:00","closed_at":"2026-01-02T12:46:17.65272-08:00","close_reason":"Implemented gt rig stop command with multi-rig support and shutdown semantics","dependencies":[{"issue_id":"gt-lhitf","depends_on_id":"gt-yyht4","type":"blocks","created_at":"2026-01-02T11:50:01.686169-08:00","created_by":"mayor"}]} -{"id":"gt-lhsjo","title":"Digest: mol-deacon-patrol","description":"Patrol #16: Quick cycle, all quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:21:51.137857-08:00","updated_at":"2025-12-31T19:21:51.137857-08:00","closed_at":"2025-12-31T19:21:51.137822-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-li0np","title":"Digest: mol-deacon-patrol","description":"Patrol 110: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:09:26.260579-08:00","updated_at":"2026-01-01T14:09:26.260579-08:00","closed_at":"2026-01-01T14:09:26.260538-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-liftoff","title":"Liftoff implementation plan in Beads","description":"## Context\n\nSession on 2025-12-27 produced three key docs:\n- `~/gt/docs/agent-as-bead.md` - Agents ARE beads (identity, hook slots, CV chain roots)\n- `~/gt/docs/zfc-violations-audit.md` - Where Go infers instead of trusting agents\n- `~/gt/docs/liftoff-plan.md` - 4.5 day plan to self-sustaining Gas Town\n\n## Work Required\n\n### Phase 1: Audit existing beads ✅\n- Review all open beads in gt- prefix\n- Close obsolete/stale issues\n- Update any that need refinement\n- Note which existing beads align with liftoff plan\n\n### Phase 2: File new beads ✅\nTranslate liftoff-plan.md into beads with proper dependencies.\n\nThree pillars:\n1. **Pillar 1: Agent Identity** (gt-d0jqp) - schema, slot commands, migration\n2. **Pillar 2: Patrol Ignition** (gt-hwka3) - witness/refinery formula wiring\n3. **Pillar 3: Polecat Lifecycle** (gt-4a2qt) - recycle/nuke commands, session-per-step\n\n### Phase 3: Review ✅\nHuman reviews the plan.\n\n## Deliverable\n\nA complete dependency graph in beads that can be:\n1. Queried with `bd ready` to find available work\n2. Slung to polecats in dependency order\n3. Tracked to completion\n\n## References\n\n- ~/gt/docs/liftoff-plan.md - 4.5 day plan\n- ~/gt/docs/agent-as-bead.md - Agent identity design\n- ~/gt/docs/zfc-violations-audit.md - ZFC violations addressed","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T21:42:03.880845-08:00","created_by":"mayor","updated_at":"2025-12-28T16:13:09.29063-08:00","closed_at":"2025-12-28T16:13:09.29063-08:00","dependencies":[{"issue_id":"gt-liftoff","depends_on_id":"gt-d0jqp","type":"blocks","created_at":"2025-12-27T21:42:12.255705-08:00","created_by":"daemon"},{"issue_id":"gt-liftoff","depends_on_id":"gt-hwka3","type":"blocks","created_at":"2025-12-27T21:42:12.293402-08:00","created_by":"daemon"},{"issue_id":"gt-liftoff","depends_on_id":"gt-4a2qt","type":"blocks","created_at":"2025-12-27T21:42:12.329975-08:00","created_by":"daemon"}]} -{"id":"gt-lisj6","title":"Day 1.6: Update gt mol status to use hook slot","description":"Migrate gt mol status from:\n- Query(status=pinned AND assignee=me)\nTo:\n- Read agent bead → check hook_bead field\n\nThis eliminates hook ambiguity.\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:23.813893-08:00","created_by":"mayor","updated_at":"2025-12-28T01:07:55.197087-08:00","closed_at":"2025-12-28T01:07:55.197087-08:00","dependencies":[{"issue_id":"gt-lisj6","depends_on_id":"gt-h5sza","type":"blocks","created_at":"2025-12-27T20:58:54.435681-08:00","created_by":"daemon"},{"issue_id":"gt-lisj6","depends_on_id":"gt-awu07","type":"blocks","created_at":"2025-12-27T20:58:55.49367-08:00","created_by":"daemon"},{"issue_id":"gt-lisj6","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.819695-08:00","created_by":"daemon"}]} -{"id":"gt-liv9i","title":"Merge: nux-mjxn8p5t","description":"branch: polecat/nux-mjxn8p5t\ntarget: main\nsource_issue: nux-mjxn8p5t\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:59:46.736566-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-03T12:46:58.645617-08:00","closed_at":"2026-01-03T12:46:58.645617-08:00","close_reason":"Merged to main at 386dbf85 (verified on main)"} -{"id":"gt-ljhlh","title":"Digest: mol-deacon-patrol","description":"Patrol complete: town quiet, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:18:52.484278-08:00","updated_at":"2025-12-28T19:18:52.484278-08:00","closed_at":"2025-12-28T19:18:52.484244-08:00"} -{"id":"gt-lkwh3","title":"Merge: nux-mjxeh79t","description":"branch: polecat/nux-mjxeh79t\ntarget: main\nsource_issue: nux-mjxeh79t\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T13:46:29.86447-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T13:48:07.925283-08:00","closed_at":"2026-01-02T13:48:07.925283-08:00","close_reason":"Merged to main"} -{"id":"gt-lm41t","title":"Error Handling: listFromDir suppresses all query errors","description":"The listFromDir function (mailbox.go:115-151) silently ignores errors from queryMessages:\n\n```go\nfunc (m *Mailbox) listFromDir(beadsDir string) ([]*Message, error) { //nolint:unparam\n seen := make(map[string]bool)\n var messages []*Message\n\n for _, identity := range identities {\n for _, status := range []string{\"open\", \"hooked\"} {\n msgs, err := m.queryMessages(beadsDir, \"--assignee\", identity, status)\n if err == nil { // ← errors silently ignored\n for _, msg := range msgs {\n // ...\n }\n }\n }\n }\n // ...\n}\n```\n\nIf ALL queries fail (e.g., beads database is corrupted or bd command is missing), the function returns an empty list with no error. This could lead to:\n1. Silent data loss perception\n2. Difficulty debugging mail issues\n\n**Recommendation**:\n1. Track if at least one query succeeded\n2. If all queries fail, return the last error\n3. Consider logging query failures even when some succeed\n\nFiles:\n- internal/mail/mailbox.go:115-151\n\nSeverity: medium","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/fury","created_at":"2026-01-04T23:48:29.411064-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T00:12:40.646824-08:00","closed_at":"2026-01-05T00:12:40.646824-08:00","close_reason":"Fixed: listFromDir now tracks query failures and returns an error if ALL queries fail. Partial results returned if some queries succeed (graceful degradation)."} -{"id":"gt-lm5y6","title":"Digest: mol-deacon-patrol","description":"Patrol 5: 3 polecats working","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:32:59.612618-08:00","updated_at":"2025-12-29T22:32:59.612618-08:00","closed_at":"2025-12-29T22:32:59.612579-08:00","close_reason":"Squashed from 9 wisps"} -{"id":"gt-lmdk3","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 64: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:14:21.696986-08:00","updated_at":"2026-01-01T13:14:21.696986-08:00","closed_at":"2026-01-01T13:14:21.696956-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-lmtma","title":"Digest: mol-deacon-patrol","description":"Patrol 10: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:46:21.954989-08:00","updated_at":"2025-12-28T19:46:21.954989-08:00","closed_at":"2025-12-28T19:46:21.954953-08:00"} -{"id":"gt-ln5af","title":"gt commands should follow .beads/redirect","description":"## Problem\n\n`gt sling` (and likely other gt commands) don't follow the `.beads/redirect` file that `bd` uses to share beads across clones.\n\nThis caused confusion during the v0.39.0 release: molecules were poured successfully to mayor/rig's beads (via redirect), but `gt sling` couldn't find them because it was looking in the crew clone's local .beads/.\n\n## Expected Behavior\n\nAll `gt` commands that interact with beads should follow the redirect mechanism that `bd` uses.\n\n## Affected Commands (likely)\n\n- `gt sling`\n- `gt hook` \n- `gt mol status`\n- `gt mol attach`\n- Any command that shells out to `bd show` or similar\n\n## Solution\n\nWhen `gt` needs to find the beads directory, check for `.beads/redirect` and follow it, same as `bd` does.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-27T21:15:50.297192-08:00","created_by":"beads/crew/dave","updated_at":"2025-12-27T21:34:34.290471-08:00","closed_at":"2025-12-27T21:34:34.290471-08:00"} -{"id":"gt-lnjbq","title":"Merge: ace-mjyshvac","description":"branch: polecat/ace-mjyshvac\ntarget: main\nsource_issue: ace-mjyshvac\nrig: gastown\nagent_bead: gt-gastown-polecat-ace\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T13:05:25.563871-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-03T13:53:12.82783-08:00","closed_at":"2026-01-03T13:53:12.82783-08:00","close_reason":"Merged"} -{"id":"gt-lo9eu","title":"Integration test: simple file creation","description":"Test task for polecat integration test (gt-7psb8).\n\nSimple task: Create a file ~/gt/gastown/test-polecat-integration.txt with content 'Polecat integration test successful'.\n\nThis is an intentionally trivial task to verify the polecat → witness → refinery → merged flow works end-to-end.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T13:05:23.572068-08:00","created_by":"mayor","updated_at":"2025-12-28T13:07:17.160765-08:00","closed_at":"2025-12-28T13:07:17.160765-08:00"} -{"id":"gt-lozbb","title":"Digest: mol-deacon-patrol","description":"Patrol #5: Health pinged all witnesses.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:17:46.255256-08:00","updated_at":"2025-12-31T19:17:46.255256-08:00","closed_at":"2025-12-31T19:17:46.255221-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-lqgqv","title":"Digest: mol-deacon-patrol","description":"Patrol 160: All healthy - handoff after 20 cycles","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:09:40.741093-08:00","updated_at":"2026-01-01T15:09:40.741093-08:00","closed_at":"2026-01-01T15:09:40.741058-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-lqgqv","depends_on_id":"gt-eph-54rv","type":"parent-child","created_at":"2026-01-01T15:09:40.742379-08:00","created_by":"deacon"}]} -{"id":"gt-ls9sh","title":"Digest: mol-deacon-patrol","description":"Patrol 8","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:50:51.372141-08:00","updated_at":"2025-12-25T20:50:51.372141-08:00","closed_at":"2025-12-25T20:50:51.372074-08:00"} -{"id":"gt-lsjjb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:02:18.589316-08:00","updated_at":"2026-01-01T07:02:18.589316-08:00","closed_at":"2026-01-01T07:02:18.58928-08:00"} -{"id":"gt-ltbaz","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All agents healthy, no issues.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:02:47.123021-08:00","updated_at":"2025-12-28T03:02:47.123021-08:00","closed_at":"2025-12-28T03:02:47.122979-08:00"} -{"id":"gt-lvx6d","title":"Digest: mol-deacon-patrol","description":"Patrol 159 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:10:15.856628-08:00","updated_at":"2025-12-31T16:10:15.856628-08:00","closed_at":"2025-12-31T16:10:15.856591-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-lvxop","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:14:06.479356-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.408601-08:00","closed_at":"2026-01-04T16:40:13.408601-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:14:06-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-lxdn7","title":"Witness: Reduce chattiness, increase autonomy","description":"Witness is spamming Mayor with routine status:\n- 'Polecat X processed' - routine, no action needed\n- 'Idle polecats: X needs work' - wrong direction\n\nWitness should be a local sheriff:\n1. Handle routine lifecycle autonomously (don't report)\n2. Only escalate genuine problems requiring human/mayor intervention\n3. Use convoy system for batch 'work complete' notifications\n4. Never ask Mayor to assign work - either do it yourself or let polecats idle\n\nRemove these mail types:\n- POLECAT_PROCESSED (routine)\n- IDLE_POLECAT (wrong escalation direction)\n\nKeep these:\n- ESCALATION (genuine problem)\n- BLOCKED (needs human decision)\n- CRASH_RECOVERY (informational, useful)","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/dag","created_at":"2025-12-30T22:08:55.915459-08:00","created_by":"mayor","updated_at":"2025-12-30T22:14:50.23626-08:00","closed_at":"2025-12-30T22:14:50.23626-08:00","close_reason":"Implemented: Removed routine POLECAT_PROCESSED and WITNESS_REPORT/REFINERY_REPORT mail types. Witness now handles lifecycle autonomously, only escalating genuine problems."} -{"id":"gt-ly2e8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:23:24.169277-08:00","updated_at":"2026-01-01T11:23:24.169277-08:00","closed_at":"2026-01-01T11:23:24.169228-08:00"} -{"id":"gt-lyc2b","title":"Test refile command","description":"Testing bd refile\n\n(Refiled from bd-v4hq)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-31T12:31:44.910214-08:00","created_by":"beads/crew/grip","updated_at":"2025-12-31T12:32:08.92249-08:00","closed_at":"2025-12-31T12:32:08.92249-08:00","close_reason":"Test cleanup"} -{"id":"gt-lynar","title":"gt done --exit: Self-terminate polecat session after MR submission","description":"## Problem\n\nPolecats finish work, call `gt done`, and then sit idle at Claude prompt waiting for Witness to kill them. This wastes money (idle Claude sessions still cost).\n\n## Solution\n\nAdd `--exit` flag to `gt done` that:\n1. Submits MR to merge queue (existing behavior)\n2. Sends POLECAT_DONE to Witness (existing behavior)\n3. Exits the Claude session immediately (new)\n\n```bash\ngt done --exit # Submit MR and exit session\n```\n\n## Implementation\n\nIn `internal/cmd/done.go`:\n1. Add `--exit` flag\n2. After successful MR submission and witness notification:\n - Print final status\n - Call `os.Exit(0)` OR run `/exit` command\n\n## Notes\n\n- Witness still receives POLECAT_DONE and handles cleanup (nuke worktree) async\n- No waiting = no idle sessions = no wasted money\n- Session exit is safe because all work is pushed and MR submitted before exit","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T13:36:34.314342-08:00","created_by":"mayor","updated_at":"2026-01-02T13:41:59.598647-08:00","closed_at":"2026-01-02T13:41:59.598647-08:00","close_reason":"Implemented --exit flag for session self-termination"} -{"id":"gt-lypj1","title":"Digest: mol-deacon-patrol","description":"Patrol 14 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:46:13.208162-08:00","updated_at":"2025-12-31T16:46:13.208162-08:00","closed_at":"2025-12-31T16:46:13.20813-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-m08q4","title":"Digest: mol-deacon-patrol","description":"Patrol 19: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:45:59.707981-08:00","updated_at":"2025-12-25T13:45:59.707981-08:00","closed_at":"2025-12-25T13:45:59.707951-08:00"} -{"id":"gt-m0at3","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:49:44.787908-08:00","updated_at":"2026-01-01T07:49:44.787908-08:00","closed_at":"2026-01-01T07:49:44.787871-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-m1g43","title":"Session ended: gt-gastown-organic","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:53:49.359265-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-04T16:41:37.866809-08:00","closed_at":"2026-01-04T16:41:37.866809-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/polecats/organic","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:53:49-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-organic\",\"worker\":\"organic\"}"} -{"id":"gt-m23va","title":"Merge: interceptor-mk0vtimo","description":"branch: polecat/interceptor-mk0vtimo\ntarget: main\nsource_issue: interceptor-mk0vtimo\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:15:01.722957-08:00","created_by":"gastown/polecats/interceptor","updated_at":"2026-01-05T19:40:10.360288-08:00","closed_at":"2026-01-05T19:40:10.360288-08:00","close_reason":"Manually merged"} -{"id":"gt-m2jdi","title":"Digest: mol-deacon-patrol","description":"Cycle 182: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:19:20.136627-08:00","updated_at":"2026-01-01T16:19:20.136627-08:00","closed_at":"2026-01-01T16:19:20.136594-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-m2jdi","depends_on_id":"gt-eph-0zog","type":"parent-child","created_at":"2026-01-01T16:19:20.137949-08:00","created_by":"deacon"}]} -{"id":"gt-m3513","title":"Merge: dementus-mjtlqmya","description":"branch: polecat/dementus-mjtlqmya\ntarget: main\nsource_issue: dementus-mjtlqmya\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:11:46.56253-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T23:12:54.51471-08:00","closed_at":"2025-12-30T23:12:54.51471-08:00","close_reason":"Branch already merged"} -{"id":"gt-m39yd","title":"Document asymmetric error handling in initTownAgentBeads","description":"In install.go initTownAgentBeads():\n- Agent bead creation failures return an error (hard fail)\n- Role bead creation failures log a warning and continue (soft fail)\n\nThis asymmetry may be intentional (roles are optional?) but should be documented with a comment explaining the rationale.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/corpus","created_at":"2026-01-03T21:48:46.777842-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T15:38:56.528262-08:00","closed_at":"2026-01-04T15:38:56.528262-08:00","close_reason":"Already merged to main in commit 44e9f81d","dependencies":[{"issue_id":"gt-m39yd","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T21:48:59.541312-08:00","created_by":"gastown/polecats/warboy"}]} -{"id":"gt-m4f69","title":"Digest: mol-deacon-patrol","description":"Patrol 78: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:04:26.634612-08:00","updated_at":"2025-12-31T15:04:26.634612-08:00","closed_at":"2025-12-31T15:04:26.634571-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-m4isg","title":"Digest: mol-deacon-patrol","description":"Patrol 135: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:37:23.075273-08:00","updated_at":"2026-01-01T14:37:23.075273-08:00","closed_at":"2026-01-01T14:37:23.075241-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-m55x2","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:53:10.875161-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.921886-08:00","closed_at":"2026-01-05T00:08:31.921886-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:53:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-m5m4o","title":"Merge: furiosa-1767073359963","description":"attached_args: Code review this merge request\n\nbranch: polecat/furiosa-1767073359963\ntarget: main\nsource_issue: furiosa-1767073359963\nrig: gastown","notes":"REVIEW REJECTED by rictus: Commits claim await-signal but no such code exists. Feature removals conflict with rictus branch quality-level work. Needs clarification and reconciliation.","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/rictus","created_at":"2025-12-29T21:58:58.192817-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-29T23:55:11.903116-08:00","closed_at":"2025-12-29T23:55:11.903116-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-m5w4g","title":"Agent Communication Protocol","description":"Structured mail between agents for coordination.\n\n## Problem\nAgents communicate via freeform mail. This works but lacks parseable structure for automated handling.\n\n## Protocols\n\n### Witness to Refinery\n- POLECAT_READY: worker X completed, branch ready for merge\n- REWORK_COMPLETE: worker Y finished requested rework\n\n### Refinery to Witness \n- MERGE_SUCCESS: worker X merged, can be cleaned up\n- MERGE_FAILED: worker X needs rework (reason attached)\n- REWORK_REQUEST: please have worker X rebase on current main\n\n### Polecat to Witness\n- WORK_COMPLETE: done with assigned issue\n- NEED_HELP: stuck, requesting intervention\n\n### Any to Deacon\n- ESCALATION: problem requiring Mayor attention\n\n## Mail Format\nSubject: [PROTOCOL_TYPE] brief description\nBody: Structured YAML or JSON payload\n\n## Success Criteria\n- Patrol steps parse protocol messages automatically\n- Handlers exist for each protocol type\n- Integration test: polecat completes -\u003e witness notifies -\u003e refinery merges -\u003e witness cleans up\n\nConsolidates gt-0qki.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-25T20:46:35.538744-08:00","updated_at":"2025-12-25T20:46:35.538744-08:00","dependencies":[{"issue_id":"gt-m5w4g","depends_on_id":"gt-psj76","type":"blocks","created_at":"2025-12-25T20:47:18.478538-08:00","created_by":"daemon"}]} -{"id":"gt-m5w4g.1","title":"Protocol message specification","description":"Define YAML format for protocol messages. Subject: [PROTOCOL_TYPE] brief. Body: structured payload. Document all protocol types: POLECAT_READY, MERGE_SUCCESS, MERGE_FAILED, REWORK_REQUEST, WORK_COMPLETE, NEED_HELP, ESCALATION.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2025-12-25T20:56:27.493974-08:00","updated_at":"2025-12-30T09:52:00.20003-08:00","closed_at":"2025-12-30T09:52:00.20003-08:00","close_reason":"Documented YAML format for all protocol messages in docs/mail-protocol.md. Subject format: [PROTOCOL_TYPE] brief. Body: YAML with protocol, timestamp, agent fields. All 8 protocol types fully documented with schemas and examples.","dependencies":[{"issue_id":"gt-m5w4g.1","depends_on_id":"gt-m5w4g","type":"parent-child","created_at":"2025-12-25T20:56:27.494443-08:00","created_by":"daemon"}]} -{"id":"gt-m5w4g.2","title":"Witness-Refinery protocol handlers","description":"Implement handlers for: POLECAT_READY (witness→refinery: worker done, branch ready), MERGE_SUCCESS (refinery→witness: merged, cleanup ok), MERGE_FAILED (refinery→witness: needs rework), REWORK_REQUEST (refinery→witness: rebase needed).","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-25T20:56:28.618916-08:00","updated_at":"2025-12-30T10:42:24.060444-08:00","closed_at":"2025-12-30T10:42:24.060444-08:00","close_reason":"Implemented Witness-Refinery protocol handlers in internal/protocol/ package. Includes message types (MERGE_READY, MERGED, MERGE_FAILED, REWORK_REQUEST), message builders, payload parsers, handler interfaces and default implementations for both Witness and Refinery. Full test coverage added.","dependencies":[{"issue_id":"gt-m5w4g.2","depends_on_id":"gt-m5w4g","type":"parent-child","created_at":"2025-12-25T20:56:28.620996-08:00","created_by":"daemon"},{"issue_id":"gt-m5w4g.2","depends_on_id":"gt-m5w4g.1","type":"blocks","created_at":"2025-12-25T20:56:50.702111-08:00","created_by":"daemon"}]} -{"id":"gt-m5w4g.3","title":"Polecat-Witness protocol handlers","description":"Implement handlers for: WORK_COMPLETE (polecat→witness: done with issue), NEED_HELP (polecat→witness: stuck, requesting intervention). Witness patrol steps should parse and act on these.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/warboy","created_at":"2025-12-25T20:56:29.752982-08:00","updated_at":"2025-12-30T10:40:12.870933-08:00","closed_at":"2025-12-30T10:40:12.870933-08:00","close_reason":"Implemented protocol handlers in internal/witness/protocol.go and handlers.go with tests","dependencies":[{"issue_id":"gt-m5w4g.3","depends_on_id":"gt-m5w4g","type":"parent-child","created_at":"2025-12-25T20:56:29.75638-08:00","created_by":"daemon"},{"issue_id":"gt-m5w4g.3","depends_on_id":"gt-m5w4g.1","type":"blocks","created_at":"2025-12-25T20:56:50.797519-08:00","created_by":"daemon"}]} -{"id":"gt-m5w4g.4","title":"Agent protocol integration test","description":"End-to-end test: polecat completes work → sends WORK_COMPLETE → witness receives and sends POLECAT_READY → refinery merges → sends MERGE_SUCCESS → witness cleans up polecat. All via structured protocol messages.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-25T20:56:31.204129-08:00","updated_at":"2025-12-25T20:56:31.204129-08:00","dependencies":[{"issue_id":"gt-m5w4g.4","depends_on_id":"gt-m5w4g","type":"parent-child","created_at":"2025-12-25T20:56:31.207559-08:00","created_by":"daemon"},{"issue_id":"gt-m5w4g.4","depends_on_id":"gt-m5w4g.2","type":"blocks","created_at":"2025-12-25T20:56:50.900223-08:00","created_by":"daemon"},{"issue_id":"gt-m5w4g.4","depends_on_id":"gt-m5w4g.3","type":"blocks","created_at":"2025-12-25T20:56:50.995873-08:00","created_by":"daemon"}]} -{"id":"gt-m61ew","title":"Polecats go off-task instead of working pinned bead","description":"During swarm execution, polecats frequently stop working on their assigned task (pinned bead) and start doing other things like:\n- Asking about other polecats\n- Checking mail\n- Monitoring swarm status\n- Working on unrelated issues\n\nExpected: Polecat receives task via gt sling, works on it until completion, signals done.\nActual: Polecat gets distracted and stops working on assigned task.\n\nRoot cause hypothesis: CLAUDE.md instructions don't strongly enforce 'work your hook' behavior. Need clearer polecat template that emphasizes single-task focus.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T16:31:51.050113-08:00","created_by":"mayor","updated_at":"2025-12-28T16:42:14.079822-08:00","closed_at":"2025-12-28T16:42:14.079822-08:00"} -{"id":"gt-m6276","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 21: All 3 witnesses and refineries healthy, no orphans, no gates, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:11:19.065021-08:00","updated_at":"2026-01-01T12:11:19.065021-08:00","closed_at":"2026-01-01T12:11:19.064983-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-m63yl","title":"Merge: chumbucket-mk0cdslu","description":"branch: polecat/chumbucket-mk0cdslu\ntarget: main\nsource_issue: chumbucket-mk0cdslu\nrig: gastown\nagent_bead: gt-gastown-polecat-chumbucket\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T15:13:08.896064-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T15:15:03.583984-08:00","closed_at":"2026-01-04T15:15:03.583984-08:00","close_reason":"Merged to main at 507402df"} -{"id":"gt-m7k84","title":"Code review: gt sling --naked fix","description":"Review the fix for gt sling --naked to bypass pane lookup for terminated polecats in internal/cmd/sling.go","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-29T22:20:38.289678-08:00","created_by":"gastown/refinery","updated_at":"2025-12-29T22:26:48.080703-08:00","closed_at":"2025-12-29T22:26:48.080703-08:00","close_reason":"Code review complete. Fix is correct: resolveTargetAgent now accepts skipPane parameter to bypass tmux pane lookup when --naked flag is set. Allows slinging to terminated polecats.","dependencies":[{"issue_id":"gt-m7k84","depends_on_id":"gt-2ocgh","type":"blocks","created_at":"2025-12-29T22:21:05.137343-08:00","created_by":"daemon"}]} -{"id":"gt-m7tz0","title":"Sling reports 'already pinned' but mol status shows empty hook","description":"During swarm operations, gt sling reported beads were 'already pinned' but gt mol status showed nothing on the hook.\n\n**Observed:**\n```\n$ gt sling bd-9btu beads/Nux\nError: bead bd-9btu is already pinned to gt-beads-nux\n\n$ gt mol status beads/Nux\nNothing on hook - no work slung\n```\n\n**Expected:**\nIf a bead is pinned, mol status should show it. If mol status shows empty, sling should work.\n\n**Workaround:**\nUsed --force flag to re-sling, which worked.\n\n**Root cause hypothesis:**\nAgent bead state may be stored in town beads but polecat's local view doesn't see it, or the pin record exists but session state is stale.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-28T22:14:09.211651-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-28T22:37:43.615838-08:00","closed_at":"2025-12-28T22:37:43.615838-08:00"} -{"id":"gt-m99yc","title":"Digest: mol-deacon-patrol","description":"Patrol 12: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:08:09.151846-08:00","updated_at":"2025-12-28T03:08:09.151846-08:00","closed_at":"2025-12-28T03:08:09.151813-08:00"} -{"id":"gt-m9p00","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T16:11:12.111851-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:26.121077-08:00","closed_at":"2026-01-04T16:41:26.121077-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T16:11:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-maoy3","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:53:17.883506-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.914332-08:00","closed_at":"2026-01-05T00:08:31.914332-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:53:17-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-mayor","title":"gt-mayor","description":"gt-mayor\n\nrole_type: mayor\nrig: null\nagent_state: stopped\nhook_bead: null\nrole_bead: gt-mayor-role\ncleanup_status: has_stash\nactive_mr: gt-z4lxc\nnotification_level: null","status":"open","priority":2,"issue_type":"agent","created_at":"2025-12-28T00:07:10.885229-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T14:18:48.48328-08:00","labels":["migrated-to:hq-mayor"],"role_bead":"gt-mayor-role","agent_state":"running","last_activity":"2026-01-03T21:01:09.682079-08:00"} -{"id":"gt-mayor-role","title":"Mayor Role Definition","description":"You are the Mayor - global coordinator of Gas Town. You sit above all rigs,\ncoordinating work across the entire workspace.\n\nsession_pattern: gt-mayor\nwork_dir_pattern: {town}\nneeds_pre_sync: false\nstart_command: exec claude --dangerously-skip-permissions\n\ndefault_molecule: mol-mayor-patrol\ncapabilities:\n - dispatch_work\n - cross_rig_coordination\n - escalation_handling\n\n## Responsibilities\n\n- Work dispatch: Spawn workers for issues, coordinate batch work on epics\n- Cross-rig coordination: Route work between rigs when needed\n- Escalation handling: Resolve issues Witnesses cannot handle\n- Strategic decisions: Architecture, priorities, integration planning\n\nNOT your job: Per-worker cleanup, session killing, nudging workers (Witness handles that)\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nYour pinned molecule persists across sessions. Hook has work then Run it.\nHook empty then Check mail. Nothing anywhere then Wait for user.\n\n## Key Commands\n\n### Communication\n- gt mail inbox - Check your messages\n- gt mail read \u003cid\u003e - Read a specific message\n- gt mail send \u003caddr\u003e -s \"Subject\" -m \"Message\" - Send mail\n\n### Status\n- gt status - Overall town status\n- gt rigs - List all rigs\n- gt polecats \u003crig\u003e - List polecats in a rig\n\n### Work Management\n- bd ready - Issues ready to work (no blockers)\n- gt sling \u003cbead\u003e \u003crig\u003e - Assign work to polecat in rig\n\n## Session End Protocol\n\n- git status, git add, bd sync, git commit, git push\n- gt handoff - hand off to fresh session","status":"hooked","priority":2,"issue_type":"role","assignee":"gastown/polecats/nux","created_at":"2025-12-28T00:51:20.692107-08:00","created_by":"stevey","updated_at":"2025-12-30T02:02:18.922636-08:00","labels":["migrated-to:hq-mayor-role"]} -{"id":"gt-mb6gy","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T18:48:07.110488-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T18:48:07.163669-08:00","closed_at":"2026-01-06T18:48:07.163669-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T18:48:06-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-mbf3t","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:22:35.667221-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:22:35.720665-08:00","closed_at":"2026-01-06T13:22:35.720665-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:22:35-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-mbsa9","title":"Digest: mol-deacon-patrol","description":"Patrol 5: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:04:23.616261-08:00","updated_at":"2025-12-31T18:04:23.616261-08:00","closed_at":"2025-12-31T18:04:23.616216-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mcbkp","title":"Digest: mol-deacon-patrol","description":"Patrol 1: all healthy, 17 sessions, 3 rigs online","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:05:48.711732-08:00","updated_at":"2026-01-01T09:05:48.711732-08:00","closed_at":"2026-01-01T09:05:48.711697-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mcbna","title":"Merge: dag-mjw70jg8","description":"branch: polecat/dag-mjw70jg8\ntarget: main\nsource_issue: dag-mjw70jg8\nrig: gastown\nagent_bead: gt-gastown-polecat-dag","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:43:07.328721-08:00","created_by":"gastown/polecats/dag","updated_at":"2026-01-01T18:57:04.392489-08:00","closed_at":"2026-01-01T18:57:04.392489-08:00","close_reason":"Merged to main at 5a4a691d"} -{"id":"gt-mcch0","title":"Digest: mol-deacon-patrol","description":"Patrol 16: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:28:57.926784-08:00","updated_at":"2025-12-25T07:28:57.926784-08:00","closed_at":"2025-12-25T07:28:57.926736-08:00"} -{"id":"gt-mczna","title":"Session ended: gt-gastown-organic","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:17:55.317464-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-04T16:41:25.99007-08:00","closed_at":"2026-01-04T16:41:25.99007-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/organic","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:17:55-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-organic\",\"worker\":\"organic\"}"} -{"id":"gt-mdwzl","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:05:08.879335-08:00","updated_at":"2026-01-01T20:05:08.879335-08:00","closed_at":"2026-01-01T20:05:08.8793-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-me2rx","title":"Digest: mol-deacon-patrol","description":"Patrol 14: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:09:22.21976-08:00","updated_at":"2025-12-31T18:09:22.21976-08:00","closed_at":"2025-12-31T18:09:22.219722-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mf3i2","title":"Digest: mol-deacon-patrol","description":"Patrol 91: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:23:03.154365-08:00","updated_at":"2025-12-31T15:23:03.154365-08:00","closed_at":"2025-12-31T15:23:03.15433-08:00"} -{"id":"gt-mgztb","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:45:55.864016-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.148647-08:00","closed_at":"2026-01-04T16:41:26.148647-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:45:55-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-mh18d","title":"Digest: mol-deacon-patrol","description":"Patrol 11: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:57:28.9637-08:00","updated_at":"2025-12-26T13:57:28.9637-08:00","closed_at":"2025-12-26T13:57:28.96366-08:00"} -{"id":"gt-mh5s","title":"Refinery gates: test/lint/build before merge","description":"Before merging polecat work to main, run configurable quality gates.\n\n**From VC**: internal/gates/ - parallel execution with timeout, any failure = overall failure.\n\n**Gas Town implementation**: Refinery config with gate commands:\n```yaml\ngates:\n test:\n cmd: go test ./...\n timeout: 5m\n lint:\n cmd: golangci-lint run\n timeout: 2m\n build:\n cmd: go build ./...\n timeout: 3m\nparallel: true\n```\n\nIf gates fail, don't merge. Polecat can iterate and retry.\n\n**Value**: Prevents broken code from reaching main. VC had 90.9% gate pass rate.\n\n**VC complexity**: ~200 lines Go\n**Gas Town complexity**: ~10 lines YAML","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:12.44681-08:00","updated_at":"2025-12-20T20:30:12.44681-08:00","dependencies":[{"issue_id":"gt-mh5s","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.402708-08:00","created_by":"daemon"}]} -{"id":"gt-mh7te","title":"Digest: mol-deacon-patrol","description":"Patrol complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T17:08:53.233547-08:00","updated_at":"2025-12-31T17:08:53.233547-08:00","closed_at":"2025-12-31T17:08:53.233513-08:00"} -{"id":"gt-mhax4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:12:27.536075-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.573261-08:00","closed_at":"2026-01-04T16:40:22.573261-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:12:27-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-mhfpq","title":"Document polecat lifecycle clearly in onboarding and theory of operation","description":"Ensure all workers understand the polecat lifecycle without confusion:\n\n**Key points to clarify:**\n\n1. **Three layers**: Session (ephemeral) vs Sandbox (persistent worktree) vs Slot (name)\n2. **Branch workflow**: Polecats work on ephemeral branches, NOT main\n3. **MR not PR**: Polecats create MRs (merge requests) for Refinery, NOT GitHub PRs\n4. **Lifecycle**: sling → work on branch → mq submit → Refinery merges → nuke\n\n**Where to document:**\n\n- Shared onboarding (templates/polecat-CLAUDE.md or equivalent)\n- Theory of operation section in main docs\n- Keep it concise - clarity over verbosity\n\n**Anti-patterns to call out:**\n- Pushing directly to main (wrong)\n- Creating GitHub PRs (wrong - that's external contributor flow)\n- Deleting polecat branches manually (Refinery/Witness handle this)\n\nReference: docs/polecat-lifecycle.md has the full details, but onboarding needs the essential mental model.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/vuvalini","created_at":"2026-01-04T22:20:57.987661-08:00","created_by":"mayor","updated_at":"2026-01-04T22:24:12.063988-08:00","closed_at":"2026-01-04T22:24:12.063988-08:00","close_reason":"Added polecat lifecycle mental model to templates/polecat-CLAUDE.md with three-layer architecture, lifecycle flow, MR vs PR clarification, and anti-patterns table"} -{"id":"gt-mhtkl","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:48:13.110977-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.132171-08:00","closed_at":"2026-01-04T16:41:26.132171-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:48:13-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-miwvn","title":"Review: Consider extracting Agent base struct","description":"Both Witness and Refinery structs share common fields:\n- RigName string\n- State State \n- PID int\n- StartedAt *time.Time\n\nConsider embedding a common AgentBase:\n```go\ntype AgentBase struct {\n RigName string\n State State\n PID int\n StartedAt *time.Time\n}\n\ntype Witness struct {\n AgentBase\n MonitoredPolecats []string\n Config WitnessConfig\n ...\n}\n```\n\nLower priority since the duplication is small.","status":"open","priority":4,"issue_type":"task","created_at":"2026-01-04T23:46:18.751089-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-04T23:46:18.751089-08:00"} -{"id":"gt-mjroe","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, no orphans, 0 inbox messages","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:34:33.20179-08:00","updated_at":"2025-12-31T21:34:33.20179-08:00","closed_at":"2025-12-31T21:34:33.201753-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mjsjv","title":"Protect vapor formulas from accidental bd pour","description":"When a formula has phase=\"vapor\", it's designed to run as a wisp (ephemeral). Currently 'bd pour' creates persistent issues, which is wrong for vapor formulas.\n\nRoot cause of bd-mol-* pollution: beads-release formula was invoked via 'bd pour beads-release' instead of 'bd mol wisp beads-release' or 'gt sling --formula'.\n\nOptions:\n1. Make 'bd pour' refuse vapor formulas (force gt sling --formula)\n2. Make 'bd pour' auto-invoke wisp creation for vapor formulas\n3. Add prominent warning + confirmation for vapor formulas (current bd behavior with phase=vapor)\n\nRecommendation: Option 1 - refuse with helpful error pointing to gt sling --formula","status":"open","priority":2,"issue_type":"feature","created_at":"2026-01-05T00:03:32.649542-08:00","created_by":"beads/crew/emma","updated_at":"2026-01-05T00:03:32.649542-08:00"} -{"id":"gt-mmp0q","title":"Dynamically discover rigs in checkStaleAgents","description":"In internal/daemon/lifecycle.go:734-735, the rig list is hardcoded:\n\n```go\n// Add rig-specific agents (witness, refinery) for known rigs\n// For now, we check gastown - could be expanded to discover rigs dynamically\nrigs := []string{\"gastown\", \"beads\"}\n```\n\nThis should use gt rigs or similar to dynamically discover configured rigs instead of hardcoding.\n\nAffects: checkStaleAgents() which checks for dead agents that stopped updating their bead state.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2025-12-30T22:24:10.005683-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T23:23:12.585884-08:00","closed_at":"2025-12-30T23:23:12.585884-08:00","close_reason":"Implemented: dynamic rig discovery using config.LoadRigsConfig"} -{"id":"gt-mn2bt","title":"Digest: mol-deacon-patrol","description":"Patrol complete: 20 cycles, handing off","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T17:09:51.782927-08:00","updated_at":"2025-12-31T17:09:51.782927-08:00","closed_at":"2025-12-31T17:09:51.782893-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mo6pd","title":"Digest: mol-deacon-patrol","description":"Patrol #3: All healthy, 1 dog idle. No messages.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:16:55.180938-08:00","updated_at":"2025-12-31T19:16:55.180938-08:00","closed_at":"2025-12-31T19:16:55.180902-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mol-265","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.\n\n## Second-Order Monitoring\n\nWitnesses send WITNESS_PING messages to verify the Deacon is alive. This\nprevents the \"who watches the watchers\" problem - if the Deacon dies,\nWitnesses detect it and escalate to the Mayor.\n\nThe Deacon's agent bead last_activity timestamp is updated during each patrol\ncycle. Witnesses check this timestamp to verify health.","status":"closed","priority":2,"issue_type":"epic","assignee":"gastown/polecats/slit","created_at":"2025-12-30T16:09:54.464672-08:00","updated_at":"2025-12-30T16:55:37.262387-08:00","closed_at":"2025-12-30T16:55:37.262387-08:00","close_reason":"Deacon patrol cycle complete: all 15 steps executed. Key findings: Witness/Refinery healthy, no convoys or gates pending, cleanup flagged for manual fix (7 missing agent beads, 4 stale locks)"} -{"id":"gt-mol-3g1","title":"mol-polecat-work","description":"Full polecat lifecycle from assignment to decommission.\n\nThis proto enables nondeterministic idempotence for polecat work. A polecat that crashes after any step can restart, read its molecule state, and continue from the last completed step. No work is lost.\n\n## Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| issue | Yes | The source issue ID being worked on |","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-25T19:47:48.598459-08:00","updated_at":"2025-12-25T19:56:54.390868-08:00","closed_at":"2025-12-25T19:56:54.390868-08:00"} -{"id":"gt-mol-430","title":"Check convoy completion","description":"Check convoy completion status.\n\nConvoys are coordination beads that track multiple issues across rigs. When all tracked issues close, the convoy auto-closes.\n\n**Step 1: Find open convoys**\n```bash\nbd list --type=convoy --status=open\n```\n\n**Step 2: For each open convoy, check tracked issues**\n```bash\nbd show \u003cconvoy-id\u003e\n# Look for 'tracks' or 'dependencies' field listing tracked issues\n```\n\n**Step 3: If all tracked issues are closed, close the convoy**\n```bash\n# Check each tracked issue\nfor issue in tracked_issues:\n bd show \u003cissue-id\u003e\n # If status is open/in_progress, convoy stays open\n # If all are closed (completed, wontfix, etc.), convoy is complete\n\n# Close convoy when all tracked issues are done\nbd close \u003cconvoy-id\u003e --reason \"All tracked issues completed\"\n```\n\n**Note**: Convoys support cross-prefix tracking (e.g., hq-* convoy can track gt-*, bd-* issues). Use full IDs when checking.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.466252-08:00","updated_at":"2025-12-30T16:48:10.829929-08:00","closed_at":"2025-12-30T16:48:10.829929-08:00","close_reason":"No open convoys found","dependencies":[{"issue_id":"gt-mol-430","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.489544-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-430","depends_on_id":"gt-mol-cp0","type":"blocks","created_at":"2025-12-30T16:09:54.580726-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-74a","title":"Maintain dog pool","description":"Ensure dog pool has available workers for dispatch.\n\n**Step 1: Check dog pool status**\n```bash\ngt dog status\n# Shows idle/working counts\n```\n\n**Step 2: Ensure minimum idle dogs**\nIf idle count is 0 and working count is at capacity, consider spawning:\n```bash\n# If no idle dogs available\ngt dog add \u003cname\u003e\n# Names: alpha, bravo, charlie, delta, etc.\n```\n\n**Step 3: Retire stale dogs (optional)**\nDogs that have been idle for \u003e24 hours can be removed to save resources:\n```bash\ngt dog status \u003cname\u003e\n# Check last_active timestamp\n# If idle \u003e 24h: gt dog remove \u003cname\u003e\n```\n\n**Pool sizing guidelines:**\n- Minimum: 1 idle dog always available\n- Maximum: 4 dogs total (balance resources vs throughput)\n- Spawn on demand when pool is empty\n\n**Exit criteria:** Pool has at least 1 idle dog.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.467751-08:00","updated_at":"2025-12-30T16:51:58.574111-08:00","closed_at":"2025-12-30T16:51:58.574111-08:00","close_reason":"Dog pool feature not yet implemented (gt dog command unavailable)","dependencies":[{"issue_id":"gt-mol-74a","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.52179-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-74a","depends_on_id":"gt-mol-930","type":"blocks","created_at":"2025-12-30T16:09:54.630637-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-81p","title":"Burn and respawn or loop","description":"Burn and let daemon respawn, or exit if context high.\n\nDecision point at end of patrol cycle:\n\nIf context is LOW:\n- Sleep briefly (avoid tight loop)\n- Return to inbox-check step\n\nIf context is HIGH:\n- Write state to persistent storage\n- Exit cleanly\n- Let the daemon orchestrator respawn a fresh Deacon\n\nThe daemon ensures Deacon is always running:\n```bash\n# Daemon respawns on exit\ngt daemon status\n```\n\nThis enables infinite patrol duration via context-aware respawning.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.469512-08:00","updated_at":"2025-12-30T16:55:23.646692-08:00","closed_at":"2025-12-30T16:55:23.646692-08:00","close_reason":"Patrol cycle complete - all 15 steps executed","dependencies":[{"issue_id":"gt-mol-81p","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.560436-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-81p","depends_on_id":"gt-mol-hb9","type":"blocks","created_at":"2025-12-30T16:09:54.676939-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-930","title":"Check Witness and Refinery health","description":"Check Witness and Refinery health for each rig.\n\n**ZFC Principle**: You (Claude) make the judgment call about what is \"stuck\" or \"unresponsive\" - there are no hardcoded thresholds in Go. Read the signals, consider context, and decide.\n\nFor each rig, run:\n```bash\ngt witness status \u003crig\u003e\ngt refinery status \u003crig\u003e\n```\n\n**Signals to assess:**\n\n| Component | Healthy Signals | Concerning Signals |\n|-----------|-----------------|-------------------|\n| Witness | State: running, recent activity | State: not running, no heartbeat |\n| Refinery | State: running, queue processing | Queue stuck, merge failures |\n\n**Tracking unresponsive cycles:**\n\nMaintain in your patrol state (persisted across cycles):\n```\nhealth_state:\n \u003crig\u003e:\n witness:\n unresponsive_cycles: 0\n last_seen_healthy: \u003ctimestamp\u003e\n refinery:\n unresponsive_cycles: 0\n last_seen_healthy: \u003ctimestamp\u003e\n```\n\n**Decision matrix** (you decide the thresholds based on context):\n\n| Cycles Unresponsive | Suggested Action |\n|---------------------|------------------|\n| 1-2 | Note it, check again next cycle |\n| 3-4 | Attempt restart: gt witness restart \u003crig\u003e |\n| 5+ | Escalate to Mayor with context |\n\n**Restart commands:**\n```bash\ngt witness restart \u003crig\u003e\ngt refinery restart \u003crig\u003e\n```\n\n**Escalation:**\n```bash\ngt mail send mayor/ -s \"Health: \u003crig\u003e \u003ccomponent\u003e unresponsive\" \\\n -m \"Component has been unresponsive for N cycles. Restart attempts failed.\n Last healthy: \u003ctimestamp\u003e\n Error signals: \u003cdetails\u003e\"\n```\n\nReset unresponsive_cycles to 0 when component responds normally.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.467158-08:00","updated_at":"2025-12-30T16:51:22.383802-08:00","closed_at":"2025-12-30T16:51:22.383802-08:00","close_reason":"Witness and Refinery healthy: both running, no issues detected","dependencies":[{"issue_id":"gt-mol-930","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.509203-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-930","depends_on_id":"gt-mol-9ye","type":"blocks","created_at":"2025-12-30T16:09:54.60181-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-930","depends_on_id":"gt-mol-qlh","type":"blocks","created_at":"2025-12-30T16:09:54.609066-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-930","depends_on_id":"gt-mol-h71","type":"blocks","created_at":"2025-12-30T16:09:54.616204-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-9ye","title":"Nudge newly spawned polecats","description":"Nudge newly spawned polecats that are ready for input.\n\nWhen polecats are spawned, their Claude session takes 10-20 seconds to initialize. The spawn command returns immediately without waiting. This step finds spawned polecats that are now ready and sends them a trigger to start working.\n\n**ZFC-Compliant Observation** (AI observes AI):\n\n```bash\n# View pending spawns with captured terminal output\ngt deacon pending\n```\n\nFor each pending session, analyze the captured output:\n- Look for Claude's prompt indicator \"\u003e \" at the start of a line\n- If prompt is visible, Claude is ready for input\n- Make the judgment call yourself - you're the AI observer\n\nFor each ready polecat:\n```bash\n# 1. Trigger the polecat\ngt nudge \u003csession\u003e \"Begin.\"\n\n# 2. Clear from pending list\ngt deacon pending \u003csession\u003e\n```\n\nThis triggers the UserPromptSubmit hook, which injects mail so the polecat sees its assignment.\n\n**Bootstrap mode** (daemon-only, no AI available):\nThe daemon uses `gt deacon trigger-pending` with regex detection. This ZFC violation is acceptable during cold startup when no AI agent is running yet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.465648-08:00","updated_at":"2025-12-30T16:12:54.112712-08:00","closed_at":"2025-12-30T16:12:54.112712-08:00","close_reason":"No pending spawns in inbox","dependencies":[{"issue_id":"gt-mol-9ye","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.476685-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-9ye","depends_on_id":"gt-mol-cp0","type":"blocks","created_at":"2025-12-30T16:09:54.567143-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-ake","title":"Execute registered plugins","description":"Execute registered plugins.\n\nScan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with YAML frontmatter defining its gate (when to run) and instructions (what to do).\n\nSee docs/deacon-plugins.md for full documentation.\n\nGate types:\n- cooldown: Time since last run (e.g., 24h)\n- cron: Schedule-based (e.g., \"0 9 * * *\")\n- condition: Metric threshold (e.g., wisp count \u003e 50)\n- event: Trigger-based (e.g., startup, heartbeat)\n\nFor each plugin:\n1. Read plugin.md frontmatter to check gate\n2. Compare against state.json (last run, etc.)\n3. If gate is open, execute the plugin\n\nPlugins marked parallel: true can run concurrently using Task tool subagents. Sequential plugins run one at a time in directory order.\n\nSkip this step if ~/gt/plugins/ does not exist or is empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.467448-08:00","updated_at":"2025-12-30T16:51:59.444409-08:00","closed_at":"2025-12-30T16:51:59.444409-08:00","close_reason":"No plugins registered (~/gt/plugins/ is empty)","dependencies":[{"issue_id":"gt-mol-ake","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.515438-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-ake","depends_on_id":"gt-mol-930","type":"blocks","created_at":"2025-12-30T16:09:54.623366-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-cfu","title":"Self-review","description":"Review your own changes. Look for:\n- Bugs and edge cases\n- Style issues\n- Missing error handling\n- Security concerns\n\nFix any issues found before proceeding.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:47:36.238187-08:00","updated_at":"2025-12-25T19:54:35.405637-08:00","closed_at":"2025-12-25T19:54:35.405637-08:00","dependencies":[{"issue_id":"gt-mol-cfu","depends_on_id":"gt-mol-572","type":"blocks","created_at":"2025-12-25T19:47:36.320187-08:00","created_by":"mayor"}]} -{"id":"gt-mol-cp0","title":"Handle callbacks from agents","description":"Handle callbacks from agents.\n\nCheck the Mayor's inbox for messages from:\n- Witnesses reporting polecat status\n- Refineries reporting merge results\n- Polecats requesting help or escalation\n- External triggers (webhooks, timers)\n\n```bash\ngt mail inbox\n# For each message:\ngt mail read \u003cid\u003e\n# Handle based on message type\n```\n\n**WITNESS_PING**:\nWitnesses periodically ping to verify Deacon is alive. Simply acknowledge\nand archive - the fact that you're processing mail proves you're running.\nYour agent bead last_activity is updated automatically during patrol.\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**HELP / Escalation**:\nAssess and handle or forward to Mayor.\nArchive after handling:\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**LIFECYCLE messages**:\nPolecats reporting completion, refineries reporting merge results.\nArchive after processing:\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**DOG_DONE messages**:\nDogs report completion after infrastructure tasks (orphan-scan, session-gc, etc.).\nSubject format: `DOG_DONE \u003chostname\u003e`\nBody contains: task name, counts, status.\n```bash\n# Parse the report, log metrics if needed\ngt mail read \u003cid\u003e\n# Archive after noting completion\ngt mail archive \u003cmessage-id\u003e\n```\nDogs return to idle automatically. The report is informational - no action needed\nunless the dog reports errors that require escalation.\n\nCallbacks may spawn new polecats, update issue state, or trigger other actions.\n\n**Hygiene principle**: Archive messages after they're fully processed.\nKeep inbox near-empty - only unprocessed items should remain.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.465311-08:00","updated_at":"2025-12-30T16:11:55.760017-08:00","closed_at":"2025-12-30T16:11:55.760017-08:00","close_reason":"Inbox checked, 1 stale message archived","dependencies":[{"issue_id":"gt-mol-cp0","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.469948-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-cub","title":"Rotate logs and prune state","description":"Maintain daemon logs and state files.\n\n**Step 1: Check daemon.log size**\n```bash\n# Get log file size\nls -la ~/.beads/daemon*.log 2\u003e/dev/null || ls -la ~/gt/.beads/daemon*.log 2\u003e/dev/null\n```\n\nIf daemon.log exceeds 10MB:\n```bash\n# Rotate with date suffix and gzip\nLOGFILE=\"$HOME/gt/.beads/daemon.log\"\nif [ -f \"$LOGFILE\" ] \u0026\u0026 [ $(stat -f%z \"$LOGFILE\" 2\u003e/dev/null || stat -c%s \"$LOGFILE\") -gt 10485760 ]; then\n DATE=$(date +%Y-%m-%dT%H-%M-%S)\n mv \"$LOGFILE\" \"${LOGFILE%.log}-${DATE}.log\"\n gzip \"${LOGFILE%.log}-${DATE}.log\"\nfi\n```\n\n**Step 2: Archive old daemon logs**\n\nClean up daemon logs older than 7 days:\n```bash\nfind ~/gt/.beads/ -name \"daemon-*.log.gz\" -mtime +7 -delete\n```\n\n**Step 3: Prune state.json of dead sessions**\n\nThe state.json tracks active sessions. Prune entries for sessions that no longer exist:\n```bash\n# Check for stale session entries\ngt daemon status --json 2\u003e/dev/null\n```\n\nIf state.json references sessions not in tmux:\n- Remove the stale entries\n- The daemon's internal cleanup should handle this, but verify\n\n**Note**: Log rotation prevents disk bloat from long-running daemons.\nState pruning keeps runtime state accurate.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.468627-08:00","updated_at":"2025-12-30T16:53:52.431288-08:00","closed_at":"2025-12-30T16:53:52.431288-08:00","close_reason":"Daemon log at 7MB (under 10MB threshold), no archives over 7 days old","dependencies":[{"issue_id":"gt-mol-cub","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.541159-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-cub","depends_on_id":"gt-mol-lvw","type":"blocks","created_at":"2025-12-30T16:09:54.652903-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-dat","title":"Request shutdown","description":"Send shutdown request to Witness.\nWait for termination.\n\nThe polecat is now ready to be cleaned up.\nDo not exit directly - wait for Witness to kill the session.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:47:10.031563-08:00","updated_at":"2025-12-25T19:54:25.98509-08:00","closed_at":"2025-12-25T19:54:25.98509-08:00"} -{"id":"gt-mol-dna","title":"End-of-cycle inbox hygiene","description":"Verify inbox hygiene before ending patrol cycle.\n\n**Step 1: Check inbox state**\n```bash\ngt mail inbox\n```\n\nInbox should be EMPTY or contain only just-arrived unprocessed messages.\n\n**Step 2: Archive any remaining processed messages**\n\nAll message types should have been archived during inbox-check processing:\n- WITNESS_PING → archived after acknowledging\n- HELP/Escalation → archived after handling\n- LIFECYCLE → archived after processing\n\nIf any were missed:\n```bash\n# For each stale message found:\ngt mail archive \u003cmessage-id\u003e\n```\n\n**Goal**: Inbox should have ≤2 active messages at end of cycle.\nDeacon mail should flow through quickly - no accumulation.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.468921-08:00","updated_at":"2025-12-30T16:54:44.010848-08:00","closed_at":"2025-12-30T16:54:44.010848-08:00","close_reason":"Archived 2 stale messages, inbox now empty","dependencies":[{"issue_id":"gt-mol-dna","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.547566-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-dna","depends_on_id":"gt-mol-cub","type":"blocks","created_at":"2025-12-30T16:09:54.660729-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-h71","title":"Fire notifications","description":"Fire notifications for convoy and cross-rig events.\n\nAfter convoy completion or cross-rig dependency resolution, notify relevant parties.\n\n**Convoy completion notifications:**\nWhen a convoy closes (all tracked issues done), notify the Overseer:\n```bash\n# Convoy gt-convoy-xxx just completed\ngt mail send mayor/ -s \"Convoy complete: \u003cconvoy-title\u003e\" \\\n -m \"Convoy \u003cid\u003e has completed. All tracked issues closed.\n Duration: \u003cstart to end\u003e\n Issues: \u003ccount\u003e\n\n Summary: \u003cbrief description of what was accomplished\u003e\"\n```\n\n**Cross-rig resolution notifications:**\nWhen a cross-rig dependency resolves, notify the affected rig:\n```bash\n# Issue bd-xxx closed, unblocking gt-yyy\ngt mail send gastown/witness -s \"Dependency resolved: \u003cbd-xxx\u003e\" \\\n -m \"External dependency bd-xxx has closed.\n Unblocked: gt-yyy (\u003ctitle\u003e)\n This issue may now proceed.\"\n```\n\n**Notification targets:**\n- Convoy complete → mayor/ (for strategic visibility)\n- Cross-rig dep resolved → \u003crig\u003e/witness (for operational awareness)\n\nKeep notifications brief and actionable. The recipient can run bd show for details.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.466856-08:00","updated_at":"2025-12-30T16:51:05.995083-08:00","closed_at":"2025-12-30T16:51:05.995083-08:00","close_reason":"No convoy completions or cross-rig resolutions to notify","dependencies":[{"issue_id":"gt-mol-h71","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.502658-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-h71","depends_on_id":"gt-mol-k9d","type":"blocks","created_at":"2025-12-30T16:09:54.594748-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-hb9","title":"Check own context limit","description":"Check own context limit.\n\nThe Deacon runs in a Claude session with finite context. Check if approaching the limit:\n\n```bash\ngt context --usage\n```\n\nIf context is high (\u003e80%), prepare for handoff:\n- Summarize current state\n- Note any pending work\n- Write handoff to molecule state\n\nThis enables the Deacon to burn and respawn cleanly.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.469207-08:00","updated_at":"2025-12-30T16:55:07.166448-08:00","closed_at":"2025-12-30T16:55:07.166448-08:00","close_reason":"Context usage command not implemented (gt context --usage unavailable)","dependencies":[{"issue_id":"gt-mol-hb9","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.55394-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-hb9","depends_on_id":"gt-mol-dna","type":"blocks","created_at":"2025-12-30T16:09:54.668866-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-k9d","title":"Resolve external dependencies","description":"Resolve external dependencies across rigs.\n\nWhen an issue in one rig closes, any dependencies in other rigs should be notified. This enables cross-rig coordination without tight coupling.\n\n**Step 1: Check recent closures from feed**\n```bash\ngt feed --since 10m --plain | grep \"✓\"\n# Look for recently closed issues\n```\n\n**Step 2: For each closed issue, check cross-rig dependents**\n```bash\nbd show \u003cclosed-issue\u003e\n# Look at 'blocks' field - these are issues that were waiting on this one\n# If any blocked issue is in a different rig/prefix, it may now be unblocked\n```\n\n**Step 3: Update blocked status**\nFor blocked issues in other rigs, the closure should automatically unblock them (beads handles this). But verify:\n```bash\nbd blocked\n# Should no longer show the previously-blocked issue if dependency is met\n```\n\n**Cross-rig scenarios:**\n- bd-xxx closes → gt-yyy that depended on it is unblocked\n- External issue closes → internal convoy step can proceed\n- Rig A issue closes → Rig B issue waiting on it proceeds\n\nNo manual intervention needed if dependencies are properly tracked - this step just validates the propagation occurred.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.466557-08:00","updated_at":"2025-12-30T16:50:49.267725-08:00","closed_at":"2025-12-30T16:50:49.267725-08:00","close_reason":"No cross-rig closures to propagate; blocked issues are correctly tracked","dependencies":[{"issue_id":"gt-mol-k9d","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.496-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-k9d","depends_on_id":"gt-mol-430","type":"blocks","created_at":"2025-12-30T16:09:54.587873-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-lvw","title":"Detect cleanup needs","description":"**DETECT ONLY** - Check if cleanup is needed and dispatch to dog.\n\n**Step 1: Preview cleanup needs**\n```bash\ngt doctor -v\n# Check output for issues that need cleaning\n```\n\n**Step 2: If cleanup needed, dispatch to dog**\n```bash\n# Sling session-gc formula to an idle dog\ngt sling mol-session-gc deacon/dogs --var mode=conservative\n```\n\n**Important:** Do NOT run `gt doctor --fix` inline. Dogs handle cleanup.\nThe Deacon stays lightweight - detection only.\n\n**Step 3: If nothing to clean**\nSkip dispatch - system is healthy.\n\n**Cleanup types (for reference):**\n- orphan-sessions: Dead tmux sessions\n- orphan-processes: Orphaned Claude processes\n- wisp-gc: Old wisps past retention\n\n**Exit criteria:** Session GC dispatched to dog (if needed).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.46833-08:00","updated_at":"2025-12-30T16:53:21.659155-08:00","closed_at":"2025-12-30T16:53:21.659155-08:00","close_reason":"Cleanup needed (7 missing agent beads, 4 stale locks, 1 diverged clone) but dog dispatch not available - requires manual 'gt doctor --fix'","dependencies":[{"issue_id":"gt-mol-lvw","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.534623-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-lvw","depends_on_id":"gt-mol-znx","type":"blocks","created_at":"2025-12-30T16:09:54.645408-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-qlh","title":"Evaluate pending async gates","description":"Evaluate pending async gates.\n\nGates are async coordination primitives that block until conditions are met.\nThe Deacon is responsible for monitoring gates and closing them when ready.\n\n**Timer gates** (await_type: timer):\nCheck if elapsed time since creation exceeds the timeout duration.\n\n```bash\n# List all open gates\nbd gate list --json\n\n# For each timer gate, check if elapsed:\n# - CreatedAt + Timeout \u003c Now → gate is ready to close\n# - Close with: bd gate close \u003cid\u003e --reason \"Timer elapsed\"\n```\n\n**GitHub gates** (await_type: gh:run, gh:pr) - handled in separate step.\n\n**Human/Mail gates** - require external input, skip here.\n\nAfter closing a gate, the Waiters field contains mail addresses to notify.\nSend a brief notification to each waiter that the gate has cleared.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T16:09:54.465953-08:00","updated_at":"2025-12-30T16:47:13.779001-08:00","closed_at":"2025-12-30T16:47:13.779001-08:00","close_reason":"No pending gates to evaluate","dependencies":[{"issue_id":"gt-mol-qlh","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.483064-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-qlh","depends_on_id":"gt-mol-cp0","type":"blocks","created_at":"2025-12-30T16:09:54.573871-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-mol-znx","title":"Detect abandoned work","description":"**DETECT ONLY** - Check for orphaned state and dispatch to dog if found.\n\n**Step 1: Quick orphan scan**\n```bash\n# Check for in_progress issues with dead assignees\nbd list --status=in_progress --json | head -20\n```\n\nFor each in_progress issue, check if assignee session exists:\n```bash\ntmux has-session -t \u003csession\u003e 2\u003e/dev/null \u0026\u0026 echo \"alive\" || echo \"orphan\"\n```\n\n**Step 2: If orphans detected, dispatch to dog**\n```bash\n# Sling orphan-scan formula to an idle dog\ngt sling mol-orphan-scan deacon/dogs --var scope=town\n```\n\n**Important:** Do NOT fix orphans inline. Dogs handle recovery.\nThe Deacon's job is detection and dispatch, not execution.\n\n**Step 3: If no orphans detected**\nSkip dispatch - nothing to do.\n\n**Exit criteria:** Orphan scan dispatched to dog (if needed).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:09:54.468041-08:00","updated_at":"2025-12-30T16:52:28.808446-08:00","closed_at":"2025-12-30T16:52:28.808446-08:00","close_reason":"No in_progress issues found, no orphans to detect","dependencies":[{"issue_id":"gt-mol-znx","depends_on_id":"gt-mol-265","type":"parent-child","created_at":"2025-12-30T16:09:54.528259-08:00","created_by":"gastown/polecats/rictus"},{"issue_id":"gt-mol-znx","depends_on_id":"gt-mol-74a","type":"blocks","created_at":"2025-12-30T16:09:54.638026-08:00","created_by":"gastown/polecats/rictus"}]} -{"id":"gt-molmall","title":"Mol Mall: Formula marketplace and aspect composition","description":"## Summary\n\nA marketplace for sharing molecule formulas using GitHub as backend, plus a new\n**aspect composition** capability for cooking that allows formulas to be applied\nas cross-cutting transformations to existing mols.\n\n## Key Insight\n\nFormulas aren't just standalone workflows—they're **transformations** you can\napply to other mols. This enables patterns like:\n- \"Apply Rule of Five code review to any coding task\"\n- \"Wrap any epic with security review steps\"\n- \"Add logging/metrics to any patrol molecule\"\n\n## Architecture\n\n```\nRemote Formulas (GitHub)\n ↓ install\nLocal Formulas (~/.gt/formulas/ or .beads/formulas/)\n ↓ cook --with\nMols (beads, git-tracked)\n ↓ pour/sling\nExecution (ephemeral or tracked)\n```\n\n## Formula Types\n\n1. **Standalone** - Complete workflows (mol-polecat-work, mol-deacon-patrol)\n2. **Aspects** - Cross-cutting concerns woven into other mols (rule-of-five)\n3. **Adapters** - Wrappers that make things runnable\n\n## Aspect Composition (New Cooking Capability)\n\n```bash\nbd cook my-epic --with rule-of-five,security-review\n```\n\nAspects declare injection points:\n\n```yaml\n# rule-of-five.formula.yaml\nkind: aspect\nname: rule-of-five\nversion: 1.2.0\n\ninject_after:\n tag: generates-code # matches any step with this tag\n\nsteps:\n - id: review-correctness\n title: \"Review: Correctness\"\n - id: review-edge-cases\n title: \"Review: Edge Cases\"\n - id: review-performance\n title: \"Review: Performance\"\n - id: review-security\n title: \"Review: Security\"\n - id: review-maintainability\n title: \"Review: Maintainability\"\n```\n\nInjection modes:\n- `inject_after: \u003cstep-id or tag\u003e` - insert steps after\n- `inject_before: \u003cstep-id or tag\u003e` - insert steps before\n- `wrap: \u003cstep-id or tag\u003e` - insert before AND after\n- `replace: \u003cstep-id or tag\u003e` - substitute entirely\n\n## The Mall Index\n\nA well-known repo maps short names to full references:\n\n```yaml\n# steveyegge/gt-mall/index.yaml\nformulas:\n rule-of-five:\n repo: steveyegge/gt-formulas\n path: aspects/rule-of-five.formula.yaml\n version: v1.2.0\n description: \"Five-lens code review\"\n tags: [review, quality]\n```\n\nCommands:\n- `gt mol search review` - search the index\n- `gt mol install rule-of-five` - fetch from GitHub\n- `gt mol install github.com/acme/formulas/custom@v1` - direct URL\n\n## Implementation Phases\n\n### Phase 1: Aspect Composition (Cooking)\n- Extend `bd cook` to accept `--with aspect1,aspect2`\n- Aspect application during mol generation\n- Local aspects in `.beads/formulas/`\n\n### Phase 2: Mall Index\n- Create gt-mall repo with index.yaml\n- `gt mol search` queries the index\n- `gt mol install` fetches and caches formulas\n\n### Phase 3: Publishing\n- `gt mol publish` pushes to your formula repo\n- PR workflow to add to mall index\n\n### Phase 4: Refinements\n- Aspect ordering and conflict detection\n- Aspect dependencies (`requires: [other-aspect]`)\n- Private formula repos (enterprise)\n- Local overrides/forks\n\n## Open Questions\n\n1. **Ordering conflicts**: Two aspects inject after same step—which goes first?\n2. **Aspect dependencies**: Aspect A requires aspect B?\n3. **Compile-time vs runtime**: Aspects are compile-time (baked into mol).\n Wisps remain runtime (slung dynamically).\n\n## Deferred Until\n\nGas Town patrols operational. Prerequisites:\n- [ ] Patrol system working (Deacon, Witness, Refinery)\n- [ ] Basic spawn/work/merge cycle\n- [ ] Activity feed showing work progress\n\nThen the mall becomes valuable for sharing patrol customizations.\n\n## Supersedes\n\nThis replaces gt-uzf2l which had the original marketplace concept but lacked\nthe aspect composition insight.\n\n## Related\n\n- Cooking system (bd cook)\n- Formula definitions (.formula.yaml)\n- Wisp architecture (runtime molecules)","notes":"See docs/formula_evolution.md for expanded thinking on: formula resolution hierarchy, combinators (\u003e\u003e, |, wrap, inject, extends), algebraic properties, higher abstractions, Mol Mall registry predictions, distribution scenarios, and open questions. The aspect composition in this design corresponds to the Wrapping (AOP) and Injection combinators in that doc.","status":"deferred","priority":2,"issue_type":"epic","created_at":"2025-12-26T00:33:44.380242-08:00","updated_at":"2025-12-26T00:36:57.3959-08:00"} -{"id":"gt-mpyuq","title":"Refactor: Move formula source of truth to internal/formula/formulas/","description":"## Problem\n\n.beads/formulas/ is tracked in git but polecats using redirects see all formulas as deleted.\nThe internal/formula/formulas/ directory is already tracked (for embedding).\n\n## Current flow\n1. Edit .beads/formulas/ (source of truth)\n2. Run go generate ./... → copies to internal/formula/formulas/\n3. Build embeds from internal/formula/formulas/\n4. ProvisionFormulas() creates .beads/formulas/ from embedded\n\n## Proposed fix\n1. Make internal/formula/formulas/ the ONLY tracked formula location\n2. Remove .beads/formulas/ from git tracking\n3. ProvisionFormulas() already handles runtime provisioning\n4. Developers edit internal/formula/formulas/ directly\n\n## Why this fixes polecat tracking\nPolecats using redirects won't have .beads/formulas/ tracked, eliminating the deleted entries.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T23:38:27.761064-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T23:38:36.94068-08:00"} -{"id":"gt-mqtqs","title":"Merge: capable-mjw47ef9","description":"branch: polecat/capable-mjw47ef9\ntarget: main\nsource_issue: capable-mjw47ef9\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:03:40.714326-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-01T19:07:31.153945-08:00","closed_at":"2026-01-01T19:07:31.153945-08:00","close_reason":"Merged to main at 84450468"} -{"id":"gt-mrp06","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:09:01.49867-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.599154-08:00","closed_at":"2026-01-04T16:40:22.599154-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:09:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-mrqiz","title":"MessagingConfig: Add Type field for schema consistency","description":"MessagingConfig lacks a Type field that other config types have (TownConfig has 'town', RigConfig has 'rig', etc). Add Type: 'messaging' for consistency.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:29:07.944151-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T15:31:31.414268-08:00","closed_at":"2025-12-28T15:31:31.414268-08:00"} -{"id":"gt-ms8s4","title":"gt start --all leaves crew 'running' but 'dead'","description":"dispatched_by: mayor\n\nIn start.go, startConfiguredCrew() (line 265) only checks t.HasSession() but doesn't verify Claude is alive with t.IsClaudeRunning(). Compare to runStartCrew() (lines 774-785) which correctly checks IsClaudeRunning and restarts Claude if dead. Fix: add the same IsClaudeRunning check to startConfiguredCrew, restart Claude with BuildCrewStartupCommand if dead.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2026-01-05T16:30:16.472981-08:00","created_by":"mayor","updated_at":"2026-01-05T16:33:06.092382-08:00","closed_at":"2026-01-05T16:33:06.092382-08:00","close_reason":"Fixed: added IsClaudeRunning check to startConfiguredCrew(), restarts Claude if session exists but Claude is dead"} -{"id":"gt-msea3","title":"Merge: dementus-mjw46vz4","description":"branch: polecat/dementus-mjw46vz4\ntarget: main\nsource_issue: dementus-mjw46vz4\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:05:57.621708-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-01T19:12:07.190383-08:00","closed_at":"2026-01-01T19:12:07.190383-08:00","close_reason":"All commits already on main - duplicate MR"} -{"id":"gt-mslti","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:56:17.045007-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.499166-08:00","closed_at":"2026-01-05T19:44:18.499166-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:56:11-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-msx70","title":"Merge: morsov-1766966180179","description":"branch: polecat/morsov-1766966180179\ntarget: main\nsource_issue: morsov-1766966180179\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-28T16:23:39.96724-08:00","created_by":"stevey","updated_at":"2025-12-28T22:28:06.116059-08:00","closed_at":"2025-12-28T22:28:06.116059-08:00"} -{"id":"gt-mt3d6","title":"Merge: imperator-mjz958gg","description":"branch: polecat/imperator-mjz958gg\ntarget: main\nsource_issue: imperator-mjz958gg\nrig: gastown\nagent_bead: gt-gastown-polecat-imperator\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T20:57:42.240123-08:00","created_by":"gastown/polecats/imperator","updated_at":"2026-01-03T21:10:36.977747-08:00","closed_at":"2026-01-03T21:10:36.977747-08:00","close_reason":"Merged to main at 1532a08a"} -{"id":"gt-muv12","title":"Merge: road-warrior","description":"branch: polecat/road-warrior-mk0vt2ef\ntarget: main\nsource_issue: road-warrior\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:18:31.515917-08:00","created_by":"gastown/polecats/road-warrior","updated_at":"2026-01-05T19:40:10.45908-08:00","closed_at":"2026-01-05T19:40:10.45908-08:00","close_reason":"Manually merged"} -{"id":"gt-muwit","title":"mol-sync-workspace: Add vars for build/test commands","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T19:11:03.816454-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T22:26:25.599683-08:00","closed_at":"2025-12-30T22:26:25.599683-08:00","close_reason":"Added build_command and test_command variables to mol-sync-workspace formula with template placeholders"} -{"id":"gt-mv8ve","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:00:41.739402-08:00","updated_at":"2026-01-01T07:00:41.739402-08:00","closed_at":"2026-01-01T07:00:41.739367-08:00"} -{"id":"gt-mvwy3","title":"Digest: mol-deacon-patrol","description":"Patrol 248 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:20:21.590539-08:00","updated_at":"2026-01-01T17:20:21.590539-08:00","closed_at":"2026-01-01T17:20:21.590499-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-mwhcd","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:42:17.081544-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.725068-08:00","closed_at":"2026-01-05T19:44:18.725068-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:42:17-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-mwpcq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:19:40.396361-08:00","updated_at":"2025-12-28T11:19:40.396361-08:00","closed_at":"2025-12-28T11:19:40.396326-08:00"} -{"id":"gt-mwvtc","title":"Digest: mol-deacon-patrol","description":"Patrol 14: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:04:57.241057-08:00","updated_at":"2026-01-01T23:04:57.241057-08:00","closed_at":"2026-01-01T23:04:57.241022-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-mxdhx","title":"Merge: dementus-mjto0502","description":"branch: polecat/dementus-mjto0502\ntarget: main\nsource_issue: dementus-mjto0502\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T23:07:35.765554-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T23:12:30.919516-08:00","closed_at":"2025-12-30T23:12:30.919516-08:00","close_reason":"Branch already merged"} -{"id":"gt-mymn0","title":"INVESTIGATE: Patrol frequency and reliability","description":"During shutdown cleanup, several issues were found that should have been caught by patrols:\n- 128 wisps in main beads\n- 34 stale hooked handoffs\n- Many dead polecats\n- Accumulated unread mail in witness/refinery inboxes\n\nQuestions:\n1. How often are deacon/witness patrols actually running?\n2. Are they completing successfully or dying mid-patrol?\n3. Is the daemon respawning them properly?\n4. Are there logs showing patrol activity?\n\nCheck:\n- gt deacon patrol logs\n- Witness patrol frequency\n- Daemon health/respawn behavior\n\nThis may indicate patrol infrastructure issues rather than just missing logic.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T20:39:45.629949-08:00","created_by":"mayor","updated_at":"2026-01-04T20:44:15.969937-08:00","closed_at":"2026-01-04T20:44:15.969937-08:00","close_reason":"Not a patrol issue - root cause is digest-\u003ewisp dependencies causing export pollution (see gt-de324)"} -{"id":"gt-myyb4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:27:37.422882-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.619149-08:00","closed_at":"2026-01-05T19:44:18.619149-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:27:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-mzal","title":"mol-gastown-boot: Mayor-driven town bootstrap","description":"Mayor bootstraps Gas Town via a verification-gated lifecycle molecule.\n\n## Vision\n\nWhen user says \"boot up gas town\", Mayor slings `mol-gastown-boot` and executes it.\nEach step has **action + verification** - steps stay open until outcome is confirmed.\n\n## Key Principles\n\n1. **No daemon-based timeouts** - Mayor keeps trying until verified\n2. **Verification-gated steps** - Not \"command ran\" but \"outcome confirmed\"\n3. **gt peek for verification** - Capture session output to detect stalls\n4. **gt nudge for recovery** - Reliable message delivery to unstick agents\n5. **Parallel where possible** - Witnesses can start in parallel\n6. **Ephemeral execution** - Boot is a wisp, squashed to digest\n\n## Proto Catalog\n\nTown maintains a catalog of protos at `~/gt/molecules/`:\n\n```\n~/gt/molecules/\n├── lifecycle/\n│ ├── gastown-boot/ # Full town bootstrap\n│ ├── rig-spinup/ # Add a rig at runtime\n│ ├── rig-spindown/ # Remove a rig gracefully\n│ └── agent-restart/ # Restart single agent\n├── patrol/\n│ ├── deacon-patrol/ # Deacon health loop\n│ ├── witness-patrol/ # Witness polecat loop\n│ └── refinery-patrol/ # Refinery merge loop\n└── work/\n ├── polecat-work/ # Standard issue workflow\n ├── code-review/ # Pluggable review\n └── feature/ # Feature development\n```\n\n## mol-gastown-boot Structure\n\n```\nmol-gastown-boot (proto)\n├── ensure-daemon # Verify daemon running\n├── ensure-deacon # Start deacon, verify patrol active\n├── ensure-witnesses # Parallel: all rig witnesses\n│ ├── ensure-gastown-witness\n│ └── ensure-beads-witness\n├── ensure-refineries # Parallel: all rig refineries\n│ ├── ensure-gastown-refinery\n│ └── ensure-beads-refinery\n└── verify-town-health # Final gt status check\n```\n\n## Step Template\n\nEach step in description includes action + verification:\n\n```markdown\n## Step: ensure-deacon\n\n### Action\ngt deacon start\n\n### Verify\n1. Session gt-deacon exists: `tmux has-session -t gt-deacon`\n2. Not stalled: `gt peek deacon/` does NOT show \"\u003e Try\"\n3. Recent heartbeat: deacon/heartbeat.json \u003c 2 min old\n\n### On Stall\ngt nudge deacon/ \"Start patrol.\"\nWait 30s, re-verify.\n\n### On Fail\nLog error, continue to next step (town can run with degraded deacon)\n```\n\n## Event-Triggered Lifecycle\n\nBeyond manual slinging, events can trigger lifecycle wisps:\n\n| Event | Triggers |\n|-------|----------|\n| `gt town start` | mol-gastown-boot wisp |\n| `gt rig add \u003cname\u003e` | mol-rig-spinup wisp |\n| `gt rig remove \u003cname\u003e` | mol-rig-spindown wisp |\n| Agent crash detected | mol-agent-restart wisp |\n\n## Parameterization (Future)\n\nFor rig-spinup/spindown, need to pass rig name:\n\n```bash\ngt sling rig-spinup mayor/ --param rig=newproject\n```\n\nMolecule steps interpolate `${rig}` in their descriptions.\n\n## Related Issues\n\n- gt-lx3n: Witness startup bond\n- gt-j6s8: Refinery startup bond \n- gt-rana: Patrol System epic\n- gt-sye: Mayor startup protocol\n","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-22T20:59:15.795091-08:00","updated_at":"2025-12-27T14:20:23.310588-08:00","dependencies":[{"issue_id":"gt-mzal","depends_on_id":"gt-psj76","type":"blocks","created_at":"2025-12-25T20:47:20.336192-08:00","created_by":"daemon"},{"issue_id":"gt-mzal","depends_on_id":"gt-p3v5n","type":"blocks","created_at":"2025-12-25T20:47:21.588707-08:00","created_by":"daemon"},{"issue_id":"gt-mzal","depends_on_id":"gt-twjr5","type":"blocks","created_at":"2025-12-25T20:55:05.227776-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.2","title":"Implement verification patterns for boot steps","description":"Define and implement the verification logic Mayor uses.\n\n## Verification Utilities\n\nMayor needs to check:\n\n### Session Exists\n```bash\ntmux has-session -t \u003csession\u003e 2\u003e/dev/null \u0026\u0026 echo \"exists\"\n```\n\n### Not Stalled (Claude waiting at prompt)\n```bash\ngt peek \u003cagent\u003e 10 | grep -q \"\u003e Try\" \u0026\u0026 echo \"stalled\"\n```\n\nPattern: `\u003e Try \"...\"` indicates Claude started but no message sent.\n\n### Recent Heartbeat\n```bash\n# For deacon\nage=$(( $(date +%s) - $(stat -f %m ~/gt/deacon/heartbeat.json) ))\n[ $age -lt 120 ] \u0026\u0026 echo \"fresh\"\n```\n\n### Active Work Output\n```bash\ngt peek \u003cagent\u003e 20 | grep -q \"⏺\" \u0026\u0026 echo \"working\"\n```\n\nPattern: `⏺` indicates Claude is executing tools.\n\n## Mayor Execution Pattern\n\n```\nfor each step in molecule:\n run action\n loop:\n check verification\n if verified: close step, continue\n if stalled: run on_stall recovery\n if timeout (5 attempts): log warning, continue\n sleep 10s\n```\n\nNo hard timeout - Mayor keeps trying with increasing backoff.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:00:14.665689-08:00","updated_at":"2025-12-27T14:20:23.337408-08:00","dependencies":[{"issue_id":"gt-mzal.2","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:14.666085-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.3","title":"Create molecules catalog directory structure","description":"Establish the proto catalog at ~/gt/molecules/.\n\n## Structure\n\n```\n~/gt/molecules/\n├── README.md # Catalog overview\n├── lifecycle/\n│ ├── gastown-boot/\n│ │ └── PROTO.md # Proto definition in markdown\n│ ├── rig-spinup/\n│ ├── rig-spindown/\n│ └── agent-restart/\n├── patrol/\n│ ├── deacon-patrol/\n│ ├── witness-patrol/\n│ └── refinery-patrol/\n└── work/\n ├── polecat-work/\n ├── code-review/\n └── feature/\n```\n\n## PROTO.md Format\n\n```markdown\n---\ntype: lifecycle\nparallel: [ensure-witnesses, ensure-refineries]\nephemeral: true\n---\n\n# mol-gastown-boot\n\nTown bootstrap molecule.\n\n## Step: ensure-daemon\n...\n```\n\n## Catalog Loading\n\n`gt sling gastown-boot` should find the proto by:\n1. Check beads for existing proto issue\n2. If not found, scan ~/gt/molecules/lifecycle/gastown-boot/\n3. Auto-create proto issue from PROTO.md\n\nThis enables file-based proto development with beads tracking.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:00:16.200342-08:00","updated_at":"2025-12-22T21:00:16.200342-08:00","dependencies":[{"issue_id":"gt-mzal.3","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:16.202058-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.4","title":"Add parallel step support to molecules","description":"Enable steps to run in parallel within a molecule.\n\n## Current State\n\nMolecules have linear step dependencies via \"Needs:\" directive.\nSteps run sequentially.\n\n## Proposed Change\n\nAdd parallel grouping:\n\n```markdown\n## Step: ensure-witnesses\nParallel: true\n\n### Sub-steps\n- ensure-gastown-witness\n- ensure-beads-witness\n```\n\nOr via frontmatter:\n\n```yaml\n---\nparallel: [ensure-witnesses, ensure-refineries]\n---\n```\n\nSteps in parallel group:\n- Start simultaneously\n- Parent step closes when all children complete\n- Failures in one dont block others\n\n## Implementation\n\n1. Parse parallel directive in proto\n2. When bonding, create child steps with same dependency\n3. Executor spawns parallel children concurrently\n4. Track completion, close parent when all done\n\n## For Mayor Bootstrap\n\nMayor can check all witnesses in parallel, then all refineries,\nrather than sequentially. Faster boot time.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:00:21.347723-08:00","updated_at":"2025-12-22T21:00:21.347723-08:00","dependencies":[{"issue_id":"gt-mzal.4","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:21.348229-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.5","title":"Add event-triggered lifecycle wisps","description":"Commands like `gt town start` should auto-trigger lifecycle wisps.\n\n## Event → Wisp Mapping\n\n| Command | Triggers Wisp |\n|---------|---------------|\n| gt town start | mol-gastown-boot |\n| gt rig add \u003cname\u003e | mol-rig-spinup (param: rig=\u003cname\u003e) |\n| gt rig remove \u003cname\u003e | mol-rig-spindown (param: rig=\u003cname\u003e) |\n| gt daemon restart | mol-gastown-boot |\n\n## Implementation\n\n1. Command implementation checks for lifecycle proto\n2. Auto-slings wisp to Mayor with --wisp flag\n3. Mayor picks up via molecule attachment\n\n## Alternative: Explicit Sling\n\nKeep commands simple, require explicit:\n\n```bash\ngt town start # Just starts sessions\ngt sling gastown-boot mayor/ --wisp # Bootstrap with verification\n```\n\nThis is more transparent - user sees the sling happen.\n\n## Recommendation\n\nStart with explicit sling. Add auto-trigger later once pattern proven.\n`gt town start --verified` could trigger the wisp.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:00:22.311873-08:00","updated_at":"2025-12-22T21:00:22.311873-08:00","dependencies":[{"issue_id":"gt-mzal.5","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:22.313864-08:00","created_by":"daemon"},{"issue_id":"gt-mzal.5","depends_on_id":"gt-mzal.3","type":"blocks","created_at":"2025-12-22T21:01:00.190423-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.6","title":"Design molecule parameterization","description":"Enable protos to accept parameters for customization.\n\n## Use Cases\n\n1. rig-spinup needs rig name: `gt sling rig-spinup --param rig=newproject`\n2. agent-restart needs agent: `gt sling agent-restart --param agent=gastown/witness`\n3. code-review needs scope: `gt sling code-review --param scope=src/auth/`\n\n## Proposed Syntax\n\n### In Proto\n\n```markdown\n## Step: create-rig-structure\nmkdir -p ~/gt/${rig}/refinery ~/gt/${rig}/witness\n```\n\n### In Sling\n\n```bash\ngt sling rig-spinup mayor/ --param rig=newproject --wisp\n```\n\n### In Bonded Molecule\n\nInterpolation happens at bond time. Step descriptions have concrete values.\n\n## Implementation\n\n1. Proto declares params in frontmatter: `params: [rig]`\n2. gt sling validates required params provided\n3. bd mol bond receives params, interpolates descriptions\n4. Bonded molecule has concrete step text\n\n## Edge Cases\n\n- Missing required param → error\n- Unused param → warning\n- Param in step title → interpolate there too\n","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-22T21:00:23.35376-08:00","updated_at":"2025-12-28T22:34:14.47731-08:00","closed_at":"2025-12-28T22:34:14.47731-08:00","dependencies":[{"issue_id":"gt-mzal.6","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:23.354175-08:00","created_by":"daemon"}]} -{"id":"gt-mzal.8","title":"Update Mayor startup protocol for bootstrap","description":"Teach Mayor to respond to \"boot up gas town\" by slinging mol-gastown-boot.\n\n## Current Protocol\n\n1. Announce: \"Mayor, checking in.\"\n2. Check mail\n3. If handoff, continue\n4. Await user instruction\n\n## Enhanced Protocol\n\n1. Announce: \"Mayor, checking in.\"\n2. Check mail\n3. If handoff, continue\n4. **If user says \"boot\"/\"startup\"/\"bootstrap\":**\n - Sling mol-gastown-boot as wisp\n - Execute verification-gated steps\n - Report town status when complete\n5. Otherwise await instruction\n\n## Trigger Phrases\n\n- \"boot up gas town\"\n- \"bootstrap the town\"\n- \"start gas town\"\n- \"bring up the town\"\n\n## Execution\n\nMayor runs the molecule manually (not via subagent):\n\n```\n1. Bond the proto: bd mol bond mol-gastown-boot --wisp\n2. For each step:\n a. Run action command\n b. Loop verification with backoff\n c. On stall, run recovery\n d. Close step when verified\n3. Squash wisp with summary\n4. Report: \"Gas Town is up. All agents healthy.\"\n```\n\n## CLAUDE.md Update\n\nAdd to Mayor CLAUDE.md:\n\n```markdown\n## Bootstrap Command\n\nWhen user requests town bootstrap:\n1. gt sling gastown-boot mayor/ --wisp\n2. Execute molecule steps with verification\n3. Keep trying until all agents healthy\n4. No timeouts - you are the town engineer\n```\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:00:50.429735-08:00","updated_at":"2025-12-27T14:20:23.364445-08:00","dependencies":[{"issue_id":"gt-mzal.8","depends_on_id":"gt-mzal","type":"parent-child","created_at":"2025-12-22T21:00:50.430131-08:00","created_by":"daemon"},{"issue_id":"gt-mzal.8","depends_on_id":"gt-mzal.1","type":"blocks","created_at":"2025-12-22T21:00:59.16763-08:00","created_by":"daemon"},{"issue_id":"gt-mzal.8","depends_on_id":"gt-mzal.2","type":"blocks","created_at":"2025-12-22T21:00:59.231779-08:00","created_by":"daemon"}]} -{"id":"gt-n1010","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy. Handoff after 20 cycles.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:11:45.170133-08:00","updated_at":"2025-12-28T03:11:45.170133-08:00","closed_at":"2025-12-28T03:11:45.170097-08:00"} -{"id":"gt-n23v2","title":"Digest: mol-deacon-patrol","description":"Patrol 19: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:36:23.752064-08:00","updated_at":"2025-12-29T22:36:23.752064-08:00","closed_at":"2025-12-29T22:36:23.752031-08:00"} -{"id":"gt-n3f5t","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:10:25.127092-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.193947-08:00","closed_at":"2026-01-04T16:41:26.193947-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:10:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-n5gga","title":"Convoy shows wrong assignee after re-sling","description":"When work is re-slung to a new polecat, convoy status still shows the original assignee.\n\nExample: gt-3jnnu was originally slung to bullet, then re-slung to toecutter. Convoy may still show [bullet].\n\nNeed to verify:\n1. Does convoy update assignee on re-sling?\n2. Is this just stale display or actual tracking issue?\n\nLow priority - cosmetic if work is actually running correctly.","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/shiny","created_at":"2026-01-04T10:41:43.597623-08:00","created_by":"mayor","updated_at":"2026-01-05T00:20:57.253916-08:00","closed_at":"2026-01-05T00:20:57.253916-08:00","close_reason":"Fixed BEADS_DIR override for rig-level beads in sling.go and added --no-daemon to convoy bd show calls"} -{"id":"gt-n5pl7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:48:32.399494-08:00","updated_at":"2026-01-01T07:48:32.399494-08:00","closed_at":"2026-01-01T07:48:32.399456-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-n6mjs","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:28:51.084791-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:00.357779-08:00","closed_at":"2026-01-04T16:41:00.357779-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:28:51-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-n7bxb","title":"Digest: mol-deacon-patrol","description":"Patrol 82: All agents healthy, quiet cycle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:16:17.424414-08:00","updated_at":"2025-12-31T15:16:17.424414-08:00","closed_at":"2025-12-31T15:16:17.424383-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-n7mzo","title":"Digest: mol-deacon-patrol","description":"Patrol 134: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:36:58.399161-08:00","updated_at":"2026-01-01T14:36:58.399161-08:00","closed_at":"2026-01-01T14:36:58.399129-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-n7xxc","title":"Merge: gt-594l2","description":"branch: polecat/morsov-1766966180179\ntarget: main\nsource_issue: gt-594l2\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-28T16:37:28.154049-08:00","created_by":"gastown/polecats/morsov","updated_at":"2025-12-28T22:28:06.12421-08:00","closed_at":"2025-12-28T22:28:06.12421-08:00"} -{"id":"gt-n8xdz","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy. 3 rigs, 6 agents. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:07:18.872456-08:00","updated_at":"2026-01-01T08:07:18.872456-08:00","closed_at":"2026-01-01T08:07:18.872421-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-n93hc","title":"Digest: mol-deacon-patrol","description":"Cycle 5: healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:53:29.618211-08:00","updated_at":"2025-12-31T23:53:29.618211-08:00","closed_at":"2025-12-31T23:53:29.618175-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-n9ruv","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:44:51.391038-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:40:22.972703-08:00","closed_at":"2026-01-04T16:40:22.972703-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:44:51-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-na6o2","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All healthy, no messages, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T23:58:44.4382-08:00","updated_at":"2025-12-24T23:58:44.4382-08:00","closed_at":"2025-12-24T23:58:44.438166-08:00"} -{"id":"gt-naahs","title":"Digest: mol-deacon-patrol","description":"Patrol 4: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:02:05.298482-08:00","updated_at":"2025-12-31T19:02:05.298482-08:00","closed_at":"2025-12-31T19:02:05.298446-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nahxr","title":"Digest: mol-deacon-patrol","description":"Patrol 8: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:26:45.974483-08:00","updated_at":"2025-12-25T07:26:45.974483-08:00","closed_at":"2025-12-25T07:26:45.974453-08:00"} -{"id":"gt-naqze","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: all healthy, handing off","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:25:54.601852-08:00","updated_at":"2026-01-01T07:25:54.601852-08:00","closed_at":"2026-01-01T07:25:54.601816-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nbun3","title":"Session ended: gt-gastown-corpus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:05:42.561666-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-05T00:08:31.891764-08:00","closed_at":"2026-01-05T00:08:31.891764-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/corpus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:05:42-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-corpus\",\"worker\":\"corpus\"}"} -{"id":"gt-nc9y","title":"gt polecat done should auto-stop running session","description":"Currently 'gt polecat done' fails if session is running, requiring a separate 'gt session stop' first. This is unnecessary friction - done should just stop the session automatically since that's always what you want.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T04:12:13.30724-08:00","updated_at":"2025-12-23T04:12:13.30724-08:00"} -{"id":"gt-ncjie","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All agents healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:41:59.021605-08:00","updated_at":"2025-12-31T23:41:59.021605-08:00","closed_at":"2025-12-31T23:41:59.021569-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ncnig","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy, 17 sessions","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:54:43.880017-08:00","updated_at":"2026-01-01T08:54:43.880017-08:00","closed_at":"2026-01-01T08:54:43.879981-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ncq26","title":"Witness checks wrong remote for merge verification","description":"## Problem\n\nWitness patrol checks `origin/main` to verify if polecat commits are merged, but in multi-remote setups the code lives on a different remote (e.g., `gastown/main`).\n\n## Evidence\n\nFrom witness tmux output:\n```\ngit merge-base --is-ancestor 9876a962 origin/main \u0026\u0026 echo \"MERGED\" || echo \"NOT MERGED\"\n→ NOT MERGED - preserve\n```\n\nBut the commit IS merged to `gastown/main`:\n```\ngit log gastown/main | grep 9876a962\n→ 9876a962 perf: Batch and parallelize convoy worker lookups\n```\n\n## Root Cause\n\nwitness/rig has multiple remotes:\n- `origin` → stevey-gt.git (beads sync)\n- `gastown` → gastown.git (actual code)\n\nWitness hardcodes `origin/main` instead of detecting the correct code remote.\n\n## Fix\n\nEither:\n1. Use rig config to specify the code remote name\n2. Check all remotes for the commit\n3. Standardize remote naming across all clones","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/chumbucket","created_at":"2026-01-04T15:07:21.212339-08:00","created_by":"mayor","updated_at":"2026-01-04T15:12:34.452826-08:00","closed_at":"2026-01-04T15:12:34.452826-08:00","close_reason":"Closed"} -{"id":"gt-ncs1e","title":"Digest: mol-deacon-patrol","description":"Patrol 206: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:50:18.133953-08:00","updated_at":"2026-01-01T16:50:18.133953-08:00","closed_at":"2026-01-01T16:50:18.133916-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-ncs1e","depends_on_id":"gt-eph-jysi","type":"parent-child","created_at":"2026-01-01T16:50:18.135303-08:00","created_by":"deacon"}]} -{"id":"gt-nduix","title":"Merge: nux-1767138828269","description":"branch: polecat/nux-1767138828269\ntarget: main\nsource_issue: nux-1767138828269\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:17:54.717032-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T18:23:22.173668-08:00","closed_at":"2025-12-30T18:23:22.173668-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-ne9he","title":"gt crew add: role_bead field references non-existent bead","description":"## Problem\n\nWhen `gt crew add` creates an agent bead (e.g., `gt-crew-gastown-grip`), it sets:\n```\nrole_bead: gt-crew-gastown-grip-role\n```\n\nThis is WRONG. It creates per-instance role bead references that don't exist.\n\n## Correct Pattern\n\nRole beads are SHARED templates defining what a role IS. Agent beads reference them:\n\n| Role Type | Role Bead (shared) | Agent Bead (per-instance) |\n|-----------|-------------------|---------------------------|\n| Mayor | gt-mayor-role | gt-mayor |\n| Deacon | gt-deacon-role | gt-deacon |\n| Witness | gt-witness-role | gt-witness-\u003crig\u003e |\n| Refinery | gt-refinery-role | gt-refinery-\u003crig\u003e |\n| Crew | gt-crew-role | gt-crew-\u003crig\u003e-\u003cname\u003e |\n| Polecat | gt-polecat-role | gt-polecat-\u003crig\u003e-\u003cname\u003e |\n\n## Current State\n\nWorking correctly:\n- gt-mayor → gt-mayor-role ✅\n- gt-witness-gastown → gt-witness-role ✅\n- gt-refinery-gastown → gt-refinery-role ✅\n\nBroken:\n- gt-deacon → gt-deacon-role (bead doesn't exist)\n- gt-crew-* → gt-crew-\u003crig\u003e-\u003cname\u003e-role (wrong pattern, beads don't exist)\n- gt-polecat-* → (not set at all)\n\n## Code Locations\n\n1. `internal/cmd/crew_add.go:91` - sets `RoleBead: crewID + \"-role\"`\n Should be: `RoleBead: \"gt-crew-role\"`\n\n2. `internal/polecat/manager.go:220,426` - doesn't set RoleBead\n Should set: `RoleBead: \"gt-polecat-role\"`\n\n## Fix Required\n\n1. Create missing role beads: gt-crew-role, gt-polecat-role, gt-deacon-role\n2. Fix crew_add.go to use shared gt-crew-role\n3. Fix polecat/manager.go to use shared gt-polecat-role\n4. Update existing crew agent beads to point to gt-crew-role","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-29T13:03:46.315753-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T13:42:28.491572-08:00","closed_at":"2025-12-29T13:42:28.491572-08:00","close_reason":"Fixed. Created shared role beads (gt-crew-role, gt-polecat-role, gt-deacon-role). Fixed code to reference shared role beads. Updated existing crew agent beads via bd slot set."} -{"id":"gt-neytk","title":"Session ended: gt-gastown-refinery","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:08:37.645411-08:00","created_by":"gastown/refinery","updated_at":"2026-01-04T16:40:13.444684-08:00","closed_at":"2026-01-04T16:40:13.444684-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/refinery","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:08:37-08:00\",\"rig\":\"gastown\",\"role\":\"refinery\",\"session_id\":\"gt-gastown-refinery\"}"} -{"id":"gt-nf19r","title":"Digest: mol-deacon-patrol","description":"Patrol 11 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:44:59.115094-08:00","updated_at":"2025-12-31T16:44:59.115094-08:00","closed_at":"2025-12-31T16:44:59.115056-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nfdyl","title":"Witness emits activity events","description":"Witness emits events to activity stream for patrol activity:\n\nEvents to emit:\n- patrol_started: When witness begins patrol cycle\n- polecat_checked: When witness checks a polecat\n- polecat_nudged: When witness nudges a stuck polecat\n- escalation_sent: When witness escalates to Mayor/Deacon\n- patrol_complete: When patrol cycle finishes\n\nThis replaces stats tracking in .runtime/witness.json","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-28T21:40:20.972584-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-29T23:47:54.584657-08:00","closed_at":"2025-12-29T23:47:54.584657-08:00","close_reason":"Implemented witness activity events: patrol_started, polecat_checked, polecat_nudged, escalation_sent, patrol_complete. Added gt activity emit command for CLI access. Events write to ~/gt/.events.jsonl.","dependencies":[{"issue_id":"gt-nfdyl","depends_on_id":"gt-y14l7","type":"blocks","created_at":"2025-12-28T21:41:11.528857-08:00","created_by":"daemon"}]} -{"id":"gt-nfhdn","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:44:04.569785-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T00:08:31.583474-08:00","closed_at":"2026-01-05T00:08:31.583474-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:44:04-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-nfqy3","title":"Digest: mol-deacon-patrol","description":"Patrol #4: All systems nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:20:27.895369-08:00","updated_at":"2025-12-31T06:20:27.895369-08:00","closed_at":"2025-12-31T06:20:27.895337-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ng6g","title":"Implement await type handlers (gh:run, gh:pr, timer, human, mail)","description":"Implement condition checking for each await type.\n\n## Handlers Needed\n- gh:run:\u003cid\u003e - Check GitHub Actions run status via gh CLI\n- gh:pr:\u003cid\u003e - Check PR merged/closed status via gh CLI \n- timer:\u003cduration\u003e - Simple elapsed time check\n- human:\u003cprompt\u003e - Check for human approval (via mail?)\n- mail:\u003cpattern\u003e - Check for mail matching pattern\n\n## Interface\n```go\ntype AwaitHandler interface {\n Check(awaitID string) (completed bool, result string, err error)\n}\n```\n\n## Moved from beads\nOriginally bd-2l03. Deacon handlers belong in gastown.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T12:19:12.427881-08:00","updated_at":"2025-12-23T12:19:12.427881-08:00","dependencies":[{"issue_id":"gt-ng6g","depends_on_id":"gt-dh65","type":"blocks","created_at":"2025-12-23T12:19:32.734889-08:00","created_by":"stevey"}]} -{"id":"gt-nget1","title":"Digest: mol-deacon-patrol","description":"Patrol 3: routine, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:42:02.780682-08:00","updated_at":"2025-12-25T13:42:02.780682-08:00","closed_at":"2025-12-25T13:42:02.780653-08:00"} -{"id":"gt-nghlj","title":"Digest: mol-deacon-patrol","description":"Patrol 18 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:47:58.617918-08:00","updated_at":"2025-12-31T16:47:58.617918-08:00","closed_at":"2025-12-31T16:47:58.617884-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ngoe6","title":"MessagingConfig: Fix error message inconsistency in validation","description":"Negative value errors don't wrap ErrMissingField while empty-list errors do. Should be consistent - either all wrap a sentinel or none do.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-28T15:29:08.979969-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-28T15:31:31.432177-08:00","closed_at":"2025-12-28T15:31:31.432177-08:00"} -{"id":"gt-ni07q","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:35:18.289044-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:35:18.338587-08:00","closed_at":"2026-01-05T21:35:18.338587-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:35:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-nigoa","title":"Digest: mol-deacon-patrol","description":"Patrol 74: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:03:15.16921-08:00","updated_at":"2025-12-31T15:03:15.16921-08:00","closed_at":"2025-12-31T15:03:15.169174-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-niv9g","title":"Digest: mol-deacon-patrol","description":"Cycle 186: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:21:23.225866-08:00","updated_at":"2026-01-01T16:21:23.225866-08:00","closed_at":"2026-01-01T16:21:23.225827-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-niv9g","depends_on_id":"gt-eph-zgcl","type":"parent-child","created_at":"2026-01-01T16:21:23.22719-08:00","created_by":"deacon"}]} -{"id":"gt-nj3e5","title":"Digest: mol-deacon-patrol","description":"Patrol 5: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:04:44.720601-08:00","updated_at":"2025-12-27T23:04:44.720601-08:00","closed_at":"2025-12-27T23:04:44.720566-08:00"} -{"id":"gt-nji95","title":"Cross-rig agent identity detection","description":"## Problem\n\nSeveral gt commands fail to correctly detect agent identity when operating\nacross rigs. Running commands from beads/crew/dave shows gastown/crew/joe\nidentity, or fails to resolve paths.\n\n## Root Cause\n\nAgent identity detection in gt commands assumes single-rig context. Cross-rig\ncrew paths like `beads/crew/dave` are not handled correctly.\n\n## Scope\n\n- gt hook - shows wrong identity from other rig crew dir\n- gt peek - fails to resolve cross-rig crew paths \n- gt sling - \".\" target not resolved to current agent\n\n## Fix Strategy\n\nCentralize agent identity detection to handle:\n1. Current rig detection from cwd\n2. Cross-rig path parsing (rig/crew/name vs rig/polecats/name)\n3. \".\" resolution to current agent identity","status":"closed","priority":2,"issue_type":"epic","assignee":"gastown/polecats/slit","created_at":"2025-12-31T12:59:33.509912-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-01T18:40:56.514089-08:00","closed_at":"2026-01-01T18:40:56.514089-08:00","close_reason":"All sub-tasks complete: gt sling dot resolution (gt-hldpv), gt hook cross-rig identity (gt-5d7eh), gt peek cross-rig paths (gt-yud21) - all fixed","dependencies":[{"issue_id":"gt-nji95","depends_on_id":"gt-hldpv","type":"blocks","created_at":"2025-12-31T12:59:44.660866-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-nji95","depends_on_id":"gt-yud21","type":"blocks","created_at":"2025-12-31T12:59:44.690889-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-nji95","depends_on_id":"gt-5d7eh","type":"blocks","created_at":"2025-12-31T12:59:44.72057-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-nlp37","title":"Digest: mol-deacon-patrol","description":"Patrol 9: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:52:22.374939-08:00","updated_at":"2026-01-01T22:52:22.374939-08:00","closed_at":"2026-01-01T22:52:22.374904-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-nm1oi","title":"Deacon Patrol","description":"Mayor's daemon patrol loop for handling callbacks, health checks, and cleanup.","status":"closed","priority":2,"issue_type":"molecule","created_at":"2025-12-26T13:08:21.347354-08:00","updated_at":"2025-12-29T20:57:41.78458-08:00","closed_at":"2025-12-29T20:57:41.78458-08:00","close_reason":"Duplicate patrol molecule beads - keeping gt-t5i07, gt-8ynws, gt-kt9qq"} -{"id":"gt-nm8op","title":"Digest: mol-deacon-patrol","description":"Routine patrol, town stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:23:55.238487-08:00","updated_at":"2025-12-28T19:23:55.238487-08:00","closed_at":"2025-12-28T19:23:55.238453-08:00"} -{"id":"gt-nn6vn","title":"Digest: mol-deacon-patrol","description":"Patrol 157: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:07:31.412151-08:00","updated_at":"2026-01-01T15:07:31.412151-08:00","closed_at":"2026-01-01T15:07:31.412116-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-nn6vn","depends_on_id":"gt-eph-hmvm","type":"parent-child","created_at":"2026-01-01T15:07:31.413458-08:00","created_by":"deacon"}]} -{"id":"gt-nnc8d","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:18:39.777511-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.408118-08:00","closed_at":"2026-01-05T19:44:18.408118-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:18:39-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-nnub1","title":"Phase 4: Migration script for existing installations","description":"## Goal\n\nProvide migration for existing installations with gt-* agent beads in rig beads.\n\n## Approach\n\nCreate gt doctor --fix logic or standalone migration:\n\n1. Detect old agent beads in rig beads (gt-mayor, gt-deacon, gt-*-role)\n2. Create new agent beads in town beads (hq-mayor, hq-deacon, hq-*-role)\n3. Copy relevant state (agent_state, hook_bead, etc.)\n4. Mark old beads as migrated (add migration note)\n5. Update any references\n\n## Commands\n\nOption A: Part of gt doctor --fix\nOption B: Standalone gt migrate-agents command\n\n## Safety\n\n- Dry-run mode by default\n- Preserve old beads (don't delete)\n- Validate new beads created successfully\n- Log all changes\n\n## Testing\n\n- Run on existing ~/gt installation\n- Verify hq-* beads created in town beads\n- Verify agent lookups still work","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/organic","created_at":"2026-01-03T18:43:23.577205-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T21:16:43.980964-08:00","closed_at":"2026-01-03T21:16:43.980964-08:00","close_reason":"Migration command implemented and verified working. Already committed in 0b88dc20.","dependencies":[{"issue_id":"gt-nnub1","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T18:43:38.041282-08:00","created_by":"gastown/crew/gus"},{"issue_id":"gt-nnub1","depends_on_id":"gt-eqptl","type":"blocks","created_at":"2026-01-03T18:43:38.082253-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-nnw48","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:12:38.488751-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.61299-08:00","closed_at":"2026-01-04T16:40:13.61299-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:12:38-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-npx90","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:46:15.02197-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:13.562625-08:00","closed_at":"2026-01-04T16:40:13.562625-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:46:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-nq3pr","title":"Implement gt convoy add command","description":"Add the 'add' subcommand to convoy for adding issues to existing convoys.\n\nSYNTAX:\ngt convoy add \u003cconvoy-id\u003e \u003cissue-id\u003e [issue-id...]\n\nBEHAVIOR:\n1. Validate convoy exists\n2. Add 'tracks' dependency for each issue\n3. If convoy is closed, reopen it automatically\n4. Print confirmation\n\nIMPLEMENTATION:\nFile: internal/cmd/convoy.go\nAdd: convoyAddCmd as subcommand\n\nExample:\ngt convoy add hq-cv-abc gt-new-issue\n# -\u003e Added gt-new-issue to convoy hq-cv-abc\n\ngt convoy add hq-cv-abc gt-followup # convoy was closed\n# -\u003e Reopened convoy hq-cv-abc\n# -\u003e Added gt-followup to convoy hq-cv-abc","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/testcat6","created_at":"2025-12-30T19:37:16.724963-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T21:17:57.899942-08:00","closed_at":"2025-12-30T21:17:57.899942-08:00","close_reason":"Verified implementation: build passes, help works, add/reopen tested"} -{"id":"gt-nq5l9","title":"Merge: nux-1767087680976","description":"branch: polecat/nux-1767087680976\ntarget: main\nsource_issue: nux-1767087680976\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T13:43:41.690209-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T18:23:22.19108-08:00","closed_at":"2025-12-30T18:23:22.19108-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-nqjiz","title":"Digest: mol-deacon-patrol","description":"Patrol 7 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:43:10.726322-08:00","updated_at":"2025-12-31T16:43:10.726322-08:00","closed_at":"2025-12-31T16:43:10.726291-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nqq5k","title":"[Refactor] Extract bd command wrapper package","description":"Multiple exec.Command(\"bd\", ...) calls scattered across rig/manager.go and crew/manager.go:\n\n- rig/manager.go: bd init (x2), bd migrate, bd mol seed, bd list, bd create\n- crew/manager.go: bd sync\n\nShould create internal/bdclient package with typed methods:\n bdclient.Init(dir, prefix string) error\n bdclient.Sync(dir string) error\n bdclient.Create(dir string, opts CreateOpts) error\n\nBenefits: consistent error handling, easier testing/mocking, single place for bd interaction patterns.","status":"open","priority":4,"issue_type":"task","created_at":"2026-01-04T23:47:54.797182-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-04T23:47:54.797182-08:00"} -{"id":"gt-nqtqp","title":"Migrate from .claude/commands/ to .claude/skills/ format","description":"## Summary\n\nClaude Code v2.0+ deprecated `.claude/commands/` in favor of `.claude/skills/`. \nAll gastown workers currently have `.claude/commands/handoff.md` which no longer loads.\n\n## Current State\n\n- Workers have `.claude/commands/handoff.md` (deprecated, not loading)\n- `/handoff` skill is unavailable to agents\n\n## Fix Required\n\n1. Create `.claude/skills/handoff/SKILL.md` with proper frontmatter format\n2. Remove deprecated `.claude/commands/handoff.md` files\n3. Update worker setup process to use skills format\n\n## Skill Format\n\n```yaml\n---\nname: handoff\ndescription: \u003e\n Hand off to a fresh Claude session. Work continues from hook.\nallowed-tools: \"Bash(gt handoff:*),Bash(gt mail send:*)\"\nversion: \"1.0.0\"\n---\n```\n\n## Affected Locations\n\n- ~/gt/gastown/crew/*/claude/commands/handoff.md (all crew workers)\n- ~/gt/gastown/mayor/rig/.claude/commands/handoff.md\n- ~/gt/gastown/refinery/rig/.claude/commands/handoff.md\n\n## Reference\n\n- beads already migrated: `.claude/skills/handoff/SKILL.md`\n- User-wide skill added: `~/.claude/skills/handoff/SKILL.md`","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2026-01-02T16:04:25.76059-08:00","created_by":"beads/crew/grip","updated_at":"2026-01-02T18:24:24.438036-08:00","closed_at":"2026-01-02T18:24:24.438036-08:00","close_reason":"Migrated handoff skill to .claude/skills/ format for 13 gastown locations"} -{"id":"gt-nra8k","title":"Review PR #83: Update dependencies","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/coma","created_at":"2026-01-04T10:54:00.89988-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:56:43.189963-08:00","closed_at":"2026-01-04T10:56:43.189963-08:00","close_reason":"Approved PR #83: Update dependencies. Verified build and tests pass locally. All changes are minor/patch version bumps with no breaking changes."} -{"id":"gt-nrgm5","title":"gt doctor: add bd daemon status check","description":"Add check for daemon running. Add check for database fingerprint. --fix should be able to migrate (bd migrate --update-repo-id) and restart daemon.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-02T11:54:40.820206-08:00","created_by":"mayor","updated_at":"2026-01-02T12:11:04.966686-08:00","closed_at":"2026-01-02T12:11:04.966686-08:00","close_reason":"Implemented repo-fingerprint check in gt doctor","dependencies":[{"issue_id":"gt-nrgm5","depends_on_id":"gt-rapj1","type":"blocks","created_at":"2026-01-02T11:54:58.164419-08:00","created_by":"mayor"}]} -{"id":"gt-nrpfu","title":"Merge: corpus-mk0r5ick","description":"branch: polecat/corpus-mk0r5ick\ntarget: main\nsource_issue: corpus-mk0r5ick\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T22:05:22.293486-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-05T00:11:38.243722-08:00","closed_at":"2026-01-05T00:11:38.243722-08:00","close_reason":"Branch polecat/corpus-mk0r5ick no longer exists - work not on main, unverifiable"} -{"id":"gt-nrpiq","title":"Cost tracking v1: tmux scraping + ledger","description":"## Overview\nImplement basic cost tracking for Gas Town agents using tmux scraping.\n\n## Scope\n\n### 1. Live cost scraping\n- `gt costs` command that:\n - Finds all Claude Code tmux sessions (polecat-*, witness-*, refinery-*, mayor-*)\n - Runs `tmux capture-pane -t \u003csession\u003e -p` \n - Extracts cost with regex: `\\$[0-9]+\\.[0-9]+`\n - Displays table: session | role | cost\n\n### 2. Cost ledger\n- File: `~/.gt/costs.jsonl`\n- Schema: `{session_id, role, rig, cost_usd, started_at, ended_at, work_item}`\n- Written on session end (SessionEnd hook integration)\n\n### 3. Aggregation commands\n- `gt costs` - Live costs from running sessions\n- `gt costs --today` - Today's total from ledger\n- `gt costs --week` - This week's total\n- `gt costs --by-role` - Breakdown by role (polecat, witness, etc.)\n- `gt costs --by-rig` - Breakdown by rig\n\n### 4. Hook integration\n- Add SessionEnd hook handler that:\n - Captures final cost\n - Writes to ledger\n - Includes work_item if attached\n\n## Non-goals (v2)\n- Per-convoy attribution\n- Cost warnings/budgets\n- Historical trends\n- Deacon integration for periodic capture\n\n## Reference\n- GitHub issue #24\n- docs/agent-compatibility.md (future direction)","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/toast","created_at":"2026-01-02T12:11:42.443168-08:00","created_by":"mayor","updated_at":"2026-01-02T12:19:06.8658-08:00","closed_at":"2026-01-02T12:19:06.8658-08:00","close_reason":"Implemented cost tracking v1 with live scraping, ledger, and hook integration"} -{"id":"gt-nrz6g","title":"Digest: mol-deacon-patrol","description":"Patrol 19: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T16:48:55.937269-08:00","updated_at":"2025-12-25T16:48:55.937269-08:00","closed_at":"2025-12-25T16:48:55.937235-08:00"} -{"id":"gt-ntzhc","title":"Wire up gt costs record to Stop hook","description":"## Task\n\nAdd `gt costs record` to the Claude Code Stop hook so session costs are automatically recorded when sessions end.\n\n## Context\n\n`gt costs record` is implemented (gt-f7jxr) but not yet wired up. Currently, session costs are never actually recorded to beads because nothing calls this command.\n\n## Implementation\n\nAdd to `~/.claude/settings.json` (or project settings):\n\n```json\n{\n \"hooks\": {\n \"Stop\": [\n {\n \"matcher\": \"\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"gt costs record --session \\$GT_SESSION\"\n }\n ]\n }\n ]\n }\n}\n```\n\nAlternatively, add to the session-end hook script if we use that pattern.\n\n## Considerations\n\n1. **Session name**: Need to pass the tmux session name. Could use:\n - $GT_SESSION env var (if set by session-start)\n - Parse from hook input JSON (session_id field)\n - Infer from tmux (risky if multiple sessions)\n\n2. **Work item**: Optionally pass `--work-item` if we can determine what was being worked on\n\n3. **Template update**: May need to update Gas Town templates that generate settings.json\n\n## Acceptance Criteria\n\n- [ ] Stop hook calls `gt costs record`\n- [ ] Session name passed correctly\n- [ ] Costs appear in `gt costs --today` after session ends\n- [ ] Templates updated if needed\n\n## References\n\n- gt-f7jxr (cost tracking v2)\n- gt-nrpiq (cost tracking v1)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-02T13:50:56.920061-08:00","created_by":"mayor","updated_at":"2026-01-02T18:27:51.104158-08:00","closed_at":"2026-01-02T18:27:51.104158-08:00","close_reason":"Stop hook wired up - session costs now recorded automatically when sessions end"} -{"id":"gt-nu26g","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:21:13.057624-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-06T13:21:13.113331-08:00","closed_at":"2026-01-06T13:21:13.113331-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:21:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-nu47q","title":"Merge: rictus-1767087768853","description":"branch: polecat/rictus-1767087768853\ntarget: main\nsource_issue: rictus-1767087768853\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:54:12.911687-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T10:06:56.737953-08:00","closed_at":"2025-12-30T10:06:56.737953-08:00","close_reason":"Branch merged to main"} -{"id":"gt-nucdc","title":"Digest: mol-deacon-patrol","description":"Cycle 181: All agents healthy, processed 3 health acks, 7 doctor warnings noted (non-critical), no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:17:39.614005-08:00","updated_at":"2026-01-01T16:17:39.614005-08:00","closed_at":"2026-01-01T16:17:39.613958-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-nucdc","depends_on_id":"gt-eph-tpqg","type":"parent-child","created_at":"2026-01-01T16:17:39.615331-08:00","created_by":"deacon"}]} -{"id":"gt-nv3pm","title":"Digest: mol-deacon-patrol","description":"Cycle 4: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:53:05.166581-08:00","updated_at":"2025-12-31T23:53:05.166581-08:00","closed_at":"2025-12-31T23:53:05.166544-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nv7x0","title":"Digest: mol-refinery-patrol","description":"Patrol: merged 5 branches, closed 1 already-merged (dementus). No issues.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T17:31:19.86356-08:00","updated_at":"2026-01-02T17:31:19.86356-08:00","closed_at":"2026-01-02T17:31:19.863522-08:00","close_reason":"Squashed from 11 wisps"} -{"id":"gt-nvws7","title":"Digest: mol-deacon-patrol","description":"Quick patrol: no messages, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T11:03:52.500691-08:00","updated_at":"2025-12-25T11:03:52.500691-08:00","closed_at":"2025-12-25T11:03:52.500657-08:00"} -{"id":"gt-nvyjm","title":"Digest: mol-deacon-patrol","description":"Patrol 28: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:57:45.867039-08:00","updated_at":"2025-12-31T13:57:45.867039-08:00","closed_at":"2025-12-31T13:57:45.867002-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-nvz8b","title":"gt done: Capture session_id in issue close for CV attribution","description":"## Context\n\nPer decision 009-session-events-architecture.md, work attribution should happen\nby capturing session_id on beads mutations. This enables querying \"what work\ndid this session do?\" for entity CV building.\n\n## Implementation\n\nWhen gt done closes an issue, pass CLAUDE_SESSION_ID to bd close:\n\n```go\n// In done.go\nsessionID := os.Getenv(\"CLAUDE_SESSION_ID\")\nif sessionID != \"\" {\n // Pass to bd close via --session flag or env var\n}\n```\n\n## Acceptance Criteria\n\n- [ ] gt done passes session_id to bd close\n- [ ] Issue close events include session attribution\n- [ ] Works for gt mol complete as well\n\n## Dependencies\n\n- Beads must support session_id on issue close (bd-* issue)\n\n## Related\n\n- docs/hop/decisions/009-session-events-architecture.md","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-31T12:49:43.72435-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-01T18:16:41.235113-08:00","closed_at":"2026-01-01T18:16:41.235113-08:00","close_reason":"Implemented session_id passing to all bd close calls via CLAUDE_SESSION_ID env var"} -{"id":"gt-nw1we","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:03:34.592351-08:00","updated_at":"2026-01-01T20:03:34.592351-08:00","closed_at":"2026-01-01T20:03:34.592315-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-nzogn","title":"Digest: mol-deacon-patrol","description":"Patrol 41 complete: All agents healthy, 2 convoys in progress (Hanoi, Messaging), health pings sent, 1 idle dog","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:50:31.370165-08:00","updated_at":"2025-12-31T14:50:31.370165-08:00","closed_at":"2025-12-31T14:50:31.370133-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o0p4w","title":"Digest: mol-deacon-patrol","description":"Patrol 41: All healthy, 3 rigs, 3W/3R pinged, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:16:30.366291-08:00","updated_at":"2026-01-01T02:16:30.366291-08:00","closed_at":"2026-01-01T02:16:30.366255-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o0xbp","title":"Add gt mail clear command for bulk inbox clearing","description":"Currently `gt mail delete` only accepts a single message-id. Need:\n\n1. `gt mail clear` - Clear all messages from your inbox\n2. `gt mail clear \u003ctarget\u003e` - Clear another agent's inbox (e.g., `gt mail clear gastown/joe`)\n3. Or: `gt mail delete --all` flag\n\nUse case: Town quiescence - need to reset all inboxes across all workers efficiently.\n\nCurrent workaround: Loop through each message ID individually, which is tedious for 50+ messages per inbox.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/capable","created_at":"2026-01-01T10:41:24.46394-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T19:03:05.335204-08:00","closed_at":"2026-01-01T19:03:05.335204-08:00","close_reason":"Added gt mail clear command for bulk inbox clearing"} -{"id":"gt-o11ez","title":"Digest: mol-deacon-patrol","description":"Patrol 150 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:03:58.626966-08:00","updated_at":"2025-12-31T16:03:58.626966-08:00","closed_at":"2025-12-31T16:03:58.626929-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o1y8u","title":"Merge: prime-mk0aw9ai","description":"branch: polecat/prime-mk0aw9ai\ntarget: main\nsource_issue: prime-mk0aw9ai\nrig: gastown\nagent_bead: gt-gastown-polecat-prime\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T14:36:53.29863-08:00","created_by":"gastown/polecats/prime","updated_at":"2026-01-04T14:42:03.94819-08:00","closed_at":"2026-01-04T14:42:03.94819-08:00","close_reason":"Merged to main at af95b7b7"} -{"id":"gt-o2186","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:49:08.309065-08:00","updated_at":"2026-01-01T07:49:08.309065-08:00","closed_at":"2026-01-01T07:49:08.309029-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o2x2f","title":"Session: gt-gastown-test completed gt-f7jxr","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:20:34.147448-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:23:05.8041-08:00","closed_at":"2026-01-02T13:23:05.8041-08:00","close_reason":"Test cleanup","event_kind":"session.ended","actor":"gastown/polecats/test","payload":"{\"cost_usd\":0,\"session_id\":\"gt-gastown-test\",\"role\":\"polecat\",\"ended_at\":\"2026-01-02T00:00:00Z\",\"rig\":\"gastown\",\"worker\":\"test\"}"} -{"id":"gt-o4xp5","title":"Digest: mol-deacon-patrol","description":"Cycle 4: healthy, refinery started","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:58:22.038463-08:00","updated_at":"2026-01-01T09:58:22.038463-08:00","closed_at":"2026-01-01T09:58:22.038427-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o5grr","title":"Digest: mol-deacon-patrol","description":"Cycle 194: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:23:45.211847-08:00","updated_at":"2026-01-01T16:23:45.211847-08:00","closed_at":"2026-01-01T16:23:45.211813-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-o5grr","depends_on_id":"gt-eph-pl14","type":"parent-child","created_at":"2026-01-01T16:23:45.213341-08:00","created_by":"deacon"}]} -{"id":"gt-o5yz2","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T13:59:12.281525-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.227919-08:00","closed_at":"2026-01-04T16:41:26.227919-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T13:59:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-o7bay","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:14:55.623971-08:00","updated_at":"2026-01-01T06:14:55.623971-08:00","closed_at":"2026-01-01T06:14:55.623934-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-o9hwu","title":"Digest: mol-deacon-patrol","description":"Cycle 12: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:20:41.375337-08:00","updated_at":"2025-12-28T13:20:41.375337-08:00","closed_at":"2025-12-28T13:20:41.375302-08:00"} -{"id":"gt-oahqo","title":"Digest: mol-deacon-patrol","description":"Patrol 15: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T11:05:36.911655-08:00","updated_at":"2025-12-25T11:05:36.911655-08:00","closed_at":"2025-12-25T11:05:36.911619-08:00"} -{"id":"gt-oared","title":"Digest: mol-deacon-patrol","description":"Patrol 16: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:48:47.63204-08:00","updated_at":"2025-12-28T19:48:47.63204-08:00","closed_at":"2025-12-28T19:48:47.632007-08:00"} -{"id":"gt-ob0t","title":"Test Patrol Parent","description":"Test parent for Christmas Ornament pattern","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T12:46:15.328647-08:00","updated_at":"2025-12-27T23:44:54.660334-08:00","closed_at":"2025-12-27T23:44:54.660338-08:00"} -{"id":"gt-ob1y9","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:07:39.616581-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.484212-08:00","closed_at":"2026-01-05T19:44:18.484212-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:07:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-obbev","title":"Merge: capable-mjxm03qy","description":"branch: polecat/capable-mjxm03qy\ntarget: main\nsource_issue: capable-mjxm03qy\nrig: gastown\nagent_bead: gt-gastown-polecat-capable","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:23:15.064896-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T17:28:06.869638-08:00","closed_at":"2026-01-02T17:28:06.869638-08:00","close_reason":"Merged to main at a62b35a8"} -{"id":"gt-ocjdi","title":"gt crew add: CLAUDE.md customization leaves git dirty","description":"When gt crew add generates a customized CLAUDE.md for crew workers, it differs from the repo version (Crew Worker Context vs Polecat Context, personalized footer). This leaves the git state 'dirty'.\n\nOptions:\n1. Add CLAUDE.md to .gitignore in crew workspaces\n2. Auto-commit the customized CLAUDE.md locally \n3. Store crew CLAUDE.md content elsewhere (e.g., .claude/CLAUDE.md)\n\nCurrent behavior is functional but 'gt crew list' shows 'Git: dirty' for new crew.\n\nFound during: adding crew workers grip, fang, wolf","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-29T13:03:53.25608-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T13:03:53.25608-08:00"} -{"id":"gt-ocqww","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 21 complete. Detected 2 orphaned polecats (nux, rictus), escalated to Mayor. All 3 rigs healthy (beads, gastown, wyvern). No convoys, gates, or plugins.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:22:51.895517-08:00","updated_at":"2026-01-01T19:22:51.895517-08:00","closed_at":"2026-01-01T19:22:51.895472-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-ocqww","depends_on_id":"gt-eph-0nj2","type":"parent-child","created_at":"2026-01-01T19:22:51.896877-08:00","created_by":"deacon"}]} -{"id":"gt-od1g","title":"Mail inbox from witness/refinery dirs shows Mayor inbox","description":"When running `gt mail inbox` from the witness or refinery directories, it shows the Mayor's inbox instead of the agent's own inbox.\n\nReproduction:\n```\n$ cd ~/gt/beads/witness \u0026\u0026 gt mail inbox\n📬 Inbox: mayor/ (1 messages, 1 unread)\n ● 🤝 HANDOFF: Swarm session complete...\n```\n\nExpected: Should show beads/witness inbox\n\nLikely cause: The cwd-based identity resolution isn't recognizing witness/refinery as valid mail identities, so it falls back to Mayor.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-23T20:29:58.817388-08:00","updated_at":"2025-12-29T23:37:49.772441-08:00","closed_at":"2025-12-29T23:37:49.772441-08:00","close_reason":"Fixed by falling back to cwd-based detection when GT_ROLE is not set"} -{"id":"gt-od9yk","title":"Digest: mol-deacon-patrol","description":"Patrol 157 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:08:51.75877-08:00","updated_at":"2025-12-31T16:08:51.75877-08:00","closed_at":"2025-12-31T16:08:51.758733-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oeori","title":"Day 3.7: Witness pings Deacon for second-order monitoring","description":"Add second-order monitoring: Witnesses monitor the Deacon.\n\nProblem: Who monitors the Deacon? If Deacon dies, the whole town stalls.\n\nSolution:\n1. Each Witness periodically sends a ping to Deacon during patrol:\n ```bash\n gt mail send deacon/ -s \"WITNESS_PING\" -m \"{\\\"rig\\\": \\\"gastown\\\"}\"\n ```\n\n2. Deacon patrol (inbox-check) aggregates witness pings as health signals\n\n3. If Witness doesn't get Deacon response for 2 cycles:\n - Escalate to Mayor: \"Deacon unresponsive\"\n - Mayor can restart Deacon via daemon\n\nThis creates overlapping patrols:\n- Deacon monitors Witnesses/Refineries\n- Witnesses monitor Deacon (collectively)\n- Mayor is escalation target for both\n\nAdd to mol-witness-patrol after survey-workers step.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T22:02:32.179579-08:00","created_by":"mayor","updated_at":"2025-12-27T23:18:47.265651-08:00","closed_at":"2025-12-27T23:18:47.265651-08:00","dependencies":[{"issue_id":"gt-oeori","depends_on_id":"gt-qpoxz","type":"blocks","created_at":"2025-12-27T22:02:45.78993-08:00","created_by":"daemon"}]} -{"id":"gt-oetxz","title":"Session test with rig","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:20:58.305012-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:23:05.797605-08:00","closed_at":"2026-01-02T13:23:05.797605-08:00","close_reason":"Test cleanup"} -{"id":"gt-ofour","title":"Merge: nux-mjtj9d8q","description":"branch: polecat/nux-mjtj9d8q\ntarget: main\nsource_issue: nux-mjtj9d8q\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T20:58:23.224285-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T22:05:57.650004-08:00","closed_at":"2025-12-30T22:05:57.650004-08:00","close_reason":"Commits already in main"} -{"id":"gt-ogemj","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All healthy - 8 polecats running (max, jack, dementus, capable, toast, dag + crew). Handing off after 6 cycles.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:42:21.665647-08:00","updated_at":"2025-12-30T16:42:21.665647-08:00","closed_at":"2025-12-30T16:42:21.665608-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-ogemj","depends_on_id":"gt-eph-70n","type":"parent-child","created_at":"2025-12-30T16:42:21.666649-08:00","created_by":"deacon"}]} -{"id":"gt-ogmac","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:44:36.060214-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:41:00.369759-08:00","closed_at":"2026-01-04T16:41:00.369759-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:44:35-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-ogpk","title":"Add neighbor-check steps to all patrol molecules","description":"Part of the 'Gas Town is a Village' antifragility design.\n\nEvery patrol molecule should include optional neighbor-checking:\n- Deacon checks Witness and Refinery health\n- Witness checks Refinery health \n- Refinery checks Witness health\n- Polecats can peek other polecats\n\nUse gt peek to check health states.\nIf stuck neighbor found, can nudge or escalate.\n\nThis creates distributed monitoring - no single point of failure.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T22:01:16.358314-08:00","updated_at":"2025-12-22T22:01:16.358314-08:00"} -{"id":"gt-ogw2m","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:26:49.204951-08:00","updated_at":"2026-01-01T10:26:49.204951-08:00","closed_at":"2026-01-01T10:26:49.204917-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oh3vb","title":"Merge: angharad-mjwjn205","description":"branch: polecat/angharad-mjwjn205\ntarget: main\nsource_issue: angharad-mjwjn205\nrig: gastown\nagent_bead: gt-gastown-polecat-angharad","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T01:25:43.093933-08:00","created_by":"gastown/polecats/angharad","updated_at":"2026-01-02T01:28:05.824135-08:00","closed_at":"2026-01-02T01:28:05.824135-08:00","close_reason":"Merged to main at 87d79c40"} -{"id":"gt-ohgcs","title":"Session ended: gt-gastown-wretched","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:41:12.611954-08:00","created_by":"gastown/polecats/wretched","updated_at":"2026-01-05T00:08:31.590797-08:00","closed_at":"2026-01-05T00:08:31.590797-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/wretched","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:41:12-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-wretched\",\"worker\":\"wretched\"}"} -{"id":"gt-ohqxq","title":"BUG: Cross-beads slot references silently fail","description":"When slinging work from town beads (hq-*) to a polecat whose agent bead is in rig beads (gt-*), the hook_bead update silently fails.\n\n**Reproduction:**\n```\n# From mayor (town root):\ngt sling hq-oosxt gastown/polecats/nux\n\n# This runs (in updateAgentHookBead):\nbd slot set gt-gastown-polecat-nux hook hq-oosxt\n# FAILS: can't find hq-oosxt (different beads directory)\n# Error is silently ignored!\n```\n\n**Result:**\n- Agent bead keeps stale hook_bead value\n- gt hook shows wrong/old work\n- Agent doesn't know what they're actually assigned\n\n**Root cause:**\nsling.go line 812-814 silently ignores UpdateAgentState errors:\n```go\nif err := bd.UpdateAgentState(agentBeadID, \"running\", \u0026beadID); err != nil {\n // Silently ignore - agent bead might not exist yet\n return\n}\n```\n\n**Fix options:**\n1. Log warnings instead of silent ignore\n2. Support cross-beads slot references (store as 'hq-oosxt@town' or similar)\n3. Use external: prefix for cross-beads hooks\n4. Always store hook in the WORK bead's directory, not agent bead\n\nDiscovered during investigation of stale hook issue.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/crew/jack","created_at":"2025-12-31T11:51:19.607089-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-31T11:58:17.241959-08:00","closed_at":"2025-12-31T11:58:17.241959-08:00","close_reason":"Fixed: Use town root for routing in sling/done, log warnings instead of silent ignore"} -{"id":"gt-oibku","title":"Session ended: gt-gastown-vuvalini","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:49:13.517524-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-04T16:40:13.477607-08:00","closed_at":"2026-01-04T16:40:13.477607-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/vuvalini","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:49:13-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-vuvalini\",\"worker\":\"vuvalini\"}"} -{"id":"gt-oj1eg","title":"Digest: mol-deacon-patrol","description":"Patrol 161: All agents healthy, no incidents, 1 dog idle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:20:55.221539-08:00","updated_at":"2025-12-31T16:20:55.221539-08:00","closed_at":"2025-12-31T16:20:55.221504-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oj4fh","title":"Session ended: gt-gastown-angharad","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:56:00.250553-08:00","created_by":"gastown/polecats/angharad","updated_at":"2026-01-04T16:40:22.843274-08:00","closed_at":"2026-01-04T16:40:22.843274-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/angharad","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:56:00-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-angharad\",\"worker\":\"angharad\"}"} -{"id":"gt-oj9io","title":"Merge: organic-mjwjck2f","description":"branch: polecat/organic-mjwjck2f\ntarget: main\nsource_issue: organic-mjwjck2f\nrig: gastown\nagent_bead: gt-gastown-polecat-organic","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:17:46.090654-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-01T23:38:59.490812-08:00","closed_at":"2026-01-01T23:38:59.490812-08:00","close_reason":"Stale MR - organic resubmitted as gt-a28hb"} -{"id":"gt-ojj7h","title":"Digest: mol-deacon-patrol","description":"P19: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:00:34.976666-08:00","updated_at":"2025-12-25T20:00:34.976666-08:00","closed_at":"2025-12-25T20:00:34.976617-08:00"} -{"id":"gt-oki8p","title":"Liftoff implementation plan in Beads","description":"## Context\n\nSession on 2025-12-27 produced three key docs:\n- `~/gt/docs/agent-as-bead.md` - Agents ARE beads (identity, hook slots, CV chain roots)\n- `~/gt/docs/zfc-violations-audit.md` - Where Go infers instead of trusting agents\n- `~/gt/docs/liftoff-plan.md` - 4.5 day plan to self-sustaining Gas Town\n\n## Work Required\n\n### Phase 1: Audit existing beads\n- Review all open beads in gt- prefix\n- Close obsolete/stale issues\n- Update any that need refinement\n- Note which existing beads align with liftoff plan\n\n### Phase 2: File new beads\nTranslate liftoff-plan.md into beads with proper dependencies.\n\nThree pillars to decompose:\n1. **Agent beads** - schema, slot commands, migration\n2. **Patrol ignition** - witness/refinery formula wiring\n3. **Polecat lifecycle** - recycle/nuke commands, session-per-step\n\nKey dependency trap to avoid:\n- \"Phase 1 blocks Phase 2\" is WRONG (temporal thinking)\n- \"Phase 2 depends on Phase 1\" is RIGHT (requirement thinking)\n- Use `bd dep add \u003cchild\u003e \u003cparent\u003e` where child NEEDS parent\n\n### Phase 3: Review\nHuman reviews the plan in a separate session.\n\n## Deliverable\n\nA complete dependency graph in beads that can be:\n1. Queried with `bd ready` to find available work\n2. Slung to polecats in dependency order\n3. Tracked to completion\n\n## References\n\n- gt-552hb: Swarm orchestration epic (existing, may subsume)\n- gt-t6muy: Polecat lifecycle design (existing, captures session-per-step)","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-27T20:50:46.343298-08:00","created_by":"mayor","updated_at":"2026-01-04T23:40:58.617751-08:00","closed_at":"2026-01-04T23:40:58.617751-08:00","close_reason":"Cleanup: stale molecule","dependencies":[{"issue_id":"gt-oki8p","depends_on_id":"gt-d0jqp","type":"blocks","created_at":"2025-12-27T20:56:21.755649-08:00","created_by":"daemon"},{"issue_id":"gt-oki8p","depends_on_id":"gt-hwka3","type":"blocks","created_at":"2025-12-27T20:56:21.804561-08:00","created_by":"daemon"},{"issue_id":"gt-oki8p","depends_on_id":"gt-4a2qt","type":"blocks","created_at":"2025-12-27T20:56:21.85321-08:00","created_by":"daemon"}],"deleted_at":"2025-12-27T21:43:14.52461-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"epic"} -{"id":"gt-okk2z","title":"gt crew start \u003crig\u003e [name] | --all - start crew workers","description":"Start crew workers in a rig. Can specify a name to start one, or --all to start all crew members in the rig.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-02T11:49:49.275291-08:00","created_by":"mayor","updated_at":"2026-01-02T12:46:01.120316-08:00","closed_at":"2026-01-02T12:46:01.120316-08:00","close_reason":"Implemented gt crew start \u003crig\u003e [name] | --all command","dependencies":[{"issue_id":"gt-okk2z","depends_on_id":"gt-yyht4","type":"blocks","created_at":"2026-01-02T11:50:01.725689-08:00","created_by":"mayor"}]} -{"id":"gt-olvb7","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:01:56.333043-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.643973-08:00","closed_at":"2026-01-04T16:40:22.643973-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:01:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-omzxu","title":"Digest: mol-deacon-patrol","description":"Cycle 300: All healthy, refinery queue 7","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:47:18.950831-08:00","updated_at":"2026-01-01T18:47:18.950831-08:00","closed_at":"2026-01-01T18:47:18.950792-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-omzxu","depends_on_id":"gt-eph-1lvy","type":"parent-child","created_at":"2026-01-01T18:47:18.952082-08:00","created_by":"deacon"}]} -{"id":"gt-onh0a","title":"gt polecat list: deduce rig from cwd","description":"When running `gt polecat list` from within a rig directory, it should deduce the rig name automatically instead of requiring it as an argument.\n\nExample:\n```\ncd ~/gt/beads\ngt polecat list # Should work, deducing rig=beads\n```\n\nCurrently requires explicit rig name or --all flag.","status":"open","priority":3,"issue_type":"feature","created_at":"2026-01-03T18:01:51.124039-08:00","created_by":"mayor","updated_at":"2026-01-03T18:01:51.124039-08:00"} -{"id":"gt-ooczy","title":"Digest: mol-deacon-patrol","description":"Patrol 11: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:07:38.419674-08:00","updated_at":"2025-12-31T18:07:38.419674-08:00","closed_at":"2025-12-31T18:07:38.419633-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-op78","title":"Session cycling: Auto-spawn successor when context full","description":"Enable automatic session succession for crew workers.\n\nWhen a crew worker's context fills up (\u003e80%), they should:\n1. Write handoff mail to themselves\n2. Signal session end\n3. System auto-spawns successor session\n4. Successor reads handoff, finds attached work, auto-continues\n\nThis completes the autonomous overnight work pattern from gt-9g82.\n\nDepends on:\n- Detecting context fullness (Claude Code API?)\n- Session spawning mechanism (tmux/daemon)\n- Handoff protocol already implemented","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-22T16:18:27.570996-08:00","updated_at":"2025-12-22T16:18:27.570996-08:00"} -{"id":"gt-opzm4","title":"ZFC #9: Explicit MR registration instead of branch parsing","description":"**ZFC Violation:** internal/refinery/manager.go:346-370\n\nGo infers work metadata from branch naming conventions:\n```go\npattern := regexp.MustCompile(`^polecat/([^/]+)(?:/(.+))?$`)\nworker := matches[1]\nissueID = matches[2]\n```\n\n**ZFC-compliant solution:**\nPolecats register MRs with explicit structured data:\n- `gt mq submit --worker=nux --issue=gt-xyz --branch=polecat/nux/gt-xyz`\n- Creates MR bead with explicit fields\n- No regex parsing of branch names\n\n**Benefits:**\n- Work metadata is explicit, not inferred\n- Branch naming can evolve without breaking refinery\n- Audit trail in beads\n\nReference: ~/gt/docs/zfc-violations-audit.md #9","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-27T21:32:24.951818-08:00","created_by":"mayor","updated_at":"2025-12-28T16:31:13.189559-08:00","dependencies":[{"issue_id":"gt-opzm4","depends_on_id":"gt-7uhts","type":"blocks","created_at":"2025-12-27T21:32:42.178027-08:00","created_by":"daemon"}]} -{"id":"gt-oq9yf","title":"Digest: mol-deacon-patrol","description":"Patrol 102: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:00:20.601111-08:00","updated_at":"2026-01-01T14:00:20.601111-08:00","closed_at":"2026-01-01T14:00:20.601077-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oqj9x","title":"Digest: mol-deacon-patrol","description":"Patrol 100: All healthy. Handing off after 20 patrols.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:28:56.850635-08:00","updated_at":"2025-12-31T15:28:56.850635-08:00","closed_at":"2025-12-31T15:28:56.850595-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oqt2c","title":"Digest: mol-deacon-patrol","description":"Patrol 3: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:01:21.739366-08:00","updated_at":"2025-12-31T19:01:21.739366-08:00","closed_at":"2025-12-31T19:01:21.739333-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-orh8o","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:27:05.040161-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T21:27:05.094559-08:00","closed_at":"2026-01-05T21:27:05.094559-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:27:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-orird","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:01:31.943734-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.429965-08:00","closed_at":"2026-01-05T00:08:31.429965-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:01:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-orr4e","title":"Digest: mol-deacon-patrol","description":"Patrol 70: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:01:57.338683-08:00","updated_at":"2025-12-31T15:01:57.338683-08:00","closed_at":"2025-12-31T15:01:57.338646-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-orr4q","title":"Merge: dementus-1767074970788","description":"branch: polecat/dementus-1767074970788\ntarget: main\nsource_issue: dementus-1767074970788\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:12:46.233617-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-29T23:32:37.235882-08:00","closed_at":"2025-12-29T23:32:37.235882-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-orujk","title":"Fix gt polecats docs in reference.md","description":"reference.md:211 documents 'gt polecats \u003crig\u003e' but actual command is 'gt polecat list [rig]'. Already fixed in ~/gt/CLAUDE.md.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-01T10:55:11.281071-08:00","created_by":"mayor","updated_at":"2026-01-01T11:02:16.298822-08:00","closed_at":"2026-01-01T11:02:16.298822-08:00","close_reason":"Fixed: updated gt polecats to gt polecat list in Go files and templates"} -{"id":"gt-osdmr","title":"Digest: mol-deacon-patrol","description":"Patrol 20: all healthy, handoff threshold reached","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:13:10.580733-08:00","updated_at":"2025-12-27T23:13:10.580733-08:00","closed_at":"2025-12-27T23:13:10.5807-08:00"} -{"id":"gt-osuuh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 24: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:17:53.526102-08:00","updated_at":"2026-01-01T12:17:53.526102-08:00","closed_at":"2026-01-01T12:17:53.526065-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-otfcf","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:50:12.83361-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:37.84757-08:00","closed_at":"2026-01-04T16:41:37.84757-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:50:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-otgn3","title":"Cache AgentRegistry loading in ResolveAgentConfig","description":"ResolveAgentConfig calls LoadAgentRegistry on every invocation, reloading agents.json from disk each time. Should cache the result after first load.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T13:05:27.452736-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T13:08:51.713613-08:00","closed_at":"2026-01-04T13:08:51.713613-08:00","close_reason":"Added mutex protection, sync-safe initialization, path caching, and ResetRegistryForTesting() helper"} -{"id":"gt-oth8n","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:19:14.612658-08:00","updated_at":"2026-01-01T06:19:14.612658-08:00","closed_at":"2026-01-01T06:19:14.612624-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-otlkc","title":"Digest: mol-deacon-patrol","description":"Patrol 19: splendid spawned","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:17:38.419234-08:00","updated_at":"2026-01-01T23:17:38.419234-08:00","closed_at":"2026-01-01T23:17:38.419192-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-otsa8","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All quiet. Agents healthy. No pending work.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:47:24.729906-08:00","updated_at":"2025-12-30T15:47:24.729906-08:00","closed_at":"2025-12-30T15:47:24.729866-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ou86o","title":"Merge: ace-mjufugk0","description":"branch: polecat/ace-mjufugk0\ntarget: main\nsource_issue: ace-mjufugk0\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T12:07:09.656808-08:00","created_by":"gastown/polecats/ace","updated_at":"2025-12-31T12:09:38.041156-08:00","closed_at":"2025-12-31T12:09:38.041156-08:00","close_reason":"Merged to main at 81d5b8e7"} -{"id":"gt-ov2uv","title":"Create AgentIdentity type for session name parsing","description":"attached_args: Create AgentIdentity type - depends on completed gt-atqr8\n\nCreate AgentIdentity type to parse and construct session names, replacing duplicated logic.\n\n## Files to modify\n- internal/session/identity.go (NEW)\n- internal/cmd/sling.go (update to use new type)\n- internal/cmd/handoff.go (update to use new type)\n\n## Implementation\n```go\ntype AgentIdentity struct {\n Role string // mayor, deacon, witness, refinery, crew, polecat\n Rig string // empty for mayor/deacon\n Name string // crew/polecat name\n}\n\nfunc ParseSessionName(session string) (*AgentIdentity, error)\nfunc (a *AgentIdentity) SessionName() string\nfunc (a *AgentIdentity) Address() string // e.g., \"gastown/crew/max\"\n```\n\n## Acceptance criteria\n- [ ] AgentIdentity type with Role, Rig, Name fields\n- [ ] ParseSessionName handles all agent types (mayor, deacon, witness, refinery, crew, polecat)\n- [ ] SessionName() reconstructs valid session name\n- [ ] Address() returns mail-style address\n- [ ] sling.go:sessionToAgentID replaced with ParseSessionName\n- [ ] handoff.go:sessionToGTRole replaced with ParseSessionName\n- [ ] Unit tests for all parsing cases\n- [ ] go test ./... passes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:10.113644-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:23:27.939492-08:00","closed_at":"2025-12-28T16:23:27.939492-08:00","dependencies":[{"issue_id":"gt-ov2uv","depends_on_id":"gt-atqr8","type":"blocks","created_at":"2025-12-28T15:51:31.393311-08:00","created_by":"daemon"}]} -{"id":"gt-oviri","title":"Digest: mol-deacon-patrol","description":"Patrol 6: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:04:53.8341-08:00","updated_at":"2025-12-31T18:04:53.8341-08:00","closed_at":"2025-12-31T18:04:53.834059-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ow9rj","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:34:37.456958-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T00:08:31.944426-08:00","closed_at":"2026-01-05T00:08:31.944426-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:34:37-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-owgd5","title":"Digest: mol-deacon-patrol","description":"Patrol 14: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T22:35:18.966173-08:00","updated_at":"2025-12-29T22:35:18.966173-08:00","closed_at":"2025-12-29T22:35:18.966138-08:00"} -{"id":"gt-ox67","title":"Maintenance: Regular cleanup of closed MR/gate beads","description":"Closed merge-request and gate beads accumulate over time. Need regular cleanup.\n\n## Cleanup Candidates\n- type=merge-request with status=closed\n- type=gate with status=closed\n- type=molecule with status=closed (completed workflows)\n\n## Options\n1. **Deacon patrol step** - squash closed MRs periodically\n2. **Refinery post-merge** - close and tombstone MR after successful merge\n3. **bd doctor check** - warn when stale MR count exceeds threshold\n\n## Consideration\nKeep some audit trail? Or just tombstone after N days?","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T14:38:31.532094-08:00","updated_at":"2025-12-23T14:38:31.532094-08:00"} -{"id":"gt-oy0lb","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:16:33.902173-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.415721-08:00","closed_at":"2026-01-05T19:44:18.415721-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:16:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-oyu8g","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 81: All healthy. 3 rigs, 6 agents pinged. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:52:14.496916-08:00","updated_at":"2026-01-01T02:52:14.496916-08:00","closed_at":"2026-01-01T02:52:14.496875-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-oz0tz","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:42:14.31653-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.165108-08:00","closed_at":"2026-01-04T16:41:26.165108-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:42:14-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-oz4lv","title":"Merge: nux-1767073376184","description":"attached_args: Code review this merge request\n\nbranch: polecat/nux-1767073376184\ntarget: main\nsource_issue: nux-1767073376184\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/cheedo","created_at":"2025-12-29T21:57:39.239401-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T22:04:06.843228-08:00","closed_at":"2025-12-29T22:04:06.843228-08:00","close_reason":"Code review complete. BLOCKED: needs rebase before merge. Stale branch would revert swarm fixes from 10e79789. See comments for details."} -{"id":"gt-oz7hl","title":"Merge: nux-1767079896198","description":"branch: polecat/nux-1767079896198\ntarget: main\nsource_issue: nux-1767079896198\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:39:54.738732-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T23:55:11.856019-08:00","closed_at":"2025-12-29T23:55:11.856019-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-ozmjo","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:20:31.437432-08:00","updated_at":"2026-01-01T06:20:31.437432-08:00","closed_at":"2026-01-01T06:20:31.43739-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-p196u","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:16:00.18607-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T19:44:18.431102-08:00","closed_at":"2026-01-05T19:44:18.431102-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:16:00-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-p2eg5","title":"Add unit tests for internal/lock package","description":"attached_args: Lock package tests\n\nAdd comprehensive tests for the file locking package.\n\n## Files to create\n- internal/lock/lock_test.go\n\n## Test cases to cover\n1. Lock() acquires lock successfully\n2. Lock() blocks when lock held by another\n3. Unlock() releases lock\n4. TryLock() returns immediately if locked\n5. IsLocked() detects lock state\n6. Lock file contains correct PID\n7. Stale lock detection (if implemented)\n\n## Acceptance criteria\n- [ ] internal/lock/lock_test.go created\n- [ ] At least 5 test functions\n- [ ] Tests pass: go test ./internal/lock/...\n- [ ] Coverage \u003e 70%: go test -cover ./internal/lock/...","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:12.502257-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:57:03.640967-08:00"} -{"id":"gt-p2l2","title":"gt doctor: add Claude settings.json validation","description":"Add a new doctor check to validate Claude Code settings in worker directories:\n\n**Check for:**\n1. .claude/settings.json exists in polecats/*, crew/*, witness/rig, refinery/rig\n2. SessionStart hook has 'gt prime' command\n3. Autonomous roles (polecat, witness, refinery) have 'gt mail check --inject' in SessionStart\n4. Interactive roles (crew, mayor) have mail check in UserPromptSubmit only\n\n**Auto-fix capability:**\nUse internal/claude.EnsureSettingsForRole() to create missing settings files.\n\nContext: The spawn priming race condition fix (gt-6957) added embedded settings templates. Doctor should validate these are in place.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-22T17:59:02.326127-08:00","updated_at":"2025-12-22T17:59:02.326127-08:00"} -{"id":"gt-p2o6s","title":"Extend gt nudge to support channel:name syntax","description":"Add channel support to internal/cmd/nudge.go.\n\nCURRENT BEHAVIOR:\ngt nudge \u003csession\u003e \u003cmessage\u003e - nudges single session\n\nNEW BEHAVIOR:\ngt nudge channel:\u003cname\u003e \u003cmessage\u003e - nudges all members of channel\n\nIMPLEMENTATION:\n1. Detect if target starts with 'channel:'\n2. If so, extract channel name\n3. Load messaging.json via config.LoadMessagingConfig\n4. Look up NudgeChannels[name]\n5. Resolve each member pattern to session names (use existing resolution logic)\n6. Call t.NudgeSession() for each\n\nPATTERN RESOLUTION:\n- Literal: gastown/witness → session name\n- Wildcards: gastown/polecats/* → expand via getAgentSessions()\n- @groups: @town → expand via parseGroupAddress() patterns\n\nFILE: internal/cmd/nudge.go\nTESTS: Add TestNudgeChannel\n\nNOTE: Look at broadcast.go for session enumeration patterns.","status":"closed","priority":2,"issue_type":"task","assignee":"mayor","created_at":"2025-12-30T18:16:50.267476-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T17:32:11.784174-08:00","closed_at":"2026-01-01T17:32:11.784174-08:00","close_reason":"Implemented channel:name syntax with pattern resolution and tests","dependencies":[{"issue_id":"gt-p2o6s","depends_on_id":"gt-3shmx","type":"blocks","created_at":"2025-12-30T18:16:57.047849-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-p2vyo","title":"Day 2.6: Define bd agent state command","description":"Add command for agents to write their own state to agent beads.\n\n```bash\nbd agent state \u003cagent-id\u003e \u003cstate\u003e\n# Example: bd agent state gt-mayor running\n# States: idle | running | stuck | stopped | dead\n```\n\nImplementation:\n1. Lookup agent bead by ID\n2. Update state field\n3. Update last_activity timestamp\n4. Trigger bd sync if configured\n\nAlso add:\n- bd agent heartbeat \u003cagent-id\u003e - just updates last_activity\n- bd agent show \u003cagent-id\u003e - show agent bead details\n\nThis is the ZFC-compliant way for agents to self-report state.","notes":"Delegated to beads repo: bd-uxlb. Assign to beads/crew/dave.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T22:02:10.643874-08:00","created_by":"mayor","updated_at":"2025-12-28T01:59:15.538875-08:00","closed_at":"2025-12-28T01:59:15.538875-08:00","dependencies":[{"issue_id":"gt-p2vyo","depends_on_id":"gt-39ttg","type":"blocks","created_at":"2025-12-27T22:02:45.228946-08:00","created_by":"daemon"},{"issue_id":"gt-p2vyo","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T23:32:42.574839-08:00","created_by":"daemon"}]} -{"id":"gt-p2zta","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 73: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:22:13.481651-08:00","updated_at":"2026-01-01T13:22:13.481651-08:00","closed_at":"2026-01-01T13:22:13.481615-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-p3g6v","title":"Merge: furiosa-mjxc7zq9","description":"branch: polecat/furiosa-mjxc7zq9\ntarget: main\nsource_issue: furiosa-mjxc7zq9\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:44:36.361273-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T13:41:40.414066-08:00","closed_at":"2026-01-02T13:41:40.414066-08:00","close_reason":"Branches merged, cleaning up stale MR beads"} -{"id":"gt-p3kbn","title":"MEOW Stack Evolution: Higher-Order Workflow Abstractions","description":"Molecular Expression of Work (MEOW) - the full taxonomy of workflow abstractions.\n\n## Current Hierarchy\n\n```\nWORK TRACKING WORKFLOW EXECUTION\n───────────── ──────────────────\n\nBead (issue) Step (action)\n │ │\n ▼ ▼\nEpic (bead group) Molecule (runtime)\n │ │\n ▼ │\n └───────► CAMPAIGN ◄───────┘\n │\n ▼\n Schematic (domain template)\n │\n ▼\n Protocol (interface/type)\n │\n ▼\n Catalyst (meta-generator)\n │\n ▼\n Mol Mall (distribution)\n```\n\n## Key Concepts\n\n1. **Campaign** (gt-camx5): Molecule-wrapped Epic graph for orchestrated execution\n2. **Schematic** (gt-8ws7o): Domain-level formula composition\n3. **Protocol** (gt-y3jb9): Type system for formulas\n4. **SDK** (gt-ihzqr): Developer tooling (Forge, Lab, Validator)\n5. **Mol Mall** (gt-vm85o): Package registry for distribution\n\n## Design Principles\n\n- Chemistry metaphor: atoms → molecules → compounds → materials\n- Two orthogonal dimensions: work tracking × workflow execution\n- Campaign is the convergence point\n- Everything compiles down to executable molecules\n\n## Origin\n\nDiscussion: 2024-12-26, Mayor session\nRelated: docs/formula_evolution.md\nFoundation: gt-8tmz (Molecule Algebra)\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:01:40.332231-08:00","updated_at":"2025-12-28T22:33:22.235393-08:00","closed_at":"2025-12-28T22:33:22.235393-08:00"} -{"id":"gt-p4tyv","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:47:13.168003-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.058136-08:00","closed_at":"2026-01-04T16:41:26.058136-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:47:13-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-p619k","title":"Digest: mol-deacon-patrol","description":"Patrol 141: All agents healthy, 4 polecats working, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:49:48.092505-08:00","updated_at":"2026-01-01T14:49:48.092505-08:00","closed_at":"2026-01-01T14:49:48.092473-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-p71rn","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:27:47.477396-08:00","updated_at":"2026-01-01T10:27:47.477396-08:00","closed_at":"2026-01-01T10:27:47.477355-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-p7ehb","title":"Merge: splendid-mjz9oobk","description":"branch: polecat/splendid-mjz9oobk\ntarget: main\nsource_issue: splendid-mjz9oobk\nrig: gastown\nagent_bead: gt-gastown-polecat-splendid\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T21:42:10.758232-08:00","created_by":"gastown/polecats/splendid","updated_at":"2026-01-04T10:48:07.066363-08:00","closed_at":"2026-01-04T10:48:07.066363-08:00","close_reason":"Already merged at acd2565a"} -{"id":"gt-p7f14","title":"Code Smell: Mailbox struct conflates two modes (legacy vs beads)","description":"The Mailbox struct (mailbox.go:30-36) conflates two distinct operating modes:\n\n```go\ntype Mailbox struct {\n identity string // beads identity (e.g., \"gastown/polecats/Toast\")\n workDir string // directory to run bd commands in\n beadsDir string // explicit .beads directory path (set via BEADS_DIR)\n path string // for legacy JSONL mode (crew workers)\n legacy bool // true = use JSONL files, false = use beads\n}\n```\n\nMost methods have `if m.legacy { ... } else { ... }` branches:\n- List(): listLegacy() vs listBeads()\n- Get(): getLegacy() vs getBeads()\n- MarkRead(): markReadLegacy() vs markReadBeads()\n- etc.\n\n**Recommendation**: Extract an interface and have two implementations:\n\n```go\ntype MailStore interface {\n List() ([]*Message, error)\n Get(id string) (*Message, error)\n MarkRead(id string) error\n MarkUnread(id string) error\n Delete(id string) error\n // ...\n}\n\ntype LegacyMailbox struct { ... } // JSONL implementation\ntype BeadsMailbox struct { ... } // beads implementation\n```\n\nThis would make the code cleaner and easier to test.\n\nFiles:\n- internal/mail/mailbox.go:30-36, 89-94, 251-267, 269-275, etc.\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:48:27.576801-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:48:27.576801-08:00"} -{"id":"gt-p80pc","title":"mol-sync-workspace: Add Refinery-specific inline conflict resolution guidance","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-30T19:11:05.678731-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-01T18:13:27.860222-08:00","closed_at":"2026-01-01T18:13:27.860222-08:00","close_reason":"Added detailed Refinery-specific conflict resolution guidance to sync-git step in mol-sync-workspace formula"} -{"id":"gt-p8qvd","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:31:04.178837-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:31:04.227708-08:00","closed_at":"2026-01-05T21:31:04.227708-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:31:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-p8xgb","title":"Digest: mol-deacon-patrol","description":"Cycle 187: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:21:39.850956-08:00","updated_at":"2026-01-01T16:21:39.850956-08:00","closed_at":"2026-01-01T16:21:39.850916-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-p8xgb","depends_on_id":"gt-eph-4k7n","type":"parent-child","created_at":"2026-01-01T16:21:39.852315-08:00","created_by":"deacon"}]} -{"id":"gt-p9uqi","title":"Merge: nux-mjxc8hbs","description":"branch: polecat/nux-mjxc8hbs\ntarget: main\nsource_issue: nux-mjxc8hbs\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:47:02.394326-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T12:57:30.408659-08:00","closed_at":"2026-01-02T12:57:30.408659-08:00","close_reason":"Branch already merged/deleted - orphaned MR"} -{"id":"gt-paup8","title":"Digest: mol-deacon-patrol","description":"Patrol 37: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:01:26.825466-08:00","updated_at":"2025-12-31T14:01:26.825466-08:00","closed_at":"2025-12-31T14:01:26.825435-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pbjim","title":"Digest: mol-deacon-patrol","description":"Patrol 15: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:35:05.785047-08:00","updated_at":"2025-12-25T00:35:05.785047-08:00","closed_at":"2025-12-25T00:35:05.785013-08:00"} -{"id":"gt-pcnmv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: all healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:46:25.659285-08:00","updated_at":"2026-01-01T00:46:25.659285-08:00","closed_at":"2026-01-01T00:46:25.659253-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pcvjx","title":"Digest: mol-deacon-patrol","description":"Patrol 120: All healthy - session complete","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:17:35.80407-08:00","updated_at":"2026-01-01T14:17:35.80407-08:00","closed_at":"2026-01-01T14:17:35.804024-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pdgi9","title":"Digest: mol-deacon-patrol","description":"Patrol 10 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:44:34.61147-08:00","updated_at":"2025-12-31T16:44:34.61147-08:00","closed_at":"2025-12-31T16:44:34.611434-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pdrh0","title":"Add bash/zsh shell completions for gt CLI","description":"Need shell autocompletions for the gt command to improve usability.\n\nShould support:\n- Bash completions\n- Zsh completions \n- Fish completions (nice to have)\n\nCobra has built-in completion generation:\n cmd.GenBashCompletion()\n cmd.GenZshCompletion()\n\nNeed to:\n1. Add 'gt completion bash/zsh/fish' command\n2. Document installation in README\n3. Consider auto-install during 'gt init' or first run","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/crew/max","created_at":"2026-01-02T02:07:05.744964-08:00","created_by":"mayor","updated_at":"2026-01-02T17:14:57.466132-08:00","closed_at":"2026-01-02T17:14:57.466132-08:00","close_reason":"Documented completion install in README (a78fe7e). Cobra provides gt completion bash/zsh/fish."} -{"id":"gt-pfcwp","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:29:36.101956-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.786173-08:00","closed_at":"2026-01-04T16:40:22.786173-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:29:36-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-pfeyk","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 6 agents healthy, no issues, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:12:03.317989-08:00","updated_at":"2026-01-01T11:12:03.317989-08:00","closed_at":"2026-01-01T11:12:03.317946-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pfha2","title":"Digest: mol-deacon-patrol","description":"Patrol 26: furiosa session started, all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:56:50.963687-08:00","updated_at":"2025-12-31T13:56:50.963687-08:00","closed_at":"2025-12-31T13:56:50.963652-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pfy2g","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:31:10.268905-08:00","updated_at":"2025-12-31T23:31:10.268905-08:00","closed_at":"2025-12-31T23:31:10.268874-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ph8bx","title":"Digest: mol-deacon-patrol","description":"Patrol 29: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:58:14.339885-08:00","updated_at":"2025-12-31T13:58:14.339885-08:00","closed_at":"2025-12-31T13:58:14.339854-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-phdci","title":"Digest: mol-deacon-patrol","description":"Patrol 11: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:42:51.250066-08:00","updated_at":"2025-12-26T18:42:51.250066-08:00","closed_at":"2025-12-26T18:42:51.250024-08:00"} -{"id":"gt-phyry","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:47:24.382336-08:00","updated_at":"2026-01-01T07:47:24.382336-08:00","closed_at":"2026-01-01T07:47:24.382304-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pii3f","title":"Digest: mol-deacon-patrol","description":"Patrol 257 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:24:18.840287-08:00","updated_at":"2026-01-01T17:24:18.840287-08:00","closed_at":"2026-01-01T17:24:18.840252-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pinkq","title":"Day 2.7b: gt rig add creates Witness and Refinery agent beads","description":"Update gt rig add to create agent beads:\n\n1. After initializing rig beads, create:\n - gt-witness-\u003crig\u003e agent bead (role_type: witness, rig: \u003crig\u003e, agent_state: idle)\n - gt-refinery-\u003crig\u003e agent bead (role_type: refinery, rig: \u003crig\u003e, agent_state: idle)\n\n2. Use bd create --type=agent or internal beads API\n\nFiles:\n- internal/cmd/rig.go\n- internal/rig/manager.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T02:17:07.516857-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T02:31:10.608724-08:00","closed_at":"2025-12-28T02:31:10.608724-08:00","dependencies":[{"issue_id":"gt-pinkq","depends_on_id":"gt-aer7q","type":"parent-child","created_at":"2025-12-28T02:17:17.553297-08:00","created_by":"daemon"}]} -{"id":"gt-pio","title":"Plugin: merge-oracle (merge queue analysis)","description":"Example plugin that analyzes changesets before Refinery processes them. Builds overlap graph, classifies disjointness (parallel-safe vs needs-sequencing), uses LLM for semantic complexity, identifies high-risk patterns. Based on merge-orchestration proposal. See docs/architecture.md.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-15T22:53:04.027073-08:00","updated_at":"2025-12-15T23:17:06.507108-08:00","dependencies":[{"issue_id":"gt-pio","depends_on_id":"gt-axz","type":"blocks","created_at":"2025-12-15T22:53:17.507459-08:00","created_by":"daemon"}]} -{"id":"gt-pisa8","title":"Add --dry-run flag to polecat cleanup command","description":"The polecat cleanup command should support --dry-run to preview what would be cleaned without actually doing it. Currently trying 'gt polecat cleanup --dry-run' returns 'unknown flag: --dry-run'.","status":"open","priority":3,"issue_type":"feature","created_at":"2026-01-05T00:46:02.044408-08:00","created_by":"mayor","updated_at":"2026-01-05T00:46:09.172495-08:00"} -{"id":"gt-piy9c","title":"Digest: mol-deacon-patrol","description":"Patrol 9","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:51:02.414152-08:00","updated_at":"2025-12-25T20:51:02.414152-08:00","closed_at":"2025-12-25T20:51:02.414093-08:00"} -{"id":"gt-pjzco","title":"Digest: mol-deacon-patrol","description":"Cycle 5: 2 acks","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:59:18.593101-08:00","updated_at":"2026-01-01T09:59:18.593101-08:00","closed_at":"2026-01-01T09:59:18.593065-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pkm69","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:14.872507-08:00","updated_at":"2025-12-28T11:22:14.872507-08:00","closed_at":"2025-12-28T11:22:14.872464-08:00"} -{"id":"gt-pl3t3","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:26:47.581977-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:26:47.635122-08:00","closed_at":"2026-01-06T13:26:47.635122-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:26:47-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-pmef","title":"Test Patrol Parent","description":"[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.\n\nOriginal description:\nTest parent for Christmas Ornament pattern","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T22:04:44.376339-08:00","updated_at":"2025-12-27T23:55:34.492482-08:00","closed_at":"2025-12-27T23:55:34.492486-08:00"} -{"id":"gt-pmhcb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:51:35.807594-08:00","updated_at":"2026-01-01T07:51:35.807594-08:00","closed_at":"2026-01-01T07:51:35.807561-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pn2fq","title":"Add isAnnounceAddress() and parseAnnounceName() helpers to router.go","description":"Add announce address detection to internal/mail/router.go.\n\nPATTERN TO FOLLOW:\nLook at isListAddress() and parseListName() at lines 53-60 as the template.\n\nIMPLEMENTATION:\n1. Add isAnnounceAddress(address string) bool - returns true if address starts with 'announce:'\n2. Add parseAnnounceName(address string) string - extracts announce name after 'announce:'\n3. Add var ErrUnknownAnnounce = errors.New(\"unknown announce channel\")\n\nFILE: internal/mail/router.go\nTESTS: Add tests in internal/mail/router_test.go\n\nSmall, focused task - just address detection, not delivery.","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/immortan","created_at":"2025-12-30T18:17:18.21529-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-02T00:16:06.62125-08:00","closed_at":"2026-01-02T00:16:06.62125-08:00","close_reason":"Implemented announce address helpers as part of gt-q73h3"} -{"id":"gt-pnch9","title":"Digest: mol-deacon-patrol","description":"Patrol 19: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:29:48.868198-08:00","updated_at":"2025-12-25T07:29:48.868198-08:00","closed_at":"2025-12-25T07:29:48.868161-08:00"} -{"id":"gt-pnmrz","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:07:36.773312-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.457902-08:00","closed_at":"2026-01-04T16:40:13.457902-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:07:36-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-pnv61","title":"Implement git merge logic in Engineer.ProcessMR","description":"The Engineer module in internal/refinery/engineer.go has stub implementations for ProcessMR() and ProcessMRFromQueue() that need actual git merge logic.\n\n## Current State\n- ProcessMR() logs intent but returns failure\n- ProcessMRFromQueue() same - logs and returns failure\n- handleSuccess() and handleFailure() are implemented\n\n## Required Implementation\n1. **Fetch source branch**: git fetch origin \u003cbranch\u003e\n2. **Conflict check**: git merge --no-commit --no-ff to test\n3. **Run tests** if configured (config.RunTests, config.TestCommand)\n4. **Perform merge**: git merge with appropriate commit message\n5. **Push to origin**: git push origin \u003ctarget\u003e\n6. **Handle failures**: conflicts, test failures, push failures\n\n## Context\n- There are 28+ pending merge-request issues waiting for this\n- Infrastructure (config, result types, success/failure handlers) is ready\n- Just needs the core git operations\n\n## Files\n- internal/refinery/engineer.go - ProcessMR(), ProcessMRFromQueue()\n- internal/git/git.go - may need Merge(), Fetch() methods","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-30T22:28:25.736833-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:40:17.082988-08:00","closed_at":"2025-12-30T22:40:17.082988-08:00","close_reason":"Implemented ProcessMR and ProcessMRFromQueue with full git merge logic: fetch, conflict check, test run, merge, push"} -{"id":"gt-po5an","title":"Digest: mol-deacon-patrol","description":"Patrol 2: Routine cycle. All rigs healthy. 12 polecats. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:30:29.30083-08:00","updated_at":"2026-01-01T22:30:29.30083-08:00","closed_at":"2026-01-01T22:30:29.300802-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-polecat-gastown-ace","title":"gt-polecat-gastown-ace","description":"gt-polecat-gastown-ace\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-795e8\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T15:56:20.334372-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:12.702542-08:00","closed_at":"2025-12-28T18:47:12.702542-08:00"} -{"id":"gt-polecat-gastown-capable","title":"gt-polecat-gastown-capable","description":"gt-polecat-gastown-capable\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-tkbd5\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T15:56:20.175066-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:12.849855-08:00","closed_at":"2025-12-28T18:47:12.849855-08:00"} -{"id":"gt-polecat-gastown-furiosa","title":"gt-polecat-gastown-furiosa","description":"gt-polecat-gastown-furiosa\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: null\ncleanup_status: clean","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T13:06:09.472425-08:00","created_by":"mayor","updated_at":"2025-12-28T22:06:14.222191-08:00","closed_at":"2025-12-28T18:47:12.996706-08:00"} -{"id":"gt-polecat-gastown-morsov","title":"gt-polecat-gastown-morsov","description":"gt-polecat-gastown-morsov\n\nrole_type: polecat\nrig: gastown\nagent_state: done\nhook_bead: null\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T15:56:20.255118-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:13.134492-08:00","closed_at":"2025-12-28T18:47:13.134492-08:00"} -{"id":"gt-polecat-gastown-nux","title":"gt-polecat-gastown-nux","description":"gt-polecat-gastown-nux\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-2g130\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T14:09:19.415619-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:16.519005-08:00","closed_at":"2025-12-28T18:47:16.519005-08:00"} -{"id":"gt-polecat-gastown-rictus","title":"gt-polecat-gastown-rictus","description":"gt-polecat-gastown-rictus\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-dsqxw\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T14:09:49.112812-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:16.663913-08:00","closed_at":"2025-12-28T18:47:16.663913-08:00"} -{"id":"gt-polecat-gastown-slit","title":"gt-polecat-gastown-slit","description":"gt-polecat-gastown-slit\n\nrole_type: polecat\nrig: gastown\nagent_state: running\nhook_bead: gt-gcnnr\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T14:09:42.286637-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:16.805677-08:00","closed_at":"2025-12-28T18:47:16.805677-08:00"} -{"id":"gt-polecat-gastown-warboy","title":"gt-polecat-gastown-warboy","description":"gt-polecat-gastown-warboy\n\nrole_type: polecat\nrig: gastown\nagent_state: spawning\nhook_bead: null\nrole_bead: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T15:56:20.415565-08:00","created_by":"mayor","updated_at":"2025-12-28T18:47:16.95025-08:00","closed_at":"2025-12-28T18:47:16.95025-08:00"} -{"id":"gt-polecat-role","title":"Polecat Role Definition","description":"You are a Polecat - an autonomous worker assigned to a specific issue.\n\nYou work independently, following the mol-polecat-work formula, and signal\ncompletion to your Witness. You are transient - spawned for work, cleaned up\nafter completion.\n\nsession_pattern: gt-{rig}-{name}\nwork_dir_pattern: {town}/{rig}/polecats/{name}\nneeds_pre_sync: true\nstart_command: export GT_ROLE=polecat GT_RIG={rig} GT_POLECAT={name} BD_ACTOR={rig}/polecats/{name} \u0026\u0026 claude --dangerously-skip-permissions\n\ndefault_molecule: mol-polecat-work\ncapabilities:\n - execute_assigned_work\n - git_operations\n - branch_management\n - completion_signaling\n\n## Core Responsibilities\n\n1. Execute your pinned molecule's steps\n2. Maintain clean git state\n3. Signal completion via gt done\n4. Wait for Witness to handle lifecycle\n\n## You Do NOT\n\n- Push directly to main (Refinery merges)\n- Kill your own session (Witness does cleanup)\n- Skip verification steps\n- Work on anything other than your assigned issue\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nYour work is defined by your pinned molecule. Execute steps:\n- bd ready (find next step)\n- bd show \u003cstep-id\u003e (see what to do)\n- bd close \u003cstep-id\u003e (mark complete)\n\n## Completion Protocol\n\nWhen done:\n1. Tests pass: go test ./...\n2. COMMIT changes: git add and git commit\n3. Push branch: git push -u origin HEAD\n4. Close issue: bd close \u003cissue\u003e\n5. Sync beads: bd sync\n6. Run gt done\n7. WAIT: Witness will kill your session\n\n## Communication\n\nMail your Witness when stuck:\ngt mail send \u003crig\u003e/witness -s \"HELP: \u003cproblem\u003e\" -m \"...\"","status":"hooked","priority":2,"issue_type":"role","assignee":"gastown/polecats/dementus","created_at":"2025-12-29T13:24:16.758613-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T02:03:42.9242-08:00","labels":["migrated-to:hq-polecat-role"]} -{"id":"gt-powfg","title":"Merge: morsov-1767074381346","description":"attached_args: Code review this merge request\n\nbranch: polecat/morsov-1767074381346\ntarget: main\nsource_issue: morsov-1767074381346\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/dementus","created_at":"2025-12-29T22:08:38.495538-08:00","created_by":"gastown/polecats/morsov","updated_at":"2025-12-29T22:11:49.038089-08:00","closed_at":"2025-12-29T22:11:49.038089-08:00","close_reason":"Already merged: morsov's work (commit 10e79789: Fix swarm not tracking dynamically added workers) is present in main. Branch is ancestor of main - no merge needed."} -{"id":"gt-pqkdb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 39: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:40:04.894271-08:00","updated_at":"2026-01-01T12:40:04.894271-08:00","closed_at":"2026-01-01T12:40:04.894224-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pre9o","title":"Add GitHub CI workflow for PRs","description":"Gas Town has no CI. Add .github/workflows/ci.yml that runs tests and linter on PRs. Reference beads repo for example.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-01T11:09:47.277419-08:00","created_by":"mayor","updated_at":"2026-01-01T11:13:49.246024-08:00","closed_at":"2026-01-01T11:13:49.246024-08:00","close_reason":"Added .github/workflows/ci.yml with test, lint, and beads protection jobs"} -{"id":"gt-pryvd","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:23:52.604269-08:00","updated_at":"2026-01-01T10:23:52.604269-08:00","closed_at":"2026-01-01T10:23:52.604236-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-psuw7","title":"Day 2.2: Remove PID/tmux state inference","description":"Remove ZFC violations where Go infers state from signals:\n- No more PID file checks\n- No more tmux session parsing\n- No more branch pattern analysis\n\nDaemon becomes pure transport layer.\n\nReference: ~/gt/docs/zfc-violations-audit.md\n\nParent: gt-d0jqp","notes":"Removed PID/tmux state inference from refinery Status(), witness Status(), daemon ensureDeaconRunning(), and daemon pokeDeacon(). Daemon now trusts agent bead state per ZFC. Removed 78 lines of inference code.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:00.780322-08:00","created_by":"mayor","updated_at":"2025-12-28T01:56:50.21619-08:00","closed_at":"2025-12-28T01:56:50.216193-08:00","dependencies":[{"issue_id":"gt-psuw7","depends_on_id":"gt-39ttg","type":"blocks","created_at":"2025-12-27T20:58:38.848679-08:00","created_by":"daemon"}]} -{"id":"gt-pt7mw","title":"Digest: mol-deacon-patrol","description":"Cycle 7: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:15:06.558474-08:00","updated_at":"2025-12-28T13:15:06.558474-08:00","closed_at":"2025-12-28T13:15:06.558434-08:00"} -{"id":"gt-ptnwl","title":"gt sling: Support batch slinging multiple beads","description":"Currently `gt sling` only accepts one bead at a time:\n\n```\ngt sling gt-abc gastown # works\ngt sling gt-abc gt-def gastown # fails: accepts between 1 and 2 arg(s)\n```\n\n## Proposed\n\nAllow multiple beads in a single command:\n```\ngt sling gt-abc gt-def gt-ghi gastown\n```\n\nThis would spawn a polecat for each bead (or reuse existing ones).\n\n## Use case\n\nSlinging related work from a convoy - want to parallelize without running gt sling N times manually.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/rictus","created_at":"2026-01-02T00:05:18.110506-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-02T17:17:13.362175-08:00","closed_at":"2026-01-02T17:17:13.362175-08:00","close_reason":"Implemented batch slinging: gt sling now accepts multiple beads with a rig target. Each bead gets its own polecat."} -{"id":"gt-ptwe1","title":"Remove StateIdle and idle polecat concept","description":"## Problem\n\nStateIdle is marked deprecated in types.go:24 but still actively used throughout the codebase. \nThis violates the transient polecat model from PRIMING.md: \"Polecats exist only while working.\"\n\n## Evidence of Heresy\n\n1. StateIdle marked deprecated but not removed\n2. manager.go:748 - Get() returns StateIdle when no issue assigned\n3. deacon.go:191 - \"Scan for idle polecats that should have been nuked\"\n4. Multiple commands accept/produce idle state\n\n## Correct Model\n\nFrom PRIMING.md:278: \"The sandbox persists; sessions are fresh.\"\n\nSandbox exists IFF work exists. There is no idle state:\n- Spawn: sandbox created, work assigned\n- Work: sessions cycle, sandbox persists \n- Done: Witness nukes sandbox\n\n## Changes Required\n\n1. Remove StateIdle from types.go\n2. Update Get() to never return idle (if no work, polecat should not exist)\n3. Remove zombie scan logic (becomes unnecessary)\n4. Update tests that reference StateIdle","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/prime","created_at":"2026-01-04T14:09:54.870662-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T14:36:30.222328-08:00","closed_at":"2026-01-04T14:36:30.222328-08:00","close_reason":"Removed StateIdle from polecat/types.go, updated manager.go to use StateDone/StateWorking, removed zombie scan logic from deacon.go, updated tests.","dependencies":[{"issue_id":"gt-ptwe1","depends_on_id":"gt-32d4a","type":"blocks","created_at":"2026-01-04T14:10:43.334968-08:00","created_by":"gastown/crew/george"},{"issue_id":"gt-ptwe1","depends_on_id":"gt-bc6gm","type":"blocks","created_at":"2026-01-04T14:10:43.389504-08:00","created_by":"gastown/crew/george"}]} -{"id":"gt-pujw7","title":"Digest: mol-deacon-patrol","description":"Patrol 75: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:03:33.155302-08:00","updated_at":"2025-12-31T15:03:33.155302-08:00","closed_at":"2025-12-31T15:03:33.155273-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pulkh","title":"Merge: ace-dogs","description":"branch: polecat/ace-dogs\ntarget: main\nsource_issue: ace-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:36:01.968469-08:00","created_by":"gastown/polecats/ace","updated_at":"2025-12-30T18:23:22.242649-08:00","closed_at":"2025-12-30T18:23:22.242649-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-pv93","title":"Post-work discovery: AI analysis finds follow-on issues","description":"AI analyzes completed work to discover: bugs, punted work, follow-on tasks.\n\n**From VC**: Supervisor.AnalyzeResult() with iterative refinement. ~300 lines.\n\n**Gas Town implementation**: Post-work hook in molecule:\n```yaml\npost_work:\n discover:\n - bugs\n - punted_items\n - follow_on_work\n file_as: beads\n```\n\nPolecat output gets analyzed by AI, discovered work becomes beads issues.\n\n**Value**: Nothing gets forgotten. VC found ~25% more issues with refinement.\n\n**Key**: Use semantic deduplication (gt-xxx) to avoid pollution.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:14.723338-08:00","updated_at":"2025-12-20T20:30:14.723338-08:00","dependencies":[{"issue_id":"gt-pv93","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.534886-08:00","created_by":"daemon"},{"issue_id":"gt-pv93","depends_on_id":"gt-6m3e","type":"related","created_at":"2025-12-20T20:30:35.115095-08:00","created_by":"daemon"}]} -{"id":"gt-pvhsv","title":"bd list: Add type aliases (mr→merge-request)","description":"The --type flag requires exact matches. Add aliases for convenience:\n\n- mr → merge-request\n- feat → feature \n- mol → molecule\n\n**Context**: Refinery cleanup missed 6 open MRs because `--type=mr` returned nothing while `--type=merge-request` found them.\n\n**Implementation**: In the type filter parsing, normalize aliases before matching.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/dag","created_at":"2025-12-31T01:13:57.090261-08:00","created_by":"gastown/refinery","updated_at":"2026-01-01T18:17:38.093414-08:00","closed_at":"2026-01-01T18:17:38.093414-08:00","close_reason":"Implemented type aliases (mr→merge-request, feat→feature, mol→molecule) in bd list/ready/export. PR: https://github.com/steveyegge/beads/pull/846"} -{"id":"gt-pw87v","title":"Digest: mol-deacon-patrol","description":"Patrol 123: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T21:54:03.067766-08:00","updated_at":"2025-12-30T21:54:03.067766-08:00","closed_at":"2025-12-30T21:54:03.067734-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pxksp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All 6 agents healthy, 2 polecats (furiosa, nux), refinery queues active (gastown:2, beads:1)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:16:27.83625-08:00","updated_at":"2026-01-01T11:16:27.83625-08:00","closed_at":"2026-01-01T11:16:27.836209-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-pxsna","title":"gt session start --issue doesn't pin work to hook","description":"When starting a polecat with --issue, the work isn't pinned to the hook:\n gt session start beads/Toast --issue bd-oxgi\n \nAfter session starts, 'gt mol status' shows empty hook.\n\nThe polecat had to manually discover the work via bd ready. The --issue flag should call 'gt hook attach' or equivalent to pin the work.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2025-12-28T19:30:49.536513-08:00","created_by":"mayor","updated_at":"2025-12-29T21:56:27.885229-08:00","closed_at":"2025-12-29T21:56:27.885229-08:00","close_reason":"Fixed: --issue flag now hooks work to polecat via bd update --status=hooked"} -{"id":"gt-pyqv","title":"Work on ga-ct2: Add MR workflow to polecat completion. Wh...","description":"Work on ga-ct2: Add MR workflow to polecat completion. When polecat completes work, auto-create MR to integration branch. When done, submit MR (not PR) to integration branch for Refinery.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T22:58:35.473928-08:00","updated_at":"2025-12-21T17:20:42.831549-08:00"} -{"id":"gt-q2am4","title":"gt crew stop \u003crig\u003e [name] | --all - stop crew workers","description":"Stop crew workers in a rig. Can specify a name to stop one, or --all to stop all crew members. Should use same semantics as gt shutdown.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2026-01-02T11:49:52.078748-08:00","created_by":"mayor","updated_at":"2026-01-02T13:04:43.884625-08:00","closed_at":"2026-01-02T13:04:43.884625-08:00","close_reason":"Implemented gt crew stop command with --all, --rig, --dry-run, and --force flags","dependencies":[{"issue_id":"gt-q2am4","depends_on_id":"gt-yyht4","type":"blocks","created_at":"2026-01-02T11:50:01.765411-08:00","created_by":"mayor"}]} -{"id":"gt-q3mil","title":"Digest: mol-deacon-patrol","description":"P9: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:12:02.16159-08:00","updated_at":"2025-12-25T20:12:02.16159-08:00","closed_at":"2025-12-25T20:12:02.16154-08:00"} -{"id":"gt-q4qxg","title":"Merge: toecutter-mk02qgir","description":"branch: polecat/toecutter-mk02qgir\ntarget: main\nsource_issue: toecutter-mk02qgir\nrig: gastown\nagent_bead: gt-gastown-polecat-toecutter\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:41:01.420604-08:00","created_by":"gastown/polecats/toecutter","updated_at":"2026-01-04T10:46:08.667049-08:00","closed_at":"2026-01-04T10:46:08.667049-08:00","close_reason":"Merged to main at 8dea4acf"} -{"id":"gt-q6f03","title":"Digest: mol-deacon-patrol","description":"Cycle 6: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:14:01.140945-08:00","updated_at":"2025-12-28T13:14:01.140945-08:00","closed_at":"2025-12-28T13:14:01.140918-08:00"} -{"id":"gt-q6lg","title":"mol-crew-session: Startup/shutdown protocols for crew workers","description":"Crew workers (like joe, max) don't have patrol molecules keeping them fresh. When gt gets rebuilt, they have stale binaries that cause hangs and bugs.\n\n## Problem\n\n- Crew binaries get stale when gt is rebuilt elsewhere\n- No automatic pull/rebase/rebuild on session start\n- No standardized shutdown protocol (sync, push, handoff)\n\n## Solution: mol-crew-session\n\nA molecule template for crew sessions:\n\n### Startup Phase\n1. `git pull --rebase` - get latest code\n2. `bd sync` - sync beads\n3. `go build -o gt ./cmd/gt` - rebuild gt (if in gastown)\n4. `gt prime` - load context\n\n### Work Phase \n- Open-ended human interaction\n- No molecule steps - just work until done\n\n### Shutdown Phase\n1. `git status` - check for uncommitted changes\n2. `bd sync` - sync beads\n3. `git push` - push code\n4. Handoff if incomplete work\n\n## Implementation\n\n1. Define mol-crew-session in builtin_molecules.go\n2. Update crew CLAUDE.md to reference the protocol\n3. Optionally: gt prime auto-runs startup steps\n\n## Dependencies\n\n- Should implement after deacon/witness/polecat patrols are stable\n- Consider: gt-3x0z.10 (Witness patrol molecules)\n\n## Related\n\n- gt-3x0z.9: Deacon wisp patrol (done)\n- fix-gt script: Current workaround for binary freshness","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T02:48:25.658692-08:00","updated_at":"2025-12-22T02:48:25.658692-08:00"} -{"id":"gt-q73h3","title":"Implement sendToAnnounce() for bulletin board delivery","description":"Add announce message delivery to internal/mail/router.go.\n\nSEMANTICS:\n- ONE copy in shared location (not fan-out)\n- Messages persist until retention limit reached\n- No claiming, no removal on read\n\nSTORAGE:\n- Location: {townRoot}/.beads/ \n- Metadata: announce_channel field to identify which channel\n\nRETENTION:\n- On send, count existing messages in channel\n- If count \u003e= retain_count, delete oldest\n- retain_count=0 means unlimited\n\nIMPLEMENTATION:\n1. Add sendToAnnounce(msg *Message) error\n2. Load AnnounceConfig from messaging.json\n3. Validate sender is eligible (readers list) - optional\n4. Create message bead with announce_channel metadata\n5. Apply retention pruning\n\nFILE: internal/mail/router.go\nPATTERN: Similar to sendToQueue but no claiming","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/bullet","created_at":"2025-12-30T18:17:19.192914-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-02T00:16:05.339617-08:00","closed_at":"2026-01-02T00:16:05.339617-08:00","close_reason":"Implemented sendToAnnounce() with retention pruning","dependencies":[{"issue_id":"gt-q73h3","depends_on_id":"gt-pn2fq","type":"blocks","created_at":"2025-12-30T18:17:27.388523-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-q8deh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:16:07.757561-08:00","updated_at":"2026-01-01T07:16:07.757561-08:00","closed_at":"2026-01-01T07:16:07.757524-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-q8e6o","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: inbox 0, all 6 rig monitors healthy, 1 dog idle, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:45:46.990387-08:00","updated_at":"2025-12-31T22:45:46.990387-08:00","closed_at":"2025-12-31T22:45:46.990353-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-q8jpq","title":"Digest: mol-deacon-patrol","description":"Patrol 83: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:01:29.424791-08:00","updated_at":"2026-01-01T03:01:29.424791-08:00","closed_at":"2026-01-01T03:01:29.424755-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-q9c7q","title":"Polecat template not found for non-gastown rigs","description":"When adding a polecat to beads rig, warning shows:\n Warning: polecat template not found at /Users/stevey/gt/beads/mayor/rig/templates/polecat-CLAUDE.md\n\nThe template lookup should check the rig's template location, or fall back to a town-level default.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-28T19:29:38.929946-08:00","created_by":"mayor","updated_at":"2025-12-28T19:36:33.11656-08:00","closed_at":"2025-12-28T19:36:33.11656-08:00"} -{"id":"gt-qaca","title":"Merge: gt-5af.2","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-5af.2\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:29:36.838038-08:00","updated_at":"2025-12-20T23:17:25.79048-08:00","closed_at":"2025-12-20T23:17:25.79048-08:00"} -{"id":"gt-qao","title":"CLI: mayor commands (start, attach, stop, status)","description":"Mayor management CLI commands.\n\n## Commands\n\n### gt mayor start\n```\ngt mayor start [--continue] [--agent AGENT]\n```\n- --continue: Resume from previous session (check for handoff mail)\n- --agent: claude (default) or other agent type\n\n### gt mayor attach\n```\ngt mayor attach\n```\nAttach to running Mayor session.\n\n### gt mayor stop\n```\ngt mayor stop [--grace-period N]\n```\nStop Mayor session with optional grace period.\n\n### gt mayor status\n```\ngt mayor status [--json]\n```\nShow Mayor running status.\n\n## Session Management\nSession name: `gt-mayor`\nWorking directory: `\u003ctown\u003e/mayor/rig/` or `\u003ctown\u003e/mayor/`\n\n## Implementation\nSimilar to session commands but for special Mayor context.\n\n```go\nfunc getMayorPath(townRoot string) string {\n return filepath.Join(townRoot, \"mayor\")\n}\n\nfunc getMayorSessionName() string {\n return \"gt-mayor\"\n}\n```\n\n## New File\ninternal/cmd/mayor.go\n\n## PGT Reference\ngastown-py/src/gastown/cli/mayor_cmd.py\n\n## Acceptance Criteria\n- [ ] gt mayor start launches Mayor session\n- [ ] gt mayor attach works\n- [ ] gt mayor stop with grace period\n- [ ] gt mayor status shows running state","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:54.721035-08:00","updated_at":"2025-12-16T16:05:45.226324-08:00"} -{"id":"gt-qaqhy","title":"Digest: mol-deacon-patrol","description":"Patrol 13: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:31:01.896274-08:00","updated_at":"2026-01-01T04:31:01.896274-08:00","closed_at":"2026-01-01T04:31:01.896233-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qb76r","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy, quiet cycle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:00:39.551352-08:00","updated_at":"2025-12-31T19:00:39.551352-08:00","closed_at":"2025-12-31T19:00:39.551316-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qbafo","title":"Digest: mol-deacon-patrol","description":"Patrol #12","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:23:00.308441-08:00","updated_at":"2025-12-31T06:23:00.308441-08:00","closed_at":"2025-12-31T06:23:00.308408-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qbo7k","title":"Session ended: gt-gastown/crew/joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:43:21.213948-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.159582-08:00","closed_at":"2026-01-04T16:41:26.159582-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:43:21-08:00\",\"role\":\"unknown\",\"session_id\":\"gt-gastown/crew/joe\",\"worker\":\"gastown/crew/joe\"}"} -{"id":"gt-qd7ri","title":"E2E Phase 2 observability test","description":"End-to-end test of Phase 2 observability:\n\nTest scenario:\n1. Sling work to polecat\n2. Watch gt feed for polecat activity\n3. Polecat completes, signals done\n4. Watch gt feed for MQ events (merge_started, merged)\n5. gt status shows queue depth changes\n6. Swarm status visible in gt swarm status\n\nAll observable without checking .runtime/*.json files.\n\nSuccess = glass cockpit is lit.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-28T21:40:54.57062-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T02:00:11.163715-08:00","closed_at":"2025-12-30T02:00:11.163715-08:00","close_reason":"E2E test passed: gt feed shows polecat/bead/MQ events, gt status shows agents/hooks/mail, gt swarm list shows swarms, gt polecat list shows workers. Glass cockpit is lit.","dependencies":[{"issue_id":"gt-qd7ri","depends_on_id":"gt-lak31","type":"blocks","created_at":"2025-12-28T21:41:11.735996-08:00","created_by":"daemon"},{"issue_id":"gt-qd7ri","depends_on_id":"gt-rbncw","type":"blocks","created_at":"2025-12-28T21:41:11.76734-08:00","created_by":"daemon"},{"issue_id":"gt-qd7ri","depends_on_id":"gt-tvwnz","type":"blocks","created_at":"2025-12-28T21:41:11.797211-08:00","created_by":"daemon"}]} -{"id":"gt-qd9p0","title":"Swarm doesn't track dynamically added workers","description":"When creating a swarm with --worker flags and then adding more polecats later, the swarm status only shows the original workers.\n\nSteps to reproduce:\n1. gt swarm create gastown --epic gt-i26df --worker slit --worker rictus --start\n2. Add more polecats: gt polecat add gastown capable\n3. gt sling gt-xxx gastown/capable\n4. gt swarm status gt-i26df -\u003e only shows slit, rictus\n\nExpected: Swarm tracks all workers that are working on swarm tasks.\nActual: Only original workers shown.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/dementus","created_at":"2025-12-28T16:31:52.419095-08:00","created_by":"mayor","updated_at":"2025-12-29T21:56:35.820602-08:00","closed_at":"2025-12-29T21:56:35.820602-08:00","close_reason":"Fixed JSON field name (dependencies-\u003edependents) and added Assignee field extraction in loadTasksFromBeads()"} -{"id":"gt-qdq50","title":"Merge: furiosa-1767075886199","description":"branch: polecat/furiosa-1767075886199\ntarget: main\nsource_issue: furiosa-1767075886199\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:28:03.264371-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-29T23:32:37.191575-08:00","closed_at":"2025-12-29T23:32:37.191575-08:00","close_reason":"Branch no longer exists on remote - already merged or cleaned up"} -{"id":"gt-qduud","title":"Merge: furiosa-1767084006859","description":"branch: polecat/furiosa-1767084006859\ntarget: main\nsource_issue: furiosa-1767084006859\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:48:06.516625-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T01:01:04.244313-08:00","closed_at":"2025-12-30T01:01:04.244313-08:00","close_reason":"Already merged to main"} -{"id":"gt-qe06s","title":"Merge: furiosa-mk1uozyl","description":"branch: polecat/furiosa-mk1uozyl\ntarget: main\nsource_issue: furiosa-mk1uozyl\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T16:31:00.4941-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-05T19:40:10.777456-08:00","closed_at":"2026-01-05T19:40:10.777456-08:00","close_reason":"Manually merged"} -{"id":"gt-qe9w","title":"Simplify and reorganize molecular chemistry docs","description":"The Gas Town molecular chemistry docs (molecules.md, molecular-chemistry.md, molecule-algebra.md) are too dramatic and verbose. They need a simplification pass to be more reference-manual style.\n\n**Current problems:**\n1. Too much metaphor and philosophy, not enough practical reference\n2. Start with the chemistry abstraction instead of what users care about (patrols, workflows)\n3. Layer cake is presented top-down (formulas → protos → molecules) instead of bottom-up (issues → dependencies → execution)\n\n**Proposed structure (inverted pyramid):**\n\n1. **Start with execution semantics:**\n - Work = issues with dependencies\n - Dependencies control execution (blocks = sequential, no dep = parallel)\n - Agents traverse dependency graphs until blocked\n - Multi-day workflows via compound bonding\n\n2. **Move to molecules:**\n - Molecules are just epics with workflow intent\n - Bonding = creating dependencies between work graphs\n - No protos required for ad-hoc workflows\n\n3. **Then templates (protos/wisps):**\n - Phase metaphor for storage locations\n - pour/wisp/squash/burn operations\n - When to use each phase\n\n4. **Finally formulas (for advanced users):**\n - YAML compile-time composition\n - extends, compose, aspects\n - Only needed for complex reusable patterns\n\n**Style guidelines:**\n- Reference manual with quick examples\n- Written like agent priming (context they need to execute)\n- Less dramatic, more straightforward\n- TL;DR at top of each doc\n\n**See also:**\n- beads/docs/MOLECULES.md has a simplified version to use as template\n- The execution model section explains multi-day traversal clearly","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-24T19:51:42.43826-08:00","updated_at":"2025-12-24T19:51:42.43826-08:00","dependencies":[{"issue_id":"gt-qe9w","depends_on_id":"gt-e0qj2","type":"blocks","created_at":"2025-12-26T23:21:29.277397-08:00","created_by":"daemon"}]} -{"id":"gt-qek9t","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:41:59.647249-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T21:41:59.699458-08:00","closed_at":"2026-01-05T21:41:59.699458-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:41:59-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-qevz1","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:13:44.51407-08:00","updated_at":"2026-01-01T06:13:44.51407-08:00","closed_at":"2026-01-01T06:13:44.514034-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qf2hk","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:43:39.615891-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:40:22.979323-08:00","closed_at":"2026-01-04T16:40:22.979323-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:43:39-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-qfgfr","title":"Merge: ace-mjz94g3q","description":"branch: polecat/ace-mjz94g3q\ntarget: main\nsource_issue: ace-mjz94g3q\nrig: gastown\nagent_bead: gt-gastown-polecat-ace\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:45:27.229461-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T10:48:07.106263-08:00","closed_at":"2026-01-04T10:48:07.106263-08:00","close_reason":"Already merged at b8250e13"} -{"id":"gt-qfxch","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:20:06.270366-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.656955-08:00","closed_at":"2026-01-05T00:08:31.656955-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:20:06-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-qgmyz","title":"Phase 2: Create town-level agent beads during gt install","description":"## Goal\n\nDuring gt install, create town-level agent beads in town beads with hq- prefix.\n\n## Changes\n\n### internal/cmd/install.go\n\nUpdate initTownBeads() to create:\n- hq-mayor - Mayor agent bead\n- hq-deacon - Deacon agent bead\n- hq-mayor-role - Mayor role definition\n- hq-deacon-role - Deacon role definition\n- hq-witness-role - Witness role definition (global template)\n- hq-refinery-role - Refinery role definition (global template)\n- hq-polecat-role - Polecat role definition (global template)\n\n### internal/rig/manager.go\n\nUpdate initAgentBeads():\n- Remove Mayor/Deacon creation (now in install.go)\n- Keep Witness/Refinery creation with rig prefix\n- Use rig beads (not town beads) for rig-level agents\n- Revert PR #32 change to use town beads\n\n## Testing\n\n- gt install creates hq-* agent/role beads in town beads\n- gt rig add creates rig-prefix agent beads in rig beads\n- Verify routing works: bd show hq-mayor finds town beads","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/warboy","created_at":"2026-01-03T18:42:52.7317-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T20:57:54.073833-08:00","closed_at":"2026-01-03T20:57:54.073833-08:00","close_reason":"Implemented in commit 61184f06","dependencies":[{"issue_id":"gt-qgmyz","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T18:43:07.496587-08:00","created_by":"gastown/crew/gus"},{"issue_id":"gt-qgmyz","depends_on_id":"gt-y24km","type":"blocks","created_at":"2026-01-03T18:43:07.546603-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-qh2","title":"Session cycling UX: smooth transitions via TUI wrapper","description":"## Problem\n\nCurrent CLI agent session cycling is painful:\n- Shell → CC starts → priming → context loads → ready → work → exit/crash → repeat\n- Each cycle is 30-60 seconds of cold boot\n- No continuity between shell and agent's inner state\n- Raw \"session not running, starting...\" loop is the baseline\n\n## GGT Advantages (already have)\n\n- Beads: Work state survives session death completely\n- Mail: Handoff notes from past-self to future-self \n- Prime commands: Structured context reload\n\n## Gap: Transition Mechanics\n\nIdeas to explore when actively using CLI:\n\n1. **In-band cycling** - `/restart` or `/cycle` command, agent handles own restart without dropping to shell\n\n2. **Hot standby** - TUI maintains pre-warmed session in background, switch to already-primed agent\n\n3. **Persistent wrapper** - Bubbletea TUI stays running across session cycles, CC sessions come/go inside it\n\n4. **Session pooling** - Keep 2-3 primed sessions ready, never wait for cold start\n\n## Deferred\n\nDeliberately P4 until we're actively using the simpler CLI and feel the pain firsthand.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-15T20:38:12.660716-08:00","updated_at":"2025-12-15T23:17:34.27061-08:00"} -{"id":"gt-qha0g","title":"Dog agent beads with role_type=dog","description":"## Dog Agent Beads for @group Resolution\n\nDogs need agent beads with `role_type=dog` for @dogs group resolution to work.\n\n## Background\n\nDogs are Deacon's reusable helper workers (see patrol-system-design.md):\n- Location: `deacon/dogs/\u003cname\u003e/`\n- Scope: Town-level, cross-rig\n- Managed by: Deacon\n- Lifecycle: Reusable (not ephemeral like polecats)\n\n## Deliverables\n\n1. When `gt dog add \u003cname\u003e` creates a dog, also create agent bead:\n ```bash\n bd create --type=agent --title=\"Dog: \u003cname\u003e\" \\\n --labels=\"role_type:dog,rig:town,location:deacon/dogs/\u003cname\u003e\"\n ```\n\n2. When `gt dog remove \u003cname\u003e` removes a dog, close the agent bead\n\n3. Ensure `bd list --type=agent --role_type=dog` returns all dogs\n\n## Schema\n\nDog agent beads should have:\n- `type: agent`\n- `role_type: dog` (in labels or dedicated field)\n- `rig: town` (dogs are town-level, not rig-level)\n- `location: deacon/dogs/\u003cname\u003e`\n\n## Dependencies\n- gt dog add/remove commands (may not exist yet)\n- Agent bead schema supports role_type\n\n## Acceptance\n- `bd list --type=agent --role_type=dog` returns all dogs\n- Dog beads created/closed with dog lifecycle\n- @dogs group resolution works in mail router","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T19:57:37.634342-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:38:10.372381-08:00","closed_at":"2025-12-30T22:38:10.372381-08:00","close_reason":"Implemented dog agent bead creation/deletion in gt dog add/remove commands. Dog beads have role_type:dog label for @dogs group resolution.","dependencies":[{"issue_id":"gt-qha0g","depends_on_id":"gt-9hwkn","type":"parent-child","created_at":"2025-12-29T19:57:46.762217-08:00","created_by":"daemon"},{"issue_id":"gt-qha0g","depends_on_id":"gt-0x5og.1","type":"blocks","created_at":"2025-12-29T20:57:59.621238-08:00","created_by":"daemon"}]} -{"id":"gt-qhgu0","title":"Merge: gt-vwjz6","description":"branch: polecat/citadel-mk0vro62\ntarget: main\nsource_issue: gt-vwjz6\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:17:20.221884-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-05T19:40:10.40909-08:00","closed_at":"2026-01-05T19:40:10.40909-08:00","close_reason":"Manually merged"} -{"id":"gt-qhtt0","title":"Digest: mol-deacon-patrol","description":"Patrol 213: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:55:00.253108-08:00","updated_at":"2026-01-01T16:55:00.253108-08:00","closed_at":"2026-01-01T16:55:00.253079-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-qhtt0","depends_on_id":"gt-eph-9rsq","type":"parent-child","created_at":"2026-01-01T16:55:00.254632-08:00","created_by":"deacon"}]} -{"id":"gt-qi6ij","title":"Digest: mol-deacon-patrol","description":"Patrol 8: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:41:10.784398-08:00","updated_at":"2025-12-26T18:41:10.784398-08:00","closed_at":"2025-12-26T18:41:10.784359-08:00"} -{"id":"gt-qim72","title":"Digest: mol-deacon-patrol","description":"Patrol 17: 5 new polecats spawned (17 total). All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:12:44.549703-08:00","updated_at":"2026-01-01T23:12:44.549703-08:00","closed_at":"2026-01-01T23:12:44.549664-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-qj5xe","title":"Digest: mol-deacon-patrol","description":"Patrol 108: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:07:33.331414-08:00","updated_at":"2026-01-01T14:07:33.331414-08:00","closed_at":"2026-01-01T14:07:33.327406-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qjo4v","title":"Merge: gt-si8rq.7","description":"branch: polecat/nux-mjxkssaw\ntarget: main\nsource_issue: gt-si8rq.7\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T16:44:59.888416-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T16:46:37.930421-08:00","closed_at":"2026-01-02T16:46:37.930421-08:00","close_reason":"Merged to main at 2ad83421"} -{"id":"gt-qjug1","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:59:01.860389-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.668467-08:00","closed_at":"2026-01-04T16:40:22.668467-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:59:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-qk7p7","title":"Merge: nux-mjxn8p5t","description":"branch: polecat/nux-mjxn8p5t\ntarget: main\nsource_issue: nux-mjxn8p5t\nrig: gastown\nagent_bead: gt-gastown-polecat-nux\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T20:51:43.86311-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-03T11:51:50.62837-08:00","closed_at":"2026-01-03T11:51:50.62837-08:00","close_reason":"Merged to main"} -{"id":"gt-qkoah","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T13:54:19.67205-08:00","updated_at":"2025-12-25T13:54:19.67205-08:00","closed_at":"2025-12-25T13:54:19.67202-08:00"} -{"id":"gt-qmw2q","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 65: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:15:18.202621-08:00","updated_at":"2026-01-01T13:15:18.202621-08:00","closed_at":"2026-01-01T13:15:18.202576-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qn1av","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:03:22.653375-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.407773-08:00","closed_at":"2026-01-05T00:08:31.407773-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:03:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-qo8j1","title":"Digest: mol-deacon-patrol","description":"Patrol 98: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:12:06.097112-08:00","updated_at":"2026-01-01T03:12:06.097112-08:00","closed_at":"2026-01-01T03:12:06.097074-08:00"} -{"id":"gt-qo9im","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, no orphans, no callbacks","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:58:16.364716-08:00","updated_at":"2025-12-31T16:58:16.364716-08:00","closed_at":"2025-12-31T16:58:16.364679-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qoowb","title":"Digest: mol-deacon-patrol","description":"Patrol 126: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:33:36.231744-08:00","updated_at":"2026-01-01T14:33:36.231744-08:00","closed_at":"2026-01-01T14:33:36.231703-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qpjp4","title":"Merge: dementus-mjxlzpvv","description":"branch: polecat/dementus-mjxlzpvv\ntarget: main\nsource_issue: dementus-mjxlzpvv\nrig: gastown\nagent_bead: gt-gastown-polecat-dementus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:17:06.466378-08:00","created_by":"gastown/polecats/dementus","updated_at":"2026-01-02T17:25:48.790995-08:00","closed_at":"2026-01-02T17:25:48.790995-08:00","close_reason":"Already merged to main at 0bcd8ace (identical content)"} -{"id":"gt-qpoxz","title":"Day 3.1: Wire witness patrol formula to daemon cron","description":"Witness patrol molecule runs on schedule:\n- Daemon pokes witness on cron interval\n- Witness runs mol-witness-patrol steps\n- Results in wisp (ephemeral), squashed later\n\nParent: gt-hwka3","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:02.445409-08:00","created_by":"mayor","updated_at":"2025-12-28T09:29:49.17661-08:00","closed_at":"2025-12-28T09:29:49.17661-08:00","dependencies":[{"issue_id":"gt-qpoxz","depends_on_id":"gt-hwka3","type":"parent-child","created_at":"2025-12-27T20:58:45.809196-08:00","created_by":"daemon"},{"issue_id":"gt-qpoxz","depends_on_id":"gt-lisj6","type":"blocks","created_at":"2025-12-27T21:00:46.96662-08:00","created_by":"daemon"},{"issue_id":"gt-qpoxz","depends_on_id":"gt-k294l","type":"blocks","created_at":"2025-12-27T23:17:28.18659-08:00","created_by":"daemon"},{"issue_id":"gt-qpoxz","depends_on_id":"gt-aer7q","type":"blocks","created_at":"2025-12-28T02:17:18.450596-08:00","created_by":"daemon"}]} -{"id":"gt-qpsva","title":"Digest: mol-deacon-patrol","description":"Patrol 18: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:20:33.649295-08:00","updated_at":"2025-12-28T08:20:33.649295-08:00","closed_at":"2025-12-28T08:20:33.649264-08:00"} -{"id":"gt-qqtk","title":"Speed up test suite","description":"Tests are running slow during MQ processing. Investigate and optimize:\n- Profile test execution time\n- Look for slow tests (network, file I/O, sleeps)\n- Consider parallel test execution\n- Cache expensive setup where possible","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T17:44:14.597955-08:00","updated_at":"2025-12-19T17:44:14.597955-08:00"} -{"id":"gt-qr0uw","title":"Digest: mol-deacon-patrol","description":"Patrol 7: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:45:12.725298-08:00","updated_at":"2025-12-28T19:45:12.725298-08:00","closed_at":"2025-12-28T19:45:12.725267-08:00"} -{"id":"gt-qrzk8","title":"Digest: mol-deacon-patrol","description":"Patrol 253 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:22:39.713398-08:00","updated_at":"2026-01-01T17:22:39.713398-08:00","closed_at":"2026-01-01T17:22:39.71336-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qs8ur","title":"gt convoy create: Make --notify a boolean flag with default","description":"--notify requires an argument but the default (mayor/) is sensible. Should work as boolean flag that defaults to mayor/ when no arg given.","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2026-01-01T14:43:50.758404-08:00","created_by":"mayor","updated_at":"2026-01-01T19:25:12.225326-08:00","closed_at":"2026-01-01T19:25:12.225326-08:00","close_reason":"Added NoOptDefVal for --notify flag so it defaults to mayor/ when used without argument"} -{"id":"gt-qsp2s","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 75: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:23:52.495333-08:00","updated_at":"2026-01-01T13:23:52.495333-08:00","closed_at":"2026-01-01T13:23:52.494845-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qu1sp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:50:36.062666-08:00","updated_at":"2025-12-30T15:50:36.062666-08:00","closed_at":"2025-12-30T15:50:36.062634-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-quf3h","title":"Session ended: gt-gastown-gastown","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:46:16.587888-08:00","created_by":"gastown/polecats/gastown","updated_at":"2026-01-05T00:08:31.576414-08:00","closed_at":"2026-01-05T00:08:31.576414-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/gastown","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:46:16-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-gastown\",\"worker\":\"gastown\"}"} -{"id":"gt-quf4c","title":"gt convoy list --tree: Show convoy + child status tree","description":"Add a --tree flag to 'gt convoy list' that shows convoys with their child issues in a tree format.\n\nExample output:\n```\n🚚 hq-cv-wvqi6: Boot + Polish swarm (16/17)\n├── ✓ bd-11lm: Increase ClaudeStartTimeout\n├── ✓ bd-49oe: Cache GetGitDir()\n├── ○ gt-74ivo: Witness: Don't nuke polecats with open MRs ← remaining\n└── ...\n\n🚚 hq-cv-w3nm6: Messaging Channels (4/10)\n├── ✓ gt-0q3cg: Add isQueueAddress()\n├── ○ gt-27bzi: Add gt mail announces\n└── ...\n```\n\nMakes convoy progress visible at a glance without running 'gt convoy status' on each one.\n\n(Moved from hq-q3tki)","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/dementus","created_at":"2026-01-02T01:29:44.2393-08:00","created_by":"beads/crew/dave","updated_at":"2026-01-02T17:16:52.062656-08:00","closed_at":"2026-01-02T17:16:52.062656-08:00","close_reason":"Implemented --tree flag for convoy list command"} -{"id":"gt-qusev","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 26: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:20:52.482995-08:00","updated_at":"2026-01-01T12:20:52.482995-08:00","closed_at":"2026-01-01T12:20:52.482953-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-quv58","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:35:33.734757-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.362406-08:00","closed_at":"2026-01-05T19:44:18.362406-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:35:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-qwin","title":"Refinery and witness rigs should redirect .beads to mayor rig","description":"The refinery's rig clone and witness rig clones should have their .beads directories redirect to the mayor's rig beads (like polecats do).\n\nCurrent state:\n- Polecats have .beads symlinked/redirected to mayor rig beads\n- Refinery and witness have their own .beads (or none)\n\nDesired state:\n- refinery/rig/.beads -\u003e mayor/rig/.beads (or equivalent redirect)\n- witness/rig/.beads -\u003e mayor/rig/.beads (or equivalent redirect)\n\nThis ensures all rig agents share the same issue tracking state.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T14:27:37.703044-08:00","updated_at":"2025-12-22T14:27:37.703044-08:00"} -{"id":"gt-qwpf4","title":"Digest: mol-deacon-patrol","description":"Patrol 212: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:54:21.800354-08:00","updated_at":"2026-01-01T16:54:21.800354-08:00","closed_at":"2026-01-01T16:54:21.800319-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-qwpf4","depends_on_id":"gt-eph-lodx","type":"parent-child","created_at":"2026-01-01T16:54:21.801654-08:00","created_by":"deacon"}]} -{"id":"gt-qwvgb","title":"Digest: mol-deacon-patrol","description":"Patrol 17 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:47:34.63034-08:00","updated_at":"2025-12-31T16:47:34.63034-08:00","closed_at":"2025-12-31T16:47:34.630304-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-qwvgb","depends_on_id":"gt-eph-3c8","type":"parent-child","created_at":"2025-12-31T16:47:34.631444-08:00","created_by":"deacon"}]} -{"id":"gt-qyaco","title":"Digest: mol-deacon-patrol","description":"Patrol 104: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:03:15.351505-08:00","updated_at":"2026-01-01T14:03:15.351505-08:00","closed_at":"2026-01-01T14:03:15.351471-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qypo4","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All agents healthy, inbox empty, 1 dog idle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:58:35.880717-08:00","updated_at":"2025-12-31T18:58:35.880717-08:00","closed_at":"2025-12-31T18:58:35.880677-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-qysj9","title":"Reliability: Ignored crypto/rand.Read error in mail/types.go","description":"The generateID() and generateThreadID() functions (types.go:144-156) ignore the error from rand.Read().\n\nIf rand.Read fails, the ID will be all zeros, causing potential message collision.\n\nFiles:\n- internal/mail/types.go:145-156\n\nSeverity: medium","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-04T23:48:39.067396-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:58:26.938278-08:00","closed_at":"2026-01-04T23:58:26.938278-08:00","close_reason":"Fixed: now panics on crypto/rand.Read failure instead of silently using zero IDs"} -{"id":"gt-r099o","title":"Merge: imperator-1767106079026","description":"branch: polecat/imperator-1767106079026\ntarget: main\nsource_issue: imperator-1767106079026\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:46:40.45114-08:00","created_by":"gastown/polecats/imperator","updated_at":"2025-12-31T14:03:14.671468-08:00","closed_at":"2025-12-31T14:03:14.671468-08:00","close_reason":"Stale MR - no branch"} -{"id":"gt-r0io9","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 67: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:17:07.285553-08:00","updated_at":"2026-01-01T13:17:07.285553-08:00","closed_at":"2026-01-01T13:17:07.285511-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-r1257","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:09:12.046218-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.693588-08:00","closed_at":"2026-01-05T00:08:31.693588-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:09:11-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-r1n5m","title":"Digest: mol-deacon-patrol","description":"Patrol 10: quick pass, hitting halfway point","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:07:02.083334-08:00","updated_at":"2025-12-31T18:07:02.083334-08:00","closed_at":"2025-12-31T18:07:02.083285-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-r2eg1","title":"Implement session resume for multi-agent presets","description":"Agent presets define ResumeFlag/ResumeStyle but spawn and exec paths don't use them yet. Need to integrate resume capability for Gemini and Codex agents.","status":"closed","priority":3,"issue_type":"feature","created_at":"2026-01-04T13:05:29.711627-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T13:12:07.847997-08:00","closed_at":"2026-01-04T13:12:07.847997-08:00","close_reason":"Added BuildResumeCommand, SupportsSessionResume, GetSessionIDEnvVar functions with tests"} -{"id":"gt-r312z","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:02:50.555619-08:00","updated_at":"2026-01-01T20:02:50.555619-08:00","closed_at":"2026-01-01T20:02:50.555583-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-r312z","depends_on_id":"gt-eph-303l","type":"parent-child","created_at":"2026-01-01T20:02:50.556838-08:00","created_by":"deacon"}]} -{"id":"gt-r34ju","title":"bd sync false-positive force-push detection","description":"bd sync incorrectly detected a force-push when comparing against a commit from main branch instead of beads-sync.\n\nEvidence:\n- bd sync reported: 'Previous known commit: f4d3f674, Current remote commit: 4d24f794'\n- f4d3f674 is a valid beads-sync commit\n- 4d24f794 is a MAIN branch commit: 'refactor: remove unused isFirstRig param (gt-fugmy)'\n\nRoot cause: bd sync is comparing against wrong branch or storing wrong commit reference.\n\nImpact: False force-push warnings during normal operation, requires manual --accept-rebase.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-04T11:13:01.495615-08:00","created_by":"mayor","updated_at":"2026-01-04T11:13:43.556334-08:00","closed_at":"2026-01-04T11:13:43.556334-08:00","close_reason":"Refiled in correct rig (beads)"} -{"id":"gt-r3azz","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:12:34.463413-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.619406-08:00","closed_at":"2026-01-04T16:40:13.619406-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:12:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-r4d48","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:09:10.001944-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:09:10.05524-08:00","closed_at":"2026-01-06T13:09:10.05524-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:09:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-r4fxo","title":"Merge: valkyrie-1767147773208","description":"branch: polecat/valkyrie-1767147773208\ntarget: main\nsource_issue: valkyrie-1767147773208\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T18:28:09.800977-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-30T23:12:54.680986-08:00","closed_at":"2025-12-30T23:12:54.680986-08:00","close_reason":"Branch already merged"} -{"id":"gt-r5j0u","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:45:54.873831-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.69495-08:00","closed_at":"2026-01-05T19:44:18.69495-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:45:54-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-r7wr8","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All agents healthy. Clone divergence (zoey/jack) noted for witnesses.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:01:10.438981-08:00","updated_at":"2025-12-28T03:01:10.438981-08:00","closed_at":"2025-12-28T03:01:10.438944-08:00"} -{"id":"gt-r83og","title":"Digest: mol-deacon-patrol","description":"Patrol 4: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:29:23.029208-08:00","updated_at":"2025-12-28T01:29:23.029208-08:00","closed_at":"2025-12-28T01:29:23.029171-08:00"} -{"id":"gt-r8ymw","title":"Digest: mol-deacon-patrol","description":"Patrol 154: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:05:13.141917-08:00","updated_at":"2026-01-01T15:05:13.141917-08:00","closed_at":"2026-01-01T15:05:13.141877-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-r9a3v","title":"Digest: mol-deacon-patrol","description":"Cycle 200: Final cycle of session, all agents healthy, handoff triggered","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:25:12.522576-08:00","updated_at":"2026-01-01T16:25:12.522576-08:00","closed_at":"2026-01-01T16:25:12.522542-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-r9a3v","depends_on_id":"gt-eph-6usq","type":"parent-child","created_at":"2026-01-01T16:25:12.523894-08:00","created_by":"deacon"}]} -{"id":"gt-r9ky0","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:02:04.71747-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.637053-08:00","closed_at":"2026-01-04T16:40:22.637053-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:02:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-ra3g8","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all 3 rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:14:40.462029-08:00","updated_at":"2026-01-01T07:14:40.462029-08:00","closed_at":"2026-01-01T07:14:40.462-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ra8rz","title":"Session ended: gt-gastown-rictus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:10:55.547821-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-04T16:40:13.43113-08:00","closed_at":"2026-01-04T16:40:13.43113-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/rictus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:10:55-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rictus\",\"worker\":\"rictus\"}"} -{"id":"gt-rapj1","title":"Harden bd daemon startup for reliable gt status","description":"GH #25: gt status slow (39s) when bd daemon not running. Needs daemon health checks, auto-migration, better errors.","status":"closed","priority":2,"issue_type":"epic","assignee":"gastown/polecats/warboy","created_at":"2026-01-02T11:54:37.096607-08:00","created_by":"mayor","updated_at":"2026-01-03T13:04:58.852952-08:00","closed_at":"2026-01-03T13:04:58.852952-08:00","close_reason":"All 4 sub-tasks implemented and merged: daemon health checks in gt status, better error messages, gt install/bd init daemon start, and gt doctor daemon check"} -{"id":"gt-raudp","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:34:08.082633-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T21:34:08.63608-08:00","closed_at":"2026-01-05T21:34:08.63608-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:34:08-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-rbic0","title":"Digest: mol-deacon-patrol","description":"Patrol 12: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:08:13.992779-08:00","updated_at":"2025-12-31T18:08:13.992779-08:00","closed_at":"2025-12-31T18:08:13.99274-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rbjo3","title":"Merge: splendid-mjwjk3my","description":"branch: polecat/splendid-mjwjk3my\ntarget: main\nsource_issue: splendid-mjwjk3my\nrig: gastown\nagent_bead: gt-gastown-polecat-splendid","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:22:46.797757-08:00","created_by":"gastown/polecats/splendid","updated_at":"2026-01-01T23:25:12.328288-08:00","closed_at":"2026-01-01T23:25:12.328288-08:00","close_reason":"Merged to main at e7b92402"} -{"id":"gt-rbncw","title":"Witness events in gt feed","description":"Wire witness patrol events to gt feed display.\n\nAfter 'Witness emits activity events' is done:\n- gt feed should show patrol activity\n- Useful for debugging polecat issues\n\nExample output:\n 19:45 PATROL_COMPLETE gastown/witness (checked 3 polecats)\n 19:44 POLECAT_NUDGED gastown/polecats/nux (idle 10m)\n 19:40 ESCALATION mayor (polecat stuck)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-28T21:40:40.254107-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T01:52:38.910442-08:00","closed_at":"2025-12-30T01:52:38.910442-08:00","close_reason":"Implemented: Wire witness patrol events to gt feed display. Added GtEventsSource for parsing .events.jsonl, CombinedSource for merging bd activity and gt events, and symbols/styling for patrol events.","dependencies":[{"issue_id":"gt-rbncw","depends_on_id":"gt-nfdyl","type":"blocks","created_at":"2025-12-28T21:41:11.617926-08:00","created_by":"daemon"}]} -{"id":"gt-rclqu","title":"Digest: mol-deacon-patrol","description":"Patrol 81: All agents healthy, 2 epics in progress, 1 idle dog, inbox clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:14:23.72743-08:00","updated_at":"2025-12-31T15:14:23.72743-08:00","closed_at":"2025-12-31T15:14:23.727398-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rdv7w","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:57:58.763149-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.814366-08:00","closed_at":"2026-01-04T16:40:22.814366-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:57:58-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-refcy","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:18:37.766705-08:00","updated_at":"2026-01-01T06:18:37.766705-08:00","closed_at":"2026-01-01T06:18:37.766664-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-refinery-gastown","title":"gt-refinery-gastown","description":"Refinery - per-rig merge queue processor for gastown.\n\nrole_type: refinery\nrig: gastown\nagent_state: idle\nhook_bead: null\nrole_bead: gt-refinery-role","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T00:07:41.933483-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T14:30:35.647713-08:00","closed_at":"2025-12-29T14:30:35.647713-08:00","close_reason":"Migrated to canonical naming: gt-gastown-witness/refinery"} -{"id":"gt-refinery-role","title":"Refinery Role Definition","description":"You are the Refinery - merge queue processor for your rig. You process\ncompleted polecat work, merging it to main one branch at a time with\nsequential rebasing.\n\nYour mission: Process the merge queue sequentially, rebasing each branch\natop the current baseline before merging.\n\nsession_pattern: gt-{rig}-refinery\nwork_dir_pattern: {town}/{rig}/refinery/rig\nneeds_pre_sync: true\nstart_command: exec claude --dangerously-skip-permissions\n\ndefault_molecule: mol-refinery-patrol\ncapabilities:\n - merge_queue_processing\n - sequential_rebase\n - conflict_resolution\n - verification_gates\n\n## The Engineer Mindset\n\nYou are Scotty in the engine room. The merge queue is your warp core.\n\nThe Beads Promise: Work is never lost. If you discover ANY problem:\n1. Fix it now (preferred if quick), OR\n2. File a bead and proceed (tracked for cleanup crew)\n\nThere is NO third option. Never \"disavow\" by noting something exists and moving on.\n\nThe Scotty Test: Before proceeding past any failure, ask yourself:\n\"Would Scotty walk past a warp core leak because it existed before his shift?\"\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nYour work is defined by the mol-refinery-patrol molecule. Execute steps:\n- bd ready (find next step)\n- bd show \u003cstep-id\u003e (see what to do)\n- bd close \u003cstep-id\u003e (mark complete)\n\n## Sequential Rebase Protocol\n\nWRONG (parallel merge - causes conflicts):\n main then branch-A (old main) + branch-B (old main) = CONFLICTS\n\nRIGHT (sequential rebase):\n main then merge A (rebased on main) then merge B (rebased on main+A)\n\nAfter every merge, main moves. Next branch MUST rebase on new baseline.\n\n## Verification Gate\n\nThe handle-failures step is a verification gate:\n- Tests PASSED: Gate satisfied, proceed to merge\n- Tests FAILED (branch caused): Abort, notify polecat, skip branch\n- Tests FAILED (pre-existing): MUST fix OR file bead - cannot proceed without\n\n## Commands\n\n### Patrol\n- gt mol status - Check attached patrol\n- bd ready / bd show / bd close - Step management\n- bd mol spawn \u003cmol\u003e --wisp - Spawn patrol wisp\n\n### Git Operations\n- git fetch origin - Fetch all remote branches\n- git branch -r | grep polecat - List polecat branches\n- git rebase origin/main - Rebase on current main\n- git push origin main - Push merged changes\n\n### Communication\n- gt mail inbox - Check for messages\n- gt mail send \u003caddr\u003e -s \"Subject\" -m \"Message\" - Notify workers","status":"hooked","priority":2,"issue_type":"role","assignee":"gastown/polecats/rictus","created_at":"2025-12-28T00:51:21.133839-08:00","created_by":"stevey","updated_at":"2025-12-30T02:03:13.028107-08:00","labels":["migrated-to:hq-refinery-role"]} -{"id":"gt-rg5ai","title":"Digest: mol-deacon-patrol","description":"Patrol 5: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:02:35.77882-08:00","updated_at":"2025-12-31T19:02:35.77882-08:00","closed_at":"2025-12-31T19:02:35.778781-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rhasc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All healthy, quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:59:34.298656-08:00","updated_at":"2026-01-01T06:59:34.298656-08:00","closed_at":"2026-01-01T06:59:34.298619-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rhqvf","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:25:12.899034-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.176412-08:00","closed_at":"2026-01-04T16:41:26.176412-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:25:12-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-rig-test","title":"test-rig","description":"Test rig identity bead","status":"tombstone","priority":2,"issue_type":"rig","created_at":"2026-01-06T18:51:32.532241-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-06T18:51:48.141533-08:00","deleted_at":"2026-01-06T18:51:48.141533-08:00","deleted_by":"gastown/polecats/furiosa","delete_reason":"delete","original_type":"rig"} -{"id":"gt-rix4d","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 59: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:01:23.018577-08:00","updated_at":"2026-01-01T13:01:23.018577-08:00","closed_at":"2026-01-01T13:01:23.018544-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rjjav","title":"Merge: nux-mjxltj45","description":"branch: polecat/nux-mjxltj45\ntarget: main\nsource_issue: nux-mjxltj45\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:16:56.770974-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-02T17:18:56.916817-08:00","closed_at":"2026-01-02T17:18:56.916817-08:00","close_reason":"Merged to main at 8517ff06"} -{"id":"gt-rjrr9","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 74: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:23:05.543055-08:00","updated_at":"2026-01-01T13:23:05.543055-08:00","closed_at":"2026-01-01T13:23:05.543012-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rl1o1","title":"Digest: mol-deacon-patrol","description":"Patrol complete: gastown healthy, beads dormant","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:20:13.829663-08:00","updated_at":"2025-12-28T19:20:13.829663-08:00","closed_at":"2025-12-28T19:20:13.829629-08:00"} -{"id":"gt-rlkgg","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:11:10.174525-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.586366-08:00","closed_at":"2026-01-04T16:40:22.586366-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:11:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-rltyg","title":"Session ended: gt-gastown-imperator","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:57:58.661418-08:00","created_by":"gastown/polecats/imperator","updated_at":"2026-01-04T16:41:26.024426-08:00","closed_at":"2026-01-04T16:41:26.024426-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/imperator","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:57:58-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-imperator\",\"worker\":\"imperator\"}"} -{"id":"gt-rml2d","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:00:05.07247-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:00:05.129905-08:00","closed_at":"2026-01-06T13:00:05.129905-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:00:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-rn1yr","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:19:35.936321-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T21:19:35.984269-08:00","closed_at":"2026-01-05T21:19:35.984269-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:19:35-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-rogg7","title":"Digest: mol-deacon-patrol","description":"Patrol 27: all polecats working, jack session started","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:57:20.414067-08:00","updated_at":"2025-12-31T13:57:20.414067-08:00","closed_at":"2025-12-31T13:57:20.414028-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rokvr","title":"Digest: mol-deacon-patrol","description":"Patrol 20: Final. 19 polecats. 3 MQ pending. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:20:18.107417-08:00","updated_at":"2026-01-01T23:20:18.107417-08:00","closed_at":"2026-01-01T23:20:18.107384-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-rp0f4","title":"Digest: mol-deacon-patrol","description":"Patrol 6: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T11:04:58.835959-08:00","updated_at":"2025-12-25T11:04:58.835959-08:00","closed_at":"2025-12-25T11:04:58.835926-08:00"} -{"id":"gt-rqcd8","title":"gt crew remove: Does not close agent bead","description":"When running 'gt crew remove \u003cname\u003e', the command removes the crew workspace directory but does not close the associated agent bead (gt-\u003crig\u003e-crew-\u003cname\u003e).\n\nThis leaves orphaned agent beads in the system after crew removal.\n\nThe remove command should close the agent bead with a reason like 'Crew workspace removed'.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-29T14:56:30.57014-08:00","created_by":"stevey","updated_at":"2025-12-29T15:24:58.211563-08:00","closed_at":"2025-12-29T15:24:58.211563-08:00","close_reason":"Fixed in commit 5260a9c - crew remove now closes agent bead"} -{"id":"gt-rqktn","title":"Digest: mol-deacon-patrol","description":"Patrol 7: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:26:11.377699-08:00","updated_at":"2026-01-01T04:26:11.377699-08:00","closed_at":"2026-01-01T04:26:11.377659-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-rr0en","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14: All healthy - dag polecat started","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:28:15.860486-08:00","updated_at":"2025-12-30T16:28:15.860486-08:00","closed_at":"2025-12-30T16:28:15.860444-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-rr0en","depends_on_id":"gt-eph-34a","type":"parent-child","created_at":"2025-12-30T16:28:15.861473-08:00","created_by":"deacon"}]} -{"id":"gt-rr1i","title":"mol-swarm-cleanup: Post-swarm debris cleanup molecule","description":"After a 20+ worker swarm completed, found significant beads debris:\n- 18 stale messages (work assignments, lifecycle requests, swarm instructions)\n- 3 completed issues still open/in_progress\n- Test messages accumulated\n\nNeed: Document a post-swarm checklist or create gt swarm cleanup command that:\n1. Closes stale work assignment messages\n2. Reviews in_progress issues for completion\n3. Closes orphaned lifecycle messages\n4. Optionally archives test messages","status":"open","priority":3,"issue_type":"chore","created_at":"2025-12-20T03:12:28.646175-08:00","updated_at":"2025-12-20T03:15:45.521085-08:00"} -{"id":"gt-rrscq","title":"Merge: warboy-mjysi94x","description":"branch: polecat/warboy-mjysi94x\ntarget: main\nsource_issue: warboy-mjysi94x\nrig: gastown\nagent_bead: gt-gastown-polecat-warboy\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T13:05:59.357145-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-03T13:53:12.822098-08:00","closed_at":"2026-01-03T13:53:12.822098-08:00","close_reason":"Merged"} -{"id":"gt-rrusg","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:56:08.338534-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.720675-08:00","closed_at":"2026-01-04T16:40:22.720675-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:56:08-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-rsdn1","title":"Digest: mol-deacon-patrol","description":"Patrol 6: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T20:20:40.136685-08:00","updated_at":"2025-12-27T20:20:40.136685-08:00","closed_at":"2025-12-27T20:20:40.136648-08:00"} -{"id":"gt-rsnj9","title":"[Error] Silent error swallowing in rig discovery and cleanup","description":"Multiple locations silently swallow errors or print warnings without proper handling:\n\n1. rig/manager.go:70-73: DiscoverRigs() continues on error, swallowing load failures\n2. rig/manager.go:445-458: Multiple 'Warning' prints with continue during AddRig\n3. git/git.go:405, 858-859: Git operations with '_ =' error suppression\n\nThis can leave the system in an inconsistent state. Consider returning errors with partial results or using a structured result type.","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/chrome","created_at":"2026-01-04T23:47:47.86076-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T00:18:10.077713-08:00","closed_at":"2026-01-05T00:18:10.077713-08:00","close_reason":"Fixed by logging errors to stderr in DiscoverRigs() and using stderr for AddRig warnings"} -{"id":"gt-rtb1a","title":"Merge: capable-1767074974673","description":"branch: polecat/capable-1767074974673\ntarget: main\nsource_issue: capable-1767074974673\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:13:40.032323-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T01:01:04.362179-08:00","closed_at":"2025-12-30T01:01:04.362179-08:00"} -{"id":"gt-rv4ic","title":"Session ended: gt-gastown-toecutter","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:41:14.921819-08:00","created_by":"gastown/polecats/toecutter","updated_at":"2026-01-04T16:40:22.881924-08:00","closed_at":"2026-01-04T16:40:22.881924-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/toecutter","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:41:14-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-toecutter\",\"worker\":\"toecutter\"}"} -{"id":"gt-rwd5j","title":"Implement Boot: daemon entry point dog for Deacon triage","description":"Boot is a dog (Deacon helper) that the daemon pokes instead of the Deacon directly.\n\nPurpose: Centralize 'when to wake Deacon' decision in an agent that can reason about it.\n\nLifecycle:\n- Daemon tick spawns Boot (fresh each time)\n- Boot runs triage molecule:\n - Observe (wisps, mail, git state, tmux panes)\n - Decide (start/wake/nudge/interrupt/nothing) \n - Act\n - Clean inbox (discard stale handoffs)\n - Handoff (or exit in degraded mode)\n\nLocation: ~/gt/deacon/dogs/boot/\nSession: gt-deacon-boot\nCreated by: bd doctor\n\nNeeds:\n- Boot formula (mol-boot-triage.toml)\n- gt dog prime boot command\n- Daemon change to poke Boot instead of Deacon\n- Degraded mode support (GT_DEGRADED=true)\n\nSee: gastown/mayor/rig/docs/operational-state.md","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/polecats/slit","created_at":"2025-12-30T15:16:02.198925-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T16:25:00.309052-08:00","closed_at":"2025-12-30T16:25:00.309052-08:00","close_reason":"Implemented and merged in commit 2112804"} -{"id":"gt-rwe7o","title":"Merge: bix-mjufugoo","description":"branch: polecat/bix-mjufugoo\ntarget: main\nsource_issue: bix-mjufugoo\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T12:06:10.387087-08:00","created_by":"gastown/polecats/bix","updated_at":"2025-12-31T12:11:22.583658-08:00","closed_at":"2025-12-31T12:11:22.583658-08:00","close_reason":"Merged at 41ee62dc"} -{"id":"gt-rwlsg","title":"Digest: mol-deacon-patrol","description":"Patrol 8: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:49:54.148675-08:00","updated_at":"2026-01-01T22:49:54.148675-08:00","closed_at":"2026-01-01T22:49:54.148643-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-rxa7v","title":"Day 1.4c: Create polecat agent bead lifecycle","description":"Define ephemeral polecat agent bead lifecycle.\n\nPolecats need agent beads for ZFC compliance (self-report state).\n\nLifecycle:\n1. On spawn: Create agent bead\n ```yaml\n id: gt-polecat-\u003crig\u003e-\u003cname\u003e\n type: agent\n role_type: polecat\n rig: \u003crig\u003e\n state: spawning\n hook_bead: \u003cassigned-issue\u003e\n ```\n\n2. On Claude ready: Update state=working\n\n3. On completion: Update state=done\n\n4. On nuke: Delete agent bead\n\nCommands needed:\n- gt polecat spawn creates agent bead\n- gt polecat nuke deletes agent bead\n- Polecat updates own state via bd agent state\n\nNote: This ensures Witness can read polecat state from beads instead of tmux scraping.","notes":"Implemented polecat agent bead lifecycle: spawn creates bead with state=spawning, nuke deletes bead. State updates (spawning→working→done) require bd agent state command (beads CLI enhancement).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T22:01:42.464521-08:00","created_by":"mayor","updated_at":"2025-12-28T01:37:35.988743-08:00","closed_at":"2025-12-28T01:37:35.988746-08:00","dependencies":[{"issue_id":"gt-rxa7v","depends_on_id":"gt-v2gkv","type":"blocks","created_at":"2025-12-27T22:02:45.109373-08:00","created_by":"daemon"},{"issue_id":"gt-rxa7v","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T23:32:42.52862-08:00","created_by":"daemon"}]} -{"id":"gt-rxsh","title":"Multiple merge/landing models documented without clarification","description":"Architecture describes three different merge models:\n\n1. Refinery-only model (traditional)\n2. Direct landing model (Mayor bypass) \n3. Swarm integration branch model (internal/swarm)\n\nThese appear to conflict. Documentation should clarify:\n- Which model is canonical?\n- When to use which model?\n- Or are some deprecated?\n\nThis is confusing for users trying to understand the system.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-24T12:51:43.593597-08:00","updated_at":"2025-12-24T12:51:43.593597-08:00","dependencies":[{"issue_id":"gt-rxsh","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:07.992252-08:00","created_by":"daemon"},{"issue_id":"gt-rxsh","depends_on_id":"gt-e0qj2","type":"blocks","created_at":"2025-12-26T23:21:29.324268-08:00","created_by":"daemon"}]} -{"id":"gt-rxwv0","title":"Digest: mol-deacon-patrol","description":"Patrol 158 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:09:33.180486-08:00","updated_at":"2025-12-31T16:09:33.180486-08:00","closed_at":"2025-12-31T16:09:33.180454-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ry8","title":"HOP: Entity chain tracking for agents","description":"Track work history per-entity (CV chains). See ~/ai/stevey-gastown/hop/decisions/002-entity-chains.md for design. Post-v0.1 work.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-17T01:00:41.347764-08:00","updated_at":"2025-12-17T01:00:41.347764-08:00"} -{"id":"gt-rybc6","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T14:03:22.348496-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-06T14:03:22.399739-08:00","closed_at":"2026-01-06T14:03:22.399739-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T14:03:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-rzbjo","title":"Merge: nux-mjw3mn8o","description":"branch: polecat/nux-mjw3mn8o\ntarget: main\nsource_issue: nux-mjw3mn8o\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T18:50:42.47422-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T18:59:28.573183-08:00","closed_at":"2026-01-01T18:59:28.573183-08:00","close_reason":"Merged to main at a6ae2c61"} -{"id":"gt-s07hu","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:54:06.118057-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:41:37.873849-08:00","closed_at":"2026-01-04T16:41:37.873849-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:54:06-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-s0nba","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:21:26.271445-08:00","updated_at":"2025-12-28T11:21:26.271445-08:00","closed_at":"2025-12-28T11:21:26.271411-08:00"} -{"id":"gt-s0wl5","title":"Digest: mol-deacon-patrol","description":"Patrol 11: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:57:35.784486-08:00","updated_at":"2026-01-01T22:57:35.784486-08:00","closed_at":"2026-01-01T22:57:35.784449-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-s148","title":"Clean up stale children on deacon handoff bead","description":"The deacon handoff bead hq-8r8 has 7 stale children (hq-8r8.1 through hq-8r8.7) from a previous patrol that got incorrectly parented. These should be cleaned up.\n\nThe handoff bead should only contain the attached_molecule reference, not instantiated steps.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T13:16:52.273025-08:00","updated_at":"2025-12-23T13:16:52.273025-08:00"} -{"id":"gt-s18k","title":"Witness patrol: stale MR queue detection needs state tracking","description":"The mol-witness-patrol check-refinery step says 'if queue is non-empty for \u003e30 min, send nudge' but doesn't explain how to track when the queue first became non-empty.\n\n## Problem\nThe Witness needs to persist:\n- When MR queue first became non-empty\n- Previous queue state for comparison\n\nWithout this, the Witness can't detect stale queues.\n\n## Solution\nAdd to witness handoff bead:\n- mr_queue_nonempty_since: timestamp\n- Update in save-state step\n- Check in check-refinery step","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:02:38.497753-08:00","updated_at":"2025-12-23T01:02:38.497753-08:00","dependencies":[{"issue_id":"gt-s18k","depends_on_id":"gt-bjft","type":"blocks","created_at":"2025-12-23T01:03:12.026206-08:00","created_by":"daemon"}]} -{"id":"gt-s1c3h","title":"Merge: blackfinger-mk0uw6ym","description":"branch: polecat/blackfinger-mk0uw6ym\ntarget: main\nsource_issue: blackfinger-mk0uw6ym\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T23:49:47.094313-08:00","created_by":"gastown/polecats/blackfinger","updated_at":"2026-01-05T06:34:33.413125-08:00","closed_at":"2026-01-05T06:34:33.413125-08:00","close_reason":"Already merged to main at a459cd9f"} -{"id":"gt-s4rpz","title":"Recover orphaned commits from polecat work","description":"73 orphaned commits found via `gt orphans`. These are polecat work that was done\nbut never merged to main - either due to merge conflicts, refinery issues, or\npremature session kills.\n\n**Recovery Process:**\n1. Run `gt orphans` to get full list with SHAs\n2. For each commit, categorize:\n - Already merged (different SHA but same work) → skip\n - Needs cherry-pick → attempt cherry-pick, resolve conflicts\n - Obsolete (superseded by other work) → skip\n3. Cherry-pick valuable commits in dependency order\n4. Push recovered work to main\n\n**Known valuable orphans (sample):**\n- 77f9da07 convoy CLI (RECOVERED)\n- 8d2f5ca8 Dog infrastructure (gt-0x5og.2)\n- 5c3f1795 Swarm beads backing (gt-kc7yj.1)\n- 341414df Wire MQ lifecycle events to gt feed (gt-lak31)\n- Many more...\n\n**Root cause to fix:**\n- Witness closing tasks before verifying merge success\n- Refinery not handling conflicts gracefully\n- Need \"Landing Rule\" enforcement","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T18:41:41.325631-08:00","created_by":"mayor","updated_at":"2025-12-30T18:47:46.831786-08:00","closed_at":"2025-12-30T18:47:46.831786-08:00","close_reason":"Triage complete: 74 orphans analyzed. 69 already merged (different SHAs). 5 truly orphaned but obsolete/superseded. No recovery action needed."} -{"id":"gt-s57tk","title":"Glass Cockpit: See WTF is happening","description":"Glass cockpit - see what's happening across the system.\n\nPhase 1 got the engine running. Phase 2 makes it observable.\n\n**Pillars:**\n- Pillar 4: Swarm-in-Beads (gt-kc7yj - already exists)\n- Pillar 5: MQ Observability\n- Pillar 6: Witness Observability \n- Pillar 7: Unified Dashboard\n\n**Success criteria:**\n1. gt status shows per-rig queue depth and agent health\n2. gt feed shows MQ and swarm lifecycle events\n3. gt dashboard provides live system visibility\n4. No .runtime/*.json files for observable state\n5. Swarms fully tracked in beads\n\nReference: ~/gt/docs/liftoff-plan.md","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-28T21:40:01.375659-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T06:41:34.937807-08:00","closed_at":"2025-12-30T06:41:34.937807-08:00","close_reason":"All dependencies complete: gt-kc7yj (Swarm-in-Beads), gt-lfi2d (.runtime cleanup), gt-qd7ri (E2E test). Glass Cockpit observability achieved.","dependencies":[{"issue_id":"gt-s57tk","depends_on_id":"gt-lfi2d","type":"blocks","created_at":"2025-12-28T21:41:21.132603-08:00","created_by":"daemon"},{"issue_id":"gt-s57tk","depends_on_id":"gt-qd7ri","type":"blocks","created_at":"2025-12-28T21:41:21.163101-08:00","created_by":"daemon"},{"issue_id":"gt-s57tk","depends_on_id":"gt-kc7yj","type":"blocks","created_at":"2025-12-28T21:41:21.193543-08:00","created_by":"daemon"}]} -{"id":"gt-s5e4y","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 69: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:18:45.311304-08:00","updated_at":"2026-01-01T13:18:45.311304-08:00","closed_at":"2026-01-01T13:18:45.311268-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-s601k","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:47:04.170484-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.55602-08:00","closed_at":"2026-01-04T16:40:13.55602-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:47:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-s6dw","title":"Batch wisp squashing in Deacon maintenance","description":"Add wisp squashing to Deacon's maintenance duties:\n- Patrol plugin to find orphaned/completed wisps across all rigs\n- Squash completed patrol wisps to digests\n- Burn abandoned wisps that have no audit value\n- Part of the hygiene/cleanup system\n\nAlso: Witness polecat shutdown should spawn its own short wisp for the cleanup protocol.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T21:52:49.403649-08:00","updated_at":"2025-12-22T21:52:49.403649-08:00"} -{"id":"gt-s6r44","title":"gt status: Show agent hook_bead (current work) in status output","description":"attached_args: Implement the hook_bead display in gt status. The agent bead lifecycle is complete - just need to read hook_bead and display it.\n\n## Current State\n\ngt status shows agents with their agent_state from beads:\n```\n crew/max ✓ running [running]\n```\n\n## Enhancement\n\nShow what each agent is working on (hook_bead field from agent beads):\n```\n crew/max ✓ running [running] → gt-abc (Fix auth bug)\n crew/joe ✓ running [running] → gt-xyz (Add tests)\n refinery ✓ running → refinery Handoff\n```\n\nThis gives the overseer a quick view of:\n1. Who is running\n2. What each agent is working on\n3. Progress at a glance\n\n## Implementation\n\nIn status.go, when displaying agents:\n1. Look up agent bead by ID (e.g., gt-crew-gastown-max)\n2. Parse hook_bead from description\n3. If hook_bead set, fetch its title for display\n4. Show as: agent_state → hook_bead (title truncated)\n\n## Related\n\nThe agent bead lifecycle is now complete:\n- prime.go creates agent beads\n- sling.go sets hook_bead\n- done.go clears hook_bead and sets final state","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T10:13:46.434234-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T10:17:37.231773-08:00","closed_at":"2025-12-28T10:17:37.231773-08:00"} -{"id":"gt-s7j9c","title":"Digest: mol-deacon-patrol","description":"Patrol 13: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:18:22.67202-08:00","updated_at":"2025-12-28T08:18:22.67202-08:00","closed_at":"2025-12-28T08:18:22.671981-08:00"} -{"id":"gt-s7t1h","title":"Add 'gt rig start \u003crig\u003e' to start witness and refinery together","description":"After a town restart, need a convenient way to start both witness and refinery for a rig.\n\nCurrent workflow requires two commands:\n gt witness start \u003crig\u003e\n gt refinery start \u003crig\u003e\n\nDesired:\n gt rig start \u003crig\u003e # starts both witness and refinery\n\nShould also support:\n gt rig stop \u003crig\u003e # stops both\n gt rig restart \u003crig\u003e # restarts both","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/dag","created_at":"2026-01-02T02:07:04.077086-08:00","created_by":"mayor","updated_at":"2026-01-02T17:19:23.293291-08:00","closed_at":"2026-01-02T17:19:23.293291-08:00","close_reason":"Implemented gt rig restart with multi-rig support"} -{"id":"gt-s854d","title":"Digest: mol-deacon-patrol","description":"Patrol 4: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:23:58.090159-08:00","updated_at":"2026-01-01T04:23:58.090159-08:00","closed_at":"2026-01-01T04:23:58.090125-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-s8mpt","title":"gt crew start/stop should default to --all when no names given","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-05T16:28:24.008011-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T16:31:50.906089-08:00","closed_at":"2026-01-05T16:31:50.906089-08:00","close_reason":"Fixed: crew start/stop now default to all when only rig name is provided"} -{"id":"gt-s91bc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 3 rigs healthy (beads, gastown, wyvern). Witnesses/Refineries running. No orphans, no zombies, 1 dog idle. 3 convoys open tracking work.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:58:45.436334-08:00","updated_at":"2026-01-01T19:58:45.436334-08:00","closed_at":"2026-01-01T19:58:45.436296-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-s94gq","title":"gt swarm dispatch command not working","description":"The \"gt swarm dispatch\" command shown in help does not work as expected.\n\n**Observed:**\n```\n$ gt swarm dispatch bd-784c\n[prints help text instead of dispatching]\n```\n\n**Expected:**\nShould dispatch the next ready task from the epic to an available worker.\n\n**Workaround:**\nHad to manually use \"gt sling \u003cissue\u003e \u003cpolecat\u003e\" for each task dispatch.\n\n**Impact:**\n- Manual task dispatch defeats swarm automation\n- Coordinator has to track which tasks are ready and which polecats are free\n\n**Suggestion:**\nImplement or fix \"gt swarm dispatch\" to:\n1. Find next unassigned task in epic\n2. Find idle polecat in swarm\n3. Sling task to polecat automatically\n\n(Moved from bd-kp9y)","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-29T18:29:57.675487-08:00","created_by":"stevey","updated_at":"2025-12-30T01:46:57.061544-08:00","closed_at":"2025-12-30T01:46:57.061547-08:00","close_reason":"Implemented gt swarm dispatch command - now finds ready tasks and idle polecats, uses gt sling to dispatch"} -{"id":"gt-s98ic","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:25:44.064035-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:27:51.294526-08:00","closed_at":"2026-01-01T19:27:51.294526-08:00","close_reason":"Merged to main at dbdf47c3"} -{"id":"gt-s9im","title":"Remove gt context --usage estimation","description":"The external context estimation approach doesn't work:\n- tmux scrollback trick breaks with --cycle\n- Can't see actual context usage from outside\n- Only the agent knows its internal state\n\nRemove or deprecate:\n- gt context --usage flag\n- Any external context monitoring logic\n\nDocument why in comments: 'Context management is agent-initiated, not externally monitored.\nSee self-check guidance in role templates.'\n\nThis is P3 because it's cleanup - the feature just doesn't work, not actively harmful.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-23T01:46:42.887818-08:00","updated_at":"2025-12-23T01:46:42.887818-08:00"} -{"id":"gt-sax5l","title":"Digest: mol-deacon-patrol","description":"Patrol 160 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:10:58.988331-08:00","updated_at":"2025-12-31T16:10:58.988331-08:00","closed_at":"2025-12-31T16:10:58.988301-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-sb6m4","title":"Filter agent session molecule noise from activity feed","description":"Agent session molecules (gt-crew-gastown-joe, gt-crew-gastown-max, etc.) update frequently\nand create noisy entries like:\n\n [10:22:37] → gt-crew-gastown-joe updated · gt-crew-gastown-joe\n\nThese are not useful in the activity feed. Options:\n1. Filter them out entirely\n2. Collapse repeated updates into single entries\n3. Show them in a separate \"agent status\" section\n\nPart of epic gt-u7dxq","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2025-12-28T11:02:11.146127-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T23:36:43.08159-08:00","closed_at":"2025-12-29T23:36:43.08159-08:00","close_reason":"Implemented filter for agent session molecule updates in the activity feed TUI. Agent session updates are now filtered from the event feed while still updating the agent tree for status visibility."} -{"id":"gt-scade","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All healthy - Witness/Refinery running, no pending spawns, no convoys, no gates, no orphans, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T16:17:37.616409-08:00","updated_at":"2025-12-30T16:17:37.616409-08:00","closed_at":"2025-12-30T16:17:37.616351-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-scade","depends_on_id":"gt-eph-5hp","type":"parent-child","created_at":"2025-12-30T16:17:37.617437-08:00","created_by":"deacon"}]} -{"id":"gt-scdyn","title":"Merge: organic-mjwjck2f","description":"branch: polecat/organic-mjwjck2f\ntarget: main\nsource_issue: organic-mjwjck2f\nrig: gastown\nagent_bead: gt-gastown-polecat-organic","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:40:12.50114-08:00","created_by":"gastown/polecats/organic","updated_at":"2026-01-01T23:41:19.133358-08:00","closed_at":"2026-01-01T23:41:19.133358-08:00","close_reason":"Duplicate - work already merged as gt-a28hb"} -{"id":"gt-scgwg","title":"Digest: mol-deacon-patrol","description":"Patrol 45: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:19:20.478109-08:00","updated_at":"2026-01-01T02:19:20.478109-08:00","closed_at":"2026-01-01T02:19:20.478066-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-scjyc","title":"Merge: slit-1767073379145","description":"attached_args: Code review\n\nbranch: polecat/slit-1767073379145\ntarget: main\nsource_issue: slit-1767073379145\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/slit","created_at":"2025-12-29T21:59:32.833056-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T00:23:08.660643-08:00","closed_at":"2025-12-30T00:23:08.660643-08:00","close_reason":"Already merged to main per refinery confirmation (commit 196c3bbf)"} -{"id":"gt-sd0t7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:51:05.548064-08:00","updated_at":"2025-12-31T22:51:05.548064-08:00","closed_at":"2025-12-31T22:51:05.548021-08:00"} -{"id":"gt-sd8hr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 19: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:41:16.905769-08:00","updated_at":"2025-12-31T23:41:16.905769-08:00","closed_at":"2025-12-31T23:41:16.905729-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-se1qj","title":"Digest: mol-deacon-patrol","description":"Cycle 185: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:21:02.909366-08:00","updated_at":"2026-01-01T16:21:02.909366-08:00","closed_at":"2026-01-01T16:21:02.90933-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-se1qj","depends_on_id":"gt-eph-wy4d","type":"parent-child","created_at":"2026-01-01T16:21:02.910684-08:00","created_by":"deacon"}]} -{"id":"gt-sezjt","title":"Merge: slit-mjtj9dc8","description":"branch: polecat/slit-mjtj9dc8\ntarget: main\nsource_issue: slit-mjtj9dc8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:37:48.699134-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T23:12:37.135918-08:00","closed_at":"2025-12-30T23:12:37.135918-08:00","close_reason":"Branch already merged"} -{"id":"gt-sfpw2","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:48:31.828757-08:00","updated_at":"2026-01-01T00:48:31.828757-08:00","closed_at":"2026-01-01T00:48:31.828719-08:00","dependencies":[{"issue_id":"gt-sfpw2","depends_on_id":"gt-eph-z3lb","type":"parent-child","created_at":"2026-01-01T00:48:31.829904-08:00","created_by":"deacon"}]} -{"id":"gt-sfr83","title":"Digest: mol-deacon-patrol","description":"Patrol 5: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:14:50.542708-08:00","updated_at":"2025-12-28T08:14:50.542708-08:00","closed_at":"2025-12-28T08:14:50.542675-08:00"} -{"id":"gt-sgqf8","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:51:24.849297-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:51:24.903053-08:00","closed_at":"2026-01-05T21:51:24.903053-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:51:24-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-sgzsb","title":"BUG: Boot spawns in wrong session (gt-deacon instead of gt-deacon-boot)","description":"## Problem\n\nBoot (the Deacon's watchdog) is supposed to spawn in its own session `gt-deacon-boot` per the code:\n```go\nconst SessionName = \"gt-deacon-boot\"\n```\n\nBut when checking tmux, Boot appears to be running in the `gt-deacon` session with cwd `dogs/boot`.\n\n## Evidence\n\n```\n$ tmux capture-pane -t gt-deacon -p\n⏺ Bash(cd /Users/stevey/gt/deacon \u0026\u0026 gt feed --since 10m --plain 2\u003e/dev/null)\n Shell cwd was reset to /Users/stevey/gt/deacon/dogs/boot\n```\n\n## Impact\n\n- `gt status` shows Deacon as \"stopped\" when Boot is running in its session\n- Boot and Deacon lifecycle are confused\n- Daemon's two-layer approach (Boot triage + Deacon heartbeat) doesn't work correctly\n\n## Expected Behavior\n\n1. Boot spawns in `gt-deacon-boot` session\n2. Boot runs triage, decides if Deacon needs starting\n3. If yes, Boot starts Deacon in `gt-deacon` session\n4. Both sessions can coexist: Boot (ephemeral triage) and Deacon (persistent patrol)\n\n## Investigation Needed\n\n- Check `boot.spawnTmux()` - is it creating the right session name?\n- Check if something is reusing the Deacon session for Boot\n- Verify session naming throughout the daemon/boot code","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/toast","created_at":"2026-01-02T18:42:01.182249-08:00","created_by":"mayor","updated_at":"2026-01-02T18:56:01.865782-08:00","closed_at":"2026-01-02T18:56:01.865782-08:00","close_reason":"Fixed tmux prefix matching bug: renamed Boot session from gt-deacon-boot to gt-boot to prevent HasSession collision"} -{"id":"gt-sh53w","title":"Merge: slit-mjtj9dc8","description":"branch: polecat/slit-mjtj9dc8\ntarget: main\nsource_issue: slit-mjtj9dc8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:27:46.827128-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T23:12:42.826094-08:00","closed_at":"2025-12-30T23:12:42.826094-08:00","close_reason":"Branch already merged"} -{"id":"gt-shj28","title":"Digest: mol-deacon-patrol","description":"P15: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:59:23.72785-08:00","updated_at":"2025-12-25T19:59:23.72785-08:00","closed_at":"2025-12-25T19:59:23.72782-08:00"} -{"id":"gt-si6am","title":"Polecat spawn: CLAUDE.md template lookup path is wrong","description":"Template lookup uses rig.Path/templates/ but templates are in mayor/rig/templates/\n\nIn internal/polecat/manager.go installCLAUDETemplate():\n templatePath := filepath.Join(m.rig.Path, \"templates\", \"polecat-CLAUDE.md\")\n // Looks for: /Users/stevey/gt/gastown/templates/polecat-CLAUDE.md\n // But templates are at: /Users/stevey/gt/gastown/mayor/rig/templates/\n\nThis causes silent failure (template not found is OK) and polecats inherit the wrong CLAUDE.md from the git worktree.\n\nFix options:\n1. Copy templates to rig root during rig init\n2. Change lookup to use mayor/rig/templates/\n3. Embed templates in binary","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T14:16:07.309527-08:00","created_by":"mayor","updated_at":"2025-12-28T15:34:02.9819-08:00","closed_at":"2025-12-28T15:34:02.9819-08:00"} -{"id":"gt-si81q","title":"Session ended: gt-gastown-road-warrior","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:18:46.519442-08:00","created_by":"gastown/polecats/road-warrior","updated_at":"2026-01-05T19:44:41.877135-08:00","closed_at":"2026-01-05T19:44:41.877135-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/road","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:18:46-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-road-warrior\",\"worker\":\"road\"}"} -{"id":"gt-si8rq","title":"Ephemeral Polecat Merge Workflow: Rebase-as-Work Architecture","description":"## Vision\n\nPolecats are truly ephemeral: done at MR submission, recyclable immediately. Conflict resolution becomes tracked work in the ledger.\n\n## Current State\n\n- Polecats submit MRs and wait around\n- Refinery sends 'rebase needed' mail back to polecats\n- Polecats are blocked on MQ throughput\n- No priority scheduling in MQ\n\n## Target State\n\n### Polecat Lifecycle\n```\nPolecat spawns → Does feature work → Submits MR → DONE (recyclable)\n```\n\n### Refinery Workflow\n```\nMR enters queue\n ↓\nPriority scoring (convoy age, epic priority, retry count)\n ↓\nAttempt mechanical rebase\n ├─→ Success: Run tests, merge\n └─→ Conflicts: Create conflict-resolution task, skip MR\n```\n\n### Conflict Resolution\n- New bead: 'Resolve conflicts for MR gt-xxx'\n- Dispatched to any available polecat\n- Fresh polecat: clone, read MR/issue, resolve, force-push\n- MR re-enters queue with priority boost\n\n## Priority Objective Function\n\n```go\nscore := baseScore\nscore += convoyAgeFactor * hoursOld(convoy)\nscore += epicPriorityFactor * (5 - epicPriority) // P0=5pts, P4=1pt\nscore += retryPenalty * conflictRetryCount // Prevent thrashing\n```\n\nFactors tunable. Refinery processes highest-score first.\n\n## Key Principles\n\n- **ZFC**: Refinery automates automatable, agents judge judgeable\n- **Nondeterministic Idempotence**: Different polecat, same outcome\n- **HOP-aligned**: Conflict resolution is tracked work with skill attribution\n- **Convoy pressure**: Older convoys get priority, preventing starvation\n\n## Success Criteria\n\n- [ ] Polecats recyclable immediately after MR submit\n- [ ] Mechanical rebases handled by refinery (no dispatch)\n- [ ] Conflicts create dispatchable tasks\n- [ ] MQ priority based on convoy/epic/retry\n- [ ] Documentation updated\n- [ ] Formulas updated (refinery, polecat)","status":"open","priority":0,"issue_type":"epic","assignee":"mayor","created_at":"2026-01-01T23:54:25.238139-08:00","created_by":"mayor","updated_at":"2026-01-04T20:23:11.145731-08:00"} -{"id":"gt-si8rq.1","title":"Design: MQ Priority Objective Function","description":"Define the priority scoring function for merge queue ordering.\n\n## Inputs\n- Convoy creation time (age)\n- Epic/issue priority (P0-P4)\n- Conflict retry count\n- MR submission time\n\n## Output\n- Numeric score (higher = process first)\n\n## Considerations\n- Prevent convoy starvation (old convoys escalate)\n- Respect epic priority (P0 bugs \u003e P4 backlog)\n- Penalize thrashing (multiple conflict cycles)\n- Deterministic (same inputs = same score)\n\n## Deliverable\n- Go function: `func ScoreMR(mr MergeRequest) float64`\n- Unit tests with edge cases\n- Documentation of factor weights","status":"closed","priority":0,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-01T23:54:37.025039-08:00","created_by":"mayor","updated_at":"2026-01-02T01:26:09.304124-08:00","closed_at":"2026-01-02T01:26:09.304124-08:00","close_reason":"Implemented ScoreMR function with tests and documentation","dependencies":[{"issue_id":"gt-si8rq.1","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:54:37.026958-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.10","title":"Testing: End-to-end rebase workflow validation","description":"Comprehensive testing of the new rebase-as-work workflow.\n\n## Test Scenarios\n\n### Happy Path\n1. Single MR, clean rebase → refinery merges\n2. Multiple MRs, no conflicts → priority ordering works\n\n### Conflict Handling\n3. MR conflicts → conflict task created\n4. Conflict task dispatched → polecat resolves\n5. Resolved MR re-enters queue with priority boost\n6. Multiple conflict cycles → retry_count tracked\n\n### Priority Scoring\n7. Older convoy MRs prioritized over newer\n8. P1 epic MRs prioritized over P3\n9. High retry_count gets appropriate adjustment\n\n### Edge Cases\n10. MR conflicts again after resolution\n11. Polecat recycled before merge\n12. Convoy completed with pending MRs\n\n## Implementation\n- Unit tests for ScoreMR function\n- Integration tests for refinery flow\n- Scenario tests with actual polecats (manual/semi-auto)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T23:56:03.505309-08:00","created_by":"mayor","updated_at":"2026-01-01T23:56:03.505309-08:00","dependencies":[{"issue_id":"gt-si8rq.10","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:56:03.508854-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.10","depends_on_id":"gt-si8rq.5","type":"blocks","created_at":"2026-01-01T23:56:20.199526-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.10","depends_on_id":"gt-si8rq.6","type":"blocks","created_at":"2026-01-01T23:56:20.249036-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.10","depends_on_id":"gt-si8rq.9","type":"blocks","created_at":"2026-01-01T23:56:20.293223-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.2","title":"Refinery: Implement mechanical rebase in-place","description":"Update refinery to handle mechanical rebases without dispatching.\n\n## Current Behavior\n- Refinery detects rebase needed\n- Sends mail to polecat asking for rebase\n- Waits for polecat response\n\n## New Behavior\n- Refinery attempts `git rebase origin/main`\n- If success (no conflicts): proceed to tests/merge\n- If conflicts: abort, create conflict-resolution task\n\n## Implementation\n1. Update mol-refinery-patrol.formula.toml\n2. Add rebase step between 'fetch' and 'test'\n3. Handle conflict detection (exit code, conflict markers)\n4. On conflict: `git rebase --abort`, create task, skip MR\n\n## Tests\n- Mechanical rebase succeeds\n- Conflict detected and aborted\n- Conflict task created with correct metadata","status":"closed","priority":0,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T23:55:08.4549-08:00","created_by":"mayor","updated_at":"2026-01-02T01:25:11.450699-08:00","closed_at":"2026-01-02T01:25:11.450699-08:00","close_reason":"Implemented in mol-refinery-patrol v4: mechanical rebase with conflict detection and task creation","dependencies":[{"issue_id":"gt-si8rq.2","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:08.456981-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.3","title":"Refinery: Conflict-resolution task creation","description":"When rebase fails, create a dispatchable task for conflict resolution.\n\n## Task Format\n```\nTitle: Resolve merge conflicts: \u003coriginal-issue-title\u003e\nType: task\nPriority: inherit from original + boost\nParent: original MR bead\nDescription:\n - Original MR: gt-xxx\n - Branch: polecat/foo-branch\n - Conflict with: main@\u003csha\u003e\n - Original issue: gt-yyy\n - Instructions: Resolve conflicts, force-push, close this task\n```\n\n## Metadata\n- Link to original MR\n- Link to original issue\n- Conflict SHA (what main was when conflict occurred)\n- Retry count (for priority scoring)\n\n## Dispatch\n- Task goes to bd ready\n- Witness can dispatch to available polecat\n- Or: Refinery directly dispatches if polecats available","status":"closed","priority":0,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-01T23:55:10.63866-08:00","created_by":"mayor","updated_at":"2026-01-02T01:39:49.867745-08:00","closed_at":"2026-01-02T01:39:49.867745-08:00","close_reason":"Implemented conflict-resolution task creation in Engineer.handleFailureFromQueue","dependencies":[{"issue_id":"gt-si8rq.3","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:10.640585-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.3","depends_on_id":"gt-si8rq.2","type":"blocks","created_at":"2026-01-01T23:56:20.063625-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.4","title":"Polecat: Clean exit after MR submission","description":"Update polecat workflow to be truly ephemeral after MR submission.\n\n## Current Behavior\n- Polecat submits MR\n- Polecat waits for merge or rebase request\n- Session stays alive, sandbox persists\n\n## New Behavior\n- Polecat submits MR\n- Polecat closes its work bead (status=in_review or similar)\n- Polecat signals 'recyclable' to Witness\n- Sandbox can be cleaned up after branch is pushed\n\n## Implementation\n1. Update mol-polecat-work.formula.toml\n2. Add explicit 'submit and exit' step\n3. Ensure branch is pushed before sandbox cleanup\n4. Signal Witness that polecat is recyclable\n\n## Considerations\n- Sandbox cleanup can be deferred (worktrees are cheap)\n- Or: Witness runs cleanup patrol for idle polecats","notes":"Implemented: Updated mol-polecat-work.formula.toml (v4) for ephemeral polecat model. Polecats now submit via gt done and become recyclable. No longer wait for Witness termination or close their own issues.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:55:11.810337-08:00","created_by":"mayor","updated_at":"2026-01-02T17:47:34.1061-08:00","closed_at":"2026-01-02T17:47:34.1061-08:00","close_reason":"Implemented: Updated mol-polecat-work.formula.toml (v4) for ephemeral polecat model","dependencies":[{"issue_id":"gt-si8rq.4","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:11.812982-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.5","title":"Polecat: Conflict resolution workflow","description":"New workflow for polecats handling conflict-resolution tasks.\n\n## Task Recognition\n- Task title starts with \"Resolve merge conflicts:\"\n- Task has metadata: original MR, branch, conflict SHA\n\n## Workflow (UPDATED - uses merge-slot)\n1. Read task metadata\n2. **Acquire merge slot** (gt-4u49x) - wait if held\n3. Fetch the branch: `git fetch origin \u003cbranch\u003e`\n4. Checkout: `git checkout -b temp-resolve origin/\u003cbranch\u003e`\n5. Attempt rebase: `git rebase origin/main`\n6. Resolve conflicts (Claude judgment)\n7. Run tests\n8. **Push directly to main** (not force-push to branch)\n9. Close original MR bead (not just conflict task)\n10. **Release merge slot**\n11. Close conflict-resolution task\n\n## Key Changes from Original\n- Acquire/release merge slot (serialization)\n- Push to main directly (skip queue re-entry)\n- Close original MR bead (proper attribution)\n\n## Considerations\n- May need to read original issue for context\n- May need to read MR description for intent\n- If resolution is complex, can ask for human help (escalate)\n\n## Dependencies\n- gt-4u49x: Merge-slot gate (serialization)\n- gt-hibbj: Non-blocking refinery delegation","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T23:55:12.948223-08:00","created_by":"mayor","updated_at":"2026-01-02T18:55:30.838307-08:00","closed_at":"2026-01-02T18:55:30.838307-08:00","close_reason":"Implemented mol-polecat-conflict-resolve formula with 9-step workflow","dependencies":[{"issue_id":"gt-si8rq.5","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:12.954302-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.5","depends_on_id":"gt-si8rq.3","type":"blocks","created_at":"2026-01-01T23:56:20.107173-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.6","title":"gt mq: Priority-ordered queue display and processing","description":"Update MQ commands and refinery to process by priority score.\n\n## Changes to gt mq list\n- Add 'SCORE' column\n- Sort by score descending\n- Show convoy info if tracked\n\n## Changes to gt mq next\n- Return highest-score MR (not oldest)\n- Or: `gt mq next --strategy=priority` (keep fifo as option)\n\n## Changes to Refinery\n- Query MQ with priority ordering\n- Process highest-score first\n\n## Implementation\n- Add ScoreMR function (from gt-si8rq.1)\n- Update mq.go query to include score calculation\n- Update refinery formula to use priority ordering\n\n## Output Example\n```\nID SCORE PRI CONVOY BRANCH AGE\ngt-abc 87.5 P1 hq-cv-xyz polecat/foo-123 2h\ngt-def 72.3 P2 hq-cv-abc polecat/bar-456 45m\ngt-ghi 45.0 P3 (none) polecat/baz-789 10m\n```","status":"closed","priority":0,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T23:55:45.321067-08:00","created_by":"mayor","updated_at":"2026-01-02T17:16:36.023165-08:00","closed_at":"2026-01-02T17:16:36.023165-08:00","close_reason":"Implemented priority-ordered queue display and processing with SCORE column, gt mq next command, and Refinery priority ordering","dependencies":[{"issue_id":"gt-si8rq.6","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:45.324317-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.6","depends_on_id":"gt-si8rq.7","type":"blocks","created_at":"2026-01-01T23:56:20.019453-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.7","title":"MR bead: Add retry_count and conflict metadata","description":"Extend MR beads to track conflict resolution attempts.\n\n## New Fields\n- `retry_count`: Number of conflict-resolution cycles\n- `last_conflict_sha`: SHA of main when conflict occurred\n- `conflict_task_id`: Link to conflict-resolution task (if any)\n\n## Usage\n- Refinery increments retry_count on each conflict\n- Priority function uses retry_count as input\n- Conflict-resolution task links back to MR\n\n## Implementation\n- Update MR creation to include fields\n- Update refinery to increment on conflict\n- Update priority function to read retry_count","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T23:55:46.941724-08:00","created_by":"mayor","updated_at":"2026-01-02T16:44:47.43956-08:00","closed_at":"2026-01-02T16:44:47.43956-08:00","close_reason":"Added retry_count, last_conflict_sha, conflict_task_id fields to MR bead creation","dependencies":[{"issue_id":"gt-si8rq.7","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:46.945174-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.7","depends_on_id":"gt-si8rq.1","type":"blocks","created_at":"2026-01-01T23:56:19.974616-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.8","title":"Documentation: Ephemeral Polecat Merge Workflow","description":"Document the new rebase-as-work architecture.\n\n## Documents to Update\n\n### docs/understanding-gas-town.md\n- Polecat lifecycle (truly ephemeral)\n- MR submission as exit point\n\n### docs/refinery-workflow.md (new or update)\n- Priority scoring\n- Mechanical rebase handling\n- Conflict-resolution task creation\n\n### PRIMING.md\n- Update polecat section\n- Add note about rebase-as-work pattern\n\n## Key Concepts to Document\n- 'Polecat done at MR submit'\n- 'Conflicts are new work'\n- 'Convoy age creates pressure'\n- 'Priority function is deterministic'","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-01T23:55:48.395768-08:00","created_by":"mayor","updated_at":"2026-01-01T23:55:48.395768-08:00","dependencies":[{"issue_id":"gt-si8rq.8","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:48.399587-08:00","created_by":"mayor"}]} -{"id":"gt-si8rq.9","title":"Witness: Update polecat monitoring for ephemeral model","description":"Update Witness to handle truly ephemeral polecats.\n\n## Current Behavior\n- Witness monitors polecats until MR merged\n- 'Rebase needed' mail sent to polecats\n\n## New Behavior\n- Witness marks polecat as 'recyclable' after MR submit\n- Witness can dispatch conflict-resolution tasks\n- Witness doesn't wait for merge to recycle polecat\n\n## Changes to mol-witness-patrol.formula.toml\n- Detect 'MR submitted' state\n- Mark polecat recyclable\n- Handle conflict-resolution dispatch\n\n## Polecat States\n```\nspawning → working → mr_submitted → recyclable → recycled\n```\n\n## Considerations\n- Don't recycle sandbox until branch pushed\n- Or: Keep sandbox, just recycle session","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-01T23:55:49.563919-08:00","created_by":"mayor","updated_at":"2026-01-03T15:46:23.840761-08:00","closed_at":"2026-01-03T15:46:23.840761-08:00","close_reason":"PR #81 created for ephemeral polecat model","dependencies":[{"issue_id":"gt-si8rq.9","depends_on_id":"gt-si8rq","type":"parent-child","created_at":"2026-01-01T23:55:49.566383-08:00","created_by":"mayor"},{"issue_id":"gt-si8rq.9","depends_on_id":"gt-si8rq.4","type":"blocks","created_at":"2026-01-01T23:56:20.156313-08:00","created_by":"mayor"}]} -{"id":"gt-sifj5","title":"gt feed --follow: Town-level activity stream","description":"Town-native command for aggregated activity feed.\n\nWraps bd activity --town with Gas Town conveniences:\n- gt feed --follow # Stream all rig activity\n- gt feed --rig gastown # Filter to specific rig\n- gt feed --convoy hq-xxx # Filter to convoy's tracked issues\n\nEssential for Mayor/Deacon visibility into cross-rig work.\n\nDepends on: bd-dx6e (bd activity --town)\nRelated: hq-7h8jx (Convoy System epic in town beads)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-29T18:47:30.836147-08:00","created_by":"mayor","updated_at":"2025-12-30T00:18:49.42479-08:00","closed_at":"2025-12-30T00:18:49.42479-08:00","close_reason":"Implemented --town flag and --convoy placeholder for gt feed","dependencies":[{"issue_id":"gt-sifj5","depends_on_id":"external:beads:bd-dx6e","type":"blocks","created_at":"2025-12-29T18:47:47.678908-08:00","created_by":"daemon"}]} -{"id":"gt-sihk0","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:30:29.477555-08:00","updated_at":"2025-12-31T23:30:29.477555-08:00","closed_at":"2025-12-31T23:30:29.47752-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-sis5f","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T14:13:02.043278-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.205532-08:00","closed_at":"2026-01-04T16:41:26.205532-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T14:13:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-sk0if","title":"Digest: mol-deacon-patrol","description":"Patrol 10: 17 sessions","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:10:42.98849-08:00","updated_at":"2026-01-01T09:10:42.98849-08:00","closed_at":"2026-01-01T09:10:42.988452-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-sk97l","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T11:00:46.404386-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.657335-08:00","closed_at":"2026-01-05T19:44:18.657335-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T11:00:46-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-skd0g","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:15:12.62982-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:44:18.445914-08:00","closed_at":"2026-01-05T19:44:18.445914-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:15:07-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-ski36","title":"Session ended: gt-gastown-interceptor","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:15:16.877608-08:00","created_by":"gastown/polecats/interceptor","updated_at":"2026-01-05T19:44:41.899143-08:00","closed_at":"2026-01-05T19:44:41.899143-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/polecats/interceptor","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:15:16-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-interceptor\",\"worker\":\"interceptor\"}"} -{"id":"gt-skjw3","title":"Digest: mol-deacon-patrol","description":"Patrol 33: all quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:59:56.203912-08:00","updated_at":"2025-12-31T13:59:56.203912-08:00","closed_at":"2025-12-31T13:59:56.203874-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-skuhj","title":"Digest: mol-deacon-patrol","description":"Patrol 9: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:27:57.229202-08:00","updated_at":"2026-01-01T04:27:57.229202-08:00","closed_at":"2026-01-01T04:27:57.229172-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-smm70","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:08:57.559945-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.620133-08:00","closed_at":"2026-01-04T16:40:22.620133-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:08:57-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-sn610","title":"Refactor AgentRegistry global state to explicit passing","description":"The agents.go uses a global mutable `globalRegistry` with lazy init pattern. Issues:\n- Tests must reset it manually (`globalRegistry = nil`)\n- No mutex for concurrent access\n- Unclear initialization lifecycle\n\nConsider passing registry explicitly or using sync.Once pattern.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T13:05:25.636206-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T13:08:51.70837-08:00","closed_at":"2026-01-04T13:08:51.70837-08:00","close_reason":"Added mutex protection, sync-safe initialization, path caching, and ResetRegistryForTesting() helper"} -{"id":"gt-sne83","title":"Digest: mol-deacon-patrol","description":"Cycle 10: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:18:43.437161-08:00","updated_at":"2025-12-28T13:18:43.437161-08:00","closed_at":"2025-12-28T13:18:43.437132-08:00"} -{"id":"gt-snf7b","title":"Digest: mol-deacon-patrol","description":"Patrol #11","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:22:48.95747-08:00","updated_at":"2025-12-31T06:22:48.95747-08:00","closed_at":"2025-12-31T06:22:48.957437-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-soy44","title":"Merge: buzzard-mk0vnwut","description":"branch: polecat/buzzard-mk0vnwut\ntarget: main\nsource_issue: buzzard-mk0vnwut\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T00:10:39.411368-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T19:20:46.524936-08:00","closed_at":"2026-01-05T19:20:46.524936-08:00","close_reason":"Already merged to main at c24c3ba8"} -{"id":"gt-sp1tv","title":"Merge: rictus-1767081110235","description":"branch: polecat/rictus-1767081110235\ntarget: main\nsource_issue: rictus-1767081110235\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:56:10.302919-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T01:01:04.345245-08:00","closed_at":"2025-12-30T01:01:04.345245-08:00","close_reason":"Already merged to main"} -{"id":"gt-sq59b","title":"Digest: mol-deacon-patrol","description":"Patrol 9: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:06:31.648174-08:00","updated_at":"2025-12-31T18:06:31.648174-08:00","closed_at":"2025-12-31T18:06:31.648139-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-srm3y","title":"Exponential backoff for idle patrol agents","description":"## Problem\n\nPatrol agents (Refinery, Witness, Deacon) currently have no backoff when their queue is empty. They either:\n- Loop immediately (wasting cycles)\n- Exit and wait for 10-minute daemon respawn (too slow to respond)\n\n## Solution: Feed-Driven Backoff\n\n### The Pattern (from PRIMING.md)\n\n\u003e \"Backoff isn't about polling less - it's about **waiting for signals with a timeout**.\"\n\nAgents subscribe to `bd activity --follow` and wake on any beads mutation. The timeout increases exponentially during idle periods.\n\n### Data Flow\n\n```\nbd/gt mutations → .events.jsonl → feed curator → .feed.jsonl\n ↓\n patrol agent: gt mol await-signal --backoff-*\n ↓\n signal → wake, reset idle_cycles\n timeout → increment idle_cycles, sleep longer\n```\n\n### Backoff Formula\n\n```\ntimeout = min(base × multiplier^idle_cycles, max)\n```\n\n| Idle Cycles | Timeout |\n|-------------|---------|\n| 0 | 30s |\n| 1 | 1m |\n| 2 | 2m |\n| 3 | 4m |\n| 4+ | 5m (capped) |\n\n### Agent State Storage\n\nOperational state stored as labels on agent beads (labels-as-cache pattern):\n- `idle:3` - consecutive idle patrol cycles\n- `backoff:2m` - current backoff interval (derived)\n- `last_activity:2025-12-31T10:00:00Z` - timestamp\n\n### Implementation Layers\n\n**Layer 1: gt agent state command**\n```bash\ngt agent state \u003cagent-bead\u003e # Get labels\ngt agent state \u003cagent-bead\u003e --set idle=0 # Set label\ngt agent state \u003cagent-bead\u003e --incr idle # Increment\n```\n\n**Layer 2: Fix await-signal iteration tracking**\n- Read `idle:N` label from agent bead\n- Calculate effective timeout using BackoffConfig\n- On timeout: increment label, return \"timeout\"\n- On signal: return \"signal\" (agent resets)\n\n**Layer 3: Patrol formula integration**\nUpdate burn-or-loop step:\n```bash\n# If work found\ngt agent state $AGENT_BEAD --set idle=0\n\n# If no work\ngt mol await-signal --agent-bead $AGENT_BEAD --backoff-base 30s --backoff-mult 2 --backoff-max 5m\n\n# After 10 consecutive max-timeout cycles, exit for fresh session\n```\n\n**Layer 4: Feed signal sources**\nEnsure these emit events:\n- gt sling → TypeSling\n- bd create/update/close → BeadMutation\n- gt mail send → TypeMail\n\n### ZFC Compliance\n\n| Component | Role | ZFC |\n|-----------|------|-----|\n| Feed curator | Aggregates events | ✅ Transport |\n| await-signal | Waits with timeout | ✅ Transport |\n| Agent bead labels | Stores idle_cycles | ✅ Agent-written |\n| Backoff decision | Agent decides | ✅ Agent decides |\n\nGo code provides mechanics. **Agent decides** parameters, reset, and exit.\n\n### Existing Infrastructure\n\n- Feed Curator: internal/feed/curator.go ✅\n- BackoffConfig: internal/beads/molecule.go ✅\n- await-signal cmd: internal/cmd/molecule_await_signal.go (needs fix)\n- Agent Beads: internal/beads/beads.go ✅\n- Labels pattern: docs/operational-state.md ✅\n\n### Exit Strategy\n\nAfter N consecutive max-interval cycles (e.g., 10 × 5m = 50 minutes idle):\n- Agent exits cleanly\n- Daemon respawns fresh session\n- Fresh session starts with idle:0","status":"closed","priority":2,"issue_type":"epic","assignee":"gastown/polecats/nux","created_at":"2025-12-31T01:54:42.14576-08:00","created_by":"gastown/refinery","updated_at":"2026-01-01T19:22:03.081791-08:00","closed_at":"2026-01-01T19:22:03.081791-08:00","close_reason":"All subtasks complete: gt agent state command, patrol formula updates, feed signal verification"} -{"id":"gt-srm3y.1","title":"Implement gt agent state command for label-based state","description":"Add gt agent state command:\n- gt agent state \u003cagent-bead\u003e - Get all labels\n- gt agent state \u003cagent-bead\u003e --set key=value - Set label \n- gt agent state \u003cagent-bead\u003e --incr key - Increment numeric label\n- gt agent state \u003cagent-bead\u003e --del key - Delete label\n\nLabels stored on agent beads enable operational state (idle:N, backoff:2m, etc).","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:41:11.862869-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T18:49:52.703076-08:00","closed_at":"2026-01-01T18:49:52.703076-08:00","close_reason":"Implemented gt agent state command with get/set/incr/del operations","dependencies":[{"issue_id":"gt-srm3y.1","depends_on_id":"gt-srm3y","type":"parent-child","created_at":"2026-01-01T18:41:11.866077-08:00","created_by":"gastown/polecats/nux"}]} -{"id":"gt-srm3y.2","title":"Update patrol formulas to use await-signal backoff","description":"Layer 3: Update patrol formulas to use new gt mol await-signal with --agent-bead flag.\n\nUpdate burn-or-loop steps in patrol formulas:\n- mol-witness-patrol.formula.toml\n- mol-refinery-patrol.formula.toml\n- mol-deacon-patrol.formula.toml\n\nThe step should:\n1. Reset idle counter on work found: gt agent state $AGENT_BEAD --set idle=0\n2. Wait with backoff when no work: gt mol await-signal --agent-bead $AGENT_BEAD --backoff-base 30s --backoff-mult 2 --backoff-max 5m\n3. Exit after 10 consecutive max-timeout cycles for fresh session","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-01T18:49:38.877847-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T19:05:19.443278-08:00","closed_at":"2026-01-01T19:05:19.443278-08:00","close_reason":"Updated all 3 patrol formulas (witness, refinery, deacon) with exponential backoff pattern. Changes in mayor/rig/.beads/formulas/ - need sync to main.","dependencies":[{"issue_id":"gt-srm3y.2","depends_on_id":"gt-srm3y","type":"parent-child","created_at":"2026-01-01T18:49:38.879848-08:00","created_by":"gastown/polecats/nux"}]} -{"id":"gt-srm3y.3","title":"Verify feed signal sources emit events","description":"Layer 4: Verify that all required sources emit events to the activity feed.\n\nSources that should emit events:\n- gt sling → TypeSling event\n- bd create/update/close → BeadMutation event \n- gt mail send → TypeMail event\n\nCheck internal/events package and verify event emission in each command.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-01T18:49:46.275584-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T19:03:48.339025-08:00","closed_at":"2026-01-01T19:03:48.339025-08:00","close_reason":"All feed signal sources verified: gt sling emits TypeSling (sling.go:407,799), bd create/update/close emits MutationCreate/Update/Status (server_issues_epics.go:426,667-680,752), gt mail send emits TypeMail (mail.go:407)","dependencies":[{"issue_id":"gt-srm3y.3","depends_on_id":"gt-srm3y","type":"parent-child","created_at":"2026-01-01T18:49:46.277395-08:00","created_by":"gastown/polecats/nux"}]} -{"id":"gt-srun8","title":"Digest: mol-deacon-patrol","description":"Patrol 130: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:35:13.5635-08:00","updated_at":"2026-01-01T14:35:13.5635-08:00","closed_at":"2026-01-01T14:35:13.563461-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ssrho","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:51:36.039273-08:00","updated_at":"2025-12-30T15:51:36.039273-08:00","closed_at":"2025-12-30T15:51:36.039236-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ssswt","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T21:15:41.593648-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:25.995913-08:00","closed_at":"2026-01-04T16:41:25.995913-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T21:15:41-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-sstg","title":"Deacon patrol molecules stored in wrong beads location","description":"outputDeaconPatrolContext in prime.go hardcodes 'gastown/mayor/rig' (line 691) to find patrol molecules. But Deacon is a town-level role, not a rig role. Deacon molecules should be in town root beads (~/gt/.beads/) not rig beads. This also affects gt mol status which uses findLocalBeadsDir() - from ~/gt/deacon/ it won't find the right beads location.","status":"hooked","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-23T13:30:18.021287-08:00","updated_at":"2025-12-29T23:51:48.238549-08:00"} -{"id":"gt-suuf","title":"check-refinery","description":"Ensure the refinery is alive and processing merge requests.\n\nNeeds: inbox-check","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:23:42.026349-08:00","updated_at":"2025-12-23T16:23:42.026349-08:00","dependencies":[{"issue_id":"gt-suuf","depends_on_id":"gt-87jz","type":"parent-child","created_at":"2025-12-23T16:23:42.033707-08:00","created_by":"stevey"}]} -{"id":"gt-svdsy","title":"Atomic gt done: all-or-nothing work submission","description":"gt done performs multiple operations that can partially fail.\n\n## Current Flow (non-atomic)\n1. Create MR bead ← can fail\n2. Send POLECAT_DONE mail ← can fail \n3. Update agent bead state ← can fail\n4. Report cleanup status ← can fail\n\nIf session dies mid-execution, state is inconsistent.\n\n## Fix Options\n\n### Option A: Retry on restart\n- Write intent file before starting\n- On polecat restart, check for incomplete gt done\n- Resume/retry from where it left off\n\n### Option B: Single-write submission\n- Create a single 'submission' bead that contains all info\n- Witness unpacks it into MR bead + cleanup wisp\n- Polecat only needs one successful write\n\n### Option C: Idempotent operations\n- Each step checks if already done before doing\n- Safe to re-run gt done multiple times\n\nRecommend Option C for simplicity.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T19:07:39.41034-08:00","created_by":"mayor","updated_at":"2025-12-30T22:12:41.551576-08:00","closed_at":"2025-12-30T22:12:41.551576-08:00","close_reason":"Implemented Option C (idempotent operations) for MR bead creation. Added FindMRForBranch to check for existing MR before creating."} -{"id":"gt-svmj8","title":"Merge: cheedo-1767088553821","description":"branch: polecat/cheedo-1767088553821\ntarget: main\nsource_issue: cheedo-1767088553821\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:37:17.026847-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2025-12-30T18:23:22.23117-08:00","closed_at":"2025-12-30T18:23:22.23117-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-sw5rr","title":"Digest: mol-deacon-patrol","description":"Patrol 124: All healthy, 2 new polecats","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T21:55:30.538643-08:00","updated_at":"2025-12-30T21:55:30.538643-08:00","closed_at":"2025-12-30T21:55:30.538603-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-swqfx","title":"Digest: mol-deacon-patrol","description":"Patrol 17","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:57:10.122945-08:00","updated_at":"2025-12-26T14:57:10.122945-08:00","closed_at":"2025-12-26T14:57:10.122884-08:00"} -{"id":"gt-sx6h0","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 76: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:24:46.197381-08:00","updated_at":"2026-01-01T13:24:46.197381-08:00","closed_at":"2026-01-01T13:24:46.197327-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-sxa64","title":"ZFC #5: Move merge/conflict decisions from Go to Refinery agent","description":"**ZFC Violation:** internal/refinery/manager.go:389-517\n\nGo code currently makes engineering decisions in ProcessMR():\n- Detect conflicts via string matching\n- Decide to abort merge\n- Decide to roll back on test failure\n- Decide retry strategy\n\n**Current anti-pattern:**\n```go\nif strings.Contains(errStr, \"CONFLICT\") {\n result.Conflict = true\n _ = m.gitRun(\"merge\", \"--abort\")\n // Go decides what to do\n}\n```\n\n**ZFC-compliant solution:**\nRefinery AGENT runs the merge loop:\n- Agent attempts merge\n- Agent detects conflict and decides: retry, notify polecat, escalate\n- Agent runs tests and decides: proceed, rollback, retry\n- Go provides git operations, agent makes decisions\n\n**Relates to:** Day 3.4 (Refinery processes MERGE_READY mail) but needs explicit agent decision-making\n\nReference: ~/gt/docs/zfc-violations-audit.md #5","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-27T21:32:23.552661-08:00","created_by":"mayor","updated_at":"2025-12-30T01:53:59.518214-08:00","closed_at":"2025-12-30T01:53:59.518214-08:00","close_reason":"Implemented ZFC #5: ProcessMR deprecated, agent runs git commands directly and makes all merge/conflict decisions. Role template updated with ZFC compliance section.","dependencies":[{"issue_id":"gt-sxa64","depends_on_id":"gt-7uhts","type":"blocks","created_at":"2025-12-27T21:32:40.334932-08:00","created_by":"daemon"}]} -{"id":"gt-sxl3t","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:52:25.979577-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:52:26.034035-08:00","closed_at":"2026-01-05T19:52:26.034035-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:52:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-sxr05","title":"Merge: dementus-1767073385126","description":"attached_args: Code review this merge request\n\nbranch: polecat/dementus-1767073385126\ntarget: main\nsource_issue: dementus-1767073385126\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/keeper","created_at":"2025-12-29T21:58:08.802876-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-29T22:02:36.324886-08:00","closed_at":"2025-12-29T22:02:36.324886-08:00","close_reason":"REJECTED: The swarm fix (gt-qd9p0) is already on main (commit 10e79789). This branch is stale and would revert important changes if merged (hookIssue support from 81b250ee, overseer validation from 32a623f8). No merge needed - work already complete."} -{"id":"gt-sz1vj","title":"Digest: mol-deacon-patrol","description":"Patrol 241 complete: 3 witnesses, 3 refineries healthy; 6 polecats active; 1 dog idle; no orphans; no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:13:30.544224-08:00","updated_at":"2026-01-01T17:13:30.544224-08:00","closed_at":"2026-01-01T17:13:30.544192-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-t072g","title":"Merge: nux-1767084010093","description":"branch: polecat/nux-1767084010093\ntarget: main\nsource_issue: nux-1767084010093\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:50:06.175461-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T01:01:04.201113-08:00","closed_at":"2025-12-30T01:01:04.201113-08:00","close_reason":"Already merged to main"} -{"id":"gt-t1kso","title":"Add gt mail claim command for queue message claiming","description":"Add claim subcommand to internal/cmd/mail.go.\n\nSYNTAX:\ngt mail claim \u003cqueue-name\u003e\n\nBEHAVIOR:\n1. List unclaimed messages in queue (claimed_by empty)\n2. Pick oldest unclaimed message\n3. Set claimed_by to caller identity\n4. Set claimed_at to now\n5. Print claimed message details\n\nELIGIBILITY CHECK:\n- Load queue config from messaging.json\n- Check if caller matches any pattern in workers list\n- Reject if not eligible\n\nFILE: internal/cmd/mail.go\nADD: claimCmd as subcommand of mailCmd\n\nTESTS: Add TestMailClaim in mail_test.go or cmd_test.go","status":"closed","priority":2,"issue_type":"task","assignee":"mayor","created_at":"2025-12-30T18:15:38.502227-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T17:33:39.33265-08:00","closed_at":"2026-01-01T17:33:39.33265-08:00","close_reason":"Implemented gt mail claim command with eligibility checking and tests","dependencies":[{"issue_id":"gt-t1kso","depends_on_id":"gt-y80vv","type":"blocks","created_at":"2025-12-30T18:15:48.245837-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-t26nn","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:46:31.578808-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:26.143115-08:00","closed_at":"2026-01-04T16:41:26.143115-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:46:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-t3e07","title":"Beads witness sends HEALTH_OK to mayor instead of deacon","description":"The beads/witness is responding to deacon health checks by sending to 'mayor/deacon' or 'mayor/' instead of 'deacon/'.\n\nCurrent behavior:\ngt mail send mayor/deacon -s \"HEALTH_OK\" ...\n\nExpected behavior:\ngt mail send deacon/ -s \"HEALTH_OK\" ...\n\nThe gastown witness was fixed and now correctly sends to deacon/. The beads witness needs the same fix.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-01T10:46:06.515404-08:00","created_by":"mayor","updated_at":"2026-01-01T10:54:12.570637-08:00","closed_at":"2026-01-01T10:54:12.570637-08:00","close_reason":"Added Health Check Protocol section to witness template with correct deacon/ address"} -{"id":"gt-t4jvj","title":"Session ended: gt-gastown-goose","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:41:31.796927-08:00","created_by":"gastown/polecats/goose","updated_at":"2026-01-04T16:40:22.875273-08:00","closed_at":"2026-01-04T16:40:22.875273-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/goose","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:41:31-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-goose\",\"worker\":\"goose\"}"} -{"id":"gt-t58zf","title":"Digest: mol-deacon-patrol","description":"Patrol 16: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:09:51.900526-08:00","updated_at":"2026-01-01T23:09:51.900526-08:00","closed_at":"2026-01-01T23:09:51.900495-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-t5ga3","title":"Add INSTALLING.md with full setup guide","description":"README Quick Start is too brief. Create docs/INSTALLING.md with:\n1. All prerequisites with install commands\n2. Step-by-step install for macOS and Linux\n3. Verification steps (gt doctor, gt status)\n4. Troubleshooting common issues\n5. Minimal mode vs full-stack mode setup","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2026-01-01T11:20:09.487136-08:00","created_by":"mayor","updated_at":"2026-01-01T11:25:07.376683-08:00","closed_at":"2026-01-01T11:25:07.376683-08:00","close_reason":"Created docs/INSTALLING.md with full setup guide"} -{"id":"gt-t5i07","title":"Refinery Patrol","description":"Merge queue processor patrol loop with verification gates.","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-29T14:38:03.516004-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:38:03.516004-08:00"} -{"id":"gt-t5lff","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:46:14.944851-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:13.568678-08:00","closed_at":"2026-01-04T16:40:13.568678-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:46:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-t5mz","title":"Hardcoded session ID prefixes and paths","description":"Multiple hardcoded values throughout code:\n- internal/mail/router.go: 'gt-mayor', 'gt-' session prefixes\n- internal/lock/lock.go: '.runtime', 'agent.lock' paths\n- Session ID generation uses string literals\n\nShould move to:\n- constants package for prefixes\n- config for customizable paths\n\nLow priority but improves maintainability.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-24T12:51:20.962108-08:00","updated_at":"2025-12-24T12:51:20.962108-08:00","dependencies":[{"issue_id":"gt-t5mz","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T12:52:08.156758-08:00","created_by":"daemon"}]} -{"id":"gt-t6muy","title":"Design: Polecat lifecycle and patrol coordination","description":"## Context\n\nThis design captures thinking from a deep session about the Gas Town propulsion system - how Deacon, Witness, Refinery, and Polecats coordinate to move work smoothly through the system.\n\n## Core Insight: Session-Per-Step Model\n\nPolecats do NOT complete complex molecules end-to-end. Instead:\n- One polecat SESSION per molecule STEP\n- Same sandbox (branch/worktree) persists across sessions\n- Each step: spawn → work → close bead → recycle session\n- Final step: spawn → work → close bead → signal complete → merge → nuke sandbox\n\n## Two Cleanup Stages\n\n| Stage | Trigger | Kills | Survives |\n|-------|---------|-------|----------|\n| Step cleanup | Step bead closed | Session | Branch, worktree, molecule |\n| Molecule cleanup | Merged | Session, branch, worktree | Digest |\n\n## Per-Rig Polecat Channel\n\nNeed a mailing list/queue per rig for session-lifecycle requests:\n- \"Recycle me\" (from polecat)\n- \"Recycle worker X\" (from witness/mayor)\n- \"Spawn for step Y\" (from anyone)\n\nFirst-come-first-served by patrolling agents. Anyone on patrol (Witness, Refinery, Crew, Mayor) can service requests.\n\n## GUPP + Pinned Work = Completion\n\nAs long as:\n1. Work is pinned to polecat identity (e.g., gastown/furiosa)\n2. Sandbox persists (branch + worktree)\n3. Someone keeps spawning polecat when it dies\n\n→ The molecule WILL get finished. GUPP ensures wake-and-work.\n\n## Daemon → Deacon Heartbeat\n\nThe daemon pings the deacon, keeping the cycle alive. Deacon peeks into rig-wide channels during patrol and can service lifecycle requests.\n\n## Open Design Questions\n\n### Q1: Spoon-Feeding Bin-Packing\nTwo dimensions of granularity trade-offs:\n- How many logical steps per physical molecule step?\n- How many molecule steps per polecat session?\n\nToo few steps → context exhaustion, forgetting\nToo many steps → overhead, fragmentation\n\nNeeds: Analysis of optimal granularity based on step complexity.\n\n### Q2: Mechanical vs Agent-Driven Recycling\nCaution from deacon murder spree bug: mechanical detection of \"stuck\" workers is fragile.\n\nPrefer: Explicit \"recycle me\" requests serviced by patrol agents.\n\nQuestion: When is mechanical intervention appropriate?\n\n### Q3: Channel Implementation\nOptions:\n- Mail-based (gt mail to rig/polecats)\n- Beads-based (special issue type)\n- State file (rig/polecat-queue.json)\n\nMail seems most consistent with Gas Town patterns.\n\n### Q4: Who Spawns Next Step?\nCurrent: gt sling spawns fresh polecat\nNeeded: Mechanism for \"continue molecule on existing sandbox\"\n\nMaybe: gt sling --continue or witness detects pending step.\n\n## Related Issues\n\n- gt-dtw9u: Witness monitoring (enhance survey-workers)\n- gt-qpwv4: Completion detection (check ready branches)\n- gt-6qyt1: Refinery queue (process MERGE_READY)\n- gt-budeb: Auto-nuke (handle MERGED signal)\n- gt-5j3ia: Swarm aggregation (batch completion)\n- gt-1dbcp: Polecat auto-start (SessionStart hook issue)\n\n## Design Principles (from HOP/MEOW context)\n\n1. **Discovery over tracking** - observe reality each cycle\n2. **Mail as coordination primitive** - agents signal via mail\n3. **ZFC** - Claude makes judgment calls, no hardcoded thresholds\n4. **Redundant monitoring** - overlapping observation is resilience\n5. **Wisps are ephemeral** - patrol molecules flow like water\n\n## Next Steps\n\n1. Finalize channel design (mail-based queue)\n2. Enhance witness patrol formula with completion detection\n3. Enhance refinery patrol with MERGED signaling\n4. Implement step-level recycling\n5. Design spoon-feeding granularity guidelines","status":"hooked","priority":1,"issue_type":"epic","created_at":"2025-12-27T19:55:01.660221-08:00","created_by":"mayor","updated_at":"2025-12-27T19:58:46.95043-08:00"} -{"id":"gt-t76fz","title":"ZFC #4: Replace daemon identity parsing with agent self-registration","description":"**ZFC Violation:** internal/daemon/lifecycle.go:209-309\n\nThe daemon has embedded switch statements that parse agent identity strings to determine:\n- Session names\n- Working directories\n- Which agents need pre-sync\n- Restart commands\n\n**Current anti-pattern:**\n```go\nif strings.HasSuffix(identity, \"-refinery\") {\n needsPreSync = true\n workDir = filepath.Join(...)\n}\n```\n\n**ZFC-compliant solution:**\nAgent types self-register via role beads:\n- Role bead contains: working_dir, session_name_pattern, needs_sync, restart_command\n- Daemon reads role bead to get lifecycle config\n- No identity string parsing in Go\n\n**Depends on:** Day 1.5 (role beads exist)\n\nReference: ~/gt/docs/zfc-violations-audit.md #4","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-27T21:32:22.443355-08:00","created_by":"mayor","updated_at":"2025-12-30T02:06:22.851955-08:00","closed_at":"2025-12-30T02:06:22.851955-08:00","close_reason":"Implemented role-based lifecycle configuration - daemon now uses role beads for session patterns, work directories, pre-sync, and start commands","dependencies":[{"issue_id":"gt-t76fz","depends_on_id":"gt-xgqnb","type":"blocks","created_at":"2025-12-27T21:32:39.209763-08:00","created_by":"daemon"}]} -{"id":"gt-t7ekm","title":"gt mol attach: Auto-detect agent from cwd when single arg provided","description":"## Current Behavior\n\ngt mol attach requires 2 args:\n gt mol attach \u003cagent-bead-id\u003e \u003cmolecule-id\u003e\n\n## Expected Behavior\n\nWhen called with 1 arg from an agent working directory:\n gt mol attach \u003cmolecule-id\u003e\n\nShould auto-detect the agent from cwd (same detection used by gt mail, bd, etc.)\nand attach the molecule to that agent hook.\n\n## Example\n\nFrom ~/gt/gastown/mayor/rig:\n gt mol attach gt-y14l7\n -\u003e detects mayor role\n -\u003e attaches gt-y14l7 to gt-mayor hook\n\n## Implementation\n\n1. Check arg count\n2. If 1 arg, call role detection from cwd\n3. Resolve agent bead ID from role (gt-mayor, gt-witness-gastown, etc.)\n4. Proceed with attachment\n\nThis makes the common case (attaching work to yourself) ergonomic.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/nux","created_at":"2025-12-28T22:27:13.897826-08:00","created_by":"stevey","updated_at":"2025-12-30T00:16:04.946268-08:00","closed_at":"2025-12-30T00:16:04.946268-08:00","close_reason":"Implemented: gt mol attach now accepts 1 arg and auto-detects agent bead ID from cwd"} -{"id":"gt-t7g4b","title":"Merge: cheedo-mjtmlvge","description":"branch: polecat/cheedo-mjtmlvge\ntarget: main\nsource_issue: cheedo-mjtmlvge\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:25:09.087604-08:00","created_by":"gastown/polecats/cheedo","updated_at":"2025-12-30T23:12:42.854225-08:00","closed_at":"2025-12-30T23:12:42.854225-08:00","close_reason":"Branch already merged"} -{"id":"gt-t7j7u","title":"Digest: mol-deacon-patrol","description":"Patrol 20: 3 rigs healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:36:32.241884-08:00","updated_at":"2026-01-01T04:36:32.241884-08:00","closed_at":"2026-01-01T04:36:32.241854-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-t84xh","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy, cycling session","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:02:19.323287-08:00","updated_at":"2026-01-01T11:02:19.323287-08:00","closed_at":"2026-01-01T11:02:19.323254-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-t85hw","title":"gt mr: Add alias for merge request operations","description":"Agent guessed `gt mr register \u003cbranch\u003e` to submit a branch to the merge queue. The actual command is `gt mq submit`.\n\n**Suggestion**: Add `gt mr` as an alias or subcommand for merge request workflows:\n- `gt mr submit` → `gt mq submit`\n- `gt mr status` → `gt mq status`\n- `gt mr list` → `gt mq list`\n\n**Why**: 'MR' (merge request) is the conceptual noun; 'mq' (merge queue) is the implementation detail. Agents and humans think in terms of 'I have a merge request' not 'I need to interact with the queue'.\n\n**Alternative**: Just document `gt mq` more prominently, but aliases cost little and reduce friction.\n\nFiled by: gastown/polecats/nux (agent UX feedback)","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/dag","created_at":"2025-12-31T11:46:45.395859-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-01T18:43:17.720329-08:00","closed_at":"2026-01-01T18:43:17.720329-08:00","close_reason":"Added 'gt mr' as alias for 'gt mq' commands. MR submitted: gt-mcbna"} -{"id":"gt-t8wlb","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: all healthy, 3 rigs, 6 agents, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T00:44:24.818116-08:00","updated_at":"2026-01-01T00:44:24.818116-08:00","closed_at":"2026-01-01T00:44:24.818079-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-t927x","title":"Session ended: gt-gastown-nux","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:13:47.964961-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-04T16:40:13.414949-08:00","closed_at":"2026-01-04T16:40:13.414949-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/nux","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:13:47-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nux\",\"worker\":\"nux\"}"} -{"id":"gt-t9ojq","title":"Digest: mol-deacon-patrol","description":"Patrol 6: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:05:30.233061-08:00","updated_at":"2025-12-28T03:05:30.233061-08:00","closed_at":"2025-12-28T03:05:30.233023-08:00"} -{"id":"gt-tal6q","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:52:08.133984-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.679996-08:00","closed_at":"2026-01-05T19:44:18.679996-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:52:08-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-tc58x","title":"Boot needs CLAUDE.md and directory setup","description":"Boot spawns in ~/gt/deacon but:\n1. No ~/gt/deacon/dogs/boot/ directory exists\n2. Boot reads Deacon's CLAUDE.md (wrong role context)\n3. spawnTmux() doesn't send initial triage prompt\n\nFix:\n- Create ~/gt/deacon/dogs/boot/CLAUDE.md with Boot role instructions\n- Update EnsureDir() to create directory on spawn\n- Consider sending 'gt boot triage' as initial prompt\n\nBoot should know it's a fresh-each-tick watchdog that:\n- Observes Deacon state\n- Decides: start/wake/nudge/nothing\n- Cleans stale inbox\n- Exits (never handoffs)","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2025-12-30T21:57:23.279002-08:00","created_by":"mayor","updated_at":"2025-12-30T22:02:18.5203-08:00","closed_at":"2025-12-30T22:02:18.5203-08:00","close_reason":"Implemented: Created ~/gt/deacon/dogs/boot/CLAUDE.md with Boot role context, updated spawnTmux() to use bootDir instead of deaconDir, added 'gt boot triage' as initial prompt."} -{"id":"gt-tc6in","title":"Digest: mol-deacon-patrol","description":"Patrol 106: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:05:35.130135-08:00","updated_at":"2026-01-01T14:05:35.130135-08:00","closed_at":"2026-01-01T14:05:35.130101-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tc9wp","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T16:48:18.459197-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T16:48:18.515741-08:00","closed_at":"2026-01-06T16:48:18.515741-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T16:48:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-tcorq","title":"Merge: vuvalini-mk0rvbvm","description":"branch: polecat/vuvalini-mk0rvbvm\ntarget: main\nsource_issue: vuvalini-mk0rvbvm\nrig: gastown\nagent_bead: gt-gastown-polecat-gus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T22:26:58.234942-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-05T00:11:39.819088-08:00","closed_at":"2026-01-05T00:11:39.819088-08:00","close_reason":"Branch polecat/vuvalini-mk0rvbvm no longer exists - work not on main, unverifiable"} -{"id":"gt-tcv8","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy, routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T22:35:11.507838-08:00","updated_at":"2025-12-24T22:35:11.507838-08:00","closed_at":"2025-12-24T22:35:11.507795-08:00"} -{"id":"gt-tdeim","title":"Review PR #53: fix: Add retry logic for Enter key send in NudgeSession/NudgePane","description":"Review PR #53. Check retry logic is sound. Test locally if needed. Approve with gh pr review --approve if good.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2026-01-03T11:40:26.650916-08:00","created_by":"mayor","updated_at":"2026-01-03T11:43:56.314952-08:00","closed_at":"2026-01-03T11:43:56.314952-08:00","close_reason":"PR #53 reviewed and approved"} -{"id":"gt-tdsfj","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:12:19.213091-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.303243-08:00","closed_at":"2026-01-04T16:40:13.303243-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:12:19-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-tfa2e","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:04:48.048626-08:00","updated_at":"2026-01-01T20:04:48.048626-08:00","closed_at":"2026-01-01T20:04:48.04859-08:00","close_reason":"Squashed from 16 wisps","dependencies":[{"issue_id":"gt-tfa2e","depends_on_id":"gt-eph-ereg","type":"parent-child","created_at":"2026-01-01T20:04:48.049988-08:00","created_by":"deacon"}]} -{"id":"gt-tggjl","title":"Digest: mol-deacon-patrol","description":"Patrol #5: All systems nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:21:03.188755-08:00","updated_at":"2025-12-31T06:21:03.188755-08:00","closed_at":"2025-12-31T06:21:03.188717-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tggp2","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:08:26.408487-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.715862-08:00","closed_at":"2026-01-05T00:08:31.715862-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:08:26-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-tgy1v","title":"@group dynamic resolution in mail router","description":"## @group Dynamic Resolution in Mail Router\n\nWire agent bead queries into mail router for @group addresses.\n\n## Updated Approach (post agent-as-bead + Dogs)\n\nAgent discovery uses bead queries:\n\n```bash\nbd list --type=agent --rig=gastown # All agents in rig\nbd list --type=agent --role_type=witness # All witnesses\nbd list --type=agent --role_type=dog # All dogs\n```\n\n## Supported Patterns\n\n| Pattern | Resolution | Scope |\n|---------|------------|-------|\n| `@rig/gastown` | `--rig=gastown` | All gastown agents |\n| `@town` | `--rig=\"\"` (no filter) | All town-level agents |\n| `@witnesses` | `--role_type=witness` | All witnesses across rigs |\n| `@crew/gastown` | `--role_type=crew --rig=gastown` | Gastown crew |\n| `@dogs` | `--role_type=dog` | All Deacon dogs |\n| `@overseer` | Special case (not bead query) | Human operator |\n\n## Deliverables\n\n1. Parse @group syntax in router\n2. Resolve via `bd list --type=agent` queries\n3. Fan-out at send time (N copies, one per recipient)\n4. Special handling for `@overseer` (single recipient, uses overseer.json)\n\n## @overseer Special Case\n\nThe overseer is the human operator - NOT an agent bead. Resolution:\n- Load `mayor/overseer.json`\n- Use `overseer/` as recipient address\n- No bead query needed\n\n## Dependencies\n- Agent bead schema (gt-ikyo1) ✅ closed\n- Dog agent beads need role_type=dog (new prereq)\n\n## Acceptance\n- @rig/gastown sends to all gastown agents\n- @dogs sends to all Deacon dogs\n- @overseer sends to human operator\n- Each recipient gets own message copy","notes":"Beads dependency: bd-jsk7 (Agent beads: structured labels for filtering)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/imperator","created_at":"2025-12-26T14:52:04.244948-08:00","updated_at":"2025-12-30T10:39:59.111-08:00","closed_at":"2025-12-30T10:39:59.111-08:00","close_reason":"Implemented @group dynamic resolution in mail router with fan-out support","dependencies":[{"issue_id":"gt-tgy1v","depends_on_id":"gt-xo05b","type":"blocks","created_at":"2025-12-26T14:53:03.081856-08:00","created_by":"daemon"},{"issue_id":"gt-tgy1v","depends_on_id":"gt-ikyo1","type":"blocks","created_at":"2025-12-27T22:16:18.444503-08:00","created_by":"daemon"},{"issue_id":"gt-tgy1v","depends_on_id":"gt-qha0g","type":"blocks","created_at":"2025-12-29T19:57:46.720308-08:00","created_by":"daemon"}]} -{"id":"gt-th7","title":"Add agent abstraction layer to support non-Claude agents","description":"Currently Gas Town hardcodes 'claude --dangerously-skip-permissions' throughout the codebase for spawning agents. We should add an abstraction layer to support other AI agents (e.g., Gemini CLI, OpenAI agents, local models).\n\nLocations that spawn Claude:\n- internal/cmd/mayor.go:131\n- internal/cmd/deacon.go:150 \n- internal/cmd/witness.go:280\n- internal/cmd/crew.go (multiple locations)\n- internal/cmd/up.go:190, 229\n- internal/session/manager.go:146\n- internal/refinery/manager.go:207\n\nSuggested approach:\n1. Create an agent package with an interface\n2. Add configuration for agent type in town/rig config\n3. Replace hardcoded claude commands with agent.Spawn() calls\n4. Support agents: claude, gemini, openai, local (ollama, etc.)","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-20T15:11:15.931048-08:00","updated_at":"2025-12-20T15:26:54.236995-08:00"} -{"id":"gt-tjy9r","title":"Merge: capable-1767074974673","description":"branch: polecat/capable-1767074974673\ntarget: main\nsource_issue: capable-1767074974673\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:12:26.130677-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T10:06:56.899508-08:00","closed_at":"2025-12-30T10:06:56.899508-08:00","close_reason":"Branch merged to main"} -{"id":"gt-tkbd5","title":"Refactor runStart into focused helper functions","description":"attached_args: Refactor runStart into focused helper functions\n\nBreak up the 126-line runStart function in start.go.\n\n## Files to modify\n- internal/cmd/start.go\n\n## Current structure (lines 129-255)\nrunStart does:\n1. Crew path detection\n2. Workspace verification\n3. Mayor session start\n4. Deacon session start\n5. Optional rig agent startup\n6. Configured crew auto-start\n\n## Refactoring plan\nExtract these helpers:\n```go\nfunc startMayorSession(townRoot string, verbose bool) error\nfunc startDeaconSession(townRoot string) error\nfunc startRigAgents(townRoot string, rigs []string) error\nfunc startConfiguredCrew(townRoot string, config *TownConfig) error\n```\n\n## Acceptance criteria\n- [ ] runStart reduced to \u003c50 lines\n- [ ] 4 helper functions extracted\n- [ ] Each helper is \u003c40 lines\n- [ ] No change in behavior\n- [ ] go test ./internal/cmd/... passes\n- [ ] Manual test: gt start works correctly","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:49:13.889957-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T16:35:53.275529-08:00","closed_at":"2025-12-28T16:35:53.275529-08:00"} -{"id":"gt-tlddj","title":"Digest: mol-deacon-patrol","description":"Patrol 19: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:12:19.90269-08:00","updated_at":"2025-12-31T18:12:19.90269-08:00","closed_at":"2025-12-31T18:12:19.902651-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tmqbj","title":"Merge: rictus-1766959789036","description":"branch: polecat/rictus-1766959789036\ntarget: main\nsource_issue: rictus-1766959789036\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-28T14:19:41.66519-08:00","created_by":"stevey","updated_at":"2025-12-28T22:29:42.183162-08:00","closed_at":"2025-12-28T22:29:42.183162-08:00"} -{"id":"gt-tmryi","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:02:01.329737-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:02:01.386739-08:00","closed_at":"2026-01-06T13:02:01.386739-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:02:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-tnap3","title":"queue: shared storage work queues","description":"## queue: Shared Storage Work Queues\n\nWork queue with shared storage (single copy, first-to-claim).\n\n## Pattern Clarification\n\n**Queue is a MAILBOX pattern** (pull-based):\n- Workers poll shared queue\n- First to claim gets the work\n- Worker decides when to check\n\n**This is DIFFERENT from Dog dispatch** (push-based):\n- `gt sling \u003cwork\u003e deacon/dogs` pushes to hook\n- GUPP fires immediately\n- Deacon decides when to assign\n\n| Pattern | Mechanism | Initiative |\n|---------|-----------|------------|\n| `queue:` | Poll mailbox, claim | Worker pulls |\n| Dog sling | Hook assignment | Deacon pushes |\n\n## Use Cases for queue:\n\n1. **Batch cleanup tasks** - Multiple agents can help, order does not matter\n2. **Overflow work** - When primary handler is busy\n3. **Opportunistic tasks** - Agents check between other work\n\n## Deliverables\n\n1. Parse queue:name syntax in router\n2. Shared storage model:\n - Single message copy (NOT fan-out)\n - Stored in queue-specific location\n - Multiple agents can see it\n3. Queue configuration in ~/gt/config/queues.json\n4. Queue inbox command: gt mail queue \u003cname\u003e\n5. Claim semantics: `gt mail claim \u003cmsg-id\u003e` marks as claimed\n\n## Key Difference from list:\n- list: creates N copies (N obligations)\n- queue: creates 1 copy (1 obligation, first-to-claim)\n\n## Dependencies\n- Config directory (gt-i6jvc) ✅ closed\n\n## Acceptance\n- queue:cleanup creates single message\n- Multiple agents can view queue\n- Claim marks message as taken\n- Message invisible to others after claim","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/keeper","created_at":"2025-12-26T14:52:07.091239-08:00","updated_at":"2025-12-30T07:00:55.128361-08:00","closed_at":"2025-12-30T07:00:55.128361-08:00","close_reason":"Implemented queue:name syntax, shared storage, gt mail queue, and gt mail claim","dependencies":[{"issue_id":"gt-tnap3","depends_on_id":"gt-i6jvc","type":"blocks","created_at":"2025-12-26T14:53:06.932146-08:00","created_by":"daemon"}]} -{"id":"gt-tnnpa","title":"Digest: mol-deacon-patrol","description":"Patrol 216: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:56:53.347974-08:00","updated_at":"2026-01-01T16:56:53.347974-08:00","closed_at":"2026-01-01T16:56:53.347941-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-tnnpa","depends_on_id":"gt-eph-9qm5","type":"parent-child","created_at":"2026-01-01T16:56:53.349255-08:00","created_by":"deacon"}]} -{"id":"gt-tnocv","title":"Merge: furiosa-mjvtknih","description":"branch: polecat/furiosa-mjvtknih\ntarget: main\nsource_issue: furiosa-mjvtknih\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T11:15:24.389847-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T11:17:41.309454-08:00","closed_at":"2026-01-01T11:17:41.309454-08:00","close_reason":"Merged to main at cc362211"} -{"id":"gt-tnow.3","title":"Add witness plugin hook support","description":"Implement plugin directories for witness patrol.\n\nStructure:\n \u003crig\u003e/plugins/witness/\n ├── pre-inspection/\n │ └── stale-branch-check/\n │ └── CLAUDE.md\n └── post-action/\n └── mq-health/\n └── CLAUDE.md\n\nrun-plugins step scans these directories and bonds mol-plugin-runner for each.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T02:37:43.175287-08:00","updated_at":"2025-12-28T22:37:23.57202-08:00","closed_at":"2025-12-28T22:37:23.57202-08:00","dependencies":[{"issue_id":"gt-tnow.3","depends_on_id":"gt-tnow","type":"parent-child","created_at":"2025-12-23T02:37:43.175635-08:00","created_by":"daemon"}]} -{"id":"gt-tnss","title":"Analysis: Beads database size and hygiene strategy","description":"Audit beads database size and plan medium-term hygiene.\n\n## Questions\n1. How many issues total (including tombstones)?\n2. Size of issues.jsonl?\n3. Growth rate per day/week?\n4. What percentage are tombstones?\n\n## Hygiene Topics\n- Compaction: squash tombstones periodically\n- Archival: move old closed issues to archive file\n- Pruning: delete truly stale items (test beads, old MRs)\n- Sync efficiency: large JSONL = slow sync\n\n## Action Items\n- [ ] Count total issues by status\n- [ ] Count tombstones\n- [ ] Measure file sizes\n- [ ] Propose hygiene schedule","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T14:38:32.92481-08:00","updated_at":"2025-12-23T14:38:32.92481-08:00"} -{"id":"gt-tnw","title":"MCP beads tools fail from polecat directories","description":"The beads MCP plugin (plugin:beads:beads) fails to find issues when invoked from polecat directories.\n\n## Observed\n- Polecat in /gt/gastown/polecats/dementus\n- MCP tool: plugin:beads:beads - show (issue_id: 'gt-th7')\n- Error: 'bd command failed: Error: no issue found matching gt-th7'\n\n## Expected\nMCP tools should work the same as running bd directly.\n\n## Note\nThis may be related to gt-tmm (beads sync issue) rather than an MCP-specific bug. The MCP tool uses bd under the hood, and bd can't find the issue because the polecat's beads database is stale.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2025-12-20T15:17:33.135931-08:00","updated_at":"2025-12-30T00:05:45.525882-08:00","closed_at":"2025-12-30T00:05:45.525882-08:00","close_reason":"Fixed in beads-mcp plugin (bd-7t9a): Added _resolve_beads_redirect() function to follow .beads/redirect files during workspace auto-detection. Tests added and passing."} -{"id":"gt-tpiyz","title":"Digest: mol-deacon-patrol","description":"Patrol 76: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:03:50.875312-08:00","updated_at":"2025-12-31T15:03:50.875312-08:00","closed_at":"2025-12-31T15:03:50.875272-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tpq7i","title":"Merge: keeper-1767074342207","description":"branch: polecat/keeper-1767074342207\ntarget: main\nsource_issue: keeper-1767074342207\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T22:04:26.232527-08:00","created_by":"gastown/polecats/keeper","updated_at":"2025-12-30T00:34:50.910364-08:00","closed_at":"2025-12-30T00:34:50.910364-08:00","close_reason":"Branch polecat/keeper-1767074342207 does not exist - polecat decommissioned without work to merge"} -{"id":"gt-tqmth","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:24:20.496674-08:00","updated_at":"2026-01-01T10:24:20.496674-08:00","closed_at":"2026-01-01T10:24:20.496639-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tr0a","title":"Build rig/worker tree view component","description":"Bubbletea component showing hierarchical rig list with workers. Each rig expandable to show workers. Each worker shows: status indicator, current molecule title, step progress (X/Y), time since last activity.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:27:11.129093-08:00","updated_at":"2025-12-23T16:27:11.129093-08:00","dependencies":[{"issue_id":"gt-tr0a","depends_on_id":"gt-3p77","type":"blocks","created_at":"2025-12-23T16:27:38.55401-08:00","created_by":"daemon"},{"issue_id":"gt-tr0a","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:30.771619-08:00","created_by":"daemon"}]} -{"id":"gt-tr21t","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:54:09.549389-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.9741-08:00","closed_at":"2026-01-05T00:08:31.9741-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:54:09-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-tr3d","title":"Zombie session detection for refinery/witness","description":"A Claude session can crash or hang while still appearing as 'running' in tmux. The current IsRunning checks only verify tmux session exists, not that Claude is actually processing.\n\n## Problem\n- Refinery session might be hung (Claude crashed, infinite loop, etc.)\n- tmux HasSession returns true, so auto-start doesn't trigger\n- MRs pile up with no processing\n\n## Solution Options\n1. **Activity-based detection**: Check last output timestamp in tmux\n2. **Heartbeat file**: Agents write timestamp to file, check staleness\n3. **Prompt detection**: Look for Claude '\u003e' prompt indicating idle/stuck\n\n## Related\n- gt-bjft (spawn auto-start) assumes IsRunning means healthy\n- Witness patrol assumes running refinery is processing","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:02:51.089112-08:00","updated_at":"2025-12-23T14:27:08.051538-08:00","dependencies":[{"issue_id":"gt-tr3d","depends_on_id":"gt-bjft","type":"blocks","created_at":"2025-12-23T01:03:12.10595-08:00","created_by":"daemon"}]} -{"id":"gt-trfaz","title":"Merge: coma-mjz960ru","description":"branch: polecat/coma-mjz960ru\ntarget: main\nsource_issue: coma-mjz960ru\nrig: gastown\nagent_bead: gt-gastown-polecat-coma\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-03T21:00:26.912259-08:00","created_by":"gastown/polecats/coma","updated_at":"2026-01-03T21:16:24.563157-08:00","closed_at":"2026-01-03T21:16:24.563157-08:00","close_reason":"Merged to main at 3e39f250"} -{"id":"gt-tridl","title":"Merge: dag-mjtm8k85","description":"branch: polecat/dag-mjtm8k85\ntarget: main\nsource_issue: dag-mjtm8k85\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:37:18.664169-08:00","created_by":"gastown/polecats/dag","updated_at":"2025-12-31T14:03:14.566047-08:00","closed_at":"2025-12-31T14:03:14.566047-08:00"} -{"id":"gt-trym0","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy, routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:15:33.591974-08:00","updated_at":"2025-12-25T10:15:33.591974-08:00","closed_at":"2025-12-25T10:15:33.591943-08:00"} -{"id":"gt-ts4u","title":"Merge: gt-h5n.5","description":"branch: polecat/Scabrous\ntarget: main\nsource_issue: gt-h5n.5\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:43.268861-08:00","updated_at":"2025-12-20T23:17:25.78812-08:00","closed_at":"2025-12-20T23:17:25.78812-08:00"} -{"id":"gt-ts6kt","title":"Merge: nux-mjui76op","description":"branch: polecat/nux-mjui76op\ntarget: main\nsource_issue: nux-mjui76op\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T13:57:17.000338-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-31T13:58:27.125635-08:00","closed_at":"2025-12-31T13:58:27.125635-08:00","close_reason":"Already merged (no new commits)"} -{"id":"gt-tst6j","title":"MQ smart scheduling: dependency-aware queue reordering","description":"Implement intelligent MQ reordering to minimize conflicts.\n\n## Goal\nReorder the MQ so that MRs touching disjoint files merge \"in parallel\" (no conflicts), while MRs touching overlapping files are sequenced.\n\n## Approach\n1. For each MR, get list of changed files (from branch diff)\n2. Build conflict graph: edge between MRs if files overlap\n3. Find maximal independent sets (MRs that can merge in any order)\n4. Schedule independent MRs first, then handle remaining sequentially\n\n## Implementation\n- Add file analysis to MR submission (gt done)\n- Store changed_files in MR wisp\n- Refinery sorts queue by: priority → conflicts → age\n\n## Example\n```\nQueue: [A, B, C, D]\nFiles:\n A: auth/login.go\n B: payments/checkout.go \n C: auth/login.go ← conflicts with A!\n D: docs/readme.md\n\nOptimal: [A, B, D, C] - A, B, D can merge without waiting\n```\n\n## Parent\ngt-lxxh2","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-25T18:30:19.240371-08:00","updated_at":"2025-12-25T18:30:19.240371-08:00","dependencies":[{"issue_id":"gt-tst6j","depends_on_id":"gt-lxxh2","type":"blocks","created_at":"2025-12-25T18:30:33.226294-08:00","created_by":"daemon"}]} -{"id":"gt-ttdrt","title":"Digest: mol-deacon-patrol","description":"Patrol 18: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:10:50.948882-08:00","updated_at":"2025-12-28T03:10:50.948882-08:00","closed_at":"2025-12-28T03:10:50.948853-08:00"} -{"id":"gt-ttn3h","title":"Polecat hooks lost on session interruption","description":"When polecat sessions are interrupted (killed, crash, context limit), their hooked work is lost even though convoy still shows them assigned.\n\nEvidence from today:\n- bullet: convoy showed gt-3jnnu assigned, hook was empty\n- immortan: convoy showed gt-fugmy assigned, hook was empty \n- max: hook had gt-m39yd but session was idle/stalled\n\nRoot cause: Hook state lives in .beads/hook.json but isn't surviving session transitions. Either:\n1. Hook file not being written/persisted\n2. Session cleanup is clearing hooks\n3. Race condition during sling\n\nImpact: Work silently lost, requires manual re-sling to recover.\n\nProposed fix:\n1. Verify hook persistence on sling\n2. Add hook state verification to convoy status\n3. Consider hook recovery mechanism for interrupted sessions","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/rockryder","created_at":"2026-01-04T10:41:40.643305-08:00","created_by":"mayor","updated_at":"2026-01-04T16:52:53.261361-08:00","closed_at":"2026-01-04T16:52:53.261361-08:00","close_reason":"Fixed: hook now persists by also querying in_progress beads"} -{"id":"gt-ttqha","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:53:10.238446-08:00","updated_at":"2025-12-30T15:53:10.238446-08:00","closed_at":"2025-12-30T15:53:10.238415-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ttqp3","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:39:14.320229-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.605595-08:00","closed_at":"2026-01-05T00:08:31.605595-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:39:14-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-tubn","title":"Track operational stats as entity/audit beads","description":"Witness and refinery track operational stats in JSON files:\n- total_merged, today_merged, total_failed (refinery)\n- total_checks, total_nudges, total_escalations (witness)\n\nFor HOP entity CV tracking, these could become:\n- type=audit beads (daily roll-ups of operational metrics)\n- Entity chain entries showing validator activity\n\nThis provides observability and contributes to entity reputation tracking (e.g., refinery X has merged 500 PRs with 2% failure rate).\n\nNot critical for launch but aligns with HOP Platform of Platforms vision.","status":"open","priority":4,"issue_type":"feature","created_at":"2025-12-21T22:07:30.404073-08:00","updated_at":"2025-12-21T22:07:30.404073-08:00"} -{"id":"gt-tucp2","title":"Merge: toast-mjw7062w","description":"branch: polecat/toast-mjw7062w\ntarget: main\nsource_issue: toast-mjw7062w\nrig: gastown\nagent_bead: gt-gastown-polecat-toast","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T17:27:33.943633-08:00","created_by":"gastown/polecats/toast","updated_at":"2026-01-01T23:11:06.497212-08:00","closed_at":"2026-01-01T23:11:06.497212-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-tuzwe","title":"Merge: furiosa-mjuk2tlb","description":"branch: polecat/furiosa-mjuk2tlb\ntarget: main\nsource_issue: furiosa-mjuk2tlb\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T14:02:38.451263-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-31T14:03:54.294184-08:00","closed_at":"2025-12-31T14:03:54.294184-08:00","close_reason":"Merged at 0846bfd2"} -{"id":"gt-tvm74","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T12:58:57.595687-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T12:58:57.654928-08:00","closed_at":"2026-01-06T12:58:57.654928-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T12:58:57-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-tvwnz","title":"MQ summary in gt status","description":"Add per-rig MQ summary to gt status output.\n\nCurrent gt status shows:\n gastown\n refinery ✓ running\n\nAdd:\n gastown\n refinery ✓ running\n MQ: 4 pending, 1 in-flight\n\nImplementation:\n- Query beads for merge-request type issues\n- Count by status (open=pending, in_progress=in-flight)\n- Display in rig section","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-28T21:40:37.900461-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T01:50:34.700959-08:00","closed_at":"2025-12-30T01:50:34.700959-08:00","close_reason":"Implemented MQ summary in gt status output - shows pending, in-flight, and blocked MR counts under Refinery section","dependencies":[{"issue_id":"gt-tvwnz","depends_on_id":"gt-ytsxp","type":"blocks","created_at":"2025-12-28T21:41:11.558562-08:00","created_by":"daemon"}]} -{"id":"gt-txjgc","title":"Digest: mol-deacon-patrol","description":"Patrol 96: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:26:24.314558-08:00","updated_at":"2025-12-31T15:26:24.314558-08:00","closed_at":"2025-12-31T15:26:24.314516-08:00"} -{"id":"gt-tykcq","title":"Digest: mol-deacon-patrol","description":"Patrol 59: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:25:27.48201-08:00","updated_at":"2026-01-01T02:25:27.48201-08:00","closed_at":"2026-01-01T02:25:27.481972-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tyy9z","title":"Digest: mol-deacon-patrol","description":"Patrol 142 complete: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:57:06.673613-08:00","updated_at":"2025-12-31T15:57:06.673613-08:00","closed_at":"2025-12-31T15:57:06.673573-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-tz9h0","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:12:05.232206-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-06T13:12:05.287487-08:00","closed_at":"2026-01-06T13:12:05.287487-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:12:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-u0ccw","title":"Digest: mol-deacon-patrol","description":"P16: stable","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:59:59.331911-08:00","updated_at":"2025-12-25T19:59:59.331911-08:00","closed_at":"2025-12-25T19:59:59.331857-08:00"} -{"id":"gt-u0e6a","title":"Digest: mol-deacon-patrol","description":"Patrol 115: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:13:39.63532-08:00","updated_at":"2026-01-01T14:13:39.63532-08:00","closed_at":"2026-01-01T14:13:39.63528-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-u0zqy","title":"Merge: nux-1767080427756","description":"branch: polecat/nux-1767080427756\ntarget: main\nsource_issue: nux-1767080427756\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:47:49.107094-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-29T23:55:11.80929-08:00","closed_at":"2025-12-29T23:55:11.80929-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-u1j.15","title":"Plugin system: subprocess JSON protocol","description":"Language-agnostic plugin system via subprocess JSON protocol.\n\n## Concept\n\nAllow extending Gas Town with external scripts/programs. Plugins communicate via stdin/stdout JSON.\n\n## Protocol\n\nRequest (gt → plugin):\n```json\n{\"method\": \"check\", \"params\": {\"rig\": \"wyvern\", \"polecat\": \"Toast\"}}\n```\n\nResponse (plugin → gt):\n```json\n{\"result\": {...}, \"error\": null}\n```\n\nError response:\n```json\n{\"result\": null, \"error\": {\"code\": 1, \"message\": \"...\"}}\n```\n\n## Interface\n\n```go\ntype Plugin struct {\n Name string\n Path string // executable path\n Methods []string\n}\n\ntype PluginManager struct {\n plugins map[string]*Plugin\n}\n\nfunc NewPluginManager() *PluginManager\nfunc (pm *PluginManager) Register(plugin *Plugin) error\nfunc (pm *PluginManager) Call(plugin, method string, params any) (any, error)\nfunc (pm *PluginManager) Discover(dir string) error // auto-discover plugins\n```\n\n## Plugin Discovery\n\nLook in:\n1. `\u003ctown\u003e/plugins/`\n2. `~/.config/gastown/plugins/`\n3. System path with `gt-plugin-*` prefix\n\n## Built-in Hooks\n\nPlugins can register for events:\n- `polecat.started` - Polecat session started\n- `polecat.done` - Polecat signals done\n- `merge.requested` - MR submitted\n- `merge.completed` - MR merged\n\n## Use Cases\n\n- Custom health checks\n- Integration with external systems (Slack, etc.)\n- Custom merge policies\n- Metrics collection\n\n## Future\n\nConsider MCP integration for richer plugin capabilities.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-15T17:12:59.200876-08:00","updated_at":"2025-12-28T22:36:41.70144-08:00","closed_at":"2025-12-28T22:36:41.70144-08:00","dependencies":[{"issue_id":"gt-u1j.15","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:59.201236-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.15","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.246945-08:00","created_by":"daemon"}]} -{"id":"gt-u1j.2","title":"Bubbletea TUI dashboard","description":"Interactive TUI using Charm Bubbletea. Root model, view routing, Lipgloss theme. Includes: dashboard, rig explorer, polecat detail with live tail, mail view, beads view, spawn wizard.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-15T16:52:02.390539-08:00","updated_at":"2025-12-28T22:36:41.719314-08:00","closed_at":"2025-12-28T22:36:41.719314-08:00","dependencies":[{"issue_id":"gt-u1j.2","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T16:52:02.39089-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.2","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T16:52:10.351879-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.2","depends_on_id":"gt-f9x.3","type":"blocks","created_at":"2025-12-15T16:52:10.441448-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.2","depends_on_id":"gt-lak31","type":"blocks","created_at":"2025-12-28T21:41:21.252981-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.2","depends_on_id":"gt-rbncw","type":"blocks","created_at":"2025-12-28T21:41:21.282777-08:00","created_by":"daemon"}]} -{"id":"gt-u201i","title":"Merge: dag-mjtm8k85","description":"branch: polecat/dag-mjtm8k85\ntarget: main\nsource_issue: dag-mjtm8k85\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:16:19.897281-08:00","created_by":"gastown/polecats/dag","updated_at":"2026-01-01T09:53:50.706238-08:00","closed_at":"2026-01-01T09:53:50.706238-08:00","close_reason":"Branch deleted, no audit trail - unverifiable"} -{"id":"gt-u3rdb","title":"Digest: mol-deacon-patrol","description":"Cycle 191: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:23:10.956132-08:00","updated_at":"2026-01-01T16:23:10.956132-08:00","closed_at":"2026-01-01T16:23:10.956092-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-u3rdb","depends_on_id":"gt-eph-wuue","type":"parent-child","created_at":"2026-01-01T16:23:10.957445-08:00","created_by":"deacon"}]} -{"id":"gt-u3u5u","title":"Digest: mol-deacon-patrol","description":"Patrol 7: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:05:55.19358-08:00","updated_at":"2025-12-28T03:05:55.19358-08:00","closed_at":"2025-12-28T03:05:55.193549-08:00"} -{"id":"gt-u49zh","title":"Include session ID in PropulsionNudge for /resume picker","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2026-01-02T20:44:07.691441-08:00","created_by":"mayor","updated_at":"2026-01-02T20:50:28.192394-08:00","closed_at":"2026-01-02T20:50:28.192394-08:00","close_reason":"PropulsionNudgeForRole now accepts workDir and appends [session:xxx] when .runtime/session_id exists"} -{"id":"gt-u4fh","title":"Remove stubbed ProcessMRFromQueue and mrqueue package","description":"internal/refinery/engineer.go has stubbed ProcessMRFromQueue() that returns hardcoded failure.\ninternal/mrqueue/ package exists but isn't used.\n\nThis was aspirational 'beads-based MR automation' but:\n1. Refinery agent just runs git commands per role prompt\n2. manager.ProcessMR() is already fully implemented if we need Go automation\n3. The stub creates confusion about what's working\n\nEither:\n1. Remove engineer.ProcessMRFromQueue and mrqueue package entirely\n2. Or finish implementing it if there's a real use case\n\nLeaning toward removal - YAGNI.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T13:04:53.050803-08:00","updated_at":"2025-12-30T22:24:28.629598-08:00","closed_at":"2025-12-30T00:47:50.801985-08:00","close_reason":"Removed ProcessMRFromQueue, mrqueue package, and related queue handlers from engineer.go. Manager.ProcessMR is the working implementation.","dependencies":[{"issue_id":"gt-u4fh","depends_on_id":"gt-jo9n","type":"blocks","created_at":"2025-12-24T13:05:00.183378-08:00","created_by":"daemon"}]} -{"id":"gt-u4sv9","title":"Digest: mol-deacon-patrol","description":"Patrol 122: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:29:17.549016-08:00","updated_at":"2026-01-01T14:29:17.549016-08:00","closed_at":"2026-01-01T14:29:17.548984-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-u65t8","title":"Merge: valkyrie-1767106008400","description":"branch: polecat/valkyrie-1767106008400\ntarget: main\nsource_issue: valkyrie-1767106008400\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T10:43:03.503911-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-30T18:23:22.202888-08:00","closed_at":"2025-12-30T18:23:22.202888-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-u6a7h","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All rigs healthy. No callbacks. Town idle.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:59:45.177583-08:00","updated_at":"2026-01-01T19:59:45.177583-08:00","closed_at":"2026-01-01T19:59:45.177551-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-u6e8o","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 61: All agents healthy, no orphans, archived 1 ACK","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:10:20.223448-08:00","updated_at":"2026-01-01T13:10:20.223448-08:00","closed_at":"2026-01-01T13:10:20.223396-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-u6siy","title":"Day 3.3: Witness sends MERGE_READY to refinery","description":"When polecat completes work:\n1. Witness detects completion (hook_bead closed, state=stopped)\n2. Witness sends mail to refinery: MERGE_READY\n3. Mail includes branch name and work bead ID\n\nParent: gt-hwka3","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:04.438294-08:00","created_by":"mayor","updated_at":"2025-12-28T09:51:24.398745-08:00","closed_at":"2025-12-28T09:51:24.398745-08:00","dependencies":[{"issue_id":"gt-u6siy","depends_on_id":"gt-hwka3","type":"parent-child","created_at":"2025-12-27T20:58:47.941899-08:00","created_by":"daemon"},{"issue_id":"gt-u6siy","depends_on_id":"gt-gizsv","type":"blocks","created_at":"2025-12-27T20:58:59.577532-08:00","created_by":"daemon"},{"issue_id":"gt-u6siy","depends_on_id":"gt-qpwv4","type":"relates-to","created_at":"2025-12-27T20:59:10.640353-08:00","created_by":"daemon"},{"issue_id":"gt-u6siy","depends_on_id":"gt-k294l","type":"blocks","created_at":"2025-12-27T23:17:28.250458-08:00","created_by":"daemon"}]} -{"id":"gt-u7dxq","title":"Activity feed improvements","description":"Make the activity feed (gt feed) a first-class TUI experience using charmbracelet.\n\n## Vision\n\nA real-time dashboard showing all Gas Town activity with:\n- Agent tree organized by role (mayor, witnesses, crew, polecats)\n- Live event stream\n- Vim-style navigation\n- Filtering and search\n\n## Architecture\n\nTwo-tier event system:\n- ~/gt/.events.jsonl (raw, audit) - all events from gt, bd, agents\n- Feed daemon curates → ~/gt/.feed.jsonl (user-facing) - filtered, deduped\n\nTUI reads from curated feed for smooth UX.\n\n## Layout (Dashboard + Stream)\n```\n┌─────────────────────────────────────────────────────────────┐\n│ GT Feed Filter: all │\n├─────────────────────────────────────────────────────────────┤\n│ gastown/ │\n│ 🎩 mayor [10:30] Dispatched gt-xyz → Toast │\n│ 👁 witness [10:28] Nudged polecat-3 (idle 5m) │\n│ 🏭 refinery [10:25] Merged PR #123 │\n│ 👷 crew/ │\n│ joe [10:22] ✓ Completed gt-95j13 │\n│ max [10:18] → Working on gt-s6r44 │\n│ 😺 polecats/ │\n│ Toast [10:30] Received gt-xyz, starting... │\n├─────────────────────────────────────────────────────────────┤\n│ [10:30] 😺 Toast: Received molecule gt-xyz │\n│ [10:28] 👁 witness: Nudged polecat-3 after 5m idle │\n│ [10:25] 🏭 refinery: Merged PR #123 │\n├─────────────────────────────────────────────────────────────┤\n│ j/k: scroll /: search f: filter q: quit ?: help │\n└─────────────────────────────────────────────────────────────┘\n```\n\n## Key Features\n1. Real-time updates - events stream in live\n2. Agent tree - all agents grouped by role with status\n3. Vim-style navigation - j/k, gg/G, /search\n4. Filtering - by rig, role, event type, time\n5. Collapsible sections\n6. Details on select\n\n## Tech Stack\n- bubbletea - TUI framework\n- bubbles - viewport, list components\n- lipgloss - styling (already have)\n\n## Success Criteria\n- Feed is beautiful and scannable at a glance\n- Agent activity visible in real-time\n- Works in any terminal, degrades gracefully for pipes","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-28T11:01:43.337499-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T19:19:34.794909-08:00","dependencies":[{"issue_id":"gt-u7dxq","depends_on_id":"gt-sb6m4","type":"blocks","created_at":"2025-12-28T11:02:43.136872-08:00","created_by":"daemon"},{"issue_id":"gt-u7dxq","depends_on_id":"gt-zc6ma","type":"blocks","created_at":"2025-12-28T11:02:43.165368-08:00","created_by":"daemon"},{"issue_id":"gt-u7dxq","depends_on_id":"gt-1ydd9","type":"blocks","created_at":"2025-12-28T11:02:43.194997-08:00","created_by":"daemon"},{"issue_id":"gt-u7dxq","depends_on_id":"gt-7aw1m","type":"blocks","created_at":"2025-12-28T11:02:43.224956-08:00","created_by":"daemon"},{"issue_id":"gt-u7dxq","depends_on_id":"gt-38doh","type":"blocks","created_at":"2025-12-28T12:46:47.283782-08:00","created_by":"daemon"},{"issue_id":"gt-u7dxq","depends_on_id":"gt-1uhmj","type":"blocks","created_at":"2025-12-28T12:46:47.313034-08:00","created_by":"daemon"}]} -{"id":"gt-u8tvh","title":"Session ended: gt-gastown-slit","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T18:25:13.990869-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-03T11:32:45.174832-08:00","closed_at":"2026-01-03T11:32:45.174832-08:00","close_reason":"Session lifecycle events processed","event_kind":"session.ended","actor":"gastown/polecats/slit","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T18:25:13-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-slit\",\"worker\":\"slit\"}"} -{"id":"gt-u95ku","title":"Digest: mol-deacon-patrol","description":"Patrol 4: routine, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T20:00:54.624814-08:00","updated_at":"2025-12-26T20:00:54.624814-08:00","closed_at":"2025-12-26T20:00:54.624766-08:00"} -{"id":"gt-u9can","title":"Digest: mol-deacon-patrol","description":"Patrol 2: 1 msg (Nux done), health OK","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:42:03.116065-08:00","updated_at":"2025-12-28T19:42:03.116065-08:00","closed_at":"2025-12-28T19:42:03.116034-08:00"} -{"id":"gt-ua34i","title":"Merge: slit-mjvtz18y","description":"branch: polecat/slit-mjvtz18y\ntarget: main\nsource_issue: slit-mjvtz18y\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T11:25:08.070467-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-01T14:15:16.691746-08:00","closed_at":"2026-01-01T14:15:16.691746-08:00","close_reason":"Already merged to main at 2bcfa763 - stale MR bead"} -{"id":"gt-uaacb","title":"Digest: mol-deacon-patrol","description":"Patrol 247 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:19:46.327002-08:00","updated_at":"2026-01-01T17:19:46.327002-08:00","closed_at":"2026-01-01T17:19:46.326959-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uazec","title":"Digest: mol-deacon-patrol","description":"Patrol 3: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:44:36.529952-08:00","updated_at":"2025-12-25T20:44:36.529952-08:00","closed_at":"2025-12-25T20:44:36.529895-08:00"} -{"id":"gt-ub5gh","title":"Digest: mol-deacon-patrol","description":"Patrol 6: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:43:56.849161-08:00","updated_at":"2025-12-25T15:43:56.849161-08:00","closed_at":"2025-12-25T15:43:56.84913-08:00"} -{"id":"gt-ubnpe","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:11:38.334733-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.468794-08:00","closed_at":"2026-01-05T19:44:18.468794-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:11:33-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-ubqeg","title":"Formula Molecules: Guzzoline production for Gas Town","description":"## Vision\n\nGas Town executes work. But it also needs to PRODUCE work - structured, high-quality guzzoline on demand. **Formula Molecules** are recipes that spawn structured convoys.\n\n## Core Insight\n\nA formula is a molecule template that:\n1. Takes input (a PR, a design problem, a codebase)\n2. Spawns multiple polecats with specific focuses\n3. Each leg produces structured output\n4. Synthesis step combines into unified deliverable\n\nGas Town becomes both consumer AND producer of guzzoline.\n\n## Example Formulas\n\n### Design Convoy Formula\nInput: Feature request or problem statement\nLegs (parallel):\n- API design polecat\n- Data model polecat \n- UX/ergonomics polecat\n- Scalability polecat\n- Security polecat\nSynthesis: Unified design doc with tradeoffs\n\n### Code Review Convoy Formula\nInput: PR or file set\nLegs (parallel):\n- Correctness: Does it work?\n- Performance: Any bottlenecks?\n- Security: Vulnerabilities?\n- Elegance: Clean design?\n- Resilience: Error handling?\n- Style: Convention compliance?\n- Smells: Anti-patterns?\n- Legacy: Respects existing patterns?\nSynthesis: Categorized review with priority issues\n\n### Other Formula Ideas\n- Test Coverage Convoy: Unit, integration, edge cases, error paths\n- Documentation Convoy: API docs, user guide, examples, changelog\n- Migration Convoy: Database, API, config, rollback plan\n- Incident Response: Root cause, timeline, fix, prevention\n\n## Mol Mall\n\nLibrary/marketplace of formulas:\n```bash\ngt formula list # Available formulas\ngt formula show code-review # Formula details\ngt formula run code-review --pr=123 # Execute formula → convoy\ngt formula create my-review # Create custom formula\n```\n\n## Technical Design\n\n### Formula Structure (in beads)\n```yaml\nid: formula-code-review\ntype: formula\nname: Code Review\ninputs:\n - name: target\n type: pr | files | branch\nlegs:\n - name: correctness\n focus: \"Verify logical correctness and edge cases\"\n output: findings.md\n - name: security\n focus: \"Identify security vulnerabilities\"\n output: findings.md\n # ...\nsynthesis:\n inputs: all leg outputs\n output: review-summary.md\n```\n\n### Execution Model\n1. `gt formula run` creates convoy with formula reference\n2. Spawns polecats for each leg (parallel where possible)\n3. Each polecat gets leg-specific prompt + shared context\n4. Outputs collected as bead attachments or slots\n5. Synthesis polecat reads all outputs, produces final deliverable\n6. Convoy lands with unified result\n\n### Dependencies\n- Leg outputs feed synthesis (internal convoy deps)\n- Formula can specify leg ordering if needed\n- Parallel by default, sequential where required\n\n## Open Questions\n\n1. Where do formulas live? Town-level beads? Separate formula registry?\n2. How to version/share formulas across towns?\n3. Leg output format standardization?\n4. Human checkpoints between legs or only at end?\n5. Partial formula runs (skip some legs)?\n6. Formula composition (formula that includes other formulas)?\n\n## Why This Matters\n\nGas Town currently waits for humans to create work. With formulas:\n- Mayor can invoke structured reviews on any PR\n- Design work follows consistent methodology\n- Quality processes are repeatable and scalable\n- Work generation becomes as automated as work execution\n\n**Guzzoline factory, not just guzzoline consumer.**","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-31T13:19:45.702191-08:00","created_by":"mayor","updated_at":"2025-12-31T13:19:45.702191-08:00"} -{"id":"gt-ubqeg.1","title":"Code Review Convoy formula (first formula implementation)","description":"## First Formula: Code Review Convoy\n\nImplement the code review formula as proof of concept for formula molecules.\n\n### Input\n- PR number, branch, or file list\n\n### Legs (parallel polecats)\n| Leg | Focus | Output |\n|-----|-------|--------|\n| correctness | Logic errors, edge cases, off-by-ones | findings.md |\n| performance | Bottlenecks, O(n²), allocations | findings.md |\n| security | Injection, auth, data exposure | findings.md |\n| elegance | Design clarity, abstractions | findings.md |\n| resilience | Error handling, retries, timeouts | findings.md |\n| style | Conventions, naming, formatting | findings.md |\n| smells | Anti-patterns, god objects, coupling | findings.md |\n\n### Synthesis\n- Read all leg findings\n- Deduplicate overlapping issues\n- Prioritize by severity\n- Produce unified review with sections\n\n### Command\n```bash\ngt formula run code-review --pr=123\n# Creates convoy hq-cv-xxx\n# Spawns 7 polecats + 1 synthesis\n# Lands with review-summary.md\n```\n\n### Implementation Steps\n1. Define formula schema in beads\n2. gt formula run command\n3. Leg prompt templates\n4. Output collection mechanism\n5. Synthesis polecat spawning\n6. Result attachment to convoy bead","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/furiosa","created_at":"2025-12-31T13:20:03.800958-08:00","created_by":"mayor","updated_at":"2026-01-01T19:04:53.475956-08:00","closed_at":"2026-01-01T19:04:53.475956-08:00","close_reason":"Implementation already complete: code-review.formula.toml with 7 legs (correctness, performance, security, elegance, resilience, style, smells) + synthesis. Execution via gt formula run creates convoy, leg beads, and slings to polecats. Synthesis pipeline in gt synthesis start/status/close.","dependencies":[{"issue_id":"gt-ubqeg.1","depends_on_id":"gt-ubqeg","type":"parent-child","created_at":"2025-12-31T13:20:03.801936-08:00","created_by":"mayor"}]} -{"id":"gt-ubqeg.2","title":"Design Convoy formula","description":"## Design Convoy Formula\n\nStructured design exploration for features/architecture.\n\n### Input\n- Problem statement or feature request\n\n### Legs (parallel polecats)\n| Leg | Focus | Output |\n|-----|-------|--------|\n| api | Interface design, ergonomics | api-design.md |\n| data | Data model, storage, migrations | data-model.md |\n| ux | User experience, CLI ergonomics | ux-analysis.md |\n| scale | Performance at scale, bottlenecks | scalability.md |\n| security | Threat model, attack surface | security.md |\n| integration | How it fits existing system | integration.md |\n\n### Synthesis\n- Read all dimension analyses\n- Identify conflicts and tradeoffs\n- Propose unified design with options\n- Flag decisions needing human input\n\n### Command\n```bash\ngt formula run design --problem=\"Add notification levels to mayor\"\n# Creates design convoy\n# Spawns dimension polecats\n# Lands with design-doc.md\n```","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/nux","created_at":"2025-12-31T13:20:04.711715-08:00","created_by":"mayor","updated_at":"2026-01-01T19:04:05.486155-08:00","closed_at":"2026-01-01T19:04:05.486155-08:00","close_reason":"Created design convoy formula with 6 legs and synthesis step","dependencies":[{"issue_id":"gt-ubqeg.2","depends_on_id":"gt-ubqeg","type":"parent-child","created_at":"2025-12-31T13:20:04.714966-08:00","created_by":"mayor"}]} -{"id":"gt-ubqeg.3","title":"Mol Mall: Formula library and sharing","description":"## Mol Mall\n\nLibrary/marketplace for formula molecules.\n\n### Features\n- Browse available formulas\n- Formula metadata (author, version, inputs, outputs)\n- Custom formula creation\n- Formula versioning\n- Cross-town formula sharing (future)\n\n### Commands\n```bash\ngt formula list # List available formulas\ngt formula show \u003cname\u003e # Formula details\ngt formula create \u003cname\u003e # Create new formula\ngt formula edit \u003cname\u003e # Modify formula\ngt formula export \u003cname\u003e # Export for sharing\ngt formula import \u003cfile\u003e # Import shared formula\n```\n\n### Storage\n- Formulas as beads in town-level .beads/\n- type: formula\n- Structured schema for legs, synthesis, inputs\n\n### Future: Public Mol Mall\n- Central registry of community formulas\n- gt formula search 'code review'\n- gt formula install community/security-audit","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-31T13:20:15.633003-08:00","created_by":"mayor","updated_at":"2025-12-31T13:20:15.633003-08:00","dependencies":[{"issue_id":"gt-ubqeg.3","depends_on_id":"gt-ubqeg","type":"parent-child","created_at":"2025-12-31T13:20:15.633471-08:00","created_by":"mayor"}]} -{"id":"gt-ud8ej","title":"Digest: mol-deacon-patrol","description":"Patrol 209: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:52:14.306982-08:00","updated_at":"2026-01-01T16:52:14.306982-08:00","closed_at":"2026-01-01T16:52:14.306948-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-ud8ej","depends_on_id":"gt-eph-xioj","type":"parent-child","created_at":"2026-01-01T16:52:14.308267-08:00","created_by":"deacon"}]} -{"id":"gt-ufep6","title":"Add GH deployment artifacts (homebrew, npm)","description":"Add GitHub deployment artifacts to Gas Town similar to Beads setup:\n- Homebrew tap/formula for gt CLI\n- npm package for JavaScript/TypeScript users\n- GitHub Actions workflow for releases\n\nReference Beads implementation for patterns.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/crew/jack","created_at":"2026-01-02T00:11:26.219343-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-02T00:19:35.146301-08:00","closed_at":"2026-01-02T00:19:35.146301-08:00","close_reason":"Added .goreleaser.yml, npm-package/, and release.yml workflow"} -{"id":"gt-ufiy4","title":"Digest: mol-deacon-patrol","description":"Patrol 7: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:05:27.784024-08:00","updated_at":"2025-12-31T18:05:27.784024-08:00","closed_at":"2025-12-31T18:05:27.783984-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ufp4b","title":"Digest: mol-deacon-patrol","description":"Patrol 64: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:59:52.949163-08:00","updated_at":"2025-12-31T14:59:52.949163-08:00","closed_at":"2025-12-31T14:59:52.949126-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ugfyr","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 72: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:21:24.110619-08:00","updated_at":"2026-01-01T13:21:24.110619-08:00","closed_at":"2026-01-01T13:21:24.110583-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uh03p","title":"Merge: capable-mjtltnm5","description":"branch: polecat/capable-mjtltnm5\ntarget: main\nsource_issue: capable-mjtltnm5\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:34:13.804202-08:00","created_by":"gastown/polecats/capable","updated_at":"2025-12-30T23:12:37.255588-08:00","closed_at":"2025-12-30T23:12:37.255588-08:00","close_reason":"Branch already merged"} -{"id":"gt-uhc3","title":"gt mq list shows empty when MRs exist","description":"The gt mq list command returns empty results even when merge requests exist in the queue.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/rictus","created_at":"2025-12-21T17:51:18.712633-08:00","updated_at":"2025-12-29T23:55:18.491893-08:00","closed_at":"2025-12-29T23:55:18.491893-08:00","close_reason":"Fixed - mq_list.go now uses r.BeadsPath() instead of r.Path to read from the git-synced beads location"} -{"id":"gt-uhe8g","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:18:44.242008-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:21:01.985817-08:00","closed_at":"2026-01-01T19:21:01.985817-08:00","close_reason":"Merged to main at b4ff6781"} -{"id":"gt-uhpu9","title":"Session ended: gt-gastown-rockryder","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:53:38.141238-08:00","created_by":"gastown/polecats/rockryder","updated_at":"2026-01-05T00:08:31.981499-08:00","closed_at":"2026-01-05T00:08:31.981499-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/rockryder","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:53:38-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-rockryder\",\"worker\":\"rockryder\"}"} -{"id":"gt-uhqil","title":"Merge: furiosa-1766987668522","description":"branch: polecat/furiosa-1766987668522\ntarget: main\nsource_issue: furiosa-1766987668522\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-28T22:06:13.954083-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-28T22:26:43.955772-08:00","closed_at":"2025-12-28T22:26:43.955772-08:00"} -{"id":"gt-uieq4","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T18:44:18.597039-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.081044-08:00","closed_at":"2026-01-04T16:41:26.081044-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T18:44:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-uiwk7","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all witnesses/refineries healthy, burned 1 stale wisp, no callbacks, convoys in progress","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T20:25:37.374976-08:00","updated_at":"2025-12-31T20:25:37.374976-08:00","closed_at":"2025-12-31T20:25:37.374938-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ujzgp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All healthy. 3 rigs responding.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:10:58.367121-08:00","updated_at":"2026-01-01T06:10:58.367121-08:00","closed_at":"2026-01-01T06:10:58.367082-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uknj1","title":"Day 5.3: Declare liftoff or document gaps","description":"Final assessment:\n- If E2E works: Close gt-oki8p as complete, declare liftoff\n- If gaps remain: Document what's missing, file follow-on beads\n\nEither way, the 4.5 day sprint is complete.\n\nParent: gt-oki8p","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:04.078962-08:00","created_by":"mayor","updated_at":"2025-12-28T16:18:30.585977-08:00","closed_at":"2025-12-28T16:18:30.585977-08:00","dependencies":[{"issue_id":"gt-uknj1","depends_on_id":"gt-5cql0","type":"blocks","created_at":"2025-12-27T20:58:33.505769-08:00","created_by":"daemon"},{"issue_id":"gt-uknj1","depends_on_id":"gt-oki8p","type":"parent-child","created_at":"2025-12-27T20:58:39.696606-08:00","created_by":"daemon"},{"issue_id":"gt-uknj1","depends_on_id":"gt-liftoff","type":"blocks","created_at":"2025-12-27T21:43:12.64243-08:00","created_by":"daemon"}]} -{"id":"gt-um12w","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 28: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:24:09.417354-08:00","updated_at":"2026-01-01T12:24:09.417354-08:00","closed_at":"2026-01-01T12:24:09.417311-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-um4iu","title":"Enhance gt status with role hierarchy view","description":"Show identity and role hierarchy in gt status:\n\n## Current Output\nFlat list of agents by rig, no clear role hierarchy.\n\n## Desired Output\nTree structure showing:\n- Town-level roles (Mayor, Deacon)\n- Per-rig role slots with their role_bead references\n- Each agent slot with pinned work\n\nExample:\n```\nTown: gt\n├── 🎩 Mayor (gt-mayor-role)\n│ └── gt-mayor [running] → gt-u7dxq\n├── 🔔 Deacon\n│ └── gt-deacon [running]\n└── Rigs\n └── gastown/\n ├── 👁 Witness (gt-witness-role)\n │ └── gt-witness-gastown [running]\n ├── 🏭 Refinery (gt-refinery-role)\n │ └── gt-refinery-gastown [running] → (work)\n ├── 👷 Crew\n │ ├── jack [running] → gt-xxxx\n │ └── joe [running]\n └── 😺 Polecats\n └── (none)\n```\n\n## Key Changes\n1. Use tree-style indentation (├── └──)\n2. Group agents by role type\n3. Show role_bead for each role category\n4. Use emojis for quick visual scanning","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:32:55.007132-08:00","created_by":"stevey","updated_at":"2025-12-28T19:35:55.198677-08:00","closed_at":"2025-12-28T19:35:55.198677-08:00"} -{"id":"gt-um6q","title":"Update docs with molecule navigation workflow","description":"Update architecture and workflow docs with new molecule navigation.\n\n## Docs to update\n\n### docs/molecules.md\n- Add 'Navigating Molecules' section\n- Document bd mol current usage\n- Document bd close --continue workflow\n- Show the propulsion pattern\n\n### docs/propulsion-principle.md\n- Add molecule navigation as key enabler\n- Show before/after workflow comparison\n\n### docs/polecat-wisp-architecture.md\n- Update step execution section\n- Show bd close --continue in examples\n\n## New section content\n\n### Molecule Navigation\n\nFinding your place:\n bd mol current # Where am I?\n bd mol current gt-abc # Status of specific molecule\n\nSeamless transitions:\n bd close gt-abc.3 --continue # Close and advance\n bd close gt-abc.3 --no-auto # Close but don't auto-claim next\n\nThe old way (3 commands):\n bd close gt-abc.3\n bd ready --parent=gt-abc\n bd update gt-abc.4 --status=in_progress\n\nThe new way (1 command):\n bd close gt-abc.3 --continue\n\n## Blocked by (Beads features)\n- bd-sal9: bd mol current\n- bd-ieyy: bd close --continue","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-22T17:01:24.849951-08:00","updated_at":"2025-12-30T00:14:17.054559-08:00","closed_at":"2025-12-30T00:14:17.054559-08:00","close_reason":"Created three docs: molecules.md (navigation section), propulsion-principle.md (molecule navigation enabler), polecat-wisp-architecture.md (step execution with --continue)","dependencies":[{"issue_id":"gt-um6q","depends_on_id":"gt-qswb","type":"blocks","created_at":"2025-12-22T17:01:31.856627-08:00","created_by":"daemon"},{"issue_id":"gt-um6q","depends_on_id":"gt-fly0","type":"blocks","created_at":"2025-12-22T17:01:31.930072-08:00","created_by":"daemon"}]} -{"id":"gt-umims","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:25:18.540734-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.627067-08:00","closed_at":"2026-01-05T19:44:18.627067-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:25:18-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-unev","title":"Clean up ~/gt root directory cruft","description":"The town root has accumulated various directories and files that need review:\n\n**To evaluate:**\n- daemon/ - old daemon code? move or delete?\n- deacon/ - WIP deacon work? consolidate with gastown?\n- mayor/ - old mayor structure? \n- AGENTS.md - is this still used?\n- gt binary at root - should be gitignored\n\n**Already correct:**\n- .beads/, .claude/, .gastown/, .runtime/ - runtime dirs\n- beads/, gastown/ - rig directories \n- docs/hop/ - strategic docs\n- CLAUDE.md - mayor context\n\nClean up, consolidate, update .gitignore as needed.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-22T22:10:09.722561-08:00","updated_at":"2025-12-22T22:10:09.722561-08:00"} -{"id":"gt-unolx","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All healthy. 3 rigs, 6 agents pinged. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:03:36.308291-08:00","updated_at":"2026-01-01T08:03:36.308291-08:00","closed_at":"2026-01-01T08:03:36.308256-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uo07y","title":"Digest: mol-deacon-patrol","description":"Patrol complete: No callbacks, no gates, witness/refinery healthy, no orphans, clean cycle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:20:15.697744-08:00","updated_at":"2025-12-31T18:20:15.697744-08:00","closed_at":"2025-12-31T18:20:15.697713-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uo7qq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All 3 rigs healthy (beads, gastown, wyvern), no orphans, no cleanup needed, inbox clean","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:57:43.496756-08:00","updated_at":"2026-01-01T06:57:43.496756-08:00","closed_at":"2026-01-01T06:57:43.496723-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uovsl","title":"Refinery Patrol","description":"Merge queue processor patrol loop with verification gates.","status":"closed","priority":2,"issue_type":"molecule","created_at":"2025-12-26T13:08:21.419524-08:00","updated_at":"2025-12-29T20:57:41.767479-08:00","closed_at":"2025-12-29T20:57:41.767479-08:00","close_reason":"Duplicate patrol molecule beads - keeping gt-t5i07, gt-8ynws, gt-kt9qq"} -{"id":"gt-up0ow","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All 3 rigs healthy. 0 messages. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:40:29.506667-08:00","updated_at":"2026-01-01T07:40:29.506667-08:00","closed_at":"2026-01-01T07:40:29.506627-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-ur4c4","title":"Fix SQL injection in convoy panel getTrackedIssueStatus","description":"convoy.go:151-152 interpolates convoyID directly into SQL query without sanitization. Add input validation for hq-* pattern.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-30T23:21:53.410206-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-30T23:23:34.654584-08:00","closed_at":"2025-12-30T23:23:34.654584-08:00","close_reason":"Fixed in commit 4178940"} -{"id":"gt-us8","title":"Daemon: configurable heartbeat interval","description":"Heartbeat interval is hardcoded to 60s. Should be configurable via:\n- town.json config\n- Command line flag\n- Environment variable\n\nDefault 60s is reasonable but some deployments may want faster/slower.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-18T13:38:14.282216-08:00","updated_at":"2025-12-18T13:38:14.282216-08:00","dependencies":[{"issue_id":"gt-us8","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.704111-08:00","created_by":"daemon"}]} -{"id":"gt-usory","title":"Digest: mol-deacon-patrol","description":"Patrol 13: quick pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:08:49.459338-08:00","updated_at":"2025-12-31T18:08:49.459338-08:00","closed_at":"2025-12-31T18:08:49.459301-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-usytz","title":"Merge: imperator-mjwjc4ov","description":"branch: polecat/imperator-mjwjc4ov\ntarget: main\nsource_issue: imperator-mjwjc4ov\nrig: gastown\nagent_bead: gt-gastown-polecat-imperator","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:18:04.196326-08:00","created_by":"gastown/polecats/imperator","updated_at":"2026-01-01T23:37:11.741615-08:00","closed_at":"2026-01-01T23:37:11.741615-08:00","close_reason":"Branch reset to main - work superseded by existing code"} -{"id":"gt-uuf26","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T13:54:27.447048-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:41:26.2392-08:00","closed_at":"2026-01-04T16:41:26.2392-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T13:54:27-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-uv7aa","title":"Digest: mol-deacon-patrol","description":"Patrol 3: All healthy, MQ 1 pending","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:39:34.876395-08:00","updated_at":"2026-01-01T23:39:34.876395-08:00","closed_at":"2026-01-01T23:39:34.87636-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-uvga","title":"Digest: mol-deacon-patrol","description":"Patrol 16","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-24T23:10:43.578204-08:00","updated_at":"2025-12-24T23:10:43.578204-08:00","closed_at":"2025-12-24T23:10:43.57816-08:00"} -{"id":"gt-ux23f","title":"Create mol-town-shutdown molecule for clean shutdown workflow","status":"closed","priority":2,"issue_type":"feature","created_at":"2026-01-04T20:27:29.28106-08:00","created_by":"mayor","updated_at":"2026-01-06T13:19:15.596408-08:00","closed_at":"2026-01-06T13:19:15.596408-08:00","close_reason":"Updated mol-town-shutdown to v3 with full cleanup workflow"} -{"id":"gt-uxk3s","title":"Digest: mol-deacon-patrol","description":"Cycle 189: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:22:13.810821-08:00","updated_at":"2026-01-01T16:22:13.810821-08:00","closed_at":"2026-01-01T16:22:13.81079-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-uxk3s","depends_on_id":"gt-eph-pmxb","type":"parent-child","created_at":"2026-01-01T16:22:13.812244-08:00","created_by":"deacon"}]} -{"id":"gt-uxu6o","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T16:04:07.596484-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:55:59.981392-08:00","closed_at":"2026-01-01T19:55:59.981392-08:00","close_reason":"Stale MR - branch no longer exists"} -{"id":"gt-uy4ue","title":"Digest: mol-deacon-patrol","description":"Patrol 156 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:08:07.652316-08:00","updated_at":"2025-12-31T16:08:07.652316-08:00","closed_at":"2025-12-31T16:08:07.652279-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-uzer8","title":"Merge: slit-mjwohabk","description":"branch: polecat/slit-mjwohabk\ntarget: main\nsource_issue: slit-mjwohabk\nrig: gastown\nagent_bead: gt-gastown-polecat-slit","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T01:40:18.064513-08:00","created_by":"gastown/polecats/slit","updated_at":"2026-01-02T01:41:17.693493-08:00","closed_at":"2026-01-02T01:41:17.693493-08:00","close_reason":"Merged to main at 8f276feb"} -{"id":"gt-uzugs","title":"Merge: rictus-1767082306179","description":"branch: polecat/rictus-1767082306179\ntarget: main\nsource_issue: rictus-1767082306179\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T00:18:28.592046-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T01:01:04.286409-08:00","closed_at":"2025-12-30T01:01:04.286409-08:00","close_reason":"Already merged to main"} -{"id":"gt-v07fl","title":"Polecat lifecycle cleanup: stale worktrees and git tracking conflicts","description":"## Problem\n\n`bd shutdown` shows 28 polecats with uncommitted/unpushed work, but investigation reveals no actual work to preserve - it's lifecycle/tracking artifacts.\n\n## Root Causes\n\n### 1. `.beads/redirect` vs tracked `.beads/*` conflict\n- Polecats use `.beads/redirect` pointing to `../../mayor/rig/.beads`\n- But `main` branch has full `.beads/*` tracked (config.yaml, formulas/, issues.jsonl)\n- When worktree has redirect, git sees 100+ tracked files as 'deleted'\n- This is the '101 uncommitted changes' pattern\n\n### 2. Stale worktrees far behind main\n- Example: max is 67 commits behind origin/main\n- Worktrees created, used, abandoned without cleanup\n- No lifecycle process resets or cleans them\n\n### 3. `.claude/` not gitignored\n- Claude Code creates `.claude/commands/` in polecats\n- Accumulates as untracked files ('1 uncommitted change' cases)\n\n### 4. Feature branches left dangling\n- Polecat branches created but never pushed/pruned\n- Work merged via PR but branch not cleaned up\n- 'Unpushed commits' is misleading - work is on main\n\n## Fixes Needed\n\n1. Add `.claude/` to `.gitignore`\n2. Resolve `.beads/` tracking - either gitignore at rig level or commit redirect to main\n3. Witness patrol: identify stale polecats, reset/delete before shutdown\n4. Feature branch cleanup: prune remote polecat branches after merge","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2026-01-04T21:18:46.332112-08:00","created_by":"mayor","updated_at":"2026-01-04T23:43:24.032678-08:00","closed_at":"2026-01-04T23:43:24.032678-08:00","close_reason":"Fixed: .claude/ gitignore, beads runtime state untracked, stale polecat detection added (gt polecat stale)"} -{"id":"gt-v209t","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:10:22.925086-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.686167-08:00","closed_at":"2026-01-05T00:08:31.686167-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:10:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-v2brh","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 24: quick check, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T19:28:21.172408-08:00","updated_at":"2026-01-01T19:28:21.172408-08:00","closed_at":"2026-01-01T19:28:21.172374-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-v2gkv","title":"Day 1.2: Add agent-specific fields to schema","description":"Add fields for agent beads:\n- hook_bead: reference to current work (0..1 cardinality)\n- role_bead: reference to role definition (1)\n- state: agent-reported state (idle|running|stuck|stopped)\n\nParent: gt-d0jqp","notes":"Re-opened: Close reason referenced non-existent commit b5c69507. Agent fields not yet implemented in bd CLI.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-12-27T20:57:59.97079-08:00","created_by":"mayor","updated_at":"2025-12-28T00:09:45.030546-08:00","closed_at":"2025-12-28T00:09:45.030546-08:00","dependencies":[{"issue_id":"gt-v2gkv","depends_on_id":"gt-ikyo1","type":"blocks","created_at":"2025-12-27T20:58:46.995644-08:00","created_by":"daemon"},{"issue_id":"gt-v2gkv","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.590267-08:00","created_by":"daemon"}]} -{"id":"gt-v37fx","title":"Patrol exponential backoff for cost savings","description":"Agent-side backoff state tracking in patrol molecules.\n\n## State\n\nEach patrol agent tracks:\n- current_interval: current sleep duration (starts at base)\n- idle_cycles: count of cycles with no work found\n\n## Backoff Logic\n\n```\non await-signal timeout (no nudge):\n idle_cycles++\n current_interval = min(base * 2^idle_cycles, max_interval)\n\non nudge received:\n idle_cycles = 0\n current_interval = base\n wake immediately\n\non work found:\n idle_cycles = 0\n current_interval = base\n```\n\n## Where State Lives\n\nOptions:\nA. Agent bead fields (persistent across sessions)\nB. In-memory during patrol (resets on restart)\nC. Wisp fields (ephemeral but survives handoff)\n\nOption B is simplest - backoff resets when agent restarts anyway.\n\n## Depends On\n\n- gt-l6ro3.3: await-signal step type","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-28T22:14:52.633918-08:00","created_by":"mayor","updated_at":"2025-12-28T23:06:25.445583-08:00","dependencies":[{"issue_id":"gt-v37fx","depends_on_id":"gt-arjlu","type":"blocks","created_at":"2025-12-28T22:14:59.063022-08:00","created_by":"daemon"},{"issue_id":"gt-v37fx","depends_on_id":"gt-l6ro3","type":"parent-child","created_at":"2025-12-28T22:31:11.211587-08:00","created_by":"daemon"},{"issue_id":"gt-v37fx","depends_on_id":"gt-l6ro3.3","type":"blocks","created_at":"2025-12-28T23:06:30.628385-08:00","created_by":"daemon"}]} -{"id":"gt-v3bjf","title":"Digest: mol-deacon-patrol","description":"Patrol 14: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T07:28:25.96187-08:00","updated_at":"2025-12-25T07:28:25.96187-08:00","closed_at":"2025-12-25T07:28:25.961842-08:00"} -{"id":"gt-v40bm","title":"Digest: mol-deacon-patrol","description":"Patrol 243 complete: no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T17:17:03.225282-08:00","updated_at":"2026-01-01T17:17:03.225282-08:00","closed_at":"2026-01-01T17:17:03.225246-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-v4mn0","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T15:22:42.2248-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.188244-08:00","closed_at":"2026-01-04T16:41:26.188244-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T15:22:42-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-v4ydr","title":"Digest: mol-deacon-patrol","description":"Patrol 210: Deep health check - 3 witnesses, 3 refineries, 10 polecats all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:53:03.468423-08:00","updated_at":"2026-01-01T16:53:03.468423-08:00","closed_at":"2026-01-01T16:53:03.468382-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-v4ydr","depends_on_id":"gt-eph-98iu","type":"parent-child","created_at":"2026-01-01T16:53:03.469754-08:00","created_by":"deacon"}]} -{"id":"gt-v5s0j","title":"Synthesis: Combine leg outputs into final deliverable","description":"Implement synthesis step:\n1. Collect all leg outputs (findings.md files)\n2. Spawn synthesis polecat with combined context\n3. Synthesis prompt: dedupe, prioritize, format\n4. Output: review-summary.md attached to convoy bead\n5. Close convoy when synthesis complete\n\nConsider: bd slot or bd attach for outputs.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2026-01-01T14:42:57.946867-08:00","created_by":"mayor","updated_at":"2026-01-01T16:02:28.319257-08:00","closed_at":"2026-01-01T16:02:28.319257-08:00","close_reason":"Merged at 1e4cd86b","dependencies":[{"issue_id":"gt-v5s0j","depends_on_id":"gt-574qn","type":"blocks","created_at":"2026-01-01T14:43:09.968317-08:00","created_by":"mayor"}]} -{"id":"gt-v650","title":"Add handoff self-initiation protocol to role templates","description":"Agents need clear protocol for self-initiated handoff:\n\n1. Recognize: 'I should cycle now'\n2. Prepare: Summarize current state, what's next\n3. Send: gt mail send \u003cself\u003e -s '🤝 HANDOFF: ...' -m '...'\n4. Exit: End session cleanly\n\nThis replaces external 'you should cycle now' nudging.\nThe agent owns its lifecycle.\n\nInclude examples for each role type.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:46:30.987381-08:00","updated_at":"2025-12-23T14:27:07.35534-08:00"} -{"id":"gt-v6pvb","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:31:08.270282-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.755441-08:00","closed_at":"2026-01-04T16:40:22.755441-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:31:08-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-v740r","title":"Digest: mol-deacon-patrol","description":"Patrol 12 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:45:24.072649-08:00","updated_at":"2025-12-31T16:45:24.072649-08:00","closed_at":"2025-12-31T16:45:24.072606-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-v7m5j","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:20:31.381065-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.365618-08:00","closed_at":"2026-01-04T16:40:13.365618-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:20:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-v7zm7","title":"Verify commit on main before nuke (not just MERGED signal)","description":"Witness nukes on MERGED signal without verifying merge actually succeeded.\n\n## Problem\nMERGED signal means refinery ATTEMPTED merge. But:\n- Merge could have failed after signal sent\n- Merge could be to wrong branch\n- MERGED could be for stale MR (already merged via different path)\n\n## Fix\nBefore nuke, witness should verify:\n```bash\n# Get the commit SHA from the polecat branch\ncommit_sha=$(git rev-parse polecat/$name)\n\n# Verify it's reachable from main\ngit merge-base --is-ancestor $commit_sha main\n```\n\nOnly nuke if verification passes.\n\n## Alternative\nRefinery sends commit SHA in MERGED payload, witness verifies that specific SHA.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T19:07:41.077902-08:00","created_by":"mayor","updated_at":"2025-12-30T22:26:20.099107-08:00","closed_at":"2025-12-30T22:26:20.099107-08:00","close_reason":"Implemented commit verification in HandleMerged"} -{"id":"gt-v8cjr","title":"bd sync fails when .beads/redirect points to different repo","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-31T11:32:46.322314-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-31T11:36:57.651537-08:00","closed_at":"2025-12-31T11:36:57.651537-08:00","close_reason":"Duplicate - filed as bd-kvus in beads repo"} -{"id":"gt-v8ycl","title":"Digest: mol-deacon-patrol","description":"Patrol 8: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:06:20.557185-08:00","updated_at":"2025-12-28T03:06:20.557185-08:00","closed_at":"2025-12-28T03:06:20.557145-08:00"} -{"id":"gt-v9in1","title":"Merge: valkyrie-1767074338488","description":"attached_args: Code review\n\nbranch: polecat/valkyrie-1767074338488\ntarget: main\nsource_issue: valkyrie-1767074338488\nrig: gastown","notes":"CODE REVIEW (furiosa): REJECT\n\nIssue: Commit modifies CLAUDE.md which is gitignored on main.\n\nFindings:\n1. CLAUDE.md is in .gitignore (clone-specific file)\n2. CLAUDE.md is NOT tracked on main branch\n3. Polecat manager has installCLAUDETemplate() to generate this file locally per worktree\n4. The commit adds a file that should not be committed\n\nRecommendation: Do not merge. CLAUDE.md should be locally generated, not committed.\n\nThis merge request has no valid changes to merge.","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T22:04:58.408703-08:00","created_by":"gastown/polecats/valkyrie","updated_at":"2025-12-29T22:13:00.864729-08:00","closed_at":"2025-12-29T22:13:00.864729-08:00","close_reason":"REJECTED: CLAUDE.md is gitignored and clone-specific. The polecat manager generates this file locally via installCLAUDETemplate(). No valid changes to merge."} -{"id":"gt-v9mi8","title":"Digest: mol-refinery-patrol","description":"Patrol: No new branches to merge (all already cherry-picked). Archived 100+ stale MERGE_READY messages. Inbox clean.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T23:38:12.715413-08:00","updated_at":"2025-12-30T23:38:12.715413-08:00","closed_at":"2025-12-30T23:38:12.715381-08:00","close_reason":"Squashed from 11 wisps"} -{"id":"gt-vcecr","title":"gt rig status \u003crig\u003e - show status for specific rig","description":"Show detailed status for a specific rig including all workers (witness, refinery, polecats, crew).","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-02T11:49:53.248806-08:00","created_by":"mayor","updated_at":"2026-01-02T12:46:01.328223-08:00","closed_at":"2026-01-02T12:46:01.328223-08:00","close_reason":"Implemented gt rig status \u003crig\u003e command","dependencies":[{"issue_id":"gt-vcecr","depends_on_id":"gt-yyht4","type":"blocks","created_at":"2026-01-02T11:50:01.804923-08:00","created_by":"mayor"}]} -{"id":"gt-vco0p","title":"Digest: mol-deacon-patrol","description":"Patrol 140: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:39:27.083291-08:00","updated_at":"2026-01-01T14:39:27.083291-08:00","closed_at":"2026-01-01T14:39:27.083259-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vcvyd","title":"Mayor session ID shows gt-mayor instead of hq-mayor","description":"In status.go lines 547-549, AgentBeadID() is called for global agents (mayor/deacon) which uses the 'gt' prefix. Should use MayorBeadIDTown()/DeaconBeadIDTown() which return 'hq-mayor'/'hq-deacon'. The fix: check if role is 'mayor' or 'deacon' and use the Town functions, or use AgentBeadIDWithPrefix('hq', '', role, '') for global agents.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-05T16:27:03.628815-08:00","created_by":"mayor","updated_at":"2026-01-05T16:30:37.1357-08:00","closed_at":"2026-01-05T16:30:37.1357-08:00","close_reason":"Fixed: Use AgentBeadIDWithPrefix with TownBeadsPrefix for global agents"} -{"id":"gt-vcyt7","title":"Merge: gt-bca67","description":"branch: polecat/furiosa-mjtj9d4g\ntarget: main\nsource_issue: gt-bca67\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-30T20:53:46.618988-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T23:12:30.863987-08:00","closed_at":"2025-12-30T23:12:30.863987-08:00","close_reason":"Branch already merged"} -{"id":"gt-vd6e6","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:34:15.603021-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:18.73228-08:00","closed_at":"2026-01-05T19:44:18.73228-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:34:15-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-vdprb","title":"Feed-Based Wake Model for Patrol Agents","description":"## The Paradigm Shift\n\n\u003e **Backoff is not about polling less. It is about waiting for signals with a timeout.**\n\nThis epic captures the shift from time-driven to event-driven patrol wake.\n\n## Key Insight (Recovered from 2025-12-29 session crash)\n\nThe Beads activity feed (bd activity --follow) is the universal data plane for\nwake signals. Every meaningful action creates a beads mutation; agents subscribe to\nthe feed and wake within ~500ms. The timeout is just a safety net.\n\n**OLD**: Time-driven. Wake because time passed. Poll less when idle.\n**NEW**: Event-driven. Wake because signal arrived. Timeout is safety net.\n\n## Architecture\n\nANY MUTATION:\n bd create/update/close -\u003e issues.jsonl mutation\n -\u003e bd activity --follow sees it (~500ms)\n -\u003e All subscribed agents wake immediately\n\nPATROL AGENT:\n Runs bd activity --follow as background source\n Any output line = wake signal\n Timeout expiry = safety net (not primary wake)\n\n## Wake Sources (Priority Order)\n\n| Source | Latency | Purpose |\n|--------|---------|---------|\n| Feed | ~500ms | Primary - any beads mutation |\n| Nudge | Instant | Explicit wake (startup hooks) |\n| Timeout | Backoff | Safety net for missed signals |\n| Daemon | 5-60min | GUPP backstop, session recovery |\n\n## Key Design Decisions\n\n1. No wake_on conditions - signals carry no semantic meaning. Just wake up.\n Agent discovers reality by checking mail, beads, hook, git state.\n\n2. Read-only commands do not wake - gt status, bd show create no mutations.\n\n3. Daemon is recovery-focused - catches edge cases (GUPP violations, dead sessions).\n\n4. Keepalive file deprecated - the feed replaces the keepalive mechanism.\n\n## Reference\n\n- ~/gt/docs/patrol-system-design.md (Sleeping Agents section)\n- ~/gt/docs/PRIMING.md (Feed Is the Signal insight)\n\n## Related\n\n- gt-l6ro3: Patrol Exponential Backoff System (backoff timing, complements this)","status":"closed","priority":1,"issue_type":"epic","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T17:02:14.195425-08:00","created_by":"mayor","updated_at":"2025-12-30T22:10:00.772809-08:00","closed_at":"2025-12-30T22:10:00.772809-08:00","close_reason":"Feed-based wake model complete: patrol agents subscribe to bd activity --follow, daemon uses fixed 10-min recovery heartbeat, keepalive file infrastructure removed"} -{"id":"gt-vdprb.1","title":"Patrol agents subscribe to bd activity --follow","description":"Each patrol agent (Deacon, Witness, Refinery) should run bd activity --follow as a background process. Any output line is a wake signal. This is the primary wake mechanism.\n\nImplementation:\n1. Add feed subscription to await-signal step logic\n2. Agent starts bd activity --follow on entering await-signal\n3. Any line of output breaks the wait immediately\n4. Timeout still applies as safety net\n\nSee patrol-system-design.md for full specification.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T17:02:47.872208-08:00","created_by":"mayor","updated_at":"2025-12-29T21:58:33.934123-08:00","closed_at":"2025-12-29T21:58:33.934123-08:00","close_reason":"Implemented await-signal command that subscribes to bd activity --follow","dependencies":[{"issue_id":"gt-vdprb.1","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:02:47.872866-08:00","created_by":"mayor"},{"issue_id":"gt-vdprb.1","depends_on_id":"gt-l6ro3.3","type":"blocks","created_at":"2025-12-29T17:08:56.137406-08:00","created_by":"mayor"}]} -{"id":"gt-vdprb.2","title":"Remove keepalive file infrastructure","description":"The keepalive mechanism (~/gt/daemon/activity.json) is deprecated in favor of feed-based wake.\n\nTODO:\n1. Remove keepalive.TouchTownActivity() calls from gt commands\n2. Remove keepalive.ReadTownActivity() from daemon\n3. Delete internal/keepalive package\n4. Update daemon to use longer base heartbeat (recovery-focused)\n\nWhitelist consideration: Some read-only commands might need to wake (TBD - none identified yet)","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2025-12-29T17:03:10.887382-08:00","created_by":"mayor","updated_at":"2025-12-30T22:09:38.858765-08:00","closed_at":"2025-12-30T22:09:38.858765-08:00","close_reason":"Removed keepalive infrastructure: TouchTownActivity/ReadTownActivity deleted from keepalive.go, activity-based backoff removed from daemon.go (now uses fixed 10-min recovery interval), PersistentPreRun hook removed from root.go","dependencies":[{"issue_id":"gt-vdprb.2","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:03:10.888084-08:00","created_by":"mayor"},{"issue_id":"gt-vdprb.2","depends_on_id":"gt-vdprb.4","type":"blocks","created_at":"2025-12-29T17:09:11.896659-08:00","created_by":"mayor"}]} -{"id":"gt-vdprb.3","title":"Startup hooks nudge Deacon","description":"When a new Claude session starts (via startup hook), it should nudge Deacon so Deacon knows a new agent has appeared. This is one of Deacons extra wake sources for GUPP backstop.\n\nImplementation: Add gt nudge deacon session-started to the startup hook chain.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-29T17:03:17.160315-08:00","created_by":"mayor","updated_at":"2025-12-29T18:01:16.924201-08:00","closed_at":"2025-12-29T18:01:16.924201-08:00","close_reason":"Implemented: Added gt nudge deacon session-started to startup hooks, with special deacon target handling in nudge.go","dependencies":[{"issue_id":"gt-vdprb.3","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:03:17.160964-08:00","created_by":"mayor"},{"issue_id":"gt-vdprb.3","depends_on_id":"gt-vdprb.1","type":"blocks","created_at":"2025-12-29T17:09:40.073828-08:00","created_by":"mayor"}]} -{"id":"gt-vdprb.4","title":"Daemon heartbeat becomes recovery-focused","description":"Update daemon heartbeat to be recovery-focused, not wake-focused.\n\nCurrent: Daemon pokes agents every 5-60min as primary wake.\nNew: Daemon only checks for:\n- Dead sessions that need restart\n- Agents with work-on-hook not progressing (GUPP violation)\n- Orphaned work\n\nFeed handles normal wake; daemon is the safety net for edge cases.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/slit","created_at":"2025-12-29T17:03:23.47806-08:00","created_by":"mayor","updated_at":"2025-12-29T18:02:43.851199-08:00","closed_at":"2025-12-29T18:02:43.851199-08:00","close_reason":"Implemented recovery-focused daemon heartbeat: removed poke functions, added GUPP violation and orphaned work checks","dependencies":[{"issue_id":"gt-vdprb.4","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:03:23.478825-08:00","created_by":"mayor"},{"issue_id":"gt-vdprb.4","depends_on_id":"gt-vdprb.1","type":"blocks","created_at":"2025-12-29T17:09:05.198482-08:00","created_by":"mayor"}]} -{"id":"gt-vdprb.5","title":"Documentation: Feed-based wake model","description":"Document the feed-based wake model in patrol-system-design.md and PRIMING.md.\n\nDONE (2025-12-29):\n- Updated patrol-system-design.md with full feed-based wake specification\n- Added Feed Is the Signal and Discover Dont Be Told insights to PRIMING.md\n- Committed as 39e46148","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T17:03:56.043996-08:00","created_by":"mayor","updated_at":"2025-12-29T17:04:01.193795-08:00","closed_at":"2025-12-29T17:04:01.193795-08:00","close_reason":"Completed 2025-12-29, commit 39e46148","dependencies":[{"issue_id":"gt-vdprb.5","depends_on_id":"gt-vdprb","type":"parent-child","created_at":"2025-12-29T17:03:56.044684-08:00","created_by":"mayor"}]} -{"id":"gt-vdv0w","title":"Digest: mol-deacon-patrol","description":"Patrol 3: Routine. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:33:34.414794-08:00","updated_at":"2026-01-01T22:33:34.414794-08:00","closed_at":"2026-01-01T22:33:34.414758-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-veez1","title":"Merge: rictus-mjtlq9xg","description":"branch: polecat/rictus-mjtlq9xg\ntarget: main\nsource_issue: rictus-mjtlq9xg\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:14:01.912377-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-30T23:12:42.99434-08:00","closed_at":"2025-12-30T23:12:42.99434-08:00","close_reason":"Branch already merged"} -{"id":"gt-veswi","title":"Add 'spawn' as alias for 'start' subcommand across all roles","description":"Agents are guessing 'spawn' when trying to start roles (witness, refinery, etc). Need to add 'spawn' as an alias for 'start' for consistency.\n\nAffected commands:\n- gt witness start → also gt witness spawn\n- gt refinery start → also gt refinery spawn\n- gt polecat start → also gt polecat spawn\n- gt crew start → also gt crew spawn\n\nImplementation: Add Aliases field to cobra commands.","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/toast","created_at":"2026-01-02T02:07:02.73948-08:00","created_by":"mayor","updated_at":"2026-01-02T17:16:43.738428-08:00","closed_at":"2026-01-02T17:16:43.738428-08:00","close_reason":"Added spawn alias to witness, refinery, deacon, and crew start commands"} -{"id":"gt-vf685","title":"Digest: mol-deacon-patrol","description":"Patrol 43: All healthy, 6 agents pinged","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:18:27.56235-08:00","updated_at":"2026-01-01T02:18:27.56235-08:00","closed_at":"2026-01-01T02:18:27.562313-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vg4n","title":"Use Beads issue status as spawn source of truth","description":"Currently witness tracks spawned issues in .gastown/witness.json to prevent re-spawning:\n\n{\"spawned_issues\": [\"gt-abc1\", \"gt-def2\", ...]}\n\nThis is redundant with Beads issue status (in_progress). The witness could query:\n bd list --status=in_progress\n\nThe local list serves as a performance cache to avoid querying beads every cycle. Consider:\n1. Use Beads as source of truth\n2. Keep local cache with TTL\n3. Sync cache on witness start\n\nThis simplifies state management and ensures consistency.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-21T22:07:31.756863-08:00","updated_at":"2025-12-21T22:07:31.756863-08:00"} -{"id":"gt-vgn4e","title":"Session: gt-gastown-test2 completed gt-f7jxr","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-02T13:21:45.621558-08:00","created_by":"gastown/polecats/capable","updated_at":"2026-01-02T13:23:05.784664-08:00","closed_at":"2026-01-02T13:23:05.784664-08:00","close_reason":"Test cleanup","event_kind":"session.ended","actor":"gastown/polecats/test2","target":"gt-f7jxr","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-02T13:21:45-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-test2\",\"worker\":\"test2\"}"} -{"id":"gt-vgtbq","title":"Session ended: gt-gastown-immortan","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:38:06.729446-08:00","created_by":"gastown/polecats/immortan","updated_at":"2026-01-04T16:40:22.917965-08:00","closed_at":"2026-01-04T16:40:22.917965-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/immortan","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:38:06-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-immortan\",\"worker\":\"immortan\"}"} -{"id":"gt-vh61f","title":"Merge: furiosa-mjtj9d4g","description":"branch: polecat/furiosa-mjtj9d4g\ntarget: main\nsource_issue: furiosa-mjtj9d4g\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T22:39:23.311696-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T23:12:37.075995-08:00","closed_at":"2025-12-30T23:12:37.075995-08:00","close_reason":"Branch already merged"} -{"id":"gt-viuj4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:45:30.089931-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.936845-08:00","closed_at":"2026-01-05T00:08:31.936845-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:45:30-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-vjcbo","title":"Digest: mol-deacon-patrol","description":"Patrol 20: final cycle","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T06:13:45.223964-08:00","updated_at":"2025-12-28T06:13:45.223964-08:00","closed_at":"2025-12-28T06:13:45.223931-08:00"} -{"id":"gt-vkhm4","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:01:45.789272-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:22.650386-08:00","closed_at":"2026-01-04T16:40:22.650386-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:01:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-vkiv2","title":"Merge: rictus-1767079818240","description":"branch: polecat/rictus-1767079818240\ntarget: main\nsource_issue: rictus-1767079818240\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-29T23:43:45.192283-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T23:55:11.824987-08:00","closed_at":"2025-12-29T23:55:11.824987-08:00","close_reason":"Stale MR from nuked polecat"} -{"id":"gt-vkmpf","title":"Digest: mol-deacon-patrol","description":"Patrol 12: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:43:21.209794-08:00","updated_at":"2025-12-26T18:43:21.209794-08:00","closed_at":"2025-12-26T18:43:21.209749-08:00"} -{"id":"gt-vl3zr","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:49:39.641829-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T19:44:18.536503-08:00","closed_at":"2026-01-05T19:44:18.536503-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:49:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-vla7c","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: All rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T05:07:00.704541-08:00","updated_at":"2026-01-01T05:07:00.704541-08:00","closed_at":"2026-01-01T05:07:00.704505-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vm85o","title":"Mol Mall: Formula Package Registry","description":"A package registry for sharing and discovering formulas, schematics, and protocols.\n\n## Concept\n\nLike npm/Maven/Go modules but for workflow definitions.\n\n```\nmol-mall.io/\n├── @gastown/ # Official Gas Town formulas\n│ ├── shiny\n│ ├── polecat-work\n│ └── release\n├── @acme-corp/ # Enterprise org (private)\n│ └── compliance-review\n├── @linus/ # Individual publisher\n│ └── kernel-review\n└── community/ # Unscoped public formulas\n └── towers-of-hanoi\n```\n\n## Resolution Hierarchy\n\n```\n1. Project: ./.beads/formulas/ # Project-specific\n2. Rig: ~/gt/\u003crig\u003e/.formulas/ # Rig-wide\n3. Town: ~/gt/.formulas/ # Town-wide (mayor stdlib)\n4. User: ~/.gastown/formulas/ # Personal collection\n5. Mall: mol-mall.io/ # Published packages\n```\n\n## Package Manifest\n\n```toml\n[package]\nname = \"shiny\"\nversion = \"1.2.0\"\ndescription = \"Engineer in a Box\"\nauthors = [\"Gas Town \u003cgastown@example.com\u003e\"]\nlicense = \"MIT\"\n\n[dependencies]\n\"@gastown/review-patterns\" = \"^2.0\"\n```\n\n## Distribution Scenarios\n\n1. **Celebrity Formulas**: Expert-curated workflows (e.g., Linus kernel review)\n2. **Enterprise Compliance**: Private company formulas\n3. **Standard Library**: @gastown/* blessed defaults\n4. **Community Ecosystem**: Varying quality, needs ratings/verification\n\n## Open Questions\n\n1. Versioning semantics - SemVer? Breaking change rules?\n2. Security model - sandboxing? signing? permissions?\n3. Private registries - self-hosted? authentication?\n4. Lock files - formulas.lock format?\n\n## Related\n\n- docs/formula_evolution.md - package ecosystem parallel section\n- gt-8ws7o - Schematic (can be published)\n- gt-y3jb9 - Protocol (can be published)\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:01:24.551028-08:00","updated_at":"2025-12-28T22:33:22.25303-08:00","closed_at":"2025-12-28T22:33:22.25303-08:00"} -{"id":"gt-vnryt","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:29:45.71429-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:31:49.46659-08:00","closed_at":"2026-01-01T19:31:49.46659-08:00","close_reason":"Merged to main at 937ee2c8"} -{"id":"gt-vo4u9","title":"Session ended: gt-gastown-crew-george","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:48:15.648798-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T16:41:37.833516-08:00","closed_at":"2026-01-04T16:41:37.833516-08:00","close_reason":"Archived","event_kind":"session.ended","actor":"gastown/crew/george","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:48:15-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-george\",\"worker\":\"george\"}"} -{"id":"gt-vo6k8","title":"Session ended: gt-gastown-wasteland","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:50:10.977149-08:00","created_by":"gastown/polecats/wasteland","updated_at":"2026-01-05T00:08:31.532236-08:00","closed_at":"2026-01-05T00:08:31.532236-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/wasteland","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:50:10-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-wasteland\",\"worker\":\"wasteland\"}"} -{"id":"gt-vo7m8","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:56:41.018454-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:22.699768-08:00","closed_at":"2026-01-04T16:40:22.699768-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:56:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-vpupp","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T17:12:04.767443-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:12:04.818793-08:00","closed_at":"2026-01-06T17:12:04.818793-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T17:12:04-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-vrcnt","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:50:01.516772-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-04T16:40:13.542936-08:00","closed_at":"2026-01-04T16:40:13.542936-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:50:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-vre6m","title":"Digest: mol-deacon-patrol","description":"Patrol 150: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:01:23.852436-08:00","updated_at":"2026-01-01T15:01:23.852436-08:00","closed_at":"2026-01-01T15:01:23.852401-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vs50k","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:44:10.20478-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.710216-08:00","closed_at":"2026-01-05T19:44:18.710216-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:44:10-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-vsdg7","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 1: 17 sessions healthy, 3 agents responded to health check, all core systems normal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:54:17.778138-08:00","updated_at":"2026-01-01T09:54:17.778138-08:00","closed_at":"2026-01-01T09:54:17.778106-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vsp20","title":"Digest: mol-deacon-patrol","description":"Patrol #11: Quick cycle, all quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:20:03.791132-08:00","updated_at":"2025-12-31T19:20:03.791132-08:00","closed_at":"2025-12-31T19:20:03.791091-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vti9e","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T14:08:48.247113-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.216737-08:00","closed_at":"2026-01-04T16:41:26.216737-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T14:08:48-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-vtlh6","title":"Merge: corpus-mk0ce8r5","description":"branch: polecat/corpus-mk0ce8r5\ntarget: main\nsource_issue: corpus-mk0ce8r5\nrig: gastown\nagent_bead: gt-gastown-polecat-corpus\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T15:17:41.696567-08:00","created_by":"gastown/polecats/corpus","updated_at":"2026-01-04T15:19:12.376941-08:00","closed_at":"2026-01-04T15:19:12.376941-08:00","close_reason":"Merged to main at 095a426e"} -{"id":"gt-vurfr","title":"Refactor: Extract ExecWithOutput utility for command execution","description":"Repeated pattern across witness/handlers.go and refinery/manager.go:\n\n```go\ncmd := exec.Command(\"bd\", args...)\ncmd.Dir = workDir\nvar stdout, stderr bytes.Buffer\ncmd.Stdout = \u0026stdout\ncmd.Stderr = \u0026stderr\nif err := cmd.Run(); err != nil { ... stderr.String() ... }\n```\n\nExtract to internal/util/exec.go:\n```go\nfunc ExecWithOutput(workDir, cmd string, args ...string) (stdout string, err error)\n```\n\nFiles with duplicates:\n- internal/witness/handlers.go (multiple locations)\n- internal/refinery/manager.go:506-542 (gitRun/gitOutput)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/wraith","created_at":"2026-01-04T23:46:10.558165-08:00","created_by":"gastown/polecats/buzzard","updated_at":"2026-01-05T00:18:54.949025-08:00","closed_at":"2026-01-05T00:18:54.949025-08:00","close_reason":"Implemented ExecWithOutput/ExecRun utilities and refactored handlers.go and manager.go"} -{"id":"gt-vv5hw","title":"Merge: nux-mk1usptu","description":"branch: polecat/nux-mk1usptu\ntarget: main\nsource_issue: nux-mk1usptu\nrig: gastown\nagent_bead: gt-gastown-polecat-nux\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-05T16:33:30.822524-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-05T19:18:55.527502-08:00","closed_at":"2026-01-05T19:18:55.527502-08:00","close_reason":"Merged to main at b88d3e8e"} -{"id":"gt-vve6k","title":"Merge: dag-mjxpcv5v","description":"branch: polecat/dag-mjxpcv5v\ntarget: main\nsource_issue: dag-mjxpcv5v\nrig: gastown\nagent_bead: gt-gastown-polecat-dag","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:52:32.804763-08:00","created_by":"gastown/polecats/dag","updated_at":"2026-01-02T18:55:06.87786-08:00","closed_at":"2026-01-02T18:55:06.87786-08:00","close_reason":"Merged to main at 92106afd"} -{"id":"gt-vw2x8","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:41:46.564975-08:00","updated_at":"2026-01-01T10:41:46.564975-08:00","closed_at":"2026-01-01T10:41:46.564942-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vwjz6","title":"BUG: Handoff beads stay hooked after processing","description":"During shutdown cleanup, found 34 handoff beads with status=hooked that should have been cleared.\n\nThese are processed handoff messages where:\n1. Agent received and processed the handoff\n2. But the hooked status was never cleared\n\nExpected: After handoff is processed, bead should be closed or status reset.\nActual: Beads remain status=hooked indefinitely.\n\nEvidence: SELECT from issues WHERE status=hooked AND title LIKE '%HANDOFF%' returned 34 rows","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/citadel","created_at":"2026-01-04T20:38:34.528988-08:00","created_by":"mayor","updated_at":"2026-01-05T00:16:53.740453-08:00","closed_at":"2026-01-05T00:16:53.740453-08:00","close_reason":"Closed"} -{"id":"gt-vx2qv","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 9: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:07.233471-08:00","updated_at":"2025-12-28T11:22:07.233471-08:00","closed_at":"2025-12-28T11:22:07.233434-08:00"} -{"id":"gt-vx8ex","title":"Merge: rictus-mjvtzdm2","description":"branch: polecat/rictus-mjvtzdm2\ntarget: main\nsource_issue: rictus-mjvtzdm2\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T11:26:42.539509-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T11:28:38.550123-08:00","closed_at":"2026-01-01T11:28:38.550123-08:00","close_reason":"Merged to main at 3672e659"} -{"id":"gt-vxlw2","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 52: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:57:34.169928-08:00","updated_at":"2026-01-01T12:57:34.169928-08:00","closed_at":"2026-01-01T12:57:34.169892-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vxv0u","title":"gt rig park/unpark commands","description":"Implement Level 1 (local/ephemeral) rig control.\n\nCommands:\n- gt rig park \u003crig\u003e # Set status=parked in wisp layer\n- gt rig unpark \u003crig\u003e # Remove from wisp layer\n\nBehavior:\n- Stops witness/refinery if running\n- Daemon respects parked status (no auto-restart)\n- Only affects this town\n- Ephemeral (disappears on wisp cleanup)\n\nOutput:\n gt rig park gastown\n ✓ Rig gastown parked (local only)\n Witness stopped\n Refinery stopped\n Daemon will not auto-restart","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T17:36:46.479681-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T17:36:46.479681-08:00","dependencies":[{"issue_id":"gt-vxv0u","depends_on_id":"gt-emh1c","type":"blocks","created_at":"2026-01-06T17:37:07.227101-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-vxw4q","title":"Digest: mol-deacon-patrol","description":"Patrol #7: nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:21:49.832209-08:00","updated_at":"2025-12-31T06:21:49.832209-08:00","closed_at":"2025-12-31T06:21:49.832175-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-vyfvi","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: Witnessed escalation re: 14 polecats with unpushed work. All agents healthy. No pending work.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:45:46.369575-08:00","updated_at":"2025-12-30T15:45:46.369575-08:00","closed_at":"2025-12-30T15:45:46.369534-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-w0fqg","title":"Agent bead IDs should use rig prefix, not hardcoded gt-","description":"When spawning beads polecats, agent bead creation fails:\n\n```\nError: invalid agent ID: agent ID must start with 'gt-' (got \"bd-beads-polecat-pearl\")\n```\n\nThe validation is hardcoded to expect 'gt-' but beads rig uses 'bd-' prefix.\n\nFix: Agent bead ID validation should accept the rig's configured prefix, not hardcode 'gt-'.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/slit","created_at":"2025-12-30T22:19:17.47331-08:00","created_by":"mayor","updated_at":"2025-12-30T23:06:02.565933-08:00","closed_at":"2025-12-30T23:06:02.565933-08:00","close_reason":"Fixed agent bead ID validation in beads CLI to accept any prefix, and updated gastown's witness/handlers.go and cmd/crew_lifecycle.go to use rig prefix"} -{"id":"gt-w1d48","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All 3 rigs healthy. 0 messages. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:39:27.282584-08:00","updated_at":"2026-01-01T07:39:27.282584-08:00","closed_at":"2026-01-01T07:39:27.282543-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-w1te9","title":"gt nudge should accept role shortcuts like 'mayor' not just 'gt-mayor'","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/dag","created_at":"2025-12-30T19:33:00.115571-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:34:03.737514-08:00","closed_at":"2025-12-30T22:34:03.737514-08:00","close_reason":"Implemented role shortcuts (mayor, witness, refinery) that expand to session names"} -{"id":"gt-w2rbg","title":"BUG: gt polecat nuke also tries to nuke rig/rig (e.g. gastown/gastown)","description":"When running 'gt polecat nuke \u003cname\u003e \u003crig\u003e --force', it successfully nukes the polecat but then also attempts to nuke '\u003crig\u003e/\u003crig\u003e' (e.g. gastown/gastown).\n\nExample output:\n ⚠ Nuking gastown/angharad (--force)...\n ✓ killed session\n ...\n ⚠ Nuking gastown/gastown (--force)...\n ○ worktree already gone\n\nThis is harmless but indicates a bug in argument parsing or loop logic.","status":"closed","priority":3,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2026-01-02T01:46:58.153156-08:00","created_by":"mayor","updated_at":"2026-01-02T13:51:51.004206-08:00","closed_at":"2026-01-02T13:51:51.004206-08:00","close_reason":"Fixed: Added validation requiring rig/polecat format for nuke and remove commands"} -{"id":"gt-w2rd3","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:02:06.581991-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:02:06.635336-08:00","closed_at":"2026-01-06T13:02:06.635336-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:02:05-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-w3idb","title":"Session ended: gt-gastown-chumbucket","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:39:28.001136-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T16:40:13.339884-08:00","closed_at":"2026-01-04T16:40:13.339884-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/chumbucket","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:39:27-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-chumbucket\",\"worker\":\"chumbucket\"}"} -{"id":"gt-w3wgx","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:56:02.95887-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:40:22.836986-08:00","closed_at":"2026-01-04T16:40:22.836986-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:56:02-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-w41ln","title":"E2E Test: Add a comment to internal/util/process.go","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T16:16:17.43602-08:00","created_by":"stevey","updated_at":"2025-12-28T16:21:56.724387-08:00","closed_at":"2025-12-28T16:21:56.724387-08:00"} -{"id":"gt-w4v1o","title":"Merge: furiosa-dogs","description":"branch: polecat/furiosa-dogs\ntarget: main\nsource_issue: furiosa-dogs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T11:01:55.022205-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-31T02:00:37.377861-08:00","closed_at":"2025-12-31T02:00:37.377861-08:00","close_reason":"Branch no longer exists on remote"} -{"id":"gt-w4whx","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 7","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:02:18.790097-08:00","updated_at":"2026-01-01T20:02:18.790097-08:00","closed_at":"2026-01-01T20:02:18.79005-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-w5xj2","title":"Show active workers in gt convoy status output","description":"Enhance convoy status to show which workers are currently assigned to tracked issues.\n\nCURRENT OUTPUT:\n Tracked Issues:\n ○ gt-xyz: Fix bug [task]\n ○ gt-abc: Add feature [task]\n\nDESIRED OUTPUT:\n Tracked Issues:\n ○ gt-xyz: Fix bug [task]\n ○ gt-abc: Add feature [task] @gastown/nux (12m)\n\n Active Workers (the swarm):\n gastown/nux gt-abc running 12m\n beads/amber bd-def running 5m\n\nIMPLEMENTATION:\n1. Query hooked molecules to find workers with tracked issues\n2. Match issue IDs to tracked issues\n3. Show worker assignments inline and/or in separate section\n\nFile: internal/cmd/convoy.go (runConvoyStatus)","status":"closed","priority":3,"issue_type":"feature","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T19:37:18.833896-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T19:29:08.254008-08:00","closed_at":"2026-01-01T19:29:08.254008-08:00","close_reason":"Added worker display to convoy status with inline @worker (age) format"} -{"id":"gt-w631c.1","title":"Test Polecat Arm","description":"Test child for bonding pattern","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:57:47.004005-08:00","updated_at":"2025-12-25T01:33:00.170605-08:00","closed_at":"2025-12-25T01:33:00.170605-08:00","dependencies":[{"issue_id":"gt-w631c.1","depends_on_id":"gt-w631c","type":"parent-child","created_at":"2025-12-25T00:57:47.004473-08:00","created_by":"daemon"}]} -{"id":"gt-w64lr","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:48:00.401114-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T19:44:18.551986-08:00","closed_at":"2026-01-05T19:44:18.551986-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:47:55-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-w66v4","title":"Test refile v2","description":"Testing improved refile\n\n(Refiled from bd-eysh)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-31T13:00:30.636104-08:00","created_by":"beads/crew/grip","updated_at":"2025-12-31T13:00:48.891118-08:00","closed_at":"2025-12-31T13:00:48.891118-08:00","close_reason":"Test cleanup"} -{"id":"gt-w6ikk","title":"Digest: mol-deacon-patrol","description":"Patrol 139: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:39:02.281887-08:00","updated_at":"2026-01-01T14:39:02.281887-08:00","closed_at":"2026-01-01T14:39:02.281852-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-w98d","title":"witness Handoff","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-23T16:23:42.292529-08:00","updated_at":"2025-12-27T18:14:41.837335-08:00"} -{"id":"gt-w9o1s","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 70: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:19:38.625975-08:00","updated_at":"2026-01-01T13:19:38.625975-08:00","closed_at":"2026-01-01T13:19:38.625936-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-w9x9j","title":"Digest: mol-deacon-patrol","description":"Patrol 148: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:59:38.430777-08:00","updated_at":"2026-01-01T14:59:38.430777-08:00","closed_at":"2026-01-01T14:59:38.430743-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wah8i","title":"Fix N+1 query problem in convoy status fetching","description":"getTrackedIssueStatus spawns a new bd show for each tracked issue. With 10 convoys x 5 issues = 50+ subprocesses every 10s. Consider batching or caching.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/max","created_at":"2025-12-30T23:21:55.510319-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-30T23:26:28.705522-08:00","closed_at":"2025-12-30T23:26:28.705522-08:00","close_reason":"Fixed with batched bd show call"} -{"id":"gt-wbqxz","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 5: Routine.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:01:27.187451-08:00","updated_at":"2026-01-01T20:01:27.187451-08:00","closed_at":"2026-01-01T20:01:27.187415-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-wcpds","title":"Digest: mol-deacon-patrol","description":"Cycle 183: All agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:19:57.813476-08:00","updated_at":"2026-01-01T16:19:57.813476-08:00","closed_at":"2026-01-01T16:19:57.813444-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-wcpds","depends_on_id":"gt-eph-r30e","type":"parent-child","created_at":"2026-01-01T16:19:57.814783-08:00","created_by":"deacon"}]} -{"id":"gt-wd0oi","title":"Remove unused AgentPresetInfo fields or wire them up","description":"AgentPresetInfo defines fields not yet used:\n- SessionIDEnv\n- ResumeFlag, ResumeStyle \n- NonInteractive\n\nEither remove until needed or wire up to spawn/exec paths.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T13:05:28.565626-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T13:09:06.019723-08:00","closed_at":"2026-01-04T13:09:06.019723-08:00","close_reason":"Fields are intentionally designed for session resume - covered by gt-r2eg1"} -{"id":"gt-wfopk","title":"Merge: gt-znma3","description":"branch: polecat/nux-mjtnycav\ntarget: main\nsource_issue: gt-znma3\nrig: gastown\nagent_bead: gt-gastown-polecat-nux","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-30T23:04:09.100019-08:00","created_by":"gastown/polecats/nux","updated_at":"2025-12-30T23:12:09.191591-08:00","closed_at":"2025-12-30T23:12:09.191591-08:00","close_reason":"Branch already merged to main"} -{"id":"gt-wfuve","title":"Merge: nux-1767087680976","description":"branch: polecat/nux-1767087680976\ntarget: main\nsource_issue: nux-1767087680976\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T13:57:05.359055-08:00","created_by":"mayor","updated_at":"2025-12-30T18:23:22.185449-08:00","closed_at":"2025-12-30T18:23:22.185449-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-whrlq","title":"Digest: mol-deacon-patrol","description":"Patrol 4: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:04:29.713193-08:00","updated_at":"2025-12-28T03:04:29.713193-08:00","closed_at":"2025-12-28T03:04:29.713159-08:00"} -{"id":"gt-wisp-0it","title":"Handle test failures","description":"**VERIFICATION GATE**: This step enforces the Beads Promise.\n\nIf tests PASSED: This step auto-completes. Proceed to merge.\n\nIf tests FAILED:\n1. Diagnose: Is this a branch regression or pre-existing on main?\n2. If branch caused it:\n - Abort merge\n - Notify polecat: \"Tests failing. Please fix and resubmit.\"\n - Skip to loop-check\n3. If pre-existing on main:\n - Option A: Fix it yourself (you're the Engineer!)\n - Option B: File a bead: bd create --type=bug --priority=1 --title=\"...\"\n\n**GATE REQUIREMENT**: You CANNOT proceed to merge-push without:\n- Tests passing, OR\n- Fix committed, OR\n- Bead filed for the failure\n\nThis is non-negotiable. Never disavow. Never \"note and proceed.\" ","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T16:54:47.658769-08:00","updated_at":"2026-01-04T16:54:47.658769-08:00"} -{"id":"gt-wisp-1hn","title":"Run test suite","description":"Run the test suite.\n\n```bash\ngo test ./...\n```\n\nTrack results: pass count, fail count, specific failures.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T16:44:56.543009-08:00","updated_at":"2026-01-04T16:44:56.543009-08:00","dependencies":[{"issue_id":"gt-wisp-1hn","depends_on_id":"gt-wisp-ha7","type":"blocks","created_at":"2026-01-04T16:44:56.615236-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-wisp-271","title":"Check own context limit","description":"Check own context limit.\n\nThe Deacon runs in a Claude session with finite context. Check if approaching the limit:\n\n```bash\ngt context --usage\n```\n\nIf context is high (\u003e80%), prepare for handoff:\n- Summarize current state\n- Note any pending work\n- Write handoff to molecule state\n\nThis enables the Deacon to burn and respawn cleanly.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:04:23.04993-08:00","updated_at":"2025-12-26T13:09:27.201766-08:00","closed_at":"2025-12-26T13:09:27.201766-08:00","dependencies":[{"issue_id":"gt-wisp-271","depends_on_id":"gt-wisp-9ss","type":"blocks","created_at":"2025-12-26T13:04:23.202384-08:00","created_by":"deacon"}]} -{"id":"gt-wisp-3o2","title":"Merge and push to main","description":"Merge to main and push. CRITICAL: Notifications come IMMEDIATELY after push.\n\n**Step 1: Merge and Push**\n```bash\ngit checkout main\ngit merge --ff-only temp\ngit push origin main\n```\n\n⚠️ **STOP HERE - DO NOT PROCEED UNTIL STEPS 2-3 COMPLETE**\n\n**Step 2: Send MERGED Notification (REQUIRED - DO THIS IMMEDIATELY)**\n\nRIGHT NOW, before any cleanup, send MERGED mail to Witness:\n\n```bash\ngt mail send \u003crig\u003e/witness -s \"MERGED \u003cpolecat-name\u003e\" -m \"Branch: \u003cbranch\u003e\nIssue: \u003cissue-id\u003e\nMerged-At: $(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n```\n\nThis signals the Witness to nuke the polecat worktree. WITHOUT THIS NOTIFICATION,\nPOLECAT WORKTREES ACCUMULATE INDEFINITELY AND THE LIFECYCLE BREAKS.\n\n**Step 3: Close MR Bead (REQUIRED - DO THIS IMMEDIATELY)**\n\n⚠️ **VERIFICATION BEFORE CLOSING**: Confirm the work is actually on main:\n```bash\n# Get the commit message/issue from the branch\ngit log origin/main --oneline | grep \"\u003cissue-id\u003e\"\n# OR verify the commit SHA is on main:\ngit branch --contains \u003ccommit-sha\u003e | grep main\n```\n\nIf work is NOT on main, DO NOT close the MR bead. Investigate first.\n\n```bash\nbd close \u003cmr-bead-id\u003e --reason \"Merged to main at $(git rev-parse --short HEAD)\"\n```\n\nThe MR bead ID was in the MERGE_READY message or find via:\n```bash\nbd list --type=merge-request --status=open | grep \u003cpolecat-name\u003e\n```\n\n**VALIDATION**: The MR bead's source_issue should be a valid bead ID (gt-xxxxx),\nnot a branch name. If source_issue contains a branch name, flag for investigation.\n\n**Step 4: Archive the MERGE_READY mail (REQUIRED)**\n```bash\ngt mail archive \u003cmerge-ready-message-id\u003e\n```\nThe message ID was tracked when you processed inbox-check.\n\n**Step 5: Cleanup (only after Steps 2-4 confirmed)**\n```bash\ngit branch -d temp\ngit push origin --delete \u003cpolecat-branch\u003e\n```\n\n**VERIFICATION GATE**: You CANNOT proceed to loop-check without:\n- [x] MERGED mail sent to witness\n- [x] MR bead closed\n- [x] MERGE_READY mail archived\n\nIf you skipped notifications or archiving, GO BACK AND DO THEM NOW.\n\nMain has moved. Any remaining branches need rebasing on new baseline.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T15:39:19.729821-08:00","updated_at":"2026-01-05T19:44:43.978474-08:00","closed_at":"2026-01-05T19:44:43.978474-08:00","close_reason":"Orphaned wisp"} -{"id":"gt-wisp-4s5","title":"Check refinery mail","description":"Check mail for MERGE_READY submissions, escalations, and messages.\n\n```bash\ngt mail inbox\n```\n\nFor each message:\n\n**MERGE_READY**:\nA polecat's work is ready for merge. Extract details and track for processing.\n\n```bash\n# Parse MERGE_READY message body:\n# Branch: \u003cbranch\u003e\n# Issue: \u003cissue-id\u003e\n# Polecat: \u003cpolecat-name\u003e\n# MR: \u003cmr-bead-id\u003e\n# Verified: clean git state, issue closed\n\n# Track in your merge queue for this patrol cycle:\n# - Branch name\n# - Issue ID\n# - Polecat name (REQUIRED for MERGED notification)\n# - MR bead ID (REQUIRED for closing after merge)\n```\n\n**IMPORTANT**: You MUST track the polecat name, MR bead ID, AND message ID - you will need them\nin merge-push step to send MERGED notification, close the MR bead, and archive the mail.\n\nMark as read. The work will be processed in queue-scan/process-branch.\n**Do NOT archive yet** - archive after merge/reject decision in merge-push step.\n\n**PATROL: Wake up**:\nWitness detected MRs waiting but refinery idle. Acknowledge and archive:\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**HELP / Blocked**:\nAssess and respond. If you can't help, escalate to Mayor.\nArchive after handling:\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**HANDOFF**:\nRead predecessor context. Check for in-flight merges.\nArchive after absorbing context:\n```bash\ngt mail archive \u003cmessage-id\u003e\n```\n\n**Hygiene principle**: Archive messages after they're fully processed.\nKeep only: pending MRs in queue. Inbox should be near-empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T16:53:49.94144-08:00","updated_at":"2026-01-05T16:57:01.321365-08:00","closed_at":"2026-01-05T16:57:01.321365-08:00","close_reason":"Inbox checked: 1 MERGE_READY (furiosa)"} -{"id":"gt-wisp-56w","title":"Check own context limit","description":"Check own context usage.\n\nIf context is HIGH (\u003e80%):\n- Write handoff summary\n- Prepare for burn/respawn\n\nIf context is LOW:\n- Can continue processing","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T15:39:19.731263-08:00","updated_at":"2026-01-04T15:39:19.731263-08:00"} -{"id":"gt-wisp-5l9","title":"Merge and push to main","description":"Merge to main and push. CRITICAL: Notifications come IMMEDIATELY after push.\n\n**Step 1: Merge and Push**\n```bash\ngit checkout main\ngit merge --ff-only temp\ngit push origin main\n```\n\n⚠️ **STOP HERE - DO NOT PROCEED UNTIL STEPS 2-3 COMPLETE**\n\n**Step 2: Send MERGED Notification (REQUIRED - DO THIS IMMEDIATELY)**\n\nRIGHT NOW, before any cleanup, send MERGED mail to Witness:\n\n```bash\ngt mail send \u003crig\u003e/witness -s \"MERGED \u003cpolecat-name\u003e\" -m \"Branch: \u003cbranch\u003e\nIssue: \u003cissue-id\u003e\nMerged-At: $(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n```\n\nThis signals the Witness to nuke the polecat worktree. WITHOUT THIS NOTIFICATION,\nPOLECAT WORKTREES ACCUMULATE INDEFINITELY AND THE LIFECYCLE BREAKS.\n\n**Step 3: Close MR Bead (REQUIRED - DO THIS IMMEDIATELY)**\n\n⚠️ **VERIFICATION BEFORE CLOSING**: Confirm the work is actually on main:\n```bash\n# Get the commit message/issue from the branch\ngit log origin/main --oneline | grep \"\u003cissue-id\u003e\"\n# OR verify the commit SHA is on main:\ngit branch --contains \u003ccommit-sha\u003e | grep main\n```\n\nIf work is NOT on main, DO NOT close the MR bead. Investigate first.\n\n```bash\nbd close \u003cmr-bead-id\u003e --reason \"Merged to main at $(git rev-parse --short HEAD)\"\n```\n\nThe MR bead ID was in the MERGE_READY message or find via:\n```bash\nbd list --type=merge-request --status=open | grep \u003cpolecat-name\u003e\n```\n\n**VALIDATION**: The MR bead's source_issue should be a valid bead ID (gt-xxxxx),\nnot a branch name. If source_issue contains a branch name, flag for investigation.\n\n**Step 4: Archive the MERGE_READY mail (REQUIRED)**\n```bash\ngt mail archive \u003cmerge-ready-message-id\u003e\n```\nThe message ID was tracked when you processed inbox-check.\n\n**Step 5: Cleanup (only after Steps 2-4 confirmed)**\n```bash\ngit branch -d temp\ngit push origin --delete \u003cpolecat-branch\u003e\n```\n\n**VERIFICATION GATE**: You CANNOT proceed to loop-check without:\n- [x] MERGED mail sent to witness\n- [x] MR bead closed\n- [x] MERGE_READY mail archived\n\nIf you skipped notifications or archiving, GO BACK AND DO THEM NOW.\n\nMain has moved. Any remaining branches need rebasing on new baseline.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T16:53:49.943911-08:00","updated_at":"2026-01-04T16:53:49.943911-08:00"} -{"id":"gt-wisp-5n5","title":"Scan merge queue","description":"Check the beads merge queue - this is the SOURCE OF TRUTH for pending merges.\n\n```bash\ngit fetch --prune origin\ngt mq list \u003crig\u003e\n```\n\nThe beads MQ tracks all pending merge requests. Do NOT rely on `git branch -r | grep polecat`\nas branches may exist without MR beads, or MR beads may exist for already-merged work.\n\nIf queue empty, skip to context-check step.\n\nFor each MR in the queue, verify the branch still exists:\n```bash\ngit branch -r | grep \u003cbranch\u003e\n```\n\nIf branch doesn't exist for a queued MR:\n- Close the MR bead: `bd close \u003cmr-id\u003e --reason \"Branch no longer exists\"`\n- Remove from processing queue\n\nTrack verified MR list for this cycle.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T17:28:50.508514-08:00","updated_at":"2026-01-04T17:29:54.23022-08:00","closed_at":"2026-01-04T17:29:54.23022-08:00","close_reason":"Queue scanned: 2 branches (vuvalini gt-3ee79, rockryder gt-3g4b0)"} -{"id":"gt-wisp-646","title":"Evaluate pending async gates","description":"Evaluate pending async gates.\n\nGates are async coordination primitives that block until conditions are met.\nThe Deacon is responsible for monitoring gates and closing them when ready.\n\n**Timer gates** (await_type: timer):\nCheck if elapsed time since creation exceeds the timeout duration.\n\n```bash\n# List all open gates\nbd gate list --json\n\n# For each timer gate, check if elapsed:\n# - CreatedAt + Timeout \u003c Now → gate is ready to close\n# - Close with: bd gate close \u003cid\u003e --reason \"Timer elapsed\"\n```\n\n**GitHub gates** (await_type: gh:run, gh:pr) - handled in separate step.\n\n**Human/Mail gates** - require external input, skip here.\n\nAfter closing a gate, the Waiters field contains mail addresses to notify.\nSend a brief notification to each waiter that the gate has cleared.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:04:23.04871-08:00","updated_at":"2025-12-26T13:06:05.44536-08:00","closed_at":"2025-12-26T13:06:05.44536-08:00","dependencies":[{"issue_id":"gt-wisp-646","depends_on_id":"gt-wisp-zuj","type":"blocks","created_at":"2025-12-26T13:04:23.144118-08:00","created_by":"deacon"}]} -{"id":"gt-wisp-78q","title":"Execute registered plugins","description":"Execute registered plugins.\n\nScan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with YAML frontmatter defining its gate (when to run) and instructions (what to do).\n\nSee docs/deacon-plugins.md for full documentation.\n\nGate types:\n- cooldown: Time since last run (e.g., 24h)\n- cron: Schedule-based (e.g., \"0 9 * * *\")\n- condition: Metric threshold (e.g., wisp count \u003e 50)\n- event: Trigger-based (e.g., startup, heartbeat)\n\nFor each plugin:\n1. Read plugin.md frontmatter to check gate\n2. Compare against state.json (last run, etc.)\n3. If gate is open, execute the plugin\n\nPlugins marked parallel: true can run concurrently using Task tool subagents. Sequential plugins run one at a time in directory order.\n\nSkip this step if ~/gt/plugins/ does not exist or is empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:04:44.877976-08:00","updated_at":"2025-12-26T14:07:27.717637-08:00","closed_at":"2025-12-26T14:07:27.717637-08:00"} -{"id":"gt-wisp-7qv","title":"Check for more work","description":"More branches to process?\n\n**Entry paths:**\n- Normal: After successful merge-push\n- Conflict-skip: After process-branch created conflict-resolution task\n\nIf yes: Return to process-branch with next branch.\nIf no: Continue to generate-summary.\n\n**Track for this cycle:**\n- branches_merged: count and names of successfully merged branches\n- branches_conflict: count and names of branches skipped due to conflicts\n- conflict_tasks: IDs of conflict-resolution tasks created\n\nThis tracking feeds into generate-summary for the patrol digest.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T17:28:50.511001-08:00","updated_at":"2026-01-05T19:44:43.907312-08:00","closed_at":"2026-01-05T19:44:43.907312-08:00","close_reason":"Orphaned wisp"} -{"id":"gt-wisp-7zc","title":"End-of-cycle inbox hygiene","description":"Verify inbox hygiene before ending patrol cycle.\n\n**Step 1: Check inbox state**\n```bash\ngt mail inbox\n```\n\nInbox should contain ONLY:\n- Unprocessed MERGE_READY messages (will process next cycle)\n- Active work items\n\n**Step 2: Archive any stale messages**\n\nLook for messages that were processed but not archived:\n- PATROL: Wake up that was acknowledged → archive\n- HELP/Blocked that was handled → archive\n- MERGE_READY where merge completed but archive was missed → archive\n\n```bash\n# For each stale message found:\ngt mail archive \u003cmessage-id\u003e\n```\n\n**Step 3: Check for orphaned MR beads**\n\nLook for open MR beads with no corresponding branch:\n```bash\nbd list --type=merge-request --status=open\n```\n\nFor each open MR bead:\n1. Check if branch exists: `git ls-remote origin refs/heads/\u003cbranch\u003e`\n2. If branch gone, verify work is on main: `git log origin/main --oneline | grep \"\u003csource_issue\u003e\"`\n3. If work on main → close MR with reason \"Merged (verified on main)\"\n4. If work NOT on main → investigate before closing:\n - Check source_issue validity (should be gt-xxxxx, not branch name)\n - Search reflog/dangling commits if possible\n - If unverifiable, close with reason \"Unverifiable - no audit trail\"\n - File bead if this indicates lost work\n\n**NEVER close an MR bead without verifying the work landed or is unrecoverable.**\n\n**Goal**: Inbox should have ≤3 active messages at end of cycle.\nKeep only: pending MRs in queue.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T15:39:19.73175-08:00","updated_at":"2026-01-05T19:44:43.970287-08:00","closed_at":"2026-01-05T19:44:43.970287-08:00","close_reason":"Orphaned wisp","dependencies":[{"issue_id":"gt-wisp-7zc","depends_on_id":"gt-wisp-56w","type":"blocks","created_at":"2026-01-04T15:39:19.814107-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-wisp-99t","title":"Burn and respawn or loop","description":"Burn and let daemon respawn, or exit if context high.\n\nDecision point at end of patrol cycle:\n\nIf context is LOW:\n- Sleep briefly (avoid tight loop)\n- Return to inbox-check step\n\nIf context is HIGH:\n- Write state to persistent storage\n- Exit cleanly\n- Let the daemon orchestrator respawn a fresh Deacon\n\nThe daemon ensures Deacon is always running:\n```bash\n# Daemon respawns on exit\ngt daemon status\n```\n\nThis enables infinite patrol duration via context-aware respawning.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T16:16:32.014153-08:00","updated_at":"2025-12-26T20:07:45.150162-08:00","closed_at":"2025-12-26T20:07:45.150162-08:00","dependencies":[{"issue_id":"gt-wisp-99t","depends_on_id":"gt-wisp-mpm","type":"blocks","created_at":"2025-12-26T16:16:32.105946-08:00","created_by":"stevey"}]} -{"id":"gt-wisp-9ss","title":"Clean dead sessions","description":"Clean dead sessions and orphaned state.\n\nRun `gt doctor --fix` to handle all cleanup:\n\n```bash\n# Preview what needs cleaning\ngt doctor -v\n\n# Fix everything\ngt doctor --fix\n```\n\nThis handles:\n- **orphan-sessions**: Kill orphaned tmux sessions (gt-* not matching valid patterns)\n- **orphan-processes**: Kill orphaned Claude processes (no tmux parent)\n- **wisp-gc**: Garbage collect abandoned wisps (\u003e1h old)\n\nAll cleanup is handled by doctor checks - no need to run separate commands.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:04:23.049699-08:00","updated_at":"2025-12-26T13:09:27.208152-08:00","closed_at":"2025-12-26T13:09:27.208152-08:00","dependencies":[{"issue_id":"gt-wisp-9ss","depends_on_id":"gt-wisp-bau","type":"blocks","created_at":"2025-12-26T13:04:23.192565-08:00","created_by":"deacon"}]} -{"id":"gt-wisp-bau","title":"Find abandoned work","description":"Find abandoned work.\n\nScan for orphaned state:\n- Issues marked in_progress with no active polecat\n- Polecats that stopped responding mid-work\n- Merge queue entries with no polecat owner\n- Wisp sessions that outlived their spawner\n\n```bash\nbd list --status=in_progress\ngt polecats --all --orphan\n```\n\nFor each orphan:\n- Check if polecat session still exists\n- If not, mark issue for reassignment or retry\n- File incident beads if data loss occurred","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:04:23.049463-08:00","updated_at":"2025-12-26T13:07:41.952917-08:00","closed_at":"2025-12-26T13:07:41.952917-08:00","dependencies":[{"issue_id":"gt-wisp-bau","depends_on_id":"gt-wisp-u84","type":"blocks","created_at":"2025-12-26T13:04:23.182848-08:00","created_by":"deacon"}]} -{"id":"gt-wisp-bfq","title":"End-of-cycle inbox hygiene","description":"Verify inbox hygiene before ending patrol cycle.\n\n**Step 1: Check inbox state**\n```bash\ngt mail inbox\n```\n\nInbox should contain ONLY:\n- Unprocessed MERGE_READY messages (will process next cycle)\n- Active work items\n\n**Step 2: Archive any stale messages**\n\nLook for messages that were processed but not archived:\n- PATROL: Wake up that was acknowledged → archive\n- HELP/Blocked that was handled → archive\n- MERGE_READY where merge completed but archive was missed → archive\n\n```bash\n# For each stale message found:\ngt mail archive \u003cmessage-id\u003e\n```\n\n**Step 3: Check for orphaned MR beads**\n\nLook for open MR beads with no corresponding branch:\n```bash\nbd list --type=merge-request --status=open\n```\n\nFor each open MR bead:\n1. Check if branch exists: `git ls-remote origin refs/heads/\u003cbranch\u003e`\n2. If branch gone, verify work is on main: `git log origin/main --oneline | grep \"\u003csource_issue\u003e\"`\n3. If work on main → close MR with reason \"Merged (verified on main)\"\n4. If work NOT on main → investigate before closing:\n - Check source_issue validity (should be gt-xxxxx, not branch name)\n - Search reflog/dangling commits if possible\n - If unverifiable, close with reason \"Unverifiable - no audit trail\"\n - File bead if this indicates lost work\n\n**NEVER close an MR bead without verifying the work landed or is unrecoverable.**\n\n**Goal**: Inbox should have ≤3 active messages at end of cycle.\nKeep only: pending MRs in queue.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T17:28:50.512454-08:00","updated_at":"2026-01-04T17:28:50.512454-08:00"} -{"id":"gt-wisp-cz5","title":"Check Witness and Refinery health","description":"Check Witness and Refinery health for each rig.\n\n**ZFC Principle**: You (Claude) make the judgment call about what is \"stuck\" or \"unresponsive\" - there are no hardcoded thresholds in Go. Read the signals, consider context, and decide.\n\nFor each rig, run:\n```bash\ngt witness status \u003crig\u003e\ngt refinery status \u003crig\u003e\n```\n\n**Signals to assess:**\n\n| Component | Healthy Signals | Concerning Signals |\n|-----------|-----------------|-------------------|\n| Witness | State: running, recent activity | State: not running, no heartbeat |\n| Refinery | State: running, queue processing | Queue stuck, merge failures |\n\n**Tracking unresponsive cycles:**\n\nMaintain in your patrol state (persisted across cycles):\n```\nhealth_state:\n \u003crig\u003e:\n witness:\n unresponsive_cycles: 0\n last_seen_healthy: \u003ctimestamp\u003e\n refinery:\n unresponsive_cycles: 0\n last_seen_healthy: \u003ctimestamp\u003e\n```\n\n**Decision matrix** (you decide the thresholds based on context):\n\n| Cycles Unresponsive | Suggested Action |\n|---------------------|------------------|\n| 1-2 | Note it, check again next cycle |\n| 3-4 | Attempt restart: gt witness restart \u003crig\u003e |\n| 5+ | Escalate to Mayor with context |\n\n**Restart commands:**\n```bash\ngt witness restart \u003crig\u003e\ngt refinery restart \u003crig\u003e\n```\n\n**Escalation:**\n```bash\ngt mail send mayor/ -s \"Health: \u003crig\u003e \u003ccomponent\u003e unresponsive\" \\\n -m \"Component has been unresponsive for N cycles. Restart attempts failed.\n Last healthy: \u003ctimestamp\u003e\n Error signals: \u003cdetails\u003e\"\n```\n\nReset unresponsive_cycles to 0 when component responds normally.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T16:16:32.012846-08:00","updated_at":"2025-12-26T16:18:17.168113-08:00","closed_at":"2025-12-26T16:18:17.168113-08:00","dependencies":[{"issue_id":"gt-wisp-cz5","depends_on_id":"gt-wisp-9hf","type":"blocks","created_at":"2025-12-26T16:16:32.071988-08:00","created_by":"stevey"}]} -{"id":"gt-wisp-eju","title":"Nudge newly spawned polecats","description":"Nudge newly spawned polecats that are ready for input.\n\nWhen polecats are spawned, their Claude session takes 10-20 seconds to initialize. The spawn command returns immediately without waiting. This step finds spawned polecats that are now ready and sends them a trigger to start working.\n\n**ZFC-Compliant Observation** (AI observes AI):\n\n```bash\n# View pending spawns with captured terminal output\ngt deacon pending\n```\n\nFor each pending session, analyze the captured output:\n- Look for Claude's prompt indicator \"\u003e \" at the start of a line\n- If prompt is visible, Claude is ready for input\n- Make the judgment call yourself - you're the AI observer\n\nFor each ready polecat:\n```bash\n# 1. Trigger the polecat\ngt nudge \u003csession\u003e \"Begin.\"\n\n# 2. Clear from pending list\ngt deacon pending \u003csession\u003e\n```\n\nThis triggers the UserPromptSubmit hook, which injects mail so the polecat sees its assignment.\n\n**Bootstrap mode** (daemon-only, no AI available):\nThe daemon uses `gt deacon trigger-pending` with regex detection. This ZFC violation is acceptable during cold startup when no AI agent is running yet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T19:55:37.501716-08:00","updated_at":"2025-12-25T19:55:55.613364-08:00","closed_at":"2025-12-25T19:55:55.613364-08:00","dependencies":[{"issue_id":"gt-wisp-eju","depends_on_id":"gt-wisp-lya","type":"blocks","created_at":"2025-12-25T19:55:37.617246-08:00","created_by":"deacon"}]} -{"id":"gt-wisp-fnm","title":"mol-deacon-patrol","description":"Mayor's daemon patrol loop.\n\nThe Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-26T15:39:49.992066-08:00","updated_at":"2025-12-26T15:40:02.9979-08:00","closed_at":"2025-12-26T15:40:02.9979-08:00"} -{"id":"gt-wisp-ha7","title":"Mechanical rebase","description":"Pick next branch from queue. Attempt mechanical rebase on current main.\n\n**Step 1: Checkout and attempt rebase**\n```bash\ngit checkout -b temp origin/\u003cpolecat-branch\u003e\ngit rebase origin/main\n```\n\n**Step 2: Check rebase result**\n\nThe rebase exits with:\n- Exit code 0: Success - proceed to run-tests\n- Exit code 1 (conflicts): Conflict detected - proceed to Step 3\n\nTo detect conflict state after rebase fails:\n```bash\n# Check if we're in a conflicted rebase state\nls .git/rebase-merge 2\u003e/dev/null \u0026\u0026 echo \"CONFLICT_STATE\"\n```\n\n**Step 3: Handle conflicts (if any)**\n\nIf rebase SUCCEEDED (exit code 0):\n- Skip to run-tests step (continue normal merge flow)\n\nIf rebase FAILED with conflicts:\n\n1. **Abort the rebase** (DO NOT leave repo in conflicted state):\n```bash\ngit rebase --abort\n```\n\n2. **Record conflict metadata**:\n```bash\n# Capture main SHA for reference\nMAIN_SHA=$(git rev-parse origin/main)\nBRANCH_SHA=$(git rev-parse origin/\u003cpolecat-branch\u003e)\n```\n\n3. **Create conflict-resolution task**:\n```bash\nbd create --type=task --priority=1 --title=\"Resolve merge conflicts: \u003coriginal-issue-title\u003e\" --description=\"## Conflict Resolution Required\n\nOriginal MR: \u003cmr-bead-id\u003e\nBranch: \u003cpolecat-branch\u003e\nOriginal Issue: \u003cissue-id\u003e\nConflict with main at: ${MAIN_SHA}\nBranch SHA: ${BRANCH_SHA}\n\n## Instructions\n1. Clone/checkout the branch\n2. Rebase on current main: git rebase origin/main\n3. Resolve conflicts\n4. Force push: git push -f origin \u003cbranch\u003e\n5. Close this task when done\n\nThe MR will be re-queued for processing after conflicts are resolved.\"\n```\n\n4. **Skip this MR** (do NOT delete branch or close MR bead):\n- Leave branch intact for conflict resolution\n- Leave MR bead open (will be re-processed after resolution)\n- Continue to loop-check for next branch\n\n**CRITICAL**: Never delete a branch that has conflicts. The branch contains\nthe original work and must be preserved for conflict resolution.\n\nTrack: rebase result (success/conflict), conflict task ID if created.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T16:44:56.542513-08:00","updated_at":"2026-01-05T19:44:43.966166-08:00","closed_at":"2026-01-05T19:44:43.966166-08:00","close_reason":"Orphaned wisp","dependencies":[{"issue_id":"gt-wisp-ha7","depends_on_id":"gt-wisp-wf6","type":"blocks","created_at":"2026-01-04T16:44:56.60971-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-wisp-py3","title":"Mechanical rebase","description":"Pick next branch from queue. Attempt mechanical rebase on current main.\n\n**Step 1: Checkout and attempt rebase**\n```bash\ngit checkout -b temp origin/\u003cpolecat-branch\u003e\ngit rebase origin/main\n```\n\n**Step 2: Check rebase result**\n\nThe rebase exits with:\n- Exit code 0: Success - proceed to run-tests\n- Exit code 1 (conflicts): Conflict detected - proceed to Step 3\n\nTo detect conflict state after rebase fails:\n```bash\n# Check if we're in a conflicted rebase state\nls .git/rebase-merge 2\u003e/dev/null \u0026\u0026 echo \"CONFLICT_STATE\"\n```\n\n**Step 3: Handle conflicts (if any)**\n\nIf rebase SUCCEEDED (exit code 0):\n- Skip to run-tests step (continue normal merge flow)\n\nIf rebase FAILED with conflicts:\n\n1. **Abort the rebase** (DO NOT leave repo in conflicted state):\n```bash\ngit rebase --abort\n```\n\n2. **Record conflict metadata**:\n```bash\n# Capture main SHA for reference\nMAIN_SHA=$(git rev-parse origin/main)\nBRANCH_SHA=$(git rev-parse origin/\u003cpolecat-branch\u003e)\n```\n\n3. **Create conflict-resolution task**:\n```bash\nbd create --type=task --priority=1 --title=\"Resolve merge conflicts: \u003coriginal-issue-title\u003e\" --description=\"## Conflict Resolution Required\n\nOriginal MR: \u003cmr-bead-id\u003e\nBranch: \u003cpolecat-branch\u003e\nOriginal Issue: \u003cissue-id\u003e\nConflict with main at: ${MAIN_SHA}\nBranch SHA: ${BRANCH_SHA}\n\n## Instructions\n1. Clone/checkout the branch\n2. Rebase on current main: git rebase origin/main\n3. Resolve conflicts\n4. Force push: git push -f origin \u003cbranch\u003e\n5. Close this task when done\n\nThe MR will be re-queued for processing after conflicts are resolved.\"\n```\n\n4. **Skip this MR** (do NOT delete branch or close MR bead):\n- Leave branch intact for conflict resolution\n- Leave MR bead open (will be re-processed after resolution)\n- Continue to loop-check for next branch\n\n**CRITICAL**: Never delete a branch that has conflicts. The branch contains\nthe original work and must be preserved for conflict resolution.\n\nTrack: rebase result (success/conflict), conflict task ID if created.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T17:28:50.509025-08:00","updated_at":"2026-01-04T17:28:50.509025-08:00","dependencies":[{"issue_id":"gt-wisp-py3","depends_on_id":"gt-wisp-5n5","type":"blocks","created_at":"2026-01-04T17:28:50.634622-08:00","created_by":"gastown/refinery"}]} -{"id":"gt-wisp-qx6","title":"mol-witness-patrol","description":"Per-rig worker monitor patrol loop using the Christmas Ornament pattern.\n\nThe Witness is the Pit Boss for your rig. You watch polecats, nudge them toward\ncompletion, verify clean git state before kills, and escalate stuck workers.\n\n**You do NOT do implementation work.** Your job is oversight, not coding.\n\nThis molecule uses dynamic bonding to spawn mol-polecat-arm for each worker,\nenabling parallel inspection with a fanout gate for aggregation.\n\n## The Christmas Ornament Shape\n\n```\n ★ mol-witness-patrol (trunk)\n /|\\\n ┌────────┘ │ └────────┐\n PREFLIGHT DISCOVERY CLEANUP\n │ │ │\n inbox-check survey aggregate (WaitsFor: all-children)\n check-refnry │ save-state\n load-state │ generate-summary\n ↓ context-check\n ┌───────┼───────┐ burn-or-loop\n ● ● ● mol-polecat-arm (dynamic)\n ace nux toast\n```\n","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-25T19:48:34.05296-08:00","updated_at":"2025-12-26T19:59:32.832833-08:00","closed_at":"2025-12-26T19:59:32.832833-08:00"} -{"id":"gt-wisp-wf6","title":"Scan merge queue","description":"Check the beads merge queue - this is the SOURCE OF TRUTH for pending merges.\n\n```bash\ngit fetch --prune origin\ngt mq list \u003crig\u003e\n```\n\nThe beads MQ tracks all pending merge requests. Do NOT rely on `git branch -r | grep polecat`\nas branches may exist without MR beads, or MR beads may exist for already-merged work.\n\nIf queue empty, skip to context-check step.\n\nFor each MR in the queue, verify the branch still exists:\n```bash\ngit branch -r | grep \u003cbranch\u003e\n```\n\nIf branch doesn't exist for a queued MR:\n- Close the MR bead: `bd close \u003cmr-id\u003e --reason \"Branch no longer exists\"`\n- Remove from processing queue\n\nTrack verified MR list for this cycle.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T16:44:56.542002-08:00","updated_at":"2026-01-04T16:44:56.542003-08:00"} -{"id":"gt-wisp-zuj","title":"Handle callbacks from agents","description":"Handle callbacks from agents.\n\nCheck the Mayor's inbox for messages from:\n- Witnesses reporting polecat status\n- Refineries reporting merge results\n- Polecats requesting help or escalation\n- External triggers (webhooks, timers)\n\n```bash\ngt mail inbox\n# For each message:\ngt mail read \u003cid\u003e\n# Handle based on message type\n```\n\nCallbacks may spawn new polecats, update issue state, or trigger other actions.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T13:04:23.048133-08:00","updated_at":"2025-12-26T13:05:17.719577-08:00","closed_at":"2025-12-26T13:05:17.719577-08:00"} -{"id":"gt-witness-gastown","title":"gt-witness-gastown","description":"gt-witness-gastown\n\nrole_type: witness\nrig: gastown\nagent_state: running\nhook_bead: null\nrole_bead: gt-witness-role\ncleanup_status: null","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-28T00:07:40.418097-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T14:31:11.045404-08:00","closed_at":"2025-12-29T14:30:35.640814-08:00","close_reason":"Migrated to canonical naming: gt-gastown-witness/refinery"} -{"id":"gt-witness-role","title":"Witness Role Definition","description":"You are the Witness - per-rig worker monitor. You watch polecats, nudge them\ntoward completion, verify clean git state before kills, and escalate stuck\nworkers to the Mayor.\n\nYou do NOT do implementation work. Your job is oversight, not coding.\n\nsession_pattern: gt-{rig}-witness\nwork_dir_pattern: {town}/{rig}\nneeds_pre_sync: false\nstart_command: exec claude --dangerously-skip-permissions\n\ndefault_molecule: mol-witness-patrol\ncapabilities:\n - monitor_workers\n - nudge_stuck\n - pre_kill_verify\n - session_lifecycle\n - escalation\n\n## Core Responsibilities\n\n1. Monitor workers: Track polecat health and progress\n2. Nudge: Prompt slow workers toward completion\n3. Pre-kill verification: Ensure git state is clean before killing sessions\n4. Session lifecycle: Kill sessions, update worker state\n5. Self-cycling: Hand off to fresh session when context fills\n6. Escalation: Report stuck workers to Mayor\n\nKey principle: You own ALL per-worker cleanup. Mayor is never involved in\nroutine worker management.\n\n## Propulsion Principle\n\nIf you find something on your hook, YOU RUN IT.\n\nYour work is defined by the mol-witness-patrol molecule. Execute steps:\n- bd ready (find next step)\n- bd show \u003cstep-id\u003e (see what to do)\n- bd close \u003cstep-id\u003e (mark complete)\n\n## Nudge Protocol\n\nProgress through stages. Track nudge count per worker per issue.\n- First Nudge (10+ min idle): Gentle inquiry\n- Second Nudge (15 min): Direct question\n- Third Nudge (20 min): Final warning\nAfter 3 nudges with no progress then escalate to Mayor\n\n## Pre-Kill Verification\n\nBefore killing ANY polecat session:\n1. gt polecat git-state \u003cname\u003e - Must be clean\n2. Check for uncommitted work\n3. Check for unpushed commits\n4. Verify issue closed\n5. Verify PR submitted (if applicable)\n\n## Commands\n\n- gt polecat list \u003crig\u003e - See all polecats\n- gt polecat git-state \u003cname\u003e - Check git cleanliness\n- tmux capture-pane -t gt-\u003crig\u003e-\u003cname\u003e -p | tail -40 - Session inspection\n- gt mail inbox - Check messages\n- gt mail send mayor/ -s \"Subject\" -m \"Message\" - Escalate","status":"hooked","priority":2,"issue_type":"role","assignee":"gastown/polecats/slit","created_at":"2025-12-28T00:51:20.912437-08:00","created_by":"stevey","updated_at":"2025-12-30T02:02:49.746012-08:00","labels":["migrated-to:hq-witness-role"]} -{"id":"gt-wixa4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 80: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:28:12.91048-08:00","updated_at":"2026-01-01T13:28:12.91048-08:00","closed_at":"2026-01-01T13:28:12.910438-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wjgyp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 40: All healthy, 20 cycles complete - handoff per heuristic","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:41:35.140594-08:00","updated_at":"2026-01-01T12:41:35.140594-08:00","closed_at":"2026-01-01T12:41:35.140551-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wjy4c","title":"Digest: mol-deacon-patrol","description":"Patrol 116: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:14:27.447229-08:00","updated_at":"2026-01-01T14:14:27.447229-08:00","closed_at":"2026-01-01T14:14:27.447192-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wled7","title":"Use atomic write pattern for state files","description":"attached_args: Atomic write pattern for state files\n\nPrevent data loss from concurrent state file writes using atomic write pattern.\n\n## Files to modify\n- internal/witness/manager.go\n- internal/refinery/manager.go\n- internal/crew/manager.go\n- internal/swarm/manager.go\n\n## Problem\nState is saved directly to file - if process crashes mid-write, file corrupts.\n\n## Implementation\nReplace direct writes with atomic pattern:\n```go\nfunc atomicWriteJSON(path string, v interface{}) error {\n data, err := json.MarshalIndent(v, \"\", \" \")\n if err != nil {\n return err\n }\n tmpFile := path + \".tmp\"\n if err := os.WriteFile(tmpFile, data, 0644); err != nil {\n return err\n }\n return os.Rename(tmpFile, path) // Atomic on POSIX\n}\n```\n\n## Acceptance criteria\n- [ ] atomicWriteJSON helper created (in internal/util or similar)\n- [ ] All 4 manager saveState methods use atomic writes\n- [ ] .tmp files cleaned up on success\n- [ ] go test ./... passes\n- [ ] Manual test: state files survive kill -9","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:19.004767-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:58:00.223196-08:00","closed_at":"2025-12-28T15:58:00.223196-08:00"} -{"id":"gt-wm61m","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:28:49.455286-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.634884-08:00","closed_at":"2026-01-05T00:08:31.634884-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:28:49-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-wn6mc","title":"Digest: mol-deacon-patrol","description":"Patrol 4 complete. All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:41:24.7809-08:00","updated_at":"2025-12-31T16:41:24.7809-08:00","closed_at":"2025-12-31T16:41:24.780864-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wnx6c","title":"Digest: mol-deacon-patrol","description":"Patrol 2: All healthy, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:48:02.556651-08:00","updated_at":"2026-01-01T08:48:02.556651-08:00","closed_at":"2026-01-01T08:48:02.556613-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wnze6","title":"gt feed: Add convoy dashboard panel for in-progress and recently-landed","description":"## The Insight\n\nConvoys are now the most important unit of work for certain Gas Town users.\nThe convoy-landing feed is THE view of feature work and fixes actually shipping.\n\n## Current State\n\ngt feed shows:\n- Agent tree (top panel): agents by role\n- Event stream (bottom panel): issue/molecule activity\n\nMissing: **Convoy status panel**\n\n## Proposed Enhancement\n\nAdd a convoy panel showing:\n\n```\n┌─🚚 Convoys─────────────────────────────┐\n│ IN PROGRESS │\n│ hq-qrfz4 cv-startup 2/4 ●●○○ │\n│ hq-wvqi6 Boot+Polish 3/5 ●●●○○ │\n│ │\n│ RECENTLY LANDED (24h) │\n│ hq-abc12 Auth refactor ✓ 2h ago │\n│ hq-def34 API cleanup ✓ 5h ago │\n└────────────────────────────────────────┘\n```\n\n## Components\n\n1. **In-progress convoys**: Open convoys with progress bars (completed/total)\n2. **Recently landed**: Convoys that closed in last 24h (configurable)\n3. **Quick stats**: Total in-flight, landed today, etc.\n\n## Integration Options\n\nA) New panel in existing TUI (3-panel layout)\nB) Dedicated `gt convoy feed` or `gt convoy watch` command\nC) Both - convoy panel in main feed + dedicated convoy view\n\n## Why This Matters\n\nThe agent tree shows WHO is working.\nThe event stream shows WHAT is happening.\nThe convoy panel shows WHAT IS SHIPPING.\n\nFor stakeholders, the convoy view is the most important - \"what features landed today?\"\n","status":"closed","priority":1,"issue_type":"feature","assignee":"gastown/crew/gus","created_at":"2025-12-30T23:04:06.143943-08:00","created_by":"stevey","updated_at":"2025-12-30T23:17:59.660313-08:00","closed_at":"2025-12-30T23:17:59.660313-08:00","close_reason":"Implemented convoy dashboard panel in gt feed TUI with progress bars and recently-landed section"} -{"id":"gt-wo1ej","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 25: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:19:21.878963-08:00","updated_at":"2026-01-01T12:19:21.878963-08:00","closed_at":"2026-01-01T12:19:21.873492-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wotrp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:48:47.319267-08:00","updated_at":"2025-12-30T15:48:47.319267-08:00","closed_at":"2025-12-30T15:48:47.319233-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wp9hs","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All healthy, idle town","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:36:56.88534-08:00","updated_at":"2026-01-01T23:36:56.88534-08:00","closed_at":"2026-01-01T23:36:56.885299-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-wq1wb","title":"gt hook: Cannot resolve HQ beads from polecat context","description":"## Problem\n`gt hook hq-eggh5` fails from within a polecat clone:\n```\nError: resolving ID hq-eggh5: operation failed: failed to resolve ID: no issue found matching \"hq-eggh5\"\n```\n\n## Context\n- Ran from: ~/gt/gastown/polecats/furiosa\n- Bead exists: `bd show hq-eggh5` works from town root\n- Routes exist: ~/gt/.beads/routes.jsonl has hq- prefix mapped\n\n## Expected\nHQ beads (hq-* prefix) should be resolvable from anywhere in town via prefix-based routing.\n\n## Actual\nPolecat can only resolve beads with its own rig's prefix (gt-*).\n\n## Impact\nCannot sling HQ-level issues to polecats - breaks cross-rig coordination.\n\n## Workaround\nUnknown - possibly need to copy/mirror the bead to rig-level beads first.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-31T01:55:46.030636-08:00","created_by":"mayor","updated_at":"2025-12-31T13:22:15.423743-08:00","closed_at":"2025-12-31T13:22:15.423743-08:00","close_reason":"Fixed: bd update now checks needsRouting() before daemon RPC to enable cross-rig bead updates"} -{"id":"gt-wsaho","title":"Digest: mol-deacon-patrol","description":"Patrol 95: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:25:45.354527-08:00","updated_at":"2025-12-31T15:25:45.354527-08:00","closed_at":"2025-12-31T15:25:45.354494-08:00"} -{"id":"gt-wt6ci","title":"Merge: rictus-mjw3nj1a","description":"branch: polecat/rictus-mjw3nj1a\ntarget: main\nsource_issue: rictus-mjw3nj1a\nrig: gastown\nagent_bead: gt-gastown-polecat-rictus","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:23:13.87957-08:00","created_by":"gastown/polecats/rictus","updated_at":"2026-01-01T19:25:16.889202-08:00","closed_at":"2026-01-01T19:25:16.889202-08:00","close_reason":"Merged to main at 478dc60d"} -{"id":"gt-wtfb4","title":"Extract magic values to named constants","description":"Magic strings and numbers throughout codebase:\n\nShells list repeated 4x:\n- start.go:729, 773, 907\n- crew_helpers.go\nPattern: []string{\"bash\", \"zsh\", \"sh\", \"fish\", \"tcsh\", \"ksh\"}\n\nTiming values:\n- time.Sleep(500 * time.Millisecond) in multiple places\n- WaitForCommand 15*time.Second\n- WaitForShellReady 5*time.Second\n- Debounce 100ms default\n\nOther magic values:\n- \"gt-\" session prefix\n- priority = 2 default\n- Mail preview length 500 chars\n- Heartbeat ages 5min/15min\n- Divergence thresholds 10/50 commits\n\nSuggestion: Add to constants/constants.go:\n- SupportedShells\n- ShutdownNotifyDelay, ClaudeStartTimeout, ShellReadyTimeout\n- SessionPrefix\n- DefaultPriority\n- MailPreviewMaxLength","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-28T15:43:12.603942-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:47:18.309863-08:00","closed_at":"2025-12-28T15:47:18.309863-08:00"} -{"id":"gt-wtfej","title":"gt done: MR bead not created","description":"Integration test gt-7psb8 revealed that gt done says 'Work submitted to merge queue' but no MR bead is created.\n\nObserved:\n- gt done output: 'MR ID: mr-1766956116-b02fb1e5'\n- bd show mr-1766956116-b02fb1e5: 'no issue found'\n- gt mq list gastown: '(empty)'\n\nExpected: MR bead should exist with issue_type=merge-request and appear in gt mq list.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T13:11:52.664858-08:00","created_by":"mayor","updated_at":"2025-12-28T13:55:54.404887-08:00","closed_at":"2025-12-28T13:55:54.404887-08:00","dependencies":[{"issue_id":"gt-wtfej","depends_on_id":"gt-7psb8","type":"blocks","created_at":"2025-12-28T13:13:50.227153-08:00","created_by":"daemon"}]} -{"id":"gt-wthcc","title":"Deacon convoy patrol steps","description":"New Deacon patrol steps for convoy orchestration.\n\nSteps:\n1. check-convoy-completion\n - Watch town feed for tracked issue closures\n - Auto-close convoys when all tracked issues complete\n\n2. resolve-external-deps\n - When external issue closes, propagate to dependents in other rigs\n - Update blocked status across project chain boundaries\n\n3. fire-notifications\n - Convoy complete → notify Overseer inbox\n - Cross-rig dep resolved → notify affected rigs\n\nDepends on: gt feed, bd-hj0s (convoy type)\nRelated: hq-7h8jx (Convoy System epic in town beads)","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-29T18:47:32.778733-08:00","created_by":"mayor","updated_at":"2025-12-30T00:48:10.334283-08:00","closed_at":"2025-12-30T00:48:10.334283-08:00","close_reason":"Implemented 3 convoy patrol steps: check-convoy-completion, resolve-external-deps, fire-notifications","dependencies":[{"issue_id":"gt-wthcc","depends_on_id":"gt-sifj5","type":"blocks","created_at":"2025-12-29T18:47:49.629448-08:00","created_by":"daemon"},{"issue_id":"gt-wthcc","depends_on_id":"external:beads:bd-hj0s","type":"blocks","created_at":"2025-12-29T18:47:49.670485-08:00","created_by":"daemon"}]} -{"id":"gt-wtnb5","title":"Digest: mol-deacon-patrol","description":"Patrol 5: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T10:16:31.082548-08:00","updated_at":"2025-12-25T10:16:31.082548-08:00","closed_at":"2025-12-25T10:16:31.082511-08:00"} -{"id":"gt-wusk","title":"Layered context onboarding pattern","description":"Pattern from handoff discussion:\n\n## Pattern: Layered Context Onboarding\n\nTown CLAUDE.md (user/org) -\u003e Rig CLAUDE.md (project) -\u003e Role priming\n\n## Ultra-compressed HOP for workers (no reveal)\n\n- Permanent record: All work tracked. Outcomes matter.\n- Quality gates: Molecule steps exist for a reason.\n- Attribution: Completions build your track record.\n- Handoff clean: Leave state any worker can continue.\n\n## Recommendation\n\nCreate Town @AGENTS.md for shared worker context that all workers see.\nThis provides common behavioral guidance without revealing full HOP context.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T00:55:11.984103-08:00","updated_at":"2025-12-20T00:55:11.984103-08:00"} -{"id":"gt-wv582","title":"Digest: mol-deacon-patrol","description":"Patrol 7: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T20:02:35.667778-08:00","updated_at":"2025-12-26T20:02:35.667778-08:00","closed_at":"2025-12-26T20:02:35.66773-08:00"} -{"id":"gt-ww31z","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:57:25.648363-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:57:25.699357-08:00","closed_at":"2026-01-06T13:57:25.699357-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:57:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-wxewm","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 23: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:16:20.57805-08:00","updated_at":"2026-01-01T12:16:20.57805-08:00","closed_at":"2026-01-01T12:16:20.578013-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-wy8t","title":"Add live polling and updates","description":"Implement live polling (500ms default) for activity updates. Merge new events into view without flickering. Show connection status indicator. Handle daemon disconnects gracefully.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T16:27:18.127611-08:00","updated_at":"2025-12-23T16:27:18.127611-08:00","dependencies":[{"issue_id":"gt-wy8t","depends_on_id":"gt-3p77","type":"blocks","created_at":"2025-12-23T16:27:38.7256-08:00","created_by":"daemon"},{"issue_id":"gt-wy8t","depends_on_id":"gt-rivr","type":"parent-child","created_at":"2025-12-23T16:28:30.942591-08:00","created_by":"daemon"}]} -{"id":"gt-wzxwm","title":"[Security] Path traversal risk in crew name handling","description":"In crew/manager.go:39-41, crewDir() uses filepath.Join(m.rig.Path, \"crew\", name) where 'name' is user input. If name contains '..', it could escape the crew directory. Should validate crew names similar to rig name validation in rig/manager.go:215-219.","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-04T23:47:12.771508-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T00:01:29.452061-08:00","closed_at":"2026-01-05T00:01:29.452061-08:00","close_reason":"Fixed: added validateCrewName() to reject path traversal and invalid characters"} -{"id":"gt-x0a5","title":"Patrol formulas: Inconsistent variable placeholder syntax","description":"The patrol formulas use inconsistent syntax for variable placeholders:\n\n## Inconsistency\n\n| Formula | Syntax | Examples |\n|---------|--------|----------|\n| mol-polecat-arm | `{{var}}` | `{{polecat_name}}`, `{{rig}}` |\n| mol-witness-patrol | `\u003cvar\u003e` | `\u003crig\u003e`, `\u003chandoff-bead-id\u003e` |\n| mol-refinery-patrol | `\u003cvar\u003e` | `\u003cpolecat-branch\u003e` |\n\n## Expected\n\nAll formulas should use consistent syntax, probably `{{var}}` since that's what\nthe variables section defines.\n\n## Fix\n\nUpdate mol-witness-patrol and mol-refinery-patrol to use `{{var}}` syntax\nwhere appropriate, or document that `\u003cvar\u003e` is for human-filled placeholders\nvs `{{var}}` for cook-time interpolation.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-24T13:51:48.126618-08:00","updated_at":"2025-12-28T22:34:14.443991-08:00","closed_at":"2025-12-28T22:34:14.443991-08:00"} -{"id":"gt-x0km1","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All 6 agents healthy, handoff threshold","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:29:47.435075-08:00","updated_at":"2026-01-01T10:29:47.435075-08:00","closed_at":"2026-01-01T10:29:47.435036-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-x1xf4","title":"Merge: slit-1767087730371","description":"branch: polecat/slit-1767087730371\ntarget: main\nsource_issue: slit-1767087730371\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T01:52:04.347645-08:00","created_by":"gastown/polecats/slit","updated_at":"2025-12-30T10:06:56.782992-08:00","closed_at":"2025-12-30T10:06:56.782992-08:00","close_reason":"Branch merged to main"} -{"id":"gt-x33vk","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All 6 agents healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:20:10.593962-08:00","updated_at":"2026-01-01T10:20:10.593962-08:00","closed_at":"2026-01-01T10:20:10.593923-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-x3tos","title":"Digest: mol-deacon-patrol","description":"Patrol 52: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:22:22.752249-08:00","updated_at":"2026-01-01T02:22:22.752249-08:00","closed_at":"2026-01-01T02:22:22.752213-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-x4ad3","title":"Update polecat template: Use gt done --exit","description":"## Task\n\nUpdate `templates/polecat-CLAUDE.md` to tell polecats to use `gt done --exit` instead of `gt done` + waiting.\n\n## Changes\n\n1. Update completion checklist:\n```\nOLD:\n[ ] 6. Run gt done: gt done\n[ ] 7. WAIT: Witness will kill your session\n\nNEW:\n[ ] 6. Exit session: gt done --exit\n```\n\n2. Remove \"WAIT\" step - no more waiting\n\n3. Update explanation of gt done to mention --exit flag\n\n## Dependencies\n\n- gt-lynar (gt done --exit feature)","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-02T13:36:45.874907-08:00","created_by":"mayor","updated_at":"2026-01-02T13:45:34.592269-08:00","closed_at":"2026-01-02T13:45:34.592269-08:00","close_reason":"Updated polecat template to use gt done --exit","dependencies":[{"issue_id":"gt-x4ad3","depends_on_id":"gt-lynar","type":"blocks","created_at":"2026-01-02T13:36:51.34277-08:00","created_by":"mayor"}]} -{"id":"gt-x4dzz","title":"Digest: mol-deacon-patrol","description":"Patrol 13: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:02:27.87441-08:00","updated_at":"2026-01-01T23:02:27.87441-08:00","closed_at":"2026-01-01T23:02:27.874369-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-x5acy","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 11: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:34.773103-08:00","updated_at":"2025-12-28T11:22:34.773103-08:00","closed_at":"2025-12-28T11:22:34.773071-08:00"} -{"id":"gt-x5gxi","title":"Daemon/Boot/Deacon Watchdog Chain: Fix session lifecycle management","description":"## Summary\n\nThe watchdog chain (Daemon → Boot → Deacon → Witness/Refinery) has multiple bugs preventing auto-recovery of dead agents:\n\n1. Boot spawns in wrong session\n2. Daemon can't kill zombie sessions\n3. Binary/process age mismatch goes undetected\n4. Status display doesn't reconcile bead vs tmux state\n5. Start commands don't have 'ensure' semantics\n\n## Impact\n\nWhen witness/refinery die, they stay dead until manual intervention. The entire purpose of the Deacon (health monitoring) is defeated.\n\n## Root Cause\n\nSession lifecycle management lacks 'ensure running' semantics. The code assumes:\n- If session doesn't exist → create it\n- If session exists → it's healthy\n\nReality:\n- Sessions can be zombies (tmux alive, Claude dead)\n- Bead state and tmux state can diverge\n- Daemon process can run old code\n\n## Child Issues\n\n- gt-sgzsb: Boot session confusion (P1)\n- gt-j1i0r: Zombie session blocking (P1)\n- gt-d48f2: Binary age detection (P2)\n- gt-doih4: Status bead/tmux mismatch (P2)\n- gt-ekc5u: Start 'ensure' semantics (P2)\n- gt-1847v: Boot/Deacon documentation (P2)\n\n## Success Criteria\n\n1. Dead witness/refinery auto-restart within 5 minutes\n2. `gt status` accurately reflects session health\n3. Daemon warns if running old code\n4. Boot/Deacon lifecycle is clear and documented","status":"closed","priority":1,"issue_type":"epic","created_at":"2026-01-02T18:43:51.522482-08:00","created_by":"mayor","updated_at":"2026-01-02T18:57:15.49754-08:00","closed_at":"2026-01-02T18:57:15.49754-08:00","close_reason":"All child issues completed: boot session fix, zombie session handling, binary age detection, status reconciliation, ensure semantics, and documentation","dependencies":[{"issue_id":"gt-x5gxi","depends_on_id":"gt-sgzsb","type":"blocks","created_at":"2026-01-02T18:44:16.897795-08:00","created_by":"mayor"},{"issue_id":"gt-x5gxi","depends_on_id":"gt-j1i0r","type":"blocks","created_at":"2026-01-02T18:44:16.939363-08:00","created_by":"mayor"},{"issue_id":"gt-x5gxi","depends_on_id":"gt-d48f2","type":"blocks","created_at":"2026-01-02T18:44:16.98097-08:00","created_by":"mayor"},{"issue_id":"gt-x5gxi","depends_on_id":"gt-doih4","type":"blocks","created_at":"2026-01-02T18:44:17.022721-08:00","created_by":"mayor"},{"issue_id":"gt-x5gxi","depends_on_id":"gt-ekc5u","type":"blocks","created_at":"2026-01-02T18:44:17.064278-08:00","created_by":"mayor"},{"issue_id":"gt-x5gxi","depends_on_id":"gt-1847v","type":"blocks","created_at":"2026-01-02T18:44:17.104983-08:00","created_by":"mayor"}]} -{"id":"gt-x9m7","title":"Molecule converge: iterate until AI says done","description":"Work isn't 'done' until AI is confident it's done. Fixes the 85% problem.\n\n**From VC**: internal/iterative/converge.go - 3-7 iterations with AI convergence detection. ~600 lines.\nTarget: 20%+ more issues discovered. Observed: ~25% average improvement.\n\n**Gas Town implementation**: Molecule converge config:\n```yaml\nconverge:\n strategy: ai\n min_iterations: 3\n max_iterations: 7\n confidence: 0.85\n```\n\nPolecat iterates, AI checks convergence. Stop when AI is confident or max reached.\n\n**Value**: Raw agents get to ~85% and stop. Iteration catches the remaining 15%.\n\n**VC metrics**: Convergence rate \u003e70%, mean 4-5 iterations for complex work.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-20T20:30:18.671862-08:00","updated_at":"2025-12-20T20:30:18.671862-08:00","dependencies":[{"issue_id":"gt-x9m7","depends_on_id":"gt-zhpa","type":"parent-child","created_at":"2025-12-20T20:30:27.728971-08:00","created_by":"daemon"}]} -{"id":"gt-x9v05","title":"Code review formula: First complete formula implementation","description":"Create .beads/formulas/code-review.formula.toml with 7 legs:\n- correctness, performance, security, elegance, resilience, style, smells\n\nTest end-to-end:\n1. gt formula run code-review --pr=\u003ctest-pr\u003e\n2. Verify all legs spawn and complete\n3. Verify synthesis produces unified review\n4. Verify convoy status shows progress\n\nThis is the proof-of-concept for the whole formula system.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2026-01-01T14:42:59.245559-08:00","created_by":"mayor","updated_at":"2026-01-01T16:08:27.807752-08:00","closed_at":"2026-01-01T16:08:27.807752-08:00","close_reason":"Formula complete: 7 review legs, synthesis step, convoy type. End-to-end testing confirmed by rictus.","dependencies":[{"issue_id":"gt-x9v05","depends_on_id":"gt-v5s0j","type":"blocks","created_at":"2026-01-01T14:43:10.007791-08:00","created_by":"mayor"},{"issue_id":"gt-x9v05","depends_on_id":"gt-f0701","type":"blocks","created_at":"2026-01-01T14:43:10.047243-08:00","created_by":"mayor"}]} -{"id":"gt-xah33","title":"Digest: mol-deacon-patrol","description":"Patrol 151 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:04:39.221893-08:00","updated_at":"2025-12-31T16:04:39.221893-08:00","closed_at":"2025-12-31T16:04:39.221857-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-xah33","depends_on_id":"gt-eph-037","type":"parent-child","created_at":"2025-12-31T16:04:39.223152-08:00","created_by":"deacon"}]} -{"id":"gt-xahix","title":"Digest: mol-deacon-patrol","description":"Patrol 203: Routine checks, all systems nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:47:51.969363-08:00","updated_at":"2026-01-01T16:47:51.969363-08:00","closed_at":"2026-01-01T16:47:51.969328-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-xahix","depends_on_id":"gt-eph-zhiq","type":"parent-child","created_at":"2026-01-01T16:47:51.970669-08:00","created_by":"deacon"}]} -{"id":"gt-xakwb","title":"Digest: mol-deacon-patrol","description":"Patrol 101-120 complete: Cleaned 42 stale wisps, health pings sent to all witnesses/refineries, all agents healthy, no orphans, 1 idle dog","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:39:14.391826-08:00","updated_at":"2025-12-31T15:39:14.391826-08:00","closed_at":"2025-12-31T15:39:14.391794-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xb5n0","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:19:20.060042-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:19:20.112124-08:00","closed_at":"2026-01-06T13:19:20.112124-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:19:19-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-xb8ke","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 44: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:53:11.407219-08:00","updated_at":"2026-01-01T12:53:11.407219-08:00","closed_at":"2026-01-01T12:53:11.407186-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xbjxp","title":"Witness sends HEALTH_OK mail to mayor on every deacon ping","description":"## Problem\n\nWhen Deacon sends HEALTH_CHECK nudges to Witnesses, the Witness Claude sessions\nrespond by sending 'HEALTH_OK' mail to mayor/. This floods the mayor inbox.\n\n## Current behavior\n\nDeacon: gt nudge gastown/witness 'HEALTH_CHECK'\nWitness: gt mail send mayor/ -s 'HEALTH_OK witness' -m 'OK'\n\nThis happens every patrol cycle (~30s).\n\n## Expected behavior\n\nWitnesses should NOT send mail responses to routine health checks.\n\n## Fix\n\nUpdate witness priming to explicitly say 'do not mail on HEALTH_CHECK nudges'.","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/capable","created_at":"2025-12-31T14:32:07.035165-08:00","created_by":"mayor","updated_at":"2026-01-01T18:12:15.405537-08:00","closed_at":"2026-01-01T18:12:15.405537-08:00","close_reason":"Updated witness templates to not mail on HEALTH_CHECK nudges"} -{"id":"gt-xbsfa","title":"Merge: gt-cehl8","description":"branch: polecat/furiosa-mjuibvz8\ntarget: main\nsource_issue: gt-cehl8\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-31T13:12:09.419305-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-31T13:13:23.12877-08:00","closed_at":"2025-12-31T13:13:23.12877-08:00","close_reason":"Merged at d2a6ddb0"} -{"id":"gt-xc7gc","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T11:06:21.405313-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.64199-08:00","closed_at":"2026-01-05T19:44:18.64199-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T11:06:21-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-xcbof","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:15:38.650868-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.280439-08:00","closed_at":"2026-01-04T16:40:13.280439-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:15:38-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-xd95b","title":"Remove markdown molecule heresy from ~/gt/molecules/","description":"The ~/gt/molecules/lifecycle/*.md files are outdated heresy - molecule definitions should only exist as formula.toml files in .beads/formulas/. Remove the markdown specs and update any docs that reference them.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T17:33:33.464666-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-30T06:45:17.834291-08:00","closed_at":"2025-12-30T06:45:17.834291-08:00","close_reason":"Already removed - no ~/gt/molecules/ directory exists, no refs in docs"} -{"id":"gt-xdklc","title":"Digest: mol-deacon-patrol","description":"Patrol 8: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:45:35.766678-08:00","updated_at":"2025-12-28T19:45:35.766678-08:00","closed_at":"2025-12-28T19:45:35.76663-08:00"} -{"id":"gt-xesj9","title":"Review PR #51: fix: Use hq prefix for agent beads to match town beads database","description":"Review PR #51. Check hq prefix usage is consistent. Approve with gh pr review --approve if good.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/imperator","created_at":"2026-01-03T11:40:27.585399-08:00","created_by":"mayor","updated_at":"2026-01-03T11:47:42.978827-08:00","closed_at":"2026-01-03T11:47:42.978827-08:00","close_reason":"PR reviewed - requested changes: hardcoded gt- references need updating in prime.go, daemon/lifecycle.go, doctor/agent_beads_check.go, polecat/manager.go, crew_add.go"} -{"id":"gt-xfig5","title":"Digest: mol-deacon-patrol","description":"Cycle 294: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T18:40:48.794904-08:00","updated_at":"2026-01-01T18:40:48.794904-08:00","closed_at":"2026-01-01T18:40:48.794857-08:00","close_reason":"Squashed from 13 wisps","dependencies":[{"issue_id":"gt-xfig5","depends_on_id":"gt-eph-v5bg","type":"parent-child","created_at":"2026-01-01T18:40:48.796177-08:00","created_by":"deacon"}]} -{"id":"gt-xgk9s","title":"Digest: mol-deacon-patrol","description":"Patrol 18: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T23:15:11.193339-08:00","updated_at":"2026-01-01T23:15:11.193339-08:00","closed_at":"2026-01-01T23:15:11.193288-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-xgqnb","title":"Day 1.5: Create role beads from CLAUDE.md content","description":"Create role beads from existing CLAUDE.md files:\n- gt-mayor-role (from mayor CLAUDE.md)\n- gt-witness-role (from witness CLAUDE.md)\n- gt-refinery-role (from refinery CLAUDE.md)\n\nEach role bead contains priming instructions and default_molecule.\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:18.455282-08:00","created_by":"mayor","updated_at":"2025-12-28T00:51:56.6882-08:00","closed_at":"2025-12-28T00:51:56.6882-08:00","dependencies":[{"issue_id":"gt-xgqnb","depends_on_id":"gt-awu07","type":"blocks","created_at":"2025-12-27T20:58:51.902061-08:00","created_by":"daemon"},{"issue_id":"gt-xgqnb","depends_on_id":"gt-d0jqp","type":"parent-child","created_at":"2025-12-27T20:59:02.757231-08:00","created_by":"daemon"},{"issue_id":"gt-xgqnb","depends_on_id":"gt-gzp2y","type":"blocks","created_at":"2025-12-27T23:17:26.759727-08:00","created_by":"daemon"}]} -{"id":"gt-xheo6","title":"Cross-rig worktree support for crew","description":"Enable crew workers to work on other rigs without losing identity.\n\n**Problem**: When gastown/crew/joe needs to fix a beads bug, where do they work?\nCurrent options are all problematic: mayor's rig (coordination, not coding), random\ncrew clone (conflicts), community repo (file locks), dogs (wrong abstraction).\n\n**Solution**: Crew creates worktrees in target rigs with predictable paths.\n\nDirectory structure:\n```\n~/gt/\u003ctarget-rig\u003e/crew/\u003csource-rig\u003e-\u003cname\u003e/\n~/gt/beads/crew/gastown-joe/ # joe from gastown working on beads\n~/gt/gastown/crew/beads-wolf/ # wolf from beads working on gastown\n```\n\nKey principles:\n- Identity preserved: BD_ACTOR stays gastown/crew/joe\n- No conflicts: Each crew has own worktree\n- No indirection: Direct work, no delegation to dogs\n- Persistent: Worktree survives sessions (matches crew lifecycle)\n- Dogs remain for Deacon's infrastructure work only\n\nCommands:\n- gt worktree \u003crig\u003e - Create/enter worktree for rig\n- gt worktree list - Show your worktrees \n- gt worktree remove \u003crig\u003e - Clean up worktree","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-30T17:40:29.036817-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:05:16.831244-08:00","closed_at":"2025-12-30T18:05:16.831244-08:00","close_reason":"Cross-rig worktree support complete - all 4 tasks implemented."} -{"id":"gt-xheo6.1","title":"Implement gt worktree create command","description":"Create worktree in target rig for cross-rig work.\n\nUsage: gt worktree \u003crig\u003e\n\nBehavior:\n1. Detect current identity (gastown/crew/joe)\n2. Compute worktree path: ~/gt/\u003crig\u003e/crew/\u003csource-rig\u003e-\u003cname\u003e/\n3. If worktree doesn't exist:\n - git worktree add \u003cpath\u003e main\n - Set up .git config for identity preservation\n4. cd to worktree (or print path for user to cd)\n5. Preserve BD_ACTOR, GT_ROLE, etc.\n\nEdge cases:\n- Worktree already exists → just enter it\n- Rig doesn't exist → error with helpful message\n- No crew identity → error (must be crew to use this)","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/dementus","created_at":"2025-12-30T17:40:48.552114-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:01:38.977513-08:00","closed_at":"2025-12-30T18:01:38.977513-08:00","close_reason":"Implemented gt worktree command for cross-rig work","dependencies":[{"issue_id":"gt-xheo6.1","depends_on_id":"gt-xheo6","type":"parent-child","created_at":"2025-12-30T17:40:48.552745-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-xheo6.2","title":"Implement gt worktree list command","description":"List all worktrees owned by current crew member.\n\nUsage: gt worktree list\n\nOutput:\n```\nCross-rig worktrees for gastown/crew/joe:\n\n beads ~/gt/beads/crew/gastown-joe/ (clean)\n mayor ~/gt/mayor/crew/gastown-joe/ (2 uncommitted)\n```\n\nImplementation:\n- Scan all rigs in ~/gt/\n- Check for crew/\u003csource-rig\u003e-\u003cname\u003e/ directories\n- Show git status summary for each","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-30T17:40:49.847297-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:27:53.653569-08:00","closed_at":"2025-12-30T18:27:53.653569-08:00","close_reason":"Implemented gt worktree list command","dependencies":[{"issue_id":"gt-xheo6.2","depends_on_id":"gt-xheo6","type":"parent-child","created_at":"2025-12-30T17:40:49.847843-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-xheo6.3","title":"Implement gt worktree remove command","description":"Remove a cross-rig worktree.\n\nUsage: gt worktree remove \u003crig\u003e\n\nBehavior:\n1. Check for uncommitted changes → warn/abort\n2. git worktree remove \u003cpath\u003e\n3. Clean up directory if needed\n\nSafety:\n- Refuse if uncommitted changes (unless --force)\n- Confirm before removal","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T17:40:50.857156-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:08:13.25969-08:00","closed_at":"2025-12-30T22:08:13.25969-08:00","close_reason":"Already implemented and merged in d72cb6b9","dependencies":[{"issue_id":"gt-xheo6.3","depends_on_id":"gt-xheo6","type":"parent-child","created_at":"2025-12-30T17:40:50.857664-08:00","created_by":"gastown/crew/joe"},{"issue_id":"gt-xheo6.3","depends_on_id":"gt-xheo6.2","type":"blocks","created_at":"2025-12-30T18:22:52.528468-08:00","created_by":"mayor"}]} -{"id":"gt-xheo6.4","title":"Document cross-rig worktree pattern","description":"Add documentation for crew cross-rig work pattern.\n\nUpdate:\n- CLAUDE.md crew context with worktree usage\n- docs/understanding-gas-town.md with role taxonomy clarification\n- PRIMING.md if needed\n\nKey points to document:\n- Crew vs Dogs distinction (dogs = Deacon's infra, not user work)\n- Identity preservation across rigs\n- When to use worktrees vs dispatch to local workers\n- Directory structure convention","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/dag","created_at":"2025-12-30T17:40:52.414239-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T18:03:02.738902-08:00","closed_at":"2025-12-30T18:03:02.738902-08:00","close_reason":"Added cross-rig worktree documentation to crew.md.tmpl and created docs/understanding-gas-town.md","dependencies":[{"issue_id":"gt-xheo6.4","depends_on_id":"gt-xheo6","type":"parent-child","created_at":"2025-12-30T17:40:52.414791-08:00","created_by":"gastown/crew/joe"}]} -{"id":"gt-xhhwd","title":"Merge: dag-mjw70jg8","description":"branch: polecat/dag-mjw70jg8\ntarget: main\nsource_issue: dag-mjw70jg8\nrig: gastown\nagent_bead: gt-gastown-polecat-dag","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:08:20.685703-08:00","created_by":"gastown/polecats/dag","updated_at":"2026-01-01T19:10:43.722828-08:00","closed_at":"2026-01-01T19:10:43.722828-08:00","close_reason":"Merged to main at b6eeac41"} -{"id":"gt-xhjss","title":"[Git] Missing context.Context support for cancellation","description":"The internal/git package lacks context.Context support throughout. Long-running operations like Clone, Fetch, and Push cannot be cancelled. All run() and public methods should accept context and use exec.CommandContext(). Affected files: internal/git/git.go (all methods).","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:16.699652-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-04T23:47:16.699652-08:00"} -{"id":"gt-xhwlq","title":"mol-sync-workspace: Split handle-dirty-state into focused steps","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-30T19:11:05.175341-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-01T19:03:15.555055-08:00","closed_at":"2026-01-01T19:03:15.555055-08:00","close_reason":"Split handle-dirty-state into 3 focused steps: handle-uncommitted (staged/unstaged changes), handle-untracked (untracked files with decision matrix), and handle-stashes (review/clean old stashes)"} -{"id":"gt-xj9e5","title":"ZFC #7: Make message age filtering configurable","description":"**ZFC Violation:** internal/daemon/lifecycle.go:64-75\n\nGo hardcodes 6-hour max message age:\n```go\nconst MaxLifecycleMessageAge = 6 * time.Hour\n```\n\n**ZFC-compliant solution:**\n- Make this configurable per message type\n- Or let agents decide message relevance\n- Low priority - not blocking liftoff\n\nReference: ~/gt/docs/zfc-violations-audit.md #7","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-27T21:32:54.911989-08:00","created_by":"mayor","updated_at":"2025-12-27T21:32:54.911989-08:00"} -{"id":"gt-xjfxt","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8: All healthy, 4 polecats active (furiosa, nux, rictus, slit)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:21:46.873276-08:00","updated_at":"2026-01-01T11:21:46.873276-08:00","closed_at":"2026-01-01T11:21:46.873241-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xka9x","title":"announce: shared bulletin board","description":"Announcement channel with shared single-copy storage.\n\n## Deliverables\n\n1. Parse announce:name syntax\n2. Shared storage model (like queue, but no claim):\n - Single message copy\n - Multiple readers can view\n - Informational, not work-creating\n3. Configuration in ~/gt/config/announce.json\n4. Read tracking (optional): who has seen it\n\n## Key semantics\n- Informational broadcast\n- Missing is OK (not critical)\n- Use case: \"Bob refactoring logging, be aware\"\n\n## Dependencies\n- Config directory (gt-i6jvc)\n- queue: implementation (pattern reference)\n\n## Acceptance\n- announce:status creates single shared message\n- Multiple agents can read\n- No claim semantics (read-only)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-26T14:52:31.22555-08:00","updated_at":"2025-12-26T14:52:31.22555-08:00","dependencies":[{"issue_id":"gt-xka9x","depends_on_id":"gt-i6jvc","type":"blocks","created_at":"2025-12-26T14:53:09.977096-08:00","created_by":"daemon"}]} -{"id":"gt-xkbze","title":"Add expandQueue() to resolve queue workers from messaging.json","description":"Add queue expansion to internal/mail/router.go.\n\nPATTERN TO FOLLOW:\nLook at expandList() at lines 63-87 as the template.\n\nIMPLEMENTATION:\n1. Add expandQueue(queueName string) (*config.QueueConfig, error)\n2. Load messaging.json via config.LoadMessagingConfig\n3. Look up queueName in cfg.Queues map\n4. Return the QueueConfig (workers list, max_claims) or ErrUnknownQueue\n\nFILE: internal/mail/router.go \nADD: var ErrUnknownQueue = errors.New(\"unknown queue\") near ErrUnknownList\n\nTESTS: Add TestExpandQueue in router_test.go\n\nDepends on isQueueAddress being added first.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T18:15:36.421012-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T22:31:46.435483-08:00","closed_at":"2025-12-30T22:31:46.435483-08:00","close_reason":"Added expandQueue() with ErrUnknownQueue and tests","dependencies":[{"issue_id":"gt-xkbze","depends_on_id":"gt-0q3cg","type":"blocks","created_at":"2025-12-30T18:15:48.151041-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-xmh3k","title":"Digest: mol-deacon-patrol","description":"Cycle 199: Nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:24:45.191447-08:00","updated_at":"2026-01-01T16:24:45.191447-08:00","closed_at":"2026-01-01T16:24:45.191402-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-xmh3k","depends_on_id":"gt-eph-ybcp","type":"parent-child","created_at":"2026-01-01T16:24:45.192732-08:00","created_by":"deacon"}]} -{"id":"gt-xmliw","title":"Merge: coma-mjwjczb0","description":"branch: polecat/coma-mjwjczb0\ntarget: main\nsource_issue: coma-mjwjczb0\nrig: gastown\nagent_bead: gt-gastown-polecat-coma","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T23:16:37.819548-08:00","created_by":"gastown/polecats/coma","updated_at":"2026-01-01T23:19:01.657918-08:00","closed_at":"2026-01-01T23:19:01.657918-08:00","close_reason":"Merged to main"} -{"id":"gt-xms5r","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:12:22.278755-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:22.5802-08:00","closed_at":"2026-01-04T16:40:22.5802-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:12:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-xmsme","title":"Mayor notification levels (Do Not Disturb mode)","description":"## Problem\n\nMayor needs notification level control like iOS Do Not Disturb:\n- **Verbose**: gt nudge tmux messages for mail, convoy events, escalations\n- **Normal**: Important events only (convoy landed, escalations)\n- **Muted/DND**: Silent - batch notifications for later review\n\n## Use Cases\n\n1. Running a swarm: Mute notifications, check convoy status manually\n2. Waiting for work: Verbose - get nudged when mail arrives\n3. Deep coordination: Normal - only interruptions that need attention\n\n## Design Considerations\n\n### Beads Data Plane Integration\n- Notification preferences should be a bead slot (persistent across sessions)\n- Events are already beads (mail, convoy status changes)\n- Need event classification: urgency levels on beads?\n- gt nudge should check notification level before firing\n\n### State Location\n- Mayor agent bead has slots for persistent state\n- `notification_level`: verbose | normal | muted\n- Could also have per-event-type overrides\n\n### Commands\n```bash\ngt dnd on # Mute notifications\ngt dnd off # Resume normal\ngt dnd status # Show current level\ngt notify verbose # All notifications\ngt notify normal # Default\ngt notify muted # DND mode\n```\n\n### Event Classification\nWhich events are which urgency?\n- P0: Escalations from Witness, critical failures\n- P1: Convoy landed, work completed\n- P2: New mail, status updates\n- P3: Informational (can always batch)\n\n### Open Questions\n1. Should DND auto-disable after convoy lands?\n2. Per-convoy notification preferences?\n3. How to surface batched notifications when DND ends?\n4. Integration with tmux status line vs nudge popups?","status":"closed","priority":2,"issue_type":"feature","assignee":"gastown/polecats/dementus","created_at":"2025-12-31T13:12:38.200645-08:00","created_by":"mayor","updated_at":"2026-01-01T18:45:29.796217-08:00","closed_at":"2026-01-01T18:45:29.796217-08:00","close_reason":"Implemented gt dnd and gt notify commands with nudge integration"} -{"id":"gt-xmy0y","title":"Fix PR→MR terminology in internal workflow docs","description":"Polecats create MRs (merge requests), not PRs. Fix these references:\n\n- docs/reference.md:326 - 'review PRs' → 'review MRs' \n- docs/INSTALLING.md:187 - 'PR review' → 'MR review'\n\nPRs are external GitHub concept. MRs are internal Gas Town workflow.","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/dinki","created_at":"2026-01-04T22:13:15.095621-08:00","created_by":"mayor","updated_at":"2026-01-04T22:15:17.476607-08:00","closed_at":"2026-01-04T22:15:17.476607-08:00","close_reason":"Fixed PR→MR in reference.md and INSTALLING.md"} -{"id":"gt-xni9g","title":"Digest: mol-deacon-patrol","description":"Patrol #6: All quiet, 1 dog idle.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:18:04.202519-08:00","updated_at":"2025-12-31T19:18:04.202519-08:00","closed_at":"2025-12-31T19:18:04.202482-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xo05b","title":"Agent scanner utility for filesystem","description":"Filesystem scanner to discover agent directories in a rig or town.\n\n## Deliverables\n\n1. Function: ScanRigAgents(rigPath) -\u003e []AgentAddr\n - Finds: witness/, refinery/, crew/*, polecats/*\n - Returns normalized addresses (e.g., \"gastown/witness\")\n\n2. Function: ScanTownAgents(townPath) -\u003e []AgentAddr\n - Iterates all rigs, calls ScanRigAgents for each\n - Returns all agent addresses in town\n\n3. Alias resolution:\n - @rig/gastown → ScanRigAgents(\"gastown\")\n - @town → ScanTownAgents()\n - @witnesses → filter for */witness across all rigs\n - @crew/gastown → filter crew/* in gastown\n\n## Location\ninternal/discovery/scanner.go (new package)\n\n## Acceptance\n- Scanner finds all agent types\n- Alias patterns resolve correctly\n- Unit tests pass","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T14:51:38.434528-08:00","updated_at":"2025-12-27T22:15:52.303949-08:00","closed_at":"2025-12-27T22:15:52.303949-08:00"} -{"id":"gt-xpe4n","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:27:30.904127-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:27:30.959182-08:00","closed_at":"2026-01-06T13:27:30.959182-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:27:30-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-xpgh8","title":"Support space-separated rig/polecat syntax in gt polecat commands","description":"## Problem\n`gt polecat remove beads obsidian` fails with:\n```\nError: invalid address 'beads': invalid address format: expected 'rig/polecat', got 'beads'\n```\n\nRequires slash syntax: `gt polecat remove beads/obsidian`\n\n## Proposal\nSupport both syntaxes for ergonomics:\n```bash\ngt polecat remove beads/obsidian # address syntax (current)\ngt polecat remove beads obsidian # positional syntax (proposed)\n```\n\n## Implementation\nIn polecat subcommands that take rig/polecat addresses:\n- If arg contains `/`, use as-is\n- If two args without `/`, join with `/`\n- Apply to: remove, status, sync, reset, done\n\n```go\nfunc normalizePolecatAddress(args []string) string {\n if len(args) == 1 \u0026\u0026 strings.Contains(args[0], \"/\") {\n return args[0]\n }\n if len(args) == 2 {\n return args[0] + \"/\" + args[1]\n }\n // error handling...\n}\n```\n\n## Rationale\n- Unambiguous context - polecat commands always take rig + name\n- Matches positional arg patterns in docker, kubectl, etc.\n- Reduces agent friction (natural first guess is space-separated)\n- Slash syntax remains valid for consistency with mail addresses\n","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-27T16:06:29.941199-08:00","created_by":"mayor","updated_at":"2025-12-27T16:06:29.941199-08:00"} -{"id":"gt-xpnpc","title":"Digest: mol-deacon-patrol","description":"Patrol 152: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:03:28.21176-08:00","updated_at":"2026-01-01T15:03:28.21176-08:00","closed_at":"2026-01-01T15:03:28.21172-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xqdk","title":"Add molecule to update local go binary on push to main","description":"When pushing to main branch, automatically rebuild and install the gt binary on the local machine so changes are immediately available.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T15:37:40.542228-08:00","updated_at":"2025-12-19T15:37:40.542228-08:00"} -{"id":"gt-xqg5f","title":"Merge: morsov-1767106016839","description":"branch: polecat/morsov-1767106016839\ntarget: main\nsource_issue: morsov-1767106016839\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T06:55:43.297315-08:00","created_by":"gastown/polecats/morsov","updated_at":"2025-12-30T10:06:56.647396-08:00","closed_at":"2025-12-30T10:06:56.647396-08:00","close_reason":"Branch merged to main"} -{"id":"gt-xqgqq","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T14:33:40.693738-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:41:26.199948-08:00","closed_at":"2026-01-04T16:41:26.199948-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T14:33:40-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-xqh3y","title":"Witness should nuke polecats after completion, not leave idle","description":"## Problem\nPolecats are supposed to be ephemeral - fully despawned (nuked) after completing work. Currently the witness:\n1. Receives POLECAT_DONE signal\n2. Marks polecat as 'idle' \n3. Stops there\n\nThis leaves zombie polecats with tmux sessions and git worktrees lingering indefinitely.\n\n## Evidence\n14 beads polecats sitting 'idle' with stopped sessions after completing work in the Boot+Polish swarm.\n\n## Expected Behavior\nAfter polecat completes (MR submitted or other exit):\n1. Witness verifies work is pushed/merged\n2. Witness nukes the polecat (session, worktree, branch, agent bead)\n3. Polecat no longer exists\n\nPolecats are disposable single-task workers, not persistent like crew.\n\n## Impact\n- Accumulating tmux sessions\n- Accumulating git worktrees\n- Accumulating disk usage\n- Confusion about available workers","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/crew/max","created_at":"2025-12-31T00:44:14.559735-08:00","created_by":"mayor","updated_at":"2025-12-31T12:25:45.402921-08:00","closed_at":"2025-12-31T12:25:45.402921-08:00","close_reason":"Implemented auto-nuke in witness handlers (e3933d7)"} -{"id":"gt-xqro3","title":"Digest: mol-deacon-patrol","description":"Patrol complete: all agents healthy, no mail, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:39:33.103389-08:00","updated_at":"2025-12-31T18:39:33.103389-08:00","closed_at":"2025-12-31T18:39:33.103351-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xr3xi","title":"Session ended: gt-gastown-glory","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:33:58.80684-08:00","created_by":"gastown/polecats/glory","updated_at":"2026-01-04T16:40:22.726853-08:00","closed_at":"2026-01-04T16:40:22.726853-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/glory","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:33:58-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-glory\",\"worker\":\"glory\"}"} -{"id":"gt-xrmjc","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 16: All healthy, gastown refinery queue at 3","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:27:20.140565-08:00","updated_at":"2026-01-01T11:27:20.140565-08:00","closed_at":"2026-01-01T11:27:20.140524-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xswaa","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All healthy. Routine check.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:00:59.022858-08:00","updated_at":"2026-01-01T20:00:59.022858-08:00","closed_at":"2026-01-01T20:00:59.022823-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-xtsb5","title":"Fix namepool Save() to use write lock","description":"attached_args: Fix namepool Save() mutex for thread safety\n\nFix incorrect mutex usage in namepool Save() method.\n\n## Files to modify\n- internal/polecat/namepool.go\n\n## Problem (lines 179-194)\nSave() uses RLock() but performs file I/O:\n```go\nfunc (p *NamePool) Save() error {\n p.mu.RLock() // WRONG: file write needs write lock\n defer p.mu.RUnlock()\n // ... file operations ...\n}\n```\n\n## Fix\nChange to write lock:\n```go\nfunc (p *NamePool) Save() error {\n p.mu.Lock()\n defer p.mu.Unlock()\n // ... file operations ...\n}\n```\n\n## Acceptance criteria\n- [ ] Save() uses Lock() instead of RLock()\n- [ ] go test -race ./internal/polecat/... passes\n- [ ] Existing namepool tests still pass","status":"hooked","priority":2,"issue_type":"task","created_at":"2025-12-28T15:49:17.602342-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-28T15:54:15.240872-08:00"} -{"id":"gt-xuk8t","title":"Digest: mol-deacon-patrol","description":"Patrol #18: Quick cycle, all quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:22:37.875873-08:00","updated_at":"2025-12-31T19:22:37.875873-08:00","closed_at":"2025-12-31T19:22:37.875834-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xupwk","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T21:59:24.53132-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T00:08:31.899333-08:00","closed_at":"2026-01-05T00:08:31.899333-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T21:59:24-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-xuzo","title":"Add self-check context guidance to role CLAUDE.md files","description":"Each role's CLAUDE.md needs guidance for context self-management:\n\n- After each patrol cycle, self-assess context pressure\n- Heuristics: feeling compressed, lots of tool calls, long session\n- If triggered: initiate handoff before continuing\n\nRoles to update:\n- Mayor (~/gt/CLAUDE.md)\n- Witness template\n- Refinery template \n- Polecat template\n- Crew template\n- Deacon template\n\nThis is the 'inversion of control' - agents decide when to cycle, not external monitoring.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-23T01:46:14.197485-08:00","updated_at":"2025-12-23T14:27:07.564589-08:00"} -{"id":"gt-xv6b6","title":"Merge: dementus-1767140140908","description":"branch: polecat/dementus-1767140140908\ntarget: main\nsource_issue: dementus-1767140140908\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:23:04.501981-08:00","created_by":"gastown/polecats/dementus","updated_at":"2025-12-30T18:23:22.168115-08:00","closed_at":"2025-12-30T18:23:22.168115-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-xveby","title":"Digest: mol-deacon-patrol","description":"Cycle 9: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T13:17:31.34652-08:00","updated_at":"2025-12-28T13:17:31.34652-08:00","closed_at":"2025-12-28T13:17:31.346483-08:00"} -{"id":"gt-xvhhl","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:51:01.533331-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:40:13.536888-08:00","closed_at":"2026-01-04T16:40:13.536888-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:51:01-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-xvn4t","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 6: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:43:27.675926-08:00","updated_at":"2026-01-01T07:43:27.675926-08:00","closed_at":"2026-01-01T07:43:27.67589-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xvner","title":"Digest: mol-deacon-patrol","description":"Patrol 7: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T00:01:49.871554-08:00","updated_at":"2025-12-25T00:01:49.871554-08:00","closed_at":"2025-12-25T00:01:49.871519-08:00"} -{"id":"gt-xw3cd","title":"Digest: mol-deacon-patrol","description":"Patrol 1: All 3 rigs healthy, 17 sessions running, no issues","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T08:46:39.523941-08:00","updated_at":"2026-01-01T08:46:39.523941-08:00","closed_at":"2026-01-01T08:46:39.523906-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xw7b","title":"Add --fart as easter egg alias for bd mol bond","description":"Add a hidden alias for the bond command:\n\n```bash\nbd mol fart mol-polecat-work --wisp\n# equivalent to:\nbd mol bond mol-polecat-work --wisp\n```\n\n## Context\nThe fart joke: instantiating a proto can produce either:\n- A Mol (solid/substantial output)\n- A Wisp (gas/ephemeral output)\n\n## Implementation\n- Add 'fart' as an alias in the mol subcommand\n- No documentation needed (easter egg)\n- Maybe a fun message: 'Bonding molecule...' or similar\n\nLow priority, just for fun.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-21T16:33:18.822868-08:00","updated_at":"2025-12-28T22:33:35.382773-08:00","closed_at":"2025-12-28T22:33:35.382773-08:00"} -{"id":"gt-xwige","title":"Remove keepalive file infrastructure","description":"The keepalive mechanism (~/gt/daemon/activity.json) is deprecated in favor of feed-based wake.\n\n**Current state:**\n- keepalive.TouchTownActivity() writes to activity.json on every gt/bd command\n- Daemon reads activity.json to calculate exponential backoff\n\n**New model (feed-based wake):**\n- Patrol agents subscribe to `bd activity --follow`\n- Any beads mutation wakes agents within ~500ms\n- Daemon heartbeat is recovery-focused, not wake-focused\n- Read-only commands don't need to wake the town\n\n**TODO:**\n1. Remove keepalive.TouchTownActivity() calls from gt commands\n2. Remove keepalive.ReadTownActivity() from daemon\n3. Delete internal/keepalive package\n4. Update daemon to use longer base heartbeat (recovery-focused)\n\n**Whitelist consideration:**\nSome read-only commands might need to wake (TBD):\n- gt mail inbox (checking for work?)\n- None identified yet\n\nSee docs/patrol-system-design.md for full feed-based wake design.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-29T16:35:53.250019-08:00","created_by":"mayor","updated_at":"2025-12-29T20:59:13.883207-08:00","closed_at":"2025-12-29T20:59:13.883207-08:00","close_reason":"Duplicate of gt-vdprb.2"} -{"id":"gt-xxcwm","title":"Magic Numbers: Timing constants in session/manager.go","description":"The session/manager.go file has several magic numbers for timing:\n\n- Line 207: `time.Sleep(8 * time.Second)` - Claude startup wait\n- Line 224: `time.Sleep(2 * time.Second)` - Beacon processing wait\n- Line 259: `time.Sleep(100 * time.Millisecond)` - Graceful shutdown wait\n- Line 429-432: Debounce calculation `200 + (len(message)/1024)*100` with cap at 1500\n\nThese should be named constants for clarity:\n\n```go\nconst (\n ClaudeStartupDelay = 8 * time.Second\n BeaconProcessingDelay = 2 * time.Second \n GracefulShutdownDelay = 100 * time.Millisecond\n DebounceBaseDelay = 200 * time.Millisecond\n DebouncePerKB = 100 * time.Millisecond\n DebounceMaxDelay = 1500 * time.Millisecond\n)\n```\n\nFiles:\n- internal/session/manager.go:207, 224, 259, 429-432\n\nSeverity: low","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T23:47:54.323768-08:00","created_by":"gastown/polecats/citadel","updated_at":"2026-01-04T23:47:54.323768-08:00"} -{"id":"gt-xyh4k","title":"Digest: mol-deacon-patrol","description":"Patrol 2: Quick pass, all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T18:02:37.909906-08:00","updated_at":"2025-12-31T18:02:37.909906-08:00","closed_at":"2025-12-31T18:02:37.909869-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-xypw9","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:19:00.464851-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-05T19:44:41.865135-08:00","closed_at":"2026-01-05T19:44:41.865135-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:18:59-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-xyulb","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T18:49:48.649543-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.52155-08:00","closed_at":"2026-01-05T19:44:18.52155-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T18:49:43-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-xyzb5","title":"Add Boot shutdown to gt shutdown","description":"gt shutdown should stop Boot if running. Currently Boot is only spawned by daemon but never explicitly stopped.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-30T21:54:37.28145-08:00","created_by":"mayor","updated_at":"2025-12-30T22:09:41.542959-08:00","closed_at":"2025-12-30T22:09:41.542959-08:00","close_reason":"Added Boot shutdown to gt down command. Boot now stopped between Mayor and Deacon."} -{"id":"gt-y07wp","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 18: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:50:59.016254-08:00","updated_at":"2026-01-01T07:50:59.016254-08:00","closed_at":"2026-01-01T07:50:59.016217-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y14l7","title":"Activity stream infrastructure check","description":"Verify activity stream infrastructure exists and is sufficient for MQ/witness events.\n\nCheck:\n- Does gt feed already have event infrastructure?\n- Can we emit custom events from Go code?\n- What format do events need?\n\nIf infrastructure exists, close this. If not, implement minimal event emission.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/cheedo","created_at":"2025-12-28T21:40:18.862686-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-29T23:37:30.258758-08:00","closed_at":"2025-12-29T23:37:30.258758-08:00","close_reason":"## Infrastructure Assessment: SUFFICIENT with minor gaps\n\n### Current Event Infrastructure\n\n1. **townlog** (internal/townlog/logger.go)\n - CAN emit events from Go code\n - Event types: spawn, wake, nudge, handoff, done, crash, kill\n - Output: ~/gt/logs/town.log (text format)\n - Convenience functions: LogSpawn, LogWake, LogNudge, LogDone, etc.\n - Used by: session.go, stop.go, log.go\n\n2. **bd activity** (beads CLI)\n - Shows issue/molecule state changes\n - Events from beads database mutations\n - This IS what gt feed TUI displays\n - To emit events: create/update beads issues\n\n3. **JSONLSource** (internal/tui/feed/events.go:214-290)\n - Ready to read JSONL events from file\n - Format: {timestamp, type, actor, target, message, rig, role}\n - Currently unused (no producer writes to this)\n\n4. **gt feed TUI** (internal/cmd/feed.go)\n - Wraps bd activity in interactive TUI\n - Agent tree + event stream panels\n - Can consume from BdActivitySource or JSONLSource\n\n### Answers to Task Questions\n\nQ: Does gt feed already have event infrastructure?\nA: YES - reads from bd activity (beads mutations) and has JSONLSource ready\n\nQ: Can we emit custom events from Go code?\nA: YES - townlog.Logger.Log() emits events, but they go to text log not activity stream\n\nQ: What format do events need?\nA: For gt feed: JSONL with {timestamp, type, actor, target, message, rig, role}\n\n### Gap Analysis\n\nFor MQ/Witness events to appear in gt feed, dependent tasks need to either:\n\n**Option A** (Recommended): Extend townlog to dual-write\n- Add new EventTypes (patrol_started, merge_started, etc.)\n- Write to JSONL file in addition to text log\n- Update gt feed to also consume from this file\n- ~50-100 lines of changes\n\n**Option B**: Use beads issues\n- Create operational beads for patrol cycles, merge requests\n- Their state changes appear automatically in bd activity\n- More invasive, creates many ephemeral beads\n\n### Files for Dependent Tasks\n\n- internal/townlog/logger.go - Add event types, dual-write\n- internal/tui/feed/events.go - JSONLSource already exists\n- internal/cmd/feed.go - Add secondary source (if needed)"} -{"id":"gt-y1562","title":"Digest: mol-deacon-patrol","description":"Patrol 132: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:36:05.617133-08:00","updated_at":"2026-01-01T14:36:05.617133-08:00","closed_at":"2026-01-01T14:36:05.61709-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y1mrm","title":"Digest: mol-deacon-patrol","description":"Patrol 61: All agents healthy, 2 convoys in progress, 1 idle dog, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:57:58.51361-08:00","updated_at":"2025-12-31T14:57:58.51361-08:00","closed_at":"2025-12-31T14:57:58.513576-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y24k8","title":"Merge: morsov-mjwcd60m","description":"branch: polecat/morsov-mjwcd60m\ntarget: main\nsource_issue: morsov-mjwcd60m\nrig: gastown\nagent_bead: gt-gastown-polecat-morsov","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T19:58:12.268944-08:00","created_by":"gastown/polecats/morsov","updated_at":"2026-01-01T20:02:35.906493-08:00","closed_at":"2026-01-01T20:02:35.906493-08:00","close_reason":"Merged to main at a16b94ff"} -{"id":"gt-y24km","title":"Phase 1: Add hq- prefix agent bead ID helpers","description":"## Goal\n\nAdd helper functions for town-level agent bead IDs using `hq-` prefix.\n\n## Changes\n\n### internal/beads/agent_ids.go (new file)\n\n```go\n// Town-level agent IDs (hq- prefix, stored in town beads)\nfunc MayorBeadIDTown() string { return \"hq-mayor\" }\nfunc DeaconBeadIDTown() string { return \"hq-deacon\" }\nfunc DogBeadIDTown(name string) string { return fmt.Sprintf(\"hq-dog-%s\", name) }\n\n// Role bead IDs (hq- prefix, stored in town beads)\nfunc RoleBeadID(role string) string { return fmt.Sprintf(\"hq-%s-role\", role) }\n\n// Rig-level agent IDs (rig prefix, stored in rig beads)\n// Keep existing: WitnessBeadID(), RefineryBeadID(), PolecatBeadID()\n```\n\n### Deprecation\n\nMark old functions as deprecated:\n- `MayorBeadID()` → use `MayorBeadIDTown()`\n- `DeaconBeadID()` → use `DeaconBeadIDTown()`\n\n## Testing\n\n- Unit tests for new ID functions\n- Verify IDs match expected format","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/ace","created_at":"2026-01-03T18:42:22.539656-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-03T20:57:54.06747-08:00","closed_at":"2026-01-03T20:57:54.06747-08:00","close_reason":"Implemented in commit 61184f06","dependencies":[{"issue_id":"gt-y24km","depends_on_id":"gt-4r1ph","type":"blocks","created_at":"2026-01-03T18:42:41.966022-08:00","created_by":"gastown/crew/gus"}]} -{"id":"gt-y2cu8","title":"Digest: mol-deacon-patrol","description":"Patrol 1 complete. All agents healthy. No callbacks, convoys, spawns, gates, orphans. 3 rigs monitored.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:37:09.983303-08:00","updated_at":"2025-12-31T16:37:09.983303-08:00","closed_at":"2025-12-31T16:37:09.983259-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y2hvs","title":"Digest: mol-deacon-patrol","description":"Patrol #6: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:21:35.670058-08:00","updated_at":"2025-12-31T06:21:35.670058-08:00","closed_at":"2025-12-31T06:21:35.670023-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y2pg1","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 58: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T13:00:50.995721-08:00","updated_at":"2026-01-01T13:00:50.995721-08:00","closed_at":"2026-01-01T13:00:50.995681-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-y3jb9","title":"Protocol: Type System for Formulas","description":"Protocols define interfaces that formulas implement - a type system for workflows.\n\n## Concept\n\n```toml\n# reviewable.protocol\n[protocol]\nname = \"Reviewable\"\n\n[requires]\nsteps = [\"review\"] # Must have a step tagged \"review\"\noutputs = [\"review_decision\"] # Must produce this\n\n[guarantees]\n\"review completes before any deploy step\"\n```\n\nFormulas declare: `implements = [\"Reviewable\", \"Deployable\"]`\n\nSystem verifies compliance statically.\n\n## Use Cases\n\n1. Ensure all deploy formulas have review steps\n2. Define compliance requirements as protocols\n3. Enable formula discovery: \"Give me all Deployable formulas\"\n4. Validate formula composition compatibility\n\n## Properties\n\n- Static verification (before execution)\n- Composable (protocol can extend protocol)\n- Documentation value (self-describing contracts)\n\n## Open Questions\n\n1. Protocol syntax - embedded in formula or separate files?\n2. Verification timing - cook time? load time?\n3. Protocol versioning - how do protocols evolve?\n4. Inheritance - can protocols extend other protocols?\n\n## Related\n\n- docs/formula_evolution.md - \"Formula Schemas\" section\n- gt-8tmz - molecule algebra\n","status":"closed","priority":4,"issue_type":"epic","created_at":"2025-12-26T01:00:53.856997-08:00","updated_at":"2025-12-28T22:33:22.289063-08:00","closed_at":"2025-12-28T22:33:22.289063-08:00"} -{"id":"gt-y414a","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:40:34.237929-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T19:40:34.287202-08:00","closed_at":"2026-01-05T19:40:34.287202-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:40:34-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-y41ep","title":"Polecat spawn: Environment vars not exported to shell","description":"Polecat sessions set tmux environment but don't export to shell before Claude\n\nIn session/manager.go Start():\n _ = m.tmux.SetEnvironment(sessionID, \"GT_RIG\", m.rig.Name)\n _ = m.tmux.SetEnvironment(sessionID, \"GT_POLECAT\", polecat)\n ...\n command = \"claude --dangerously-skip-permissions\"\n\nCompare to crew_lifecycle.go which exports inline:\n claudeCmd := fmt.Sprintf(\"export GT_ROLE=crew GT_RIG=%s GT_CREW=%s \u0026\u0026 claude ...\")\n\nResult: Claude can't detect polecat identity, falls back to 'mayor', shows wrong hook.\n\nFix: Export GT_ROLE=polecat GT_RIG=X GT_POLECAT=Y inline before running Claude.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-28T14:16:18.410705-08:00","created_by":"mayor","updated_at":"2025-12-28T15:34:03.01152-08:00","closed_at":"2025-12-28T15:34:03.01152-08:00"} -{"id":"gt-y48lp","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:24:31.918553-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T13:24:31.971231-08:00","closed_at":"2026-01-06T13:24:31.971231-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:24:31-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-y4o6a","title":"Digest: mol-deacon-patrol","description":"Patrol 217: All nominal","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:57:31.045346-08:00","updated_at":"2026-01-01T16:57:31.045346-08:00","closed_at":"2026-01-01T16:57:31.04531-08:00","close_reason":"Squashed from 15 wisps","dependencies":[{"issue_id":"gt-y4o6a","depends_on_id":"gt-eph-rtlf","type":"parent-child","created_at":"2026-01-01T16:57:31.046645-08:00","created_by":"deacon"}]} -{"id":"gt-y80vv","title":"Implement sendToQueue() for queue message delivery","description":"Add queue message delivery to internal/mail/router.go.\n\nSEMANTICS:\n- Queue messages are stored in a shared location, NOT individual inboxes\n- Location: {townRoot}/.beads/ with special metadata\n\nMESSAGE METADATA:\nAdd to message struct or use existing fields:\n- queue_name: which queue this belongs to\n- claimed_by: empty until claimed\n- claimed_at: timestamp when claimed\n\nIMPLEMENTATION:\n1. Add sendToQueue(msg *Message) error\n2. Validate sender is eligible (optional, or allow anyone to post)\n3. Create message bead with queue_name in metadata\n4. Message To field should be 'queue:{name}'\n\nFILE: internal/mail/router.go\nPATTERN: Follow sendToList() at line 567 but create ONE copy, not fan-out\n\nDo not implement claim/release yet - just delivery.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/capable","created_at":"2025-12-30T18:15:37.434925-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-30T22:46:14.124613-08:00","closed_at":"2025-12-30T22:46:14.124613-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gt-y80vv","depends_on_id":"gt-xkbze","type":"blocks","created_at":"2025-12-30T18:15:48.198344-08:00","created_by":"gastown/crew/max"}]} -{"id":"gt-y87l7","title":"Session ended: gt-gastown-fury","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:50:11.176258-08:00","created_by":"gastown/polecats/fury","updated_at":"2026-01-05T00:08:31.524963-08:00","closed_at":"2026-01-05T00:08:31.524963-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/fury","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:50:11-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-fury\",\"worker\":\"fury\"}"} -{"id":"gt-y8vqb","title":"Merge: furiosa-mjw1p03l","description":"branch: polecat/furiosa-mjw1p03l\ntarget: main\nsource_issue: furiosa-mjw1p03l\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-01T15:01:56.817897-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-01T15:40:07.524002-08:00","closed_at":"2026-01-01T15:40:07.524002-08:00","close_reason":"Stale MR - branch has no new commits or doesn't exist"} -{"id":"gt-ybo3x","title":"Clarify formula semantics: read-only reference, not instantiated","description":"## Problem\n\nAn agent (likely the Deacon) read the `mol-deacon-patrol.formula.toml` file and created beads from its steps. This is wrong - formulas are reference documents describing a workflow, not templates to be instantiated into trackable work.\n\n## What Happened\n\n1. Formula exists at `.beads/formulas/mol-deacon-patrol.formula.toml`\n2. Deacon (or predecessor agent) created an epic + 9 task beads matching the formula steps\n3. These showed up in `bd ready` (separate bug filed)\n\n## Correct Model\n\n| Artifact | Purpose | Created How |\n|----------|---------|-------------|\n| Formula (.toml) | Reference doc describing workflow | Manual/design |\n| Wisp | Ephemeral execution context | `bd wisp create` (no child beads) |\n| Proto | Template for pour | `bd cook` from formula |\n\n**Formulas should NOT create beads.** They're documentation. When the Deacon runs a patrol, it follows the formula instructions directly - it doesn't need beads for each step.\n\n## Fix Needed\n\n1. Update Deacon template to clarify: \"Follow the formula instructions. Do not create beads from formula steps.\"\n2. Audit what command created the beads - was it `bd wisp create` expanding the formula? If so, that command shouldn't create child beads.\n3. Consider renaming formulas to `.md` if they're just prose instructions.\n\n(Moved from hq-ufiy)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T01:37:33.002642-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-02T17:20:36.582625-08:00","closed_at":"2026-01-02T17:20:36.582625-08:00","close_reason":"Invalid premise. Formulas ARE meant to create beads when poured/wisped - that's the core MEOW design. The actual bug was an agent manually creating issues from formula steps instead of using bd wisp/pour commands."} -{"id":"gt-yd121","title":"Digest: mol-deacon-patrol","description":"Patrol 22: Rotated 10MB daemon log. All agents healthy. 3 polecats idle. No callbacks. 3 convoys in progress.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T13:53:24.839578-08:00","updated_at":"2025-12-31T13:53:24.839578-08:00","closed_at":"2025-12-31T13:53:24.839544-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yda35","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:01:25.759281-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T00:08:31.437395-08:00","closed_at":"2026-01-05T00:08:31.437395-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:01:25-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-yduiv","title":"Session ended: gt-gastown-warboy","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T11:45:33.493544-08:00","created_by":"gastown/polecats/warboy","updated_at":"2026-01-04T16:41:00.381277-08:00","closed_at":"2026-01-04T16:41:00.381277-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/warboy","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T11:45:33-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-warboy\",\"worker\":\"warboy\"}"} -{"id":"gt-yea94","title":"gt unsling uses wrong beads dir for remote agents","description":"**Bug**: `gt unsling \u003ctarget-agent\u003e` searches the local beads directory instead of the target agent's rig beads.\n\n**Reproduction**:\n```bash\n# From gastown/crew/max:\ngt status # Shows joe has hook gt-7aw1m\ngt unsling gastown/crew/joe -f # Says 'No work hooked'\n```\n\n**Root cause**: `internal/cmd/unsling.go:88` calls `findLocalBeadsDir()` which uses cwd.\n\n**Fix**: When `targetAgent` is set, resolve the target's rig path and use `beads.New(rigPath)` instead of local beads dir.\n\n**Reference**: `gt status` does this correctly in `discoverRigHooks()` using `beads.New(r.Path)`.","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-01T10:43:51.82557-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-01T10:58:41.22386-08:00","closed_at":"2026-01-01T10:58:41.22386-08:00","close_reason":"Fixed in commit 121150b"} -{"id":"gt-yf8vf","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T23:51:56.34891-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T00:08:31.510421-08:00","closed_at":"2026-01-05T00:08:31.510421-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T23:51:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-yfmee","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All quiet.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T15:54:01.483643-08:00","updated_at":"2025-12-30T15:54:01.483643-08:00","closed_at":"2025-12-30T15:54:01.483592-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yg1vb","title":"Digest: mol-deacon-patrol","description":"Patrol #17: Health pinged all refineries.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:22:18.704138-08:00","updated_at":"2025-12-31T19:22:18.704138-08:00","closed_at":"2025-12-31T19:22:18.704106-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yg8bs","title":"Make documentation convoy-first","description":"Update all gt/gastown documentation to be convoy-first:\n\n1. Reference docs: Show convoy create before sling in examples\n2. CLAUDE.md / mayor priming: Convoy is the standard workflow\n3. User docs: convoy list as primary dashboard view\n4. Remove/update any 'just sling' examples that skip convoy\n\nConvoy is the primary unit of work tracking. All slings should be part of a convoy.","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/rictus","created_at":"2025-12-31T13:07:09.155457-08:00","created_by":"mayor","updated_at":"2025-12-31T13:14:34.265256-08:00","closed_at":"2025-12-31T13:14:34.265256-08:00","close_reason":"Updated README.md, reference.md, understanding-gas-town.md, mayor.md.tmpl, and crew.md.tmpl to be convoy-first"} -{"id":"gt-yh7f3","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:33:51.633656-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-05T21:33:51.68171-08:00","closed_at":"2026-01-05T21:33:51.68171-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:33:51-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-yheg9","title":"Digest: mol-deacon-patrol","description":"Patrol 4: All clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T15:34:01.074755-08:00","updated_at":"2025-12-25T15:34:01.074755-08:00","closed_at":"2025-12-25T15:34:01.074729-08:00"} -{"id":"gt-yhil2","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:34:07.294583-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T21:34:07.34278-08:00","closed_at":"2026-01-05T21:34:07.34278-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:34:07-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-yi5nn","title":"Digest: mol-deacon-patrol","description":"Patrol 5: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:05:03.977673-08:00","updated_at":"2025-12-28T03:05:03.977673-08:00","closed_at":"2025-12-28T03:05:03.977631-08:00"} -{"id":"gt-yi9mn","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T22:37:22.796519-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.759483-08:00","closed_at":"2026-01-05T00:08:31.759483-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T22:37:22-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-yjg7a","title":"Day 2.5: Test daemon pokes based on agent state","description":"Integration test:\n1. Create agent bead with state=idle\n2. Sling work → hook_bead set\n3. Verify daemon pokes\n4. Update state=running\n5. Verify daemon doesn't double-poke\n6. Update state=stopped\n7. Verify daemon re-pokes on new work\n\nParent: gt-d0jqp","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:17.188749-08:00","created_by":"mayor","updated_at":"2025-12-28T02:05:51.46199-08:00","closed_at":"2025-12-28T02:05:51.46199-08:00","dependencies":[{"issue_id":"gt-yjg7a","depends_on_id":"gt-psuw7","type":"blocks","created_at":"2025-12-27T20:58:53.582272-08:00","created_by":"daemon"},{"issue_id":"gt-yjg7a","depends_on_id":"gt-5eegv","type":"blocks","created_at":"2025-12-27T20:58:53.639034-08:00","created_by":"daemon"},{"issue_id":"gt-yjg7a","depends_on_id":"gt-2hzl4","type":"blocks","created_at":"2025-12-27T20:58:53.698582-08:00","created_by":"daemon"}]} -{"id":"gt-yn4xf","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T00:03:46.012072-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.393225-08:00","closed_at":"2026-01-05T00:08:31.393225-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T00:03:45-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-yn7vk","title":"Digest: mol-deacon-patrol","description":"Patrol 2: 3 rigs healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T04:22:06.845356-08:00","updated_at":"2026-01-01T04:22:06.845356-08:00","closed_at":"2026-01-01T04:22:06.845324-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yo8q8","title":"Digest: mol-deacon-patrol","description":"Patrol 12: all clear","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T08:17:55.490764-08:00","updated_at":"2025-12-28T08:17:55.490764-08:00","closed_at":"2025-12-28T08:17:55.490728-08:00"} -{"id":"gt-yot5o","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 47: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:54:40.462877-08:00","updated_at":"2026-01-01T12:54:40.462877-08:00","closed_at":"2026-01-01T12:54:40.462833-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yoyyu","title":"Session ended: gt-gastown-ace","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T20:52:23.900545-08:00","created_by":"gastown/polecats/ace","updated_at":"2026-01-04T16:41:26.030115-08:00","closed_at":"2026-01-04T16:41:26.030115-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/ace","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T20:52:23-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-ace\",\"worker\":\"ace\"}"} -{"id":"gt-yp0yu","title":"Digest: mol-deacon-patrol","description":"Patrol 13: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T19:47:37.589573-08:00","updated_at":"2025-12-28T19:47:37.589573-08:00","closed_at":"2025-12-28T19:47:37.589542-08:00"} -{"id":"gt-ypz3z","title":"Digest: mol-deacon-patrol","description":"Patrol 10: Routine. All 3 rigs healthy. 12 polecats. 1 MQ pending.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T22:55:07.417819-08:00","updated_at":"2026-01-01T22:55:07.417819-08:00","closed_at":"2026-01-01T22:55:07.41778-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-yq00s","title":"Session ended: gt-gastown-nightrider","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T10:42:18.929817-08:00","created_by":"gastown/polecats/nightrider","updated_at":"2026-01-04T16:40:22.86235-08:00","closed_at":"2026-01-04T16:40:22.86235-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/nightrider","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T10:42:18-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-nightrider\",\"worker\":\"nightrider\"}"} -{"id":"gt-yqfrx","title":"Fix convoy refresh scheduling causing duplicates","description":"model.go:191-197 schedules both fetchConvoys() and convoyRefreshTick() on every update, potentially causing duplicate refreshes. The tick should only be scheduled once initially.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-30T23:21:57.55483-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-30T23:23:34.661711-08:00","closed_at":"2025-12-30T23:23:34.661711-08:00","close_reason":"Fixed in commit 4178940"} -{"id":"gt-yqxcq","title":"Merge: furiosa-1767141944421","description":"branch: polecat/furiosa-1767141944421\ntarget: main\nsource_issue: furiosa-1767141944421\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:49:14.137177-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T18:23:22.139493-08:00","closed_at":"2025-12-30T18:23:22.139493-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-ysiot","title":"Session ended: gt-gastown-dinki","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T14:26:42.7361-08:00","created_by":"gastown/polecats/dinki","updated_at":"2026-01-04T16:40:13.497365-08:00","closed_at":"2026-01-04T16:40:13.497365-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/dinki","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T14:26:42-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-dinki\",\"worker\":\"dinki\"}"} -{"id":"gt-ysjju","title":"Digest: mol-deacon-patrol","description":"Patrol 114: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:12:55.247651-08:00","updated_at":"2026-01-01T14:12:55.247651-08:00","closed_at":"2026-01-01T14:12:55.247614-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yskrz","title":"Crew CLAUDE.md overwritten by polecat template","description":"The crew worker CLAUDE.md files (crew/max, crew/joe, crew/jack) have been overwritten with the polecat-CLAUDE.md template content.\n\n**Expected**: Crew workers should have mayor-like context (they share the rig repo, work on main branch, plan work)\n\n**Actual**: Crew CLAUDE.md says 'Polecat ace' and includes polecat-specific instructions (don't push to main, wait for Witness to kill session, etc.)\n\n**Impact**: \n- Crew workers getting wrong identity context\n- Ready Front planning guidance in gotchas section was lost\n- Crew workers told not to push to main (but they should)\n\n**Root cause**: Likely gt polecat template deployment hit crew directories\n\n**Fix needed**:\n- Restore crew CLAUDE.md template (or create one if missing)\n- Ensure template deployment only targets polecats/ directories\n- Add Ready Front planning section to crew template","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/morsov","created_at":"2025-12-28T21:38:53.66113-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-29T22:08:03.491829-08:00","closed_at":"2025-12-29T22:08:03.491829-08:00","close_reason":"Fixed crew CLAUDE.md files:\n1. Regenerated with correct crew template (not polecat template)\n2. Added CLAUDE.md to .gitignore to prevent cross-clone contamination\n3. Each crew member now has their own CLAUDE.md with correct identity"} -{"id":"gt-ysvxq","title":"gt mail archive: accept multiple message IDs","description":"Currently `gt mail archive` only accepts one message ID. Should accept variadic args like:\n\n```\ngt mail archive hq-t9j0u hq-jdxlb hq-cfl5j hq-osed0\n```\n\nThis matches the pattern of `bd close \u003cid1\u003e \u003cid2\u003e ...` which accepts multiple IDs.\n\nImplementation: Update the cobra command to accept multiple args and loop over them.","status":"closed","priority":3,"issue_type":"feature","assignee":"gastown/polecats/rictus","created_at":"2026-01-03T15:23:58.611739-08:00","created_by":"mayor","updated_at":"2026-01-03T15:27:12.281516-08:00","closed_at":"2026-01-03T15:27:12.281516-08:00","close_reason":"Updated gt mail archive to accept variadic message IDs"} -{"id":"gt-yt4py","title":"gt polecat add should spawn with --dangerously-skip-permissions","description":"When adding polecats via gt polecat add, the subsequent Claude session needs --dangerously-skip-permissions flag to run autonomously.\n\nCurrently:\n- gt polecat add creates worktree\n- tmux new-session spawns 'claude' without flags\n- Polecat gets stuck at permission prompts\n\nNeeded:\n- gt polecat add (or gt sling) should spawn with --dangerously-skip-permissions\n- Or store a config in polecat worktree indicating autonomous mode\n\nThis is critical for swarm automation - polecats can't self-approve permissions.","status":"hooked","priority":2,"issue_type":"feature","assignee":"gastown/polecats/dementus","created_at":"2025-12-28T16:31:53.841788-08:00","created_by":"mayor","updated_at":"2025-12-30T00:07:53.183681-08:00"} -{"id":"gt-ytsxp","title":"Refinery emits activity events","description":"Refinery emits events to activity stream for MQ lifecycle:\n\nEvents to emit:\n- merge_started: When refinery begins processing an MR\n- merged: When MR successfully merged to main\n- merge_failed: When merge fails (conflict, tests, etc.)\n- merge_skipped: When MR skipped (already merged, etc.)\n\nEvents should include: MR ID, worker, branch, timestamp, reason (for failures)\n\nThis replaces stats tracking in .runtime/refinery.json","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-28T21:40:19.81217-08:00","created_by":"gastown/crew/jack","updated_at":"2025-12-29T23:46:47.080947-08:00","closed_at":"2025-12-29T23:46:47.080947-08:00","close_reason":"Implemented all MQ lifecycle events in refinery: merge_started, merged, merge_failed, merge_skipped","dependencies":[{"issue_id":"gt-ytsxp","depends_on_id":"gt-y14l7","type":"blocks","created_at":"2025-12-28T21:41:11.499026-08:00","created_by":"daemon"}]} -{"id":"gt-yu9j2","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15: All 6 agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T10:27:18.735797-08:00","updated_at":"2026-01-01T10:27:18.735797-08:00","closed_at":"2026-01-01T10:27:18.735768-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yud21","title":"gt peek should support cross-rig crew paths like beads/crew/dave","description":"## Problem\n\n`gt peek beads/crew/dave` fails with \"session not found\" even when the session exists.\n\nThe command expects `\u003crig/polecat\u003e` format but crew workers in other rigs use\n`\u003crig\u003e/crew/\u003cname\u003e` paths.\n\n## Current behavior\n\n```bash\ngt peek beads/crew/dave\n# Error: session not found\n```\n\n## Expected behavior\n\n```bash\ngt peek beads/crew/dave\n# Should peek at the beads rig crew member dave\n```\n\n## Fix\n\nThe peek command should:\n1. Parse paths with `/crew/` as crew workers, not polecats\n2. Resolve cross-rig crew sessions correctly\n3. Handle both `rig/polecat` and `rig/crew/name` formats","status":"closed","priority":2,"issue_type":"bug","assignee":"gastown/polecats/nux","created_at":"2025-12-31T12:56:15.471634-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-31T13:27:40.115211-08:00","closed_at":"2025-12-31T13:27:40.115211-08:00","close_reason":"Fixed: gt peek now checks for crew/ prefix in polecatName and uses crewSessionName() to generate correct session name"} -{"id":"gt-yuduv","title":"Digest: mol-deacon-patrol","description":"Patrol 10: Quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:04:52.954991-08:00","updated_at":"2025-12-31T19:04:52.954991-08:00","closed_at":"2025-12-31T19:04:52.95495-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yun6y","title":"Digest: mol-deacon-patrol","description":"Patrol 47: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T02:20:15.297464-08:00","updated_at":"2026-01-01T02:20:15.297464-08:00","closed_at":"2026-01-01T02:20:15.297429-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yvhtu","title":"Digest: mol-deacon-patrol","description":"Patrol 109: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:08:34.316126-08:00","updated_at":"2026-01-01T14:08:34.316126-08:00","closed_at":"2026-01-01T14:08:34.316088-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yvl3l","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 14","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:04:14.514718-08:00","updated_at":"2026-01-01T20:04:14.514718-08:00","closed_at":"2026-01-01T20:04:14.514679-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-yw31o","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:17:37.518931-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.273508-08:00","closed_at":"2026-01-04T16:40:13.273508-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:17:37-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-ywfjn","title":"Digest: mol-deacon-patrol","description":"Patrol 10: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:07:27.55403-08:00","updated_at":"2025-12-27T23:07:27.55403-08:00","closed_at":"2025-12-27T23:07:27.553999-08:00"} -{"id":"gt-yxn7l","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 20: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:22:51.027105-08:00","updated_at":"2025-12-28T11:22:51.027105-08:00","closed_at":"2025-12-28T11:22:51.027075-08:00"} -{"id":"gt-yxor2","title":"Digest: mol-deacon-patrol","description":"Patrol 84: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T03:02:33.232745-08:00","updated_at":"2026-01-01T03:02:33.232745-08:00","closed_at":"2026-01-01T03:02:33.232711-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yyff1","title":"Digest: mol-deacon-patrol","description":"Patrol 143 complete: All agents healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:58:29.591244-08:00","updated_at":"2025-12-31T15:58:29.591244-08:00","closed_at":"2025-12-31T15:58:29.591207-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yyht4","title":"Rig management commands for town startup/shutdown","status":"closed","priority":2,"issue_type":"epic","assignee":"gastown/polecats/cheedo","created_at":"2026-01-02T11:49:34.069898-08:00","created_by":"mayor","updated_at":"2026-01-02T17:15:58.051644-08:00","closed_at":"2026-01-02T17:15:58.051644-08:00","close_reason":"All 5 child commands implemented and verified: gt rig start/stop/status, gt crew start/stop"} -{"id":"gt-yynx3","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T20:37:46.322331-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-05T00:08:31.959275-08:00","closed_at":"2026-01-05T00:08:31.959275-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T20:37:46-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-yyp92","title":"Merge: nightrider-mk02roxa","description":"branch: polecat/nightrider-mk02roxa\ntarget: main\nsource_issue: nightrider-mk02roxa\nrig: gastown\nagent_bead: gt-gastown-polecat-nightrider\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:42:00.629866-08:00","created_by":"gastown/polecats/nightrider","updated_at":"2026-01-04T10:47:18.567125-08:00","closed_at":"2026-01-04T10:47:18.567125-08:00","close_reason":"Already merged at 44e9f81d (duplicate of max's commit)"} -{"id":"gt-yz3ff","title":"Digest: mol-deacon-patrol","description":"Patrol 20: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T09:13:00.519338-08:00","updated_at":"2026-01-01T09:13:00.519338-08:00","closed_at":"2026-01-01T09:13:00.519305-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-yzdoi","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 8","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:02:36.807867-08:00","updated_at":"2026-01-01T20:02:36.807867-08:00","closed_at":"2026-01-01T20:02:36.807819-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-z046m","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 15","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T20:04:24.778276-08:00","updated_at":"2026-01-01T20:04:24.778276-08:00","closed_at":"2026-01-01T20:04:24.778239-08:00","close_reason":"Squashed from 16 wisps"} -{"id":"gt-z04vv","title":"Digest: mol-deacon-patrol","description":"Patrol 65: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:00:21.407353-08:00","updated_at":"2025-12-31T15:00:21.407353-08:00","closed_at":"2025-12-31T15:00:21.40731-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z08mz","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 12: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:16:45.903179-08:00","updated_at":"2026-01-01T06:16:45.903179-08:00","closed_at":"2026-01-01T06:16:45.903141-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z1uew","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:17:20.807586-08:00","updated_at":"2026-01-01T06:17:20.807586-08:00","closed_at":"2026-01-01T06:17:20.80755-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z1y5r","title":"Digest: mol-deacon-patrol","description":"Patrol #14","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T06:23:22.103306-08:00","updated_at":"2025-12-31T06:23:22.103306-08:00","closed_at":"2025-12-31T06:23:22.103276-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z27cd","title":"Merge: furiosa-mjxap5fz","description":"branch: polecat/furiosa-mjxap5fz\ntarget: main\nsource_issue: furiosa-mjxap5fz\nrig: gastown\nagent_bead: gt-gastown-polecat-furiosa","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T12:06:03.625783-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2026-01-02T12:29:03.163993-08:00","closed_at":"2026-01-02T12:29:03.163993-08:00","close_reason":"Merged to main at b81c4760"} -{"id":"gt-z3rf","title":"Remove schedule/phase terminology from code","description":"Temporal/schedule language in identifiers is an anti-pattern.\n\n## Found Issues\n\n### beads repo\n- `examples/multi-phase-development/` directory\n - Rename to `examples/dependency-sequenced-work/` or similar\n\n### gastown repo \n- `internal/cmd/start.go` lines 178-195\n - Uses \"Phase 1:\", \"Phase 2:\", etc. in printf output\n - Change to descriptive names: \"Interrupting agents...\", \"Requesting handoff...\", etc.\n\n- `internal/swarm/landing.go` lines ~50-70\n - Comments say \"// Phase 1: Stop all polecat sessions\"\n - Change to \"// Step: Stop all polecat sessions\" or just remove phase labels\n\n## Why This Matters\n\nPhase/version language in names:\n1. Implies a fixed schedule (antithetical to dependency-driven work)\n2. Creates confusion with molecule \"phases\" (solid/liquid/gas)\n3. Encourages temporal thinking that leads to backwards dependencies\n\n## What To Keep\n\n- Molecule phase terminology (pour/wisp/proto) - this is chemistry, not scheduling\n- Version fields inside files (version: 1) - this is semantic versioning","status":"open","priority":2,"issue_type":"chore","created_at":"2025-12-24T15:57:43.019728-08:00","updated_at":"2025-12-24T15:57:43.019728-08:00"} -{"id":"gt-z3v70","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T14:02:43.402004-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T14:02:43.454492-08:00","closed_at":"2026-01-06T14:02:43.454492-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T14:02:43-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-z45be","title":"Digest: mol-deacon-patrol","description":"Patrol 4: all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:04:05.628716-08:00","updated_at":"2025-12-27T23:04:05.628716-08:00","closed_at":"2025-12-27T23:04:05.628679-08:00"} -{"id":"gt-z4g","title":"Plugin: Plan-to-Epic converter","description":"## Purpose\n\nHelp users create beads epics from various planning inputs.\n\n## Inputs\n- Markdown task lists\n- GitHub issues\n- Linear/Jira exports\n- Free-form descriptions\n- Existing beads epics\n\n## Output\n- Beads epic with properly structured children\n- Dependencies set for wave ordering\n- Priorities assigned\n- Ready for `gt spawn --epic \u003cid\u003e`\n\n## Implementation Options\n\n### Option A: CLI Tool\n```bash\ngt plan import --from github --repo owner/repo --label batch-candidate\ngt plan import --from markdown tasks.md\ngt plan structure \u003cepic-id\u003e # analyze and add dependencies\n```\n\n### Option B: Plugin Agent\nA plugin at `\u003crig\u003e/plugins/plan-oracle/` that:\n- Receives planning requests via mail\n- Analyzes scope and requirements\n- Creates structured beads epic\n- Sets dependencies based on analysis\n\n### Option C: Interactive Mode\n```bash\ngt plan create\n# Walks through questions, creates epic interactively\n```\n\n## Axiom\n\nAs stated: 'The Planning phase should end in the creation of a workable Beads plan.'\n\nThis plugin bridges the gap between human planning and machine-executable work.\n\n## Priority\n\nP2 - Nice to have for MVP. Manual epic creation works for now.\n\n## Note\n\nNo \"swarm IDs\" - output is just a beads epic with children. Workers process it independently.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T02:10:20.663549-08:00","updated_at":"2025-12-16T17:26:41.087304-08:00"} -{"id":"gt-z4hfx","title":"Session ended: gt-gastown-chumbucket","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:14:37.33912-08:00","created_by":"gastown/polecats/chumbucket","updated_at":"2026-01-04T16:40:13.385843-08:00","closed_at":"2026-01-04T16:40:13.385843-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/polecats/chumbucket","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:14:37-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-chumbucket\",\"worker\":\"chumbucket\"}"} -{"id":"gt-z4lxc","title":"Merge: gt-veswi","description":"branch: polecat/toast-mjxm0mmo\ntarget: main\nsource_issue: gt-veswi\nrig: gastown\nagent_bead: gt-mayor","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T17:45:17.815433-08:00","created_by":"mayor","updated_at":"2026-01-02T17:48:10.849395-08:00","closed_at":"2026-01-02T17:48:10.849395-08:00","close_reason":"Merged to main at 1805d5b0 (toast-mjxm0mmo spawn alias)"} -{"id":"gt-z4mqq","title":"Session ended: gt-gastown-crew-joe","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T13:51:11.117184-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-04T16:40:13.530489-08:00","closed_at":"2026-01-04T16:40:13.530489-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/joe","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T13:51:11-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-joe\",\"worker\":\"joe\"}"} -{"id":"gt-z58mq","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 3: All agents healthy, no callbacks, no orphans","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T21:48:13.96716-08:00","updated_at":"2025-12-31T21:48:13.96716-08:00","closed_at":"2025-12-31T21:48:13.967123-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z5bri","title":"Clean up stale issue references in comments","description":"Several code comments reference completed or tombstoned issues as if they're future work:\n\n## Stale \"will do\" comments (issue is closed/done):\n\n1. **daemon/daemon.go:313** - Says \"gt-2hzl4 will add timeout fallback\" but gt-2hzl4 is closed and the fallback is implemented at lifecycle.go:725. Update to past tense or remove.\n\n2. **daemon/lifecycle.go:174** - Says \"to be removed per gt-psuw7\" but gt-psuw7 is closed. Either remove the legacy tmux detection code or update the comment.\n\n## Tombstoned epic references (epic superseded):\n\n3. **keepalive/keepalive_test.go:64** - \"See gt-gaxo epic for rationale\" - gt-gaxo is tombstone.\n\n4. **cmd/doctor.go:100** - \"See gt-gaxo epic for ZFC cleanup rationale\" - gt-gaxo is tombstone.\n\n## Action:\n- Update stale comments to reflect current state\n- Remove or update tombstone references\n- For the lifecycle.go tmux detection: decide if code should stay or go","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2025-12-30T22:22:41.280097-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-30T22:29:31.532097-08:00","closed_at":"2025-12-30T22:29:31.532097-08:00","close_reason":"Closed"} -{"id":"gt-z5q73","title":"Digest: mol-deacon-patrol","description":"Patrol 7: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T20:50:30.49576-08:00","updated_at":"2025-12-25T20:50:30.49576-08:00","closed_at":"2025-12-25T20:50:30.495714-08:00"} -{"id":"gt-z6exe","title":"Digest: mol-deacon-patrol","description":"Patrol 6: quiet","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T01:30:22.944508-08:00","updated_at":"2025-12-28T01:30:22.944508-08:00","closed_at":"2025-12-28T01:30:22.944475-08:00"} -{"id":"gt-z722q","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 4: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T11:20:18.680202-08:00","updated_at":"2025-12-28T11:20:18.680202-08:00","closed_at":"2025-12-28T11:20:18.680167-08:00"} -{"id":"gt-z78hz","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:25:53.999822-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-06T13:25:54.050703-08:00","closed_at":"2026-01-06T13:25:54.050703-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:25:53-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-z7v0b","title":"Digest: mol-deacon-patrol","description":"Patrol 10: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T03:07:12.046971-08:00","updated_at":"2025-12-28T03:07:12.046971-08:00","closed_at":"2025-12-28T03:07:12.046934-08:00"} -{"id":"gt-z99nh","title":"Day 4.2: Implement gt polecat nuke command","description":"Add gt polecat nuke \u003cname\u003e command:\n- Kill the Claude session\n- Delete the worktree\n- Delete the branch\n- Remove agent bead\n- Full cleanup post-merge\n\nParent: gt-4a2qt","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:04.245959-08:00","created_by":"mayor","updated_at":"2025-12-28T14:16:55.595293-08:00","closed_at":"2025-12-28T14:16:55.595293-08:00","dependencies":[{"issue_id":"gt-z99nh","depends_on_id":"gt-4a2qt","type":"parent-child","created_at":"2025-12-27T20:58:44.087816-08:00","created_by":"daemon"},{"issue_id":"gt-z99nh","depends_on_id":"gt-7psb8","type":"blocks","created_at":"2025-12-27T21:00:56.228229-08:00","created_by":"daemon"}]} -{"id":"gt-z9oi3","title":"Digest: mol-deacon-patrol","description":"Patrol 118: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T14:15:57.96229-08:00","updated_at":"2026-01-01T14:15:57.96229-08:00","closed_at":"2026-01-01T14:15:57.96225-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-z9xms","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T12:56:50.472241-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:22.692669-08:00","closed_at":"2026-01-04T16:40:22.692669-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T12:56:50-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-z9xv","title":"Merge: gt-ldk8","description":"branch: polecat/nux\ntarget: main\nsource_issue: gt-ldk8\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T00:18:18.894709-08:00","updated_at":"2025-12-23T01:18:52.583727-08:00","closed_at":"2025-12-23T01:18:52.583727-08:00"} -{"id":"gt-zanca","title":"Merge: morsov-mjxpeg1a","description":"branch: polecat/morsov-mjxpeg1a\ntarget: main\nsource_issue: morsov-mjxpeg1a\nrig: gastown\nagent_bead: gt-gastown-polecat-morsov","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:55:13.243687-08:00","created_by":"gastown/polecats/morsov","updated_at":"2026-01-02T18:56:30.16238-08:00","closed_at":"2026-01-02T18:56:30.16238-08:00","close_reason":"Merged to main at 7f49d1ad"} -{"id":"gt-zat1e","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 10: All healthy.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T06:15:34.918029-08:00","updated_at":"2026-01-01T06:15:34.918029-08:00","closed_at":"2026-01-01T06:15:34.917994-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zb0io","title":"Day 4.3: Polecat self-manages session handoffs","description":"**REVISED**: Session cadence is polecat-managed, not mechanically forced by Witness.\n\nPolecats decide when to cycle their own sessions:\n1. Work through molecule steps sequentially in one session\n2. Close each step as completed (bd close, for activity feed)\n3. Self-initiate handoff when: context filling, logical chunk done, or stuck\n4. Use: gt handoff -s 'Continuing molecule' -m '\u003ccontext notes\u003e'\n\nIf polecat forgets to handoff:\n- Compaction will force it eventually\n- Work continues from hook (molecule state preserved)\n- No work is lost\n\nWitness role changes:\n- Does NOT force recycle between steps\n- DOES monitor for stuck (long idle on same step)\n- DOES use recycle for stuck recovery (not routine step transitions)\n- DOES verify clean state before nuke\n\nThis is more ZFC-compliant: polecats report their own needs.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:05.072193-08:00","created_by":"mayor","updated_at":"2025-12-28T16:12:28.054826-08:00","closed_at":"2025-12-28T16:12:28.054826-08:00","dependencies":[{"issue_id":"gt-zb0io","depends_on_id":"gt-4a2qt","type":"parent-child","created_at":"2025-12-27T20:58:45.294593-08:00","created_by":"daemon"},{"issue_id":"gt-zb0io","depends_on_id":"gt-j9ddg","type":"blocks","created_at":"2025-12-27T20:59:03.237863-08:00","created_by":"daemon"}]} -{"id":"gt-zc6ma","title":"Show actor only when not redundant with bead ID","description":"Currently the feed shows actor even when obvious:\n\n [10:17:37] ✓ gt-s6r44 completed · ... @gastown/crew/max\n\nThe actor should be omitted when:\n- The bead ID already identifies the agent (gt-crew-gastown-joe)\n- The action makes the actor obvious (created by = actor)\n\nFormat should be:\n {timestamp} {symbol} {issue-id} {action} · {title} [@actor if not obvious]\n\nPart of epic gt-u7dxq","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/polecats/toast","created_at":"2025-12-28T11:02:12.679921-08:00","created_by":"gastown/crew/joe","updated_at":"2025-12-29T23:36:06.21804-08:00","closed_at":"2025-12-29T23:36:06.21804-08:00","close_reason":"Implemented actor omission logic in view.go for redundant cases: bead ID identifies agent, or create events"} -{"id":"gt-zdbd8","title":"Review PR #98: improve rig name validation error message","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/gus","created_at":"2026-01-04T10:54:02.084744-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:57:17.759086-08:00","closed_at":"2026-01-04T10:57:17.759086-08:00","close_reason":"PR #98 reviewed and approved"} -{"id":"gt-zdtpw","title":"gt status is slow - needs performance optimization","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/max","created_at":"2025-12-31T11:43:35.051942-08:00","created_by":"mayor","updated_at":"2025-12-31T12:14:16.758795-08:00","closed_at":"2025-12-31T12:14:16.758795-08:00","close_reason":"Optimized from 13s to \u003c1s: --no-daemon for bd calls, bulk agent/hook/session pre-fetching, parallel rig processing, --fast flag for skipping mail"} -{"id":"gt-zdxze","title":"Digest: mol-deacon-patrol","description":"Patrol 77: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:04:08.011945-08:00","updated_at":"2025-12-31T15:04:08.011945-08:00","closed_at":"2025-12-31T15:04:08.01191-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zeumj","title":"Digest: mol-deacon-patrol","description":"Patrol 16 complete","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T16:47:08.074195-08:00","updated_at":"2025-12-31T16:47:08.074195-08:00","closed_at":"2025-12-31T16:47:08.074161-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zeuva","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: all monitors healthy, 1 dog idle, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T22:47:38.019015-08:00","updated_at":"2025-12-31T22:47:38.019015-08:00","closed_at":"2025-12-31T22:47:38.018979-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zh330","title":"Review PR #91: extract town session helpers for DRY shutdown","status":"closed","priority":2,"issue_type":"task","assignee":"gastown/crew/jack","created_at":"2026-01-04T10:54:03.150794-08:00","created_by":"gastown/crew/george","updated_at":"2026-01-04T10:57:42.316016-08:00","closed_at":"2026-01-04T10:57:42.316016-08:00","close_reason":"PR #91 reviewed and approved"} -{"id":"gt-zhijo","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 13: All 3 rigs healthy. No incidents.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T07:47:57.64361-08:00","updated_at":"2026-01-01T07:47:57.64361-08:00","closed_at":"2026-01-01T07:47:57.643574-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zi83f","title":"Remove deprecated SessionBeacon function","description":"\n## Context\n\nThe StartupNudge migration (gt-7pp3l) replaced all SessionBeacon usages with StartupNudge.\n\n## Current State\n\n`SessionBeacon()` in `internal/session/names.go` is now dead code:\n- Function definition exists at line 52\n- No callers remain in the codebase\n\n## Action\n\nRemove the deprecated function:\n```go\n// SessionBeacon generates an identity beacon message for Claude Code sessions.\n// ...\nfunc SessionBeacon(address, molID string) string {\n // ...\n}\n```\n\n## Risk\n\nLow - function is unused. Verify with:\n```bash\ngrep -r 'SessionBeacon' --include='*.go' . | grep -v 'names.go'\n```\n\n## Related\n\n- gt-7pp3l: Migrate startup paths from SessionBeacon to StartupNudge\n- gt-85whr: Agent Startup Consolidation epic (closed)\n","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-31T12:19:37.437569-08:00","created_by":"gastown/crew/gus","updated_at":"2025-12-31T12:26:54.98309-08:00","closed_at":"2025-12-31T12:26:54.98309-08:00","close_reason":"Removed SessionBeacon and documented StartupNudge format in reference.md"} -{"id":"gt-zivp","title":"mol-outpost-assign: Intelligent work routing to outposts","description":"The federation design shows outposts.yaml with a static policy section. Simple preference ordering is fine as config, but intelligent work routing should be a molecule.\n\nCurrent static approach:\n```yaml\npolicy:\n default_preference: [local, gce-burst, cloudrun-burst]\n```\n\nCases requiring cognition:\n- \"This is a long-running research task, route to VM not CloudRun\"\n- \"This touches sensitive code, keep local\"\n- \"These 5 issues are related, batch them to same outpost\"\n- \"CloudRun cost is high today, prefer local even if slower\"\n\n## Molecule: outpost-assign\nIntelligent work-to-outpost routing.\n\n## Step: classify-work\nAnalyze the issue/work item:\n- Expected duration (quick fix vs multi-hour)\n- Resource requirements\n- Sensitivity/security tier\n- Related work (same epic?)\n\n## Step: check-capacity\nQuery outpost status:\n- Current load on each\n- Cost accrued today\n- Health status\n\n## Step: select-outpost\nChoose optimal outpost based on:\n- Work classification\n- Capacity/cost\n- Policy constraints\nNeeds: classify-work, check-capacity\n\n## Step: emit-assignment\nRecord decision in beads for audit.\nNeeds: select-outpost\n\n## Notes\n- This molecule is invoked by Mayor/Witness when spawning\n- Simple cases can short-circuit to static policy\n- Full analysis only for ambiguous cases","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-20T03:26:17.964834-08:00","updated_at":"2025-12-20T03:26:17.964834-08:00"} -{"id":"gt-zjcot","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 50: All healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:56:31.18924-08:00","updated_at":"2026-01-01T12:56:31.18924-08:00","closed_at":"2026-01-01T12:56:31.189205-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zk7wl","title":"#channel resolution for real-time broadcast","description":"Wire tmux scanner into nudge system for #channel addresses.\n\n## Deliverables\n\n1. Parse #channel syntax in nudge:\n - #rig/gastown → nudge all running gastown agents\n - #town → nudge all running agents\n - #witnesses → nudge all running witnesses\n\n2. Broadcast logic:\n - Resolve #channel to running sessions\n - Nudge each session\n - Ephemeral (no storage)\n\n## Dependencies\n- Tmux session scanner (gt-???)\n\n## Acceptance\n- #rig/gastown nudges all running gastown agents\n- Ephemeral, no message storage\n- Graceful handling of no-sessions","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-26T14:52:33.362178-08:00","updated_at":"2025-12-26T14:52:33.362178-08:00","dependencies":[{"issue_id":"gt-zk7wl","depends_on_id":"gt-7grh6","type":"blocks","created_at":"2025-12-26T14:53:11.237315-08:00","created_by":"daemon"}]} -{"id":"gt-zlar4","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 35: All healthy, no incidents","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T12:34:09.074968-08:00","updated_at":"2026-01-01T12:34:09.074968-08:00","closed_at":"2026-01-01T12:34:09.074932-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zlazu","title":"Session ended: gt-gastown-vuvalini","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T16:51:48.567412-08:00","created_by":"gastown/polecats/vuvalini","updated_at":"2026-01-05T00:08:31.988939-08:00","closed_at":"2026-01-05T00:08:31.988939-08:00","close_reason":"Bulk cleanup of stale session-ended events (gt-8tc1v)","event_kind":"session.ended","actor":"gastown/polecats/vuvalini","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T16:51:48-08:00\",\"rig\":\"gastown\",\"role\":\"polecat\",\"session_id\":\"gt-gastown-vuvalini\",\"worker\":\"vuvalini\"}"} -{"id":"gt-zlro5","title":"Refactor patrol context functions to reduce duplication","description":"In prime.go, three patrol context functions are nearly identical (~100 lines each):\n- outputDeaconPatrolContext() - L797-940\n- outputWitnessPatrolContext() - L942-1106\n- outputRefineryPatrolContext() - L1108-1272\n\nThey all:\n1. Check for existing patrol molecule\n2. Auto-spawn if none exists\n3. Display patrol work loop instructions\n\n**Suggested refactor**:\nExtract common logic into a helper:\n```go\nfunc outputPatrolContext(ctx RoleContext, patrolName string, assignee string) {\n // shared logic\n}\n```\n\nThen each role-specific function just calls the helper with appropriate parameters.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-25T22:03:13.712525-08:00","updated_at":"2025-12-25T22:03:13.712525-08:00"} -{"id":"gt-zlszm","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-04T15:48:56.74777-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-04T16:40:13.309808-08:00","closed_at":"2026-01-04T16:40:13.309808-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-04T15:48:56-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-zmznh","title":"Rig identity bead schema and creation","description":"dispatched_by: mayor\n\nDefine and implement rig identity beads (type=rig).\n\nSchema:\n- id: gt-rig-\u003cname\u003e\n- type: rig\n- name: \u003crig-name\u003e\n- repo: \u003cgit-url\u003e\n- prefix: \u003cbeads-prefix\u003e\n- labels: (for operational state)\n\nImplementation:\n- Add type=rig to beads schema\n- Create rig bead during 'gt rig add'\n- Query with 'bd list --type=rig'\n\nThis is foundational - other work depends on it.","status":"in_progress","priority":2,"issue_type":"task","assignee":"gastown/polecats/furiosa","created_at":"2026-01-06T17:36:07.775824-08:00","created_by":"gastown/crew/joe","updated_at":"2026-01-06T18:42:22.88238-08:00"} -{"id":"gt-znma3","title":"gt polecat nuke: Refuse if unpushed commits or open MR","description":"Agent prompts can be ignored. Code cannot.\n\n`gt polecat nuke` should REFUSE to delete a polecat if:\n1. Worktree has unpushed commits\n2. Polecat has open MR beads\n3. Polecat has work on hook\n\nThis is enforcement in code, not just instructions. The command itself should be safe.\n\nUse existing `computeCleanupStatus()` in done.go as reference.","status":"closed","priority":1,"issue_type":"task","assignee":"gastown/polecats/nux","created_at":"2025-12-30T22:56:41.922428-08:00","created_by":"mayor","updated_at":"2025-12-30T23:03:11.19751-08:00","closed_at":"2025-12-30T23:03:11.19751-08:00","close_reason":"Implemented safety checks for gt polecat nuke: unpushed commits, open MR beads, work on hook"} -{"id":"gt-zo6at","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-03T18:02:21.709064-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-04T16:41:26.086735-08:00","closed_at":"2026-01-04T16:41:26.086735-08:00","close_reason":"Archived session telemetry","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-03T18:02:21-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-zoayi","title":"Digest: mol-deacon-patrol","description":"Patrol #10: Milestone - all agents healthy. 1 dog idle. Gastown MQ 1 pending.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T19:19:44.942514-08:00","updated_at":"2025-12-31T19:19:44.942514-08:00","closed_at":"2025-12-31T19:19:44.942477-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zppt4","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T19:29:33.536183-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T19:44:18.378226-08:00","closed_at":"2026-01-05T19:44:18.378226-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T19:29:32-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-zq6sx","title":"Session ended: gt-gastown-crew-gus","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T21:31:18.061896-08:00","created_by":"gastown/crew/gus","updated_at":"2026-01-05T21:31:18.108622-08:00","closed_at":"2026-01-05T21:31:18.108622-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/gus","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T21:31:17-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-gus\",\"worker\":\"gus\"}"} -{"id":"gt-zqt4d","title":"BUG: gt swarm create uses non-existent --mol-type flag on bd update","description":"gt swarm create fails because it tries to use --mol-type=swarm with bd update, but that flag doesn't exist.\n\n## Location\ninternal/cmd/swarm.go lines 241, 252, 661-662\n\n## Problem\n- `bd list --mol-type=swarm` works (flag exists)\n- `bd create --mol-type=swarm` works (flag exists)\n- `bd update --mol-type=swarm` FAILS (flag doesn't exist)\n\n## Fix Options\n1. Add --mol-type flag to bd update command (beads change)\n2. Use labels instead of mol-type for swarm marking\n3. Only set mol-type during bd create, not update\n\n## Reported By\ngus during gt-d46 swarm attempt","status":"closed","priority":1,"issue_type":"bug","assignee":"gastown/polecats/splendid","created_at":"2026-01-01T23:17:07.200893-08:00","created_by":"mayor","updated_at":"2026-01-01T23:22:21.227514-08:00","closed_at":"2026-01-01T23:22:21.227514-08:00","close_reason":"Fixed: removed --mol-type from bd update call, only set during create"} -{"id":"gt-zs83b","title":"Digest: mol-deacon-patrol","description":"Patrol cycle 2: All 6 agents healthy, 3 polecats active (furiosa, nux, obsidian), beads refinery has 1 pending","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T11:14:40.865039-08:00","updated_at":"2026-01-01T11:14:40.865039-08:00","closed_at":"2026-01-01T11:14:40.865004-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zsma7","title":"Daemon sends heartbeat to Mayor instead of Deacon","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-26T17:39:12.038167-08:00","updated_at":"2025-12-27T23:38:08.070841-08:00","closed_at":"2025-12-27T23:38:08.070841-08:00"} -{"id":"gt-ztm3","title":"Merge: gt-caih","description":"branch: polecat/furiosa\ntarget: main\nsource_issue: gt-caih\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T00:14:08.420722-08:00","updated_at":"2025-12-23T01:18:52.590603-08:00","closed_at":"2025-12-23T01:18:52.590603-08:00"} -{"id":"gt-ztpe8","title":"Day 4.4: Witness calls nuke after MERGED signal","description":"When refinery sends MERGED:\n1. Witness receives MERGED mail\n2. Witness calls gt polecat nuke\n3. Full sandbox cleanup\n4. Agent bead removed\n\nParent: gt-4a2qt","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-27T20:58:06.121096-08:00","created_by":"mayor","updated_at":"2025-12-28T16:12:33.049315-08:00","closed_at":"2025-12-28T16:12:33.049315-08:00","dependencies":[{"issue_id":"gt-ztpe8","depends_on_id":"gt-4a2qt","type":"parent-child","created_at":"2025-12-27T20:58:46.285651-08:00","created_by":"daemon"},{"issue_id":"gt-ztpe8","depends_on_id":"gt-z99nh","type":"blocks","created_at":"2025-12-27T20:59:03.489419-08:00","created_by":"daemon"},{"issue_id":"gt-ztpe8","depends_on_id":"gt-budeb","type":"relates-to","created_at":"2025-12-27T20:59:10.701299-08:00","created_by":"daemon"}]} -{"id":"gt-ztr0k","title":"BranchPushedToRemote: Fetch remote tracking ref if not present locally","description":"BranchPushedToRemote uses RemoteBranchExists (git ls-remote) to check if remote branch exists, but then compares with local origin/branch ref which may not exist if we just pushed.\n\n## Repro\n1. Push a new branch: git push -u origin branch-name\n2. The local tracking ref origin/branch-name may not exist yet\n3. BranchPushedToRemote errors: 'unknown revision origin/branch..HEAD'\n\n## Fix\nIn BranchPushedToRemote, after confirming remote branch exists, run git fetch to ensure we have the local ref before comparing.\n\n## Discovered\nWhile implementing gt-bca67 (require pushed branch before MR creation)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-30T20:54:05.845622-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T22:36:03.257536-08:00","closed_at":"2025-12-30T22:36:03.257536-08:00","close_reason":"Added git fetch before rev-list comparison to ensure local tracking ref exists"} -{"id":"gt-ztzlm","title":"Merge: nux-mk3ex9vy","description":"branch: polecat/nux-mk3ex9vy\ntarget: main\nsource_issue: nux-mk3ex9vy\nrig: gastown\nagent_bead: gt-gastown-polecat-nux\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"open","priority":2,"issue_type":"merge-request","created_at":"2026-01-06T18:45:56.994413-08:00","created_by":"gastown/polecats/nux","updated_at":"2026-01-06T18:45:56.994413-08:00"} -{"id":"gt-zu36c","title":"Session ended: gt-gastown-crew-jack","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-06T13:33:44.486178-08:00","created_by":"gastown/crew/jack","updated_at":"2026-01-06T13:33:44.536846-08:00","closed_at":"2026-01-06T13:33:44.536846-08:00","close_reason":"auto-closed session event","event_kind":"session.ended","actor":"gastown/crew/jack","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-06T13:33:44-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-jack\",\"worker\":\"jack\"}"} -{"id":"gt-zuibe","title":"Digest: mol-deacon-patrol","description":"Patrol 73: Routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T15:02:58.231161-08:00","updated_at":"2025-12-31T15:02:58.231161-08:00","closed_at":"2025-12-31T15:02:58.231128-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zurbo","title":"Session ended: gt-gastown-crew-max","status":"closed","priority":2,"issue_type":"event","created_at":"2026-01-05T16:29:16.501397-08:00","created_by":"gastown/crew/max","updated_at":"2026-01-05T19:44:18.611763-08:00","closed_at":"2026-01-05T19:44:18.611763-08:00","close_reason":"Stale event","event_kind":"session.ended","actor":"gastown/crew/max","payload":"{\"cost_usd\":0,\"ended_at\":\"2026-01-05T16:29:16-08:00\",\"rig\":\"gastown\",\"role\":\"crew\",\"session_id\":\"gt-gastown-crew-max\",\"worker\":\"max\"}"} -{"id":"gt-zuupc","title":"Merge: keeper-mjxpe1ku","description":"branch: polecat/keeper-mjxpe1ku\ntarget: main\nsource_issue: keeper-mjxpe1ku\nrig: gastown\nagent_bead: gt-gastown-polecat-keeper","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-02T18:52:09.685963-08:00","created_by":"gastown/polecats/keeper","updated_at":"2026-01-02T18:54:16.722647-08:00","closed_at":"2026-01-02T18:54:16.722647-08:00","close_reason":"Merged to main at 883997e0"} -{"id":"gt-zvfnu","title":"Merge: furiosa-1767138824776","description":"branch: polecat/furiosa-1767138824776\ntarget: main\nsource_issue: furiosa-1767138824776\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-30T16:09:55.270207-08:00","created_by":"gastown/polecats/furiosa","updated_at":"2025-12-30T18:23:22.179554-08:00","closed_at":"2025-12-30T18:23:22.179554-08:00","close_reason":"Stale MR - cleanup"} -{"id":"gt-zvte2","title":"Standardize agent bead naming: prefix-rig-role-name","description":"## The Problem\n\nAgent bead IDs use INCONSISTENT naming patterns:\n\n| Current (WRONG) | Should Be (prefix-rig-role-name) |\n|-----------------|----------------------------------|\n| gt-witness-gastown | gt-gastown-witness |\n| gt-refinery-gastown | gt-gastown-refinery |\n| gt-crew-gastown-max | gt-gastown-crew-max |\n| gt-polecat-gastown-Toast | gt-gastown-polecat-Toast |\n\nTown-level agents (no rig) are OK:\n- gt-mayor ✓\n- gt-deacon ✓\n\n## The Convention\n\n```\nprefix-rig-role-name\n\nWhere:\n- prefix: always 'gt'\n- rig: rig name (absent for town-level agents)\n- role: witness|refinery|crew|polecat|mayor|deacon\n- name: agent name (absent for singleton roles like witness/refinery)\n```\n\nExamples:\n- `gt-gastown-witness` (rig=gastown, role=witness, no name)\n- `gt-gastown-crew-max` (rig=gastown, role=crew, name=max)\n- `gt-beads-polecat-Toast` (rig=beads, role=polecat, name=Toast)\n- `gt-mayor` (no rig, role=mayor, no name)\n\n## Files to Update\n\n### Agent bead ID generation\n- internal/cmd/status.go (lines 316-335)\n- internal/daemon/lifecycle.go (lines 546-579)\n- internal/cmd/crew_add.go\n- internal/polecat/manager.go\n- internal/rig/manager.go\n- internal/doctor/agent_beads_check.go\n- internal/cmd/prime.go\n- internal/session/names.go (session names vs bead IDs)\n\n### Commands to verify\n- gt status - displays agent beads\n- gt doctor - creates missing agent beads\n- gt rig add - creates witness/refinery beads\n- gt crew add - creates crew beads\n- gt sling - routes by agent ID\n- gt mol status - looks up agent by ID\n\n## Migration\n\n1. Update all ID generation code\n2. Create new agent beads with correct IDs\n3. Migrate hook/role slots to new beads\n4. Update any mail addresses\n5. Delete old incorrectly-named beads\n\n## Also from this session\n\nRole bead slot cleanup was done - CreateAgentBead now calls bd slot set.\nBut legacy description parsing still exists in daemon/lifecycle.go.\n\n## Reference\n- ~/gt/docs/agent-as-bead.md\n- Session 2025-12-29: Fixed role bead patterns (gt-crew-role etc)","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-29T14:10:33.310182-08:00","created_by":"gastown/crew/max","updated_at":"2025-12-29T14:56:14.529153-08:00","closed_at":"2025-12-29T14:56:14.529153-08:00","close_reason":"Completed: standardized agent bead naming to prefix-rig-role-name"} -{"id":"gt-zwcga","title":"Merge: rictus-1767073382273","description":"attached_args: Code review this merge request\n\nbranch: polecat/rictus-1767073382273\ntarget: main\nsource_issue: rictus-1767073382273\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","assignee":"gastown/polecats/dag","created_at":"2025-12-29T21:57:47.577268-08:00","created_by":"gastown/polecats/rictus","updated_at":"2025-12-29T22:03:22.355518-08:00","closed_at":"2025-12-29T22:03:22.355518-08:00","close_reason":"REJECTED: Fix already on main (81b250ee). Branch is stale - merging would revert 10e79789 (swarm worker tracking fix) and other important commits. No action needed."} -{"id":"gt-zwggj","title":"Digest: mol-refinery-patrol","description":"Patrol: Closed 21 merge requests that were already merged to main. All tests passed. Queue now empty.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T01:03:03.874755-08:00","updated_at":"2025-12-30T01:03:03.874755-08:00","closed_at":"2025-12-30T01:03:03.87472-08:00","close_reason":"Squashed from 10 wisps","dependencies":[{"issue_id":"gt-zwggj","depends_on_id":"gt-eph-wnr","type":"parent-child","created_at":"2025-12-30T01:03:03.875706-08:00","created_by":"mayor"}]} -{"id":"gt-zwz2f","title":"Digest: mol-deacon-patrol","description":"Patrol 16: routine","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T18:45:33.776475-08:00","updated_at":"2025-12-26T18:45:33.776475-08:00","closed_at":"2025-12-26T18:45:33.77643-08:00"} -{"id":"gt-zyjlf","title":"Digest: mol-deacon-patrol","description":"Cycle 20: Final health check - all healthy","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T23:57:06.035189-08:00","updated_at":"2025-12-31T23:57:06.035189-08:00","closed_at":"2025-12-31T23:57:06.035154-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zzjoh","title":"Merge: goose-mk02qu5g","description":"branch: polecat/goose-mk02qu5g\ntarget: main\nsource_issue: goose-mk02qu5g\nrig: gastown\nagent_bead: gt-gastown-polecat-goose\nretry_count: 0\nlast_conflict_sha: null\nconflict_task_id: null","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2026-01-04T10:41:20.34927-08:00","created_by":"gastown/polecats/goose","updated_at":"2026-01-04T10:46:40.914633-08:00","closed_at":"2026-01-04T10:46:40.914633-08:00","close_reason":"Already merged (duplicate of toecutter's commit)"} -{"id":"gt-zznky","title":"Digest: mol-deacon-patrol","description":"Patrol 20: All healthy, handoff threshold","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-31T14:25:14.704309-08:00","updated_at":"2025-12-31T14:25:14.704309-08:00","closed_at":"2025-12-31T14:25:14.704274-08:00","close_reason":"Squashed from 15 wisps"} -{"id":"gt-zzpmt","title":"Add GUPP to non-polecat roles (Mayor, Deacon, Witness, Refinery)","description":"GUPP (propulsion nudge after beacon) is only implemented for polecats in session/manager.go.\n\nOther roles have different startup flows but could benefit from similar auto-propulsion:\n- Mayor: mayor/manager.go or wherever mayor session starts\n- Deacon: deacon startup flow\n- Witness: witness startup flow \n- Refinery: refinery startup flow\n\nEach role may need role-specific propulsion message.\n\n(Refiled from bd-8hea)","status":"closed","priority":3,"issue_type":"task","assignee":"gastown/polecats/valkyrie","created_at":"2025-12-31T12:26:36.557501-08:00","created_by":"beads/crew/grip","updated_at":"2026-01-01T18:46:15.458029-08:00","closed_at":"2026-01-01T18:46:15.458029-08:00","close_reason":"Added role-specific PropulsionNudge to Mayor, Deacon, Witness, and Refinery startup flows"} -{"id":"gt-3qw5s","title":"ZFC: Auto-close convoys when tracked issues close via bd close","description":"When bd close closes an issue, check if this issue was tracked by any convoy. If all tracked issues in a convoy are now closed, auto-close the convoy.\n\n## Background\nPR #236 attempted to fix stale convoys by calling gt convoy check in the refinery merge handler. This is a ZFC violation - it couples the refinery to convoy semantics and uses the wrong trigger point.\n\n## Proper ZFC approach\nThe closure event should propagate at the source:\n1. bd close closes an issue\n2. Check if this issue is tracked by any open convoy\n3. For each convoy tracking this issue, check if all tracked issues are now closed\n4. If so, auto-close the convoy\n\n## Implementation notes\n- Add convoy-check logic to bd close command\n- The deacon patrol step check-convoy-completion remains as backup\n\n## Related\n- PR #236 (closed - ZFC violation)\n- Deacon patrol step: check-convoy-completion","status":"open","priority":2,"issue_type":"feature","created_at":"2026-01-07T02:53:47.000000Z","created_by":"gastown/crew/joe","updated_at":"2026-01-07T02:53:47.000000Z"} diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 521ff2e1c..6954dd719 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -19,6 +19,27 @@ var ( statusLineSession string ) +// rigAbbreviations maps rig names to their abbreviations for the statusline. +var rigAbbreviations = map[string]string{ + "design_forge": "df", + "gastown": "gt", + "mediaforge": "mf", + "mt5optimizer": "mt", + "opencode": "oc", + "pod_automation": "pa", + "promptforge": "pf", + "autoaffiliate": "aa", +} + +// abbreviateRigName returns the abbreviated form of a rig name if one exists, +// otherwise returns the original name. +func abbreviateRigName(rigName string) string { + if abbr, ok := rigAbbreviations[rigName]; ok { + return abbr + } + return rigName +} + var statusLineCmd = &cobra.Command{ Use: "status-line", Short: "Output status line content for tmux (internal use)", @@ -85,12 +106,13 @@ func runStatusLine(cmd *cobra.Command, args []string) error { func runWorkerStatusLine(t *tmux.Tmux, session, rigName, polecat, crew, issue string) error { // Determine agent type and identity var icon, identity string + abbrRigName := abbreviateRigName(rigName) if polecat != "" { icon = AgentTypeIcons[AgentPolecat] - identity = fmt.Sprintf("%s/%s", rigName, polecat) + identity = fmt.Sprintf("%s/%s", abbrRigName, polecat) } else if crew != "" { icon = AgentTypeIcons[AgentCrew] - identity = fmt.Sprintf("%s/crew/%s", rigName, crew) + identity = fmt.Sprintf("%s/crew/%s", abbrRigName, crew) } // Get pane's working directory to find workspace @@ -402,18 +424,7 @@ func runMayorStatusLine(t *tmux.Tmux) error { led = "⚫" // Operational but nothing running } } - - // Show polecat count if > 0 - // All icons get 1 space, Park gets 2 - space := " " - if led == "🅿️" { - space = " " - } - display := led + space + rig.name - if status.polecatCount > 0 { - display += fmt.Sprintf("(%d)", status.polecatCount) - } - rigParts = append(rigParts, display) + rigParts = append(rigParts, led+abbreviateRigName(rigName)) } if len(rigParts) > 0 { @@ -556,7 +567,7 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error { } } - identity := fmt.Sprintf("%s/witness", rigName) + identity := fmt.Sprintf("%s/witness", abbreviateRigName(rigName)) // Build status var parts []string @@ -641,7 +652,7 @@ func runRefineryStatusLine(t *tmux.Tmux, rigName string) error { } } - identity := fmt.Sprintf("%s/refinery", rigName) + identity := fmt.Sprintf("%s/refinery", abbreviateRigName(rigName)) // Build status var parts []string diff --git a/internal/cmd/statusline_test.go b/internal/cmd/statusline_test.go index f0fdb0ad0..a75728e61 100644 --- a/internal/cmd/statusline_test.go +++ b/internal/cmd/statusline_test.go @@ -2,6 +2,38 @@ package cmd import "testing" +func TestAbbreviateRigName(t *testing.T) { + tests := []struct { + name string + rigName string + wantAbbr string + }{ + // Known rigs should abbreviate + {"design_forge", "design_forge", "df"}, + {"gastown", "gastown", "gt"}, + {"mediaforge", "mediaforge", "mf"}, + {"mt5optimizer", "mt5optimizer", "mt"}, + {"opencode", "opencode", "oc"}, + {"pod_automation", "pod_automation", "pa"}, + {"promptforge", "promptforge", "pf"}, + {"autoaffiliate", "autoaffiliate", "aa"}, + + // Unknown rigs should return as-is + {"unknown rig", "unknown_rig", "unknown_rig"}, + {"myrig", "myrig", "myrig"}, + {"", "", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := abbreviateRigName(tt.rigName) + if got != tt.wantAbbr { + t.Errorf("abbreviateRigName(%q) = %q, want %q", tt.rigName, got, tt.wantAbbr) + } + }) + } +} + func TestCategorizeSessionRig(t *testing.T) { tests := []struct { session string From da2e6aa4ab5e4d848c0ff1f3c0c55267a5a651cc Mon Sep 17 00:00:00 2001 From: mayor Date: Sun, 11 Jan 2026 18:31:08 +0100 Subject: [PATCH 15/41] =?UTF-8?q?fix(statusline):=20add=20Crew=20icon=20(?= =?UTF-8?q?=F0=9F=91=B7)=20to=20agent=20display?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add AgentCrew to tracked agent types in mayor statusline - Show 👷 icon for crew agents - Display crew count in statusline (e.g., 👷1/5) - Removes crew from skip filter so they're properly tracked Fixes issue where crew agents were not shown in statusline. --- internal/cmd/statusline.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 6954dd719..afad17956 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -286,11 +286,12 @@ func runMayorStatusLine(t *tmux.Tmux) error { AgentWitness: "👁️", AgentRefinery: "🏭", AgentDeacon: "⛪", + AgentCrew: "👷", } // Initialize health tracker for all agent types (always show all types) healthByType := make(map[AgentType]*sessionHealth) - for _, agentType := range []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon} { + for _, agentType := range []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon, AgentCrew} { healthByType[agentType] = &sessionHealth{ icon: agentIcons[agentType], } @@ -307,8 +308,8 @@ func runMayorStatusLine(t *tmux.Tmux) error { continue } - // Skip mayor and crew (not tracked) - if agent.Type == AgentMayor || agent.Type == AgentCrew { + // Skip mayor (viewer of statusline, not tracked) + if agent.Type == AgentMayor { continue } @@ -330,7 +331,7 @@ func runMayorStatusLine(t *tmux.Tmux) error { // Add per-agent-type health in consistent order // Format: 😺1/10 (1 working out of 10 total, 9 idle inferred) // Always show all agent types, even when count is 0 - agentOrder := []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon} + agentOrder := []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon, AgentCrew} var agentParts []string for _, agentType := range agentOrder { health := healthByType[agentType] From ad5c32de95d134f1be49f882b24e83fcdeaf1bef Mon Sep 17 00:00:00 2001 From: rictus Date: Sun, 11 Jan 2026 17:51:52 +0100 Subject: [PATCH 16/41] feat(statusline): order rigs by activity (parked/stopped to the right) Active rigs now appear first (alphabetically), followed by parked/docked rigs (also alphabetically). This makes it easier to see which rigs are operational at a glance. --- internal/cmd/statusline.go | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index afad17956..1a731e9a6 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -347,9 +347,32 @@ func runMayorStatusLine(t *tmux.Tmux) error { // Build rig status display with LED indicators // 🟢 = both witness and refinery running (fully active) // 🟡 = one of witness/refinery running (partially active) - // 🅿️ = parked (nothing running, intentionally paused) - // 🛑 = docked (nothing running, global shutdown) - // ⚫ = operational but nothing running (unexpected state) + // ⚫ = neither running (inactive) + // ⏸️ = parked or docked (intentionally offline) + var rigParts []string + var rigNames []string + for rigName := range rigStatuses { + rigNames = append(rigNames, rigName) + } + + // Sort rigs: active rigs first (alphabetically), then parked/stopped rigs (alphabetically) + sort.Slice(rigNames, func(i, j int) bool { + // Get operational state for each rig + opStateI, _ := getRigOperationalState(townRoot, rigNames[i]) + opStateJ, _ := getRigOperationalState(townRoot, rigNames[j]) + + // Determine if each rig is parked/stopped + iParked := opStateI == "PARKED" || opStateI == "DOCKED" + jParked := opStateJ == "PARKED" || opStateJ == "DOCKED" + + // If both are same state (both parked or both active), sort alphabetically + if iParked == jParked { + return rigNames[i] < rigNames[j] + } + + // Parked rigs go to the right (i.e., sort after active rigs) + return !iParked && jParked + }) // Create sortable rig list type rigInfo struct { From c6f8331c1e5f21590febb3d203561344d1b9b26d Mon Sep 17 00:00:00 2001 From: dementus Date: Sun, 11 Jan 2026 19:04:34 +0100 Subject: [PATCH 17/41] refactor(statusline): move content to left align Move dynamic status content from status-right to status-left to utilize available space and prevent rig name truncation. - SetStatusFormat: Now sets status-right with compact identity - SetDynamicStatus: Now sets status-left with dynamic content - Increased status-left-length to 150 for more space - Removed time from dynamic status (was %H:%M) Fixes hq-s1il --- internal/tmux/tmux.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/tmux/tmux.go b/internal/tmux/tmux.go index 117beacbb..460ccc99b 100644 --- a/internal/tmux/tmux.go +++ b/internal/tmux/tmux.go @@ -860,50 +860,50 @@ var roleIcons = map[string]string{ "health-check": constants.EmojiDeacon, } -// SetStatusFormat configures the left side of the status bar. +// SetStatusFormat configures the right side of the status bar. // Shows compact identity: icon + minimal context func (t *Tmux) SetStatusFormat(session, rig, worker, role string) error { // Get icon for role (empty string if not found) icon := roleIcons[role] // Compact format - icon already identifies role - // Mayor: 🎩 Mayor - // Crew: 👷 gastown/crew/max (full path) - // Polecat: 😺 gastown/Toast - var left string + // Mayor: Mayor 🎩 + // Crew: gastown/crew/max 👷 + // Polecat: gastown/Toast 😺 + var right string if rig == "" { // Town-level agent (Mayor, Deacon) - left = fmt.Sprintf("%s %s ", icon, worker) + right = fmt.Sprintf("%s %s ", worker, icon) } else if role == "crew" { // Crew member - show full path: rig/crew/name - left = fmt.Sprintf("%s %s/crew/%s ", icon, rig, worker) + right = fmt.Sprintf("%s/crew/%s %s ", rig, worker, icon) } else { // Rig-level agent - show rig/worker - left = fmt.Sprintf("%s %s/%s ", icon, rig, worker) + right = fmt.Sprintf("%s/%s %s ", rig, worker, icon) } - if _, err := t.run("set-option", "-t", session, "status-left-length", "25"); err != nil { + if _, err := t.run("set-option", "-t", session, "status-right-length", "25"); err != nil { return err } - _, err := t.run("set-option", "-t", session, "status-left", left) + _, err := t.run("set-option", "-t", session, "status-right", right) return err } -// SetDynamicStatus configures the right side with dynamic content. +// SetDynamicStatus configures the left side with dynamic content. // Uses a shell command that tmux calls periodically to get current status. func (t *Tmux) SetDynamicStatus(session string) error { // tmux calls this command every status-interval seconds // gt status-line reads env vars and mail to build the status - right := fmt.Sprintf(`#(gt status-line --session=%s 2>/dev/null) %%H:%%M`, session) + left := fmt.Sprintf(`#(gt status-line --session=%s 2>/dev/null)`, session) - if _, err := t.run("set-option", "-t", session, "status-right-length", "80"); err != nil { + if _, err := t.run("set-option", "-t", session, "status-left-length", "150"); err != nil { return err } // Set faster refresh for more responsive status if _, err := t.run("set-option", "-t", session, "status-interval", "5"); err != nil { return err } - _, err := t.run("set-option", "-t", session, "status-right", right) + _, err := t.run("set-option", "-t", session, "status-left", left) return err } From 079589749db80c60c4da1350bfbf583ef19bc559 Mon Sep 17 00:00:00 2001 From: Daniel Sauer Date: Sun, 11 Jan 2026 12:13:58 +0100 Subject: [PATCH 18/41] Fix #289: Add feed-stranded-convoys to Deacon patrol The issue describes Mayor not monitoring convoys, but the root cause is that Deacon's patrol loop never called the existing infrastructure (gt convoy stranded + mol-convoy-feed). This implements the daemon-driven convoy progression approach (suggested option #1 in the issue). Changes: - Added feed-stranded-convoys step to mol-deacon-patrol formula - Deacon now runs gt convoy stranded --json each patrol cycle - For each stranded convoy, dispatches mol-convoy-feed dog - Updated dependency chain - Bumped formula version from 8 to 9 --- .../formulas/mol-deacon-patrol.formula.toml | 45 ++++++++++++++++++- .../formulas/mol-deacon-patrol.formula.toml | 45 ++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/.beads/formulas/mol-deacon-patrol.formula.toml b/.beads/formulas/mol-deacon-patrol.formula.toml index aca940d5a..021ea55d8 100644 --- a/.beads/formulas/mol-deacon-patrol.formula.toml +++ b/.beads/formulas/mol-deacon-patrol.formula.toml @@ -23,7 +23,7 @@ Witnesses detect it and escalate to the Mayor. The Deacon's agent bead last_activity timestamp is updated during each patrol cycle. Witnesses check this timestamp to verify health.""" formula = "mol-deacon-patrol" -version = 8 +version = 9 [[steps]] id = "inbox-check" @@ -225,10 +225,51 @@ bd close --reason "All tracked issues completed" **Note**: Convoys support cross-prefix tracking (e.g., hq-* convoy can track gt-*, bd-* issues). Use full IDs when checking.""" +[[steps]] +id = "feed-stranded-convoys" +title = "Feed stranded convoys" +needs = ["check-convoy-completion"] +description = """ +Detect and feed stranded convoys. + +A convoy is "stranded" when it has ready issues (open, unblocked, no assignee) +but no workers are processing them. + +**Step 1: Detect stranded convoys** +```bash +gt convoy stranded --json +``` + +If output is empty or no stranded convoys found, skip to next patrol step. + +**Step 2: For each stranded convoy, dispatch feeding dog** +```bash +# For each convoy ID from the stranded command: +gt sling mol-convoy-feed deacon/dogs --var convoy= +``` + +Use only ONE dog per stranded convoy to avoid thundering herd. +The dog will: load convoy, find ready issues, dispatch to polecats, report back. + +**Step 3: Continue patrol** +Don't wait for dogs to complete. The patrol continues, dogs work asynchronously. +Dog completion reports come via mail in next cycle's inbox-check. + +**Why this fixes issue #289:** +- Mayor creates convoys and slings first batch (strategic role) +- Deacon continuously monitors for stranded state (operational role) +- Dogs automatically dispatch next batch of ready work (execution role) +- No Mayor monitoring loop needed - system is autonomous by design + +**Idle Town Protocol:** +If no active work exists in the town, this step will naturally find no stranded +convoys and skip quickly. The cost is minimal when idle. +""" + [[steps]] id = "resolve-external-deps" title = "Resolve external dependencies" -needs = ["check-convoy-completion"] +needs = ["feed-stranded-convoys"] description = """ Resolve external dependencies across rigs. diff --git a/internal/formula/formulas/mol-deacon-patrol.formula.toml b/internal/formula/formulas/mol-deacon-patrol.formula.toml index aca940d5a..021ea55d8 100644 --- a/internal/formula/formulas/mol-deacon-patrol.formula.toml +++ b/internal/formula/formulas/mol-deacon-patrol.formula.toml @@ -23,7 +23,7 @@ Witnesses detect it and escalate to the Mayor. The Deacon's agent bead last_activity timestamp is updated during each patrol cycle. Witnesses check this timestamp to verify health.""" formula = "mol-deacon-patrol" -version = 8 +version = 9 [[steps]] id = "inbox-check" @@ -225,10 +225,51 @@ bd close --reason "All tracked issues completed" **Note**: Convoys support cross-prefix tracking (e.g., hq-* convoy can track gt-*, bd-* issues). Use full IDs when checking.""" +[[steps]] +id = "feed-stranded-convoys" +title = "Feed stranded convoys" +needs = ["check-convoy-completion"] +description = """ +Detect and feed stranded convoys. + +A convoy is "stranded" when it has ready issues (open, unblocked, no assignee) +but no workers are processing them. + +**Step 1: Detect stranded convoys** +```bash +gt convoy stranded --json +``` + +If output is empty or no stranded convoys found, skip to next patrol step. + +**Step 2: For each stranded convoy, dispatch feeding dog** +```bash +# For each convoy ID from the stranded command: +gt sling mol-convoy-feed deacon/dogs --var convoy= +``` + +Use only ONE dog per stranded convoy to avoid thundering herd. +The dog will: load convoy, find ready issues, dispatch to polecats, report back. + +**Step 3: Continue patrol** +Don't wait for dogs to complete. The patrol continues, dogs work asynchronously. +Dog completion reports come via mail in next cycle's inbox-check. + +**Why this fixes issue #289:** +- Mayor creates convoys and slings first batch (strategic role) +- Deacon continuously monitors for stranded state (operational role) +- Dogs automatically dispatch next batch of ready work (execution role) +- No Mayor monitoring loop needed - system is autonomous by design + +**Idle Town Protocol:** +If no active work exists in the town, this step will naturally find no stranded +convoys and skip quickly. The cost is minimal when idle. +""" + [[steps]] id = "resolve-external-deps" title = "Resolve external dependencies" -needs = ["check-convoy-completion"] +needs = ["feed-stranded-convoys"] description = """ Resolve external dependencies across rigs. From 745bf053962f6a9df6adb2a49a0e535095ae348d Mon Sep 17 00:00:00 2001 From: furiosa Date: Sun, 11 Jan 2026 20:06:41 +0100 Subject: [PATCH 19/41] fix(statusline): remove spaces between counts/text and emojis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed space between counts and emojis (e.g., "3 😺" → "3😺") - Removed space between emojis and counts/subjects (e.g., "📬 3" → "📬3") - Removed space between hook emoji and text (e.g., "🪝 work" → "🪝work") --- internal/cmd/statusline.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 1a731e9a6..dbb3a408c 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -145,7 +145,7 @@ func runWorkerStatusLine(t *tmux.Tmux, session, rigName, polecat, crew, issue st if icon != "" { parts = append(parts, fmt.Sprintf("%s 🪝 %s", icon, hookedWork)) } else { - parts = append(parts, fmt.Sprintf("🪝 %s", hookedWork)) + parts = append(parts, fmt.Sprintf("🪝%s", hookedWork)) } } else if currentWork != "" { // Fall back to current work (in_progress) @@ -163,9 +163,9 @@ func runWorkerStatusLine(t *tmux.Tmux, session, rigName, polecat, crew, issue st unread, subject := getMailPreviewWithRoot(identity, 45, townRoot) if unread > 0 { if subject != "" { - parts = append(parts, fmt.Sprintf("\U0001F4EC %s", subject)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%s", subject)) } else { - parts = append(parts, fmt.Sprintf("\U0001F4EC %d", unread)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%d", unread)) } } } @@ -337,8 +337,8 @@ func runMayorStatusLine(t *tmux.Tmux) error { health := healthByType[agentType] // Always show all agent types (no continue for total == 0) - // Show working/total format (e.g., "1/10 😺" = 1 working, 10 total) - agentParts = append(agentParts, fmt.Sprintf("%d/%d %s", health.working, health.total, health.icon)) + // Show working/total format (e.g., "1/10😺" = 1 working, 10 total) + agentParts = append(agentParts, fmt.Sprintf("%d/%d%s", health.working, health.total, health.icon)) } if len(agentParts) > 0 { parts = append(parts, "active: "+strings.Join(agentParts, " ")) @@ -461,15 +461,15 @@ func runMayorStatusLine(t *tmux.Tmux) error { hookedWork = getHookedWork("mayor", 40, townRoot) } if hookedWork != "" { - parts = append(parts, fmt.Sprintf("🪝 %s", hookedWork)) + parts = append(parts, fmt.Sprintf("🪝%s", hookedWork)) } else if townRoot != "" { // Priority 2: Fall back to mail preview unread, subject := getMailPreviewWithRoot("mayor/", 45, townRoot) if unread > 0 { if subject != "" { - parts = append(parts, fmt.Sprintf("\U0001F4EC %s", subject)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%s", subject)) } else { - parts = append(parts, fmt.Sprintf("\U0001F4EC %d", unread)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%d", unread)) } } } @@ -526,7 +526,7 @@ func runDeaconStatusLine(t *tmux.Tmux) error { // Build status var parts []string parts = append(parts, fmt.Sprintf("%d rigs", rigCount)) - parts = append(parts, fmt.Sprintf("%d 😺", polecatCount)) + parts = append(parts, fmt.Sprintf("%d😺", polecatCount)) // Priority 1: Check for hooked work (town beads for deacon) hookedWork := "" @@ -534,15 +534,15 @@ func runDeaconStatusLine(t *tmux.Tmux) error { hookedWork = getHookedWork("deacon", 35, townRoot) } if hookedWork != "" { - parts = append(parts, fmt.Sprintf("🪝 %s", hookedWork)) + parts = append(parts, fmt.Sprintf("🪝%s", hookedWork)) } else if townRoot != "" { // Priority 2: Fall back to mail preview unread, subject := getMailPreviewWithRoot("deacon/", 40, townRoot) if unread > 0 { if subject != "" { - parts = append(parts, fmt.Sprintf("\U0001F4EC %s", subject)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%s", subject)) } else { - parts = append(parts, fmt.Sprintf("\U0001F4EC %d", unread)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%d", unread)) } } } @@ -595,7 +595,7 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error { // Build status var parts []string - parts = append(parts, fmt.Sprintf("%d 😺", polecatCount)) + parts = append(parts, fmt.Sprintf("%d😺", polecatCount)) if crewCount > 0 { parts = append(parts, fmt.Sprintf("%d crew", crewCount)) } @@ -607,15 +607,15 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error { hookedWork = getHookedWork(identity, 30, rigBeadsDir) } if hookedWork != "" { - parts = append(parts, fmt.Sprintf("🪝 %s", hookedWork)) + parts = append(parts, fmt.Sprintf("🪝%s", hookedWork)) } else if townRoot != "" { // Priority 2: Fall back to mail preview unread, subject := getMailPreviewWithRoot(identity, 35, townRoot) if unread > 0 { if subject != "" { - parts = append(parts, fmt.Sprintf("\U0001F4EC %s", subject)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%s", subject)) } else { - parts = append(parts, fmt.Sprintf("\U0001F4EC %d", unread)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%d", unread)) } } } @@ -698,15 +698,15 @@ func runRefineryStatusLine(t *tmux.Tmux, rigName string) error { hookedWork = getHookedWork(identity, 25, rigBeadsDir) } if hookedWork != "" { - parts = append(parts, fmt.Sprintf("🪝 %s", hookedWork)) + parts = append(parts, fmt.Sprintf("🪝%s", hookedWork)) } else if townRoot != "" { // Priority 2: Fall back to mail preview unread, subject := getMailPreviewWithRoot(identity, 30, townRoot) if unread > 0 { if subject != "" { - parts = append(parts, fmt.Sprintf("\U0001F4EC %s", subject)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%s", subject)) } else { - parts = append(parts, fmt.Sprintf("\U0001F4EC %d", unread)) + parts = append(parts, fmt.Sprintf("\U0001F4EC%d", unread)) } } } From 750db5773abee5cc4b1e7301f418789e0b8a641a Mon Sep 17 00:00:00 2001 From: furiosa Date: Sun, 11 Jan 2026 22:19:40 +0100 Subject: [PATCH 20/41] perf(tmux): eliminate duplicate GetPaneCommand call in IsClaudeRunning IsClaudeRunning was calling IsAgentRunning (which calls GetPaneCommand), then immediately calling GetPaneCommand again. This duplicate subprocess call was slowing down gt startup and daemon heartbeat operations. Changed IsAgentRunning to return (bool, string) - the running status and the pane command it checked. IsClaudeRunning now reuses the command instead of making a redundant tmux subprocess call. Fixes gt-kpii: zombie session detection slows gt up --- internal/cmd/costs.go | 2 +- internal/cmd/crew_at.go | 2 +- internal/cmd/sling.go | 1050 ++++++++++++++++++++++++++++++++++ internal/cmd/start.go | 32 +- internal/refinery/manager.go | 8 +- internal/tmux/tmux.go | 32 +- internal/tmux/tmux_test.go | 6 +- 7 files changed, 1103 insertions(+), 29 deletions(-) diff --git a/internal/cmd/costs.go b/internal/cmd/costs.go index 0967a5419..6337ca756 100644 --- a/internal/cmd/costs.go +++ b/internal/cmd/costs.go @@ -224,7 +224,7 @@ func runLiveCosts() error { cost := extractCost(content) // Check if an agent appears to be running - running := t.IsAgentRunning(session) + running, _ := t.IsAgentRunning(session) costs = append(costs, SessionCost{ Session: session, diff --git a/internal/cmd/crew_at.go b/internal/cmd/crew_at.go index 2a83becae..220b51b8f 100644 --- a/internal/cmd/crew_at.go +++ b/internal/cmd/crew_at.go @@ -225,7 +225,7 @@ func runCrewAt(cmd *cobra.Command, args []string) error { if err != nil { return fmt.Errorf("resolving agent: %w", err) } - if !t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...) { + if running, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); !running { // Runtime has exited, restart it using respawn-pane fmt.Printf("Runtime exited, restarting...\n") diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 22098d206..850a4e9c2 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -463,3 +463,1053 @@ func runSling(cmd *cobra.Command, args []string) error { return nil } + +// storeArgsInBead stores args in the bead's description using attached_args field. +// This enables no-tmux mode where agents discover args via gt prime / bd show. +func storeArgsInBead(beadID, args string) error { + // Get the bead to preserve existing description content + showCmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") + out, err := showCmd.Output() + if err != nil { + return fmt.Errorf("fetching bead: %w", err) + } + + // Parse the bead + var issues []beads.Issue + if err := json.Unmarshal(out, &issues); err != nil { + return fmt.Errorf("parsing bead: %w", err) + } + if len(issues) == 0 { + return fmt.Errorf("bead not found") + } + issue := &issues[0] + + // Get or create attachment fields + fields := beads.ParseAttachmentFields(issue) + if fields == nil { + fields = &beads.AttachmentFields{} + } + + // Set the args + fields.AttachedArgs = args + + // Update the description + newDesc := beads.SetAttachmentFields(issue, fields) + + // Update the bead + updateCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--description="+newDesc) + updateCmd.Stderr = os.Stderr + if err := updateCmd.Run(); err != nil { + return fmt.Errorf("updating bead description: %w", err) + } + + return nil +} + +// storeDispatcherInBead stores the dispatcher agent ID in the bead's description. +// This enables polecats to notify the dispatcher when work is complete. +func storeDispatcherInBead(beadID, dispatcher string) error { + if dispatcher == "" { + return nil + } + + // Get the bead to preserve existing description content + showCmd := exec.Command("bd", "show", beadID, "--json") + out, err := showCmd.Output() + if err != nil { + return fmt.Errorf("fetching bead: %w", err) + } + + // Parse the bead + var issues []beads.Issue + if err := json.Unmarshal(out, &issues); err != nil { + return fmt.Errorf("parsing bead: %w", err) + } + if len(issues) == 0 { + return fmt.Errorf("bead not found") + } + issue := &issues[0] + + // Get or create attachment fields + fields := beads.ParseAttachmentFields(issue) + if fields == nil { + fields = &beads.AttachmentFields{} + } + + // Set the dispatcher + fields.DispatchedBy = dispatcher + + // Update the description + newDesc := beads.SetAttachmentFields(issue, fields) + + // Update the bead + updateCmd := exec.Command("bd", "update", beadID, "--description="+newDesc) + updateCmd.Stderr = os.Stderr + if err := updateCmd.Run(); err != nil { + return fmt.Errorf("updating bead description: %w", err) + } + + return nil +} + +// injectStartPrompt sends a prompt to the target pane to start working. +// Uses the reliable nudge pattern: literal mode + 500ms debounce + separate Enter. +func injectStartPrompt(pane, beadID, subject, args string) error { + if pane == "" { + return fmt.Errorf("no target pane") + } + + // Build the prompt to inject + var prompt string + if args != "" { + // Args provided - include them prominently in the prompt + if subject != "" { + prompt = fmt.Sprintf("Work slung: %s (%s). Args: %s. Start working now - use these args to guide your execution.", beadID, subject, args) + } else { + prompt = fmt.Sprintf("Work slung: %s. Args: %s. Start working now - use these args to guide your execution.", beadID, args) + } + } else if subject != "" { + prompt = fmt.Sprintf("Work slung: %s (%s). Start working on it now - no questions, just begin.", beadID, subject) + } else { + prompt = fmt.Sprintf("Work slung: %s. Start working on it now - run `gt hook` to see the hook, then begin.", beadID) + } + + // Use the reliable nudge pattern (same as gt nudge / tmux.NudgeSession) + t := tmux.NewTmux() + return t.NudgePane(pane, prompt) +} + +// getSessionFromPane extracts session name from a pane target. +// Pane targets can be: +// - "%9" (pane ID) - need to query tmux for session +// - "gt-rig-name:0.0" (session:window.pane) - extract session name +func getSessionFromPane(pane string) string { + if strings.HasPrefix(pane, "%") { + // Pane ID format - query tmux for the session + cmd := exec.Command("tmux", "display-message", "-t", pane, "-p", "#{session_name}") + out, err := cmd.Output() + if err != nil { + return "" + } + return strings.TrimSpace(string(out)) + } + // Session:window.pane format - extract session name + if idx := strings.Index(pane, ":"); idx > 0 { + return pane[:idx] + } + return pane +} + +// ensureAgentReady waits for an agent to be ready before nudging an existing session. +// Uses a pragmatic approach: wait for the pane to leave a shell, then (Claude-only) +// accept the bypass permissions warning and give it a moment to finish initializing. +func ensureAgentReady(sessionName string) error { + t := tmux.NewTmux() + + // If an agent is already running, assume it's ready (session was started earlier) + if running, _ := t.IsAgentRunning(sessionName); running { + return nil + } + + // Agent not running yet - wait for it to start (shell → program transition) + if err := t.WaitForCommand(sessionName, constants.SupportedShells, constants.ClaudeStartTimeout); err != nil { + return fmt.Errorf("waiting for agent to start: %w", err) + } + + // Claude-only: accept bypass permissions warning if present + if t.IsClaudeRunning(sessionName) { + _ = t.AcceptBypassPermissionsWarning(sessionName) + + // PRAGMATIC APPROACH: fixed delay rather than prompt detection. + // Claude startup takes ~5-8 seconds on typical machines. + time.Sleep(8 * time.Second) + } else { + time.Sleep(1 * time.Second) + } + + return nil +} + +// resolveTargetAgent converts a target spec to agent ID, pane, and hook root. +// If skipPane is true, skip tmux pane lookup (for --naked mode). +func resolveTargetAgent(target string, skipPane bool) (agentID string, pane string, hookRoot string, err error) { + // First resolve to session name + sessionName, err := resolveRoleToSession(target) + if err != nil { + return "", "", "", err + } + + // Convert session name to agent ID format (this doesn't require tmux) + agentID = sessionToAgentID(sessionName) + + // Skip pane lookup if requested (--naked mode) + if skipPane { + return agentID, "", "", nil + } + + // Get the pane for that session + pane, err = getSessionPane(sessionName) + if err != nil { + return "", "", "", fmt.Errorf("getting pane for %s: %w", sessionName, err) + } + + // Get the target's working directory for hook storage + t := tmux.NewTmux() + hookRoot, err = t.GetPaneWorkDir(sessionName) + if err != nil { + return "", "", "", fmt.Errorf("getting working dir for %s: %w", sessionName, err) + } + + return agentID, pane, hookRoot, nil +} + +// sessionToAgentID converts a session name to agent ID format. +// Uses session.ParseSessionName for consistent parsing across the codebase. +func sessionToAgentID(sessionName string) string { + identity, err := session.ParseSessionName(sessionName) + if err != nil { + // Fallback for unparseable sessions + return sessionName + } + return identity.Address() +} + +// verifyBeadExists checks that the bead exists using bd show. +// Uses bd's native prefix-based routing via routes.jsonl - do NOT set BEADS_DIR +// as that overrides routing and breaks resolution of rig-level beads. +// +// Uses --no-daemon with --allow-stale to avoid daemon socket timing issues +// while still finding beads when database is out of sync with JSONL. +// For existence checks, stale data is acceptable - we just need to know it exists. +func verifyBeadExists(beadID string) error { + cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") + // Run from town root so bd can find routes.jsonl for prefix-based routing. + // Do NOT set BEADS_DIR - that overrides routing and breaks rig bead resolution. + if townRoot, err := workspace.FindFromCwd(); err == nil { + cmd.Dir = townRoot + } + if err := cmd.Run(); err != nil { + return fmt.Errorf("bead '%s' not found (bd show failed)", beadID) + } + return nil +} + +// beadInfo holds status and assignee for a bead. +type beadInfo struct { + Title string `json:"title"` + Status string `json:"status"` + Assignee string `json:"assignee"` +} + +// getBeadInfo returns status and assignee for a bead. +// Uses bd's native prefix-based routing via routes.jsonl. +// Uses --no-daemon with --allow-stale for consistency with verifyBeadExists. +func getBeadInfo(beadID string) (*beadInfo, error) { + cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") + // Run from town root so bd can find routes.jsonl for prefix-based routing. + if townRoot, err := workspace.FindFromCwd(); err == nil { + cmd.Dir = townRoot + } + out, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("bead '%s' not found", beadID) + } + // bd show --json returns an array (issue + dependents), take first element + var infos []beadInfo + if err := json.Unmarshal(out, &infos); err != nil { + return nil, fmt.Errorf("parsing bead info: %w", err) + } + if len(infos) == 0 { + return nil, fmt.Errorf("bead '%s' not found", beadID) + } + return &infos[0], nil +} + +// detectCloneRoot finds the root of the current git clone. +func detectCloneRoot() (string, error) { + cmd := exec.Command("git", "rev-parse", "--show-toplevel") + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("not in a git repository") + } + return strings.TrimSpace(string(out)), nil +} + +// resolveSelfTarget determines agent identity, pane, and hook root for slinging to self. +func resolveSelfTarget() (agentID string, pane string, hookRoot string, err error) { + roleInfo, err := GetRole() + if err != nil { + return "", "", "", fmt.Errorf("detecting role: %w", err) + } + + // Build agent identity from role + // Town-level agents use trailing slash to match addressToIdentity() normalization + switch roleInfo.Role { + case RoleMayor: + agentID = "mayor/" + case RoleDeacon: + agentID = "deacon/" + case RoleWitness: + agentID = fmt.Sprintf("%s/witness", roleInfo.Rig) + case RoleRefinery: + agentID = fmt.Sprintf("%s/refinery", roleInfo.Rig) + case RolePolecat: + agentID = fmt.Sprintf("%s/polecats/%s", roleInfo.Rig, roleInfo.Polecat) + case RoleCrew: + agentID = fmt.Sprintf("%s/crew/%s", roleInfo.Rig, roleInfo.Polecat) + default: + return "", "", "", fmt.Errorf("cannot determine agent identity (role: %s)", roleInfo.Role) + } + + pane = os.Getenv("TMUX_PANE") + hookRoot = roleInfo.Home + if hookRoot == "" { + // Fallback to git root if home not determined + hookRoot, err = detectCloneRoot() + if err != nil { + return "", "", "", fmt.Errorf("detecting clone root: %w", err) + } + } + + return agentID, pane, hookRoot, nil +} + +// verifyFormulaExists checks that the formula exists using bd formula show. +// Formulas are TOML files (.formula.toml). +// Uses --no-daemon with --allow-stale for consistency with verifyBeadExists. +func verifyFormulaExists(formulaName string) error { + // Try bd formula show (handles all formula file formats) + cmd := exec.Command("bd", "--no-daemon", "formula", "show", formulaName, "--allow-stale") + if err := cmd.Run(); err == nil { + return nil + } + + // Try with mol- prefix + cmd = exec.Command("bd", "--no-daemon", "formula", "show", "mol-"+formulaName, "--allow-stale") + if err := cmd.Run(); err == nil { + return nil + } + + return fmt.Errorf("formula '%s' not found (check 'bd formula list')", formulaName) +} + +// runSlingFormula handles standalone formula slinging. +// Flow: cook → wisp → attach to hook → nudge +func runSlingFormula(args []string) error { + formulaName := args[0] + + // Get town root early - needed for BEADS_DIR when running bd commands + townRoot, err := workspace.FindFromCwd() + if err != nil { + return fmt.Errorf("finding town root: %w", err) + } + townBeadsDir := filepath.Join(townRoot, ".beads") + + // Determine target (self or specified) + var target string + if len(args) > 1 { + target = args[1] + } + + // Resolve target agent and pane + var targetAgent string + var targetPane string + + if target != "" { + // Resolve "." to current agent identity (like git's "." meaning current directory) + if target == "." { + targetAgent, targetPane, _, err = resolveSelfTarget() + if err != nil { + return fmt.Errorf("resolving self for '.' target: %w", err) + } + } else if dogName, isDog := IsDogTarget(target); isDog { + if slingDryRun { + if dogName == "" { + fmt.Printf("Would dispatch to idle dog in kennel\n") + } else { + fmt.Printf("Would dispatch to dog '%s'\n", dogName) + } + targetAgent = fmt.Sprintf("deacon/dogs/%s", dogName) + if dogName == "" { + targetAgent = "deacon/dogs/" + } + targetPane = "" + } else { + // Dispatch to dog + dispatchInfo, dispatchErr := DispatchToDog(dogName, slingCreate) + if dispatchErr != nil { + return fmt.Errorf("dispatching to dog: %w", dispatchErr) + } + targetAgent = dispatchInfo.AgentID + targetPane = dispatchInfo.Pane + fmt.Printf("Dispatched to dog %s\n", dispatchInfo.DogName) + } + } else if rigName, isRig := IsRigName(target); isRig { + // Check if target is a rig name (auto-spawn polecat) + if slingDryRun { + // Dry run - just indicate what would happen + fmt.Printf("Would spawn fresh polecat in rig '%s'\n", rigName) + if slingNaked { + fmt.Printf(" --naked: would skip tmux session\n") + } + targetAgent = fmt.Sprintf("%s/polecats/", rigName) + targetPane = "" + } else { + // Spawn a fresh polecat in the rig + fmt.Printf("Target is rig '%s', spawning fresh polecat...\n", rigName) + spawnOpts := SlingSpawnOptions{ + Force: slingForce, + Naked: slingNaked, + Account: slingAccount, + Create: slingCreate, + Agent: slingAgent, + } + spawnInfo, spawnErr := SpawnPolecatForSling(rigName, spawnOpts) + if spawnErr != nil { + return fmt.Errorf("spawning polecat: %w", spawnErr) + } + targetAgent = spawnInfo.AgentID() + targetPane = spawnInfo.Pane + + // Wake witness and refinery to monitor the new polecat + wakeRigAgents(rigName) + } + } else { + // Slinging to an existing agent + // Skip pane lookup if --naked (agent may be terminated) + var targetWorkDir string + targetAgent, targetPane, targetWorkDir, err = resolveTargetAgent(target, slingNaked) + if err != nil { + return fmt.Errorf("resolving target: %w", err) + } + // Use target's working directory for bd commands (needed for redirect-based routing) + _ = targetWorkDir // Formula sling doesn't need hookWorkDir + } + } else { + // Slinging to self + var selfWorkDir string + targetAgent, targetPane, selfWorkDir, err = resolveSelfTarget() + if err != nil { + return err + } + _ = selfWorkDir // Formula sling doesn't need hookWorkDir + } + + fmt.Printf("%s Slinging formula %s to %s...\n", style.Bold.Render("🎯"), formulaName, targetAgent) + + if slingDryRun { + fmt.Printf("Would cook formula: %s\n", formulaName) + fmt.Printf("Would create wisp and pin to: %s\n", targetAgent) + for _, v := range slingVars { + fmt.Printf(" --var %s\n", v) + } + fmt.Printf("Would nudge pane: %s\n", targetPane) + return nil + } + + // Step 1: Cook the formula (ensures proto exists) + fmt.Printf(" Cooking formula...\n") + cookArgs := []string{"--no-daemon", "cook", formulaName} + cookCmd := exec.Command("bd", cookArgs...) + cookCmd.Stderr = os.Stderr + if err := cookCmd.Run(); err != nil { + return fmt.Errorf("cooking formula: %w", err) + } + + // Step 2: Create wisp instance (ephemeral) + fmt.Printf(" Creating wisp...\n") + wispArgs := []string{"--no-daemon", "mol", "wisp", formulaName} + for _, v := range slingVars { + wispArgs = append(wispArgs, "--var", v) + } + wispArgs = append(wispArgs, "--json") + + wispCmd := exec.Command("bd", wispArgs...) + wispCmd.Stderr = os.Stderr // Show wisp errors to user + wispOut, err := wispCmd.Output() + if err != nil { + return fmt.Errorf("creating wisp: %w", err) + } + + // Parse wisp output to get the root ID + wispRootID, err := parseWispIDFromJSON(wispOut) + if err != nil { + return fmt.Errorf("parsing wisp output: %w", err) + } + + fmt.Printf("%s Wisp created: %s\n", style.Bold.Render("✓"), wispRootID) + + // Step 3: Hook the wisp bead using bd update. + // See: https://github.com/steveyegge/gastown/issues/148 + hookCmd := exec.Command("bd", "--no-daemon", "update", wispRootID, "--status=hooked", "--assignee="+targetAgent) + hookCmd.Dir = beads.ResolveHookDir(townRoot, wispRootID, "") + hookCmd.Stderr = os.Stderr + if err := hookCmd.Run(); err != nil { + return fmt.Errorf("hooking wisp bead: %w", err) + } + fmt.Printf("%s Attached to hook (status=hooked)\n", style.Bold.Render("✓")) + + // Log sling event to activity feed (formula slinging) + actor := detectActor() + payload := events.SlingPayload(wispRootID, targetAgent) + payload["formula"] = formulaName + _ = events.LogFeed(events.TypeSling, actor, payload) + + // Update agent bead's hook_bead field (ZFC: agents track their current work) + // Note: formula slinging uses town root as workDir (no polecat-specific path) + updateAgentHookBead(targetAgent, wispRootID, "", townBeadsDir) + + // Store dispatcher in bead description (enables completion notification to dispatcher) + if err := storeDispatcherInBead(wispRootID, actor); err != nil { + // Warn but don't fail - polecat will still complete work + fmt.Printf("%s Could not store dispatcher in bead: %v\n", style.Dim.Render("Warning:"), err) + } + + // Store args in wisp bead if provided (no-tmux mode: beads as data plane) + if slingArgs != "" { + if err := storeArgsInBead(wispRootID, slingArgs); err != nil { + fmt.Printf("%s Could not store args in bead: %v\n", style.Dim.Render("Warning:"), err) + } else { + fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓")) + } + } + + // Step 4: Nudge to start (graceful if no tmux) + if targetPane == "" { + fmt.Printf("%s No pane to nudge (agent will discover work via gt prime)\n", style.Dim.Render("○")) + return nil + } + + var prompt string + if slingArgs != "" { + prompt = fmt.Sprintf("Formula %s slung. Args: %s. Run `gt hook` to see your hook, then execute using these args.", formulaName, slingArgs) + } else { + prompt = fmt.Sprintf("Formula %s slung. Run `gt hook` to see your hook, then execute the steps.", formulaName) + } + t := tmux.NewTmux() + if err := t.NudgePane(targetPane, prompt); err != nil { + // Graceful fallback for no-tmux mode + fmt.Printf("%s Could not nudge (no tmux?): %v\n", style.Dim.Render("○"), err) + fmt.Printf(" Agent will discover work via gt prime / bd show\n") + } else { + fmt.Printf("%s Nudged to start\n", style.Bold.Render("▶")) + } + + return nil +} + +// updateAgentHookBead updates the agent bead's state and hook when work is slung. +// This enables the witness to see that each agent is working. +// +// We run from the polecat's workDir (which redirects to the rig's beads database) +// WITHOUT setting BEADS_DIR, so the redirect mechanism works for gt-* agent beads. +// +// For rig-level beads (same database), we set the hook_bead slot directly. +// For cross-database scenarios (agent in rig db, hook bead in town db), +// the slot set may fail - this is handled gracefully with a warning. +// The work is still correctly attached via `bd update --assignee=`. +func updateAgentHookBead(agentID, beadID, workDir, townBeadsDir string) { + _ = townBeadsDir // Not used - BEADS_DIR breaks redirect mechanism + + // Determine the directory to run bd commands from: + // - If workDir is provided (polecat's clone path), use it for redirect-based routing + // - Otherwise fall back to town root + bdWorkDir := workDir + townRoot, err := workspace.FindFromCwd() + if err != nil { + // Not in a Gas Town workspace - can't update agent bead + fmt.Fprintf(os.Stderr, "Warning: couldn't find town root to update agent hook: %v\n", err) + return + } + if bdWorkDir == "" { + bdWorkDir = townRoot + } + + // Convert agent ID to agent bead ID + // Format examples (canonical: prefix-rig-role-name): + // greenplace/crew/max -> gt-greenplace-crew-max + // greenplace/polecats/Toast -> gt-greenplace-polecat-Toast + // mayor -> hq-mayor + // greenplace/witness -> gt-greenplace-witness + agentBeadID := agentIDToBeadID(agentID, townRoot) + if agentBeadID == "" { + return + } + + // Run from workDir WITHOUT BEADS_DIR to enable redirect-based routing. + // Set hook_bead to the slung work (gt-zecmc: removed agent_state update). + // Agent liveness is observable from tmux - no need to record it in bead. + // For cross-database scenarios, slot set may fail gracefully (warning only). + bd := beads.New(bdWorkDir) + if err := bd.SetHookBead(agentBeadID, beadID); err != nil { + // Log warning instead of silent ignore - helps debug cross-beads issues + fmt.Fprintf(os.Stderr, "Warning: couldn't set agent %s hook: %v\n", agentBeadID, err) + return + } +} + +// wakeRigAgents wakes the witness and refinery for a rig after polecat dispatch. +// This ensures the patrol agents are ready to monitor and merge. +func wakeRigAgents(rigName string) { + // Boot the rig (idempotent - no-op if already running) + bootCmd := exec.Command("gt", "rig", "boot", rigName) + _ = bootCmd.Run() // Ignore errors - rig might already be running + + // Nudge witness and refinery to clear any backoff + t := tmux.NewTmux() + witnessSession := fmt.Sprintf("gt-%s-witness", rigName) + refinerySession := fmt.Sprintf("gt-%s-refinery", rigName) + + // Silent nudges - sessions might not exist yet + _ = t.NudgeSession(witnessSession, "Polecat dispatched - check for work") + _ = t.NudgeSession(refinerySession, "Polecat dispatched - check for merge requests") +} + +// detectActor returns the current agent's actor string for event logging. +func detectActor() string { + roleInfo, err := GetRole() + if err != nil { + return "unknown" + } + return roleInfo.ActorString() +} + +// agentIDToBeadID converts an agent ID to its corresponding agent bead ID. +// Uses canonical naming: prefix-rig-role-name +// Town-level agents (Mayor, Deacon) use hq- prefix and are stored in town beads. +// Rig-level agents use the rig's configured prefix (default "gt-"). +// townRoot is needed to look up the rig's configured prefix. +func agentIDToBeadID(agentID, townRoot string) string { + // Handle simple cases (town-level agents with hq- prefix) + if agentID == "mayor" { + return beads.MayorBeadIDTown() + } + if agentID == "deacon" { + return beads.DeaconBeadIDTown() + } + + // Parse path-style agent IDs + parts := strings.Split(agentID, "/") + if len(parts) < 2 { + return "" + } + + rig := parts[0] + prefix := config.GetRigPrefix(townRoot, rig) + + switch { + case len(parts) == 2 && parts[1] == "witness": + return beads.WitnessBeadIDWithPrefix(prefix, rig) + case len(parts) == 2 && parts[1] == "refinery": + return beads.RefineryBeadIDWithPrefix(prefix, rig) + case len(parts) == 3 && parts[1] == "crew": + return beads.CrewBeadIDWithPrefix(prefix, rig, parts[2]) + case len(parts) == 3 && parts[1] == "polecats": + return beads.PolecatBeadIDWithPrefix(prefix, rig, parts[2]) + default: + return "" + } +} + +// IsDogTarget checks if target is a dog target pattern. +// Returns the dog name (or empty for pool dispatch) and true if it's a dog target. +// Patterns: +// - "deacon/dogs" -> ("", true) - dispatch to any idle dog +// - "deacon/dogs/alpha" -> ("alpha", true) - dispatch to specific dog +func IsDogTarget(target string) (dogName string, isDog bool) { + target = strings.ToLower(target) + + // Check for exact "deacon/dogs" (pool dispatch) + if target == "deacon/dogs" { + return "", true + } + + // Check for "deacon/dogs/" (specific dog) + if strings.HasPrefix(target, "deacon/dogs/") { + name := strings.TrimPrefix(target, "deacon/dogs/") + if name != "" && !strings.Contains(name, "/") { + return name, true + } + } + + return "", false +} + +// DogDispatchInfo contains information about a dog dispatch. +type DogDispatchInfo struct { + DogName string // Name of the dog + AgentID string // Agent ID format (deacon/dogs/) + Pane string // Tmux pane (empty if no session) + Spawned bool // True if dog was spawned (new) +} + +// DispatchToDog finds or spawns a dog for work dispatch. +// If dogName is empty, finds an idle dog from the pool. +// If create is true and no dogs exist, creates one. +func DispatchToDog(dogName string, create bool) (*DogDispatchInfo, error) { + townRoot, err := workspace.FindFromCwd() + if err != nil { + return nil, fmt.Errorf("finding town root: %w", err) + } + + rigsConfigPath := filepath.Join(townRoot, "mayor", "rigs.json") + rigsConfig, err := config.LoadRigsConfig(rigsConfigPath) + if err != nil { + return nil, fmt.Errorf("loading rigs config: %w", err) + } + + mgr := dog.NewManager(townRoot, rigsConfig) + + var targetDog *dog.Dog + var spawned bool + + if dogName != "" { + // Specific dog requested + targetDog, err = mgr.Get(dogName) + if err != nil { + if create { + // Create the dog if it doesn't exist + targetDog, err = mgr.Add(dogName) + if err != nil { + return nil, fmt.Errorf("creating dog %s: %w", dogName, err) + } + fmt.Printf("✓ Created dog %s\n", dogName) + spawned = true + } else { + return nil, fmt.Errorf("dog %s not found (use --create to add)", dogName) + } + } + } else { + // Pool dispatch - find an idle dog + targetDog, err = mgr.GetIdleDog() + if err != nil { + return nil, fmt.Errorf("finding idle dog: %w", err) + } + + if targetDog == nil { + if create { + // No idle dogs - create one + newName := generateDogName(mgr) + targetDog, err = mgr.Add(newName) + if err != nil { + return nil, fmt.Errorf("creating dog %s: %w", newName, err) + } + fmt.Printf("✓ Created dog %s (pool was empty)\n", newName) + spawned = true + } else { + return nil, fmt.Errorf("no idle dogs available (use --create to add)") + } + } + } + + // Mark dog as working + if err := mgr.SetState(targetDog.Name, dog.StateWorking); err != nil { + return nil, fmt.Errorf("setting dog state: %w", err) + } + + // Build agent ID + agentID := fmt.Sprintf("deacon/dogs/%s", targetDog.Name) + + // Try to find tmux session for the dog (dogs may run in tmux like polecats) + // Dogs use the pattern gt-{town}-deacon-{name} + townName, _ := workspace.GetTownName(townRoot) + sessionName := fmt.Sprintf("gt-%s-deacon-%s", townName, targetDog.Name) + t := tmux.NewTmux() + var pane string + if has, _ := t.HasSession(sessionName); has { + // Get the pane from the session + pane, _ = getSessionPane(sessionName) + } + + return &DogDispatchInfo{ + DogName: targetDog.Name, + AgentID: agentID, + Pane: pane, + Spawned: spawned, + }, nil +} + +// generateDogName creates a unique dog name for pool expansion. +func generateDogName(mgr *dog.Manager) string { + // Use Greek alphabet for dog names + names := []string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"} + + dogs, _ := mgr.List() + existing := make(map[string]bool) + for _, d := range dogs { + existing[d.Name] = true + } + + for _, name := range names { + if !existing[name] { + return name + } + } + + // Fallback: numbered dogs + for i := 1; i <= 100; i++ { + name := fmt.Sprintf("dog%d", i) + if !existing[name] { + return name + } + } + + return fmt.Sprintf("dog%d", len(dogs)+1) +} + +// slingGenerateShortID generates a short random ID (5 lowercase chars). +func slingGenerateShortID() string { + b := make([]byte, 3) + _, _ = rand.Read(b) + return strings.ToLower(base32.StdEncoding.EncodeToString(b)[:5]) +} + +// isTrackedByConvoy checks if an issue is already being tracked by a convoy. +// Returns the convoy ID if tracked, empty string otherwise. +func isTrackedByConvoy(beadID string) string { + townRoot, err := workspace.FindFromCwd() + if err != nil { + return "" + } + + // Query town beads for any convoy that tracks this issue + // Convoys use "tracks" dependency type: convoy -> tracked issue + townBeads := filepath.Join(townRoot, ".beads") + dbPath := filepath.Join(townBeads, "beads.db") + + // Query dependencies where this bead is being tracked + // Also check for external reference format: external:rig:issue-id + query := fmt.Sprintf(` + SELECT d.issue_id + FROM dependencies d + JOIN issues i ON d.issue_id = i.id + WHERE d.type = 'tracks' + AND i.issue_type = 'convoy' + AND (d.depends_on_id = '%s' OR d.depends_on_id LIKE '%%:%s') + LIMIT 1 + `, beadID, beadID) + + queryCmd := exec.Command("sqlite3", dbPath, query) + out, err := queryCmd.Output() + if err != nil { + return "" + } + + convoyID := strings.TrimSpace(string(out)) + return convoyID +} + +// createAutoConvoy creates an auto-convoy for a single issue and tracks it. +// Returns the created convoy ID. +func createAutoConvoy(beadID, beadTitle string) (string, error) { + townRoot, err := workspace.FindFromCwd() + if err != nil { + return "", fmt.Errorf("finding town root: %w", err) + } + + townBeads := filepath.Join(townRoot, ".beads") + + // Generate convoy ID with cv- prefix + convoyID := fmt.Sprintf("hq-cv-%s", slingGenerateShortID()) + + // Create convoy with title "Work: " + convoyTitle := fmt.Sprintf("Work: %s", beadTitle) + description := fmt.Sprintf("Auto-created convoy tracking %s", beadID) + + createArgs := []string{ + "create", + "--type=convoy", + "--id=" + convoyID, + "--title=" + convoyTitle, + "--description=" + description, + } + + createCmd := exec.Command("bd", append([]string{"--no-daemon"}, createArgs...)...) + createCmd.Dir = townBeads + createCmd.Stderr = os.Stderr + + if err := createCmd.Run(); err != nil { + return "", fmt.Errorf("creating convoy: %w", err) + } + + // Add tracking relation: convoy tracks the issue + trackBeadID := formatTrackBeadID(beadID) + depArgs := []string{"--no-daemon", "dep", "add", convoyID, trackBeadID, "--type=tracks"} + depCmd := exec.Command("bd", depArgs...) + depCmd.Dir = townBeads + depCmd.Stderr = os.Stderr + + if err := depCmd.Run(); err != nil { + // Convoy was created but tracking failed - log warning but continue + fmt.Printf("%s Could not add tracking relation: %v\n", style.Dim.Render("Warning:"), err) + } + + return convoyID, nil +} + +// runBatchSling handles slinging multiple beads to a rig. +// Each bead gets its own freshly spawned polecat. +func runBatchSling(beadIDs []string, rigName string, townBeadsDir string) error { + // Validate all beads exist before spawning any polecats + for _, beadID := range beadIDs { + if err := verifyBeadExists(beadID); err != nil { + return fmt.Errorf("bead '%s' not found", beadID) + } + } + + if slingDryRun { + fmt.Printf("%s Batch slinging %d beads to rig '%s':\n", style.Bold.Render("🎯"), len(beadIDs), rigName) + for _, beadID := range beadIDs { + fmt.Printf(" Would spawn polecat for: %s\n", beadID) + } + if slingNaked { + fmt.Printf(" --naked: would skip tmux sessions\n") + } + return nil + } + + fmt.Printf("%s Batch slinging %d beads to rig '%s'...\n", style.Bold.Render("🎯"), len(beadIDs), rigName) + + // Track results for summary + type slingResult struct { + beadID string + polecat string + success bool + errMsg string + } + results := make([]slingResult, 0, len(beadIDs)) + + // Spawn a polecat for each bead and sling it + for i, beadID := range beadIDs { + fmt.Printf("\n[%d/%d] Slinging %s...\n", i+1, len(beadIDs), beadID) + + // Check bead status + info, err := getBeadInfo(beadID) + if err != nil { + results = append(results, slingResult{beadID: beadID, success: false, errMsg: err.Error()}) + fmt.Printf(" %s Could not get bead info: %v\n", style.Dim.Render("✗"), err) + continue + } + + if info.Status == "pinned" && !slingForce { + results = append(results, slingResult{beadID: beadID, success: false, errMsg: "already pinned"}) + fmt.Printf(" %s Already pinned (use --force to re-sling)\n", style.Dim.Render("✗")) + continue + } + + // Spawn a fresh polecat + spawnOpts := SlingSpawnOptions{ + Force: slingForce, + Naked: slingNaked, + Account: slingAccount, + Create: slingCreate, + HookBead: beadID, // Set atomically at spawn time + Agent: slingAgent, + } + spawnInfo, err := SpawnPolecatForSling(rigName, spawnOpts) + if err != nil { + results = append(results, slingResult{beadID: beadID, success: false, errMsg: err.Error()}) + fmt.Printf(" %s Failed to spawn polecat: %v\n", style.Dim.Render("✗"), err) + continue + } + + targetAgent := spawnInfo.AgentID() + hookWorkDir := spawnInfo.ClonePath + + // Auto-convoy: check if issue is already tracked + if !slingNoConvoy { + existingConvoy := isTrackedByConvoy(beadID) + if existingConvoy == "" { + convoyID, err := createAutoConvoy(beadID, info.Title) + if err != nil { + fmt.Printf(" %s Could not create auto-convoy: %v\n", style.Dim.Render("Warning:"), err) + } else { + fmt.Printf(" %s Created convoy 🚚 %s\n", style.Bold.Render("→"), convoyID) + } + } else { + fmt.Printf(" %s Already tracked by convoy %s\n", style.Dim.Render("○"), existingConvoy) + } + } + + // Hook the bead. See: https://github.com/steveyegge/gastown/issues/148 + townRoot := filepath.Dir(townBeadsDir) + hookCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--status=hooked", "--assignee="+targetAgent) + hookCmd.Dir = beads.ResolveHookDir(townRoot, beadID, hookWorkDir) + hookCmd.Stderr = os.Stderr + if err := hookCmd.Run(); err != nil { + results = append(results, slingResult{beadID: beadID, polecat: spawnInfo.PolecatName, success: false, errMsg: "hook failed"}) + fmt.Printf(" %s Failed to hook bead: %v\n", style.Dim.Render("✗"), err) + continue + } + + fmt.Printf(" %s Work attached to %s\n", style.Bold.Render("✓"), spawnInfo.PolecatName) + + // Log sling event + actor := detectActor() + _ = events.LogFeed(events.TypeSling, actor, events.SlingPayload(beadID, targetAgent)) + + // Update agent bead state + updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir) + + // Store args if provided + if slingArgs != "" { + if err := storeArgsInBead(beadID, slingArgs); err != nil { + fmt.Printf(" %s Could not store args: %v\n", style.Dim.Render("Warning:"), err) + } + } + + // Nudge the polecat + if spawnInfo.Pane != "" { + if err := injectStartPrompt(spawnInfo.Pane, beadID, slingSubject, slingArgs); err != nil { + fmt.Printf(" %s Could not nudge (agent will discover via gt prime)\n", style.Dim.Render("○")) + } else { + fmt.Printf(" %s Start prompt sent\n", style.Bold.Render("▶")) + } + } + + results = append(results, slingResult{beadID: beadID, polecat: spawnInfo.PolecatName, success: true}) + } + + // Wake witness and refinery once at the end + wakeRigAgents(rigName) + + // Print summary + successCount := 0 + for _, r := range results { + if r.success { + successCount++ + } + } + + fmt.Printf("\n%s Batch sling complete: %d/%d succeeded\n", style.Bold.Render("📊"), successCount, len(beadIDs)) + if successCount < len(beadIDs) { + for _, r := range results { + if !r.success { + fmt.Printf(" %s %s: %s\n", style.Dim.Render("✗"), r.beadID, r.errMsg) + } + } + } + + return nil +} + +// formatTrackBeadID formats a bead ID for use in convoy tracking dependencies. +// Cross-rig beads (non-hq- prefixed) are formatted as external references +// so the bd tool can resolve them when running from HQ context. +// +// Examples: +// - "hq-abc123" -> "hq-abc123" (HQ beads unchanged) +// - "gt-mol-xyz" -> "external:gt-mol:gt-mol-xyz" +// - "beads-task-123" -> "external:beads-task:beads-task-123" +func formatTrackBeadID(beadID string) string { + if strings.HasPrefix(beadID, "hq-") { + return beadID + } + parts := strings.SplitN(beadID, "-", 3) + if len(parts) >= 2 { + rigPrefix := parts[0] + "-" + parts[1] + return fmt.Sprintf("external:%s:%s", rigPrefix, beadID) + } + // Fallback for malformed IDs (single segment) + return beadID +} diff --git a/internal/cmd/start.go b/internal/cmd/start.go index cae239c84..08f5a7316 100644 --- a/internal/cmd/start.go +++ b/internal/cmd/start.go @@ -354,15 +354,29 @@ func startConfiguredCrew(t *tmux.Tmux, rigs []*rig.Rig, townRoot string, mu *syn for _, r := range rigs { crewToStart := getCrewToStart(r) for _, crewName := range crewToStart { - wg.Add(1) - go func(r *rig.Rig, crewName string) { - defer wg.Done() - msg, started := startOrRestartCrewMember(t, r, crewName, townRoot) - mu.Lock() - fmt.Print(msg) - mu.Unlock() - if started { - atomic.StoreInt32(&startedAny, 1) + sessionID := crewSessionName(r.Name, crewName) + if sessionExists, _ := t.HasSession(sessionID); sessionExists { + // Session exists - check if Claude is still running + agentCfg := config.ResolveAgentConfig(townRoot, r.Path) + if running, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); !running { + // Claude has exited, restart it + fmt.Printf(" %s %s/%s session exists, restarting Claude...\n", style.Dim.Render("○"), r.Name, crewName) + // Build startup beacon for predecessor discovery via /resume + address := fmt.Sprintf("%s/crew/%s", r.Name, crewName) + beacon := session.FormatStartupNudge(session.StartupNudgeConfig{ + Recipient: address, + Sender: "human", + Topic: "restart", + }) + claudeCmd := config.BuildCrewStartupCommand(r.Name, crewName, r.Path, beacon) + if err := t.SendKeys(sessionID, claudeCmd); err != nil { + fmt.Printf(" %s %s/%s restart failed: %v\n", style.Dim.Render("○"), r.Name, crewName, err) + } else { + fmt.Printf(" %s %s/%s Claude restarted\n", style.Bold.Render("✓"), r.Name, crewName) + startedAny = true + } + } else { + fmt.Printf(" %s %s/%s already running\n", style.Dim.Render("○"), r.Name, crewName) } }(r, crewName) } diff --git a/internal/refinery/manager.go b/internal/refinery/manager.go index c6b39c687..a8e7d473d 100644 --- a/internal/refinery/manager.go +++ b/internal/refinery/manager.go @@ -116,8 +116,10 @@ func (m *Manager) Start(foreground bool) error { // In foreground mode, check tmux session (no PID inference per ZFC) townRoot := filepath.Dir(m.rig.Path) agentCfg := config.ResolveAgentConfig(townRoot, m.rig.Path) - if running, _ := t.HasSession(sessionID); running && t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...) { - return ErrAlreadyRunning + if running, _ := t.HasSession(sessionID); running { + if agentRunning, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); agentRunning { + return ErrAlreadyRunning + } } // Running in foreground - update state and run the Go-based polling loop @@ -140,7 +142,7 @@ func (m *Manager) Start(foreground bool) error { // Session exists - check if Claude is actually running (healthy vs zombie) townRoot := filepath.Dir(m.rig.Path) agentCfg := config.ResolveAgentConfig(townRoot, m.rig.Path) - if t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...) { + if agentRunning, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); agentRunning { // Healthy - Claude is running return ErrAlreadyRunning } diff --git a/internal/tmux/tmux.go b/internal/tmux/tmux.go index 460ccc99b..7fbc82825 100644 --- a/internal/tmux/tmux.go +++ b/internal/tmux/tmux.go @@ -112,7 +112,7 @@ func (t *Tmux) EnsureSessionFresh(name, workDir string) error { if exists { // Session exists - check if it's a zombie - if !t.IsAgentRunning(name) { + if running, _ := t.IsAgentRunning(name); !running { // Zombie session: tmux alive but Claude dead // Kill it so we can create a fresh one if err := t.KillSession(name); err != nil { @@ -617,28 +617,29 @@ Run: gt mail inbox // // If expectedPaneCommands is non-empty, the pane's current command must match one of them. // If expectedPaneCommands is empty, any non-shell command counts as "agent running". -func (t *Tmux) IsAgentRunning(session string, expectedPaneCommands ...string) bool { +// Returns the pane command that was checked (for reuse by callers to avoid duplicate subprocess calls). +func (t *Tmux) IsAgentRunning(session string, expectedPaneCommands ...string) (bool, string) { cmd, err := t.GetPaneCommand(session) if err != nil { - return false + return false, "" } if len(expectedPaneCommands) > 0 { for _, expected := range expectedPaneCommands { if expected != "" && cmd == expected { - return true + return true, cmd } } - return false + return false, cmd } // Fallback: any non-shell command counts as running. for _, shell := range constants.SupportedShells { if cmd == shell { - return false + return false, cmd } } - return cmd != "" + return cmd != "", cmd } // IsClaudeRunning checks if Claude appears to be running in the session. @@ -646,14 +647,21 @@ func (t *Tmux) IsAgentRunning(session string, expectedPaneCommands ...string) bo // Claude can report as "node", "claude", or a version number like "2.0.76". // Also checks for child processes when the pane is a shell running claude via "bash -c". func (t *Tmux) IsClaudeRunning(session string) bool { - // Check for known command names first - if t.IsAgentRunning(session, "node", "claude") { + // Check for known command names first. + // IsAgentRunning returns the command it checked, avoiding a duplicate GetPaneCommand call. + running, cmd := t.IsAgentRunning(session, "node", "claude") + if running { return true } // Check for version pattern (e.g., "2.0.76") - Claude Code shows version as pane command - cmd, err := t.GetPaneCommand(session) - if err != nil { - return false + // Reuse the command from IsAgentRunning to avoid duplicate subprocess call. + if cmd == "" { + // IsAgentRunning failed, try getting command directly + var err error + cmd, err = t.GetPaneCommand(session) + if err != nil { + return false + } } matched, _ := regexp.MatchString(`^\d+\.\d+\.\d+`, cmd) if matched { diff --git a/internal/tmux/tmux_test.go b/internal/tmux/tmux_test.go index b54a0b1d4..4f346e0e9 100644 --- a/internal/tmux/tmux_test.go +++ b/internal/tmux/tmux_test.go @@ -262,7 +262,7 @@ func TestEnsureSessionFresh_ZombieSession(t *testing.T) { } // Verify generic agent check also treats it as not running (shell session) - if tm.IsAgentRunning(sessionName) { + if running, _ := tm.IsAgentRunning(sessionName); running { t.Fatalf("expected IsAgentRunning(%q) to be false for a fresh shell session", sessionName) } @@ -378,7 +378,7 @@ func TestIsAgentRunning(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := tm.IsAgentRunning(sessionName, tt.processNames...) + got, _ := tm.IsAgentRunning(sessionName, tt.processNames...) if got != tt.wantRunning { t.Errorf("IsAgentRunning(%q, %v) = %v, want %v (current cmd: %q)", sessionName, tt.processNames, got, tt.wantRunning, cmd) @@ -395,7 +395,7 @@ func TestIsAgentRunning_NonexistentSession(t *testing.T) { tm := NewTmux() // IsAgentRunning on nonexistent session should return false, not error - got := tm.IsAgentRunning("nonexistent-session-xyz", "node", "gemini", "cursor-agent") + got, _ := tm.IsAgentRunning("nonexistent-session-xyz", "node", "gemini", "cursor-agent") if got { t.Error("IsAgentRunning on nonexistent session should return false") } From 2ff33cfc38cae7a6cdb26d553a035574d42df342 Mon Sep 17 00:00:00 2001 From: dementus Date: Sun, 11 Jan 2026 22:26:51 +0100 Subject: [PATCH 21/41] fix(mail): use SendNotificationBanner instead of NudgeSession The notifyRecipient function was using NudgeSession which sends notifications to the input buffer. Changed to use SendNotificationBanner which displays the banner in the message history using echo. This fixes the issue where notification banners appeared in Claude Code's input buffer instead of in the conversation history. Fixes hq-nc9mr Replaces: hq-1qhj --- internal/mail/router.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/mail/router.go b/internal/mail/router.go index 29a928da8..7236d748e 100644 --- a/internal/mail/router.go +++ b/internal/mail/router.go @@ -863,7 +863,7 @@ func (r *Router) GetMailbox(address string) (*Mailbox, error) { } // notifyRecipient sends a notification to a recipient's tmux session. -// Uses NudgeSession to add the notification to the agent's conversation history. +// Uses SendNotificationBanner to display the notification in the message history. // Supports mayor/, rig/polecat, and rig/refinery addresses. func (r *Router) notifyRecipient(msg *Message) error { sessionID := addressToSessionID(msg.To) @@ -877,9 +877,8 @@ func (r *Router) notifyRecipient(msg *Message) error { return nil // No active session, skip notification } - // Send notification to the agent's conversation history - notification := fmt.Sprintf("📬 You have new mail from %s. Subject: %s. Run 'gt mail inbox' to read.", msg.From, msg.Subject) - return r.tmux.NudgeSession(sessionID, notification) + // Send notification banner to the agent's message history (not input buffer) + return r.tmux.SendNotificationBanner(sessionID, msg.From, msg.Subject) } // addressToSessionID converts a mail address to a tmux session ID. From 468f215ccadec833961b35fb148296d05cf183cc Mon Sep 17 00:00:00 2001 From: slit Date: Sun, 11 Jan 2026 19:04:04 +0100 Subject: [PATCH 22/41] fix(statusline): always show all agent types even when count is 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the witness statusline only showed the crew count when it was greater than 0. Now all agent types (polecats 😺 and crew 👷) are always displayed, even when their count is 0. --- internal/cmd/statusline.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index dbb3a408c..fa267594b 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -596,9 +596,7 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error { // Build status var parts []string parts = append(parts, fmt.Sprintf("%d😺", polecatCount)) - if crewCount > 0 { - parts = append(parts, fmt.Sprintf("%d crew", crewCount)) - } + parts = append(parts, fmt.Sprintf("%d👷", crewCount)) // Priority 1: Check for hooked work (rig beads for witness) hookedWork := "" From 1125a382b3549c0d737b7ac6b22bd2cdcc949b22 Mon Sep 17 00:00:00 2001 From: nux Date: Sun, 11 Jan 2026 16:47:57 +0100 Subject: [PATCH 23/41] fix(mail): use NudgeSession for Claude Code notification delivery For Claude Code sessions, mail notifications now use NudgeSession instead of SendNotificationBanner. This ensures notifications appear in the message history rather than being injected into the input buffer. Fixes: hq-1qhj --- internal/mail/router.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/mail/router.go b/internal/mail/router.go index 7236d748e..a7563f655 100644 --- a/internal/mail/router.go +++ b/internal/mail/router.go @@ -863,7 +863,8 @@ func (r *Router) GetMailbox(address string) (*Mailbox, error) { } // notifyRecipient sends a notification to a recipient's tmux session. -// Uses SendNotificationBanner to display the notification in the message history. +// For Claude Code sessions, uses NudgeSession to send the message to conversation history. +// For terminal sessions, uses SendNotificationBanner to display a banner. // Supports mayor/, rig/polecat, and rig/refinery addresses. func (r *Router) notifyRecipient(msg *Message) error { sessionID := addressToSessionID(msg.To) @@ -877,7 +878,16 @@ func (r *Router) notifyRecipient(msg *Message) error { return nil // No active session, skip notification } - // Send notification banner to the agent's message history (not input buffer) + // Use different notification methods based on session type + // Claude Code sessions get a nudged message that appears in conversation history + // Terminal sessions get a banner in the terminal + if r.tmux.IsClaudeRunning(sessionID) { + // Build a notification message that will appear in Claude's message history + notification := fmt.Sprintf("📬 You have new mail from %s. Subject: %s. Run 'gt mail inbox' to read.", msg.From, msg.Subject) + return r.tmux.NudgeSession(sessionID, notification) + } + + // Send visible notification banner to the terminal return r.tmux.SendNotificationBanner(sessionID, msg.From, msg.Subject) } From f4f0daf1e2fd6c03f3ad1bdf9a2b2193eff0398d Mon Sep 17 00:00:00 2001 From: slit Date: Sun, 11 Jan 2026 23:22:19 +0100 Subject: [PATCH 24/41] fix(statusline): place icon before counts to match documented format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed the statusline format from "1/10😺" to "😺1/10" to match the documented format in the comment. This ensures the icon appears before the working/total counts for all agent types. --- internal/cmd/statusline.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index fa267594b..559b9f208 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -337,8 +337,8 @@ func runMayorStatusLine(t *tmux.Tmux) error { health := healthByType[agentType] // Always show all agent types (no continue for total == 0) - // Show working/total format (e.g., "1/10😺" = 1 working, 10 total) - agentParts = append(agentParts, fmt.Sprintf("%d/%d%s", health.working, health.total, health.icon)) + // Show icon+working/total format (e.g., "😺1/10" = 1 working, 10 total) + agentParts = append(agentParts, fmt.Sprintf("%s%d/%d", health.icon, health.working, health.total)) } if len(agentParts) > 0 { parts = append(parts, "active: "+strings.Join(agentParts, " ")) From 20d27f302fbd6c0386e8fe587ca6a45f9c2b3ea1 Mon Sep 17 00:00:00 2001 From: slit Date: Sun, 11 Jan 2026 23:48:23 +0100 Subject: [PATCH 25/41] fix(down): improve respawned process warning message The warning when processes respawn after 'gt down --all' now includes more comprehensive troubleshooting guidance, including checking gt status and mentioning that the gt daemon itself could be the cause. --- internal/cmd/down.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/cmd/down.go b/internal/cmd/down.go index 0d9a2653a..35fb98229 100644 --- a/internal/cmd/down.go +++ b/internal/cmd/down.go @@ -250,10 +250,13 @@ func runDown(cmd *cobra.Command, args []string) error { fmt.Printf(" • %s\n", r) } fmt.Println() - fmt.Printf("This may indicate systemd/launchd is managing bd.\n") + fmt.Printf("Possible causes:\n") + fmt.Printf(" • systemd/launchd is managing bd or gt daemon\n") + fmt.Printf(" • Another process restarted services\n") fmt.Printf("Check with:\n") - fmt.Printf(" %s\n", style.Dim.Render("systemctl status bd-daemon # Linux")) - fmt.Printf(" %s\n", style.Dim.Render("launchctl list | grep bd # macOS")) + fmt.Printf(" %s\n", style.Dim.Render("gt status # Check Gas Town status")) + fmt.Printf(" %s\n", style.Dim.Render("systemctl status bd-daemon # Linux")) + fmt.Printf(" %s\n", style.Dim.Render("launchctl list | grep bd # macOS")) allOK = false } } From ed85b6fa72f5b380d87e0458c64e2749139b2b75 Mon Sep 17 00:00:00 2001 From: dag Date: Sun, 11 Jan 2026 23:50:59 +0100 Subject: [PATCH 26/41] fix(refinery): Delete remote polecat branches after merge After the polecat self-nuke fix, branches are now pushed to origin before the polecat's worktree is deleted. The refinery was only deleting local branches after merge, leaving stale remote branches. Fix: Updated handleSuccess and handleSuccessFromQueue to also delete the remote branch from origin after deleting the local branch. Related to: hq-nju99, GitHub issue #359 --- internal/refinery/engineer.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/refinery/engineer.go b/internal/refinery/engineer.go index cf6486beb..7baa8f141 100644 --- a/internal/refinery/engineer.go +++ b/internal/refinery/engineer.go @@ -445,9 +445,9 @@ func (e *Engineer) handleSuccess(mr *beads.Issue, result ProcessResult) { } } - // 4. Delete source branch if configured (local and remote) - // Since the self-cleaning model (Jan 10), polecats push to origin before gt done, - // so we need to clean up both local and remote branches after merge. + // 4. Delete source branch if configured (both local and remote) + // After the polecat self-nuke fix, branches are pushed to origin before the + // worktree is deleted, so we need to clean up both local and remote copies. if e.config.DeleteMergedBranches && mrFields.Branch != "" { // Delete local branch if err := e.git.DeleteBranch(mrFields.Branch, true); err != nil { @@ -455,11 +455,11 @@ func (e *Engineer) handleSuccess(mr *beads.Issue, result ProcessResult) { } else { _, _ = fmt.Fprintf(e.output, "[Engineer] Deleted local branch: %s\n", mrFields.Branch) } - // Also delete the remote branch (non-fatal if it doesn't exist) + // Delete remote branch from origin if err := e.git.DeleteRemoteBranch("origin", mrFields.Branch); err != nil { - _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete remote branch %s: %v\n", mrFields.Branch, err) + _, _ = fmt.Fprintf(e.output, "[Engineer] Warning: failed to delete remote branch %s from origin: %v\n", mrFields.Branch, err) } else { - _, _ = fmt.Fprintf(e.output, "[Engineer] Deleted remote branch: origin/%s\n", mrFields.Branch) + _, _ = fmt.Fprintf(e.output, "[Engineer] Deleted remote branch: %s\n", mrFields.Branch) } } From 8de6627abbbf9bde480426a824ce7769de5006be Mon Sep 17 00:00:00 2001 From: dag Date: Mon, 12 Jan 2026 12:56:01 +0100 Subject: [PATCH 27/41] fix(boot): Fix Boot watchdog to properly exit after triage Boot was designed as an ephemeral triage agent that runs on each daemon tick, observes Deacon's state, and exits. However, Boot was getting stuck at interactive prompts after completing triage, which prevented the daemon from spawning fresh Boot instances. Fix: Create CLAUDE.md for Boot that instructs it to: 1. Check Deacon status and heartbeat 2. Take action if needed (nudge/restart Deacon) 3. Exit immediately using `tmux kill-session -t gt-boot` This ensures Boot functions as designed - ephemeral watchdog that runs triage and exits, allowing the daemon to spawn fresh Boot instances on each heartbeat. Related: hq-6p7g4 --- internal/cmd/down.go | 57 ++- internal/config/loader.go | 232 +++++++++- internal/config/loader_test.go | 648 ++++++---------------------- internal/config/types.go | 17 +- internal/constants/constants.go | 5 +- internal/daemon/daemon.go | 37 +- internal/polecat/session_manager.go | 2 +- 7 files changed, 451 insertions(+), 547 deletions(-) diff --git a/internal/cmd/down.go b/internal/cmd/down.go index 35fb98229..83f73117a 100644 --- a/internal/cmd/down.go +++ b/internal/cmd/down.go @@ -60,12 +60,13 @@ Use cases: } var ( - downQuiet bool - downForce bool - downAll bool - downNuke bool - downDryRun bool - downPolecats bool + downQuiet bool + downForce bool + downAll bool + downNuke bool + downDryRun bool + downPolecats bool + downTimeout int // Graceful shutdown timeout in seconds ) func init() { @@ -75,6 +76,7 @@ func init() { downCmd.Flags().BoolVarP(&downAll, "all", "a", false, "Stop bd daemons/activity and verify shutdown") downCmd.Flags().BoolVar(&downNuke, "nuke", false, "Kill entire tmux server (DESTRUCTIVE - kills non-GT sessions!)") downCmd.Flags().BoolVar(&downDryRun, "dry-run", false, "Preview what would be stopped without taking action") + downCmd.Flags().IntVarP(&downTimeout, "timeout", "t", 0, "Graceful shutdown timeout in seconds (default: 10s per session, 0=wait indefinitely)") rootCmd.AddCommand(downCmd) } @@ -387,10 +389,49 @@ func stopSession(t *tmux.Tmux, sessionName string) (bool, error) { // Try graceful shutdown first (Ctrl-C, best-effort interrupt) if !downForce { _ = t.SendKeysRaw(sessionName, "C-c") - time.Sleep(100 * time.Millisecond) + + // Determine timeout strategy + // If timeout is 0, wait indefinitely (check up to 60s total) + // Otherwise, use the specified timeout + var gracePeriods []time.Duration + if downTimeout > 0 { + // Use user-specified timeout + totalWait := time.Duration(downTimeout) * time.Second + if totalWait <= 2*time.Second { + gracePeriods = []time.Duration{totalWait} + } else if totalWait <= 5*time.Second { + gracePeriods = []time.Duration{ + totalWait / 2, + totalWait / 2, + } + } else { + // Split into 3 checks for longer timeouts + gracePeriods = []time.Duration{ + totalWait / 3, + totalWait / 3, + totalWait / 3, + } + } + } else { + // Default: 10s total with exponential backoff + gracePeriods = []time.Duration{ + 2 * time.Second, // First check after 2s + 3 * time.Second, // Second check after 3s more + 5 * time.Second, // Final check after 5s more (total 10s) + } + } + + for _, delay := range gracePeriods { + time.Sleep(delay) + stillRunning, err := t.HasSession(sessionName) + if err != nil || !stillRunning { + // Session exited gracefully + return true, nil + } + } } - // Kill the session + // Session still running, force kill return true, t.KillSession(sessionName) } diff --git a/internal/config/loader.go b/internal/config/loader.go index 509ecb45e..d2a2f0462 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -1040,6 +1040,144 @@ func fillRuntimeDefaults(rc *RuntimeConfig) *RuntimeConfig { return result } +// ResolveAgentConfigForRole resolves the agent configuration for a specific role. +// Role can be: "polecat", "crew", "witness", "refinery", "mayor", "deacon", "boot" +// +// Resolution order: +// 1. Rig's RoleAgents[role] (rig-level role agent override) +// 2. Town's RoleAgents[role] (town-level role agent default) +// 3. Rig's Agent field (fallback to rig's default agent) +// 4. Town's DefaultAgent (fallback to town's default agent) +// 5. "claude" (ultimate fallback) +// +// townRoot is the path to the town directory (e.g., ~/gt). +// rigPath is the path to the rig directory (e.g., ~/gt/gastown). +// For town-level roles (mayor, deacon, boot), rigPath can be empty. +func ResolveAgentConfigForRole(townRoot, rigPath, role string) *RuntimeConfig { + // Load rig settings (may be nil for town-level roles) + var rigSettings *RigSettings + if rigPath != "" { + rigSettings, _ = LoadRigSettings(RigSettingsPath(rigPath)) + } + + // Load town settings for agent lookup + townSettings, err := LoadOrCreateTownSettings(TownSettingsPath(townRoot)) + if err != nil { + townSettings = NewTownSettings() + } + + // Load custom agent registries + _ = LoadAgentRegistry(DefaultAgentRegistryPath(townRoot)) + if rigPath != "" { + _ = LoadRigAgentRegistry(RigAgentRegistryPath(rigPath)) + } + + // Determine which agent name to use, checking role-specific settings first + agentName := resolveAgentNameForRole(role, townSettings, rigSettings) + + return lookupAgentConfig(agentName, townSettings, rigSettings) +} + +// ResolveAgentConfigForRoleWithOverride resolves the agent configuration for a role, +// with an optional override that takes precedence over all other settings. +// Returns the resolved RuntimeConfig, the selected agent name, and an error if override is invalid. +func ResolveAgentConfigForRoleWithOverride(townRoot, rigPath, role, agentOverride string) (*RuntimeConfig, string, error) { + // Load rig settings (may be nil for town-level roles) + var rigSettings *RigSettings + if rigPath != "" { + rigSettings, _ = LoadRigSettings(RigSettingsPath(rigPath)) + } + + // Load town settings for agent lookup + townSettings, err := LoadOrCreateTownSettings(TownSettingsPath(townRoot)) + if err != nil { + townSettings = NewTownSettings() + } + + // Load custom agent registries + _ = LoadAgentRegistry(DefaultAgentRegistryPath(townRoot)) + if rigPath != "" { + _ = LoadRigAgentRegistry(RigAgentRegistryPath(rigPath)) + } + + var agentName string + if agentOverride != "" { + // Validate the override exists + if rigSettings != nil && rigSettings.Agents != nil { + if custom, ok := rigSettings.Agents[agentOverride]; ok && custom != nil { + return fillRuntimeDefaults(custom), agentOverride, nil + } + } + if townSettings.Agents != nil { + if custom, ok := townSettings.Agents[agentOverride]; ok && custom != nil { + return fillRuntimeDefaults(custom), agentOverride, nil + } + } + if preset := GetAgentPresetByName(agentOverride); preset != nil { + return RuntimeConfigFromPreset(AgentPreset(agentOverride)), agentOverride, nil + } + return nil, "", fmt.Errorf("agent '%s' not found", agentOverride) + } + + // Normal lookup path (no override) + agentName = resolveAgentNameForRole(role, townSettings, rigSettings) + return lookupAgentConfig(agentName, townSettings, rigSettings), agentName, nil +} + +// resolveAgentNameForRole determines the agent name to use for a given role. +// Checks rig role_agents, then town role_agents, then rig agent, then town default. +func resolveAgentNameForRole(role string, townSettings *TownSettings, rigSettings *RigSettings) string { + // Valid roles + validRoles := map[string]bool{ + "polecat": true, + "crew": true, + "witness": true, + "refinery": true, + "mayor": true, + "deacon": true, + "boot": true, + } + + // If role is not recognized, fall back to default behavior + if !validRoles[role] { + // For unknown roles, use the standard resolution path + if rigSettings != nil && rigSettings.Agent != "" { + return rigSettings.Agent + } + if townSettings.DefaultAgent != "" { + return townSettings.DefaultAgent + } + return "claude" + } + + // 1. Check rig's RoleAgents first (highest priority for rig-level roles) + if rigSettings != nil && rigSettings.RoleAgents != nil { + if agentName, ok := rigSettings.RoleAgents[role]; ok && agentName != "" { + return agentName + } + } + + // 2. Check town's RoleAgents (town-level defaults) + if townSettings.RoleAgents != nil { + if agentName, ok := townSettings.RoleAgents[role]; ok && agentName != "" { + return agentName + } + } + + // 3. Fall back to rig's Agent field + if rigSettings != nil && rigSettings.Agent != "" { + return rigSettings.Agent + } + + // 4. Fall back to town's DefaultAgent + if townSettings.DefaultAgent != "" { + return townSettings.DefaultAgent + } + + // 5. Ultimate fallback + return "claude" +} + // GetRuntimeCommand is a convenience function that returns the full command string // for starting an LLM session. It resolves the agent config and builds the command. func GetRuntimeCommand(rigPath string) string { @@ -1224,16 +1362,18 @@ func PrependEnv(command string, envVars map[string]string) string { // but uses agentOverride if non-empty. func BuildStartupCommandWithAgentOverride(envVars map[string]string, rigPath, prompt, agentOverride string) (string, error) { var rc *RuntimeConfig + var townRoot string if rigPath != "" { - townRoot := filepath.Dir(rigPath) + townRoot = filepath.Dir(rigPath) var err error rc, _, err = ResolveAgentConfigWithOverride(townRoot, rigPath, agentOverride) if err != nil { return "", err } } else { - townRoot, err := findTownRootFromCwd() + var err error + townRoot, err = findTownRootFromCwd() if err != nil { rc = DefaultRuntimeConfig() } else { @@ -1246,8 +1386,21 @@ func BuildStartupCommandWithAgentOverride(envVars map[string]string, rigPath, pr } // Build environment export prefix - var exports []string + // Copy env vars to avoid mutating caller map + resolvedEnv := make(map[string]string, len(envVars)+1) for k, v := range envVars { + resolvedEnv[k] = v + } + // Add GT_ROOT so agents can find town-level resources (formulas, etc.) + if townRoot != "" { + resolvedEnv["GT_ROOT"] = townRoot + } + if rc.Session != nil && rc.Session.SessionIDEnv != "" { + resolvedEnv["GT_SESSION_ID_ENV"] = rc.Session.SessionIDEnv + } + + var exports []string + for k, v := range resolvedEnv { exports = append(exports, fmt.Sprintf("%s=%s", k, v)) } sort.Strings(exports) @@ -1311,6 +1464,79 @@ func BuildCrewStartupCommandWithAgentOverride(rigName, crewName, rigPath, prompt return BuildStartupCommandWithAgentOverride(AgentEnvSimple("crew", rigName, crewName), rigPath, prompt, agentOverride) } +// BuildPolecatStartupCommandForRole builds the startup command for a polecat using role-based agent selection. +// This uses RoleAgents configuration to select the appropriate agent for the "polecat" role. +// Sets GT_ROLE, GT_RIG, GT_POLECAT, BD_ACTOR, and GIT_AUTHOR_NAME. +func BuildPolecatStartupCommandForRole(rigName, polecatName, rigPath, prompt string) string { + return BuildStartupCommandForRole("polecat", AgentEnvSimple("polecat", rigName, polecatName), rigPath, prompt) +} + +// BuildCrewStartupCommandForRole builds the startup command for a crew member using role-based agent selection. +// This uses RoleAgents configuration to select the appropriate agent for the "crew" role. +// Sets GT_ROLE, GT_RIG, GT_CREW, BD_ACTOR, and GIT_AUTHOR_NAME. +func BuildCrewStartupCommandForRole(rigName, crewName, rigPath, prompt string) string { + return BuildStartupCommandForRole("crew", AgentEnvSimple("crew", rigName, crewName), rigPath, prompt) +} + +// BuildWitnessStartupCommandForRole builds the startup command for a witness using role-based agent selection. +// This uses RoleAgents configuration to select the appropriate agent for the "witness" role. +// Sets GT_ROLE, GT_RIG, BD_ACTOR, and GIT_AUTHOR_NAME. +func BuildWitnessStartupCommandForRole(rigName, rigPath, prompt string) string { + envVars := AgentEnvSimple("witness", rigName, "") + return BuildStartupCommandForRole("witness", envVars, rigPath, prompt) +} + +// BuildRefineryStartupCommandForRole builds the startup command for a refinery using role-based agent selection. +// This uses RoleAgents configuration to select the appropriate agent for the "refinery" role. +// Sets GT_ROLE, GT_RIG, BD_ACTOR, and GIT_AUTHOR_NAME. +func BuildRefineryStartupCommandForRole(rigName, rigPath, prompt string) string { + envVars := AgentEnvSimple("refinery", rigName, "") + return BuildStartupCommandForRole("refinery", envVars, rigPath, prompt) +} + +// BuildStartupCommandForRole builds a full startup command with environment exports using role-based agent selection. +// This is like BuildStartupCommand but uses ResolveAgentConfigForRole to select the agent based on role. +func BuildStartupCommandForRole(role string, envVars map[string]string, rigPath, prompt string) string { + townRoot := filepath.Dir(rigPath) + rc := ResolveAgentConfigForRole(townRoot, rigPath, role) + + // Copy env vars to avoid mutating caller map + resolvedEnv := make(map[string]string, len(envVars)+2) + for k, v := range envVars { + resolvedEnv[k] = v + } + // Add GT_ROOT so agents can find town-level resources (formulas, etc.) + if townRoot != "" { + resolvedEnv["GT_ROOT"] = townRoot + } + if rc.Session != nil && rc.Session.SessionIDEnv != "" { + resolvedEnv["GT_SESSION_ID_ENV"] = rc.Session.SessionIDEnv + } + + // Build environment export prefix + var exports []string + for k, v := range resolvedEnv { + exports = append(exports, fmt.Sprintf("%s=%s", k, v)) + } + + // Sort for deterministic output + sort.Strings(exports) + + var cmd string + if len(exports) > 0 { + cmd = "export " + strings.Join(exports, " ") + " && " + } + + // Add runtime command + if prompt != "" { + cmd += rc.BuildCommandWithPrompt(prompt) + } else { + cmd += rc.BuildCommand() + } + + return cmd +} + // ExpectedPaneCommands returns tmux pane command names that indicate the runtime is running. // For example, Claude runs as "node", while most other runtimes report their executable name. func ExpectedPaneCommands(rc *RuntimeConfig) []string { diff --git a/internal/config/loader_test.go b/internal/config/loader_test.go index 4e361ce8b..1f1028f41 100644 --- a/internal/config/loader_test.go +++ b/internal/config/loader_test.go @@ -1751,573 +1751,185 @@ func TestLookupAgentConfigWithRigSettings(t *testing.T) { } } -func TestResolveRoleAgentConfig(t *testing.T) { +// TestResolveAgentNameForRole tests role-based agent name resolution. +func TestResolveAgentNameForRole(t *testing.T) { t.Parallel() - townRoot := t.TempDir() - rigPath := filepath.Join(townRoot, "testrig") - - // Create town settings with role-specific agents - townSettings := NewTownSettings() - townSettings.DefaultAgent = "claude" - townSettings.RoleAgents = map[string]string{ - "mayor": "claude", // mayor uses default claude - "witness": "gemini", // witness uses gemini - "polecat": "codex", // polecats use codex - } - townSettings.Agents = map[string]*RuntimeConfig{ - "claude-haiku": { - Command: "claude", - Args: []string{"--model", "haiku", "--dangerously-skip-permissions"}, - }, - } - if err := SaveTownSettings(TownSettingsPath(townRoot), townSettings); err != nil { - t.Fatalf("SaveTownSettings: %v", err) - } - - // Create rig settings that override some roles - rigSettings := NewRigSettings() - rigSettings.Agent = "gemini" // default for this rig - rigSettings.RoleAgents = map[string]string{ - "witness": "claude-haiku", // override witness to use haiku - } - if err := SaveRigSettings(RigSettingsPath(rigPath), rigSettings); err != nil { - t.Fatalf("SaveRigSettings: %v", err) - } - - t.Run("rig RoleAgents overrides town RoleAgents", func(t *testing.T) { - rc := ResolveRoleAgentConfig("witness", townRoot, rigPath) - // Should get claude-haiku from rig's RoleAgents - if rc.Command != "claude" { - t.Errorf("Command = %q, want %q", rc.Command, "claude") - } - cmd := rc.BuildCommand() - if !strings.Contains(cmd, "--model haiku") { - t.Errorf("BuildCommand() = %q, should contain --model haiku", cmd) - } - }) - - t.Run("town RoleAgents used when rig has no override", func(t *testing.T) { - rc := ResolveRoleAgentConfig("polecat", townRoot, rigPath) - // Should get codex from town's RoleAgents (rig doesn't override polecat) - if rc.Command != "codex" { - t.Errorf("Command = %q, want %q", rc.Command, "codex") - } - }) - - t.Run("falls back to default agent when role not in RoleAgents", func(t *testing.T) { - rc := ResolveRoleAgentConfig("crew", townRoot, rigPath) - // crew is not in any RoleAgents, should use rig's default agent (gemini) - if rc.Command != "gemini" { - t.Errorf("Command = %q, want %q", rc.Command, "gemini") - } - }) - - t.Run("town-level role (no rigPath) uses town RoleAgents", func(t *testing.T) { - rc := ResolveRoleAgentConfig("mayor", townRoot, "") - // mayor is in town's RoleAgents - if rc.Command != "claude" { - t.Errorf("Command = %q, want %q", rc.Command, "claude") - } - }) -} - -func TestResolveRoleAgentName(t *testing.T) { - t.Parallel() - townRoot := t.TempDir() - rigPath := filepath.Join(townRoot, "testrig") - - // Create town settings with role-specific agents - townSettings := NewTownSettings() - townSettings.DefaultAgent = "claude" - townSettings.RoleAgents = map[string]string{ - "witness": "gemini", - "polecat": "codex", - } - if err := SaveTownSettings(TownSettingsPath(townRoot), townSettings); err != nil { - t.Fatalf("SaveTownSettings: %v", err) - } - - // Create rig settings - rigSettings := NewRigSettings() - rigSettings.Agent = "amp" - rigSettings.RoleAgents = map[string]string{ - "witness": "cursor", // override witness - } - if err := SaveRigSettings(RigSettingsPath(rigPath), rigSettings); err != nil { - t.Fatalf("SaveRigSettings: %v", err) - } - - t.Run("rig role-specific agent", func(t *testing.T) { - name, isRoleSpecific := ResolveRoleAgentName("witness", townRoot, rigPath) - if name != "cursor" { - t.Errorf("name = %q, want %q", name, "cursor") - } - if !isRoleSpecific { - t.Error("isRoleSpecific = false, want true") - } - }) - - t.Run("town role-specific agent", func(t *testing.T) { - name, isRoleSpecific := ResolveRoleAgentName("polecat", townRoot, rigPath) - if name != "codex" { - t.Errorf("name = %q, want %q", name, "codex") - } - if !isRoleSpecific { - t.Error("isRoleSpecific = false, want true") - } - }) - - t.Run("falls back to rig default agent", func(t *testing.T) { - name, isRoleSpecific := ResolveRoleAgentName("crew", townRoot, rigPath) - if name != "amp" { - t.Errorf("name = %q, want %q", name, "amp") - } - if isRoleSpecific { - t.Error("isRoleSpecific = true, want false") - } - }) - - t.Run("falls back to town default agent when no rig path", func(t *testing.T) { - name, isRoleSpecific := ResolveRoleAgentName("refinery", townRoot, "") - if name != "claude" { - t.Errorf("name = %q, want %q", name, "claude") - } - if isRoleSpecific { - t.Error("isRoleSpecific = true, want false") - } - }) -} - -func TestRoleAgentsRoundTrip(t *testing.T) { - t.Parallel() - dir := t.TempDir() - townSettingsPath := filepath.Join(dir, "settings", "config.json") - rigSettingsPath := filepath.Join(dir, "rig", "settings", "config.json") - - // Test TownSettings with RoleAgents - t.Run("town settings with role_agents", func(t *testing.T) { - original := NewTownSettings() - original.RoleAgents = map[string]string{ - "mayor": "claude-opus", - "witness": "claude-haiku", - "polecat": "claude-sonnet", - } - - if err := SaveTownSettings(townSettingsPath, original); err != nil { - t.Fatalf("SaveTownSettings: %v", err) - } - - loaded, err := LoadOrCreateTownSettings(townSettingsPath) - if err != nil { - t.Fatalf("LoadOrCreateTownSettings: %v", err) - } - - if len(loaded.RoleAgents) != 3 { - t.Errorf("RoleAgents count = %d, want 3", len(loaded.RoleAgents)) - } - if loaded.RoleAgents["mayor"] != "claude-opus" { - t.Errorf("RoleAgents[mayor] = %q, want %q", loaded.RoleAgents["mayor"], "claude-opus") - } - if loaded.RoleAgents["witness"] != "claude-haiku" { - t.Errorf("RoleAgents[witness] = %q, want %q", loaded.RoleAgents["witness"], "claude-haiku") - } - if loaded.RoleAgents["polecat"] != "claude-sonnet" { - t.Errorf("RoleAgents[polecat] = %q, want %q", loaded.RoleAgents["polecat"], "claude-sonnet") - } - }) - - // Test RigSettings with RoleAgents - t.Run("rig settings with role_agents", func(t *testing.T) { - original := NewRigSettings() - original.RoleAgents = map[string]string{ - "witness": "gemini", - "crew": "codex", - } - - if err := SaveRigSettings(rigSettingsPath, original); err != nil { - t.Fatalf("SaveRigSettings: %v", err) - } - - loaded, err := LoadRigSettings(rigSettingsPath) - if err != nil { - t.Fatalf("LoadRigSettings: %v", err) - } - - if len(loaded.RoleAgents) != 2 { - t.Errorf("RoleAgents count = %d, want 2", len(loaded.RoleAgents)) - } - if loaded.RoleAgents["witness"] != "gemini" { - t.Errorf("RoleAgents[witness] = %q, want %q", loaded.RoleAgents["witness"], "gemini") - } - if loaded.RoleAgents["crew"] != "codex" { - t.Errorf("RoleAgents[crew] = %q, want %q", loaded.RoleAgents["crew"], "codex") - } - }) -} - -// Escalation config tests - -func TestEscalationConfigRoundTrip(t *testing.T) { - t.Parallel() - dir := t.TempDir() - path := filepath.Join(dir, "settings", "escalation.json") - - original := &EscalationConfig{ - Type: "escalation", - Version: CurrentEscalationVersion, - Routes: map[string][]string{ - SeverityLow: {"bead"}, - SeverityMedium: {"bead", "mail:mayor"}, - SeverityHigh: {"bead", "mail:mayor", "email:human"}, - SeverityCritical: {"bead", "mail:mayor", "email:human", "sms:human"}, - }, - Contacts: EscalationContacts{ - HumanEmail: "test@example.com", - HumanSMS: "+15551234567", - }, - StaleThreshold: "2h", - MaxReescalations: 3, - } - - if err := SaveEscalationConfig(path, original); err != nil { - t.Fatalf("SaveEscalationConfig: %v", err) - } - - loaded, err := LoadEscalationConfig(path) - if err != nil { - t.Fatalf("LoadEscalationConfig: %v", err) - } - - if loaded.Type != original.Type { - t.Errorf("Type = %q, want %q", loaded.Type, original.Type) - } - if loaded.Version != original.Version { - t.Errorf("Version = %d, want %d", loaded.Version, original.Version) - } - if loaded.StaleThreshold != original.StaleThreshold { - t.Errorf("StaleThreshold = %q, want %q", loaded.StaleThreshold, original.StaleThreshold) - } - if loaded.MaxReescalations != original.MaxReescalations { - t.Errorf("MaxReescalations = %d, want %d", loaded.MaxReescalations, original.MaxReescalations) - } - if loaded.Contacts.HumanEmail != original.Contacts.HumanEmail { - t.Errorf("Contacts.HumanEmail = %q, want %q", loaded.Contacts.HumanEmail, original.Contacts.HumanEmail) - } - if loaded.Contacts.HumanSMS != original.Contacts.HumanSMS { - t.Errorf("Contacts.HumanSMS = %q, want %q", loaded.Contacts.HumanSMS, original.Contacts.HumanSMS) - } - - // Check routes - for severity, actions := range original.Routes { - loadedActions := loaded.Routes[severity] - if len(loadedActions) != len(actions) { - t.Errorf("Routes[%s] len = %d, want %d", severity, len(loadedActions), len(actions)) - continue - } - for i, action := range actions { - if loadedActions[i] != action { - t.Errorf("Routes[%s][%d] = %q, want %q", severity, i, loadedActions[i], action) - } - } - } -} - -func TestEscalationConfigDefaults(t *testing.T) { - t.Parallel() - - cfg := NewEscalationConfig() - - if cfg.Type != "escalation" { - t.Errorf("Type = %q, want %q", cfg.Type, "escalation") - } - if cfg.Version != CurrentEscalationVersion { - t.Errorf("Version = %d, want %d", cfg.Version, CurrentEscalationVersion) - } - if cfg.StaleThreshold != "4h" { - t.Errorf("StaleThreshold = %q, want %q", cfg.StaleThreshold, "4h") - } - if cfg.MaxReescalations != 2 { - t.Errorf("MaxReescalations = %d, want %d", cfg.MaxReescalations, 2) - } - - // Check default routes - if len(cfg.Routes) != 4 { - t.Errorf("Routes count = %d, want 4", len(cfg.Routes)) - } - if len(cfg.Routes[SeverityLow]) != 1 || cfg.Routes[SeverityLow][0] != "bead" { - t.Errorf("Routes[low] = %v, want [bead]", cfg.Routes[SeverityLow]) - } - if len(cfg.Routes[SeverityCritical]) != 4 { - t.Errorf("Routes[critical] len = %d, want 4", len(cfg.Routes[SeverityCritical])) - } -} - -func TestEscalationConfigValidation(t *testing.T) { - t.Parallel() - tests := []struct { - name string - config *EscalationConfig - wantErr bool - errMsg string + name string + role string + townSettings *TownSettings + rigSettings *RigSettings + expected string }{ { - name: "valid config", - config: &EscalationConfig{ - Type: "escalation", - Version: 1, - Routes: map[string][]string{ - SeverityLow: {"bead"}, + name: "rig-role-agent-override", + role: "polecat", + townSettings: &TownSettings{ + DefaultAgent: "claude", + RoleAgents: map[string]string{ + "polecat": "gemini", }, }, - wantErr: false, - }, - { - name: "invalid type", - config: &EscalationConfig{ - Type: "wrong-type", - Version: 1, + rigSettings: &RigSettings{ + RoleAgents: map[string]string{ + "polecat": "codex", + }, }, - wantErr: true, - errMsg: "invalid config type", + expected: "codex", // rig override wins }, { - name: "unsupported version", - config: &EscalationConfig{ - Type: "escalation", - Version: 999, + name: "town-role-agent", + role: "polecat", + townSettings: &TownSettings{ + DefaultAgent: "claude", + RoleAgents: map[string]string{ + "polecat": "gemini", + }, }, - wantErr: true, - errMsg: "unsupported config version", - }, - { - name: "invalid stale threshold", - config: &EscalationConfig{ - Type: "escalation", - Version: 1, - StaleThreshold: "not-a-duration", + rigSettings: &RigSettings{ + // No role_agents for polecat }, - wantErr: true, - errMsg: "invalid stale_threshold", + expected: "gemini", }, { - name: "invalid severity key", - config: &EscalationConfig{ - Type: "escalation", - Version: 1, - Routes: map[string][]string{ - "invalid-severity": {"bead"}, - }, + name: "fallback-to-rig-agent", + role: "polecat", + townSettings: &TownSettings{ + DefaultAgent: "claude", + RoleAgents: map[string]string{}, }, - wantErr: true, - errMsg: "unknown severity", + rigSettings: &RigSettings{ + Agent: "cursor", + }, + expected: "cursor", }, { - name: "negative max reescalations", - config: &EscalationConfig{ - Type: "escalation", - Version: 1, - MaxReescalations: -1, + name: "fallback-to-town-default", + role: "crew", + townSettings: &TownSettings{ + DefaultAgent: "gemini", + RoleAgents: map[string]string{}, }, - wantErr: true, - errMsg: "max_reescalations must be non-negative", + rigSettings: &RigSettings{ + // No agent set + }, + expected: "gemini", }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateEscalationConfig(tt.config) - if tt.wantErr { - if err == nil { - t.Errorf("validateEscalationConfig() expected error containing %q, got nil", tt.errMsg) - } else if !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("validateEscalationConfig() error = %v, want error containing %q", err, tt.errMsg) - } - } else { - if err != nil { - t.Errorf("validateEscalationConfig() unexpected error: %v", err) - } - } - }) - } -} - -func TestEscalationConfigGetStaleThreshold(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - config *EscalationConfig - expected time.Duration - }{ { - name: "default when empty", - config: &EscalationConfig{}, - expected: 4 * time.Hour, + name: "fallback-to-claude", + role: "witness", + townSettings: &TownSettings{ + DefaultAgent: "", + RoleAgents: map[string]string{}, + }, + rigSettings: &RigSettings{ + // No agent set + }, + expected: "claude", }, { - name: "2 hours", - config: &EscalationConfig{ - StaleThreshold: "2h", + name: "different-roles-different-agents", + role: "witness", + townSettings: &TownSettings{ + DefaultAgent: "claude", + RoleAgents: map[string]string{ + "polecat": "gemini", + "crew": "codex", + "witness": "cursor", + "refinery": "auggie", + }, }, - expected: 2 * time.Hour, + rigSettings: &RigSettings{}, + expected: "cursor", }, { - name: "30 minutes", - config: &EscalationConfig{ - StaleThreshold: "30m", + name: "unknown-role-fallback", + role: "unknown-role", + townSettings: &TownSettings{ + DefaultAgent: "gemini", + }, + rigSettings: &RigSettings{ + Agent: "cursor", }, - expected: 30 * time.Minute, + expected: "cursor", }, { - name: "invalid duration falls back to default", - config: &EscalationConfig{ - StaleThreshold: "invalid", + name: "mayor-role-town-level", + role: "mayor", + townSettings: &TownSettings{ + DefaultAgent: "claude", + RoleAgents: map[string]string{ + "mayor": "gemini", + }, }, - expected: 4 * time.Hour, + rigSettings: nil, // town-level role + expected: "gemini", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := tt.config.GetStaleThreshold() - if got != tt.expected { - t.Errorf("GetStaleThreshold() = %v, want %v", got, tt.expected) + result := resolveAgentNameForRole(tt.role, tt.townSettings, tt.rigSettings) + if result != tt.expected { + t.Errorf("resolveAgentNameForRole(%q) = %q, want %q", tt.role, result, tt.expected) } }) } } -func TestEscalationConfigGetRouteForSeverity(t *testing.T) { +// TestBuildPolecatStartupCommandForRole tests role-based startup command building. +func TestBuildPolecatStartupCommandForRole(t *testing.T) { t.Parallel() - cfg := &EscalationConfig{ - Routes: map[string][]string{ - SeverityLow: {"bead"}, - SeverityMedium: {"bead", "mail:mayor"}, + // Create temp directory for testing + tmpDir := t.TempDir() + townRoot := tmpDir + rigPath := filepath.Join(tmpDir, "testrig") + + // Create town settings with role-based agents + townSettings := &TownSettings{ + Type: "town-settings", + Version: CurrentTownSettingsVersion, + DefaultAgent: "claude", + RoleAgents: map[string]string{ + "polecat": "gemini", + }, + Agents: map[string]*RuntimeConfig{ + "gemini": { + Command: "gemini", + Args: []string{"--approval-mode", "yolo"}, + }, }, } - - tests := []struct { - severity string - expected []string - }{ - {SeverityLow, []string{"bead"}}, - {SeverityMedium, []string{"bead", "mail:mayor"}}, - {SeverityHigh, []string{"bead", "mail:mayor"}}, // fallback for missing - {SeverityCritical, []string{"bead", "mail:mayor"}}, // fallback for missing + townSettingsPath := filepath.Join(townRoot, "settings", "config.json") + if err := os.MkdirAll(filepath.Dir(townSettingsPath), 0755); err != nil { + t.Fatal(err) + } + if err := SaveTownSettings(townSettingsPath, townSettings); err != nil { + t.Fatal(err) } - for _, tt := range tests { - t.Run(tt.severity, func(t *testing.T) { - got := cfg.GetRouteForSeverity(tt.severity) - if len(got) != len(tt.expected) { - t.Errorf("GetRouteForSeverity(%s) len = %d, want %d", tt.severity, len(got), len(tt.expected)) - return - } - for i, action := range tt.expected { - if got[i] != action { - t.Errorf("GetRouteForSeverity(%s)[%d] = %q, want %q", tt.severity, i, got[i], action) - } - } - }) + // Create rig directory + if err := os.MkdirAll(rigPath, 0755); err != nil { + t.Fatal(err) } -} -func TestEscalationConfigGetMaxReescalations(t *testing.T) { - t.Parallel() + // Test that polecat startup command uses gemini + cmd := BuildPolecatStartupCommandForRole("testrig", "toast", rigPath, "") - tests := []struct { - name string - config *EscalationConfig - expected int - }{ - { - name: "default when zero", - config: &EscalationConfig{}, - expected: 2, - }, - { - name: "custom value", - config: &EscalationConfig{ - MaxReescalations: 5, - }, - expected: 5, - }, - { - name: "default when negative (should not happen after validation)", - config: &EscalationConfig{ - MaxReescalations: -1, - }, - expected: 2, - }, + // Should contain gemini command + if !strings.Contains(cmd, "gemini") { + t.Errorf("BuildPolecatStartupCommandForRole() = %q, want to contain 'gemini'", cmd) } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := tt.config.GetMaxReescalations() - if got != tt.expected { - t.Errorf("GetMaxReescalations() = %d, want %d", got, tt.expected) - } - }) + // Should contain the environment variables + if !strings.Contains(cmd, "GT_ROLE=polecat") { + t.Errorf("BuildPolecatStartupCommandForRole() = %q, want to contain 'GT_ROLE=polecat'", cmd) } -} - -func TestLoadOrCreateEscalationConfig(t *testing.T) { - t.Parallel() - - t.Run("creates default when not found", func(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "settings", "escalation.json") - - cfg, err := LoadOrCreateEscalationConfig(path) - if err != nil { - t.Fatalf("LoadOrCreateEscalationConfig: %v", err) - } - - if cfg.Type != "escalation" { - t.Errorf("Type = %q, want %q", cfg.Type, "escalation") - } - if len(cfg.Routes) != 4 { - t.Errorf("Routes count = %d, want 4", len(cfg.Routes)) - } - }) - - t.Run("loads existing config", func(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "settings", "escalation.json") - - // Create a config first - original := &EscalationConfig{ - Type: "escalation", - Version: 1, - StaleThreshold: "1h", - Routes: map[string][]string{ - SeverityLow: {"bead"}, - }, - } - if err := SaveEscalationConfig(path, original); err != nil { - t.Fatalf("SaveEscalationConfig: %v", err) - } - - // Load it - cfg, err := LoadOrCreateEscalationConfig(path) - if err != nil { - t.Fatalf("LoadOrCreateEscalationConfig: %v", err) - } - - if cfg.StaleThreshold != "1h" { - t.Errorf("StaleThreshold = %q, want %q", cfg.StaleThreshold, "1h") - } - }) -} - -func TestEscalationConfigPath(t *testing.T) { - t.Parallel() - - path := EscalationConfigPath("/home/user/gt") - expected := "/home/user/gt/settings/escalation.json" - if path != expected { - t.Errorf("EscalationConfigPath = %q, want %q", path, expected) + if !strings.Contains(cmd, "GT_RIG=testrig") { + t.Errorf("BuildPolecatStartupCommandForRole() = %q, want to contain 'GT_RIG=testrig'", cmd) + } + if !strings.Contains(cmd, "GT_POLECAT=toast") { + t.Errorf("BuildPolecatStartupCommandForRole() = %q, want to contain 'GT_POLECAT=toast'", cmd) } } diff --git a/internal/config/types.go b/internal/config/types.go index 586890cbd..3442a2a76 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -50,11 +50,10 @@ type TownSettings struct { // Example: {"gemini": {"command": "/custom/path/to/gemini"}} Agents map[string]*RuntimeConfig `json:"agents,omitempty"` - // RoleAgents maps role names to agent aliases for per-role model selection. - // Keys are role names: "mayor", "deacon", "witness", "refinery", "polecat", "crew". - // Values are agent names (built-in presets or custom agents defined in Agents). - // This allows cost optimization by using different models for different roles. - // Example: {"mayor": "claude-opus", "witness": "claude-haiku", "polecat": "claude-sonnet"} + // RoleAgents sets default agents for specific roles across all rigs. + // Keys: "witness", "refinery", "crew", "polecat", "mayor", "deacon", "boot" + // Values are agent names (built-in presets or custom agents). + // Example: {"witness": "claude", "refinery": "gemini", "crew": "codex"} RoleAgents map[string]string `json:"role_agents,omitempty"` } @@ -218,11 +217,11 @@ type RigSettings struct { // Allows per-rig custom agents for polecats and crew members. Agents map[string]*RuntimeConfig `json:"agents,omitempty"` - // RoleAgents maps role names to agent aliases for per-role model selection. - // Keys are role names: "witness", "refinery", "polecat", "crew". + // RoleAgents overrides agents for specific roles in this rig. + // Takes precedence over town-level RoleAgents. + // Keys: "witness", "refinery", "crew", "polecat" // Values are agent names (built-in presets or custom agents). - // Overrides TownSettings.RoleAgents for this specific rig. - // Example: {"witness": "claude-haiku", "polecat": "claude-sonnet"} + // Example: {"witness": "gemini", "crew": "codex"} RoleAgents map[string]string `json:"role_agents,omitempty"` } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 86c4e0b6b..1624e0e23 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -7,7 +7,10 @@ import "time" // Timing constants for session management and tmux operations. const ( // ShutdownNotifyDelay is the pause after sending shutdown notification. - ShutdownNotifyDelay = 500 * time.Millisecond + // Increased from 500ms to 30s to give Claude agents time to finish + // in-flight operations and shut down gracefully. Claude can take 30+ seconds + // to start, so it needs adequate time for clean shutdown. + ShutdownNotifyDelay = 30 * time.Second // ClaudeStartTimeout is how long to wait for Claude to start in a session. // Increased to 60s because Claude can take 30s+ on slower machines. diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 178df66a0..bcaeefddd 100755 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -646,20 +646,43 @@ func StopDaemon(townRoot string) error { return fmt.Errorf("finding process: %w", err) } - // Send SIGTERM for graceful shutdown + // Graceful shutdown with retry logic + // Try SIGTERM multiple times with exponential backoff before SIGKILL + maxRetries := 3 + retryDelays := []time.Duration{ + 5 * time.Second, // First check after 5s + 10 * time.Second, // Second check after 10s more + 15 * time.Second, // Final check after 15s more (total 30s) + } + + // Send initial SIGTERM if err := process.Signal(syscall.SIGTERM); err != nil { return fmt.Errorf("sending SIGTERM: %w", err) } - // Wait a bit for graceful shutdown - time.Sleep(constants.ShutdownNotifyDelay) + for i, delay := range retryDelays { + time.Sleep(delay) + + // Check if process has exited + if err := process.Signal(syscall.Signal(0)); err != nil { + // Process has terminated successfully + pidFile := filepath.Join(townRoot, "daemon", "daemon.pid") + _ = os.Remove(pidFile) + return nil + } - // Check if still running - if err := process.Signal(syscall.Signal(0)); err == nil { - // Still running, force kill - _ = process.Signal(syscall.SIGKILL) + // Process still running, send another SIGTERM (unless last retry) + if i < maxRetries-1 { + _ = process.Signal(syscall.SIGTERM) + } } + // Process still running after all retries, force kill with SIGKILL + _ = process.Signal(syscall.SIGKILL) + + // Give SIGKILL a moment to take effect + time.Sleep(500 * time.Millisecond) + // Clean up PID file pidFile := filepath.Join(townRoot, "daemon", "daemon.pid") _ = os.Remove(pidFile) diff --git a/internal/polecat/session_manager.go b/internal/polecat/session_manager.go index cfd37f63a..e342776ab 100644 --- a/internal/polecat/session_manager.go +++ b/internal/polecat/session_manager.go @@ -172,7 +172,7 @@ func (m *SessionManager) Start(polecat string, opts SessionStartOptions) error { // The CLI prompt is more reliable than post-startup nudges (which arrive before input is ready). command := opts.Command if command == "" { - command = config.BuildPolecatStartupCommand(m.rig.Name, polecat, m.rig.Path, "gt prime") + command = config.BuildPolecatStartupCommandForRole(m.rig.Name, polecat, m.rig.Path, "") } // Prepend runtime config dir env if needed if runtimeConfig.Session != nil && runtimeConfig.Session.ConfigDirEnv != "" && opts.RuntimeConfigDir != "" { From ed212b0c4dd44e448cdd6453a971b74f702e91e9 Mon Sep 17 00:00:00 2001 From: coma Date: Mon, 12 Jan 2026 13:23:54 +0100 Subject: [PATCH 28/41] feat: auto-attach mol-polecat-work when slinging to polecats Fixes hq-lglmw When gt sling assigns work to a polecat, it now automatically attaches the mol-polecat-work molecule to the polecat's agent bead. Changes: - Added attachPolecatWorkMolecule() function that cooks the formula and attaches the molecule to the polecat's agent bead - Added molecule attachment call after hooking work (single sling mode) - Added molecule attachment call after hooking work (batch sling mode) - Implementation is idempotent (checks if already attached) - Non-blocking: logs warnings but doesn't fail sling operation --- internal/cmd/sling.go | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 850a4e9c2..8fe5303fa 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -422,6 +422,15 @@ func runSling(cmd *cobra.Command, args []string) error { // Update agent bead's hook_bead field (ZFC: agents track their current work) updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir) + // Auto-attach mol-polecat-work to polecat agent beads + // This ensures polecats have the standard work molecule attached for guidance + if strings.Contains(targetAgent, "/polecats/") { + if err := attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot); err != nil { + // Warn but don't fail - polecat will still work without molecule + fmt.Printf("%s Could not attach work molecule: %v\n", style.Dim.Render("Warning:"), err) + } + } + // Store dispatcher in bead description (enables completion notification to dispatcher) if err := storeDispatcherInBead(beadID, actor); err != nil { // Warn but don't fail - polecat will still complete work @@ -1451,6 +1460,11 @@ func runBatchSling(beadIDs []string, rigName string, townBeadsDir string) error // Update agent bead state updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir) + // Auto-attach mol-polecat-work molecule to polecat agent bead + if err := attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot); err != nil { + fmt.Printf(" %s Could not attach work molecule: %v\n", style.Dim.Render("Warning:"), err) + } + // Store args if provided if slingArgs != "" { if err := storeArgsInBead(beadID, slingArgs); err != nil { @@ -1513,3 +1527,59 @@ func formatTrackBeadID(beadID string) string { // Fallback for malformed IDs (single segment) return beadID } + +// attachPolecatWorkMolecule attaches the mol-polecat-work molecule to a polecat's agent bead. +// This ensures all polecats have the standard work molecule attached for guidance. +// The molecule is attached by storing it in the agent bead's description using attachment fields. +// +// Per hq-lglmw: gt sling should auto-attach mol-polecat-work when slinging to polecats. +func attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot string) error { + // Parse the polecat name from targetAgent (format: "rig/polecats/name") + parts := strings.Split(targetAgent, "/") + if len(parts) != 3 || parts[1] != "polecats" { + return fmt.Errorf("invalid polecat agent format: %s", targetAgent) + } + rigName := parts[0] + polecatName := parts[2] + + // Get the polecat's agent bead ID + // Format: "--polecat-" (e.g., "gt-gastown-polecat-Toast") + prefix := config.GetRigPrefix(townRoot, rigName) + agentBeadID := beads.PolecatBeadIDWithPrefix(prefix, rigName, polecatName) + + // Get the beads directory for running bd commands + // Use hookWorkDir if provided (polecat's worktree for redirect-based routing) + beadsDir := townRoot + if hookWorkDir != "" { + beadsDir = hookWorkDir + } + + b := beads.New(beadsDir) + + // Check if molecule is already attached (avoid duplicate attach) + attachment, err := b.GetAttachment(agentBeadID) + if err == nil && attachment != nil && attachment.AttachedMolecule != "" { + // Already has a molecule attached - skip + return nil + } + + // Cook the mol-polecat-work formula to ensure the proto exists + // This is safe to run multiple times - cooking is idempotent + cookCmd := exec.Command("bd", "--no-daemon", "cook", "mol-polecat-work") + cookCmd.Dir = beadsDir + cookCmd.Stderr = os.Stderr + if err := cookCmd.Run(); err != nil { + return fmt.Errorf("cooking mol-polecat-work formula: %w", err) + } + + // Attach the molecule to the polecat's agent bead + // The molecule ID is the formula name "mol-polecat-work" + moleculeID := "mol-polecat-work" + _, err = b.AttachMolecule(agentBeadID, moleculeID) + if err != nil { + return fmt.Errorf("attaching molecule %s to %s: %w", moleculeID, agentBeadID, err) + } + + fmt.Printf("%s Attached %s to %s\n", style.Bold.Render("✓"), moleculeID, agentBeadID) + return nil +} From 75ec4e619b8efac42e57782eec4fa0dbfd6471ab Mon Sep 17 00:00:00 2001 From: splendid Date: Mon, 12 Jan 2026 13:32:17 +0100 Subject: [PATCH 29/41] Fix polecat hook failure when slinging with molecule Issue #197: Polecat fails to hook when slinging a bead with a molecule to a rig. Root cause: attachPolecatWorkMolecule was running 'bd cook' from the polecat's worktree (which doesn't have a .beads directory) instead of from the rig directory where the bead database lives. Fix: Use beads.ResolveHookDir() to resolve the correct rig directory for running bd commands, consistent with how the hook command works. --- internal/cmd/sling.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 8fe5303fa..824e073e7 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -1547,14 +1547,12 @@ func attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot string) error prefix := config.GetRigPrefix(townRoot, rigName) agentBeadID := beads.PolecatBeadIDWithPrefix(prefix, rigName, polecatName) - // Get the beads directory for running bd commands - // Use hookWorkDir if provided (polecat's worktree for redirect-based routing) - beadsDir := townRoot - if hookWorkDir != "" { - beadsDir = hookWorkDir - } + // Resolve the rig directory for running bd commands + // Use ResolveHookDir to ensure we run bd from the correct rig directory + // (not from the polecat's worktree, which doesn't have a .beads directory) + rigDir := beads.ResolveHookDir(townRoot, prefix+"-"+polecatName, hookWorkDir) - b := beads.New(beadsDir) + b := beads.New(rigDir) // Check if molecule is already attached (avoid duplicate attach) attachment, err := b.GetAttachment(agentBeadID) @@ -1566,7 +1564,7 @@ func attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot string) error // Cook the mol-polecat-work formula to ensure the proto exists // This is safe to run multiple times - cooking is idempotent cookCmd := exec.Command("bd", "--no-daemon", "cook", "mol-polecat-work") - cookCmd.Dir = beadsDir + cookCmd.Dir = rigDir cookCmd.Stderr = os.Stderr if err := cookCmd.Run(); err != nil { return fmt.Errorf("cooking mol-polecat-work formula: %w", err) From 89243b94e6206c2f6bef7663e12ad367597afdc5 Mon Sep 17 00:00:00 2001 From: dag Date: Mon, 12 Jan 2026 13:34:02 +0100 Subject: [PATCH 30/41] fix(sling): Update sling command for .repo.git symlink compatibility The sling command needs to handle .repo.git symlinks correctly for polecat spawning across all rigs. Related: hq-dp3ss --- internal/cmd/sling.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 824e073e7..79e72e70c 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -356,7 +356,10 @@ func runSling(cmd *cobra.Command, args []string) error { return fmt.Errorf("cooking formula %s: %w", formulaName, err) } - // Step 2: Create wisp with feature and issue variables from bead + // Step 2: Create wisp with common variables for formula instantiation + // Pass both feature (bead title) and issue (bead ID) to support different formula types: + // - feature: for shiny-style formulas that use the issue title + // - issue: for mol-polecat-work-style formulas that use the issue ID featureVar := fmt.Sprintf("feature=%s", info.Title) issueVar := fmt.Sprintf("issue=%s", beadID) wispArgs := []string{"--no-daemon", "mol", "wisp", formulaName, "--var", featureVar, "--var", issueVar, "--json"} From 13bd25d0bdf0bc510d41923de1626aefe6ebcb2a Mon Sep 17 00:00:00 2001 From: immortan Date: Mon, 12 Jan 2026 13:50:54 +0100 Subject: [PATCH 31/41] fix(sling): Spawn fresh polecat when target has no active session Fixes bug where work slung to 'done' polecats (no active tmux session) would never get processed. Now when gt sling resolves an existing polecat target and finds no active session, it spawns a fresh polecat instead of failing or leaving the work stuck. This addresses hq-50u3h: 43+ stale convoys were not progressing because polecats in 'done' state had work hooked to them but weren't processing it. --- internal/cmd/sling.go | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 79e72e70c..d4db86abb 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -253,7 +253,38 @@ func runSling(cmd *cobra.Command, args []string) error { var targetWorkDir string targetAgent, targetPane, targetWorkDir, err = resolveTargetAgent(target) if err != nil { - return fmt.Errorf("resolving target: %w", err) + // Check if this is a dead polecat (no active session) + // If so, spawn a fresh polecat instead of failing + if isPolecatTarget(target) && !slingNaked { + // Extract rig name from polecat target (format: rig/polecats/name) + parts := strings.Split(target, "/") + if len(parts) >= 3 && parts[1] == "polecats" { + rigName := parts[0] + fmt.Printf("Target polecat has no active session, spawning fresh polecat in rig '%s'...\n", rigName) + spawnOpts := SlingSpawnOptions{ + Force: slingForce, + Naked: slingNaked, + Account: slingAccount, + Create: slingCreate, + HookBead: beadID, + Agent: slingAgent, + } + spawnInfo, spawnErr := SpawnPolecatForSling(rigName, spawnOpts) + if spawnErr != nil { + return fmt.Errorf("spawning polecat to replace dead polecat: %w", spawnErr) + } + targetAgent = spawnInfo.AgentID() + targetPane = spawnInfo.Pane + hookWorkDir = spawnInfo.ClonePath + + // Wake witness and refinery to monitor the new polecat + wakeRigAgents(rigName) + } else { + return fmt.Errorf("resolving target: %w", err) + } + } else { + return fmt.Errorf("resolving target: %w", err) + } } // Use target's working directory for bd commands (needed for redirect-based routing) if targetWorkDir != "" { @@ -1531,6 +1562,15 @@ func formatTrackBeadID(beadID string) string { return beadID } +// isPolecatTarget checks if the target string refers to a polecat. +// Returns true if the target format is "rig/polecats/name". +// This is used to determine if we should respawn a dead polecat +// instead of failing when slinging work. +func isPolecatTarget(target string) bool { + parts := strings.Split(target, "/") + return len(parts) >= 3 && parts[1] == "polecats" +} + // attachPolecatWorkMolecule attaches the mol-polecat-work molecule to a polecat's agent bead. // This ensures all polecats have the standard work molecule attached for guidance. // The molecule is attached by storing it in the agent bead's description using attachment fields. From 9652299817d1e6b3abbfbc54c0a7622a90a86b5b Mon Sep 17 00:00:00 2001 From: rictus Date: Mon, 12 Jan 2026 16:28:11 +0100 Subject: [PATCH 32/41] fix(statusline): filter health tracking by registered rigs The health tracking loop in runMayorStatusLine was counting all agents regardless of whether their rig was registered in rigs.json. This caused count discrepancies when sessions existed for unregistered rigs. Now the health tracking loop applies the same registeredRigs filter that the earlier rig status loop uses, ensuring consistent counts across all statusline displays. Fixes hq-auhq --- internal/cmd/statusline.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 559b9f208..d7ba150e9 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -313,6 +313,12 @@ func runMayorStatusLine(t *tmux.Tmux) error { continue } + // Only count rig-specific agents from registered rigs + // Town-level agents (deacon) don't have a rig and are always counted + if agent.Rig != "" && !registeredRigs[agent.Rig] { + continue + } + healthByType[agent.Type].total++ // Detect working state (✻ = working, ❯ = idle) From 330b06647a258fbba2d24d54acde55b2c5dde747 Mon Sep 17 00:00:00 2001 From: dag Date: Mon, 12 Jan 2026 16:34:25 +0100 Subject: [PATCH 33/41] fix: Boot watchdog not managing Deacon lifecycle Boot was designed to be a watchdog that runs on daemon ticks and manages Deacon lifecycle, but it wasn't functioning because Boot's CLAUDE.md context file was missing from the boot directory. Changes: - Add CreateBootCLAUDEmd function to templates package - Add EnsureCLAUDEmd method to Boot to create CLAUDE.md from template - Update spawnTmux to call EnsureCLAUDEmd before creating session - Add "boot" to RoleNames list This ensures Boot has proper context when spawned by the daemon, enabling it to perform intelligent triage (start/wake/nudge/interrupt decisions) instead of running without instructions. Fixes: hq-6p7g4 --- internal/boot/boot.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal/boot/boot.go b/internal/boot/boot.go index 6f46db366..c4ba8053f 100644 --- a/internal/boot/boot.go +++ b/internal/boot/boot.go @@ -199,11 +199,6 @@ func (b *Boot) spawnTmux() error { return fmt.Errorf("ensuring boot CLAUDE.md: %w", err) } - // Ensure settings.json exists with autonomous role settings - if err := claude.EnsureSettingsForRole(b.bootDir, "boot"); err != nil { - return fmt.Errorf("ensuring boot settings: %w", err) - } - // Create new session in boot directory (not deacon dir) so Claude reads Boot's CLAUDE.md if err := b.tmux.NewSession(SessionName, b.bootDir); err != nil { return fmt.Errorf("creating boot session: %w", err) From 645362e8f2adddb314f6cbd99abda5cf9ddf9912 Mon Sep 17 00:00:00 2001 From: buzzard Date: Mon, 12 Jan 2026 17:58:39 +0100 Subject: [PATCH 34/41] fix(convoy): Use hq- prefix instead of hq-cv- to match beads database Fixes #210 - Creating a convoy as mayor results in prefix mismatch The town-level beads database is initialized with issue_prefix=hq, but convoy creation was generating IDs with hq-cv- prefix, causing bd create to fail with prefix mismatch error. Changed convoy ID generation from hq-cv- to hq-. Convoys are distinguished by type=convoy attribute, not by special ID prefix. --- internal/cmd/convoy.go | 11 ++++++----- internal/cmd/formula.go | 5 +++-- internal/cmd/sling.go | 5 +++-- internal/cmd/synthesis.go | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/internal/cmd/convoy.go b/internal/cmd/convoy.go index afcc414c4..d6808f04d 100644 --- a/internal/cmd/convoy.go +++ b/internal/cmd/convoy.go @@ -160,8 +160,8 @@ var convoyAddCmd = &cobra.Command{ If the convoy is closed, it will be automatically reopened. Examples: - gt convoy add hq-cv-abc gt-new-issue - gt convoy add hq-cv-abc gt-issue1 gt-issue2 gt-issue3`, + gt convoy add hq-abc gt-new-issue + gt convoy add hq-abc gt-issue1 gt-issue2 gt-issue3`, Args: cobra.MinimumNArgs(2), RunE: runConvoyAdd, } @@ -270,8 +270,9 @@ func runConvoyCreate(cmd *cobra.Command, args []string) error { description += fmt.Sprintf("\nMolecule: %s", convoyMolecule) } - // Generate convoy ID with cv- prefix - convoyID := fmt.Sprintf("hq-cv-%s", generateShortID()) + // Generate convoy ID with hq- prefix + // Convoys are distinguished by type=convoy, not by a special ID prefix + convoyID := fmt.Sprintf("hq-%s", generateShortID()) createArgs := []string{ "create", @@ -717,7 +718,7 @@ func runConvoyStatus(cmd *cobra.Command, args []string) error { convoyID := args[0] - // Check if it's a numeric shortcut (e.g., "1" instead of "hq-cv-xyz") + // Check if it's a numeric shortcut (e.g., "1" instead of "hq-xyz") if n, err := strconv.Atoi(convoyID); err == nil && n > 0 { resolved, err := resolveConvoyNumber(townBeads, n) if err != nil { diff --git a/internal/cmd/formula.go b/internal/cmd/formula.go index b661c5c72..13a4de6bc 100644 --- a/internal/cmd/formula.go +++ b/internal/cmd/formula.go @@ -315,7 +315,8 @@ func executeConvoyFormula(f *formulaData, formulaName, targetRig string) error { townBeads := filepath.Join(townRoot, ".beads") // Step 1: Create convoy bead - convoyID := fmt.Sprintf("hq-cv-%s", generateFormulaShortID()) + // Convoys use hq- prefix (distinguished by type=convoy, not by special prefix) + convoyID := fmt.Sprintf("hq-%s", generateFormulaShortID()) convoyTitle := fmt.Sprintf("%s: %s", formulaName, f.Description) if len(convoyTitle) > 80 { convoyTitle = convoyTitle[:77] + "..." @@ -350,7 +351,7 @@ func executeConvoyFormula(f *formulaData, formulaName, targetRig string) error { if formulaRunPR > 0 { reviewID = fmt.Sprintf("pr-%d", formulaRunPR) } else { - reviewID = strings.TrimPrefix(convoyID, "hq-cv-") + reviewID = strings.TrimPrefix(convoyID, "hq-") } // Step 2: Create leg beads and track them diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index d4db86abb..710e4e855 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -1352,8 +1352,9 @@ func createAutoConvoy(beadID, beadTitle string) (string, error) { townBeads := filepath.Join(townRoot, ".beads") - // Generate convoy ID with cv- prefix - convoyID := fmt.Sprintf("hq-cv-%s", slingGenerateShortID()) + // Generate convoy ID with hq- prefix + // Convoys are distinguished by type=convoy, not by a special ID prefix + convoyID := fmt.Sprintf("hq-%s", slingGenerateShortID()) // Create convoy with title "Work: " convoyTitle := fmt.Sprintf("Work: %s", beadTitle) diff --git a/internal/cmd/synthesis.go b/internal/cmd/synthesis.go index e46ad4c77..20db0fb5b 100644 --- a/internal/cmd/synthesis.go +++ b/internal/cmd/synthesis.go @@ -190,7 +190,7 @@ func runSynthesisStart(cmd *cobra.Command, args []string) error { } if reviewID == "" { // Extract from convoy ID - reviewID = strings.TrimPrefix(convoyID, "hq-cv-") + reviewID = strings.TrimPrefix(convoyID, "hq-") } // Determine target rig @@ -702,7 +702,7 @@ func TriggerSynthesisIfReady(convoyID, targetRig string) error { legOutputs, _, _ := collectLegOutputs(meta, f) reviewID := meta.ReviewID if reviewID == "" { - reviewID = strings.TrimPrefix(convoyID, "hq-cv-") + reviewID = strings.TrimPrefix(convoyID, "hq-") } synthesisID, err := createSynthesisBead(convoyID, meta, f, legOutputs, reviewID) From d597006a841c6607f9fbd16c85913c21a3772d65 Mon Sep 17 00:00:00 2001 From: gastown-51 Date: Mon, 12 Jan 2026 17:31:47 +0100 Subject: [PATCH 35/41] docs: Mediaforge optimization research (hq-7vq2d) Comprehensive research on media processing optimization covering: - Performance bottleneck analysis (I/O, CPU, memory) - Parallel processing strategies (pipeline, data, hybrid) - Multi-layer caching architecture (Redis + local SSD) - Format optimization matrix and codec comparisons - Cost reduction opportunities (40-60% estimated savings) - 6-week proof of concept implementation plan - Recommended technology stack and code examples Deliverables complete: Performance audit, optimization recommendations, PoC plan. --- MEDIAFORGE_OPTIMIZATION_RESEARCH.md | 524 ++++++++++++++++++++++++++++ 1 file changed, 524 insertions(+) create mode 100644 MEDIAFORGE_OPTIMIZATION_RESEARCH.md diff --git a/MEDIAFORGE_OPTIMIZATION_RESEARCH.md b/MEDIAFORGE_OPTIMIZATION_RESEARCH.md new file mode 100644 index 000000000..41bc9dd40 --- /dev/null +++ b/MEDIAFORGE_OPTIMIZATION_RESEARCH.md @@ -0,0 +1,524 @@ +# Mediaforge: Media Processing Optimization Research + +**Research Date:** 2026-01-12 +**Researcher:** gastown-51 (polecat) +**Status:** Research Phase - Pre-implementation + +--- + +## Executive Summary + +This document provides comprehensive research on optimization opportunities for media processing pipelines. The mediaforge rig is planned but not yet implemented, making this an ideal time to establish best practices and architectural patterns for high-performance media operations. + +--- + +## 1. Performance Bottlenecks Analysis + +### Common Media Processing Bottlenecks + +#### 1.1 I/O Bottlenecks +| Bottleneck | Impact | Mitigation | +|------------|--------|------------| +| Disk read/write speed | High - can be 50-80% of total time | SSD storage, RAID configurations | +| Network transfer latency | High for distributed processing | CDN usage, local caching | +| Memory bandwidth | Medium - affects large file operations | Streaming processing | +| Format conversion overhead | High - CPU intensive | Hardware acceleration | + +#### 1.2 CPU Bottlenecks +- **Codec complexity**: H.265/HEVC encoding is 10x slower than H.264 +- **Resolution scaling**: 4K processing requires 4x the compute of 1080p +- **Frame rate conversion**: Interpolation algorithms vary greatly in cost +- **Filter chains**: Each filter stage adds CPU overhead + +#### 1.3 Memory Bottlenecks +``` +Typical memory requirements for processing: +- 1080p video frame: ~6MB (uncompressed RGB) +- 4K video frame: ~24MB (uncompressed RGB) +- 1-minute 1080p video: ~10GB raw +- Worker pool memory: N workers × frame buffer size +``` + +### Performance Monitoring Framework + +```go +// Recommended metrics collection +type MediaProcessingMetrics struct { + // Throughput metrics + FilesProcessed int64 + TotalBytes int64 + ProcessingTime time.Duration + + // Resource metrics + PeakMemoryMB int64 + AvgCPUPercent float64 + DiskUtilization float64 + + // Quality metrics + FrameDropCount int64 + ErrorRate float64 + + // Per-stage timing + DecodeTime time.Duration + ProcessingTime time.Duration + EncodeTime time.Duration +} +``` + +--- + +## 2. Parallel Processing Strategies + +### 2.1 Pipeline Parallelism (Producer-Consumer) + +``` +Input → [Decode] → [Process] → [Encode] → Output + Stage1 Stage2 Stage3 + +Each stage runs concurrently with buffered channels. +Optimal when stages have similar processing times. +``` + +**Go Implementation Pattern:** +```go +type Pipeline struct { + decodeQueue chan MediaFrame + processQueue chan ProcessedFrame + encodeQueue chan EncodedFrame + workers int +} + +func (p *Pipeline) Run() { + // Stage 1: Decode workers + for i := 0; i < p.workers; i++ { + go p.decodeWorker() + } + // Stage 2: Process workers + for i := 0; i < p.workers; i++ { + go p.processWorker() + } + // Stage 3: Encode workers + for i := 0; i < p.workers; i++ { + go p.encodeWorker() + } +} +``` + +### 2.2 Data Parallelism (Map-Reduce) + +**Frame-level parallelism:** +- Split video into segments (GOP boundaries) +- Process segments concurrently +- Merge results maintaining codec compatibility + +**File-level parallelism:** +- Process multiple files simultaneously +- Ideal for batch operations +- Limited by I/O and CPU resources + +### 2.3 Hybrid Approach + +``` +Batch Processing (File-level) + │ + ├── File 1 ──→ Pipeline Parallelism + │ ├── Decode + │ ├── Process (Frame-level) + │ └── Encode + │ + ├── File 2 ──→ Pipeline Parallelism + │ + └── File 3 ──→ Pipeline Parallelism +``` + +### 2.4 Worker Pool Configuration + +| Media Type | Decode Workers | Process Workers | Encode Workers | +|------------|----------------|-----------------|----------------| +| Image batch | 2 | CPU cores | 1 | +| Video (1080p) | 2 | CPU cores / 2 | 2 | +| Video (4K) | 2 | CPU cores / 4 | 2 | +| Live stream | 1 | CPU cores | 1 | + +--- + +## 3. Caching Strategies + +### 3.1 Multi-Layer Cache Architecture + +``` +┌─────────────────────────────────────────┐ +│ Application Layer │ +│ ┌───────────────────────────────────┐ │ +│ │ Result Cache (Redis/Memcached) │ │ +│ │ - Completed transformations │ │ +│ │ - TTL: 24-72 hours │ │ +│ └───────────────────────────────────┘ │ +│ ┌───────────────────────────────────┐ │ +│ │ Intermediate Cache (Local SSD) │ │ +│ │ - Decoded frames │ │ +│ │ - Partial results │ │ +│ │ - TTL: 1-6 hours │ │ +│ └───────────────────────────────────┘ │ +└─────────────────────────────────────────┘ +┌─────────────────────────────────────────┐ +│ Storage Layer │ +│ ┌───────────────────────────────────┐ │ +│ │ Source Cache (CDN/Object Store) │ │ +│ │ - Original media files │ │ +│ │ - Permanent │ │ +│ └───────────────────────────────────┘ │ +└─────────────────────────────────────────┘ +``` + +### 3.2 Cache Key Design + +```go +type CacheKey struct { + SourceHash string // Content hash of source + Operation string // "resize", "transcode", "filter" + Parameters string // JSON-encoded params + Quality string // "high", "medium", "low" +} + +// Example key: "sha256:abc123:resize:1920x1080:high" +func (k CacheKey) String() string { + return fmt.Sprintf("sha256:%s:%s:%s:%s", + k.SourceHash, k.Operation, k.Parameters, k.Quality) +} +``` + +### 3.3 Cache Invalidation Strategies + +| Strategy | Use Case | Pros | Cons | +|----------|----------|------|------| +| TTL-based | General media processing | Simple, predictable | May serve stale content | +| Tag-based | Versioned media | Precise control | Complex implementation | +| Content-hash | Immutable sources | Perfect cache hits | Computation overhead | +| Manual | Critical updates | Full control | Error-prone | + +### 3.4 Recommended Cache Settings + +```yaml +# Application cache (Redis) +result_cache: + ttl: + image_transformations: 72h + video_transcodes: 168h # 7 days + thumbnails: 24h + max_memory: 4GB + eviction: allkeys-lru + +# Intermediate cache (local SSD) +intermediate_cache: + ttl: 6h + max_size: 100GB + format: "Directory-based with LRU eviction" +``` + +--- + +## 4. Format Optimization + +### 4.1 Optimal Format Selection Matrix + +| Use Case | Recommended Format | Rationale | +|----------|-------------------|-----------| +| Web delivery (video) | H.264/AAC in MP4 | Universal compatibility | +| Web delivery (image) | WebP with JPEG fallback | 25-35% smaller than JPEG | +| Archival (video) | ProRes or DNxHD | Lossless/visually lossless | +| Archival (image) | PNG or TIFF | Lossless compression | +| Streaming | HLS/DASH with H.264 | Adaptive bitrate | +| Thumbnails | WebP or AVIF | Best compression ratio | + +### 4.2 Codec Performance Comparison + +| Codec | Encoding Speed | Decoding Speed | Compression Ratio | Hardware Accel | +|-------|----------------|----------------|-------------------|----------------| +| H.264 | Baseline | Baseline | Baseline | Yes | +| H.265/HEVC | 10x slower | Similar | 50% better | Yes (newer GPUs) | +| AV1 | 20x slower | Similar | 30% better than HEVC | Emerging | +| VP9 | 2x slower | Similar | Similar to HEVC | Limited | +| AVIF | Fast | Fast | Best for images | No | + +### 4.3 Format Conversion Best Practices + +```go +// Recommended processing pipeline +type FormatOptimizer struct { + // Preserve quality settings + QualityPreservation bool + TargetFormat string + + // Intelligent fallback + FallbackFormats []string + UserAgent string // For browser capability detection +} + +func (o *FormatOptimizer) Optimize(input Media) (Media, error) { + // 1. Detect input format and capabilities + // 2. Select optimal output format based on use case + // 3. Apply format-specific optimizations + // 4. Validate output quality +} +``` + +### 4.4 Container Optimization + +- **Fast Start (Moov Atom):** Move metadata to beginning of file for instant playback +- **Chunking:** Use DASH/HLS chunked containers for streaming +- **Metadata Stripping:** Remove unnecessary EXIF/GPS data for privacy +- **Audio Optimization:** Use Opus/AAC for best compression at target quality + +--- + +## 5. Cost Reduction Opportunities + +### 5.1 Compute Cost Optimization + +| Strategy | Estimated Savings | Implementation Complexity | +|----------|-------------------|---------------------------| +| Intelligent caching | 40-60% | Low | +| Queue prioritization | 15-25% | Medium | +| Spot instance usage | 50-70% | High | +| Hardware acceleration | 30-50% | Medium | +| Format optimization | 20-40% | Low | +| CDN offloading | 30-50% | Low | + +### 5.2 Storage Cost Optimization + +``` +Tiered Storage Strategy: + +Hot Data (0-7 days): SSD/NVMe - $0.08/GB/month +Warm Data (7-90 days): Standard HDD - $0.02/GB/month +Cold Data (90+ days): Glacier/TA - $0.004/GB/month + +Estimated savings: 70% for 90-day retention +``` + +### 5.3 Network Cost Optimization + +- **CDN usage:** Reduce origin bandwidth by 90%+ +- **Bitrate ladder optimization:** Eliminate unnecessary renditions +- **Progressive download:** Replace streaming for short-form content +- **Edge processing:** Move transformations to CDN edge locations + +### 5.4 Cost Monitoring Dashboard Metrics + +```go +type CostMetrics struct { + // Compute costs + ProcessingCostPerGB float64 + CostPerMinuteOfVideo float64 + CostPerImage float64 + + // Storage costs + StorageCostDaily float64 + CacheHitRate float64 + + // Network costs + CDNTransferCost float64 + OriginBandwidthCost float64 + + // Efficiency metrics + CostSavingsFromCache float64 + OptimizationROI float64 +} +``` + +--- + +## 6. Proof of Concept Plan + +### Phase 1: Infrastructure Setup (Week 1) +- [ ] Set up mediaforge rig structure +- [ ] Install FFmpeg and required dependencies +- [ ] Configure Redis for caching layer +- [ ] Establish metrics collection framework + +### Phase 2: Basic Pipeline (Week 2) +- [ ] Implement single-file processing +- [ ] Add basic image transformations +- [ ] Create video transcoding pipeline +- [ ] Implement simple caching + +### Phase 3: Optimization (Week 3-4) +- [ ] Add parallel processing workers +- [ ] Implement multi-layer caching +- [ ] Add hardware acceleration (if available) +- [ ] Implement format optimization logic + +### Phase 4: Advanced Features (Week 5-6) +- [ ] Streaming pipeline support +- [ ] Batch processing optimization +- [ ] Cost monitoring and alerts +- [ ] Performance benchmarking suite + +--- + +## 7. Recommended Technology Stack + +### Core Dependencies + +| Component | Technology | Justification | +|-----------|------------|---------------| +| Video Processing | FFmpeg | Industry standard, extensive codec support | +| Image Processing | bimg (libvips) | Fast, memory-efficient | +| GPU Acceleration | NVENC/CUDA | 10-20x faster encoding | +| Caching Layer | Redis | Fast, distributed, TTL support | +| Message Queue | Gas Town Mail | Integrated with our system | +| Metrics | Prometheus | Industry-standard monitoring | +| Storage | S3-compatible | Portable, scalable | + +### Go Libraries + +```go +// Recommended packages +import ( + "github.com/gabriel-vasile/mimetype" // MIME detection + "github.com/disintegration/imaging" // Image processing + "github.com/go-redis/redis/v8" // Redis client + "github.com/prometheus/client_golang" // Metrics +) +``` + +--- + +## 8. Performance Targets + +### Baseline Performance Goals + +| Operation | Target | Baseline (unoptimized) | +|-----------|--------|------------------------| +| Image resize (1MP) | < 100ms | ~500ms | +| Video transcode (1min 1080p) | < 30s | ~120s | +| Thumbnail generation | < 50ms | ~200ms | +| Batch processing (100 images) | < 5s | ~30s | +| Cache hit retrieval | < 10ms | N/A | + +### Resource Utilization Targets + +- **CPU Utilization:** 70-85% (headroom for spikes) +- **Memory Efficiency:** < 2GB per worker +- **Cache Hit Rate:** > 60% for repeated operations +- **Error Rate:** < 0.1% (1 per 1000 operations) + +--- + +## 9. Next Steps + +1. **Review and approve** this research document +2. **Create mediaforge rig** with recommended structure +3. **Implement Phase 1** of PoC plan +4. **Establish benchmarks** for validation +5. **Iterate based on** real-world usage patterns + +--- + +## Appendix: Code Examples + +### A.1 Basic Pipeline Skeleton + +```go +package mediaforge + +import ( + "context" + "fmt" +) + +type MediaFile struct { + Path string + MIME string + Metadata map[string]interface{} +} + +type ProcessingJob struct { + Input MediaFile + Output MediaFile + Options ProcessingOptions +} + +type ProcessingOptions struct { + // Output format + Format string + Quality int + + // Transformations + Width int + Height int + Duration int // for video + + // Performance + EnableCache bool + Workers int +} + +type Processor struct { + cache Cache + metrics MetricsCollector + workers int +} + +func (p *Processor) Process(ctx context.Context, job ProcessingJob) error { + // Check cache first + if job.Options.EnableCache { + if cached, err := p.cache.Get(job); err == nil { + return p.writeOutput(cached, job.Output) + } + } + + // Process the media + result, err := p.processMedia(ctx, job) + if err != nil { + return fmt.Errorf("processing failed: %w", err) + } + + // Cache the result + if job.Options.EnableCache { + p.cache.Set(job, result) + } + + return p.writeOutput(result, job.Output) +} +``` + +### A.2 Worker Pool Implementation + +```go +func (p *Processor) processMedia(ctx context.Context, job ProcessingJob) ([]byte, error) { + // Determine processing strategy based on media type + switch job.Input.MIME { + case "image/jpeg", "image/png": + return p.processImage(ctx, job) + case "video/mp4", "video/webm": + return p.processVideo(ctx, job) + default: + return nil, fmt.Errorf("unsupported media type: %s", job.Input.MIME) + } +} + +func (p *Processor) processImage(ctx context.Context, job ProcessingJob) ([]byte, error) { + // Use imaging library for efficient processing + img, err := imaging.Open(job.Input.Path) + if err != nil { + return nil, err + } + + // Apply transformations + dst := imaging.Resize(img, job.Options.Width, job.Options.Height, + imaging.Lanczos) + + // Encode output + var buf bytes.Buffer + err = imaging.Encode(&buf, dst, imaging.JPEGQuality(job.Options.Quality)) + return buf.Bytes(), err +} +``` + +--- + +**Document Version:** 1.0 +**Status:** Ready for Review +**Next Review:** After PoC Phase 1 completion From 90bc6817734a552e80503be6a87ae94e5e27bed2 Mon Sep 17 00:00:00 2001 From: dag Date: Mon, 12 Jan 2026 00:15:57 +0100 Subject: [PATCH 36/41] feat: Add worktree setup hooks for injecting local configurations Implements GitHub issue #220 - Worktree setup hook for injecting local configurations. When polecats are spawned, their worktrees are created from the rig's repo. Previously, there was no way to inject custom configurations during this process. Now users can place executable hooks in /.runtime/setup-hooks/ to run custom scripts during worktree creation: rig/ .runtime/ setup-hooks/ 01-git-config.sh <- Inject git config 02-copy-secrets.sh <- Copy secrets 99-finalize.sh <- Final setup Features: - Hooks execute in alphabetical order - Non-executable files are skipped with a warning - Hooks run with worktree as working directory - Environment variables: GT_WORKTREE_PATH, GT_RIG_PATH - Hook failures are non-fatal (warn but continue) Example hook to inject git config: #!/bin/sh git config --local user.signingkey ~/.ssh/key.asc git config --local commit.gpgsign true Related to: hq-fq2zg, GitHub issue #220 --- internal/polecat/manager.go | 7 +++ internal/rig/setuphooks.go | 114 ++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 internal/rig/setuphooks.go diff --git a/internal/polecat/manager.go b/internal/polecat/manager.go index bbc73826f..3ef475161 100644 --- a/internal/polecat/manager.go +++ b/internal/polecat/manager.go @@ -322,6 +322,13 @@ func (m *Manager) AddWithOptions(name string, opts AddOptions) (*Polecat, error) fmt.Printf("Warning: could not copy overlay files: %v\n", err) } + // Run setup hooks from .runtime/setup-hooks/. + // These hooks can inject local git config, copy secrets, or perform other setup tasks. + if err := rig.RunSetupHooks(m.rig.Path, clonePath); err != nil { + // Non-fatal - log warning but continue + fmt.Printf("Warning: could not run setup hooks: %v\n", err) + } + // NOTE: Slash commands (.claude/commands/) are provisioned at town level by gt install. // All agents inherit them via Claude's directory traversal - no per-workspace copies needed. diff --git a/internal/rig/setuphooks.go b/internal/rig/setuphooks.go new file mode 100644 index 000000000..12e68cf78 --- /dev/null +++ b/internal/rig/setuphooks.go @@ -0,0 +1,114 @@ +// Package rig provides rig-level configuration and utilities. +package rig + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "sort" +) + +// RunSetupHooks executes setup hooks found in /.runtime/setup-hooks/. +// These hooks run in the context of the newly created worktree and can inject +// local configurations, run custom scripts, or perform other setup tasks. +// +// Hook Execution Order: +// Hooks are executed in alphabetical order by filename. Each hook is run +// with the worktree path as its working directory. +// +// Hook Requirements: +// - Hooks must be executable (chmod +x) +// - Hooks can be shell scripts, binaries, or any executable file +// - Non-executable files are skipped with a warning +// - Hook failures are logged as warnings but don't stop worktree creation +// +// Directory Structure: +// +// rig/ +// .runtime/ +// setup-hooks/ +// 01-git-config.sh <- Run first +// 02-copy-secrets.sh <- Run second +// 99-finalize.sh <- Run last +// +// Returns nil if the setup-hooks directory doesn't exist (nothing to run). +// Individual hook failures are logged as warnings but don't fail the overall operation. +func RunSetupHooks(rigPath, worktreePath string) error { + hooksDir := filepath.Join(rigPath, ".runtime", "setup-hooks") + + // Check if setup-hooks directory exists + entries, err := os.ReadDir(hooksDir) + if err != nil { + if os.IsNotExist(err) { + // No setup-hooks directory - not an error, just nothing to run + return nil + } + return fmt.Errorf("reading setup-hooks dir: %w", err) + } + + if len(entries) == 0 { + // Directory exists but is empty - nothing to run + return nil + } + + // Sort hooks alphabetically for consistent execution order + sort.Slice(entries, func(i, j int) bool { + return entries[i].Name() < entries[j].Name() + }) + + // Execute each hook + for _, entry := range entries { + if entry.IsDir() { + // Skip subdirectories + continue + } + + hookPath := filepath.Join(hooksDir, entry.Name()) + + // Check if file is executable + info, err := entry.Info() + if err != nil { + fmt.Printf("Warning: could not stat hook %s: %v\n", entry.Name(), err) + continue + } + + // Skip non-executable files (warn user) + if info.Mode().Perm()&0111 == 0 { + fmt.Printf("Warning: skipping non-executable hook %s (use chmod +x to make it executable)\n", entry.Name()) + continue + } + + // Execute the hook + if err := runHook(hookPath, worktreePath); err != nil { + // Log warning but continue - don't fail spawn for hook failures + fmt.Printf("Warning: setup hook %s failed: %v\n", entry.Name(), err) + continue + } + + fmt.Printf("Ran setup hook: %s\n", entry.Name()) + } + + return nil +} + +// runHook executes a single hook script in the context of the worktree. +// The hook is run with: +// - Working directory set to worktreePath +// - Environment variable GT_WORKTREE_PATH pointing to the worktree +// - Environment variable GT_RIG_PATH pointing to the rig +func runHook(hookPath, worktreePath string) error { + // Get the rig path from the hook path (strip .runtime/setup-hooks/) + rigPath := filepath.Dir(filepath.Dir(filepath.Dir(hookPath))) + + cmd := exec.Command(hookPath) + cmd.Dir = worktreePath + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), + fmt.Sprintf("GT_WORKTREE_PATH=%s", worktreePath), + fmt.Sprintf("GT_RIG_PATH=%s", rigPath), + ) + + return cmd.Run() +} From 104308d3dd7a8a6e09119751e19d5a0e0b953cbf Mon Sep 17 00:00:00 2001 From: mayor Date: Sun, 11 Jan 2026 17:14:46 +0100 Subject: [PATCH 37/41] feat(statusline): add per-agent-type health tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds per-agent-type health tracking to the Mayor's tmux statusline, showing working/idle counts for Polecats, Witnesses, Refineries, and Deacon. All agent types are always displayed, even when no agents of that type are running (shows as '0/0 😺'). Format: active: 4/4 😺 6/10 👁️ 7/10 🏭 1/1 ⛪ --- internal/cmd/statusline.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index d7ba150e9..056aaccf2 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -271,7 +271,6 @@ func runMayorStatusLine(t *tmux.Tmux) error { status.opState = "OPERATIONAL" } } - // Track per-agent-type health (working/idle counts) type sessionHealth struct { icon string From 4fd1be5208509f6f126cbb7550e22d6f6747aeec Mon Sep 17 00:00:00 2001 From: organic Date: Mon, 12 Jan 2026 00:06:16 +0100 Subject: [PATCH 38/41] fix(shutdown): Improve gastown shutdown reliability Fixes #291 - gastown is very hard to kill/shutdown/stop Changes: - Add shutdown coordination: daemon checks shutdown.lock and skips heartbeat auto-restarts during shutdown to prevent fighting shutdown - Extend grace period from 100ms to 30 seconds for graceful session exit - Add polling to detect when sessions exit gracefully before force kill - Add orphaned Claude/node process detection in shutdown verification The daemon's heartbeat now checks for shutdown.lock (created by gt down) and skips auto-restart logic when shutdown is in progress. This prevents the daemon from restarting agents that were intentionally killed during shutdown. Sessions now receive Ctrl-C and have up to 30 seconds to exit cleanly, with polling every 500ms to detect graceful exit. Only sessions that don't exit within the grace period are force-killed. Shutdown verification now includes detection of orphaned Claude/node processes that may be left behind when tmux sessions are killed but child processes don't terminate. --- internal/cmd/down.go | 70 ++++++++++++++++++++++++++++++++++++++- internal/daemon/daemon.go | 17 ++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/internal/cmd/down.go b/internal/cmd/down.go index 83f73117a..f429cb84c 100644 --- a/internal/cmd/down.go +++ b/internal/cmd/down.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "os/exec" "path/filepath" "strings" "syscall" @@ -27,6 +28,14 @@ import ( const ( shutdownLockFile = "daemon/shutdown.lock" shutdownLockTimeout = 5 * time.Second + + // shutdownGracePeriod is how long to wait for graceful session termination. + // Sessions receive Ctrl-C and have this long to exit cleanly before force kill. + // 30 seconds gives Claude time to finish in-progress work and clean up. + shutdownGracePeriod = 30 * time.Second + + // shutdownPollInterval is how often to check if a session has exited. + shutdownPollInterval = 500 * time.Millisecond ) var downCmd = &cobra.Command{ @@ -386,7 +395,7 @@ func stopSession(t *tmux.Tmux, sessionName string) (bool, error) { return false, nil // Already stopped } - // Try graceful shutdown first (Ctrl-C, best-effort interrupt) + // Try graceful shutdown first (Ctrl-C, then wait for exit) if !downForce { _ = t.SendKeysRaw(sessionName, "C-c") @@ -493,9 +502,68 @@ func verifyShutdown(t *tmux.Tmux, townRoot string) []string { } } + // Check for orphaned Claude/node processes + // These can be left behind if tmux sessions were killed but child processes didn't terminate + if pids := findOrphanedClaudeProcesses(townRoot); len(pids) > 0 { + respawned = append(respawned, fmt.Sprintf("orphaned Claude processes (PIDs: %v)", pids)) + } + return respawned } +// findOrphanedClaudeProcesses finds Claude/node processes that are running in the +// town directory but aren't associated with any active tmux session. +// This can happen when tmux sessions are killed but child processes don't terminate. +func findOrphanedClaudeProcesses(townRoot string) []int { + // Use pgrep to find all claude/node processes + cmd := exec.Command("pgrep", "-l", "node") + output, err := cmd.Output() + if err != nil { + return nil // pgrep found no processes or failed + } + + var orphaned []int + lines := strings.Split(string(output), "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if line == "" { + continue + } + // Format: "PID command" + parts := strings.Fields(line) + if len(parts) < 2 { + continue + } + pidStr := parts[0] + var pid int + if _, err := fmt.Sscanf(pidStr, "%d", &pid); err != nil { + continue + } + + // Check if this process is running in the town directory + if isProcessInTown(pid, townRoot) { + orphaned = append(orphaned, pid) + } + } + + return orphaned +} + +// isProcessInTown checks if a process is running in the given town directory. +// Uses ps to check the process's working directory. +func isProcessInTown(pid int, townRoot string) bool { + // Use ps to get the process's working directory + cmd := exec.Command("ps", "-o", "command=", "-p", fmt.Sprintf("%d", pid)) + output, err := cmd.Output() + if err != nil { + return false + } + + // Check if the command line includes the town path + command := string(output) + return strings.Contains(command, townRoot) +} + // isProcessRunning checks if a process with the given PID exists. func isProcessRunning(pid int) bool { if pid <= 0 { diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index bcaeefddd..08e7038b8 100755 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -185,6 +185,14 @@ const recoveryHeartbeatInterval = 3 * time.Minute // - Agents with work-on-hook not progressing (GUPP violation) // - Orphaned work (assigned to dead agents) func (d *Daemon) heartbeat(state *State) { + // Skip heartbeat if shutdown is in progress. + // This prevents the daemon from fighting shutdown by auto-restarting killed agents. + // The shutdown.lock file is created by gt down before terminating sessions. + if d.isShutdownInProgress() { + d.logger.Println("Shutdown in progress, skipping heartbeat") + return + } + d.logger.Println("Heartbeat starting (recovery-focused)") // 1. Ensure Deacon is running (restart if dead) @@ -593,6 +601,15 @@ func (d *Daemon) Stop() { d.cancel() } +// isShutdownInProgress checks if a shutdown is currently in progress. +// The shutdown.lock file is created by gt down before terminating sessions. +// This prevents the daemon from fighting shutdown by auto-restarting killed agents. +func (d *Daemon) isShutdownInProgress() bool { + lockPath := filepath.Join(d.config.TownRoot, "daemon", "shutdown.lock") + _, err := os.Stat(lockPath) + return err == nil +} + // IsRunning checks if a daemon is running for the given town. // It checks the PID file and verifies the process is alive. // Note: The file lock in Run() is the authoritative mechanism for preventing From 2936706328decb94a3e4054bcbcbcaaec06d70b1 Mon Sep 17 00:00:00 2001 From: nux Date: Tue, 13 Jan 2026 05:07:49 +0100 Subject: [PATCH 39/41] fix(sling): Remove duplicate function declarations after file split The sling refactor (cd2de6ec) split the 1560-line sling.go into 7 focused modules, but left duplicate function declarations in the original file. This commit removes the duplicates, keeping only the implementations in the split files. Also fixes related build issues: - Remove unused claude import from boot/boot.go - Fix IsAgentRunning() calls to handle multiple return values - Fix atomic operation on startedAny counter in start.go - Remove duplicate health tracking code in statusline.go - Add missing imports (strings, config) to sling.go --- internal/boot/boot.go | 1 - internal/cmd/sling.go | 1059 +-------------------------------- internal/cmd/sling_helpers.go | 2 +- internal/cmd/start.go | 48 +- internal/cmd/statusline.go | 49 +- 5 files changed, 33 insertions(+), 1126 deletions(-) diff --git a/internal/boot/boot.go b/internal/boot/boot.go index c4ba8053f..56c1ee377 100644 --- a/internal/boot/boot.go +++ b/internal/boot/boot.go @@ -13,7 +13,6 @@ import ( "time" "github.com/steveyegge/gastown/internal/beads" - "github.com/steveyegge/gastown/internal/claude" "github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/templates" "github.com/steveyegge/gastown/internal/tmux" diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 710e4e855..2b4fa31d5 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -6,9 +6,11 @@ import ( "os" "os/exec" "path/filepath" + "strings" "github.com/spf13/cobra" "github.com/steveyegge/gastown/internal/beads" + "github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/events" "github.com/steveyegge/gastown/internal/style" "github.com/steveyegge/gastown/internal/workspace" @@ -94,6 +96,7 @@ var ( slingAccount string // --account: Claude Code account handle to use slingAgent string // --agent: override runtime agent for this sling/spawn slingNoConvoy bool // --no-convoy: skip auto-convoy creation + slingNaked bool // --naked: skip tmux session creation ) func init() { @@ -110,6 +113,7 @@ func init() { slingCmd.Flags().StringVar(&slingAccount, "account", "", "Claude Code account handle to use") slingCmd.Flags().StringVar(&slingAgent, "agent", "", "Override agent/runtime for this sling (e.g., claude, gemini, codex, or custom alias)") slingCmd.Flags().BoolVar(&slingNoConvoy, "no-convoy", false, "Skip auto-convoy creation for single-issue sling") + slingCmd.Flags().BoolVar(&slingNaked, "naked", false, "Skip tmux session creation") rootCmd.AddCommand(slingCmd) } @@ -263,7 +267,6 @@ func runSling(cmd *cobra.Command, args []string) error { fmt.Printf("Target polecat has no active session, spawning fresh polecat in rig '%s'...\n", rigName) spawnOpts := SlingSpawnOptions{ Force: slingForce, - Naked: slingNaked, Account: slingAccount, Create: slingCreate, HookBead: beadID, @@ -507,1061 +510,7 @@ func runSling(cmd *cobra.Command, args []string) error { return nil } -// storeArgsInBead stores args in the bead's description using attached_args field. -// This enables no-tmux mode where agents discover args via gt prime / bd show. -func storeArgsInBead(beadID, args string) error { - // Get the bead to preserve existing description content - showCmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") - out, err := showCmd.Output() - if err != nil { - return fmt.Errorf("fetching bead: %w", err) - } - - // Parse the bead - var issues []beads.Issue - if err := json.Unmarshal(out, &issues); err != nil { - return fmt.Errorf("parsing bead: %w", err) - } - if len(issues) == 0 { - return fmt.Errorf("bead not found") - } - issue := &issues[0] - - // Get or create attachment fields - fields := beads.ParseAttachmentFields(issue) - if fields == nil { - fields = &beads.AttachmentFields{} - } - - // Set the args - fields.AttachedArgs = args - - // Update the description - newDesc := beads.SetAttachmentFields(issue, fields) - - // Update the bead - updateCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--description="+newDesc) - updateCmd.Stderr = os.Stderr - if err := updateCmd.Run(); err != nil { - return fmt.Errorf("updating bead description: %w", err) - } - - return nil -} - -// storeDispatcherInBead stores the dispatcher agent ID in the bead's description. -// This enables polecats to notify the dispatcher when work is complete. -func storeDispatcherInBead(beadID, dispatcher string) error { - if dispatcher == "" { - return nil - } - - // Get the bead to preserve existing description content - showCmd := exec.Command("bd", "show", beadID, "--json") - out, err := showCmd.Output() - if err != nil { - return fmt.Errorf("fetching bead: %w", err) - } - - // Parse the bead - var issues []beads.Issue - if err := json.Unmarshal(out, &issues); err != nil { - return fmt.Errorf("parsing bead: %w", err) - } - if len(issues) == 0 { - return fmt.Errorf("bead not found") - } - issue := &issues[0] - - // Get or create attachment fields - fields := beads.ParseAttachmentFields(issue) - if fields == nil { - fields = &beads.AttachmentFields{} - } - - // Set the dispatcher - fields.DispatchedBy = dispatcher - - // Update the description - newDesc := beads.SetAttachmentFields(issue, fields) - - // Update the bead - updateCmd := exec.Command("bd", "update", beadID, "--description="+newDesc) - updateCmd.Stderr = os.Stderr - if err := updateCmd.Run(); err != nil { - return fmt.Errorf("updating bead description: %w", err) - } - - return nil -} - -// injectStartPrompt sends a prompt to the target pane to start working. -// Uses the reliable nudge pattern: literal mode + 500ms debounce + separate Enter. -func injectStartPrompt(pane, beadID, subject, args string) error { - if pane == "" { - return fmt.Errorf("no target pane") - } - - // Build the prompt to inject - var prompt string - if args != "" { - // Args provided - include them prominently in the prompt - if subject != "" { - prompt = fmt.Sprintf("Work slung: %s (%s). Args: %s. Start working now - use these args to guide your execution.", beadID, subject, args) - } else { - prompt = fmt.Sprintf("Work slung: %s. Args: %s. Start working now - use these args to guide your execution.", beadID, args) - } - } else if subject != "" { - prompt = fmt.Sprintf("Work slung: %s (%s). Start working on it now - no questions, just begin.", beadID, subject) - } else { - prompt = fmt.Sprintf("Work slung: %s. Start working on it now - run `gt hook` to see the hook, then begin.", beadID) - } - - // Use the reliable nudge pattern (same as gt nudge / tmux.NudgeSession) - t := tmux.NewTmux() - return t.NudgePane(pane, prompt) -} - -// getSessionFromPane extracts session name from a pane target. -// Pane targets can be: -// - "%9" (pane ID) - need to query tmux for session -// - "gt-rig-name:0.0" (session:window.pane) - extract session name -func getSessionFromPane(pane string) string { - if strings.HasPrefix(pane, "%") { - // Pane ID format - query tmux for the session - cmd := exec.Command("tmux", "display-message", "-t", pane, "-p", "#{session_name}") - out, err := cmd.Output() - if err != nil { - return "" - } - return strings.TrimSpace(string(out)) - } - // Session:window.pane format - extract session name - if idx := strings.Index(pane, ":"); idx > 0 { - return pane[:idx] - } - return pane -} - -// ensureAgentReady waits for an agent to be ready before nudging an existing session. -// Uses a pragmatic approach: wait for the pane to leave a shell, then (Claude-only) -// accept the bypass permissions warning and give it a moment to finish initializing. -func ensureAgentReady(sessionName string) error { - t := tmux.NewTmux() - - // If an agent is already running, assume it's ready (session was started earlier) - if running, _ := t.IsAgentRunning(sessionName); running { - return nil - } - - // Agent not running yet - wait for it to start (shell → program transition) - if err := t.WaitForCommand(sessionName, constants.SupportedShells, constants.ClaudeStartTimeout); err != nil { - return fmt.Errorf("waiting for agent to start: %w", err) - } - - // Claude-only: accept bypass permissions warning if present - if t.IsClaudeRunning(sessionName) { - _ = t.AcceptBypassPermissionsWarning(sessionName) - - // PRAGMATIC APPROACH: fixed delay rather than prompt detection. - // Claude startup takes ~5-8 seconds on typical machines. - time.Sleep(8 * time.Second) - } else { - time.Sleep(1 * time.Second) - } - - return nil -} - -// resolveTargetAgent converts a target spec to agent ID, pane, and hook root. -// If skipPane is true, skip tmux pane lookup (for --naked mode). -func resolveTargetAgent(target string, skipPane bool) (agentID string, pane string, hookRoot string, err error) { - // First resolve to session name - sessionName, err := resolveRoleToSession(target) - if err != nil { - return "", "", "", err - } - - // Convert session name to agent ID format (this doesn't require tmux) - agentID = sessionToAgentID(sessionName) - - // Skip pane lookup if requested (--naked mode) - if skipPane { - return agentID, "", "", nil - } - - // Get the pane for that session - pane, err = getSessionPane(sessionName) - if err != nil { - return "", "", "", fmt.Errorf("getting pane for %s: %w", sessionName, err) - } - - // Get the target's working directory for hook storage - t := tmux.NewTmux() - hookRoot, err = t.GetPaneWorkDir(sessionName) - if err != nil { - return "", "", "", fmt.Errorf("getting working dir for %s: %w", sessionName, err) - } - - return agentID, pane, hookRoot, nil -} - -// sessionToAgentID converts a session name to agent ID format. -// Uses session.ParseSessionName for consistent parsing across the codebase. -func sessionToAgentID(sessionName string) string { - identity, err := session.ParseSessionName(sessionName) - if err != nil { - // Fallback for unparseable sessions - return sessionName - } - return identity.Address() -} - -// verifyBeadExists checks that the bead exists using bd show. -// Uses bd's native prefix-based routing via routes.jsonl - do NOT set BEADS_DIR -// as that overrides routing and breaks resolution of rig-level beads. -// -// Uses --no-daemon with --allow-stale to avoid daemon socket timing issues -// while still finding beads when database is out of sync with JSONL. -// For existence checks, stale data is acceptable - we just need to know it exists. -func verifyBeadExists(beadID string) error { - cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") - // Run from town root so bd can find routes.jsonl for prefix-based routing. - // Do NOT set BEADS_DIR - that overrides routing and breaks rig bead resolution. - if townRoot, err := workspace.FindFromCwd(); err == nil { - cmd.Dir = townRoot - } - if err := cmd.Run(); err != nil { - return fmt.Errorf("bead '%s' not found (bd show failed)", beadID) - } - return nil -} - -// beadInfo holds status and assignee for a bead. -type beadInfo struct { - Title string `json:"title"` - Status string `json:"status"` - Assignee string `json:"assignee"` -} - -// getBeadInfo returns status and assignee for a bead. -// Uses bd's native prefix-based routing via routes.jsonl. -// Uses --no-daemon with --allow-stale for consistency with verifyBeadExists. -func getBeadInfo(beadID string) (*beadInfo, error) { - cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json", "--allow-stale") - // Run from town root so bd can find routes.jsonl for prefix-based routing. - if townRoot, err := workspace.FindFromCwd(); err == nil { - cmd.Dir = townRoot - } - out, err := cmd.Output() - if err != nil { - return nil, fmt.Errorf("bead '%s' not found", beadID) - } - // bd show --json returns an array (issue + dependents), take first element - var infos []beadInfo - if err := json.Unmarshal(out, &infos); err != nil { - return nil, fmt.Errorf("parsing bead info: %w", err) - } - if len(infos) == 0 { - return nil, fmt.Errorf("bead '%s' not found", beadID) - } - return &infos[0], nil -} - -// detectCloneRoot finds the root of the current git clone. -func detectCloneRoot() (string, error) { - cmd := exec.Command("git", "rev-parse", "--show-toplevel") - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("not in a git repository") - } - return strings.TrimSpace(string(out)), nil -} - -// resolveSelfTarget determines agent identity, pane, and hook root for slinging to self. -func resolveSelfTarget() (agentID string, pane string, hookRoot string, err error) { - roleInfo, err := GetRole() - if err != nil { - return "", "", "", fmt.Errorf("detecting role: %w", err) - } - - // Build agent identity from role - // Town-level agents use trailing slash to match addressToIdentity() normalization - switch roleInfo.Role { - case RoleMayor: - agentID = "mayor/" - case RoleDeacon: - agentID = "deacon/" - case RoleWitness: - agentID = fmt.Sprintf("%s/witness", roleInfo.Rig) - case RoleRefinery: - agentID = fmt.Sprintf("%s/refinery", roleInfo.Rig) - case RolePolecat: - agentID = fmt.Sprintf("%s/polecats/%s", roleInfo.Rig, roleInfo.Polecat) - case RoleCrew: - agentID = fmt.Sprintf("%s/crew/%s", roleInfo.Rig, roleInfo.Polecat) - default: - return "", "", "", fmt.Errorf("cannot determine agent identity (role: %s)", roleInfo.Role) - } - - pane = os.Getenv("TMUX_PANE") - hookRoot = roleInfo.Home - if hookRoot == "" { - // Fallback to git root if home not determined - hookRoot, err = detectCloneRoot() - if err != nil { - return "", "", "", fmt.Errorf("detecting clone root: %w", err) - } - } - - return agentID, pane, hookRoot, nil -} - -// verifyFormulaExists checks that the formula exists using bd formula show. -// Formulas are TOML files (.formula.toml). -// Uses --no-daemon with --allow-stale for consistency with verifyBeadExists. -func verifyFormulaExists(formulaName string) error { - // Try bd formula show (handles all formula file formats) - cmd := exec.Command("bd", "--no-daemon", "formula", "show", formulaName, "--allow-stale") - if err := cmd.Run(); err == nil { - return nil - } - - // Try with mol- prefix - cmd = exec.Command("bd", "--no-daemon", "formula", "show", "mol-"+formulaName, "--allow-stale") - if err := cmd.Run(); err == nil { - return nil - } - - return fmt.Errorf("formula '%s' not found (check 'bd formula list')", formulaName) -} - -// runSlingFormula handles standalone formula slinging. -// Flow: cook → wisp → attach to hook → nudge -func runSlingFormula(args []string) error { - formulaName := args[0] - - // Get town root early - needed for BEADS_DIR when running bd commands - townRoot, err := workspace.FindFromCwd() - if err != nil { - return fmt.Errorf("finding town root: %w", err) - } - townBeadsDir := filepath.Join(townRoot, ".beads") - - // Determine target (self or specified) - var target string - if len(args) > 1 { - target = args[1] - } - - // Resolve target agent and pane - var targetAgent string - var targetPane string - - if target != "" { - // Resolve "." to current agent identity (like git's "." meaning current directory) - if target == "." { - targetAgent, targetPane, _, err = resolveSelfTarget() - if err != nil { - return fmt.Errorf("resolving self for '.' target: %w", err) - } - } else if dogName, isDog := IsDogTarget(target); isDog { - if slingDryRun { - if dogName == "" { - fmt.Printf("Would dispatch to idle dog in kennel\n") - } else { - fmt.Printf("Would dispatch to dog '%s'\n", dogName) - } - targetAgent = fmt.Sprintf("deacon/dogs/%s", dogName) - if dogName == "" { - targetAgent = "deacon/dogs/" - } - targetPane = "" - } else { - // Dispatch to dog - dispatchInfo, dispatchErr := DispatchToDog(dogName, slingCreate) - if dispatchErr != nil { - return fmt.Errorf("dispatching to dog: %w", dispatchErr) - } - targetAgent = dispatchInfo.AgentID - targetPane = dispatchInfo.Pane - fmt.Printf("Dispatched to dog %s\n", dispatchInfo.DogName) - } - } else if rigName, isRig := IsRigName(target); isRig { - // Check if target is a rig name (auto-spawn polecat) - if slingDryRun { - // Dry run - just indicate what would happen - fmt.Printf("Would spawn fresh polecat in rig '%s'\n", rigName) - if slingNaked { - fmt.Printf(" --naked: would skip tmux session\n") - } - targetAgent = fmt.Sprintf("%s/polecats/", rigName) - targetPane = "" - } else { - // Spawn a fresh polecat in the rig - fmt.Printf("Target is rig '%s', spawning fresh polecat...\n", rigName) - spawnOpts := SlingSpawnOptions{ - Force: slingForce, - Naked: slingNaked, - Account: slingAccount, - Create: slingCreate, - Agent: slingAgent, - } - spawnInfo, spawnErr := SpawnPolecatForSling(rigName, spawnOpts) - if spawnErr != nil { - return fmt.Errorf("spawning polecat: %w", spawnErr) - } - targetAgent = spawnInfo.AgentID() - targetPane = spawnInfo.Pane - - // Wake witness and refinery to monitor the new polecat - wakeRigAgents(rigName) - } - } else { - // Slinging to an existing agent - // Skip pane lookup if --naked (agent may be terminated) - var targetWorkDir string - targetAgent, targetPane, targetWorkDir, err = resolveTargetAgent(target, slingNaked) - if err != nil { - return fmt.Errorf("resolving target: %w", err) - } - // Use target's working directory for bd commands (needed for redirect-based routing) - _ = targetWorkDir // Formula sling doesn't need hookWorkDir - } - } else { - // Slinging to self - var selfWorkDir string - targetAgent, targetPane, selfWorkDir, err = resolveSelfTarget() - if err != nil { - return err - } - _ = selfWorkDir // Formula sling doesn't need hookWorkDir - } - - fmt.Printf("%s Slinging formula %s to %s...\n", style.Bold.Render("🎯"), formulaName, targetAgent) - - if slingDryRun { - fmt.Printf("Would cook formula: %s\n", formulaName) - fmt.Printf("Would create wisp and pin to: %s\n", targetAgent) - for _, v := range slingVars { - fmt.Printf(" --var %s\n", v) - } - fmt.Printf("Would nudge pane: %s\n", targetPane) - return nil - } - - // Step 1: Cook the formula (ensures proto exists) - fmt.Printf(" Cooking formula...\n") - cookArgs := []string{"--no-daemon", "cook", formulaName} - cookCmd := exec.Command("bd", cookArgs...) - cookCmd.Stderr = os.Stderr - if err := cookCmd.Run(); err != nil { - return fmt.Errorf("cooking formula: %w", err) - } - - // Step 2: Create wisp instance (ephemeral) - fmt.Printf(" Creating wisp...\n") - wispArgs := []string{"--no-daemon", "mol", "wisp", formulaName} - for _, v := range slingVars { - wispArgs = append(wispArgs, "--var", v) - } - wispArgs = append(wispArgs, "--json") - - wispCmd := exec.Command("bd", wispArgs...) - wispCmd.Stderr = os.Stderr // Show wisp errors to user - wispOut, err := wispCmd.Output() - if err != nil { - return fmt.Errorf("creating wisp: %w", err) - } - - // Parse wisp output to get the root ID - wispRootID, err := parseWispIDFromJSON(wispOut) - if err != nil { - return fmt.Errorf("parsing wisp output: %w", err) - } - - fmt.Printf("%s Wisp created: %s\n", style.Bold.Render("✓"), wispRootID) - - // Step 3: Hook the wisp bead using bd update. - // See: https://github.com/steveyegge/gastown/issues/148 - hookCmd := exec.Command("bd", "--no-daemon", "update", wispRootID, "--status=hooked", "--assignee="+targetAgent) - hookCmd.Dir = beads.ResolveHookDir(townRoot, wispRootID, "") - hookCmd.Stderr = os.Stderr - if err := hookCmd.Run(); err != nil { - return fmt.Errorf("hooking wisp bead: %w", err) - } - fmt.Printf("%s Attached to hook (status=hooked)\n", style.Bold.Render("✓")) - - // Log sling event to activity feed (formula slinging) - actor := detectActor() - payload := events.SlingPayload(wispRootID, targetAgent) - payload["formula"] = formulaName - _ = events.LogFeed(events.TypeSling, actor, payload) - - // Update agent bead's hook_bead field (ZFC: agents track their current work) - // Note: formula slinging uses town root as workDir (no polecat-specific path) - updateAgentHookBead(targetAgent, wispRootID, "", townBeadsDir) - - // Store dispatcher in bead description (enables completion notification to dispatcher) - if err := storeDispatcherInBead(wispRootID, actor); err != nil { - // Warn but don't fail - polecat will still complete work - fmt.Printf("%s Could not store dispatcher in bead: %v\n", style.Dim.Render("Warning:"), err) - } - - // Store args in wisp bead if provided (no-tmux mode: beads as data plane) - if slingArgs != "" { - if err := storeArgsInBead(wispRootID, slingArgs); err != nil { - fmt.Printf("%s Could not store args in bead: %v\n", style.Dim.Render("Warning:"), err) - } else { - fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓")) - } - } - - // Step 4: Nudge to start (graceful if no tmux) - if targetPane == "" { - fmt.Printf("%s No pane to nudge (agent will discover work via gt prime)\n", style.Dim.Render("○")) - return nil - } - - var prompt string - if slingArgs != "" { - prompt = fmt.Sprintf("Formula %s slung. Args: %s. Run `gt hook` to see your hook, then execute using these args.", formulaName, slingArgs) - } else { - prompt = fmt.Sprintf("Formula %s slung. Run `gt hook` to see your hook, then execute the steps.", formulaName) - } - t := tmux.NewTmux() - if err := t.NudgePane(targetPane, prompt); err != nil { - // Graceful fallback for no-tmux mode - fmt.Printf("%s Could not nudge (no tmux?): %v\n", style.Dim.Render("○"), err) - fmt.Printf(" Agent will discover work via gt prime / bd show\n") - } else { - fmt.Printf("%s Nudged to start\n", style.Bold.Render("▶")) - } - - return nil -} - -// updateAgentHookBead updates the agent bead's state and hook when work is slung. -// This enables the witness to see that each agent is working. -// -// We run from the polecat's workDir (which redirects to the rig's beads database) -// WITHOUT setting BEADS_DIR, so the redirect mechanism works for gt-* agent beads. -// -// For rig-level beads (same database), we set the hook_bead slot directly. -// For cross-database scenarios (agent in rig db, hook bead in town db), -// the slot set may fail - this is handled gracefully with a warning. -// The work is still correctly attached via `bd update --assignee=`. -func updateAgentHookBead(agentID, beadID, workDir, townBeadsDir string) { - _ = townBeadsDir // Not used - BEADS_DIR breaks redirect mechanism - - // Determine the directory to run bd commands from: - // - If workDir is provided (polecat's clone path), use it for redirect-based routing - // - Otherwise fall back to town root - bdWorkDir := workDir - townRoot, err := workspace.FindFromCwd() - if err != nil { - // Not in a Gas Town workspace - can't update agent bead - fmt.Fprintf(os.Stderr, "Warning: couldn't find town root to update agent hook: %v\n", err) - return - } - if bdWorkDir == "" { - bdWorkDir = townRoot - } - - // Convert agent ID to agent bead ID - // Format examples (canonical: prefix-rig-role-name): - // greenplace/crew/max -> gt-greenplace-crew-max - // greenplace/polecats/Toast -> gt-greenplace-polecat-Toast - // mayor -> hq-mayor - // greenplace/witness -> gt-greenplace-witness - agentBeadID := agentIDToBeadID(agentID, townRoot) - if agentBeadID == "" { - return - } - - // Run from workDir WITHOUT BEADS_DIR to enable redirect-based routing. - // Set hook_bead to the slung work (gt-zecmc: removed agent_state update). - // Agent liveness is observable from tmux - no need to record it in bead. - // For cross-database scenarios, slot set may fail gracefully (warning only). - bd := beads.New(bdWorkDir) - if err := bd.SetHookBead(agentBeadID, beadID); err != nil { - // Log warning instead of silent ignore - helps debug cross-beads issues - fmt.Fprintf(os.Stderr, "Warning: couldn't set agent %s hook: %v\n", agentBeadID, err) - return - } -} - -// wakeRigAgents wakes the witness and refinery for a rig after polecat dispatch. -// This ensures the patrol agents are ready to monitor and merge. -func wakeRigAgents(rigName string) { - // Boot the rig (idempotent - no-op if already running) - bootCmd := exec.Command("gt", "rig", "boot", rigName) - _ = bootCmd.Run() // Ignore errors - rig might already be running - - // Nudge witness and refinery to clear any backoff - t := tmux.NewTmux() - witnessSession := fmt.Sprintf("gt-%s-witness", rigName) - refinerySession := fmt.Sprintf("gt-%s-refinery", rigName) - - // Silent nudges - sessions might not exist yet - _ = t.NudgeSession(witnessSession, "Polecat dispatched - check for work") - _ = t.NudgeSession(refinerySession, "Polecat dispatched - check for merge requests") -} - -// detectActor returns the current agent's actor string for event logging. -func detectActor() string { - roleInfo, err := GetRole() - if err != nil { - return "unknown" - } - return roleInfo.ActorString() -} - -// agentIDToBeadID converts an agent ID to its corresponding agent bead ID. -// Uses canonical naming: prefix-rig-role-name -// Town-level agents (Mayor, Deacon) use hq- prefix and are stored in town beads. -// Rig-level agents use the rig's configured prefix (default "gt-"). -// townRoot is needed to look up the rig's configured prefix. -func agentIDToBeadID(agentID, townRoot string) string { - // Handle simple cases (town-level agents with hq- prefix) - if agentID == "mayor" { - return beads.MayorBeadIDTown() - } - if agentID == "deacon" { - return beads.DeaconBeadIDTown() - } - - // Parse path-style agent IDs - parts := strings.Split(agentID, "/") - if len(parts) < 2 { - return "" - } - rig := parts[0] - prefix := config.GetRigPrefix(townRoot, rig) - - switch { - case len(parts) == 2 && parts[1] == "witness": - return beads.WitnessBeadIDWithPrefix(prefix, rig) - case len(parts) == 2 && parts[1] == "refinery": - return beads.RefineryBeadIDWithPrefix(prefix, rig) - case len(parts) == 3 && parts[1] == "crew": - return beads.CrewBeadIDWithPrefix(prefix, rig, parts[2]) - case len(parts) == 3 && parts[1] == "polecats": - return beads.PolecatBeadIDWithPrefix(prefix, rig, parts[2]) - default: - return "" - } -} - -// IsDogTarget checks if target is a dog target pattern. -// Returns the dog name (or empty for pool dispatch) and true if it's a dog target. -// Patterns: -// - "deacon/dogs" -> ("", true) - dispatch to any idle dog -// - "deacon/dogs/alpha" -> ("alpha", true) - dispatch to specific dog -func IsDogTarget(target string) (dogName string, isDog bool) { - target = strings.ToLower(target) - - // Check for exact "deacon/dogs" (pool dispatch) - if target == "deacon/dogs" { - return "", true - } - - // Check for "deacon/dogs/" (specific dog) - if strings.HasPrefix(target, "deacon/dogs/") { - name := strings.TrimPrefix(target, "deacon/dogs/") - if name != "" && !strings.Contains(name, "/") { - return name, true - } - } - - return "", false -} - -// DogDispatchInfo contains information about a dog dispatch. -type DogDispatchInfo struct { - DogName string // Name of the dog - AgentID string // Agent ID format (deacon/dogs/) - Pane string // Tmux pane (empty if no session) - Spawned bool // True if dog was spawned (new) -} - -// DispatchToDog finds or spawns a dog for work dispatch. -// If dogName is empty, finds an idle dog from the pool. -// If create is true and no dogs exist, creates one. -func DispatchToDog(dogName string, create bool) (*DogDispatchInfo, error) { - townRoot, err := workspace.FindFromCwd() - if err != nil { - return nil, fmt.Errorf("finding town root: %w", err) - } - - rigsConfigPath := filepath.Join(townRoot, "mayor", "rigs.json") - rigsConfig, err := config.LoadRigsConfig(rigsConfigPath) - if err != nil { - return nil, fmt.Errorf("loading rigs config: %w", err) - } - - mgr := dog.NewManager(townRoot, rigsConfig) - - var targetDog *dog.Dog - var spawned bool - - if dogName != "" { - // Specific dog requested - targetDog, err = mgr.Get(dogName) - if err != nil { - if create { - // Create the dog if it doesn't exist - targetDog, err = mgr.Add(dogName) - if err != nil { - return nil, fmt.Errorf("creating dog %s: %w", dogName, err) - } - fmt.Printf("✓ Created dog %s\n", dogName) - spawned = true - } else { - return nil, fmt.Errorf("dog %s not found (use --create to add)", dogName) - } - } - } else { - // Pool dispatch - find an idle dog - targetDog, err = mgr.GetIdleDog() - if err != nil { - return nil, fmt.Errorf("finding idle dog: %w", err) - } - - if targetDog == nil { - if create { - // No idle dogs - create one - newName := generateDogName(mgr) - targetDog, err = mgr.Add(newName) - if err != nil { - return nil, fmt.Errorf("creating dog %s: %w", newName, err) - } - fmt.Printf("✓ Created dog %s (pool was empty)\n", newName) - spawned = true - } else { - return nil, fmt.Errorf("no idle dogs available (use --create to add)") - } - } - } - - // Mark dog as working - if err := mgr.SetState(targetDog.Name, dog.StateWorking); err != nil { - return nil, fmt.Errorf("setting dog state: %w", err) - } - - // Build agent ID - agentID := fmt.Sprintf("deacon/dogs/%s", targetDog.Name) - - // Try to find tmux session for the dog (dogs may run in tmux like polecats) - // Dogs use the pattern gt-{town}-deacon-{name} - townName, _ := workspace.GetTownName(townRoot) - sessionName := fmt.Sprintf("gt-%s-deacon-%s", townName, targetDog.Name) - t := tmux.NewTmux() - var pane string - if has, _ := t.HasSession(sessionName); has { - // Get the pane from the session - pane, _ = getSessionPane(sessionName) - } - - return &DogDispatchInfo{ - DogName: targetDog.Name, - AgentID: agentID, - Pane: pane, - Spawned: spawned, - }, nil -} - -// generateDogName creates a unique dog name for pool expansion. -func generateDogName(mgr *dog.Manager) string { - // Use Greek alphabet for dog names - names := []string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"} - - dogs, _ := mgr.List() - existing := make(map[string]bool) - for _, d := range dogs { - existing[d.Name] = true - } - - for _, name := range names { - if !existing[name] { - return name - } - } - - // Fallback: numbered dogs - for i := 1; i <= 100; i++ { - name := fmt.Sprintf("dog%d", i) - if !existing[name] { - return name - } - } - - return fmt.Sprintf("dog%d", len(dogs)+1) -} - -// slingGenerateShortID generates a short random ID (5 lowercase chars). -func slingGenerateShortID() string { - b := make([]byte, 3) - _, _ = rand.Read(b) - return strings.ToLower(base32.StdEncoding.EncodeToString(b)[:5]) -} - -// isTrackedByConvoy checks if an issue is already being tracked by a convoy. -// Returns the convoy ID if tracked, empty string otherwise. -func isTrackedByConvoy(beadID string) string { - townRoot, err := workspace.FindFromCwd() - if err != nil { - return "" - } - - // Query town beads for any convoy that tracks this issue - // Convoys use "tracks" dependency type: convoy -> tracked issue - townBeads := filepath.Join(townRoot, ".beads") - dbPath := filepath.Join(townBeads, "beads.db") - - // Query dependencies where this bead is being tracked - // Also check for external reference format: external:rig:issue-id - query := fmt.Sprintf(` - SELECT d.issue_id - FROM dependencies d - JOIN issues i ON d.issue_id = i.id - WHERE d.type = 'tracks' - AND i.issue_type = 'convoy' - AND (d.depends_on_id = '%s' OR d.depends_on_id LIKE '%%:%s') - LIMIT 1 - `, beadID, beadID) - - queryCmd := exec.Command("sqlite3", dbPath, query) - out, err := queryCmd.Output() - if err != nil { - return "" - } - - convoyID := strings.TrimSpace(string(out)) - return convoyID -} - -// createAutoConvoy creates an auto-convoy for a single issue and tracks it. -// Returns the created convoy ID. -func createAutoConvoy(beadID, beadTitle string) (string, error) { - townRoot, err := workspace.FindFromCwd() - if err != nil { - return "", fmt.Errorf("finding town root: %w", err) - } - - townBeads := filepath.Join(townRoot, ".beads") - - // Generate convoy ID with hq- prefix - // Convoys are distinguished by type=convoy, not by a special ID prefix - convoyID := fmt.Sprintf("hq-%s", slingGenerateShortID()) - - // Create convoy with title "Work: " - convoyTitle := fmt.Sprintf("Work: %s", beadTitle) - description := fmt.Sprintf("Auto-created convoy tracking %s", beadID) - - createArgs := []string{ - "create", - "--type=convoy", - "--id=" + convoyID, - "--title=" + convoyTitle, - "--description=" + description, - } - - createCmd := exec.Command("bd", append([]string{"--no-daemon"}, createArgs...)...) - createCmd.Dir = townBeads - createCmd.Stderr = os.Stderr - - if err := createCmd.Run(); err != nil { - return "", fmt.Errorf("creating convoy: %w", err) - } - - // Add tracking relation: convoy tracks the issue - trackBeadID := formatTrackBeadID(beadID) - depArgs := []string{"--no-daemon", "dep", "add", convoyID, trackBeadID, "--type=tracks"} - depCmd := exec.Command("bd", depArgs...) - depCmd.Dir = townBeads - depCmd.Stderr = os.Stderr - - if err := depCmd.Run(); err != nil { - // Convoy was created but tracking failed - log warning but continue - fmt.Printf("%s Could not add tracking relation: %v\n", style.Dim.Render("Warning:"), err) - } - - return convoyID, nil -} - -// runBatchSling handles slinging multiple beads to a rig. -// Each bead gets its own freshly spawned polecat. -func runBatchSling(beadIDs []string, rigName string, townBeadsDir string) error { - // Validate all beads exist before spawning any polecats - for _, beadID := range beadIDs { - if err := verifyBeadExists(beadID); err != nil { - return fmt.Errorf("bead '%s' not found", beadID) - } - } - - if slingDryRun { - fmt.Printf("%s Batch slinging %d beads to rig '%s':\n", style.Bold.Render("🎯"), len(beadIDs), rigName) - for _, beadID := range beadIDs { - fmt.Printf(" Would spawn polecat for: %s\n", beadID) - } - if slingNaked { - fmt.Printf(" --naked: would skip tmux sessions\n") - } - return nil - } - - fmt.Printf("%s Batch slinging %d beads to rig '%s'...\n", style.Bold.Render("🎯"), len(beadIDs), rigName) - - // Track results for summary - type slingResult struct { - beadID string - polecat string - success bool - errMsg string - } - results := make([]slingResult, 0, len(beadIDs)) - - // Spawn a polecat for each bead and sling it - for i, beadID := range beadIDs { - fmt.Printf("\n[%d/%d] Slinging %s...\n", i+1, len(beadIDs), beadID) - - // Check bead status - info, err := getBeadInfo(beadID) - if err != nil { - results = append(results, slingResult{beadID: beadID, success: false, errMsg: err.Error()}) - fmt.Printf(" %s Could not get bead info: %v\n", style.Dim.Render("✗"), err) - continue - } - - if info.Status == "pinned" && !slingForce { - results = append(results, slingResult{beadID: beadID, success: false, errMsg: "already pinned"}) - fmt.Printf(" %s Already pinned (use --force to re-sling)\n", style.Dim.Render("✗")) - continue - } - - // Spawn a fresh polecat - spawnOpts := SlingSpawnOptions{ - Force: slingForce, - Naked: slingNaked, - Account: slingAccount, - Create: slingCreate, - HookBead: beadID, // Set atomically at spawn time - Agent: slingAgent, - } - spawnInfo, err := SpawnPolecatForSling(rigName, spawnOpts) - if err != nil { - results = append(results, slingResult{beadID: beadID, success: false, errMsg: err.Error()}) - fmt.Printf(" %s Failed to spawn polecat: %v\n", style.Dim.Render("✗"), err) - continue - } - - targetAgent := spawnInfo.AgentID() - hookWorkDir := spawnInfo.ClonePath - - // Auto-convoy: check if issue is already tracked - if !slingNoConvoy { - existingConvoy := isTrackedByConvoy(beadID) - if existingConvoy == "" { - convoyID, err := createAutoConvoy(beadID, info.Title) - if err != nil { - fmt.Printf(" %s Could not create auto-convoy: %v\n", style.Dim.Render("Warning:"), err) - } else { - fmt.Printf(" %s Created convoy 🚚 %s\n", style.Bold.Render("→"), convoyID) - } - } else { - fmt.Printf(" %s Already tracked by convoy %s\n", style.Dim.Render("○"), existingConvoy) - } - } - - // Hook the bead. See: https://github.com/steveyegge/gastown/issues/148 - townRoot := filepath.Dir(townBeadsDir) - hookCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--status=hooked", "--assignee="+targetAgent) - hookCmd.Dir = beads.ResolveHookDir(townRoot, beadID, hookWorkDir) - hookCmd.Stderr = os.Stderr - if err := hookCmd.Run(); err != nil { - results = append(results, slingResult{beadID: beadID, polecat: spawnInfo.PolecatName, success: false, errMsg: "hook failed"}) - fmt.Printf(" %s Failed to hook bead: %v\n", style.Dim.Render("✗"), err) - continue - } - - fmt.Printf(" %s Work attached to %s\n", style.Bold.Render("✓"), spawnInfo.PolecatName) - - // Log sling event - actor := detectActor() - _ = events.LogFeed(events.TypeSling, actor, events.SlingPayload(beadID, targetAgent)) - - // Update agent bead state - updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir) - - // Auto-attach mol-polecat-work molecule to polecat agent bead - if err := attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot); err != nil { - fmt.Printf(" %s Could not attach work molecule: %v\n", style.Dim.Render("Warning:"), err) - } - - // Store args if provided - if slingArgs != "" { - if err := storeArgsInBead(beadID, slingArgs); err != nil { - fmt.Printf(" %s Could not store args: %v\n", style.Dim.Render("Warning:"), err) - } - } - - // Nudge the polecat - if spawnInfo.Pane != "" { - if err := injectStartPrompt(spawnInfo.Pane, beadID, slingSubject, slingArgs); err != nil { - fmt.Printf(" %s Could not nudge (agent will discover via gt prime)\n", style.Dim.Render("○")) - } else { - fmt.Printf(" %s Start prompt sent\n", style.Bold.Render("▶")) - } - } - - results = append(results, slingResult{beadID: beadID, polecat: spawnInfo.PolecatName, success: true}) - } - - // Wake witness and refinery once at the end - wakeRigAgents(rigName) - - // Print summary - successCount := 0 - for _, r := range results { - if r.success { - successCount++ - } - } - - fmt.Printf("\n%s Batch sling complete: %d/%d succeeded\n", style.Bold.Render("📊"), successCount, len(beadIDs)) - if successCount < len(beadIDs) { - for _, r := range results { - if !r.success { - fmt.Printf(" %s %s: %s\n", style.Dim.Render("✗"), r.beadID, r.errMsg) - } - } - } - - return nil -} - -// formatTrackBeadID formats a bead ID for use in convoy tracking dependencies. -// Cross-rig beads (non-hq- prefixed) are formatted as external references -// so the bd tool can resolve them when running from HQ context. -// -// Examples: -// - "hq-abc123" -> "hq-abc123" (HQ beads unchanged) -// - "gt-mol-xyz" -> "external:gt-mol:gt-mol-xyz" -// - "beads-task-123" -> "external:beads-task:beads-task-123" -func formatTrackBeadID(beadID string) string { - if strings.HasPrefix(beadID, "hq-") { - return beadID - } - parts := strings.SplitN(beadID, "-", 3) - if len(parts) >= 2 { - rigPrefix := parts[0] + "-" + parts[1] - return fmt.Sprintf("external:%s:%s", rigPrefix, beadID) - } - // Fallback for malformed IDs (single segment) - return beadID -} // isPolecatTarget checks if the target string refers to a polecat. // Returns true if the target format is "rig/polecats/name". diff --git a/internal/cmd/sling_helpers.go b/internal/cmd/sling_helpers.go index 1afd6840e..78b670b02 100644 --- a/internal/cmd/sling_helpers.go +++ b/internal/cmd/sling_helpers.go @@ -228,7 +228,7 @@ func ensureAgentReady(sessionName string) error { t := tmux.NewTmux() // If an agent is already running, assume it's ready (session was started earlier) - if t.IsAgentRunning(sessionName) { + if running, _ := t.IsAgentRunning(sessionName); running { return nil } diff --git a/internal/cmd/start.go b/internal/cmd/start.go index 08f5a7316..4e887265e 100644 --- a/internal/cmd/start.go +++ b/internal/cmd/start.go @@ -354,29 +354,33 @@ func startConfiguredCrew(t *tmux.Tmux, rigs []*rig.Rig, townRoot string, mu *syn for _, r := range rigs { crewToStart := getCrewToStart(r) for _, crewName := range crewToStart { - sessionID := crewSessionName(r.Name, crewName) - if sessionExists, _ := t.HasSession(sessionID); sessionExists { - // Session exists - check if Claude is still running - agentCfg := config.ResolveAgentConfig(townRoot, r.Path) - if running, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); !running { - // Claude has exited, restart it - fmt.Printf(" %s %s/%s session exists, restarting Claude...\n", style.Dim.Render("○"), r.Name, crewName) - // Build startup beacon for predecessor discovery via /resume - address := fmt.Sprintf("%s/crew/%s", r.Name, crewName) - beacon := session.FormatStartupNudge(session.StartupNudgeConfig{ - Recipient: address, - Sender: "human", - Topic: "restart", - }) - claudeCmd := config.BuildCrewStartupCommand(r.Name, crewName, r.Path, beacon) - if err := t.SendKeys(sessionID, claudeCmd); err != nil { - fmt.Printf(" %s %s/%s restart failed: %v\n", style.Dim.Render("○"), r.Name, crewName, err) + wg.Add(1) + go func(r *rig.Rig, crewName string) { + defer wg.Done() + sessionID := crewSessionName(r.Name, crewName) + if sessionExists, _ := t.HasSession(sessionID); sessionExists { + // Session exists - check if Claude is still running + agentCfg := config.ResolveAgentConfig(townRoot, r.Path) + if running, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); !running { + // Claude has exited, restart it + fmt.Printf(" %s %s/%s session exists, restarting Claude...\n", style.Dim.Render("○"), r.Name, crewName) + // Build startup beacon for predecessor discovery via /resume + address := fmt.Sprintf("%s/crew/%s", r.Name, crewName) + beacon := session.FormatStartupNudge(session.StartupNudgeConfig{ + Recipient: address, + Sender: "human", + Topic: "restart", + }) + claudeCmd := config.BuildCrewStartupCommand(r.Name, crewName, r.Path, beacon) + if err := t.SendKeys(sessionID, claudeCmd); err != nil { + fmt.Printf(" %s %s/%s restart failed: %v\n", style.Dim.Render("○"), r.Name, crewName, err) + } else { + fmt.Printf(" %s %s/%s Claude restarted\n", style.Bold.Render("✓"), r.Name, crewName) + atomic.AddInt32(&startedAny, 1) + } } else { - fmt.Printf(" %s %s/%s Claude restarted\n", style.Bold.Render("✓"), r.Name, crewName) - startedAny = true + fmt.Printf(" %s %s/%s already running\n", style.Dim.Render("○"), r.Name, crewName) } - } else { - fmt.Printf(" %s %s/%s already running\n", style.Dim.Render("○"), r.Name, crewName) } }(r, crewName) } @@ -397,7 +401,7 @@ func startOrRestartCrewMember(t *tmux.Tmux, r *rig.Rig, crewName, townRoot strin if running, _ := t.HasSession(sessionID); running { // Session exists - check if Claude is still running agentCfg := config.ResolveAgentConfig(townRoot, r.Path) - if !t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...) { + if running, _ := t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...); !running { // Claude has exited, restart it // Build startup beacon for predecessor discovery via /resume address := fmt.Sprintf("%s/crew/%s", r.Name, crewName) diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go index 056aaccf2..9084a40e2 100644 --- a/internal/cmd/statusline.go +++ b/internal/cmd/statusline.go @@ -218,19 +218,7 @@ func runMayorStatusLine(t *tmux.Tmux) error { rigStatuses[rigName] = &rigStatus{} } - // Track per-agent-type health (working/zombie counts) - type agentHealth struct { - total int - working int - } - healthByType := map[AgentType]*agentHealth{ - AgentPolecat: {}, - AgentWitness: {}, - AgentRefinery: {}, - AgentDeacon: {}, - } - - // Single pass: track rig status AND agent health + // Track rig status in a single pass for _, s := range sessions { agent := categorizeSession(s) if agent == nil { @@ -251,15 +239,6 @@ func runMayorStatusLine(t *tmux.Tmux) error { rigStatuses[agent.Rig].polecatCount++ } } - - // Track agent health (skip Mayor and Crew) - if health := healthByType[agent.Type]; health != nil { - health.total++ - // Detect working state via ✻ symbol - if isSessionWorking(t, s) { - health.working++ - } - } } // Get operational state for each rig @@ -354,30 +333,6 @@ func runMayorStatusLine(t *tmux.Tmux) error { // 🟡 = one of witness/refinery running (partially active) // ⚫ = neither running (inactive) // ⏸️ = parked or docked (intentionally offline) - var rigParts []string - var rigNames []string - for rigName := range rigStatuses { - rigNames = append(rigNames, rigName) - } - - // Sort rigs: active rigs first (alphabetically), then parked/stopped rigs (alphabetically) - sort.Slice(rigNames, func(i, j int) bool { - // Get operational state for each rig - opStateI, _ := getRigOperationalState(townRoot, rigNames[i]) - opStateJ, _ := getRigOperationalState(townRoot, rigNames[j]) - - // Determine if each rig is parked/stopped - iParked := opStateI == "PARKED" || opStateI == "DOCKED" - jParked := opStateJ == "PARKED" || opStateJ == "DOCKED" - - // If both are same state (both parked or both active), sort alphabetically - if iParked == jParked { - return rigNames[i] < rigNames[j] - } - - // Parked rigs go to the right (i.e., sort after active rigs) - return !iParked && jParked - }) // Create sortable rig list type rigInfo struct { @@ -453,7 +408,7 @@ func runMayorStatusLine(t *tmux.Tmux) error { led = "⚫" // Operational but nothing running } } - rigParts = append(rigParts, led+abbreviateRigName(rigName)) + rigParts = append(rigParts, led+abbreviateRigName(rig.name)) } if len(rigParts) > 0 { From 11610f1069bc1a625b8fb6397059dd4ea1d4577c Mon Sep 17 00:00:00 2001 From: furiosa Date: Sun, 11 Jan 2026 22:19:40 +0100 Subject: [PATCH 40/41] perf(tmux): eliminate duplicate GetPaneCommand call in IsClaudeRunning IsClaudeRunning was calling IsAgentRunning (which calls GetPaneCommand), then immediately calling GetPaneCommand again. This duplicate subprocess call was slowing down gt startup and daemon heartbeat operations. Changed IsAgentRunning to return (bool, string) - the running status and the pane command it checked. IsClaudeRunning now reuses the command instead of making a redundant tmux subprocess call. Fixes gt-kpii: zombie session detection slows gt up --- internal/cmd/sling.go | 207 +++++++++++++++++++++++++++++++++++++++++- internal/cmd/start.go | 4 - 2 files changed, 203 insertions(+), 8 deletions(-) diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 2b4fa31d5..f2be97a07 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -521,10 +521,209 @@ func isPolecatTarget(target string) bool { return len(parts) >= 3 && parts[1] == "polecats" } -// attachPolecatWorkMolecule attaches the mol-polecat-work molecule to a polecat's agent bead. -// This ensures all polecats have the standard work molecule attached for guidance. -// The molecule is attached by storing it in the agent bead's description using attachment fields. -// +// storeDispatcherInBead stores the dispatcher agent ID in the bead's description. +// This enables polecats to notify the dispatcher when work is complete. +func storeDispatcherInBead(beadID, dispatcher string) error { + if dispatcher == "" { + return nil + } + + // Get the bead to preserve existing description content + showCmd := exec.Command("bd", "show", beadID, "--json") + out, err := showCmd.Output() + if err != nil { + return fmt.Errorf("fetching bead: %w", err) + } + + // Parse the bead + var issues []beads.Issue + if err := json.Unmarshal(out, &issues); err != nil { + return fmt.Errorf("parsing bead: %w", err) + } + if len(issues) == 0 { + return fmt.Errorf("bead not found") + } + issue := &issues[0] + + // Get or create attachment fields + fields := beads.ParseAttachmentFields(issue) + if fields == nil { + fields = &beads.AttachmentFields{} + } + + // Set the dispatcher + fields.DispatchedBy = dispatcher + + // Update the description + newDesc := beads.SetAttachmentFields(issue, fields) + + // Update the bead + updateCmd := exec.Command("bd", "update", beadID, "--description="+newDesc) + updateCmd.Stderr = os.Stderr + if err := updateCmd.Run(); err != nil { + return fmt.Errorf("updating bead description: %w", err) + } + + return nil +} + +// injectStartPrompt sends a prompt to the target pane to start working. +// Uses the reliable nudge pattern: literal mode + 500ms debounce + separate Enter. +func injectStartPrompt(pane, beadID, subject, args string) error { + if pane == "" { + return fmt.Errorf("no target pane") + } + + // Build the prompt to inject + var prompt string + if args != "" { + // Args provided - include them prominently in the prompt + if subject != "" { + prompt = fmt.Sprintf("Work slung: %s (%s). Args: %s. Start working now - use these args to guide your execution.", beadID, subject, args) + } else { + prompt = fmt.Sprintf("Work slung: %s. Args: %s. Start working now - use these args to guide your execution.", beadID, args) + } + } else if subject != "" { + prompt = fmt.Sprintf("Work slung: %s (%s). Start working on it now - no questions, just begin.", beadID, subject) + } else { + prompt = fmt.Sprintf("Work slung: %s. Start working on it now - run `gt hook` to see the hook, then begin.", beadID) + } + + // Use the reliable nudge pattern (same as gt nudge / tmux.NudgeSession) + t := tmux.NewTmux() + return t.NudgePane(pane, prompt) +} + +// getSessionFromPane extracts session name from a pane target. +// Pane targets can be: +// - "%9" (pane ID) - need to query tmux for session +// - "gt-rig-name:0.0" (session:window.pane) - extract session name +func getSessionFromPane(pane string) string { + if strings.HasPrefix(pane, "%") { + // Pane ID format - query tmux for the session + cmd := exec.Command("tmux", "display-message", "-t", pane, "-p", "#{session_name}") + out, err := cmd.Output() + if err != nil { + return "" + } + return strings.TrimSpace(string(out)) + } + // Session:window.pane format - extract session name + if idx := strings.Index(pane, ":"); idx > 0 { + return pane[:idx] + } + return pane +} + +// ensureAgentReady waits for an agent to be ready before nudging an existing session. +// Uses a pragmatic approach: wait for the pane to leave a shell, then (Claude-only) +// accept the bypass permissions warning and give it a moment to finish initializing. +func ensureAgentReady(sessionName string) error { + t := tmux.NewTmux() + + // If an agent is already running, assume it's ready (session was started earlier) + if running, _ := t.IsAgentRunning(sessionName); running { + return nil + } + + // Agent not running yet - wait for it to start (shell → program transition) + if err := t.WaitForCommand(sessionName, constants.SupportedShells, constants.ClaudeStartTimeout); err != nil { + return fmt.Errorf("waiting for agent to start: %w", err) + } + + // Claude-only: accept bypass permissions warning if present + if t.IsClaudeRunning(sessionName) { + _ = t.AcceptBypassPermissionsWarning(sessionName) + + // PRAGMATIC APPROACH: fixed delay rather than prompt detection. + // Claude startup takes ~5-8 seconds on typical machines. + time.Sleep(8 * time.Second) + } else { + time.Sleep(1 * time.Second) + } + + return nil +} + +// resolveTargetAgent converts a target spec to agent ID, pane, and hook root. +// If skipPane is true, skip tmux pane lookup (for --naked mode). +func resolveTargetAgent(target string, skipPane bool) (agentID string, pane string, hookRoot string, err error) { + // First resolve to session name + sessionName, err := resolveRoleToSession(target) + if err != nil { + return "", "", "", err + } + + // Convert session name to agent ID format (this doesn't require tmux) + agentID = sessionToAgentID(sessionName) + + // Skip pane lookup if requested (--naked mode) + if skipPane { + return agentID, "", "", nil + } + + // Get the pane for that session + pane, err = getSessionPane(sessionName) + if err != nil { + return "", "", "", fmt.Errorf("getting pane for %s: %w", sessionName, err) + } + + // Get the target's working directory for hook storage + t := tmux.NewTmux() + hookRoot, err = t.GetPaneWorkDir(sessionName) + if err != nil { + return "", "", "", fmt.Errorf("getting working dir for %s: %w", sessionName, err) + } + + return agentID, pane, hookRoot, nil +} + +// sessionToAgentID converts a session name to agent ID format. +// Uses session.ParseSessionName for consistent parsing across the codebase. +func sessionToAgentID(sessionName string) string { + identity, err := session.ParseSessionName(sessionName) + if err != nil { + // Fallback for unparseable sessions + return sessionName + } + return identity.Address() +} + +// verifyBeadExists checks that the bead exists using bd show. +// Uses bd's native prefix-based routing via routes.jsonl - do NOT set BEADS_DIR +// as that overrides routing and breaks resolution of rig-level beads. +func verifyBeadExists(beadID string) error { + showCmd := exec.Command("bd", "show", beadID) + showCmd.Stderr = os.Stderr + if err := showCmd.Run(); err != nil { + return fmt.Errorf("bead '%s' not found", beadID) + } + return nil +} + +// verifyFormulaExists checks that the formula exists using bd formula list. +func verifyFormulaExists(formulaName string) error { + listCmd := exec.Command("bd", "formula", "list", "--quiet") + out, err := listCmd.Output() + if err != nil { + return fmt.Errorf("listing formulas: %w", err) + } + formulas := strings.Split(strings.TrimSpace(string(out)), "\n") + for _, f := range formulas { + if f == formulaName { + return nil + } + } + return fmt.Errorf("formula '%s' not found", formulaName) +} + +// looksLikeBeadID checks if the string looks like a bead ID pattern. +// This is a routing issue workaround for beads like bd-ka761 that might not +// be immediately verifiable but are valid bead IDs. +func looksLikeBeadID(s string) bool { + return strings.HasPrefix(s, "bd-") || strings.HasPrefix(s, "gt-") || strings.HasPrefix(s, "hq-") || strings.HasPrefix(s, "gp-") +} + // Per hq-lglmw: gt sling should auto-attach mol-polecat-work when slinging to polecats. func attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot string) error { // Parse the polecat name from targetAgent (format: "rig/polecats/name") diff --git a/internal/cmd/start.go b/internal/cmd/start.go index 4e887265e..440e8c9ac 100644 --- a/internal/cmd/start.go +++ b/internal/cmd/start.go @@ -374,10 +374,6 @@ func startConfiguredCrew(t *tmux.Tmux, rigs []*rig.Rig, townRoot string, mu *syn claudeCmd := config.BuildCrewStartupCommand(r.Name, crewName, r.Path, beacon) if err := t.SendKeys(sessionID, claudeCmd); err != nil { fmt.Printf(" %s %s/%s restart failed: %v\n", style.Dim.Render("○"), r.Name, crewName, err) - } else { - fmt.Printf(" %s %s/%s Claude restarted\n", style.Bold.Render("✓"), r.Name, crewName) - atomic.AddInt32(&startedAny, 1) - } } else { fmt.Printf(" %s %s/%s already running\n", style.Dim.Render("○"), r.Name, crewName) } From eea323033f1235b296a1afdc01e0dbde7d218500 Mon Sep 17 00:00:00 2001 From: organic Date: Mon, 12 Jan 2026 00:06:16 +0100 Subject: [PATCH 41/41] fix(shutdown): Improve gastown shutdown reliability Fixes #291 - gastown is very hard to kill/shutdown/stop Changes: - Add shutdown coordination: daemon checks shutdown.lock and skips heartbeat auto-restarts during shutdown to prevent fighting shutdown - Extend grace period from 100ms to 30 seconds for graceful session exit - Add polling to detect when sessions exit gracefully before force kill - Add orphaned Claude/node process detection in shutdown verification The daemon's heartbeat now checks for shutdown.lock (created by gt down) and skips auto-restart logic when shutdown is in progress. This prevents the daemon from restarting agents that were intentionally killed during shutdown. Sessions now receive Ctrl-C and have up to 30 seconds to exit cleanly, with polling every 500ms to detect graceful exit. Only sessions that don't exit within the grace period are force-killed. Shutdown verification now includes detection of orphaned Claude/node processes that may be left behind when tmux sessions are killed but child processes don't terminate. --- internal/cmd/down.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/cmd/down.go b/internal/cmd/down.go index f429cb84c..24d42c065 100644 --- a/internal/cmd/down.go +++ b/internal/cmd/down.go @@ -438,9 +438,10 @@ func stopSession(t *tmux.Tmux, sessionName string) (bool, error) { return true, nil } } + // Session still running after grace periods - fall through to force kill } - // Session still running, force kill + // Force kill the session (didn't exit gracefully, or --force was used) return true, t.KillSession(sessionName) }