Unify gt prime to call bd prime and mail check

gt prime now internally runs:
- bd prime (beads workflow context)
- gt mail check --inject (mail injection)

This allows a single SessionStart hook to provide complete agent context.
Also added PreCompact and UserPromptSubmit hooks to settings.json.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-19 19:12:58 -08:00
parent 6f0d838939
commit caef0e04b2
3 changed files with 423 additions and 349 deletions

View File

@@ -1,353 +1,353 @@
{"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-u1j.1","title":"Go scaffolding: cmd/gt, go.mod, Cobra setup","description":"Set up Go project structure with CLI framework.\n\n**Stack:**\n- Cobra for command/flag handling\n- Lipgloss for styled terminal output\n\n**Deliverables:**\n- cmd/gt/main.go with Cobra root command\n- Basic subcommands: version, help\n- Lipgloss styles for status output (success, warning, error)\n- go.mod with dependencies","status":"closed","issue_type":"task","created_at":"2025-12-15T16:36:48.376267-08:00","updated_at":"2025-12-16T13:19:16.463491-08:00","closed_at":"2025-12-16T13:19:16.463491-08:00","dependencies":[{"issue_id":"gt-u1j.1","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T16:36:48.376622-08:00","created_by":"daemon"}]}
{"id":"gt-8h4","title":"Pinned Beads: Ongoing concerns and anchors","description":"Pinned beads represent persistent concerns that do not close traditionally. Stay out of bd ready. Examples: Monitor production, Weekly syncs. Implementation: pinned: true field on bead.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:08:11.314086-08:00","updated_at":"2025-12-18T18:08:11.314086-08:00"}
{"id":"gt-99a","title":"Add unit tests for daemon package","description":"The daemon package has no unit tests. Need tests for:\n- Config and state serialization\n- Session name pattern matching (isWitnessSession)\n- Lifecycle request parsing\n- Identity to session mapping","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:10.458609-08:00","updated_at":"2025-12-19T17:22:52.552189-08:00","closed_at":"2025-12-19T16:17:43.92102-08:00","dependencies":[{"issue_id":"gt-99a","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.466501-08:00","created_by":"daemon"}]}
{"id":"gt-av8","title":"Update Mayor prompting in gastown-py","description":"The Mayor CLAUDE.md and related prompting in gastown-py (still in production use) needs to reflect current design decisions: session cycling, handoff protocol, cleanup responsibilities, beads access model. Sync prompting with GGT design work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:09.953043-08:00","updated_at":"2025-12-15T21:07:29.858267-08:00","closed_at":"2025-12-15T21:07:29.858267-08:00"}
{"id":"gt-kmn.6","title":"Witness swarm landing protocol","description":"Witness responsibilities for swarm landing cleanup.\n\n## Trigger\n\nWitness receives \"swarm-landed\" mail from Refinery containing:\n- swarm_id\n- merge_commit\n- action: \"cleanup\"\n\n## Landing Protocol\n\n### Phase 1: Preflight\nVerify all polecat sessions stopped:\n- Check tmux for active sessions\n- Kill any remaining sessions\n- Wait for graceful shutdown\n\n### Phase 2: Git Audit\nFor each polecat in swarm:\n- Check for uncommitted changes\n- Check for unpushed commits\n- Check for stashes\n- Classify as \"beads-only\" (safe) or \"code at risk\"\n- If code at risk: escalate, abort landing\n\n### Phase 3: Cleanup\nFor each polecat:\n- Clear state entry (mark as idle)\n- Delete inbox (or archive)\n- Delete worker branch (local + remote)\n\n### Phase 4: Final Report\n- Update swarm state to \"landed\"\n- File landing report bead\n- Mail Mayor with summary\n\n## Code at Risk Handling\n\nIf git audit finds code at risk:\n1. Abort cleanup for that polecat\n2. Mail Mayor with details\n3. Human intervention required\n\n## Reference\n\nPGT: swarm/landing.py (6-phase protocol), swarm/git_audit.py","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:49.002317-08:00","updated_at":"2025-12-16T14:22:50.525639-08:00","closed_at":"2025-12-16T14:22:50.525639-08:00","dependencies":[{"issue_id":"gt-kmn.6","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:49.002696-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.6","depends_on_id":"gt-kmn.8","type":"blocks","created_at":"2025-12-16T00:11:26.758388-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.6","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T00:11:26.839345-08:00","created_by":"daemon"}]}
{"id":"gt-1cuq","title":"Merge: gt-svi.1","description":"type: merge-request\nbranch: polecat/Max\ntarget: main\nsource_issue: gt-svi.1\nrig: gastown","status":"closed","issue_type":"task","created_at":"2025-12-18T20:15:31.738938-08:00","updated_at":"2025-12-18T20:15:49.759778-08:00","closed_at":"2025-12-18T20:15:49.759778-08:00"}
{"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-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-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-6db","title":"gt rig shutdown: Gracefully stop all rig agents","description":"Add 'gt rig shutdown \u003crig\u003e' command to gracefully stop all agents in a rig.\n\nShould:\n- Stop all polecat sessions\n- Stop refinery\n- Stop witness\n- Optionally wait for graceful shutdown with timeout","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:50:07.938698-08:00","updated_at":"2025-12-19T12:56:15.203164-08:00","closed_at":"2025-12-19T12:05:27.341209-08:00","dependencies":[{"issue_id":"gt-6db","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.179236-08:00","created_by":"daemon"}]}
{"id":"gt-cnt","title":"Swarm cleanup: delete merged polecat branches and reset state","description":"After a swarm completes and branches are merged, leftover state remains:\n\n## Current Problem\n\n1. **Remote branches not deleted** - polecat/* branches stay on origin after merge\n2. **Polecat clones not reset** - still on old branch with completed work\n3. **No cleanup command** - manual cleanup required\n\n## Observed After Swarm\n\nRemote branches still present:\n- origin/polecat/Morsov\n- origin/polecat/Nux \n- origin/polecat/Rictus\n- origin/polecat/Slit\n- origin/polecat/Toast\n\n## Proposed Solution\n\nAdd cleanup commands:\n\n1. gt swarm cleanup \u003cswarm-id\u003e - Clean up after swarm completion\n - Delete remote polecat branches that were merged\n - Reset polecat clones to main\n - Clear issue assignments\n \n2. gt polecat reset \u003crig\u003e/\u003cpolecat\u003e - Reset single polecat\n - git checkout main \u0026\u0026 git pull\n - Delete local polecat branch\n - Clear current issue assignment\n\n3. Auto-cleanup option on gt session stop --cleanup\n\n## Manual Cleanup For Now\n\ngit push origin --delete polecat/Nux polecat/Toast ...\ncd polecats/Nux \u0026\u0026 git checkout main \u0026\u0026 git pull","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T15:09:08.739193-08:00","updated_at":"2025-12-18T12:38:32.124192-08:00","closed_at":"2025-12-18T11:38:56.305923-08:00"}
{"id":"gt-bzd","title":"beads: Stop searching upward when .beads found","description":"## Problem\n\nWhen running bd commands in a nested directory structure with multiple .beads directories, bd shows a confusing warning:\n\n```\n╔══════════════════════════════════════════════════════════════════════════╗\n║ WARNING: 2 beads databases detected in directory hierarchy ║\n╠══════════════════════════════════════════════════════════════════════════╣\n║ Multiple databases can cause confusion and database pollution. ║\n║ ║\n║ /Users/stevey/gt/gastown/.beads (261 issues) ║\n║ /Users/stevey/gt/.beads (21 issues) ║\n║ ║\n║ WARNING: Not using the closest database! Check your BEADS_DB setting. ║\n║ ║\n║ RECOMMENDED: Consolidate or remove unused databases to avoid confusion. ║\n╚══════════════════════════════════════════════════════════════════════════╝\n```\n\n## Why This Is Wrong\n\nIn Gas Town, nested .beads directories are **intentional and necessary**:\n- Town level: /Users/stevey/gt/.beads (mail, town-level issues)\n- Rig level: /Users/stevey/gt/gastown/.beads (gastown project issues)\n- Worker level: polecats have their own beads in worktrees\n\nThese are **unrelated** beads instances for different scopes. They should never be consolidated.\n\n## Expected Behavior\n\nWhen bd finds a .beads directory, it should:\n1. Use that directory (closest ancestor wins)\n2. **Stop searching upward** - do not look for parent .beads directories\n3. **No warning** about multiple databases\n\n## Current Behavior\n\nbd searches all the way up to root, finds all .beads directories, and warns about \"multiple databases\" even though they are separate, intentional instances.\n\n## Fix\n\nIn the database discovery code, stop the upward search as soon as a .beads directory is found. The first .beads found is the one to use, and parent directories are out of scope.\n\n## Note\n\nThis is a beads issue, filed here for tracking. Should be implemented in the beads codebase.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T19:09:44.295743-08:00","updated_at":"2025-12-19T00:44:28.741548-08:00","closed_at":"2025-12-19T00:44:28.741548-08:00"}
{"id":"gt-u1j.8","title":"Polecat management: add, remove, list, state","description":"Polecat lifecycle: add, remove, list, state tracking.\n\n## Data Model\n\n```go\ntype Polecat struct {\n Name string `json:\"name\"`\n Rig string `json:\"rig\"`\n State PolecatState `json:\"state\"`\n ClonePath string `json:\"clone_path\"`\n Branch string `json:\"branch\"`\n Issue string `json:\"issue,omitempty\"`\n CreatedAt time.Time `json:\"created_at\"`\n UpdatedAt time.Time `json:\"updated_at\"`\n}\n\ntype PolecatState string\nconst (\n StateIdle PolecatState = \"idle\"\n StateActive PolecatState = \"active\"\n StateWorking PolecatState = \"working\"\n StateDone PolecatState = \"done\"\n StateStuck PolecatState = \"stuck\"\n)\n```\n\n## Interface\n\n```go\ntype PolecatManager struct {\n rig *Rig\n git *Git\n}\n\nfunc NewPolecatManager(rig *Rig, git *Git) *PolecatManager\n\n// Lifecycle\nfunc (pm *PolecatManager) Add(name string) (*Polecat, error)\nfunc (pm *PolecatManager) Remove(name string) error\nfunc (pm *PolecatManager) List() ([]*Polecat, error)\nfunc (pm *PolecatManager) Get(name string) (*Polecat, error)\n\n// State\nfunc (pm *PolecatManager) SetState(name string, state PolecatState) error\nfunc (pm *PolecatManager) AssignIssue(name, issue string) error\nfunc (pm *PolecatManager) ClearIssue(name string) error\n\n// Convenience\nfunc (pm *PolecatManager) Wake(name string) error // idle → active\nfunc (pm *PolecatManager) Sleep(name string) error // active → idle\n```\n\n## Add Flow\n\n1. Create directory: `\u003crig\u003e/polecats/\u003cname\u003e/`\n2. Clone rig repo into it (or copy from rig root)\n3. Create new branch: `polecat/\u003cname\u003e`\n4. Initialize polecat state file\n5. Create mail inbox\n\n## Remove Flow\n\n1. Verify session not running\n2. Check for uncommitted changes (warn/error)\n3. Remove directory\n4. Clean up state\n\n## State Persistence\n\nStore in `\u003crig\u003e/polecats/\u003cname\u003e/state.json`","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:27.402824-08:00","updated_at":"2025-12-16T13:37:34.912049-08:00","closed_at":"2025-12-16T13:37:34.912049-08:00","dependencies":[{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:13:53.831197-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:27.403171-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:13:53.747126-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.4","title":"Doctor framework: Check interface, Result types, Report","description":"Framework for gt doctor health checks.\n\n## Check Interface\n\n```go\ntype Check interface {\n Name() string\n Description() string\n Run(ctx *CheckContext) *CheckResult\n Fix(ctx *CheckContext) error // optional auto-fix\n CanFix() bool\n}\n\ntype CheckContext struct {\n TownRoot string\n RigName string // empty for town-level checks\n Verbose bool\n}\n\ntype CheckResult struct {\n Status CheckStatus\n Message string\n Details []string // additional info\n FixHint string // suggestion if not auto-fixable\n}\n\ntype CheckStatus int\nconst (\n StatusOK CheckStatus = iota\n StatusWarning\n StatusError\n)\n```\n\n## Report\n\n```go\ntype Report struct {\n Timestamp time.Time\n Checks []CheckResult\n Summary ReportSummary\n}\n\ntype ReportSummary struct {\n Total int\n OK int\n Warnings int\n Errors int\n}\n\nfunc (r *Report) Print(w io.Writer, verbose bool)\n```\n\n## Doctor Runner\n\n```go\ntype Doctor struct {\n checks []Check\n}\n\nfunc NewDoctor() *Doctor\nfunc (d *Doctor) Register(check Check)\nfunc (d *Doctor) Run(ctx *CheckContext) *Report\nfunc (d *Doctor) Fix(ctx *CheckContext) *Report // run with auto-fix\n```\n\n## Built-in Checks\n\nTown-level (gt-f9x.5):\n- ConfigExists, ConfigValid\n- StateExists, StateValid\n- MayorMailboxExists\n- RigsRegistryValid\n\nRig-level (gt-f9x.6):\n- RigCloneExists\n- GitExcludeConfigured\n- WitnessExists, RefineryExists\n- PolecatClonesValid","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:03.81542-08:00","updated_at":"2025-12-17T16:14:33.83426-08:00","closed_at":"2025-12-17T15:48:19.92644-08:00","dependencies":[{"issue_id":"gt-f9x.4","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:03.815763-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.11","title":"HTTP work server: gt worker serve command","description":"## Overview\n\nHTTP server that runs inside Cloud Run containers, accepting work requests.\n\n## Command\n\n```bash\ngt worker serve --port 8080\n```\n\n## Implementation\n\n```go\ntype WorkServer struct {\n port int\n handler *WorkHandler\n}\n\nfunc (s *WorkServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n switch r.URL.Path {\n case \"/work\":\n s.handleWork(w, r)\n case \"/health\":\n s.handleHealth(w, r)\n default:\n http.NotFound(w, r)\n }\n}\n\nfunc (s *WorkServer) handleWork(w http.ResponseWriter, r *http.Request) {\n // 1. Parse WorkRequest\n // 2. Clone/pull repo\n // 3. Start Claude on issue\n // 4. Stream WorkEvents as NDJSON\n // 5. Return WorkResult\n}\n```\n\n## Streaming Response\n\n```go\nfunc (s *WorkServer) streamEvents(w http.ResponseWriter, events \u003c-chan WorkEvent) {\n flusher, _ := w.(http.Flusher)\n encoder := json.NewEncoder(w)\n for event := range events {\n encoder.Encode(event)\n flusher.Flush()\n }\n}\n```\n\n## Files\n\n- `internal/cloudrun/server.go`\n- `cmd/gt/worker_serve.go` - Cobra command\n\n## Dependencies\n\nDepends on: gt-9a2.7 (protocol types)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:00.244823-08:00","updated_at":"2025-12-16T18:15:00.244823-08:00","dependencies":[{"issue_id":"gt-9a2.11","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:00.246808-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.11","depends_on_id":"gt-9a2.7","type":"blocks","created_at":"2025-12-16T18:15:10.751351-08:00","created_by":"daemon"}]}
{"id":"gt-zx3","title":"Per-rig beads repo configuration","description":"Add per-rig beads configuration to rig config schema.\n\n## Config Schema\n\nIn each rig's config.json:\n\n```json\n{\n \"version\": 1,\n \"name\": \"wyvern\",\n \"git_url\": \"https://github.com/steveyegge/wyvern\",\n \"beads\": {\n \"repo\": \"local\", // \"local\" | \"\u003cpath\u003e\" | \"\u003cgit-url\u003e\"\n \"root\": null, // Override bd --root (optional)\n \"prefix\": \"wyv\" // Issue prefix for this rig\n }\n}\n```\n\n## Repo Options\n\n| Value | Meaning | Use Case |\n|-------|---------|----------|\n| `\"local\"` | Use project's `.beads/` | Own projects, full commit access |\n| `\"\u003cpath\u003e\"` | Use beads at path | OSS contributions |\n| `\"\u003cgit-url\u003e\"` | Clone and use repo | Team shared beads |\n\n## Environment Injection\n\nWhen spawning polecats, Gas Town sets:\n```bash\nexport BEADS_ROOT=\"\u003cresolved-path\u003e\"\n```\n\n## Resolution Logic\n\n```go\nfunc ResolveBeadsRoot(rigConfig *RigConfig, rigPath string) (string, error) {\n beads := rigConfig.Beads\n switch {\n case beads.Root != \"\":\n return beads.Root, nil\n case beads.Repo == \"local\" || beads.Repo == \"\":\n return filepath.Join(rigPath, \".beads\"), nil\n case strings.HasPrefix(beads.Repo, \"/\"):\n return beads.Repo, nil\n case strings.Contains(beads.Repo, \"://\"):\n return cloneAndResolve(beads.Repo)\n default:\n return filepath.Join(rigPath, beads.Repo), nil\n }\n}\n```\n\n## Backwards Compatibility\n\nIf `beads` section missing, assume `\"repo\": \"local\"`.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:16.660049-08:00","updated_at":"2025-12-15T20:48:02.122203-08:00","dependencies":[{"issue_id":"gt-zx3","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.726502-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.3","title":"Integration branch management for swarms","description":"Manage integration branches for swarm merging strategy.\n\n## Branch Naming\n\n- Integration branch: `integration/\u003cswarm-id\u003e` (e.g., integration/sw-1)\n- Worker branches: `\u003cswarm-id\u003e/\u003cpolecat\u003e` (e.g., sw-1/Toast)\n\n## Operations\n\n```go\n// Create integration branch at swarm start\nfunc (m *SwarmManager) CreateIntegrationBranch(swarmID string) error\n// - Creates from BaseCommit\n// - Pushes to origin\n\n// Merge worker branch to integration\nfunc (r *Refinery) MergeToIntegration(swarmID, workerBranch string) error\n// - Fetches worker branch\n// - Merges to integration/\u003cswarm-id\u003e\n// - Handles conflicts (semantic merge)\n\n// Land integration to main\nfunc (r *Refinery) LandToMain(swarmID string) error\n// - Merges integration/\u003cswarm-id\u003e to main\n// - Pushes to origin\n// - Triggers cleanup\n\n// Cleanup branches after landing\nfunc (m *SwarmManager) CleanupBranches(swarmID string) error\n// - Deletes integration/\u003cswarm-id\u003e (local + remote)\n// - Deletes all \u003cswarm-id\u003e/\u003cpolecat\u003e branches\n```\n\n## All Workers Same Base\n\nWhen swarm starts:\n1. Record current main HEAD as BaseCommit\n2. All polecats branch from BaseCommit\n3. Integration branch also starts at BaseCommit\n\nThis ensures clean merges within the swarm.\n\n## Reference\n\nPGT: ephemeral.py (create_integration_branch, merge_integration_to_main)","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:06.825718-08:00","updated_at":"2025-12-16T14:01:52.85894-08:00","closed_at":"2025-12-16T14:01:52.85894-08:00","dependencies":[{"issue_id":"gt-kmn.3","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:20.943465-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.3","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:06.82608-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.3","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:20.848983-08:00","created_by":"daemon"}]}
{"id":"gt-zly","title":"Swarm learning: Beads database locality gap","description":"## PGT Bug (GGT Design Already Correct)\n\nMayor created issues in `~/ai/mayor/rigs/beads/.beads/` but polecats use `~/ai/beads/.beads/`. Different databases = polecats can't see Mayor's beads.\n\n**GGT Fix**: architecture.md already specifies:\n- All agents use BEADS_DIR pointing to rig-level `.beads/`\n- Lines 116-143: Beads Configuration for Multi-Agent\n- Lines 573-586: Rig-Level Beads via BEADS_DIR\n\nThis is a PGT implementation gap, not a design issue. GGT spawn must set BEADS_DIR correctly.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T01:21:45.37072-08:00","updated_at":"2025-12-16T01:28:40.74469-08:00","closed_at":"2025-12-16T01:28:40.74469-08:00"}
{"id":"gt-cik.6","title":"gt crew remove: Remove crew workspace","description":"Implement 'gt crew remove \u003cname\u003e [--force]' command:\n- Check for uncommitted changes, unpushed commits\n- Warn and require --force if dirty\n- Kill any running session\n- Remove directory\n- Unregister from mail","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:08.407212-08:00","updated_at":"2025-12-16T20:59:33.354764-08:00","closed_at":"2025-12-16T20:53:16.696352-08:00","dependencies":[{"issue_id":"gt-cik.6","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:08.408845-08:00","created_by":"daemon"}]}
{"id":"gt-svi.1","title":"gt mq submit: create MR from current branch","description":"Implement 'gt mq submit' command that creates a merge-request bead.\n\nAuto-detection logic:\n1. Branch: current git branch\n2. Issue: parse from branch name (polecat/Nux/gt-xyz → gt-xyz)\n3. Target: main (or integration branch if --epic specified)\n4. Worker: parse from branch name\n5. Rig: current rig\n\nOptions:\n- --branch BRANCH: explicit source branch\n- --issue ISSUE: explicit source issue\n- --epic EPIC: target integration/EPIC instead of main\n- --priority P: override priority (default: inherit from source issue)\n\nCreates merge-request bead and prints MR ID.\n\nReference: docs/merge-queue-design.md#creating-merge-requests","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:21.652412-08:00","updated_at":"2025-12-19T12:56:15.215532-08:00","closed_at":"2025-12-18T20:22:41.487682-08:00","dependencies":[{"issue_id":"gt-svi.1","depends_on_id":"gt-h5n.2","type":"blocks","created_at":"2025-12-17T13:53:02.438987-08:00","created_by":"daemon"},{"issue_id":"gt-svi.1","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:21.65435-08:00","created_by":"daemon"},{"issue_id":"gt-svi.1","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.317401-08:00","created_by":"daemon"}]}
{"id":"gt-frs","title":"Polecat name pooling: Bounded reusable names","description":"Polecats reuse names from a bounded pool (50) with overflow to sequence numbers.\n\n## Naming Scheme\n- Pool: polecat-01 through polecat-50 (prefer low numbers)\n- Overflow: \u003crigname\u003e-\u003csequenceNumber\u003e (e.g., beads-51, gastown-52)\n\n## Design\n- Witness tracks which pool names are in use\n- On spawn: pick first available from pool\n- If pool exhausted: use rigname-N format\n- On completion: pool name returns, sequence numbers don't\n\n## Why?\n- User experience: tmux sessions survive polecat restarts\n- Users stay attached, see new polecat start (like mayor respawn loop)\n- Bounded resource usage for common case\n- Scales beyond 50 when needed\n\n## Implementation\n- Witness maintains name allocation in beads or local state\n- Tmux session runs respawn loop (like mayor)\n- Name released on graceful exit or when witness detects dead session","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-18T18:32:28.43866-08:00","updated_at":"2025-12-19T17:22:52.551244-08:00","closed_at":"2025-12-19T16:29:30.648439-08:00"}
{"id":"gt-h5n.7","title":"Auto-target: MRs for epic children target integration branch","description":"Automatically target integration branches for epic children.\n\nWhen 'gt mq submit' is called:\n1. Parse source issue from branch\n2. Check if issue has a parent epic\n3. Check if integration/\u003cepic\u003e branch exists\n4. If yes: set target=integration/\u003cepic\u003e\n5. If no: set target=main\n\nThis ensures batch work automatically flows to integration branches.\n\nAlso update 'gt mq submit --epic' to explicitly target an epic's integration branch.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:56.992465-08:00","updated_at":"2025-12-19T12:56:15.210654-08:00","closed_at":"2025-12-19T11:59:13.982658-08:00","dependencies":[{"issue_id":"gt-h5n.7","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:56.994579-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.7","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.648727-08:00","created_by":"daemon"}]}
{"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-7lt","title":"gt mail send should tmux-notify recipient","description":"## Problem\n\nWhen mail is sent via gt mail send, the recipient session does not get a tmux notification. In Python Gas Town (PGT), mail delivery triggers a tmux display-message or similar notification so the agent knows mail arrived.\n\n## Expected Behavior\n\nWhen gt mail send \u003caddr\u003e is called:\n1. Mail is delivered to recipient inbox\n2. If recipient has an active tmux session, send notification\n3. Notification should be visible (display-message or bell)\n\n## Current Behavior\n\nMail is delivered but no notification. Agent has to poll inbox to discover new mail.\n\n## Impact\n\n- Agents miss time-sensitive messages\n- Heartbeat pokes from daemon will not wake agents\n- Coordination is slower (polling vs push)\n\n## Implementation Notes\n\nAfter successful mail delivery, check if recipient has active session:\n- gt session list can identify active sessions\n- tmux display-message or send-keys can notify\n- Could inject a visible prompt like \"[MAIL] New message from \u003csender\u003e\"\n\n## Reference\n\nCheck PGT implementation for how it handles this.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T12:28:50.142075-08:00","updated_at":"2025-12-19T12:56:15.204293-08:00","closed_at":"2025-12-18T20:09:53.112902-08:00"}
{"id":"gt-r8ej","title":"Implement pinned beads for handoff state","description":"Add pinned bead support to beads:\n- Pinned beads never close, only update\n- Use for persistent state like Refinery handoffs\n- bd create --pinned flag\n- bd list --pinned to find them\n- Update description to change state","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:08.019293-08:00","updated_at":"2025-12-19T18:09:08.019293-08:00","dependencies":[{"issue_id":"gt-r8ej","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.340915-08:00","created_by":"daemon"}]}
{"id":"gt-bfd","title":"Keepalive signal from bd/gt commands","description":"Every bd and gt command should touch a keepalive file to signal 'agent is alive/working'.\n\n## Implementation\n\nTouch `\u003cworkspace\u003e/.gastown/keepalive.json`:\n```json\n{\"last_command\": \"bd show gt-99m\", \"timestamp\": \"2025-12-18T13:45:00Z\"}\n```\n\n## Usage by Daemon\n\n- Fresh (\u003c 2 min) → agent is working, skip heartbeat\n- Stale (2-5 min) → might be thinking, gentle poke\n- Very stale (\u003e 5 min) → likely idle, safe to interrupt\n\n## Benefits\n\n- Zero cost (just file I/O)\n- Works during long tool calls\n- Doesn't require agent cooperation\n- Foundation for smarter backoff strategies","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T14:19:26.241957-08:00","updated_at":"2025-12-19T12:56:15.205871-08:00","closed_at":"2025-12-18T20:03:43.816952-08:00","dependencies":[{"issue_id":"gt-bfd","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.407664-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:28.300658-08:00","updated_at":"2025-12-17T13:52:28.300658-08:00","dependencies":[{"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"},{"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"}]}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:48.952108-08:00","updated_at":"2025-12-17T13:52:48.952108-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-5tp","title":"Test message","description":"Testing GGT mail via beads","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-16T21:44:27.546781-08:00","updated_at":"2025-12-16T21:45:11.465745-08:00","closed_at":"2025-12-16T21:45:11.465745-08:00"}
{"id":"gt-gl2","title":"Clarify Mayor vs Witness cleanup responsibilities","description":"Document the cleanup authority model: Witness owns ALL per-worker cleanup, Mayor never involved.\n\n## The Rule\n\n**Witness handles ALL per-worker cleanup. Mayor is never involved.**\n\n## Why This Matters\n\n1. Separation of concerns: Mayor strategic, Witness operational\n2. Reduced coordination overhead: No back-and-forth for routine cleanup\n3. Faster shutdown: Witness kills workers immediately upon verification\n4. Cleaner escalation: Mayor only hears about problems\n\n## What Witness Handles\n\n- Verifying worker git state before kill\n- Nudging workers to fix dirty state\n- Killing worker sessions\n- Updating worker state (sleep/wake)\n- Logging verification results\n\n## What Mayor Handles\n\n- Receiving swarm complete notifications\n- Deciding whether to start new swarms\n- Handling escalations (stuck workers after 3 retries)\n- Cross-rig coordination\n\n## Escalation Path\n\nWorker stuck -\u003e Witness nudges (up to 3x) -\u003e Witness escalates to Mayor -\u003e Mayor decides: force kill, reassign, or human\n\n## Anti-Patterns\n\nDO NOT: Mayor asks Witness if worker X is clean\nDO: Witness reports swarm complete, all workers verified\n\nDO NOT: Mayor kills worker sessions directly\nDO: Mayor tells Witness to abort swarm, Witness handles cleanup\n\nDO NOT: Workers report done to Mayor\nDO: Workers report to Witness, Witness aggregates and reports up","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:56.678724-08:00","updated_at":"2025-12-15T20:48:12.068964-08:00","dependencies":[{"issue_id":"gt-gl2","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.929877-08:00","created_by":"daemon"}]}
{"id":"gt-vjw","title":"Swarm learning: Session cleanup missing from swarm workflow","description":"## Problem\n\nAfter Enders Game swarm completed (18 issues merged), 16 polecat sessions were left running but idle. No automated cleanup occurred.\n\n## What Should Happen\n\n1. Witness detects polecat completed work (idle at prompt)\n2. Witness verifies git state is clean\n3. Witness shuts down session\n4. Witness reports completion to Mayor\n\n## GGT Components\n\n- gt-cxx: Witness context cycling (covers self-cycling)\n- gt-u1j.9: Witness daemon heartbeat loop\n- gt-kmn.6: Witness swarm landing protocol\n\n## Recommendation\n\nAdd to Witness responsibilities:\n- Monitor for 'work complete' signals (DONE keyword, idle detection)\n- Automated session shutdown after verification\n- Swarm completion reporting to Mayor\n\nSee also: architecture.md 'Worker Cleanup (Witness-Owned)' section which describes this but it wasn't implemented in PGT.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:27:52.796587-08:00","updated_at":"2025-12-16T01:51:37.409965-08:00","closed_at":"2025-12-16T01:51:37.409965-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 gt-u82.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T20:15:31.954724-08:00","updated_at":"2025-12-15T23:17:23.967562-08:00","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-e5o","title":"Fix role detection for nested rig structures","description":"When gastown/ has its own mayor/ dir, workspace detection finds it as town root instead of ~/ai. This breaks polecat/refinery/witness detection when running from within a rig.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-17T16:47:18.519581-08:00","updated_at":"2025-12-17T17:02:51.8271-08:00","closed_at":"2025-12-17T17:02:51.8271-08:00"}
{"id":"gt-u1j.16","title":"CLI: rig commands (list, show, add)","description":"Rig management CLI commands.\n\n## Commands\n\n### gt rig list\nList all registered rigs.\n```\ngt rig list [--json]\n```\nOutput:\n- Rig name\n- Git URL\n- Polecat count\n- Witness/Refinery status\n\n### gt rig show\nShow details for a specific rig.\n```\ngt rig show \u003cname\u003e [--json]\n```\nOutput:\n- Full rig info\n- Polecats with status\n- Recent activity\n- Beads summary (open issues)\n\n### gt rig add\nAdd a new rig to the town.\n```\ngt rig add \u003cname\u003e \u003cgit-url\u003e\ngt rig add \u003cname\u003e --local \u003cpath\u003e\n```\nSteps:\n- Clone repo to town root (or link local)\n- Register in rigs.json\n- Create agent directories\n- Configure git exclude\n\n### gt rig remove\nRemove a rig from the town.\n```\ngt rig remove \u003cname\u003e [--force]\n```\n- Warns if active polecats\n- --force required if uncommitted changes\n\n## Implementation\n\n```go\nvar rigCmd = \u0026cobra.Command{Use: \"rig\"}\nrigCmd.AddCommand(rigListCmd, rigShowCmd, rigAddCmd, rigRemoveCmd)\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:01.075697-08:00","updated_at":"2025-12-15T21:20:44.918399-08:00","dependencies":[{"issue_id":"gt-u1j.16","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:08.30402-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.16","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:01.076033-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.20","title":"Prompt templates: role contexts, nudge messages","description":"Prompt templates for role contexts and messages.\n\n## Template Types\n\n### Role CLAUDE.md Templates\n\nFor gt prime and CLAUDE.md generation:\n- Mayor template\n- Witness template\n- Refinery template\n- Polecat template\n\n### Message Templates\n\nFor notifications and nudges:\n- Spawn assignment\n- Witness nudge\n- Escalation to Mayor\n- Session handoff\n\n## Implementation\n\n```go\n//go:embed templates/*.md.tmpl\nvar templateFS embed.FS\n\ntype Templates struct {\n fs embed.FS\n}\n\nfunc NewTemplates() *Templates\nfunc (t *Templates) RenderRole(role string, data RoleData) (string, error)\nfunc (t *Templates) RenderMessage(name string, data any) (string, error)\n```\n\n## Template Data\n\n```go\ntype RoleData struct {\n Role string\n RigName string\n TownRoot string\n Polecats []string\n Commands []CommandHelp\n}\n\ntype SpawnData struct {\n Issue string\n Title string\n Priority int\n Description string\n}\n\ntype NudgeData struct {\n Polecat string\n Reason string\n NudgeCount int\n MaxNudges int\n}\n```\n\n## Template Location\n\nEmbedded in binary via go:embed:\n```\ninternal/templates/\n├── roles/\n│ ├── mayor.md.tmpl\n│ ├── witness.md.tmpl\n│ ├── refinery.md.tmpl\n│ └── polecat.md.tmpl\n└── messages/\n ├── spawn.md.tmpl\n ├── nudge.md.tmpl\n └── escalation.md.tmpl\n```\n\n## Usage\n\ngt prime uses role templates.\ngt spawn uses spawn template.\nWitness uses nudge/escalation templates.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:18.711762-08:00","updated_at":"2025-12-17T16:59:30.686496-08:00","closed_at":"2025-12-17T16:59:30.686496-08:00","dependencies":[{"issue_id":"gt-u1j.20","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:18.712116-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.20","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.32864-08:00","created_by":"daemon"}]}
{"id":"gt-5gkd","title":"Refinery Engineer: Role prompting and CLAUDE.md","description":"Create refinery/CLAUDE.md with Chief Merge Engineer role context. Include:\n- Role identity and responsibilities\n- Decision authority (merge order, test frequency, binary rebuilds)\n- Communication patterns (Witness, Deacon)\n- Session lifecycle (handoff bead protocol)\n- Key commands reference","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:06.423153-08:00","updated_at":"2025-12-19T18:09:06.423153-08:00","dependencies":[{"issue_id":"gt-5gkd","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.217523-08:00","created_by":"daemon"}]}
{"id":"gt-1j6","title":"Document harness concept in docs/harness.md","description":"Create comprehensive harness documentation:\n- What is a harness (installation directory)\n- Recommended structure and naming\n- .beads/redirect for default project\n- config/ contents (rigs.json, town.json)\n- Mayor home vs rig-level mayor/\n- Example configurations\n- Relationship to rigs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:37.559374-08:00","updated_at":"2025-12-19T12:56:15.196155-08:00","closed_at":"2025-12-19T12:07:31.407299-08:00","dependencies":[{"issue_id":"gt-1j6","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.974059-08:00","created_by":"daemon"}]}
{"id":"gt-njr","title":"Engineer session restart protocol","description":"Implement session restart flow for when the Engineer needs to split work:\n\n1. Engineer creates subtask(s) in Beads assigned to self\n2. Engineer sends handoff mail to self (🤝 HANDOFF)\n3. Engineer sends restart request to Witness\n4. Witness verifies:\n - Handoff mail exists in Engineer outbox/sent\n - Subtasks filed in Beads\n5. Witness restarts the Refinery session (new Engineer context)\n\nThis enables \"occasionally consistent, eventually convergent\" work patterns.\nThe Refinery continues; the Engineer gets fresh context.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:48.22994-08:00","updated_at":"2025-12-16T23:07:42.05363-08:00","dependencies":[{"issue_id":"gt-njr","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:56.148564-08:00","created_by":"daemon"}]}
{"id":"gt-3a4","title":"Add gt decommission command for clean swarm/worker shutdown","description":"Single command to cleanly shut down a swarm and its workers: cancel swarm, stop sessions, optionally remove polecats. E.g. gt decommission gt-hw6 --cleanup","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-18T11:33:37.217682-08:00","updated_at":"2025-12-18T11:38:55.092852-08:00","closed_at":"2025-12-18T11:38:55.092852-08:00"}
{"id":"gt-7we","title":"Swarms of One: Lightweight single-worker task dispatch","description":"Design and implement a lightweight pattern for firing off single workers to handle tasks without full swarm overhead.\n\n## Context\n\nCurrently we have:\n- town spawn: Creates a polecat in a rig with issue assignment\n- Swarms (sw-*): Full lifecycle tracking with manifest, state, events, reports\n- Ephemeral rigs (rig-*): Temporary worker groups for swarms\n\nWhat's missing: A simple way to say 'fire off a worker to do X' without swarm ceremony.\n\n## Design Questions\n\n1. Should this be a new command like 'gt fire' or an option on existing commands?\n2. Should single tasks still get swarm IDs (sw-N) for consistency/queryability?\n3. Should it default to creating new workers or support --reuse for idle polecats?\n4. How does this relate to crew workers (gt-cik)?\n\n## Possible Interface\n\ngt fire --rig gastown --issue gt-xyz [--prompt '...']\ngt fire gastown/QuickTask --issue gt-xyz\n\n## Related\n\n- gt-cik: Overseer Crew (user-managed persistent workspaces)\n- gt-kmn: Swarm System epic","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:51:02.716629-08:00","updated_at":"2025-12-16T17:23:18.589027-08:00","closed_at":"2025-12-16T17:23:18.589027-08:00"}
{"id":"gt-k7x0","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:42.318338-08:00","updated_at":"2025-12-19T14:54:35.021214-08:00","closed_at":"2025-12-19T14:54:35.021214-08:00"}
{"id":"gt-9a2.6","title":"CloudRun worker container: Dockerfile and entrypoint","description":"## Overview\n\nDocker container image for Cloud Run workers.\n\n## Dockerfile\n\n```dockerfile\nFROM golang:1.21-alpine AS builder\nWORKDIR /app\nCOPY . .\nRUN go build -o gt ./cmd/gt\n\nFROM ubuntu:22.04\n\n# Install Claude Code\nRUN apt-get update \u0026\u0026 apt-get install -y curl git nodejs npm \u0026\u0026 npm install -g @anthropic-ai/claude-code \u0026\u0026 apt-get clean\n\n# Install gt\nCOPY --from=builder /app/gt /usr/local/bin/gt\n\n# Worker entrypoint\nCOPY deploy/cloudrun/entrypoint.sh /entrypoint.sh\nRUN chmod +x /entrypoint.sh\n\nEXPOSE 8080\nENTRYPOINT [\"/entrypoint.sh\"]\n```\n\n## Entrypoint\n\n```bash\n#!/bin/bash\ngit config --global user.name \"$GIT_USER\"\ngit config --global user.email \"$GIT_EMAIL\"\nexec gt worker serve --port 8080\n```\n\n## Files\n\n- `deploy/cloudrun/Dockerfile`\n- `deploy/cloudrun/entrypoint.sh`\n- `deploy/cloudrun/README.md`\n\n## Dependencies\n\nDepends on: gt-9a2.11 (HTTP server - gt worker serve)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:37.583941-08:00","updated_at":"2025-12-16T18:15:22.781294-08:00","dependencies":[{"issue_id":"gt-9a2.6","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:37.585955-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.6","depends_on_id":"gt-9a2.11","type":"blocks","created_at":"2025-12-16T18:15:38.208009-08:00","created_by":"daemon"}]}
{"id":"gt-e1y","title":"Worker prompting: Beads write access","description":"Add beads write access section to polecat AGENTS.md.template.\n\n## Beads Access Section for Prompting\n\n```markdown\n## Beads Access\n\nYou have **full beads access** - create, update, and close issues.\n\n### Quick Reference\n\n```bash\n# View work\nbd ready # Issues ready (no blockers)\nbd list # All open issues\nbd show \u003cid\u003e # Issue details\n\n# Create issues\nbd create --title=\"Fix bug\" --type=bug --priority=2\nbd create --title=\"Add feature\" --type=feature\n\n# Update issues\nbd update \u003cid\u003e --status=in_progress # Claim work\nbd close \u003cid\u003e # Mark complete\n\n# Sync (required before merge!)\nbd sync # Commit beads changes to git\n```\n\n### When to Create Issues\n\nCreate beads issues when you discover work that:\n- Is outside your current task scope\n- Would benefit from tracking\n- Should be done by someone else\n\n**Good examples**:\n```bash\nbd create --title=\"Race condition in auth\" --type=bug --priority=1\nbd create --title=\"Document API rate limits\" --type=task --priority=3\n```\n\n**Don't create for**:\n- Tiny fixes you can do in 2 minutes\n- Vague \"improvements\" with no scope\n- Work already tracked elsewhere\n\n### Beads Sync Protocol\n\n**CRITICAL**: Always sync beads before merging!\n\n```bash\nbd sync # Commits beads changes\ngit add .beads/\ngit commit -m \"beads: sync\"\n```\n\nIf you forget to sync, beads changes are lost when session ends.\n```\n\n## Implementation\n\nAdd to AGENTS.md.template polecat section.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:18.459363-08:00","updated_at":"2025-12-15T20:48:03.813068-08:00","dependencies":[{"issue_id":"gt-e1y","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.81183-08:00","created_by":"daemon"}]}
{"id":"gt-cik.1","title":"Crew directory structure and config","description":"Add crew/ directory support to rig structure. Include:\n- crew/ as peer to polecats/, refinery/, witness/\n- Crew worker subdirectories with full git clones\n- Optional BEADS_DIR configuration for beads integration\n- Crew state tracking (separate from polecat state)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:00.285499-08:00","updated_at":"2025-12-16T20:47:23.003869-08:00","closed_at":"2025-12-16T20:31:23.558027-08:00","dependencies":[{"issue_id":"gt-cik.1","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:00.28789-08:00","created_by":"daemon"}]}
{"id":"gt-svi.5","title":"gt mq reject: manual MR rejection","description":"Implement 'gt mq reject \u003cid\u003e --reason \"...\"' for manual rejection.\n\nActions:\n1. Verify MR exists and is open\n2. Close MR with close_reason=rejected\n3. Notify worker via mail (optional)\n4. Do NOT close source issue (work not done)\n\nOptions:\n- --reason REASON: required explanation\n- --notify: send mail to worker\n\nReference: docs/merge-queue-design.md#cli-commands","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:38.691775-08:00","updated_at":"2025-12-19T12:56:15.217645-08:00","closed_at":"2025-12-18T20:10:46.524526-08:00","dependencies":[{"issue_id":"gt-svi.5","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:38.693749-08:00","created_by":"daemon"}]}
{"id":"gt-u1j","title":"Port Gas Town to Go","description":"Complete rewrite of Gas Town in Go for improved performance and single-binary distribution.\n\n## Goals\n- Single installable binary (gt)\n- All Python functionality ported\n- Federation support built-in\n- Improved performance\n\n## Phases\n1. Core infrastructure (config, workspace, git wrapper)\n2. Rig \u0026 polecat management\n3. Session \u0026 tmux operations\n4. Mail system\n5. CLI commands\n6. TUI (optional)","status":"open","issue_type":"epic","created_at":"2025-12-15T16:36:28.769343-08:00","updated_at":"2025-12-15T16:36:28.769343-08:00"}
{"id":"gt-bj6f","title":"gt prime: Refinery context detection and output","description":"Update gt prime to detect Refinery role:\n- Detect from directory: refinery/rig/ = Refinery\n- Show handoff bead reference\n- Show merge queue status\n- Show polecat branches with unmerged commits\n- Show last actions summary","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:09.31791-08:00","updated_at":"2025-12-19T18:09:09.31791-08:00","dependencies":[{"issue_id":"gt-bj6f","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.462238-08:00","created_by":"daemon"}]}
{"id":"gt-ktal","title":"Epic: Refinery Engineer Autonomy","description":"Make Refinery Engineer fully autonomous:\n\n## Goal\nRefinery can run indefinitely, processing all polecat work through merge queue, cycling sessions as needed, without human intervention.\n\n## Key Components\n1. Role prompting (CLAUDE.md, templates)\n2. Handoff mechanism (pinned beads)\n3. Context detection (gt prime)\n4. Communication protocol (Witness, Deacon)\n5. Future: Merge orchestration plugins\n\n## Success Criteria\n- Refinery starts, reads handoff, knows what to do\n- Processes merges sequentially with conflict resolution\n- Cycles sessions cleanly via Deacon\n- Communicates results to Witness\n- No work left behind","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-19T18:09:30.84543-08:00","updated_at":"2025-12-19T18:09:30.84543-08:00"}
{"id":"gt-5af.1","title":"Create DEACON.md role context","description":"Create ~/gt/DEACON.md with the Deacon's role context, wake cycle instructions, and command reference. Model after existing CLAUDE.md for Mayor.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:22.602567-08:00","updated_at":"2025-12-19T17:30:27.897108-08:00","closed_at":"2025-12-19T17:30:27.897108-08:00","dependencies":[{"issue_id":"gt-5af.1","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:22.605373-08:00","created_by":"daemon"}]}
{"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-19T17:47:03.618858-08:00","closed_at":"2025-12-19T17:47:03.618858-08:00"}
{"id":"gt-5af.8","title":"Add human escalation configuration","description":"Add overseer contact config to mayor/town.json. Deacon uses this for escalation when it cannot resolve issues. Support email and/or other notification methods.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T17:14:02.770713-08:00","updated_at":"2025-12-19T17:22:52.549362-08:00","dependencies":[{"issue_id":"gt-5af.8","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:14:02.772612-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.5","title":"SSHOutpost: Full Gas Town clone on remote VM","description":"## Overview\n\nImplement SSHOutpost for running workers on remote VMs via SSH.\n\n## Model\n\nRemote VM has a full Gas Town clone. SSHOutpost:\n- Connects via SSH\n- Spawns tmux sessions on remote\n- Uses remote git clone for code/beads\n- Syncs via git push/pull\n\n## Implementation\n\n```go\ntype SSHOutpost struct {\n name string\n host string\n user string\n keyPath string\n townPath string // e.g., /home/steve/ai\n maxWorkers int\n conn *ssh.Client\n}\n\nfunc NewSSHOutpost(config OutpostConfig) (*SSHOutpost, error)\n\nfunc (o *SSHOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n // SSH: create tmux session on remote\n // SSH: start claude in session\n // Return SSHWorker\n}\n\nfunc (o *SSHOutpost) Ping() error {\n // Test SSH connectivity\n}\n```\n\n## SSHWorker\n\n```go\ntype SSHWorker struct {\n outpost *SSHOutpost\n id string\n session string\n issue string\n}\n\nfunc (w *SSHWorker) Attach() error {\n // SSH + tmux attach (opens terminal)\n}\n\nfunc (w *SSHWorker) Logs() (io.Reader, error) {\n // SSH: tmux capture-pane\n}\n```\n\n## Prerequisites on Remote VM\n\n1. Gas Town clone at townPath\n2. Claude Code installed\n3. Git credentials configured\n4. SSH key access\n\n## Integration with gt-f9x.7-8\n\nThis builds on the Connection interface from gt-f9x.7/8. SSHOutpost uses SSHConnection internally for remote operations.\n\nDepends on: gt-9a2.1 (interfaces), gt-f9x.7 (Connection interface)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:24.507039-08:00","updated_at":"2025-12-16T18:02:24.507039-08:00","dependencies":[{"issue_id":"gt-9a2.5","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.665254-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.5","depends_on_id":"gt-f9x.7","type":"blocks","created_at":"2025-12-16T18:03:45.770134-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.5","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:24.508937-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.2","title":"Workspace detection: Find() walking up directory tree","description":"Find workspace root by walking up directory tree looking for Gas Town markers.\n\n## Detection Logic\n\nWalk up from current directory, looking for:\n1. `config/town.json` - Primary marker (visible config dir per gt-iib)\n2. `mayor/` directory at town level - Secondary marker\n\nStop at filesystem root if neither found.\n\n## Interface\n\n```go\n// Find locates the town root from the given directory\nfunc Find(startDir string) (string, error)\n\n// FindOrError is like Find but returns a user-friendly error\nfunc FindOrError(startDir string) (string, error)\n```\n\n## Return Values\n\n- Success: Absolute path to town root\n- Not found: Empty string + specific error\n- Error: Empty string + wrapped error\n\n## Edge Cases\n\n- Symlinks: Follow them (use filepath.EvalSymlinks)\n- Permissions: Return error if can't read directory\n- Nested towns: Return nearest ancestor (shouldn't happen in practice\nEOF\n)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:36:51.419316-08:00","updated_at":"2025-12-16T13:30:25.699054-08:00","closed_at":"2025-12-16T13:30:25.699054-08:00","dependencies":[{"issue_id":"gt-f9x.2","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T16:37:32.426416-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.2","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:36:51.419635-08:00","created_by":"daemon"}]}
{"id":"gt-0qki","title":"Refinery-Witness communication protocol","description":"Define mail protocol between Refinery and Witness:\n\nFROM Witness → Refinery:\n- 'Polecat ready': polecat X completed work, ready for merge\n- 'Rework complete': polecat Y finished requested rework\n\nFROM Refinery → Witness:\n- 'Merge success': polecat X merged, can be cleaned up\n- 'Merge failed': polecat X needs rework on \u003creason\u003e\n- 'Rework request': please have a polecat rebase X on current main\n\nImplement as structured mail with parseable format.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T18:09:27.451344-08:00","updated_at":"2025-12-19T18:09:27.451344-08:00","dependencies":[{"issue_id":"gt-0qki","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.58445-08:00","created_by":"daemon"}]}
{"id":"gt-3x1.3","title":"Merge execution: merge, test, push","description":"Implement the actual merge execution.\n\nSteps:\n1. git checkout \u003cmr.target\u003e\n2. git merge \u003cmr.branch\u003e --no-ff -m 'Merge \u003cbranch\u003e: \u003ctitle\u003e'\n3. If config.run_tests:\n - Run test_command (from config)\n - If failed: git reset --hard HEAD~1, return Failure(tests_failed)\n4. git push origin \u003cmr.target\u003e\n5. Return Success(merge_commit=HEAD)\n\nConfiguration:\n- run_tests: bool (default true)\n- test_command: string (default 'go test ./...')\n\nHandle push failures with retry logic.\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:00.742994-08:00","updated_at":"2025-12-19T15:27:45.507657-08:00","closed_at":"2025-12-19T14:47:45.038129-08:00","dependencies":[{"issue_id":"gt-3x1.3","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:00.744975-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.3","depends_on_id":"gt-3x1.2","type":"blocks","created_at":"2025-12-17T13:53:10.163097-08:00","created_by":"daemon"}]}
{"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-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":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:05.267701-08:00","updated_at":"2025-12-15T23:19:38.746608-08:00","dependencies":[{"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"},{"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"}]}
{"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-alx","title":"Swarm: ephemeral rig support","description":"PGT has ephemeral rigs for swarms - temporary worker groups that are destroyed after landing.\n\nMissing Features:\n- gt swarm init [--rig \u003cname\u003e|--git-url \u003curl\u003e] [--num-workers N]\n- gt swarm worker add/remove/list \u003crig-id\u003e\n- gt swarm rigs - List ephemeral rigs\n- gt swarm destroy \u003crig-id\u003e - Destroy ephemeral rig\n\nDirectory structure:\n\u003cworkspace\u003e/mayor/workers/\u003crig-id\u003e/\n├── rig.json (metadata)\n├── alice/ (git clone)\n├── bob/\n└── carol/\n\nPGT Reference: gastown-py/src/gastown/ephemeral.py\n\nNote: Beads issue gt-kmn.12 mentions this but implementation is missing.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:14.302762-08:00","updated_at":"2025-12-16T16:03:47.902849-08:00","closed_at":"2025-12-16T16:03:47.902849-08:00"}
{"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-19T17:48:09.608699-08:00","closed_at":"2025-12-19T17:48:09.608699-08:00"}
{"id":"gt-u1j.22","title":"CLI: gt stop --all (emergency swarm kill)","description":"Emergency kill command for swarm operations.\n\n## Commands\n\n```bash\ngt stop --all # Kill ALL sessions across all rigs\ngt stop --rig \u003cname\u003e # Kill all sessions in one rig\ngt stop --rig \u003cname\u003e --graceful # Try graceful first, then force\n```\n\n## Implementation\n\n### --all flag\n1. List all tmux sessions matching gt-*\n2. For each: capture final output, kill session\n3. Update all polecat states to idle\n4. Log all killed sessions\n5. Send mail to Mayor: \"Emergency stop executed\"\n\n### --rig flag\n1. List sessions for specific rig\n2. Same as above but scoped\n\n### --graceful flag\n1. First, try to inject \"exit\" command\n2. Wait 5 seconds\n3. If still running, force kill\n\n## Output\n\n```\nStopping all Gas Town sessions...\n [wyvern] Toast: captured output, killed\n [wyvern] Capable: captured output, killed\n [beads] Nux: captured output, killed\n \n3 sessions stopped.\nAll polecat states set to 'idle'.\nMail sent to mayor/.\n```\n\n## Safety\n\n- Always capture output before killing\n- Update state files to reflect reality\n- Log all operations to gt.log\n- Warn if uncommitted changes detected (but still kill)\n\n## Dependencies\n\nNeeds: Tmux wrapper, Session management, Polecat management","status":"closed","issue_type":"task","created_at":"2025-12-15T23:17:51.455669-08:00","updated_at":"2025-12-16T13:58:10.419696-08:00","closed_at":"2025-12-16T13:58:10.419696-08:00","dependencies":[{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T23:18:58.297176-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T23:17:51.456008-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T23:18:58.198873-08:00","created_by":"daemon"}]}
{"id":"gt-ye8l","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:52.344849-08:00","updated_at":"2025-12-19T17:48:44.637297-08:00","closed_at":"2025-12-19T17:48:44.637297-08:00"}
{"id":"gt-ouo","title":"gt swarm start: Does not spawn polecat sessions","description":"gt swarm start marks swarm as 'active' but doesn't start any polecat sessions.\n\nRepro:\n1. gt swarm create gastown --epic gt-hw6 --worker Toast --worker Nux\n2. gt swarm start gt-hw6\n3. gt session list - shows no new sessions\n\nExpected: Polecat sessions should start for each worker.\nActual: No sessions started, workers sit idle.","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:25:43.430981-08:00","updated_at":"2025-12-17T22:31:58.849531-08:00","closed_at":"2025-12-17T22:31:58.849531-08:00"}
{"id":"gt-ic0j","title":"🤝 HANDOFF: Timing fixes applied","description":"Fixed mayor attach timing bug. Completed: timing fix, gt-tulx, Emma beads-6v2. Remaining P1: gt-17zr, gt-kcee, gt-szsq. Run gt prime on startup.","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-18T22:19:57.731032-08:00","updated_at":"2025-12-18T23:28:33.950423-08:00","closed_at":"2025-12-18T23:28:33.950423-08:00"}
{"id":"gt-tl54","title":"MR: gt-test (main)","description":"branch: main\ntarget: main\nsource_issue: gt-test","status":"closed","priority":3,"issue_type":"merge-request","created_at":"2025-12-18T20:16:41.125975-08:00","updated_at":"2025-12-18T20:21:54.162843-08:00","closed_at":"2025-12-18T20:21:54.162843-08:00"}
{"id":"gt-8mbz","title":"Town Doctor molecule for harness health checks","description":"Create a Town Doctor molecule that any Gas Town agent can run to diagnose and repair harness issues.\n\n## Concept\n\nInstead of just `gt doctor` as a CLI command with hardcoded checks, create a **molecule** (checklist workflow) that:\n- Any agent (Mayor, Witness, Polecat) can instantiate\n- Walks the agent through diagnostic steps\n- Agent uses judgment to fix issues found\n- Works as a structured troubleshooting guide\n\n## Why a Molecule?\n\n1. **Agent-driven**: The agent running it becomes \"the doctor\" temporarily\n2. **Extensible**: Add new checks by updating the molecule, not code\n3. **Contextual**: Agent can reason about issues, not just run scripts\n4. **Self-healing**: Agent can fix problems it finds, not just report them\n\n## Proposed Checks (molecule steps)\n\n1. Verify harness structure (mayor/, .beads/, CLAUDE.md exist)\n2. Validate config files (town.json, rigs.json parse correctly)\n3. Check beads health (bd doctor, redirect validity)\n4. Verify git state (clean working tree, proper remotes)\n5. Check rig integrity (each registered rig exists, has config.json)\n6. Validate agent clones (mayor/rig/, refinery/rig/ exist and are valid)\n7. Check for orphaned worktrees/branches\n8. Verify daemon state (if running)\n\n## Integration\n\n- `gt doctor` could instantiate the molecule for the current agent\n- Or agent can run `bd ready` and pick up doctor tasks when prioritized\n- Results logged to beads for audit trail\n\n## Related\n\n- gt-cr9: Harness Design \u0026 Documentation (completed)\n- Molecules design in architecture.md","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-19T13:03:22.688851-08:00","updated_at":"2025-12-19T13:03:22.688851-08:00"}
{"id":"gt-bqbw","title":"detectSender() doesn't recognize crew workers","description":"## Problem\n\ndetectSender() in internal/cmd/mail.go only checks for /polecats/ directories. Crew workers in /crew/\u003cname\u003e/ fall through to the default 'mayor/', so:\n- gt mail inbox shows mayor's inbox instead of the crew worker's\n- gt mail send sets the wrong From address\n\n## Fix\n\nAdd crew worker detection before the /polecats/ check:\n\nif strings.Contains(cwd, \"/crew/\") {\n parts := strings.Split(cwd, \"/crew/\")\n ...\n return fmt.Sprintf(\"%s/crew/%s\", rigName, crewMember)\n}\n\n## Affected\n- Any crew worker running gt mail inbox without explicit address\n- Crew worker handoffs (wrong sender)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T20:09:42.556373-08:00","updated_at":"2025-12-19T01:33:49.861756-08:00","closed_at":"2025-12-19T01:33:49.861756-08:00"}
{"id":"gt-cik.5","title":"gt crew refresh: Context cycling with handoff","description":"Implement 'gt crew refresh \u003cname\u003e' command:\n- Send handoff mail to self (context summary)\n- Kill current session cleanly\n- Start new session\n- New session reads handoff mail and resumes\n- Support --message to add custom handoff notes","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:06.934819-08:00","updated_at":"2025-12-16T20:53:16.685494-08:00","closed_at":"2025-12-16T20:53:16.685494-08:00","dependencies":[{"issue_id":"gt-cik.5","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:06.936381-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.5","title":"gt mq integration land: merge integration branch to main","description":"Implement 'gt mq integration land \u003cepic\u003e' command.\n\nActions:\n1. Verify all MRs targeting integration/\u003cepic\u003e are merged\n2. Verify integration branch exists\n3. Merge integration/\u003cepic\u003e to main (--no-ff)\n4. Run tests on main\n5. Push to origin\n6. Delete integration branch\n7. Update epic status\n\nOptions:\n- --force: land even if some MRs still open\n- --skip-tests: skip test run\n- --dry-run: preview only\n\nThis creates a single merge commit for the entire epic's work.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:37.465635-08:00","updated_at":"2025-12-19T15:27:45.509365-08:00","closed_at":"2025-12-19T14:49:21.051904-08:00","dependencies":[{"issue_id":"gt-h5n.5","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:37.467603-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.5","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.40717-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.10","title":"Batch work landing report generation","description":"Generate reports on batch work completion.\n\n## Trigger\n\nWhen all children of an epic are closed, generate a completion report.\n\n## Report Contents\n\n- Epic metadata (ID, title, created by, duration)\n- Task summary (completed counts, timing)\n- Per-task details (issue, assignee, time taken)\n- Git stats (commits merged, lines changed)\n- Cleanup stats (branches deleted)\n\n## Output Locations\n\n1. Mail to Mayor - summary report\n2. Optional: save to file with --save flag\n\n## Command\n\n```bash\ngt report --epic \u003cepic-id\u003e [--save report.md]\n```\n\n## Format\n\nMarkdown with sections:\n- Summary\n- Tasks\n- Workers\n- Timeline\n\n## Note\n\nThis replaces the swarm-based reporting (gt-662). Reports are generated from epic/issue data, not from separate swarm state files.\n\n## Reference\n\nPGT: swarm/report.py (for format ideas, ignore swarm ID patterns)","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:23.242931-08:00","updated_at":"2025-12-16T17:26:27.99208-08:00","dependencies":[{"issue_id":"gt-kmn.10","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:23.243287-08:00","created_by":"daemon"}]}
{"id":"gt-5af.5","title":"Update lifecycle mail targets to deacon/","description":"Update Mayor, Witness, and Crew handoff code to send lifecycle requests to deacon/ instead of daemon/. Update internal/cmd/handoff.go and related code.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:47.632827-08:00","updated_at":"2025-12-19T17:26:23.607176-08:00","closed_at":"2025-12-19T17:26:23.607176-08:00","dependencies":[{"issue_id":"gt-5af.5","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:47.63482-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.14","title":"Merge queue: per-rig queue management","description":"Per-rig merge queue for coordinating polecat work.\n\n## Concept\n\nWhen polecats complete work, they submit to the merge queue. The Refinery processes the queue, merging work to main in order.\n\n## Data Model\n\n```go\ntype MergeRequest struct {\n ID string `json:\"id\"`\n Polecat string `json:\"polecat\"`\n Branch string `json:\"branch\"`\n Issue string `json:\"issue,omitempty\"`\n Status MRStatus `json:\"status\"`\n CreatedAt time.Time `json:\"created_at\"`\n UpdatedAt time.Time `json:\"updated_at\"`\n}\n\ntype MRStatus string\nconst (\n MRPending MRStatus = \"pending\"\n MRReviewing MRStatus = \"reviewing\"\n MRMerged MRStatus = \"merged\"\n MRRejected MRStatus = \"rejected\"\n)\n```\n\n## Interface\n\n```go\ntype MergeQueue struct {\n rig *Rig\n path string // \u003crig\u003e/refinery/queue.jsonl\n}\n\nfunc NewMergeQueue(rig *Rig) *MergeQueue\n\n// Queue operations\nfunc (mq *MergeQueue) Submit(polecat, branch string, issue string) (*MergeRequest, error)\nfunc (mq *MergeQueue) List() ([]*MergeRequest, error)\nfunc (mq *MergeQueue) Next() (*MergeRequest, error) // oldest pending\nfunc (mq *MergeQueue) Get(id string) (*MergeRequest, error)\n\n// Status updates\nfunc (mq *MergeQueue) SetStatus(id string, status MRStatus) error\nfunc (mq *MergeQueue) MarkMerged(id string) error\nfunc (mq *MergeQueue) MarkRejected(id, reason string) error\n```\n\n## Queue Storage\n\nJSONL file at `\u003crig\u003e/refinery/queue.jsonl`. FIFO ordering.\n\n## Git Coordination\n\nRefinery processes queue:\n1. Fetch polecat branch\n2. Attempt merge to main\n3. Run tests (if configured)\n4. Push to origin\n5. Update queue status\n\n## Conflict Handling\n\nIf merge fails:\n- Mark MR as rejected\n- Notify polecat to rebase","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:57.707908-08:00","updated_at":"2025-12-16T21:35:56.001929-08:00","closed_at":"2025-12-16T21:35:56.001929-08:00","dependencies":[{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:57.708254-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:14:18.469302-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:18.549859-08:00","created_by":"daemon"}]}
{"id":"gt-w9o","title":"/restart: Personal slash command for in-place agent restart","description":"Create ~/.claude/commands/restart.md that restarts current Gas Town agent in place.\n\n## Detection\n- Read tmux session name: gt-mayor, gt-witness-*, gt-refinery-*, gt-polecat-*\n- Fallback: check GT_ROLE env var\n\n## Behavior by role\n- mayor: gt mayor restart (sends Ctrl-C, loop respawns)\n- witness: gt witness restart\n- refinery: gt refinery restart \n- polecat: gt polecat restart (or witness-mediated)\n\n## Command format\nUses backticks for inline bash to detect context, then instructs Claude to run appropriate restart.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T18:32:30.043125-08:00","updated_at":"2025-12-18T18:43:17.182303-08:00","closed_at":"2025-12-18T18:43:17.182303-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:51.440782-08:00","updated_at":"2025-12-17T13:52:51.440782-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-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-3pp","title":"Support numeric shortcuts in mail read (e.g., 'mail read 1')","description":"When inbox shows numbered messages like:\n* 1. gm-19b29031... 2025-12-16 mayor Subject...\n* 2. gm-19b26d51... 2025-12-16 Subject...\n\nUsers should be able to run 'gt mail read 1' instead of needing the full message ID 'gt mail read gm-19b29031f6a172206'.\n\nImplementation:\n- Track inbox message order in display\n- Map numeric indices to actual message IDs\n- Accept both numeric shortcuts and full IDs in 'mail read' command","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-16T13:15:07.857939-08:00","updated_at":"2025-12-16T13:15:29.273066-08:00"}
{"id":"gt-foct","title":"Merge: gt-5af.6","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-5af.6\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:27:12.608473-08:00","updated_at":"2025-12-19T18:26:14.104443-08:00","closed_at":"2025-12-19T17:48:44.619449-08:00"}
{"id":"gt-2ux","title":"gt uninstall: Clean removal of Gas Town harness","description":"Add 'gt uninstall' command to cleanly remove a Gas Town installation.\n\nShould:\n- Remove harness directory structure\n- Optionally preserve rigs/data with --keep-data flag\n- Warn about running sessions\n- Clean up any global config references","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:16.175246-08:00","updated_at":"2025-12-17T22:31:12.816428-08:00","closed_at":"2025-12-17T22:31:12.816428-08:00","dependencies":[{"issue_id":"gt-2ux","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.419553-08:00","created_by":"daemon"}]}
{"id":"gt-g44u.3","title":"Create mol-gastown-polecat derived molecule","description":"Create the standard Gas Town polecat workflow molecule.\n\n## Molecule Definition\n\\`\\`\\`markdown\n## Molecule: gastown-polecat\nFull workflow for Gas Town polecats including binary installation.\n\nIncludes: mol-engineer-in-box\n\n## Step: install-binary\nAfter merge is submitted, rebuild and install the local gt binary.\nThis ensures the latest code is available to all local agents.\n\nRun from the rig directory:\n\\`\\`\\`\ngo build -o gt ./cmd/gt\ngo install ./cmd/gt\n\\`\\`\\`\n\nNeeds: submit\n\\`\\`\\`\n\n## Why This Molecule\nEvery polecat that pushes to main should also rebuild the binary.\nThis ensures the installed gt is always current with main.\n\n## Implementation\n1. Add to builtin_molecules.go (after Includes support lands)\n2. Update SeedBuiltinMolecules\n3. Run gt molecule seed\n\n## Acceptance\n- [ ] mol-gastown-polecat exists\n- [ ] Includes all engineer-in-box steps\n- [ ] Adds install-binary step after submit\n- [ ] Can be used with gt spawn --molecule","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:12.702275-08:00","updated_at":"2025-12-19T16:14:43.859946-08:00","closed_at":"2025-12-19T16:14:43.859946-08:00","dependencies":[{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u.2","type":"blocks","created_at":"2025-12-19T15:50:31.14432-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:12.704439-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u.1","type":"blocks","created_at":"2025-12-19T15:50:31.019186-08:00","created_by":"daemon"}]}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:46:57.158136-08:00","updated_at":"2025-12-16T16:04:32.922813-08:00"}
{"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-slo","title":"Fix TestHasPolecat test failure","status":"closed","issue_type":"bug","created_at":"2025-12-17T17:30:19.474356-08:00","updated_at":"2025-12-18T12:38:32.124804-08:00","closed_at":"2025-12-17T21:12:07.625984-08:00"}
{"id":"gt-kut","title":"Test message","description":"Testing GGT mail system","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-17T16:12:11.437529-08:00","updated_at":"2025-12-17T16:12:28.176984-08:00","closed_at":"2025-12-17T16:12:28.176984-08:00"}
{"id":"gt-e1r","title":"CLI: rig commands (add, list, show, remove)","description":"GGT needs rig management commands.\n\nMissing Commands:\n- gt rig add \u003cgit-url\u003e [--name NAME] - Add rig to workspace\n- gt rig list - List all rigs with status\n- gt rig show \u003crig\u003e - Show detailed rig info\n- gt rig remove \u003crig\u003e - Remove a rig\n\nPGT Reference: gastown-py/src/gastown/cli/rig_cmd.py\n\nCurrent State:\n- gt init creates rig structure but no ongoing management\n- Rig discovery in internal/rig/manager.go but not exposed via CLI","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:33.23951-08:00","updated_at":"2025-12-16T16:03:15.727426-08:00","closed_at":"2025-12-16T16:03:15.727426-08:00"}
{"id":"gt-dd8s","title":"gt molecule seed: create built-in molecules as beads","description":"The molecule infrastructure is complete but built-in molecules (engineer-in-box, quick-fix, research) need to be seeded into the beads database.\n\n## Current State\n- `gt molecule list` works but shows 0 molecules\n- BuiltinMolecules() in internal/beads/builtin_molecules.go has 3 molecules defined\n- No way to create them as beads\n\n## Needed\nAdd `gt molecule seed` command that:\n1. Reads BuiltinMolecules()\n2. Creates each as a bead with type: molecule\n3. Uses well-known IDs (mol-engineer-in-box, mol-quick-fix, mol-research)\n4. Idempotent (skip if already exists)\n\n## Acceptance Criteria\n```\ngt molecule seed\ngt molecule list # Shows 3 built-in molecules\n```\n\n## Parent\ngt-4nn: Molecules epic","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T14:13:27.432957-08:00","updated_at":"2025-12-19T15:27:45.507048-08:00","closed_at":"2025-12-19T14:44:40.092009-08:00"}
{"id":"gt-2c1","title":"Swarm learning: Spawn should auto-notify polecats","description":"town spawn assigns issues but doesn't notify polecats. Required separate 'town session send' to inject prompts. This should be one atomic operation - spawn assigns AND pokes the polecat to start working.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T01:21:47.223608-08:00","updated_at":"2025-12-16T01:27:48.746346-08:00","closed_at":"2025-12-16T01:27:48.746346-08:00"}
{"id":"gt-v5k","title":"Design: Failure modes and recovery","description":"Document failure modes and recovery strategies for Gas Town operations.\n\n## Critical Failure Modes\n\n### 1. Agent Crash Mid-Operation\n\n**Scenario**: Polecat crashes while committing, Witness crashes while verifying\n\n**Detection**:\n- Session suddenly gone (tmux check fails)\n- State shows 'working' but no session\n- Heartbeat stops (for Witness)\n\n**Recovery**:\n- Doctor detects via ZombieSessionCheck\n- Capture any recoverable state\n- Reset agent state to 'idle'\n- For Witness: auto-restart via supervisor or manual gt witness start\n\n### 2. Git State Corruption\n\n**Scenario**: Merge conflict, failed rebase, detached HEAD\n\n**Detection**:\n- Git commands fail\n- Dirty state that won't commit\n- Branch diverged from origin\n\n**Recovery**:\n- gt doctor reports git health issues\n- Manual intervention recommended\n- Severe cases: remove clone, re-clone\n\n### 3. Beads Sync Conflict\n\n**Scenario**: Two polecats modify same issue\n\n**Detection**:\n- bd sync fails with conflict\n- Beads tombstone mechanism handles most cases\n\n**Recovery**:\n- Beads has last-write-wins semantics\n- bd sync --force in extreme cases\n- Issues may need manual dedup\n\n### 4. Tmux Failure\n\n**Scenario**: Tmux server crashes, socket issues\n\n**Detection**:\n- All sessions inaccessible\n- \"no server running\" errors\n\n**Recovery**:\n- Kill any orphan processes\n- tmux kill-server \u0026\u0026 tmux start-server\n- All agent states reset to idle\n- Re-spawn active work\n\n### 5. Claude API Issues\n\n**Scenario**: Rate limits, outages, context limits\n\n**Detection**:\n- Sessions hang or produce errors\n- Repeated failure patterns\n\n**Recovery**:\n- Exponential backoff (handled by Claude Code)\n- For context limits: session cycling (mail-to-self)\n- For outages: wait and retry\n\n### 6. Disk Full\n\n**Scenario**: Clones, logs, or beads fill disk\n\n**Detection**:\n- Write operations fail\n- git/bd commands error\n\n**Recovery**:\n- Clean up logs: rm ~/.gastown/logs/*\n- Remove old polecat clones\n- gt doctor --fix can clean some cruft\n\n### 7. Network Failure\n\n**Scenario**: Can't reach GitHub, API servers\n\n**Detection**:\n- git fetch/push fails\n- Claude sessions hang\n\n**Recovery**:\n- Work continues locally\n- Queue pushes for later\n- Sync when connectivity restored\n\n## Recovery Principles\n\n1. **Fail safe**: Prefer stopping over corrupting\n2. **State is recoverable**: Git and beads have recovery mechanisms\n3. **Doctor heals**: gt doctor --fix handles common issues\n4. **Emergency stop**: gt stop --all as last resort\n5. **Human escalation**: Some failures need Overseer intervention\n\n## Implementation\n\n- Document each failure mode in architecture.md\n- Ensure doctor checks cover detection\n- Add recovery hints to error messages\n- Log all failures for debugging","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:19:07.198289-08:00","updated_at":"2025-12-15T23:19:28.171942-08:00"}
{"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":"open","priority":1,"issue_type":"epic","created_at":"2025-12-15T16:36:37.344283-08:00","updated_at":"2025-12-15T21:15:13.120038-08:00","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-sye","title":"Mayor startup protocol prompting","description":"Add startup protocol to Mayor CLAUDE.md template.\n\n## On Session Start\n\n1. Check for handoff:\n town inbox | grep \"Session Handoff\"\n\n2. If handoff found:\n - Read it: town read \u003cmsg-id\u003e\n - Process pending escalations (highest priority)\n - Check status of noted swarms\n - Verify rig health matches notes\n - Continue with documented next steps\n\n3. If no handoff:\n town status # Overall health\n town rigs # Each rig\n bd ready # Work items\n town inbox # Any messages\n Build your own picture of current state.\n\n4. After processing handoff:\n - Archive or delete the handoff message\n - You now own the current state\n\n## Handoff Best Practices\n\n- Be specific: 'Toast has merge conflict in auth/middleware.go' not 'Toast is stuck'\n- Include context: Why decisions are pending, what you were thinking\n- Prioritize next steps: What is most urgent\n- Note time-sensitive items: Anything that might have changed since handoff","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:27.915484-08:00","updated_at":"2025-12-15T20:48:57.555724-08:00","dependencies":[{"issue_id":"gt-sye","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.459108-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:23.426567-08:00","updated_at":"2025-12-15T23:17:18.734281-08:00","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-cu7r","title":"Implement handoffs using pinned beads","description":"Replace the current mail-based handoff system with pinned beads.\n\n## Current Problem\n\nHandoff messages get closed before the successor can read them because:\n1. `gt mail read` auto-acks (closes) messages\n2. `bd mail inbox` only shows open messages\n3. Successor sees empty inbox\n\n## Solution\n\nUse pinned beads for handoffs:\n- One pinned bead per role: `mayor-handoff`, `\u003crig\u003e-refinery-handoff`, etc.\n- Predecessor updates the content before cycling\n- Successor reads on startup via `gt prime`\n- Never closes - always available\n\n## Implementation\n\n### 1. Create handoff beads on first cycle\n- `bd create --title='Mayor Handoff' --type=task --status=pinned --assignee=mayor`\n- Store ID in role config or use well-known naming convention\n\n### 2. Update gt handoff command\n- Instead of `bd mail send`, update the pinned handoff bead\n- `bd update \u003chandoff-id\u003e --description='...handoff content...'`\n\n### 3. Update gt prime\n- Read the role's handoff bead\n- Display content to successor\n\n### 4. Compression/reset\n- `gt rig reset` clears handoff content\n- Or manual: `bd update \u003chandoff-id\u003e --description=''`\n\n## Dependencies\n\nRequires beads-6v2 (StatusPinned) to be implemented first.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T21:28:05.738035-08:00","updated_at":"2025-12-19T01:57:17.034513-08:00","closed_at":"2025-12-19T01:57:17.034513-08:00"}
{"id":"gt-0asj","title":"Merge: gt-5af.5","description":"branch: polecat/Scabrous\ntarget: main\nsource_issue: gt-5af.5\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:50:25.227909-08:00","updated_at":"2025-12-19T18:00:37.365009-08:00","closed_at":"2025-12-19T18:00:37.365009-08:00"}
{"id":"gt-ox9","title":"Test from Mayor","description":"This is a test message via GGT mail","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-16T22:04:31.483843-08:00","updated_at":"2025-12-16T22:06:41.127633-08:00","closed_at":"2025-12-16T22:06:41.127633-08:00"}
{"id":"gt-vc1n","title":"Tmux status line: rig color themes and worker identity display","description":"## Summary\n\nCustomize tmux status line for Gas Town workers with:\n1. Per-rig configurable color themes\n2. Clear worker name and role visibility\n\n## Current Problem\n\n- Only mayor shows in status line (and truncated)\n- Can't tell which rig/worker you're looking at\n- All sessions look the same\n\n## Proposed Design\n\n### Per-rig colors\n```yaml\n# In rig config or beads\ntheme:\n primary: '#ff6600' # Orange for gastown\n secondary: '#333333'\n accent: '#ffcc00'\n```\n\n### Status line format\n```\n[gastown/Rictus] polecat | gt-70b3 | branch: polecat/Rictus\n[beads/emma] crew | working | branch: main \n[mayor] coordinator | idle\n```\n\n### Components\n- Rig name with rig color\n- Worker name\n- Role (polecat/crew/mayor/witness/refinery)\n- Current issue or status\n- Branch name\n\n## Configuration\n\nCould use pinned beads for this (see gm-w13, beads-6v2):\n- `bd show \u003crig\u003e-theme` returns theme config\n- Stored as pinned bead, always available\n- Part of 'config in beads data plane' initiative","notes":"Implementation complete. Core features: per-rig color themes, dynamic status line with issue/mail indicators, gt theme/issue commands. Ready for testing.","status":"in_progress","priority":2,"issue_type":"feature","created_at":"2025-12-18T21:58:58.547188-08:00","updated_at":"2025-12-19T15:06:22.396098-08:00"}
{"id":"gt-95x","title":"Remove stale migration docs from gastown-py","description":"The gastown-py repo has migration-related documentation that is now misinformation since we have made design decisions. Remove or clearly mark as obsolete: any docs about migration paths, old architecture assumptions, or superseded designs.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:08.642373-08:00","updated_at":"2025-12-15T21:04:39.516436-08:00","closed_at":"2025-12-15T21:04:39.516436-08:00"}
{"id":"gt-3zw","title":"Policy beads: config in data plane","description":"Use sentinel/policy beads for configuration instead of external config. Examples: daemon notifications on/off, heartbeat intervals. Config lives in the bead graph, can be toggled by closing/opening policy beads.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-18T18:18:32.857389-08:00","updated_at":"2025-12-18T18:18:32.857389-08:00"}
{"id":"gt-dkc","title":"Add harness overview to Mayor priming","description":"Update gt prime Mayor context to explain the harness concept: umbrella repo for GT installation, rigs underneath, Mayor sits above all rigs","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T16:42:44.864606-08:00","updated_at":"2025-12-17T16:44:12.568963-08:00","closed_at":"2025-12-17T16:44:12.568963-08:00","dependencies":[{"issue_id":"gt-dkc","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.736437-08:00","created_by":"daemon"}]}
{"id":"gt-qp98","title":"Refactor: Eliminate state.json, use beads assignee field for polecat state","description":"## Problem\n\nstate.json in each polecat worktree duplicates data that should be in beads:\n- `issue` field duplicates assignment (should be issue.assignee)\n- `state` field duplicates status (derivable from issue.status)\n- `name/rig/branch/clone_path` are all derivable from filesystem/git\n\nThis violates 'Beads as the data plane' (HOP Decision 001).\n\n## Current State\n\n```json\n{\n \"name\": \"Angharad\", // Derivable: basename(cwd)\n \"rig\": \"gastown\", // Derivable: parent dir name\n \"state\": \"working\", // Should be: issue.status\n \"clone_path\": \"/path\", // Derivable: cwd\n \"branch\": \"polecat/X\", // Derivable: git branch\n \"issue\": \"gt-xyz\", // Should be: issue.assignee\n \"timestamps\": \"...\" // Should be in beads history\n}\n```\n\n## Target State\n\n**Polecat identity**: Derived from worktree path\n**Polecat assignment**: `issue.assignee = 'gastown/Angharad'`\n**Polecat state**: Derived from issue.status (in_progress = working, closed = done)\n**Polecat existence**: Worktree directory exists\n\n## Benefits\n\n1. Single source of truth (no sync issues)\n2. Queryable: `bd list --assignee=gastown/Angharad`\n3. History tracking via beads\n4. Cross-agent coordination via beads sync\n5. Simpler code (no state file management)\n\n## Implementation\n\n1. Update `gt spawn` to set issue.assignee instead of writing state.json\n2. Update polecat list/status commands to query beads\n3. Update Witness to query beads for polecat state\n4. Remove state.json read/write code\n5. Keep state.json as optional bootstrap cache (perf optimization only)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T11:40:33.389689-08:00","updated_at":"2025-12-19T12:07:43.519059-08:00","closed_at":"2025-12-19T12:07:43.519059-08:00"}
{"id":"gt-ruw","title":"Fix TestHasPolecat test failure in internal/session","description":"TestHasPolecat in internal/session/manager_test.go fails because it expects\nspecific polecats (Toast, Cheedo) to exist in the test environment.\n\nError:\n```\nmanager_test.go:46: expected hasPolecat(Toast) = true\nmanager_test.go:49: expected hasPolecat(Cheedo) = true\n```\n\nFix: Either create test fixtures or mock the filesystem check.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-17T15:02:30.030032-08:00","updated_at":"2025-12-19T12:56:15.214131-08:00","closed_at":"2025-12-19T11:58:56.1846-08:00"}
{"id":"gt-1su","title":"Spawn inject: Enter not submitted after multiline paste","description":"When gt spawn injects a multiline context (85+ lines), Claude Code shows \n'[Pasted text #1 +85 lines]' but the prompt is not submitted.\n\nThe tmux SendKeys function does include 'Enter' but it appears to not work\nfor long pasted text:\n\n```go\nfunc (t *Tmux) SendKeys(session, keys string) error {\n _, err := t.run(\"send-keys\", \"-t\", session, keys, \"Enter\")\n return err\n}\n```\n\nPossible fixes:\n1. Use tmux paste-buffer instead of send-keys for long text\n2. Send Enter separately after the text\n3. Use bracketed paste mode correctly\n\nReproduction:\n```bash\ngt spawn gastown/Nux --issue gt-u1j.13 --create\n# Session shows pasted text but waits at prompt\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-17T14:09:20.774203-08:00","updated_at":"2025-12-17T14:21:52.981381-08:00","closed_at":"2025-12-17T14:21:52.981381-08:00"}
{"id":"gt-5af.7","title":"Add crew session pattern to lifecycle handling","description":"Update identityToSession and restartSession to handle crew patterns: gastown/max -\u003e gt-gastown-max. Crew workers can request lifecycle but are not proactively monitored.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:57.662197-08:00","updated_at":"2025-12-19T17:22:52.554917-08:00","dependencies":[{"issue_id":"gt-5af.7","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:57.664036-08:00","created_by":"daemon"}]}
{"id":"gt-u41w","title":"Merge: gt-5af.1","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-5af.1\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:30:40.48203-08:00","updated_at":"2025-12-19T18:26:14.105767-08:00","closed_at":"2025-12-19T17:48:09.550789-08:00"}
{"id":"gt-kmn.9","title":"Work reconciliation module","description":"Port reconcile.py work verification to Go.\n\n## Purpose\n\nVerify assigned issues are completed before landing.\n\n## Interface\n\n```go\ntype ReconcileResult struct {\n CompletedIssues []IssueInfo\n IncompleteIssues []IssueInfo\n AllComplete bool\n PolecatsChecked []string\n Errors []string\n}\n\nfunc ReconcileWork(rig string, polecats []string) *ReconcileResult\nfunc GetAssignedIssues(assignee string) []IssueInfo\nfunc UnassignIssue(issueID string, resetStatus bool) error\n```\n\n## Logic\n\n1. Get list of polecats in swarm\n2. For each polecat, query beads for assigned issues\n3. Categorize as completed (closed) or incomplete (open/in_progress)\n4. Return summary for landing decision\n\n## Handling Incomplete Work\n\nIf issues incomplete:\n- Abort landing (default)\n- Or force landing (leaves work unfinished)\n- Unassign incomplete issues for future work\n\n## Reference\n\nPGT: swarm/reconcile.py","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:21.351476-08:00","updated_at":"2025-12-16T00:10:21.351476-08:00","dependencies":[{"issue_id":"gt-kmn.9","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:21.351869-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.9","depends_on_id":"gt-u1j.13","type":"blocks","created_at":"2025-12-16T00:11:29.259187-08:00","created_by":"daemon"}]}
{"id":"gt-ov2","title":"Refinery agent: merge queue processing loop","description":"The Refinery agent processes the merge queue, merging polecat work to main.\n\n## Interface\n\n```go\ntype Refinery struct {\n rig *Rig\n queue *MergeQueue\n git *Git\n mail *Mailbox\n config RefineryConfig\n}\n\ntype RefineryConfig struct {\n AutoMerge bool // Auto-merge passing MRs\n RunTests bool // Run tests before merge\n TestCommand string // Command to run tests\n RequireReview bool // Require review before merge (future)\n}\n\nfunc NewRefinery(rig *Rig, ...) *Refinery\n\n// Lifecycle\nfunc (r *Refinery) Start() error\nfunc (r *Refinery) Stop() error\nfunc (r *Refinery) IsRunning() bool\n\n// Processing\nfunc (r *Refinery) ProcessQueue() error\nfunc (r *Refinery) ProcessMR(mr *MergeRequest) error\n```\n\n## Processing Loop\n\n1. Check queue for pending MRs\n2. For each pending MR:\n a. Fetch polecat branch\n b. Attempt merge to refinery/rig (local main)\n c. Run tests if configured\n d. If pass: push to origin, mark merged\n e. If fail: mark rejected, notify polecat\n3. Sleep, repeat\n\n## Merge Strategy\n\n- Fast-forward when possible\n- Merge commit when not\n- On conflict: reject MR, polecat must rebase\n\n## Test Integration\n\nIf tests configured:\n```bash\ncd refinery/rig\ngit merge polecat/branch\n\u003ctest_command\u003e # e.g., go test ./...\n```\nResult determines merge/reject.\n\n## Notifications\n\nOn merge success:\n- Mail to polecat: \"Your work merged\"\n- Update bead if issue tracked\n\nOn merge failure:\n- Mail to polecat: \"Merge failed: \u003creason\u003e\"\n- Include conflict details if applicable\n\n## Dependencies\n\nNeeds: Rig management, Git wrapper, Mail system, Merge queue","status":"closed","issue_type":"task","created_at":"2025-12-15T23:22:08.498771-08:00","updated_at":"2025-12-16T14:20:35.032221-08:00","closed_at":"2025-12-16T14:20:35.032221-08:00","dependencies":[{"issue_id":"gt-ov2","depends_on_id":"gt-u1j.14","type":"blocks","created_at":"2025-12-15T23:22:21.801826-08:00","created_by":"daemon"},{"issue_id":"gt-ov2","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T23:22:21.89716-08:00","created_by":"daemon"}]}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T00:10:44.915982-08:00","updated_at":"2025-12-16T17:26:30.080125-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-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-ct0u","title":"Merge: gt-3x1.4","description":"branch: polecat/Nux\ntarget: main\nsource_issue: gt-3x1.4\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:53.140259-08:00","updated_at":"2025-12-19T18:26:14.104002-08:00","closed_at":"2025-12-19T17:49:09.234713-08:00"}
{"id":"gt-u1j.11","title":"CLI: session commands (start, stop, at, list, capture, inject)","description":"Session management CLI commands.\n\n## Commands\n\n### gt session start\nStart a polecat session.\n```\ngt session start \u003crig\u003e/\u003cpolecat\u003e [--issue \u003cid\u003e]\n```\n- Creates tmux session\n- Launches claude in polecat workdir\n- Optionally injects initial issue context\n\n### gt session stop\nStop a polecat session.\n```\ngt session stop \u003crig\u003e/\u003cpolecat\u003e [--force]\n```\n- Graceful shutdown by default\n- --force kills immediately\n\n### gt session at (attach)\nAttach to running session.\n```\ngt session at \u003crig\u003e/\u003cpolecat\u003e\n```\n- Attaches tmux session to current terminal\n- Detach with Ctrl-B D\n\n### gt session list\nList all sessions.\n```\ngt session list [--rig \u003crig\u003e] [--json]\n```\n- Shows running/stopped status\n- Optionally filter by rig\n\n### gt session capture\nCapture recent output from session.\n```\ngt session capture \u003crig\u003e/\u003cpolecat\u003e [--lines \u003cn\u003e]\n```\n- Default: last 100 lines\n- Useful for checking polecat progress\n\n### gt session inject\nSend message to session.\n```\ngt session inject \u003crig\u003e/\u003cpolecat\u003e -m \"message\"\ngt session inject \u003crig\u003e/\u003cpolecat\u003e -f \u003cfile\u003e\n```\n- Injects text via tmux send-keys\n- Used for nudges, notifications\n\n## Address Format\n\n`\u003crig\u003e/\u003cpolecat\u003e` e.g., `wyvern/Toast`\n\n## Implementation\n\nSession subcommand group:\n```go\nvar sessionCmd = \u0026cobra.Command{Use: \"session\"}\nsessionCmd.AddCommand(startCmd, stopCmd, atCmd, listCmd, captureCmd, injectCmd)\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:40.70671-08:00","updated_at":"2025-12-16T13:51:44.7613-08:00","closed_at":"2025-12-16T13:51:44.7613-08:00","dependencies":[{"issue_id":"gt-u1j.11","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T17:14:06.23195-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.11","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:40.707072-08:00","created_by":"daemon"}]}
{"id":"gt-7ik","title":"Ephemeral polecats: spawn fresh, delete on completion","description":"## Design Decision\n\nSwitch from pooled/idle polecats to ephemeral model:\n- Spawn creates fresh worktree from main\n- Polecat requests shutdown when done (bottom-up)\n- Witness verifies handoff, kills session, deletes worktree\n- No 'idle' state - polecats exist only while working\n\n## Rationale\n\n1. **Git worktrees are fast** - pooling optimization is obsolete\n2. **Pooling creates maintenance burden:**\n - Git stashes accumulate\n - Untracked artifacts pile up\n - Branches drift from main\n - Beads DB gets stale\n3. **PGT sync problems** came from persistent branches\n4. **Support infrastructure exists** - Witness, Refinery, Mayor handle continuity\n5. **Simpler mental model** - polecat exists = work in progress\n\n## Lifecycle\n\n```\nSpawn:\n gt spawn --issue \u003cid\u003e\n → Creates fresh worktree: git worktree add polecats/\u003cname\u003e -b polecat/\u003cname\u003e\n → Initializes beads in worktree\n → Starts session, assigns work\n\nWorking:\n Polecat does task\n → Pushes to polecat/\u003cname\u003e branch\n → Submits to merge queue when ready\n\nCompletion (POLECAT-INITIATED):\n Polecat runs: gt handoff\n → Verifies git state clean\n → Sends mail to Witness: \"Ready for shutdown\"\n → Marks itself done, waits for termination\n\nCleanup (WITNESS-OWNED):\n Witness receives shutdown request\n → Verifies PR merged or in queue\n → Verifies no uncommitted changes\n → Kills session: gt session stop \u003crig\u003e/\u003cpolecat\u003e\n → Deletes worktree: git worktree remove polecats/\u003cname\u003e\n → Deletes branch: git branch -d polecat/\u003cname\u003e\n → Optionally: Notifies Mayor of completion\n```\n\n## Key Insight: Bottom-Up Shutdown\n\n**Old model (wrong)**: Top-down batch shutdown - \"cancel the swarm\"\n**New model (right)**: Bottom-up individual shutdown - polecat requests, Witness executes\n\nThis enables streaming:\n- Workers come and go continuously\n- No \"swarm end\" to trigger cleanup\n- Each worker manages its own lifecycle\n- Witness is the lifecycle authority\n\n## Implementation\n\n1. Add `gt handoff` command for polecats to request shutdown\n2. Modify gt spawn to always create fresh worktree\n3. Run bd init in new worktree (beads needs initialization)\n4. Add shutdown request handler to Witness\n5. Witness verifies handoff, then cleans up:\n - Kill session\n - Remove worktree\n - Delete branch\n6. Remove 'idle' state from polecat state machine\n7. Simplify gt polecat list (only shows active)\n\n## Impact on Other Tasks\n\n- gt-17r (Zombie cleanup): Becomes trivial - orphan worktrees\n- gt-4my (Worker health): Simpler - no idle/stuck ambiguity\n- gt-f9x.5/f9x.6 (Doctor): Fewer states to validate\n- gt-eu9 (Witness handoff): Witness receives polecat shutdown requests","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-17T15:44:31.139964-08:00","updated_at":"2025-12-19T12:56:15.203738-08:00","closed_at":"2025-12-19T01:57:17.033547-08:00"}
{"id":"gt-beqp","title":"Merge: gt-72so","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-72so\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T16:19:11.814962-08:00","updated_at":"2025-12-19T18:26:14.103556-08:00","closed_at":"2025-12-19T17:47:03.61793-08:00"}
{"id":"gt-85a","title":"gt spawn: Not injecting work instructions to session","description":"gt spawn starts session but doesn't inject the issue assignment.\n\nRepro:\n1. gt spawn gastown/Toast --issue gt-2ux\n2. Session starts but polecat just sees Claude prompt\n3. No issue context injected\n\nExpected: Polecat should receive issue details automatically.\nActual: Polecat sits at blank prompt, needs manual injection.","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:28:02.583003-08:00","updated_at":"2025-12-17T22:31:58.847834-08:00","closed_at":"2025-12-17T22:31:58.847834-08:00"}
{"id":"gt-b3p","title":"Resource Beads: Leases, locks, and quotas","description":"Resource beads represent reserved resources. Types: vm, lock, slot, quota. Fields: holder, expires, renewable. Daemon monitors for expiry and manages contention.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:08:12.745602-08:00","updated_at":"2025-12-18T18:08:12.745602-08:00"}
{"id":"gt-5af.4","title":"Simplify Go daemon to Deacon-watcher","description":"Refactor internal/daemon to only: (1) check deacon/heartbeat.json every 60s, (2) poke gt-deacon if stale, (3) restart Deacon and mail for help if very stale. Remove all lifecycle processing and agent poking.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:40.493425-08:00","updated_at":"2025-12-19T17:22:52.556187-08:00","dependencies":[{"issue_id":"gt-5af.4","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:40.495569-08:00","created_by":"daemon"},{"issue_id":"gt-5af.4","depends_on_id":"gt-5af.6","type":"blocks","created_at":"2025-12-19T17:15:11.010382-08:00","created_by":"daemon"},{"issue_id":"gt-5af.4","depends_on_id":"gt-5af.2","type":"blocks","created_at":"2025-12-19T17:15:11.158303-08:00","created_by":"daemon"}]}
{"id":"gt-56fv","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:36:24.884931-08:00","updated_at":"2025-12-19T17:42:38.560305-08:00","closed_at":"2025-12-19T17:42:38.560305-08:00"}
{"id":"gt-u1j.3","title":"Git wrapper: shell out to git","description":"Wrapper for git operations via subprocess.\n\n## Interface\n\n```go\ntype Git struct {\n workDir string\n}\n\nfunc NewGit(workDir string) *Git\n\n// Core operations\nfunc (g *Git) Clone(url, dest string) error\nfunc (g *Git) Checkout(ref string) error\nfunc (g *Git) Fetch(remote string) error\nfunc (g *Git) Pull(remote, branch string) error\nfunc (g *Git) Push(remote, branch string, force bool) error\n\n// Commit operations\nfunc (g *Git) Add(paths ...string) error\nfunc (g *Git) Commit(message string) error\nfunc (g *Git) CommitAll(message string) error\n\n// Query operations\nfunc (g *Git) Status() (*GitStatus, error)\nfunc (g *Git) CurrentBranch() (string, error)\nfunc (g *Git) HasUncommittedChanges() (bool, error)\nfunc (g *Git) RemoteURL(remote string) (string, error)\n\n// Merge operations\nfunc (g *Git) Merge(branch string) error\nfunc (g *Git) Rebase(onto string) error\nfunc (g *Git) AbortMerge() error\nfunc (g *Git) AbortRebase() error\n```\n\n## Implementation\n\nShell out to git binary via exec.Command. Parse output where needed (Status, CurrentBranch).\n\n## Error Handling\n\n- Wrap git stderr in error messages\n- Detect specific failures (merge conflict, auth failure, not a repo)\n- Return structured errors for callers to handle\n\n## Testing\n\n- Use temp directories with real git repos\n- Test both success and failure paths","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:11.907807-08:00","updated_at":"2025-12-16T13:27:03.639659-08:00","closed_at":"2025-12-16T13:27:03.639659-08:00","dependencies":[{"issue_id":"gt-u1j.3","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:13:47.220423-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.3","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:11.908262-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.7","title":"CloudRun protocol types: WorkRequest, WorkEvent, WorkResult","description":"## Overview\n\nHTTP protocol types for Cloud Run work dispatch. **Types only** - server and client are separate tasks.\n\n## Request Type\n\n```go\ntype WorkRequest struct {\n IssueID string `json:\"issue_id\"`\n Rig RigConfig `json:\"rig\"`\n Beads BeadsConfig `json:\"beads\"`\n Branch string `json:\"worker_branch\"`\n Context map[string]any `json:\"context,omitempty\"`\n}\n\ntype RigConfig struct {\n URL string `json:\"url\"`\n Branch string `json:\"branch\"`\n}\n\ntype BeadsConfig struct {\n URL string `json:\"url\"`\n Branch string `json:\"branch\"`\n}\n```\n\n## Response Types (streaming NDJSON)\n\n```go\ntype WorkEvent struct {\n Type string `json:\"type\"` // status, log, progress, result, error\n Status string `json:\"status,omitempty\"`\n Line string `json:\"line,omitempty\"`\n Percent int `json:\"percent,omitempty\"`\n Branch string `json:\"branch,omitempty\"`\n PRURL string `json:\"pr_url,omitempty\"`\n Code string `json:\"code,omitempty\"`\n Message string `json:\"message,omitempty\"`\n}\n\ntype WorkResult struct {\n Status string `json:\"status\"` // done, failed\n Branch string `json:\"branch\"`\n PRURL string `json:\"pr_url,omitempty\"`\n Error string `json:\"error,omitempty\"`\n}\n```\n\n## Files\n\n- `internal/cloudrun/protocol.go` - All types above\n\n## Notes\n\nThis is just types. Server (gt-9a2.7b) and client (gt-9a2.7c) are separate tasks.\nSmall, focused task - can complete quickly.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:51.480019-08:00","updated_at":"2025-12-16T18:14:49.196218-08:00","dependencies":[{"issue_id":"gt-9a2.7","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.984572-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.7","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:51.48197-08:00","created_by":"daemon"}]}
{"id":"gt-0pl","title":"Polecat CLAUDE.md: configure auto-approve for bd and gt commands","description":"Polecats get stuck waiting for bash command approval when running\nbd and gt commands. Need to configure Claude Code to auto-approve these.\n\nOptions:\n1. Add allowedTools to polecat CLAUDE.md\n2. Configure .claude/settings.json in polecat directory\n3. Use --dangerously-skip-permissions flag (not recommended)\n\nShould auto-approve:\n- bd (beads commands)\n- gt (gastown commands)\n- go build/test\n- git status/add/commit/push\n\nShould still require approval:\n- rm -rf\n- Arbitrary commands outside project\n\nRelated to polecat prompting (gt-e1y, gt-sd6).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T14:10:27.611612-08:00","updated_at":"2025-12-17T14:22:00.715979-08:00","closed_at":"2025-12-17T14:22:00.715979-08:00"}
{"id":"gt-6z2.1","title":"Test Task 1: Add comment to gt.go","status":"closed","issue_type":"task","created_at":"2025-12-16T21:57:43.554166-08:00","updated_at":"2025-12-16T22:06:41.126547-08:00","closed_at":"2025-12-16T22:06:41.126547-08:00","dependencies":[{"issue_id":"gt-6z2.1","depends_on_id":"gt-6z2","type":"parent-child","created_at":"2025-12-16T21:57:43.55748-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":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:06.543281-08:00","updated_at":"2025-12-15T21:18:54.012863-08:00","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-l6r9","title":"Test molecule","description":"Test","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T14:29:43.985973-08:00","updated_at":"2025-12-19T14:30:00.084138-08:00","closed_at":"2025-12-19T14:30:00.084138-08:00"}
{"id":"gt-w3bu","title":"gt spawn: Enter key needs debounce delay after paste","description":"## Problem\n\nWhen spawning polecats via `gt spawn`, instructions are pasted into tmux but workers often sit idle at prompt because the Enter key arrives before the paste is fully processed.\n\n## Observed Behavior\n\n- Instructions pasted via tmux send-keys\n- Enter key sent immediately after\n- Worker session shows prompt with no input (paste not submitted)\n- Requires manual intervention to nudge workers\n\n## Expected Behavior\n\n- Paste completes fully\n- Enter key submits the pasted instructions\n- Worker begins executing immediately\n\n## Root Cause\n\nLikely a race condition between paste buffer processing and keypress handling. Need either:\n1. Debounce delay before sending Enter\n2. Longer delay (Tmax) to ensure paste completes\n3. Alternative submission mechanism\n\n## Impact\n\n- Swarm of 10 workers had multiple stalls at startup\n- Required manual tmux send-keys to unstick them\n- Defeats purpose of automated spawning\n\n## References\n\n- Observed during Mad Max swarm (Dec 18, 2025)\n- Affects gt spawn command in internal/cmd/spawn.go","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:06:50.734123-08:00","updated_at":"2025-12-18T21:08:22.400899-08:00","closed_at":"2025-12-18T21:08:22.400899-08:00"}
{"id":"gt-u1j.19","title":"CLI: spawn command","description":"High-level command to spawn a polecat with work assignment.\n\n## Command\n\n```\ngt spawn \u003crig\u003e/\u003cpolecat\u003e --issue \u003cid\u003e\ngt spawn \u003crig\u003e --issue \u003cid\u003e # auto-select available polecat\ngt spawn \u003crig\u003e/\u003cpolecat\u003e -m \"Work on X\" # free-form task\n```\n\n## What It Does\n\n1. Select or create polecat\n2. Ensure polecat is in idle/active state\n3. Assign the issue (update beads, set polecat state)\n4. Start session (gt session start)\n5. Inject initial context\n\n## Options\n\n- `--issue \u003cid\u003e`: Beads issue to assign\n- `-m \"message\"`: Free-form work description\n- `--create`: Create polecat if it does not exist\n- `--no-start`: Assign work but do not start session\n\n## Auto-Select Logic\n\nIf polecat not specified:\n1. Look for idle polecats in rig\n2. Prefer ones that worked on similar issues before\n3. If none available, fail (or create if --create)\n\n## Initial Context\n\nInjects into session:\n```\n[SPAWN] You have been assigned: \u003cissue-title\u003e\nIssue: \u003cid\u003e\nPriority: \u003cpriority\u003e\n\n\u003cdescription\u003e\n\nWork on this issue. Signal DONE when complete.\n```\n\n## Implementation\n\nOrchestrates PolecatManager + SessionManager + Beads:\n```go\nfunc Spawn(rig, polecat, issue string, opts SpawnOptions) error\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:13:16.676891-08:00","updated_at":"2025-12-16T14:13:52.489435-08:00","closed_at":"2025-12-16T14:13:52.489435-08:00","dependencies":[{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T17:14:09.821801-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:16.677248-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:09.726436-08:00","created_by":"daemon"}]}
{"id":"gt-5af.3","title":"Add deacon/ mail identity support","description":"Ensure deacon/ works as a mail identity in town-level beads. Test with bd mail send deacon/ and bd mail inbox --identity deacon/.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:32.618418-08:00","updated_at":"2025-12-19T17:26:46.504422-08:00","closed_at":"2025-12-19T17:26:46.504422-08:00","dependencies":[{"issue_id":"gt-5af.3","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:32.620414-08:00","created_by":"daemon"}]}
{"id":"gt-hcc0","title":"gt polecat remove --all: bulk polecat teardown","description":"Currently gt polecat remove only accepts one polecat at a time. Need bulk operations:\n\n## Requested\n- `gt polecat remove gastown --all` - remove all polecats from a rig\n- `gt polecat remove gastown/A gastown/B ...` - remove multiple by name\n\n## Context\nAfter a swarm completes, tearing down 20 polecats one at a time is tedious.\nEphemeral workers should be easy to create and destroy in bulk.\n\n## Related\n- gt-c92: CLI: all command for batch polecat operations","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-19T14:06:43.892225-08:00","updated_at":"2025-12-19T14:06:43.892225-08:00"}
{"id":"gt-u1j.12","title":"CLI: mail commands (send, inbox, read)","description":"CLI: mail commands wrapping bd mail.\n\n## Status\n\nCurrent implementation works with JSONL files. Refactor to wrap bd mail CLI.\n\n## Commands\n\n### gt mail inbox\n```\ngt mail inbox [--unread] [--json]\n```\nWraps: `bd mail inbox [--json]`\n\n### gt mail read\n```\ngt mail read \u003cid\u003e\n```\nWraps: `bd mail read \u003cid\u003e \u0026\u0026 bd mail ack \u003cid\u003e`\nNote: bd mail read + ack marks as read.\n\n### gt mail send\n```\ngt mail send \u003caddress\u003e -s \"Subject\" -m \"Body\" [--notify]\n```\nWraps: `bd mail send \u003crecipient\u003e -s \"Subject\" -m \"Body\"`\nIf --notify: inject tmux notification after send.\n\n### gt mail delete\n```\ngt mail delete \u003cid\u003e\n```\nWraps: `bd mail ack \u003cid\u003e` (closes the message issue)\n\n## Address Translation\n\nSame as gt-u1j.6:\n- `mayor/` → `mayor`\n- `\u003crig\u003e/refinery` → `\u003crig\u003e-refinery`\n- `\u003crig\u003e/\u003cpolecat\u003e` → `\u003crig\u003e-\u003cpolecat\u003e`\n\n## Dependencies\n\n- gt-u1j.6: Mail system backend","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:42.038558-08:00","updated_at":"2025-12-16T21:45:22.218817-08:00","closed_at":"2025-12-16T21:45:22.218817-08:00","dependencies":[{"issue_id":"gt-u1j.12","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:42.038885-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.12","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T17:14:06.328188-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.12","depends_on_id":"gt-r01","type":"blocks","created_at":"2025-12-16T13:12:08.639736-08:00","created_by":"daemon"}]}
{"id":"gt-sqi","title":"gt session restart/status: Complete session management","description":"Add missing session subcommands:\n\n- gt session restart \u003crig\u003e \u003cpolecat\u003e - Restart a session (stop + start)\n- gt session status \u003crig\u003e \u003cpolecat\u003e - Show session status details\n\nstatus should show:\n- Running state\n- Uptime\n- Current activity\n- Last output timestamp","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:47:34.700494-08:00","updated_at":"2025-12-19T12:56:15.214592-08:00","closed_at":"2025-12-19T12:05:27.344257-08:00","dependencies":[{"issue_id":"gt-sqi","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.034222-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-yls","title":"Document merge queue architecture","description":"Update docs/architecture.md with:\n\n- Merge Queue section explaining Beads-native approach\n- Engineer role (renamed from Refinery)\n- Session restart protocol\n- gt mq command reference\n- Federation considerations for queue\n\nAlso update any references to .gastown/ → config/.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T23:02:41.533065-08:00","updated_at":"2025-12-17T13:43:41.657433-08:00","closed_at":"2025-12-17T13:43:41.657433-08:00","dependencies":[{"issue_id":"gt-yls","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:56.043373-08:00","created_by":"daemon"}]}
{"id":"gt-qn4l","title":"bd create should support molecule type","description":"gt molecule commands expect type=molecule but bd validates against bug|feature|task|epic|chore|merge-request only","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-19T18:25:31.591953-08:00","updated_at":"2025-12-19T18:25:31.591953-08:00"}
{"id":"gt-35s","title":"Architecture: beads config and direct landing docs","description":"Added to architecture.md:\n- Beads multi-agent configuration table (daemon, worktree, sync-branch)\n- ASCII directory layout for non-mermaid rendering\n- Direct landing workflow (bypass merge queue)\n- Design decisions 9 and 10 for direct landing and daemon awareness\n- CLI commands for gt land","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T00:29:52.395906-08:00","updated_at":"2025-12-16T00:29:59.188921-08:00","closed_at":"2025-12-16T00:29:59.188921-08:00"}
{"id":"gt-y2p6","title":"Merge: gt-3x1.5","description":"branch: polecat/Immortan\ntarget: main\nsource_issue: gt-3x1.5\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:53.544887-08:00","updated_at":"2025-12-19T18:26:14.106598-08:00","closed_at":"2025-12-19T17:49:09.215705-08:00"}
{"id":"gt-cxx","title":"Swarm learning: Witness needs automated context cycling","description":"Furiosa hit 2% context during swarm work. Witness role needs automated detection of low context and should trigger session cycling before agents get stuck. Add to Witness responsibilities in prompts.md.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:21:49.67756-08:00","updated_at":"2025-12-16T01:51:39.2553-08:00","closed_at":"2025-12-16T01:51:39.2553-08:00"}
{"id":"gt-d3d","title":"Design: Additional design issues (placeholder)","description":"Placeholder for additional design issues the user wants to raise and work through. Convert to specific subtasks as issues are identified.","status":"open","priority":4,"issue_type":"epic","created_at":"2025-12-15T20:24:12.601585-08:00","updated_at":"2025-12-15T23:17:32.467687-08:00"}
{"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-kp2","title":"Add merge-request type to Beads schema","description":"Define the merge-request bead type with fields:\n- branch: source branch (e.g., polecat/Nux/gt-xxx)\n- target_branch: destination (main or integration/xxx)\n- source_issue: the work being merged (gt-xxx)\n- worker: who did the work\n- rig: which rig\n- merge_commit: (filled on close) SHA of merge commit\n- close_reason: (filled on close) success/failure details\n\nThis may require beads schema changes or just convention.","status":"closed","issue_type":"task","created_at":"2025-12-16T23:02:14.471248-08:00","updated_at":"2025-12-19T12:56:15.213256-08:00","closed_at":"2025-12-18T20:09:04.684996-08:00","dependencies":[{"issue_id":"gt-kp2","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.338148-08:00","created_by":"daemon"}]}
{"id":"gt-2p2","title":"Test message","description":"Testing GGT mail integration","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-17T14:04:50.045948-08:00","updated_at":"2025-12-17T14:05:03.125655-08:00","closed_at":"2025-12-17T14:05:03.125655-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:30.716666-08:00","updated_at":"2025-12-17T13:52:30.716666-08:00","dependencies":[{"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"},{"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"}]}
{"id":"gt-u1j.13","title":"Beads CLI wrapper: shell out to bd","description":"Wrapper for bd (beads CLI) commands.\n\n## Interface\n\n```go\ntype Beads struct {\n workDir string\n}\n\nfunc NewBeads(workDir string) *Beads\n\n// Query\nfunc (b *Beads) List(opts ListOptions) ([]*Issue, error)\nfunc (b *Beads) Ready() ([]*Issue, error)\nfunc (b *Beads) Show(id string) (*Issue, error)\nfunc (b *Beads) Blocked() ([]*Issue, error)\n\n// Mutations\nfunc (b *Beads) Create(opts CreateOptions) (*Issue, error)\nfunc (b *Beads) Update(id string, opts UpdateOptions) error\nfunc (b *Beads) Close(ids ...string) error\n\n// Sync\nfunc (b *Beads) Sync() error\nfunc (b *Beads) SyncStatus() (*SyncStatus, error)\n```\n\n## Data Types\n\n```go\ntype Issue struct {\n ID string\n Title string\n Status string\n Priority int\n Type string\n Description string\n Parent string\n Children []string\n DependsOn []string\n Blocks []string\n}\n\ntype ListOptions struct {\n Status string // \"open\", \"closed\", \"all\"\n Type string\n Priority int\n}\n\ntype CreateOptions struct {\n Title string\n Type string\n Priority int\n Description string\n Parent string\n}\n```\n\n## Implementation\n\nShell out to bd binary, parse JSON output where available.\n```go\nfunc (b *Beads) runBd(args ...string) ([]byte, error) {\n cmd := exec.Command(\"bd\", args...)\n cmd.Dir = b.workDir\n return cmd.Output()\n}\n```\n\n## Error Handling\n\n- bd not installed: Clear error with install instructions\n- Not a beads repo: Detect and report\n- Sync conflicts: Parse and report","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-15T17:12:55.926393-08:00","updated_at":"2025-12-17T14:33:08.059329-08:00","dependencies":[{"issue_id":"gt-u1j.13","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:55.926744-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.13","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.168049-08:00","created_by":"daemon"}]}
{"id":"gt-82y","title":"Design: Swarm shutdown and worker cleanup","description":"Design for graceful swarm shutdown, worker cleanup, and session cycling.\n\n## Key Decisions\n\n1. Pre-kill verification uses model intelligence (not framework rules)\n2. Witness can request restart when context filling (mail self, exit)\n3. Mayor NOT involved in per-worker cleanup (Witness responsibility)\n4. Clear responsibility boundaries between Mayor/Witness/Polecat\n\n## Subtasks (implementation)\n\n- gt-sd6: Polecat decommission checklist prompting\n- gt-f8v: Witness pre-kill verification protocol\n- gt-eu9: Witness session cycling and handoff\n- gt-gl2: Mayor vs Witness cleanup responsibilities\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T19:47:44.936374-08:00","updated_at":"2025-12-15T20:49:22.849598-08:00","closed_at":"2025-12-15T20:12:05.441911-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-19T17:47:03.616174-08:00","closed_at":"2025-12-19T17:47:03.616174-08:00"}
{"id":"gt-svi.2","title":"gt mq list: show queue with status/priority/age","description":"Implement 'gt mq list' command to display the merge queue.\n\nOutput format:\nID STATUS PRIORITY BRANCH WORKER AGE\ngt-mr-001 ready P0 polecat/Nux/gt-xyz Nux 5m\ngt-mr-002 in_progress P1 polecat/Toast/gt-abc Toast 12m\ngt-mr-003 blocked P1 polecat/Capable/gt-def Capable 8m\n (waiting on gt-mr-001)\n\nOptions:\n- --ready: show only ready-to-merge (no blockers, not in progress)\n- --status STATUS: filter by status\n- --worker WORKER: filter by worker\n- --epic EPIC: show MRs targeting integration/EPIC\n\nUnder the hood: bd list --type=merge-request with filters.\n\nReference: docs/merge-queue-design.md#gt-mq-list","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:23.295587-08:00","updated_at":"2025-12-19T12:56:15.215956-08:00","closed_at":"2025-12-18T20:22:41.489063-08:00","dependencies":[{"issue_id":"gt-svi.2","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:23.297307-08:00","created_by":"daemon"},{"issue_id":"gt-svi.2","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.560128-08:00","created_by":"daemon"}]}
{"id":"gt-g44u.4","title":"Step recovery: timeout and release","description":"Implement recovery mechanism for stuck molecule steps.\n\n## Problem\nWhen a worker dies mid-step, the step stays in_progress forever.\nNeed timeout/release mechanism for nondeterministic idempotence.\n\n## Solution\n1. Track step start time (claimed_at timestamp)\n2. Timeout: After 30 min in_progress, step returns to pending\n3. Manual release: bd release \u003cstep-id\u003e\n\n## Implementation Options\n\n### Option A: Beads-level timeout\n- Add claimed_at field to issues\n- bd ready excludes items in_progress \u003c 30 min\n- bd ready includes items in_progress \u003e 30 min (auto-recovery)\n\n### Option B: Daemon-level timeout \n- Daemon watches in_progress items\n- Moves back to pending after timeout\n\n### Option C: Manual only (MVP)\n- bd release \u003cid\u003e manually moves in_progress → pending\n- Document recovery procedure\n- Witness can automate for polecats\n\n## Recommendation\nStart with Option C (manual) for Christmas. Add Option A later.\n\n## Acceptance\n- [ ] bd release command works\n- [ ] Stuck steps can be recovered\n- [ ] Documented recovery procedure","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T15:50:15.072833-08:00","updated_at":"2025-12-19T16:16:32.325856-08:00","closed_at":"2025-12-19T16:16:32.325856-08:00","dependencies":[{"issue_id":"gt-g44u.4","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:15.07451-08:00","created_by":"daemon"}]}
{"id":"gt-4my","title":"Doctor check: Worker health and stuck detection","description":"Detect and report stuck workers via gt doctor.\n\n## Checks\n\n### WorkerHealthCheck\n- List all active workers (polecats with state=working)\n- Check last activity timestamp for each\n- Flag as potentially stuck if no progress for configurable threshold (default: 30 min)\n- Check if Witness is running for the rig\n- Verify Witness last heartbeat time\n\n### Stuck Detection Criteria\n- Polecat state=working but session not running\n- Polecat state=working but output unchanged for threshold\n- Witness not responding to health checks\n- Multiple polecats in same rig all stuck\n\n## Output\n\n```\n[WARN] Workers in rig 'wyvern' may be stuck:\n - Toast: working for 45m, no recent output\n - Capable: working for 52m, session not found\n - Witness: last heartbeat 20m ago\n \n Suggestions:\n - gt witness status wyvern\n - gt capture wyvern/Toast 50\n - gt stop --rig wyvern (kill all)\n```\n\n## Auto-Fix\n\nCannot auto-fix stuck workers (risk of data loss), but can:\n- Restart Witness daemon if crashed\n- Send warning mail to Mayor","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:17:59.265062-08:00","updated_at":"2025-12-16T17:24:34.882466-08:00","dependencies":[{"issue_id":"gt-4my","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T23:19:05.565606-08:00","created_by":"daemon"},{"issue_id":"gt-4my","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-17T15:44:42.068149-08:00","created_by":"daemon"}]}
{"id":"gt-e76","title":"gt mail reply/thread: Conversation support","description":"Add mail conversation features:\n\n- gt mail reply \u003cid\u003e -m 'message' - Reply to a message\n- gt mail thread \u003cid\u003e - Show all messages in a thread\n\nEnables back-and-forth communication between agents.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:50:06.215773-08:00","updated_at":"2025-12-19T12:56:15.207793-08:00","closed_at":"2025-12-19T12:05:27.342212-08:00","dependencies":[{"issue_id":"gt-e76","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.106435-08:00","created_by":"daemon"}]}
{"id":"gt-wpg","title":"Replaceable notifications via Claude Code queue","description":"Leverage Claude Code's ability to replace queued text for notifications that supersede previous ones.\n\n## Problem\n\nIf daemon sends 10 heartbeats while agent is busy, agent returns to see 10 stacked messages. Wasteful and noisy.\n\n## Solution\n\nUse Claude Code's queue replacement for:\n- Heartbeat messages (only latest matters)\n- Status updates that supersede previous\n- Progress notifications\n\n## Implementation\n\nNotifications get a 'slot' identifier. New notification in same slot replaces old one:\n- Slot: 'heartbeat' → only one heartbeat queued at a time\n- Slot: 'status-\u003crig\u003e' → latest status per rig\n- No slot → stacks normally (for unique messages)\n\n## Research Needed\n\n- How does Claude Code expose queue replacement?\n- tmux send-keys behavior with pending input\n- Alternative: clear + resend pattern","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:29.821949-08:00","updated_at":"2025-12-18T14:19:29.821949-08:00","dependencies":[{"issue_id":"gt-wpg","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.656972-08:00","created_by":"daemon"}]}
{"id":"gt-shnp","title":"Create Refinery role template","description":"Add Refinery template to internal/templates/roles/:\n- refinery.md.tmpl with full role context\n- Variables: rig name, working directory, handoff bead ID\n- Update SeedRoleTemplates to include it\n- gt prime uses this template for Refinery context","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:28.951284-08:00","updated_at":"2025-12-19T18:09:28.951284-08:00","dependencies":[{"issue_id":"gt-shnp","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.706849-08:00","created_by":"daemon"}]}
{"id":"gt-y0t","title":"session stop: --force flag is defined but not used","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-16T13:55:12.848848-08:00","updated_at":"2025-12-16T13:56:39.09003-08:00","closed_at":"2025-12-16T13:56:39.09003-08:00"}
{"id":"gt-9a2.3","title":"Outpost configuration: YAML config and OutpostManager","description":"## Overview\n\nConfiguration file for outposts and manager to load/track them.\n\n## Config File\n\n`~/ai/config/outposts.yaml`:\n\n```yaml\noutposts:\n - name: local\n type: local\n max_workers: 4\n\n - name: gce-burst\n type: ssh\n host: 10.0.0.5\n user: steve\n ssh_key: ~/.ssh/gce_worker\n town_path: /home/steve/ai\n max_workers: 8\n\n - name: cloudrun-burst\n type: cloudrun\n project: my-gcp-project\n region: us-central1\n service: gastown-worker\n max_workers: 20\n cost_cap_hourly: 5.00\n\npolicy:\n default_preference: [local, gce-burst, cloudrun-burst]\n overrides:\n - condition: \"priority \u003e= P3\"\n prefer: cloudrun-burst\n```\n\n## OutpostManager\n\n```go\ntype OutpostManager struct {\n outposts map[string]Outpost\n policy AssignmentPolicy\n}\n\nfunc NewOutpostManager(configPath string) (*OutpostManager, error)\nfunc (m *OutpostManager) Get(name string) (Outpost, bool)\nfunc (m *OutpostManager) List() []Outpost\nfunc (m *OutpostManager) SelectOutpost(issue Issue) Outpost\n```\n\n## Files\n\n- `internal/outpost/manager.go`\n- `internal/outpost/config.go` (extend)\n- `internal/outpost/policy.go`\n\nDepends on: gt-9a2.1 (interfaces)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:01.595784-08:00","updated_at":"2025-12-16T18:02:01.595784-08:00","dependencies":[{"issue_id":"gt-9a2.3","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.448178-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.3","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:01.598029-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.3","title":"MR state transitions: validate open→in_progress→closed","description":"Enforce valid state transitions for merge-requests:\n\nValid transitions:\n- open → in_progress (Engineer claims MR)\n- in_progress → closed (merge success or rejection)\n- in_progress → open (failure, reassign to worker)\n- open → closed (manual rejection)\n\nInvalid:\n- closed → anything (immutable once closed)\n\nImplement validation in MR update operations.\n\nReference: docs/merge-queue-design.md#state-machine","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:00.417825-08:00","updated_at":"2025-12-19T12:56:15.209219-08:00","closed_at":"2025-12-18T20:00:58.572216-08:00","dependencies":[{"issue_id":"gt-h5n.3","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:50:00.419924-08:00","created_by":"daemon"}]}
{"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-l4gm","title":"Crew workers: design documentation and remaining work","description":"## Summary\n\nCrew workers are user-managed persistent workspaces within a rig, distinct from polecats.\n\n## Current Implementation\n\n### Commands (all working)\n- `gt crew add \u003cname\u003e` - Create workspace (git clone)\n- `gt crew list` - List workspaces with status\n- `gt crew at \u003cname\u003e` - Attach to tmux session\n- `gt crew remove \u003cname\u003e` - Remove workspace\n- `gt crew pristine [\u003cname\u003e]` - git pull + bd sync\n- `gt crew refresh \u003cname\u003e` - Context cycle with handoff mail\n- `gt crew status [\u003cname\u003e]` - Detailed status\n- `gt crew rename \u003cname\u003e` - Rename workspace\n\n### Crew vs Polecat\n\n| Aspect | Crew | Polecat |\n|--------|------|---------|\n| Lifecycle | User-managed | Witness-managed |\n| Scheduling | Manual | `gt spawn` |\n| Merge flow | Direct push OK | Integration branch → refinery |\n| Garbage collection | Never | Auto on completion |\n| Identity | Long-lived (emma, dave) | Ephemeral (Nux, Toast) |\n\n## Known Bugs\n\n- **gt-70b3**: detectSender() doesn't recognize crew workers\n- **gt-vdp0**: Crew CLAUDE.md shows Refinery template\n\n## Potential Enhancements\n\n1. Rebase helper in `gt crew pristine` for conflict resolution\n2. Cross-rig crew support (crew worker in multiple rigs?)\n3. Better mail identity auto-detection for crew","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T21:49:58.524424-08:00","updated_at":"2025-12-18T21:49:58.524424-08:00"}
{"id":"gt-u1j.10","title":"CLI: core commands (status, prime, version, init)","description":"Essential CLI commands for Gas Town operation.\n\n## Commands\n\n### gt status\nShow overall town status.\n```\ngt status [--json]\n```\nOutput:\n- Town name and location\n- Number of rigs\n- Active polecats across all rigs\n- Witness status per rig\n- Recent activity summary\n\n### gt prime\nOutput role context for current directory.\n```\ngt prime\n```\nDetects role from directory:\n- Town root or mayor/ → Mayor context\n- \u003crig\u003e/witness/rig/ → Witness context\n- \u003crig\u003e/refinery/rig/ → Refinery context\n- \u003crig\u003e/polecats/\u003cname\u003e/ → Polecat context\n\n### gt version\nShow version information.\n```\ngt version [--short]\n```\nOutput: version, git commit, build date.\n\n### gt init\nInitialize current rig for Gas Town (alternative to gt install for existing repos).\n```\ngt init [--force]\n```\nCreates Gas Town structure in existing git repo.\n\n## Implementation\n\nEach command is a Cobra subcommand under root:\n```go\nvar statusCmd = \u0026cobra.Command{...}\nvar primeCmd = \u0026cobra.Command{...}\nvar versionCmd = \u0026cobra.Command{...}\nvar initCmd = \u0026cobra.Command{...}\n```\n\nRegister in cmd/gt/main.go.","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:38.367667-08:00","updated_at":"2025-12-16T13:49:54.801859-08:00","closed_at":"2025-12-16T13:49:54.801859-08:00","dependencies":[{"issue_id":"gt-u1j.10","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:38.368006-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.10","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:06.123332-08:00","created_by":"daemon"}]}
{"id":"gt-y5o","title":"Daemon: verify requesting_cycle before kill","description":"Per gt-gby spec, daemon should verify agent state shows requesting_cycle=true before killing session. Currently kills on any lifecycle request without verification.\n\nRequires state.json in agent workspace with requesting_cycle field.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:13.049988-08:00","updated_at":"2025-12-19T17:22:52.55078-08:00","closed_at":"2025-12-19T16:28:41.779271-08:00","dependencies":[{"issue_id":"gt-y5o","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.590883-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.3","title":"gt install command: Create workspace structure","description":"Create Gas Town workspace structure.\n\n## Command\n\n```\ngt install [path]\n```\n\nIf path omitted, uses current directory.\n\n## Created Structure\n\n```\n\u003cpath\u003e/\n├── config/\n│ ├── town.json # {\"type\": \"town\", \"version\": 1, ...}\n│ └── rigs.json # {\"version\": 1, \"rigs\": {}}\n│\n└── mayor/\n ├── CLAUDE.md # Mayor role prompting (from template)\n ├── mail/\n │ └── inbox.jsonl # Empty inbox\n └── state.json # Initial mayor state\n```\n\n## Implementation\n\n```go\nfunc Install(path string, opts InstallOptions) error\n\ntype InstallOptions struct {\n TownName string // defaults to directory name\n Force bool // overwrite existing\n}\n```\n\n## Steps\n\n1. Validate path (exists, writable)\n2. Check not already a town (unless --force)\n3. Create config/ directory\n4. Write town.json with name and timestamp\n5. Write empty rigs.json\n6. Create mayor/ directory structure\n7. Write CLAUDE.md from template\n8. Create empty inbox.jsonl\n9. Write initial state.json\n\n## Error Cases\n\n- Path does not exist: Create it (like mkdir -p)\n- Already a town: Error unless --force\n- Permission denied: Clear error message\n- Inside existing town: Warn (nested towns not recommended)\n\n## Templates\n\nMayor CLAUDE.md comes from embedded template (see gt-u1j.20).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:36:53.455589-08:00","updated_at":"2025-12-17T17:20:04.66874-08:00","closed_at":"2025-12-17T17:20:04.66874-08:00","dependencies":[{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:36:53.455924-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T16:37:32.513796-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x.2","type":"blocks","created_at":"2025-12-15T16:37:32.597456-08:00","created_by":"daemon"}]}
{"id":"gt-vnp9","title":"tmux notifications: display-message too subtle, use send-keys instead","description":"## Problem\n\n`tmux display-message` notifications are not visible enough - they appear briefly in the status bar and are easy to miss.\n\n## Current Behavior\n\nrouter.go uses:\n```go\nr.tmux.DisplayMessageDefault(sessionID, notification)\n```\n\n## What Works\n\nSending echo commands directly to the terminal:\n```bash\ntmux send-keys -t \u003csession\u003e \"echo '📬 NEW MAIL from mayor'\" Enter\n```\n\n## Proposed Fix\n\nChange notification method to send visible output to the terminal, perhaps with a box/banner:\n```\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n📬 NEW MAIL from mayor\nSubject: \u003csubject\u003e\nRun: bd mail inbox\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n```\n\n## Considerations\n\n- This interrupts the terminal output (acceptable for important mail)\n- Could check if Claude is mid-response and queue notification\n- Or use tmux popup if available","notes":"Additional issues:\n1. Enter key not sent properly when chained with send-keys\n2. Need to debounce and send Enter separately\n3. Correct pattern: send text, sleep briefly, then send Enter","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:35:28.542985-08:00","updated_at":"2025-12-19T12:00:29.342381-08:00","closed_at":"2025-12-19T12:00:29.342381-08:00"}
{"id":"gt-svi.4","title":"gt mq retry: retry a failed MR","description":"Implement 'gt mq retry \u003cid\u003e' to retry a failed merge request.\n\nActions:\n1. Verify MR exists and is in failed state (open with failure labels)\n2. Remove failure labels (needs-rebase, needs-fix)\n3. Reset to ready state\n4. Optionally re-run immediately (--now flag)\n\nOptions:\n- --now: immediately process (instead of waiting for Engineer loop)\n\nReference: docs/merge-queue-design.md#cli-commands","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:36.336017-08:00","updated_at":"2025-12-19T12:56:15.217204-08:00","closed_at":"2025-12-18T20:11:15.063571-08:00","dependencies":[{"issue_id":"gt-svi.4","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:36.3382-08:00","created_by":"daemon"}]}
{"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-f8v","title":"Witness pre-kill verification protocol","description":"Add pre-kill verification protocol to Witness CLAUDE.md template.\n\n## Protocol for Witness Prompting\n\n```markdown\n## Pre-Kill Verification Protocol\n\nBefore killing any worker session, verify workspace is clean.\n\n### Verification Steps\n\nWhen a worker signals done:\n\n1. **Capture worker state**:\n```bash\ntown capture \u003cpolecat\u003e \"git status \u0026\u0026 git stash list \u0026\u0026 bd sync --status\"\n```\n\n2. **Assess the output** (use your judgment):\n- Is working tree clean?\n- Is stash list empty?\n- Is beads synced?\n\n3. **Decision**:\n- **CLEAN**: Proceed to kill session\n- **DIRTY**: Send nudge with specific issues\n\n### Nudge Templates\n\n**Uncommitted Changes**:\n```\ntown inject \u003cpolecat\u003e \"WITNESS CHECK: Uncommitted changes found. Please commit or discard: \u003cfiles\u003e. Signal done when clean.\"\n```\n\n**Beads Not Synced**:\n```\ntown inject \u003cpolecat\u003e \"WITNESS CHECK: Beads not synced. Run 'bd sync' then commit. Signal done when complete.\"\n```\n\n### Kill Sequence\n\nOnly after verification passes:\n```bash\ntown kill \u003cpolecat\u003e\ntown sleep \u003cpolecat\u003e\n```\n\n### Escalation\n\nIf worker fails verification 3+ times:\n```bash\ntown mail send mayor/ -s \"Escalation: \u003cpolecat\u003e stuck\" -m \"Cannot complete cleanup after 3 attempts. Issues: \u003clist\u003e.\"\n```\n```\n\n## Implementation\n\nAdd to WITNESS_CLAUDE.md template.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:54.065679-08:00","updated_at":"2025-12-15T20:47:30.415244-08:00","dependencies":[{"issue_id":"gt-f8v","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.763378-08:00","created_by":"daemon"}]}
{"id":"gt-zko","title":"gt rig info: Show detailed rig information","description":"Add 'gt rig info \u003crig\u003e' command to show detailed rig status.\n\nShould show:\n- Rig path and git URL\n- Active polecats with status\n- Refinery status\n- Witness status\n- Recent activity\n- Beads summary (open issues count)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:17.879255-08:00","updated_at":"2025-12-17T22:29:46.970197-08:00","closed_at":"2025-12-17T22:29:46.970197-08:00","dependencies":[{"issue_id":"gt-zko","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.502099-08:00","created_by":"daemon"}]}
{"id":"gt-rm3","title":"CLI: gt refinery commands (start, stop, status, queue)","description":"CLI commands for managing the Refinery agent.\n\n## Commands\n\n```bash\ngt refinery start \u003crig\u003e # Start refinery for a rig\ngt refinery stop \u003crig\u003e # Stop refinery\ngt refinery status \u003crig\u003e # Show refinery status\ngt refinery queue \u003crig\u003e # Show merge queue\n```\n\n## gt refinery start\n\nStarts the Refinery daemon for the specified rig.\n\nOptions:\n- --foreground: Run in foreground (default: background)\n- --auto-merge: Enable auto-merge (default: from config)\n\n## gt refinery stop\n\nStops a running Refinery. Gracefully finishes current MR if processing.\n\n## gt refinery status\n\nShows:\n- Running state (running/stopped)\n- Current MR being processed (if any)\n- Queue length\n- Last merge time\n- Recent activity\n\n## gt refinery queue\n\nShows the merge queue:\n```\nMerge queue for 'wyvern':\n 1. [pending] Toast/polecat-auth-fix (15m ago)\n 2. [pending] Capable/polecat-new-feature (5m ago)\n \n1 merged today, 0 rejected\n```\n\n## Implementation\n\nUses gt-ov2 (Refinery agent) for daemon functionality.","status":"closed","issue_type":"task","created_at":"2025-12-15T23:22:24.754361-08:00","updated_at":"2025-12-16T14:16:34.593637-08:00","closed_at":"2025-12-16T14:16:34.593637-08:00","dependencies":[{"issue_id":"gt-rm3","depends_on_id":"gt-ov2","type":"blocks","created_at":"2025-12-15T23:22:30.679909-08:00","created_by":"daemon"}]}
{"id":"gt-6k8","title":"Interrupt vs Queue mail semantics","description":"Add priority/delivery semantics to mail messages.\n\n## Semantics\n\n| Type | Delivery | Use Case |\n|------|----------|----------|\n| Interrupt | tmux send-keys | Lifecycle, URGENT, stuck detection |\n| Queue | Create message only | Normal mail, status, heartbeat |\n\n## Implementation\n\n- `bd mail send --interrupt` uses tmux send-keys notification\n- Default is queue (agent checks with `gt mail check`)\n- Urgent flag on messages for interrupt delivery\n\n## Agent Side\n\n- `gt mail check --quiet` - non-blocking check for queued mail\n- `gt mail wait` - block until mail arrives (for idle agents)\n- Heartbeats become queued, agent checks at natural breakpoints","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:28.408196-08:00","updated_at":"2025-12-19T17:22:52.555329-08:00","closed_at":"2025-12-19T16:31:00.450061-08:00","dependencies":[{"issue_id":"gt-6k8","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.529252-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.11","title":"Daemon heartbeat: worker and queue monitoring","description":"Daemon periodic checks for work progress.\n\n## Heartbeat Actions\n\nEvery N seconds (configurable):\n\n1. Check Witness health per rig\n - Poke if witness needs to nudge workers\n \n2. Check Refinery queue per rig\n - Poke if pending work in queue\n \n3. Check work completion\n - If epic children all closed, notify Mayor\n\n## Eventually Convergent\n\nMultiple signals reinforce state:\n- Polecat signals done → Witness notices → pokes Refinery\n- Daemon heartbeat → checks queue → pokes Refinery\n- Beads status → queryable by any agent\n\nEven if one signal missed, system converges.\n\n## Interface\n\n```go\nfunc (d *Daemon) HeartbeatLoop() {\n for {\n for _, rig := range d.rigs {\n d.CheckWitness(rig)\n d.CheckRefinery(rig)\n d.CheckWorkProgress(rig)\n }\n time.Sleep(d.config.HeartbeatInterval)\n }\n}\n```\n\n## Notifications\n\nUse mail with low priority for heartbeat pokes.\nAgents can ignore if already processing.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:25.169417-08:00","updated_at":"2025-12-16T17:24:46.380497-08:00","dependencies":[{"issue_id":"gt-kmn.11","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:25.169767-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.11","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T11:50:17.699125-08:00","created_by":"daemon"}]}
{"id":"gt-17r","title":"Doctor check: Zombie session cleanup","description":"Detect and clean up zombie tmux sessions via gt doctor.\n\n## Problem\n\nZombie sessions occur when:\n- Agent crashes without cleanup\n- gt kill fails mid-operation\n- System restart leaves orphan sessions\n- Session naming collision\n\n## Checks\n\n### ZombieSessionCheck\n- List all tmux sessions matching gt-* pattern\n- Cross-reference with known polecats\n- Flag sessions with no corresponding polecat state\n- Flag sessions for removed polecats\n- Check session age vs polecat creation time\n\n### Detection Criteria\n- Session exists but polecat directory doesn't\n- Session name doesn't match any registered polecat\n- Polecat state=idle but session running\n- Multiple sessions for same polecat\n\n## Output\n\n```\n[WARN] Zombie tmux sessions detected:\n - gt-wyvern-OldPolecat (polecat removed)\n - gt-beads-Unknown (no matching polecat)\n - gt-wyvern-Toast (duplicate session)\n\n Run 'gt doctor --fix' to clean up\n```\n\n## Auto-Fix (--fix flag)\n\n- Kill orphan tmux sessions\n- Update polecat state to match reality\n- Log all cleanup actions\n\n## Safety\n\n- Never kill sessions where polecat state=working\n- Prompt before killing if --fix used without --force\n- Create audit log of killed sessions","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:18:01.446702-08:00","updated_at":"2025-12-15T23:18:39.517644-08:00","dependencies":[{"issue_id":"gt-17r","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-17T15:44:41.945064-08:00","created_by":"daemon"},{"issue_id":"gt-17r","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T23:19:05.66301-08:00","created_by":"daemon"}]}
{"id":"gt-48bs","title":"gt rig reset: clear stale mail on reset/land","description":"## Problem\n\nWhen resetting or landing a rig/town, stale mail messages can confuse agents on startup. Old handoff messages, daemon notifications, and inter-agent mail should be cleaned up as part of reset.\n\n## Current State\n\n- `gt rig reset` exists but doesn't clear mail\n- Stale messages accumulate (e.g., daemon SHUTDOWN messages)\n- Agents may read outdated context on startup\n\n## Proposed Behavior\n\n`gt rig reset` and `gt town reset` should:\n1. Close all open messages (`--type=message`) in the relevant beads\n2. Optionally preserve pinned handoff beads (clear content, keep bead)\n3. Log what was cleaned up\n\n```bash\ngt rig reset gastown # Clears gastown mail\ngt rig reset gastown --mail # Only clear mail, keep other state\ngt town reset # Clears all town-level mail\ngt town reset --all # Clears mail in all rigs too\n```\n\n## Implementation\n\n1. Query `bd list --type=message --status=open`\n2. Close each with reason 'Cleared during reset'\n3. For pinned handoffs: `bd update \u003cid\u003e --description=''` instead of close","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T11:42:17.769674-08:00","updated_at":"2025-12-19T11:42:17.769674-08:00"}
{"id":"gt-ctr","title":"GGT vs PGT Gap Analysis Summary","description":"Summary of gaps comparing GGT (~4,500 LOC) to PGT (~27,700 LOC).\n\n## Critical Gaps (P1) - Existing Issues\n- gt-u1j.17: Polecat CLI (add, list, wake, sleep) - DETAILED\n- gt-u1j.16: Rig CLI (add, list, show, remove) - DETAILED\n- gt-u1j.18: Witness CLI (start, stop, status) - DETAILED\n- gt-f9x.4: Doctor framework - DETAILED\n- gt-f9x.5: Workspace doctor checks - DETAILED\n- gt-f9x.6: Rig doctor checks - DETAILED\n\n## Critical Gaps (P1) - New Issues\n- gt-a95: Refinery background daemon mode - ENHANCED\n- gt-hgk: Mail message types and threading - ENHANCED\n\n## Significant Gaps (P2) - New Issues\n- gt-d46: Mail CLI archive/purge/search - ENHANCED\n- gt-e9k: Swarm preflight/postflight - ENHANCED\n- gt-662: Swarm report generation - ENHANCED\n- gt-69l: Hook system - ENHANCED\n- gt-3yj: Agent monitoring - ENHANCED\n- gt-1ky: Workspace CLI (may overlap f9x.3) - ENHANCED\n- gt-9j9: Worker status reporting - ENHANCED\n- gt-qao: Mayor CLI - ENHANCED\n- gt-7o7: Session pre-shutdown checks - ENHANCED\n- gt-c92: Batch all command - ENHANCED\n- gt-lno: Swarm state persistence - ENHANCED\n- gt-a9y: File locking - ENHANCED\n- gt-30o: Error handling improvements - ENHANCED\n\n## Significant Gaps (P2) - Existing Issues\n- gt-kmn.12: Ephemeral rig support - DETAILED\n\n## Lower Priority (P3) - New Issues\n- gt-3fm: Mail orchestrator daemon - ENHANCED\n- gt-2kz: Cleanup commands - ENHANCED\n- gt-ebl: Names commands - ENHANCED\n- gt-1u9: Interactive prompts - ENHANCED\n- gt-8lz: Help text improvements - ENHANCED\n\n## Closed as Duplicates\n- gt-3tz → gt-u1j.17 (polecat CLI)\n- gt-e1r → gt-u1j.16 (rig CLI)\n- gt-86w → gt-f9x.4/5/6 (doctor)\n- gt-alx → gt-kmn.12 (ephemeral rigs)\n\n## Execution Order Recommendation\n1. P1 CLI commands (existing detailed issues ready to implement)\n2. gt-a95: Refinery daemon (blocks autonomous operation)\n3. gt-7o7: Pre-shutdown checks (prevents data loss)\n4. gt-a9y: File locking (prevents corruption)\n5. gt-hgk + gt-d46: Mail improvements\n6. gt-69l: Hook system (enables extensibility)\n7. Remaining P2s in any order\n8. P3s as time permits","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-16T14:49:09.555759-08:00","updated_at":"2025-12-16T16:07:58.413016-08:00"}
{"id":"gt-2bz","title":"Swarm learning: Refinery merge queue automation","description":"Manually merging 15 polecat branches was painful and error-prone. Refinery should automate: detect completed work, run tests, merge to main, handle conflicts. This is core Refinery value prop.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:21:51.137974-08:00","updated_at":"2025-12-16T01:51:40.603737-08:00","closed_at":"2025-12-16T01:51:40.603737-08:00"}
{"id":"gt-hzr","title":"gt witness: Witness management commands","description":"Add 'gt witness' command group for witness lifecycle management.\n\nSubcommands:\n- gt witness start [rig] - Start witness for a rig\n- gt witness stop [rig] - Stop witness\n- gt witness status [rig] - Show witness status\n- gt witness attach [rig] - Attach to witness session\n\nWitness monitors polecats and handles:\n- Idle detection and cleanup\n- Session health checks\n- Nudging stuck agents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:47:32.210917-08:00","updated_at":"2025-12-19T12:56:15.212423-08:00","closed_at":"2025-12-19T12:05:27.343254-08:00","dependencies":[{"issue_id":"gt-hzr","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:42.955006-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.17","title":"CLI: polecat commands (add, remove, list, wake, sleep)","description":"Polecat management CLI commands.\n\n## Commands\n\n### gt polecat list\nList polecats in a rig.\n```\ngt polecat list \u003crig\u003e [--json]\ngt polecat list --all [--json]\n```\nOutput:\n- Name\n- State (idle/active/working/done/stuck)\n- Current issue (if any)\n- Session status (running/stopped)\n\n### gt polecat add\nAdd a new polecat to a rig.\n```\ngt polecat add \u003crig\u003e \u003cname\u003e\n```\n- Creates polecat directory\n- Clones rig repo\n- Creates work branch\n- Initializes state\n\n### gt polecat remove\nRemove a polecat from a rig.\n```\ngt polecat remove \u003crig\u003e/\u003cpolecat\u003e [--force]\n```\n- Fails if session running\n- Warns if uncommitted changes\n- --force bypasses checks\n\n### gt polecat wake\nMark polecat as active (ready for work).\n```\ngt polecat wake \u003crig\u003e/\u003cpolecat\u003e\n```\nTransitions: idle → active\n\n### gt polecat sleep\nMark polecat as idle (not available).\n```\ngt polecat sleep \u003crig\u003e/\u003cpolecat\u003e\n```\nTransitions: active → idle\nFails if session running (stop first).\n\n## Address Format\n\n`\u003crig\u003e/\u003cpolecat\u003e` for operations on specific polecat.\n`\u003crig\u003e` for list command.\n\n## Implementation\n\n```go\nvar polecatCmd = \u0026cobra.Command{Use: \"polecat\"}\npolecatCmd.AddCommand(listCmd, addCmd, removeCmd, wakeCmd, sleepCmd)\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:13.683142-08:00","updated_at":"2025-12-15T21:20:56.485805-08:00","dependencies":[{"issue_id":"gt-u1j.17","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:08.405807-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.17","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:13.683486-08:00","created_by":"daemon"}]}
{"id":"gt-1gy","title":"gt mail read: Support numeric indices for message ID","description":"Allow 'gt mail read 1' to read the first message in inbox.\n\nCurrent behavior requires full message ID like 'msg-abc123'.\nShould support:\n- Numeric index: 'gt mail read 1' reads first/newest message\n- Partial ID match: 'gt mail read abc' matches 'msg-abc123'\n\nThis is a UX improvement - agents frequently type 'gt mail read 1'.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:49:54.60582-08:00","updated_at":"2025-12-17T22:28:59.846038-08:00","closed_at":"2025-12-17T22:28:59.846038-08:00","dependencies":[{"issue_id":"gt-1gy","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.658947-08:00","created_by":"daemon"}]}
{"id":"gt-1fl","title":"gt crew restart command","description":"Add a 'gt crew restart' command that kills the tmux session and restarts fresh. Useful when a crew member gets confused or needs a clean slate.\n\nShould:\n- Kill existing tmux session if running\n- Start fresh session with claude\n- Run gt prime to reinitialize context\n\nAlias: gt crew rs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T19:47:32.131386-08:00","updated_at":"2025-12-19T12:56:15.195247-08:00","closed_at":"2025-12-19T12:07:06.762207-08:00"}
{"id":"gt-9a2.14","title":"CloudRun cost tracking: Usage monitoring and limits","description":"## Overview\n\nTrack Cloud Run usage costs and enforce spending limits.\n\n## Cost Model\n\nCloud Run pricing (approximate):\n- CPU: ~$0.000024/vCPU-second\n- Memory: ~$0.0000025/GiB-second\n- Requests: ~$0.40/million\n\nFor 5-minute worker (2 vCPU, 4GB):\n- CPU: 300 × 2 × $0.000024 = $0.0144\n- Memory: 300 × 4 × $0.0000025 = $0.003\n- **Total: ~$0.017 per session**\n\n## Implementation\n\n```go\ntype CostTracker struct {\n cpuRate float64 // per vCPU-second\n memRate float64 // per GiB-second\n sessions []SessionCost\n mu sync.RWMutex\n}\n\ntype SessionCost struct {\n WorkerID string\n StartTime time.Time\n EndTime time.Time\n CPUs float64\n MemoryGiB float64\n}\n\nfunc (t *CostTracker) RecordSession(workerID string, start, end time.Time, cpus, mem float64) {\n t.mu.Lock()\n defer t.mu.Unlock()\n t.sessions = append(t.sessions, SessionCost{...})\n}\n\nfunc (t *CostTracker) CurrentCost() float64 {\n t.mu.RLock()\n defer t.mu.RUnlock()\n var total float64\n for _, s := range t.sessions {\n duration := s.EndTime.Sub(s.StartTime).Seconds()\n total += duration * s.CPUs * t.cpuRate\n total += duration * s.MemoryGiB * t.memRate\n }\n return total\n}\n```\n\n## Cost Cap Enforcement\n\n```go\nfunc (o *CloudRunOutpost) Spawn(...) (Worker, error) {\n if o.costCap \u003e 0 \u0026\u0026 o.costTracker.CurrentCost() \u003e= o.costCap {\n return nil, ErrCostCapExceeded\n }\n // ... spawn worker\n}\n```\n\n## Config\n\n```yaml\noutposts:\n - name: cloudrun-burst\n type: cloudrun\n cost_cap_hourly: 5.00 # Stop spawning if hourly cost exceeds $5\n cost_cap_daily: 50.00 # Daily limit\n```\n\n## CLI\n\n```bash\ngt outpost status cloudrun-burst\n# Shows: Cost (today): $0.42 / $50.00 cap\n```\n\n## Files\n\n- `internal/cloudrun/cost.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (basic CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:16:14.37154-08:00","updated_at":"2025-12-16T18:16:14.37154-08:00","dependencies":[{"issue_id":"gt-9a2.14","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:31.692724-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.14","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:14.373486-08:00","created_by":"daemon"}]}
{"id":"gt-tulx","title":"gt mq submit: creates task type instead of merge-request type","description":"## Problem\n\n`gt mq submit` creates an issue with `type: task` but should be `type: merge-request`.\n\n## Evidence\n\n```\n$ bd show gt-n508\ngt-n508: Merge: gt-70b3\nStatus: open\nPriority: P1\nType: task \u003c-- WRONG, should be merge-request\n...\nDescription:\ntype: merge-request \u003c-- Correct type is in description, not in actual type field\n```\n\n## Impact\n\n`gt mq list` shows empty queue because it queries for `type: merge-request`\n\n## Fix\n\n`gt mq submit` should set `--type merge-request` when creating the bead.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:57:37.905848-08:00","updated_at":"2025-12-18T22:16:31.393114-08:00","closed_at":"2025-12-18T22:16:31.393114-08:00"}
{"id":"gt-01u","title":"Design: Collapse mail into beads","description":"## Proposal\n\nReplace the separate mail system (JSONL inboxes) with beads issues using a naming convention.\n\n## Rationale\n\nIf all state should be in beads (work items, swarm state, dependencies), why have a separate system for messages? Mail is just:\n- Handoffs (agent → self)\n- Commands (Mayor → Refinery)\n- Escalations (Witness → Mayor)\n\nThese can all be beads issues with a special prefix.\n\n## Design\n\n### Convention\n- Messages use `@-` prefix: `@-witness-1734012345`\n- Assignee = recipient\n- Status: open = unread, closed = read/acknowledged\n- Priority 0 = urgent\n\n### Commands (thin wrappers)\n```bash\ngt mail send witness -s \"Subject\" -m \"Body\"\n → bd create --prefix=@ --title=\"Subject\" --assignee=witness --description=\"Body\"\n\ngt mail inbox\n → bd list --prefix=@ --assignee=$(gt whoami) --status=open\n\ngt mail read @-abc\n → bd show @-abc \u0026\u0026 bd close @-abc\n```\n\n### Notification\nDaemon watches for new `@-` issues and pokes relevant sessions.\nOr: agents poll on heartbeat (simpler).\n\n## What We Remove\n- `mail/inbox.jsonl` files\n- Mail JSONL read/write code\n- Separate delivery mechanism\n\n## What We Keep\n- `gt mail` CLI (as wrapper)\n- Handoff semantics\n- Notification (via daemon or polling)\n\n## Benefits\n- One system, one sync, one query interface\n- All communication in git history\n- Simpler architecture\n\n## Risks\n- Beads prefix filtering must be efficient\n- Namespace collision with user prefixes\n- Performance for high-frequency messages (probably fine for handoffs)\n\n## Decision Point\nDo we need first-class mail support in beads (`bd mail` commands) or is convention sufficient?","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T02:10:18.32879-08:00","updated_at":"2025-12-16T13:12:16.46526-08:00","closed_at":"2025-12-16T13:12:16.46526-08:00"}
{"id":"gt-9a2.1","title":"Outpost/Worker interfaces: Core abstractions for remote compute","description":"## Overview\n\nDefine the core interfaces that all outpost types implement.\n\n## Interfaces\n\n```go\ntype OutpostType string\nconst (\n OutpostLocal OutpostType = \"local\"\n OutpostSSH OutpostType = \"ssh\"\n OutpostCloudRun OutpostType = \"cloudrun\"\n)\n\ntype Outpost interface {\n Name() string\n Type() OutpostType\n MaxWorkers() int\n ActiveWorkers() int\n Spawn(issue string, config WorkerConfig) (Worker, error)\n Workers() []Worker\n Ping() error\n SendMail(worker string, msg Message) error // optional\n}\n\ntype Worker interface {\n ID() string\n Outpost() string\n Status() WorkerStatus // idle, working, done, failed\n Issue() string\n Attach() error // for interactive outposts\n Logs() (io.Reader, error)\n Stop() error\n}\n\ntype WorkerConfig struct {\n RigPath string\n BeadsDir string\n GitBranch string\n Context map[string]string // hints for worker\n}\n```\n\n## Files\n\n- `internal/outpost/outpost.go` - Outpost interface\n- `internal/outpost/worker.go` - Worker interface\n- `internal/outpost/config.go` - WorkerConfig, OutpostType\n\n## Notes\n\nThis is the foundation for all federation work. Keep interfaces minimal - we can extend later.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:01:38.268086-08:00","updated_at":"2025-12-16T18:01:38.268086-08:00","dependencies":[{"issue_id":"gt-9a2.1","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:01:38.27131-08:00","created_by":"daemon"}]}
{"id":"gt-cik.4","title":"gt crew at/attach: Start session in crew workspace","description":"Implement 'gt crew at \u003crig\u003e/\u003cname\u003e' and 'gt crew attach \u003cname\u003e' commands:\n- Start tmux session (optional - could just print cd instructions)\n- Launch claude code in the workspace\n- Deliver any pending mail\n- Support --no-tmux to just print directory path\n- 'attach' infers rig from cwd","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:04.96786-08:00","updated_at":"2025-12-16T20:59:33.355591-08:00","closed_at":"2025-12-16T20:53:16.677693-08:00","dependencies":[{"issue_id":"gt-cik.4","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:04.969488-08:00","created_by":"daemon"}]}
{"id":"gt-4nn.1","title":"Molecule schema: YAML format for workflow definitions","description":"Define the YAML schema for molecule definitions:\n\n```yaml\nmolecule: \u003cname\u003e\nversion: 1\ndescription: \"Human description\"\nsteps:\n - id: \u003cstep-id\u003e\n title: \"Step title\"\n prompt: \"Instructions for agent\"\n depends: [\u003cother-step-ids\u003e] # optional\n tier: haiku|sonnet|opus # optional, default from config\n timeout: 30m # optional\n```\n\nStore molecules in:\n- `\u003crig\u003e/molecules/\u003cname\u003e.yaml` for rig-specific\n- `\u003ctown\u003e/molecules/\u003cname\u003e.yaml` for town-wide\n\nBuilt-in molecules to ship:\n- engineer-in-box: design→code→review→test→submit\n- quick-fix: implement→test→submit\n- research: investigate→document","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:49.441267-08:00","updated_at":"2025-12-19T12:56:15.199539-08:00","closed_at":"2025-12-18T20:14:32.629327-08:00","dependencies":[{"issue_id":"gt-4nn.1","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:49.442723-08:00","created_by":"daemon"}]}
{"id":"gt-selw","title":"gt spawn: add --polecat flag for explicit worker selection","description":"Currently gt spawn requires positional arg format:\n```\ngt spawn gastown/Angharad --issue gt-xyz\n```\n\nBut I tried the more intuitive flag form:\n```\ngt spawn --issue gt-xyz --polecat Angharad\n```\n\nThis failed with 'unknown flag: --polecat'.\n\nThe flag form is more discoverable and consistent with other commands. Add --polecat flag as alternative to positional arg.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T01:41:38.540563-08:00","updated_at":"2025-12-19T01:57:17.0307-08:00","closed_at":"2025-12-19T01:57:17.0307-08:00"}
{"id":"gt-avq9","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:18.575204-08:00","updated_at":"2025-12-19T18:26:14.100966-08:00","closed_at":"2025-12-19T18:26:14.10097-08:00"}
{"id":"gt-9a2.8","title":"CloudRunOutpost: Basic implementation","description":"## Overview\n\nBasic CloudRunOutpost implementation. Persistent connections and cost tracking are separate tasks.\n\n## Implementation\n\n```go\ntype CloudRunOutpost struct {\n name string\n project string\n region string\n service string\n maxWorkers int\n client *WorkClient\n workers map[string]*CloudRunWorker\n mu sync.RWMutex\n}\n\nfunc NewCloudRunOutpost(cfg OutpostConfig) (*CloudRunOutpost, error) {\n serviceURL := fmt.Sprintf(\n \"https://%s-%s.a.run.app\",\n cfg.Service, cfg.Region,\n )\n return \u0026CloudRunOutpost{\n name: cfg.Name,\n project: cfg.Project,\n region: cfg.Region,\n service: cfg.Service,\n maxWorkers: cfg.MaxWorkers,\n client: NewWorkClient(serviceURL),\n workers: make(map[string]*CloudRunWorker),\n }, nil\n}\n```\n\n## Spawn\n\n```go\nfunc (o *CloudRunOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n req := WorkRequest{\n IssueID: issue,\n Rig: RigConfig{URL: cfg.RigURL, Branch: cfg.GitBranch},\n Beads: BeadsConfig{URL: cfg.BeadsURL, Branch: \"beads-sync\"},\n Branch: \"polecat/\" + issue,\n }\n \n events, err := o.client.DispatchWork(context.Background(), req)\n if err != nil {\n return nil, err\n }\n \n worker := \u0026CloudRunWorker{\n id: uuid.New().String(),\n outpost: o.name,\n issue: issue,\n events: events,\n status: WorkerStatusWorking,\n }\n \n o.mu.Lock()\n o.workers[worker.id] = worker\n o.mu.Unlock()\n \n go worker.monitor()\n return worker, nil\n}\n```\n\n## CloudRunWorker\n\n```go\ntype CloudRunWorker struct {\n id string\n outpost string\n issue string\n status WorkerStatus\n events \u003c-chan WorkEvent\n logs []string\n}\n\nfunc (w *CloudRunWorker) Attach() error {\n return errors.New(\"Cloud Run workers do not support attach\")\n}\n\nfunc (w *CloudRunWorker) Logs() (io.Reader, error) {\n return strings.NewReader(strings.Join(w.logs, \"\\n\")), nil\n}\n```\n\n## Files\n\n- `internal/outpost/cloudrun.go`\n\n## Dependencies\n\nDepends on: gt-9a2.1 (interfaces), gt-9a2.12 (HTTP client)\nBlocks: gt-9a2.13 (persistent connections), gt-9a2.14 (cost tracking)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:06.803401-08:00","updated_at":"2025-12-16T18:15:39.752892-08:00","dependencies":[{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:46.081721-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2.12","type":"blocks","created_at":"2025-12-16T18:15:54.915831-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:06.805524-08:00","created_by":"daemon"}]}
{"id":"gt-3x1","title":"Update Refinery to use Beads merge queue","description":"Replace branch discovery with Beads queue in the Refinery module:\n\nCurrent (internal/refinery/manager.go):\n- Scans for polecat/* branches\n- Creates MR objects on-the-fly\n\nNew:\n- Pull from Beads: bd ready --type=merge-request\n- Process each MR\n- Close with merge commit: bd close \u003cid\u003e --reason=\"Merged at \u003csha\u003e\"\n- Handle failures: bd update \u003cid\u003e --status=blocked --reason=\"...\"\n\nThe Engineer (agent) becomes Beads-native.\nThe Refinery (module) provides the infrastructure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:37.96436-08:00","updated_at":"2025-12-19T15:27:45.506132-08:00","closed_at":"2025-12-19T14:47:51.65991-08:00","dependencies":[{"issue_id":"gt-3x1","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.812433-08:00","created_by":"daemon"},{"issue_id":"gt-3x1","depends_on_id":"gt-svi","type":"blocks","created_at":"2025-12-16T23:03:12.814463-08:00","created_by":"daemon"}]}
{"id":"gt-j87","title":"Design: Work flow simulation and validation","description":"Validate GGT designs through simulation before implementation.\n\n## Validation Approaches\n\n### 1. Dry-Run Simulation (Recommended First)\nMayor walks through scenarios mentally/on paper:\n- \"If polecat Toast signals done with dirty git state, what happens?\"\n- \"If Witness context fills mid-verification, what state is lost?\"\n- \"If two polecats try to close same issue, what happens?\"\n\nCreate beads for any gaps discovered.\n\n### 2. Real Work in gastown-py\nUse Python Gas Town to stress-test assumptions:\n- Run actual batch work on test repos\n- Observe edge cases in practice\n- Document issues found\n\n### 3. Edge Case Analysis\nSystematic review of failure modes:\n- Agent crashes mid-operation\n- Network failures during sync\n- Concurrent access to shared state\n- Context limits hit at bad times\n\n## Key Scenarios to Validate\n\n- [ ] Witness session cycling (state preservation)\n- [ ] Polecat decommission with dirty state\n- [ ] Merge conflicts in queue\n- [ ] Beads sync conflicts between workers\n- [ ] Escalation path (stuck worker -\u003e Mayor)\n- [ ] Cross-rig communication\n- [ ] Federation mail routing (future)\n\n## Success Criteria\n\n- No data loss scenarios identified\n- Clear recovery paths for all failure modes\n- Edge cases either handled or documented as limitations\n- Design improves as model cognition improves\n\n## Output\n\nFor each scenario validated:\n1. Document in relevant bead if issue found\n2. Create new beads for missing functionality\n3. Update architecture.md if design changes","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-15T20:24:11.251841-08:00","updated_at":"2025-12-16T17:25:49.858717-08:00"}
{"id":"gt-kmn.4","title":"Refinery semantic merge processing loop","description":"Implement the Refinery semantic merge loop for processing polecat work.\n\n## Overview\n\nThe Refinery is a fully empowered Claude Code agent that:\n1. Fetches polecat branches\n2. Merges to integration branch\n3. Resolves conflicts semantically (re-implements if needed)\n4. Runs tests\n5. Escalates only when truly stuck\n\n## Processing Loop\n\n1. Check queue for completed tasks (polecat done, not yet merged)\n2. For each task:\n - Fetch polecat branch\n - Attempt merge to integration/\u003cswarm-id\u003e\n - On conflict: semantic resolution (understand intent, re-implement)\n - Run tests if configured\n - On success: mark merged, file bead, notify witness\n - On failure: notify polecat (test fail) or escalate (stuck)\n3. When all tasks merged: land integration to main\n\n## Semantic Merge\n\nWhen git merge fails, Refinery:\n1. Reads polecat changes and beads issue\n2. Understands intent\n3. Re-implements on current integration branch\n4. Only escalates if truly blocked\n\n## Daemon Poking\n\nRefinery is poked by:\n- Daemon heartbeat (periodic)\n- Witness notification (polecat done)\n- Mayor request (check queue)\n\n## Dependencies\n\nNeeds: gt-u1j.6 (mail), gt-u1j.3 (git), gt-u1j.14 (merge queue)\n\n## Reference\n\nSee PGT ephemeral.py for branch operations.","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:19.536429-08:00","updated_at":"2025-12-16T14:24:17.527982-08:00","closed_at":"2025-12-16T14:24:17.527982-08:00","dependencies":[{"issue_id":"gt-kmn.4","depends_on_id":"gt-kmn.3","type":"blocks","created_at":"2025-12-16T00:11:22.86454-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T00:11:22.952967-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:23.046741-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:19.536808-08:00","created_by":"daemon"}]}
{"id":"gt-9mb","title":"Recreate beads rigs with fresh clones","description":"## Problem\n\nBeads rigs have schema mismatches (missing thread_id column, etc.) from development iteration.\n\n## Tasks\n\n1. Shut down any active polecats\n2. Delete existing beads rigs: mayor/rig, refinery/rig, witness/rig, crew/*\n3. Re-clone from beads repo\n4. Run bd init in each new clone\n\n## Rigs to recreate\n\n- /Users/stevey/gt/beads/mayor/rig\n- /Users/stevey/gt/beads/refinery/rig\n- /Users/stevey/gt/beads/crew/* (if any)\n\n## Source\n\nClone from beads repo (need to confirm remote URL)","status":"closed","issue_type":"task","created_at":"2025-12-18T19:13:32.208448-08:00","updated_at":"2025-12-18T19:16:27.096311-08:00","closed_at":"2025-12-18T19:16:27.096311-08:00"}
{"id":"gt-59p","title":"Design GGT prompt architecture","description":"Audit PGT prompts and design canonical prompt system for GGT. Create docs/prompts.md with inventory, gap analysis, and Witness prompt design.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T00:46:16.916031-08:00","updated_at":"2025-12-16T00:47:38.105395-08:00","closed_at":"2025-12-16T00:47:38.105395-08:00"}
{"id":"gt-h5n.8","title":"MQ config schema: merge_queue section in rig config.json","description":"Define and implement merge_queue configuration in rig config.\n\nSchema:\n{\n \"merge_queue\": {\n \"enabled\": true,\n \"target_branch\": \"main\",\n \"integration_branches\": true,\n \"on_conflict\": \"assign_back\", // or \"auto_rebase\"\n \"run_tests\": true,\n \"test_command\": \"go test ./...\",\n \"delete_merged_branches\": true,\n \"retry_flaky_tests\": 1,\n \"poll_interval\": \"30s\",\n \"max_concurrent\": 1\n }\n}\n\nImplement:\n- Config loading in rig package\n- Default values\n- Validation\n\nReference: docs/merge-queue-design.md#configuration","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:52:00.322779-08:00","updated_at":"2025-12-19T12:56:15.211099-08:00","closed_at":"2025-12-19T01:33:49.864359-08:00","dependencies":[{"issue_id":"gt-h5n.8","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:00.324781-08:00","created_by":"daemon"}]}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:26.397214-08:00","updated_at":"2025-12-17T13:52:26.397214-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-d7i","title":"gt session capture: Support positional line count argument","description":"Make 'gt session capture gastown/Toast 50' work.\n\nCurrently requires: gt session capture gastown/Toast -n 50\nShould also accept: gt session capture gastown/Toast 50\n\nAgent UX principle: commands should work the way agents guess they work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T22:28:44.291285-08:00","updated_at":"2025-12-19T12:56:15.206849-08:00","closed_at":"2025-12-19T01:33:49.860862-08:00"}
{"id":"gt-iua8","title":"Merge: gt-frs","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-frs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:30:05.529099-08:00","updated_at":"2025-12-19T18:26:14.104887-08:00","closed_at":"2025-12-19T17:48:44.654109-08:00"}
{"id":"gt-wav5","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:30.210304-08:00","updated_at":"2025-12-19T18:26:14.103104-08:00","closed_at":"2025-12-19T18:26:14.103106-08:00"}
{"id":"gt-2jl","title":"Add bulk polecat remove command (gt polecat remove --all)","description":"When decommissioning a rig, need to remove multiple polecats one at a time. A --all or --rig flag would allow: gt polecat remove --rig gastown --force","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-18T11:33:35.206637-08:00","updated_at":"2025-12-18T11:38:53.829321-08:00","closed_at":"2025-12-18T11:38:53.829321-08:00"}
{"id":"gt-b1g","title":"MVP Cutover: GGT replaces PGT for batch work","description":"When this is closed, stop using town and start using gt.\n\n## Acceptance Criteria\n\n1. gt spawn assigns issue to polecat and starts session\n2. gt spawn --epic spawns workers for all epic children\n3. gt session manages tmux lifecycle \n4. gt send / gt inbox work for mail\n5. Refinery processes merge queue with semantic merges\n6. Integration branches created and landed correctly\n7. gt stop --all halts all sessions\n8. One successful test batch completed end-to-end\n\n## What Must Work\n\n- Spawn polecat with issue assignment\n- Spawn workers for epic children\n- Session start/stop/attach\n- Mail send/inbox/read\n- Refinery merge loop (semantic)\n- Integration branch → main landing\n- Witness cleanup protocol\n- Emergency stop\n\n## What Can Be Deferred\n\n- Doctor checks (use PGT)\n- TUI dashboard\n- Plugin system\n- Federation\n- Ephemeral rigs\n- Detailed landing reports\n\n## Test Plan\n\n1. Create epic with 2 tasks, spawn 2 workers\n2. Verify polecats get assigned and sessions start\n3. Simulate task completion\n4. Verify Refinery merges to integration\n5. Verify landing to main\n6. Verify cleanup\n\n## Validation\n\nRun one real batch implementing GGT issues using GGT.\n\n## Note\n\nNo \"swarm IDs\" - just spawn workers for epic, let merge queue coordinate.","status":"open","issue_type":"epic","created_at":"2025-12-16T00:11:09.148751-08:00","updated_at":"2025-12-16T17:26:58.140535-08:00","dependencies":[{"issue_id":"gt-b1g","depends_on_id":"gt-rm3","type":"blocks","created_at":"2025-12-16T00:11:51.69062-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.6","type":"blocks","created_at":"2025-12-16T00:11:36.351097-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.19","type":"blocks","created_at":"2025-12-16T00:11:36.196292-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.7","type":"blocks","created_at":"2025-12-16T00:11:36.431641-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-ov2","type":"blocks","created_at":"2025-12-16T00:11:51.609649-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.22","type":"blocks","created_at":"2025-12-16T00:11:36.511124-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.12","type":"blocks","created_at":"2025-12-16T21:36:35.053559-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.4","type":"blocks","created_at":"2025-12-16T00:11:36.273483-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T21:36:32.942855-08:00","created_by":"daemon"}]}
{"id":"gt-dq3","title":"Split PGT/GGT harness or migrate to GGT-only","description":"Current ~/ai harness is shared by PGT and GGT with confusing overlap. Options:\n1. Keep separate (document the coexistence)\n2. Migrate fully to GGT structure\n3. Create separate harnesses\n\nThis affects the beads redirect, Mayor home location, and rig structure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T17:15:32.308192-08:00","updated_at":"2025-12-19T12:56:15.207324-08:00","closed_at":"2025-12-19T12:08:48.653114-08:00","dependencies":[{"issue_id":"gt-dq3","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.717903-08:00","created_by":"daemon"}]}
{"id":"gt-unrd","title":"Fix gt prime to give crew workers crew context","description":"gt prime currently gives Mayor context to all agents. Crew workers should get crew-specific context. Also extract shared theory of operation from mayor priming into shared context for all roles.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T15:37:49.671015-08:00","updated_at":"2025-12-19T17:22:52.551704-08:00","closed_at":"2025-12-19T15:41:38.806903-08:00"}
{"id":"gt-9a2.9","title":"Outpost assignment policy: Smart work routing","description":"## Overview\n\nPolicy engine for deciding which outpost gets which work.\n\n## Policy Configuration\n\n```yaml\npolicy:\n # Default order of preference\n default_preference: [local, gce-burst, cloudrun-burst]\n \n # Rules applied in order\n rules:\n # Background work → Cloud Run (cheap)\n - condition: \"priority \u003e= P3\"\n prefer: cloudrun-burst\n \n # Long tasks → VM (persistent)\n - condition: \"estimated_duration \u003e 30m\"\n prefer: gce-burst\n \n # Specific epic → specific outpost\n - condition: \"epic == gt-abc\"\n prefer: local\n```\n\n## Implementation\n\n```go\ntype AssignmentPolicy struct {\n DefaultPreference []string\n Rules []PolicyRule\n}\n\ntype PolicyRule struct {\n Condition string // Simple expression\n Prefer string // Outpost name\n Require string // Must use this outpost\n}\n\nfunc (p *AssignmentPolicy) SelectOutpost(\n issue Issue, \n outposts map[string]Outpost,\n) Outpost {\n // Check rules in order\n for _, rule := range p.Rules {\n if rule.Matches(issue) {\n if op, ok := outposts[rule.Prefer]; ok {\n if op.ActiveWorkers() \u003c op.MaxWorkers() {\n return op\n }\n }\n }\n }\n \n // Fall back to default preference\n for _, name := range p.DefaultPreference {\n if op, ok := outposts[name]; ok {\n if op.ActiveWorkers() \u003c op.MaxWorkers() {\n return op\n }\n }\n }\n \n return nil // All outposts at capacity\n}\n```\n\n## Condition Language\n\nSimple expressions, not a full DSL:\n\n```\npriority \u003e= P3\npriority == P0\nestimated_duration \u003e 30m\nepic == gt-abc\ntype == bug\nlabel contains \"urgent\"\n```\n\n## Files\n\n- `internal/outpost/policy.go`\n- `internal/outpost/condition.go`\n\nDepends on: gt-9a2.3 (config)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:21.08101-08:00","updated_at":"2025-12-16T18:03:21.08101-08:00","dependencies":[{"issue_id":"gt-9a2.9","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:21.083256-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.9","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:03:46.300288-08:00","created_by":"daemon"}]}
{"id":"gt-aqm","title":"Beads as Universal Data Plane","description":"## Vision\n\nBeads is the data plane for all Gas Town operations. Everything flows through beads:\n- Work items (issues, tasks, epics)\n- Mail (messages between agents)\n- Merge requests (queue entries)\n- Workflows (composable execution patterns)\n- Resources (leases, locks, quotas)\n- Schedules (timed activities)\n\n## New Bead Categories\n\n### Molecules (Composable Workflows)\nCrystallized workflow patterns that can be attached to work items.\n\n### Timed Beads (Scheduled Work)\nBeads that wake up periodically via daemon.\n\n### Pinned Beads (Ongoing Concerns)\nBeads representing persistent concerns, not discrete tasks.\n\n### Resource Beads (Leases/Locks)\nBeads representing reserved resources.\n\n## v1 Priority\n\n- **P0**: Molecules (enables engineer-in-box)\n- **P2**: Timed, Pinned, Resource beads (post-v1)","status":"open","issue_type":"epic","created_at":"2025-12-18T18:05:57.847578-08:00","updated_at":"2025-12-18T18:06:10.898712-08:00","dependencies":[{"issue_id":"gt-aqm","depends_on_id":"gt-4nn","type":"blocks","created_at":"2025-12-18T18:06:29.881371-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-caz","type":"blocks","created_at":"2025-12-18T18:08:19.833603-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-8h4","type":"blocks","created_at":"2025-12-18T18:08:19.930166-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-b3p","type":"blocks","created_at":"2025-12-18T18:08:20.026188-08:00","created_by":"daemon"}]}
{"id":"gt-2n3f","title":"Merge conflicts: Buzzard/mq-status, Dementus/harness-docs","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T12:08:07.486349-08:00","updated_at":"2025-12-19T15:06:22.390602-08:00","closed_at":"2025-12-19T14:28:14.462028-08:00"}
{"id":"gt-51x","title":"Fix golangci-lint errcheck warnings (~160 issues)","description":"Running golangci-lint shows ~160 errcheck warnings for unchecked error returns.\n\nCommon patterns:\n- t.SetEnvironment() return values\n- os.WriteFile(), os.RemoveAll() \n- MarkFlagRequired() on cobra commands\n- Various manager methods\n\nRun: golangci-lint run ./...\n\nCould batch fix with:\n1. Add explicit _ = for intentionally ignored errors\n2. Handle errors properly where they matter\n3. Consider adding //nolint:errcheck for cobra flag setup","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T15:02:39.807659-08:00","updated_at":"2025-12-19T12:56:15.201923-08:00","closed_at":"2025-12-19T12:09:58.544102-08:00"}
{"id":"gt-dt5","title":"Define Engineer as the Refinery agent role","description":"Clarify the distinction:\n\n- **Refinery** = place/module/directory/workspace\n - `\u003crig\u003e/refinery/` directory structure\n - `gt refinery start/stop/status` commands\n - tmux session name: `refinery` or `\u003crig\u003e-refinery`\n\n- **Engineer** = role/agent who works in the Refinery\n - CLAUDE.md prompting: \"You are an Engineer...\"\n - Documentation: \"The Engineer processes merge requests...\"\n - Mail address: `\u003crig\u003e/engineer` (or `\u003crig\u003e/refinery`?)\n\nUpdates needed:\n- Add Engineer role description to docs\n- Update CLAUDE.md templates for refinery agents\n- Keep `gt refinery` commands as-is (they manage the place)\n- Internal code stays `internal/refinery/` (the module)\n\nFuture consideration: Multiple Engineers in one Refinery for parallel merge processing.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:18.591842-08:00","updated_at":"2025-12-16T23:07:21.93783-08:00","dependencies":[{"issue_id":"gt-dt5","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.577196-08:00","created_by":"daemon"}]}
{"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-9a2.15","title":"Outpost error handling: Retry logic and resilience","description":"## Overview\n\nError handling and retry logic for outpost operations.\n\n## Error Types\n\n```go\nvar (\n ErrOutpostUnreachable = errors.New(\"outpost unreachable\")\n ErrWorkerSpawnFailed = errors.New(\"worker spawn failed\")\n ErrWorkerTimeout = errors.New(\"worker timed out\")\n ErrCostCapExceeded = errors.New(\"cost cap exceeded\")\n ErrAllOutpostsBusy = errors.New(\"all outposts at capacity\")\n)\n```\n\n## Retry Policy\n\n```go\ntype RetryPolicy struct {\n MaxAttempts int\n InitialBackoff time.Duration\n MaxBackoff time.Duration\n BackoffFactor float64\n RetryableErrors []error\n}\n\nfunc DefaultRetryPolicy() *RetryPolicy {\n return \u0026RetryPolicy{\n MaxAttempts: 3,\n InitialBackoff: 1 * time.Second,\n MaxBackoff: 30 * time.Second,\n BackoffFactor: 2.0,\n RetryableErrors: []error{\n ErrOutpostUnreachable,\n ErrWorkerSpawnFailed,\n },\n }\n}\n```\n\n## Retry Implementation\n\n```go\nfunc (m *OutpostManager) SpawnWithRetry(issue string, cfg WorkerConfig) (Worker, error) {\n var lastErr error\n backoff := m.retryPolicy.InitialBackoff\n \n for attempt := 0; attempt \u003c m.retryPolicy.MaxAttempts; attempt++ {\n outpost := m.policy.SelectOutpost(issue, m.outposts)\n if outpost == nil {\n return nil, ErrAllOutpostsBusy\n }\n \n worker, err := outpost.Spawn(issue, cfg)\n if err == nil {\n return worker, nil\n }\n \n if !m.isRetryable(err) {\n return nil, err\n }\n \n lastErr = err\n time.Sleep(backoff)\n backoff = min(backoff * m.retryPolicy.BackoffFactor, m.retryPolicy.MaxBackoff)\n }\n \n return nil, fmt.Errorf(\"spawn failed after %d attempts: %w\", \n m.retryPolicy.MaxAttempts, lastErr)\n}\n```\n\n## Outpost Health Tracking\n\n```go\ntype OutpostHealth struct {\n LastPing time.Time\n LastError error\n FailureCount int\n CircuitBreaker bool // If true, skip this outpost\n}\n\nfunc (m *OutpostManager) updateHealth(name string, err error) {\n // Track failures, open circuit breaker after N failures\n // Auto-reset after successful ping\n}\n```\n\n## Config\n\n```yaml\npolicy:\n retry:\n max_attempts: 3\n initial_backoff: 1s\n max_backoff: 30s\n \n circuit_breaker:\n failure_threshold: 5\n reset_timeout: 1m\n```\n\n## Files\n\n- `internal/outpost/retry.go`\n- `internal/outpost/health.go`\n\n## Dependencies\n\nDepends on: gt-9a2.3 (OutpostManager)\nCan be done after basic outpost implementations work.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:16:33.386008-08:00","updated_at":"2025-12-16T18:16:33.386008-08:00","dependencies":[{"issue_id":"gt-9a2.15","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:33.387765-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.15","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:16:46.064482-08:00","created_by":"daemon"}]}
{"id":"gt-5af.2","title":"Add gt deacon start/stop/status commands","description":"Add CLI commands: gt deacon start (spawn gt-deacon session), gt deacon stop (kill session), gt deacon status (show health state). Similar to gt mayor commands.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:26.617077-08:00","updated_at":"2025-12-19T17:25:12.114616-08:00","closed_at":"2025-12-19T17:25:12.114616-08:00","dependencies":[{"issue_id":"gt-5af.2","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:26.618912-08:00","created_by":"daemon"}]}
{"id":"gt-5af.6","title":"Add Deacon heartbeat mechanism","description":"Deacon writes deacon/heartbeat.json on each wake. Go daemon reads it to decide whether to poke. Add heartbeat read/write helpers.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:52.057582-08:00","updated_at":"2025-12-19T17:26:36.573141-08:00","closed_at":"2025-12-19T17:26:36.573141-08:00","dependencies":[{"issue_id":"gt-5af.6","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:52.059708-08:00","created_by":"daemon"}]}
{"id":"gt-qscw","title":"Merge: gt-72so","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-72so\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T16:20:02.203335-08:00","updated_at":"2025-12-19T18:26:14.105337-08:00","closed_at":"2025-12-19T17:48:09.571107-08:00"}
{"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-vci","title":"Mayor handoff mail template","description":"Add MAYOR_HANDOFF mail template to templates.py.\n\n## Template Function\n\ndef mayor_handoff(\n active_swarms: List[SwarmStatus],\n rig_status: Dict[str, RigStatus],\n pending_escalations: List[Escalation],\n in_flight_decisions: List[Decision],\n recent_actions: List[str],\n delegated_work: List[DelegatedItem],\n user_requests: List[str],\n next_steps: List[str],\n warnings: Optional[str] = None,\n session_duration: Optional[str] = None,\n) -\u003e Message:\n metadata = {\n 'template': 'MAYOR_HANDOFF',\n 'timestamp': datetime.utcnow().isoformat(),\n 'session_duration': session_duration,\n 'active_swarm_count': len(active_swarms),\n 'pending_escalation_count': len(pending_escalations),\n }\n # ... format sections ...\n return Message.create(\n sender='mayor/',\n recipient='mayor/',\n subject='Session Handoff',\n body=body,\n priority='high',\n )\n\n## Metadata Fields\n\n- template: MAYOR_HANDOFF\n- timestamp: ISO format\n- session_duration: Human readable\n- active_swarm_count: Number of active swarms\n- pending_escalation_count: Number of escalations\n\n## Mail Priority\n\nUse priority='high' to ensure handoff is seen on startup.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:30.26323-08:00","updated_at":"2025-12-15T20:48:59.550689-08:00","dependencies":[{"issue_id":"gt-vci","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.554108-08:00","created_by":"daemon"}]}
{"id":"gt-svi","title":"Implement gt mq CLI commands","description":"Add gt mq subcommands as sugar over bd:\n\n- gt mq submit: Create MR for current branch\n- gt mq list: Show open merge requests\n- gt mq next: Show next MR ready to process\n- gt mq process: Engineer processes the queue\n- gt mq reorder \u003cid\u003e --after \u003cx\u003e: Change ordering via deps\n- gt mq status \u003cid\u003e: Show MR details\n\nAll commands should work with the Beads data plane.","status":"closed","issue_type":"task","created_at":"2025-12-16T23:02:16.649648-08:00","updated_at":"2025-12-19T12:56:15.215065-08:00","closed_at":"2025-12-18T20:22:54.684284-08:00","dependencies":[{"issue_id":"gt-svi","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.456462-08:00","created_by":"daemon"},{"issue_id":"gt-svi","depends_on_id":"gt-kp2","type":"blocks","created_at":"2025-12-16T23:03:12.689547-08:00","created_by":"daemon"}]}
{"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-u1j.18","title":"CLI: witness commands (start, stop, status)","description":"Witness daemon CLI commands.\n\n## Commands\n\n### gt witness start\nStart the witness daemon for a rig.\n```\ngt witness start \u003crig\u003e [--interval \u003cseconds\u003e]\n```\n- Starts background daemon process\n- Default heartbeat interval: 30s\n- Logs to \u003crig\u003e/witness/witness.log\n\n### gt witness stop\nStop the witness daemon.\n```\ngt witness stop \u003crig\u003e\n```\n- Graceful shutdown\n- Completes current heartbeat cycle\n\n### gt witness status\nShow witness status.\n```\ngt witness status \u003crig\u003e [--json]\n```\nOutput:\n- Running/stopped\n- Last heartbeat time\n- Polecats being monitored\n- Recent nudges/escalations\n\n### gt witness logs\nView witness logs.\n```\ngt witness logs \u003crig\u003e [--follow] [--lines \u003cn\u003e]\n```\n- --follow: Continuous output (like tail -f)\n- --lines: Number of lines (default 50)\n\n## Daemon Management\n\nWitness runs as background process:\n- PID stored in \u003crig\u003e/witness/witness.pid\n- Uses nohup for persistence\n- Logs structured JSON events\n\n## Implementation\n\n```go\nvar witnessCmd = \u0026cobra.Command{Use: \"witness\"}\nwitnessCmd.AddCommand(startCmd, stopCmd, statusCmd, logsCmd)\n```\n\nStart launches daemon via exec, status reads PID file and pings process.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:15.022371-08:00","updated_at":"2025-12-15T21:21:07.27635-08:00","dependencies":[{"issue_id":"gt-u1j.18","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:15.022774-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.18","depends_on_id":"gt-u1j.9","type":"blocks","created_at":"2025-12-15T17:14:08.490417-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.1","title":"MR field parsing: extract structured fields from description","description":"Parse merge-request beads to extract structured fields:\n- branch: source branch name\n- target: target branch (main or integration/xxx)\n- source_issue: the work item being merged\n- worker: who did the work\n- rig: which rig\n- merge_commit: (set on close)\n- close_reason: (set on close)\n\nFields stored in description as YAML block or key: value lines.\nProvide helper functions: ParseMRFields(issue) and SetMRFields(issue, fields).\n\nReference: docs/merge-queue-design.md#merge-request-schema","status":"closed","issue_type":"task","created_at":"2025-12-17T13:47:46.682379-08:00","updated_at":"2025-12-18T19:00:03.189669-08:00","closed_at":"2025-12-18T11:46:18.970805-08:00","dependencies":[{"issue_id":"gt-h5n.1","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:47:46.682911-08:00","created_by":"daemon"}]}
{"id":"gt-w5dj","title":"Merge: gt-unrd","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-unrd\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T15:42:06.600633-08:00","updated_at":"2025-12-19T18:26:14.106188-08:00","closed_at":"2025-12-19T17:48:09.590076-08:00"}
{"id":"gt-6z2","title":"Test Epic: GGT MVP Validation","status":"closed","issue_type":"epic","created_at":"2025-12-16T21:57:37.355269-08:00","updated_at":"2025-12-16T22:06:41.124727-08:00","closed_at":"2025-12-16T22:06:41.124727-08:00"}
{"id":"gt-u1j.6","title":"Mail system: JSONL inbox, delivery, tmux injection","description":"Refactor mail system to wrap bd mail commands.\n\n## Status\n\nCurrent implementation uses JSONL files directly. Now that Beads mail is available (gt-r01 closed), refactor to use bd mail as the backend.\n\n## Implementation\n\nReplace internal/mail/* with thin wrappers around bd CLI:\n\n```go\n// Send wraps: bd mail send \u003cto\u003e -s \u003csubject\u003e -m \u003cbody\u003e\nfunc (r *Router) Send(msg *Message) error\n\n// List wraps: bd mail inbox --json\nfunc (m *Mailbox) List() ([]*Message, error)\n\n// Get wraps: bd mail read \u003cid\u003e --json\nfunc (m *Mailbox) Get(id string) (*Message, error)\n\n// MarkRead wraps: bd mail ack \u003cid\u003e\nfunc (m *Mailbox) MarkRead(id string) error\n```\n\n## Address Translation\n\nGGT addresses → Beads recipients:\n- `mayor/` → `mayor`\n- `\u003crig\u003e/refinery` → `\u003crig\u003e-refinery`\n- `\u003crig\u003e/\u003cpolecat\u003e` → `\u003crig\u003e-\u003cpolecat\u003e`\n\n## Tmux Notification\n\nKeep the tmux injection for --notify flag. After bd mail send, optionally inject notification into tmux session.\n\n## Migration\n\nNo migration needed - bd mail creates messages as beads issues with type=message. Old JSONL inboxes can be ignored or cleaned up.\n\n## Dependencies\n\n- gt-r01: CLOSED (Beads mail available)\n- gt-u1j.4: Tmux wrapper (for notifications)","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:16.226478-08:00","updated_at":"2025-12-16T21:45:20.397855-08:00","closed_at":"2025-12-16T21:45:20.397855-08:00","dependencies":[{"issue_id":"gt-u1j.6","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:16.226821-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.6","depends_on_id":"gt-u1j.4","type":"blocks","created_at":"2025-12-15T17:13:51.98774-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.6","depends_on_id":"gt-r01","type":"blocks","created_at":"2025-12-16T13:12:08.753309-08:00","created_by":"daemon"}]}
{"id":"gt-kmn","title":"Batch Work System: Integration branch, merge queue, landing","description":"## Overview\n\nThis epic tracks batch work coordination in GGT. Key insight: **work is a stream, not discrete swarms**.\n\nThere are no \"swarm IDs\" - the epic IS the grouping, the merge queue IS the coordination. \"Swarming an epic\" is colloquial for spawning multiple workers on its children.\n\n## Architecture\n\n- **Epics** group related work\n- **Issues** are individual tasks \n- **Dependencies** encode ordering (multi-wave emerges automatically)\n- **Merge queue** coordinates completed work\n- **Workers** process issues independently\n\nSee Key Decision #11 in docs/architecture.md: \"Work is a Stream (No Swarm IDs)\"\n\n## What This Epic Covers\n\n1. Integration branch management for batch merges\n2. Refinery semantic merge processing\n3. Witness landing protocol (cleanup)\n4. Report generation (epic-based, not swarm-ID-based)\n5. Git safety auditing\n6. Work reconciliation\n\n## What Was Removed\n\n- Swarm IDs (sw-1, sw-2, etc.)\n- Per-swarm directories (.gastown/swarms/\u003cid\u003e/)\n- Swarm manifest/state/events files\n- swarm-started/swarm-landed beads\n\nThese were redundant - beads already provides hierarchy, status, dependencies, and history.\n\n## References\n\n- Architecture: docs/architecture.md (Key Decision #11, Multi-Wave Work Processing)\n- PGT: swarm/manager.py, swarm/landing.py (behavioral reference, but ignore swarm ID patterns)","status":"open","issue_type":"epic","created_at":"2025-12-16T00:08:15.339127-08:00","updated_at":"2025-12-16T17:25:33.208338-08:00"}
{"id":"gt-3zg","title":"Verify architecture.md shows correct harness and rig structure","description":"Review architecture.md diagrams:\n- Verify town-level structure shows harness correctly\n- Confirm rig-level mayor/rig/ is shown (it appears to be there at line 197)\n- Check mermaid diagrams match ASCII diagrams\n- Update if any inconsistencies found\n- Cross-reference with new harness.md docs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:45.10268-08:00","updated_at":"2025-12-19T12:56:15.198431-08:00","closed_at":"2025-12-19T12:06:49.800234-08:00","dependencies":[{"issue_id":"gt-3zg","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:52.090317-08:00","created_by":"daemon"}]}
{"id":"gt-4nn.4","title":"Built-in molecules: engineer-in-box, quick-fix, research","description":"Create built-in molecules as Beads issues:\n\n## engineer-in-box\n\n```markdown\nid: mol-engineer-in-box\ntype: molecule\ntitle: Engineer in a Box\n\nFull workflow from design to merge.\n\n## Step: design\nThink carefully about architecture. Consider:\n- Existing patterns in the codebase\n- Trade-offs between approaches \n- Testability and maintainability\n\nWrite a brief design summary before proceeding.\n\n## Step: implement\nWrite the code. Follow codebase conventions.\nNeeds: design\n\n## Step: review\nSelf-review the changes. Look for:\n- Bugs and edge cases\n- Style issues\n- Missing error handling\nNeeds: implement\n\n## Step: test\nWrite and run tests. Cover happy path and edge cases.\nFix any failures before proceeding.\nNeeds: implement\n\n## Step: submit\nSubmit for merge via refinery.\nNeeds: review, test\n```\n\n## quick-fix\n\n```markdown\nid: mol-quick-fix\ntype: molecule \ntitle: Quick Fix\n\nFast path for small changes.\n\n## Step: implement\nMake the fix. Keep it focused.\n\n## Step: test\nRun relevant tests. Fix any regressions.\nNeeds: implement\n\n## Step: submit\nSubmit for merge.\nNeeds: test\n```\n\n## research\n\n```markdown\nid: mol-research\ntype: molecule\ntitle: Research\n\nInvestigation workflow.\n\n## Step: investigate\nExplore the question. Search code, read docs, \nunderstand context. Take notes.\n\n## Step: document\nWrite up findings. Include:\n- What you learned\n- Recommendations\n- Open questions\nNeeds: investigate\n```\n\n## Storage\n\nBuilt-in molecules live in `\u003ctown\u003e/.beads/` as regular issues.\nCreated during `gt install` or `bd init`.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T18:07:04.574565-08:00","updated_at":"2025-12-19T12:56:15.201354-08:00","closed_at":"2025-12-19T12:02:19.332406-08:00","dependencies":[{"issue_id":"gt-4nn.4","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:07:04.576587-08:00","created_by":"daemon"}]}
{"id":"gt-1qti","title":"Mayor restart loop: auto-prime and mail check on attach","description":"When mayor session cycles (after /exit, gt mayor attach reconnects), the new session lacks context.\n\n## Current Behavior\n- Mayor exits, shell script loop restarts claude\n- New session starts cold - no gt prime, no mail check\n- Mayor is disoriented, doesn't know prior context\n- Strong 'antimemetic properties' - we discuss fixing it, then forget\n\n## Expected Behavior\nAfter restart, mayor should automatically:\n1. Run gt prime (load role context)\n2. Check gt mail inbox (find handoff messages)\n3. Look for 🤝 HANDOFF messages from predecessor\n\n## Possible Fixes\n1. Startup hook in Claude Code settings that runs gt prime\n2. CLAUDE.md instructions that say 'FIRST THING: run gt prime'\n3. Shell script wrapper that injects context before attach\n4. Modify gt mayor attach to inject prime command\n\n## Related\n- gt-vci: Mayor handoff mail template\n- gt-sye: Mayor startup protocol prompting","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:44:43.188588-08:00","updated_at":"2025-12-19T17:22:52.550264-08:00","closed_at":"2025-12-19T16:03:20.714077-08:00"}
{"id":"gt-q8du","title":"Configuration in Beads: use pinned beads for rig/agent config","description":"## Summary\n\nMove configuration from JSON files into Beads data plane using pinned beads.\n\n## Motivation\n\n- Config becomes versionable and syncable like issues\n- Agents can read config via `bd show`\n- Unified data model for everything\n- Supports the 'Beads as Universal Data Plane' vision (gt-aqm)\n\n## Config Types to Migrate\n\n### Rig-level (pinned per rig)\n- Theme/colors for tmux status line\n- Default branch naming conventions\n- Merge queue settings\n- Witness thresholds\n\n### Agent-level (pinned per role)\n- Handoffs (already planned - gt-cu7r)\n- Agent preferences\n- Current focus/context\n\n### Town-level (pinned at town root)\n- Cross-rig settings\n- Federation config\n- Global themes\n\n## Implementation\n\n1. Implement StatusPinned (beads-6v2) ✓ in progress\n2. Create config pinned beads on rig init\n3. Add `bd config get/set` commands that read/write pinned beads\n4. Migrate existing config.json fields\n\n## Naming Convention\n\n```\n\u003cprefix\u003e-cfg-\u003cscope\u003e\ngt-cfg-theme # gastown theme\nbd-cfg-merge # beads merge settings\ngm-cfg-town # town-level config\n```\n\n## Dependencies\n\n- beads-6v2: Add StatusPinned to beads schema\n- gm-w13: Pinned Beads epic","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T21:58:59.898116-08:00","updated_at":"2025-12-18T21:58:59.898116-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-19T17:49:09.254329-08:00","closed_at":"2025-12-19T17:49:09.254329-08:00"}
{"id":"gt-svi.3","title":"gt mq status: detailed MR view","description":"Implement 'gt mq status \u003cid\u003e' command for detailed MR view.\n\nDisplay:\n- All MR fields (branch, target, source_issue, worker, rig)\n- Current status with timestamps\n- Dependencies (what it's waiting on)\n- Blockers (what's waiting on it)\n- Processing history (attempts, failures)\n\nUnder the hood: bd show \u003cid\u003e with MR-specific formatting.\n\nReference: docs/merge-queue-design.md#command-details","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:25.119914-08:00","updated_at":"2025-12-19T12:56:15.216589-08:00","closed_at":"2025-12-18T20:05:27.406362-08:00","dependencies":[{"issue_id":"gt-svi.3","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.676972-08:00","created_by":"daemon"},{"issue_id":"gt-svi.3","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:25.121848-08:00","created_by":"daemon"}]}
{"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-w775","title":"MR: gt-svi.1 (polecat/Furiosa)","description":"branch: polecat/Furiosa\ntarget: main\nsource_issue: gt-svi.1","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-18T20:21:40.921429-08:00","updated_at":"2025-12-18T20:21:54.163532-08:00","closed_at":"2025-12-18T20:21:54.163532-08:00"}
{"id":"gt-sr8","title":"Test merge request","description":"branch: polecat/Test/gt-test\ntarget: main\nsource_issue: gt-test\nworker: TestWorker\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-18T20:08:22.678439-08:00","updated_at":"2025-12-18T20:08:36.133169-08:00","closed_at":"2025-12-18T20:08:36.133169-08:00"}
{"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-19T14:54:35.149068-08:00","closed_at":"2025-12-19T14:54:35.149068-08:00"}
{"id":"gt-0pc","title":"Document Overseer role (human operator)","description":"Document the Overseer role in Gas Town architecture.\n\n## The Overseer\n\nThe **Overseer** is the human operator of Gas Town. Not an agent - a person.\n\n## Responsibilities\n\n| Area | Overseer Does | Mayor/Agents Do |\n|------|---------------|-----------------|\n| Strategy | Define project goals | Execute toward goals |\n| Priorities | Set priority order | Work in priority order |\n| Escalations | Final decision on stuck work | Escalate to Overseer |\n| Resources | Provision machines | Use allocated resources |\n| Quality | Review \u0026 approve swarm output | Produce output |\n| Operations | Run gt commands, monitor dashboards | Do the work |\n\n## Key Interactions\n\n### Overseer → Mayor\n- Start/stop Mayor sessions\n- Direct Mayor via conversation\n- Review Mayor recommendations\n- Approve cross-rig decisions\n\n### Mayor → Overseer (Escalations)\n- Stuck workers after retries\n- Resource decisions (add machines, polecats)\n- Ambiguous requirements\n- Architecture decisions\n\n## Operating Cadence\n\nTypical Overseer workflow:\n1. Morning: Check status, review overnight work\n2. During day: Monitor, respond to escalations, adjust priorities\n3. End of day: Review progress, plan next batch\n\n## Commands for Overseers\n\n```bash\ngt status # Quick health check\ngt doctor # Detailed diagnostics \ngt doctor --fix # Auto-repair issues\ngt inbox # Messages from agents\ngt stop --all # Emergency halt\n```\n\n## Documentation Updates\n\nAdd to docs/architecture.md:\n- Overseer section under Agent Roles\n- Clarify Mayor reports to Overseer\n- Add Overseer to workflow diagrams","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T23:18:03.177633-08:00","updated_at":"2025-12-15T23:22:51.477786-08:00","closed_at":"2025-12-15T23:22:51.477786-08:00"}
{"id":"gt-cik.2","title":"gt crew add: Create crew workspace","description":"Implement 'gt crew add \u003cname\u003e [--rig \u003crig\u003e]' command:\n- Clone repo into \u003crig\u003e/crew/\u003cname\u003e/\n- Create feature branch (optional, or stay on main)\n- Register for mail delivery\n- Initialize CLAUDE.md with crew worker prompting\n- Do NOT register with witness (user-managed)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:02.208618-08:00","updated_at":"2025-12-16T20:47:23.004728-08:00","closed_at":"2025-12-16T20:46:19.873949-08:00","dependencies":[{"issue_id":"gt-cik.2","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:02.210603-08:00","created_by":"daemon"}]}
{"id":"gt-71i","title":"Update architecture.md: Engineer role and Beads merge queue","description":"Update docs/architecture.md with recent design decisions:\n\n1. Agent table: Change \"Refinery\" role to \"Engineer\"\n - Refinery = place/module/directory\n - Engineer = role (agent that works in the Refinery)\n\n2. Merge Queue section: Document Beads-native model\n - MRs are beads issues with --type=merge-request\n - gt mq commands (submit, list, next, process, reorder)\n - Ordering via depends-on links\n\n3. CLI section: Add gt mq commands\n\n4. Key Design Decisions: Add decisions for:\n - #15: Merge Queue in Beads\n - #16: Engineer role (distinct from Refinery place)\n - #17: Session restart protocol for Engineer","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:12:03.616159-08:00","updated_at":"2025-12-16T23:12:03.616159-08:00","dependencies":[{"issue_id":"gt-71i","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:12:14.92163-08:00","created_by":"daemon"}]}
{"id":"gt-9a2","title":"Federation: Wasteland architecture for cross-town coordination","description":"## Overview\n\nFederation enables Gas Town to scale across machines via **Outposts** - remote compute environments that can run workers.\n\n**Design doc**: docs/federation-design.md\n\n## Outpost Types\n\n| Type | Description | Cost Model |\n|------|-------------|------------|\n| Local | Current model (tmux panes) | Free |\n| SSH/VM | Full Gas Town clone on VM | Always-on |\n| CloudRun | Container workers on GCP | Pay-per-use |\n\n## Key Concepts\n\n### Outpost Abstraction\n```go\ntype Outpost interface {\n Name() string\n Type() OutpostType // local, ssh, cloudrun\n MaxWorkers() int\n Spawn(issue string, config WorkerConfig) (Worker, error)\n Workers() []Worker\n Ping() error\n}\n```\n\n### Cloud Run Workers\n- Persistent HTTP/2 connections solve zero-to-one cold start\n- Pay only when working (~$0.017 per 5-min session)\n- Scale 0→N automatically\n- Git clone via persistent volumes\n\n### SSH/VM Outposts \n- Full Gas Town clone on remote machine\n- SSH for commands, git for sync\n- Good for long-running autonomous work\n\n## Design Principles\n\n1. **Outpost abstraction** - support multiple backends\n2. **Local-first** - remote is for overflow/burst\n3. **Git as source of truth** - code and beads sync everywhere\n4. **HTTP for Cloud Run** - dont force mail onto containers\n5. **Graceful degradation** - works with any subset of outposts\n\n## Related\n\n- gt-f9x.7-10: Connection interface (lower-level abstraction)\n- docs/federation-design.md: Full architectural analysis","status":"open","priority":3,"issue_type":"epic","created_at":"2025-12-15T19:21:32.462063-08:00","updated_at":"2025-12-16T18:01:24.224349-08:00"}
{"id":"gt-7hz3","title":"Merge: gt-92l","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-92l\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:31:37.716367-08:00","updated_at":"2025-12-19T18:26:14.102101-08:00","closed_at":"2025-12-19T17:48:09.627376-08:00"}
{"id":"gt-kmn.1","title":"Swarm package: Swarm, SwarmTask, SwarmState types","description":"Define core swarm types.\n\n## Types (in `internal/swarm/`)\n\n```go\n// SwarmState represents swarm lifecycle\ntype SwarmState string\nconst (\n SwarmCreated SwarmState = \"created\"\n SwarmActive SwarmState = \"active\"\n SwarmMerging SwarmState = \"merging\"\n SwarmLanded SwarmState = \"landed\"\n SwarmFailed SwarmState = \"failed\"\n SwarmCancelled SwarmState = \"cancelled\"\n)\n\n// Swarm references a beads epic that tracks swarm work\ntype Swarm struct {\n ID string // matches beads epic ID\n RigName string\n EpicID string // beads epic tracking this swarm\n BaseCommit string // git SHA all workers branch from\n Integration string // integration branch name\n State SwarmState\n CreatedAt time.Time\n Workers []string // polecat names assigned\n}\n\n// SwarmTask represents a single task in the swarm (maps to beads issue)\ntype SwarmTask struct {\n IssueID string // beads issue ID\n Assignee string // polecat name\n Branch string // worker branch name\n State string // mirrors beads status\n}\n```\n\n## Note\n\nSwarm state is primarily stored IN beads. These types are in-memory representations for the SwarmManager to work with. No separate manifest.json files.","status":"closed","issue_type":"task","created_at":"2025-12-16T00:08:30.364047-08:00","updated_at":"2025-12-16T13:31:56.20815-08:00","closed_at":"2025-12-16T13:31:56.20815-08:00","dependencies":[{"issue_id":"gt-kmn.1","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-16T00:11:20.646487-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.1","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:08:30.364431-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.4","title":"Tmux wrapper: session operations","description":"Wrapper for tmux session operations via subprocess.\n\n## Interface\n\n```go\ntype Tmux struct{}\n\nfunc NewTmux() *Tmux\n\n// Session lifecycle\nfunc (t *Tmux) NewSession(name, workDir string) error\nfunc (t *Tmux) KillSession(name string) error\nfunc (t *Tmux) HasSession(name string) (bool, error)\nfunc (t *Tmux) ListSessions() ([]string, error)\n\n// Session interaction\nfunc (t *Tmux) SendKeys(session, keys string) error\nfunc (t *Tmux) CapturePane(session string, lines int) (string, error)\nfunc (t *Tmux) AttachSession(session string) error\n\n// Window operations (if needed)\nfunc (t *Tmux) SelectWindow(session string, index int) error\n```\n\n## Session Naming\n\nConvention: `gt-\u003crig\u003e-\u003cpolecat\u003e` (e.g., `gt-wyvern-Toast`)\n\n## Implementation\n\n- Shell out to tmux binary\n- CapturePane uses `tmux capture-pane -p -t \u003csession\u003e -S -\u003clines\u003e`\n- SendKeys uses `tmux send-keys -t \u003csession\u003e '\u003ckeys\u003e' Enter`\n\n## Error Handling\n\n- \"no server running\": tmux not started (not an error for HasSession)\n- \"session not found\": session doesn't exist\n- Wrap all tmux errors with context\n\n## Environment\n\nRequires TMUX_TMPDIR or uses default socket. Don't assume tmux is running.","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:13.432706-08:00","updated_at":"2025-12-16T13:28:35.516697-08:00","closed_at":"2025-12-16T13:28:35.516697-08:00","dependencies":[{"issue_id":"gt-u1j.4","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:13:47.298442-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.4","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:13.433043-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.12","title":"HTTP work client: CloudRun dispatch client","description":"## Overview\n\nHTTP client for dispatching work to Cloud Run and streaming results back.\n\n## Implementation\n\n```go\ntype WorkClient struct {\n serviceURL string\n httpClient *http.Client // HTTP/2 enabled\n}\n\nfunc NewWorkClient(serviceURL string) *WorkClient {\n return \u0026WorkClient{\n serviceURL: serviceURL,\n httpClient: \u0026http.Client{\n Transport: \u0026http2.Transport{},\n Timeout: 0, // No timeout for streaming\n },\n }\n}\n\nfunc (c *WorkClient) DispatchWork(ctx context.Context, req WorkRequest) (\u003c-chan WorkEvent, error) {\n // 1. POST to /work\n // 2. Return channel that streams WorkEvents\n // 3. Close channel when done/error\n}\n```\n\n## Streaming Reader\n\n```go\nfunc (c *WorkClient) streamEvents(body io.Reader, events chan\u003c- WorkEvent) {\n defer close(events)\n decoder := json.NewDecoder(body)\n for {\n var event WorkEvent\n if err := decoder.Decode(\u0026event); err != nil {\n return\n }\n events \u003c- event\n }\n}\n```\n\n## Files\n\n- `internal/cloudrun/client.go`\n\n## Dependencies\n\nDepends on: gt-9a2.7 (protocol types)\nUsed by: gt-9a2.8 (CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:10.881936-08:00","updated_at":"2025-12-16T18:15:10.881936-08:00","dependencies":[{"issue_id":"gt-9a2.12","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:10.882339-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.12","depends_on_id":"gt-9a2.7","type":"blocks","created_at":"2025-12-16T18:15:20.974167-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.2","title":"LocalOutpost: Refactor current polecat spawning","description":"## Overview\n\nRefactor current local polecat spawning to implement the Outpost interface.\n\n## Current State\n\nPolecat spawning is ad-hoc. This task wraps it in LocalOutpost.\n\n## Implementation\n\n```go\ntype LocalOutpost struct {\n name string\n maxWorkers int\n tmux *Tmux\n workers map[string]*LocalWorker\n}\n\nfunc NewLocalOutpost(config OutpostConfig) *LocalOutpost\n\nfunc (o *LocalOutpost) Type() OutpostType { return OutpostLocal }\n\nfunc (o *LocalOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n // Create tmux session\n // Start claude in pane\n // Return LocalWorker\n}\n```\n\n## LocalWorker\n\n```go\ntype LocalWorker struct {\n id string\n session string // tmux session name\n issue string\n status WorkerStatus\n}\n\nfunc (w *LocalWorker) Attach() error {\n // tmux attach-session\n}\n```\n\n## Notes\n\n- This should be a refactor, not new functionality\n- Existing polecat code becomes LocalOutpost internals\n- Tests should pass before and after\n\nDepends on: gt-9a2.1 (interfaces)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:01:49.551224-08:00","updated_at":"2025-12-16T18:01:49.551224-08:00","dependencies":[{"issue_id":"gt-9a2.2","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:01:49.553291-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.2","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.338172-08:00","created_by":"daemon"}]}
{"id":"gt-4nn","title":"Molecules: Composable Workflow Beads","description":"## Summary\n\nMolecules are crystallized workflow patterns stored as Beads issues.\nWhen instantiated, the molecule creates child beads forming a DAG.\n\n## Key Insight: Molecules ARE Beads\n\nPer HOP Decision 001: Beads IS the ledger. Molecules don't get a separate YAML format - they're issues with `type: molecule` containing prose-based step definitions.\n\nAgents don't need rigid schemas. They parse natural language natively. A molecule is just instructions with enough structure for tooling.\n\n## Example: Engineer in a Box\n\n```markdown\nid: mol-xyz\ntype: molecule\ntitle: Engineer in a Box\n\nThis workflow takes a task from design to merge.\n\n## Step: design\nThink carefully about architecture. Consider existing patterns, \ntrade-offs, testability.\n\n## Step: implement\nWrite clean code. Follow codebase conventions.\nNeeds: design\n\n## Step: review \nReview for bugs, edge cases, style issues.\nNeeds: implement\n\n## Step: test\nWrite and run tests. Cover happy path and edge cases.\nNeeds: implement\n\n## Step: submit\nSubmit for merge via refinery.\nNeeds: review, test\n```\n\n## Instantiation\n\n```bash\n# Attach molecule when spawning\ngt spawn --issue gt-abc --molecule mol-xyz\n\n# Creates child beads atomically:\ngt-abc.design ← ready first\ngt-abc.implement ← blocked by design \ngt-abc.review ← blocked by implement\ngt-abc.test ← blocked by implement\ngt-abc.submit ← blocked by review, test\n```\n\nEach step issue gets an `instantiated-from` edge to the molecule (with step metadata).\n\n## Why This Matters\n\n1. **Unified data plane**: Everything in Beads, no parallel YAML channel\n2. **AI-native**: Prose instructions, not rigid schemas\n3. **Error isolation**: Each step is a checkpoint - failure doesn't lose progress\n4. **Scales with AI**: As agents get smarter, they handle more complex molecules\n\n## Implementation Primitives\n\n- `ParseMoleculeSteps()`: Extract steps from prose (convention-based)\n- `InstantiateMolecule()`: Atomic transaction creating all steps + edges \n- `instantiated-from` edge type: Track provenance\n- Parameterization: `{{variable}}` substitution from context map","status":"closed","issue_type":"epic","created_at":"2025-12-18T18:06:24.573068-08:00","updated_at":"2025-12-19T15:06:22.393412-08:00","closed_at":"2025-12-19T14:44:59.705427-08:00"}
{"id":"gt-8bx","title":"Adaptive backoff for daemon heartbeat","description":"Track agent responsiveness and adjust heartbeat frequency.\n\n## Per-Agent State\n\n```go\ntype AgentBackoff struct {\n BaseInterval time.Duration // 60s default\n CurrentInterval time.Duration // grows when busy\n MaxInterval time.Duration // 10min cap\n ConsecutiveMiss int // pokes with no response\n}\n```\n\n## Strategy Options\n\n- **Fixed**: Always 60s (current, simple)\n- **Geometric**: 60s → 90s → 135s → 202s (factor 1.5)\n- **Exponential**: 60s → 120s → 240s (factor 2, aggressive)\n\n## Recovery\n\nWhen agent responds (runs a command):\n- Reset ConsecutiveMiss to 0\n- Return to BaseInterval immediately\n\n## Benefits\n\n- Reduces noise for busy agents\n- Saves resources during quiet periods\n- Still catches stuck agents (max interval cap)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:33.083844-08:00","updated_at":"2025-12-19T12:56:15.204827-08:00","closed_at":"2025-12-19T12:09:31.613912-08:00","dependencies":[{"issue_id":"gt-8bx","depends_on_id":"gt-bfd","type":"blocks","created_at":"2025-12-18T14:19:46.912289-08:00","created_by":"daemon"}]}
{"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-g44u","title":"Molecule Workflow Engine: Composable Crystallized Workflows","description":"# Epic: Molecule Workflow Engine\n\n**Vision**: Molecules are crystallized, composable, nondeterministic-idempotent workflow templates. Any worker can pick up where any other worker was interrupted and continue along the molecule.\n\n**Christmas Target**: Full molecule-based workflow engine operational by Dec 25, 2025.\n\n## The Core Concepts\n\n1. **Molecule**: Read-only workflow template (beads issue with type=molecule)\n2. **Atom/Step**: Individual work unit with prose instructions\n3. **Bond**: Dependency between steps\n4. **Polymer/Derived**: Molecule composed from other molecules\n5. **Instance**: Concrete beads created when molecule is attached to work\n\n## Key Features Needed\n\n### 1. Molecule Composition (Includes Directive)\nMolecules can include other molecules:\n\\`\\`\\`markdown\n## Molecule: gastown-polecat\nIncludes: mol-engineer-in-box\n\n## Step: install-binary\nBuild and install the local gt binary.\nNeeds: submit\n\\`\\`\\`\n\n### 2. Standard Molecules\n- mol-install-go-binary: Single step to build/install gt\n- mol-gastown-polecat: engineer-in-box + install-binary\n\n### 3. Spawn Integration\n\\`gt spawn --issue \u003cid\u003e --molecule \u003cmol-id\u003e\\` creates molecule instance then starts polecat on first ready step.\n\n### 4. Nondeterministic Idempotence\n- Steps are atomic (pending → in_progress → completed)\n- Any worker can pick up any ready step\n- Step timeout/recovery for stuck workers\n\n## Success Criteria\n- [ ] Polecats can be spawned with mol-gastown-polecat\n- [ ] Derived molecules work end-to-end\n- [ ] 10+ polecat swarm completes molecule workflows\n- [ ] install-go-binary step runs after successful merges","status":"closed","issue_type":"epic","created_at":"2025-12-19T15:49:32.005023-08:00","updated_at":"2025-12-19T16:23:08.857768-08:00","closed_at":"2025-12-19T16:23:08.857768-08:00"}
{"id":"gt-17zr","title":"gt refinery start: doesn't actually start a session","description":"## Problem\n\n`gt refinery start gastown` reports success but doesn't start a tmux session.\n\n## Evidence\n\n```\n$ gt refinery start gastown\nStarting refinery for gastown...\n✓ Refinery started for gastown\n\n$ tmux list-sessions | grep refinery\n(nothing)\n\n$ gt refinery status gastown\nState: ○ stopped\n```\n\n## Expected\n\nShould start a tmux session (e.g., gt-gastown-refinery) with Claude processing the merge queue.\n\n## Related\n\n- gt-kcee: Witness commands also need implementation\n- The refinery 'start' may just be updating state.json without spawning a session","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:58:57.188389-08:00","updated_at":"2025-12-19T01:33:49.858934-08:00","closed_at":"2025-12-19T01:33:49.858934-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:19.879102-08:00","updated_at":"2025-12-15T23:17:18.556669-08:00","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-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-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:07.764838-08:00","updated_at":"2025-12-15T23:17:18.465919-08:00","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-86w","title":"CLI: doctor diagnostics and auto-repair","description":"GGT completely lacks the doctor command which is critical for debugging.\n\nRequired Commands:\n- gt doctor [\u003crig\u003e] - Run diagnostic checks\n- gt doctor --fix - Auto-repair common issues\n\nChecks to Implement:\nWorkspace Level: Config validity, Mayor mailbox, Rig registry\nRig Level: Git state, clone health, witness/refinery presence, beads sync\nSwarm Level: Stuck detection, zombie sessions, heartbeat health\n\nPGT Reference: gastown-py/src/gastown/cli/dashboard_cmd.py","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:34.721484-08:00","updated_at":"2025-12-16T16:03:17.405433-08:00","closed_at":"2025-12-16T16:03:17.405433-08:00"}
{"id":"gt-6tf","title":"Implement gt harness create command","description":"Add scaffolding command to create a new harness:\n- gt harness create [path]\n- Creates config/, mayor/, .beads/redirect (optional)\n- Optionally initializes git\n- Generates CLAUDE.md with Mayor role\n- Could also offer a template repo alternative","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:34.342552-08:00","updated_at":"2025-12-17T17:20:36.774805-08:00","closed_at":"2025-12-17T17:20:36.774805-08:00","dependencies":[{"issue_id":"gt-6tf","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.845578-08:00","created_by":"daemon"}]}
{"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-h5n.6","title":"gt mq integration status: show integration branch status","description":"Implement 'gt mq integration status \u003cepic\u003e' command.\n\nDisplay:\n- Integration branch name and creation date\n- Commits ahead of main\n- MRs merged to integration (closed)\n- MRs pending (open, targeting integration)\n- Comparison: main..integration/\u003cepic\u003e\n\nOutput example:\n Integration: integration/gt-auth-epic\n Created: 2025-12-17\n Ahead of main: 5 commits\n \n Merged MRs (3):\n gt-mr-001 Fix login timeout\n gt-mr-002 Fix session expiry \n gt-mr-003 Update auth config\n \n Pending MRs (1):\n gt-mr-004 Update auth tests (in_progress)\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:39.554771-08:00","updated_at":"2025-12-19T12:56:15.210196-08:00","closed_at":"2025-12-19T11:59:37.295064-08:00","dependencies":[{"issue_id":"gt-h5n.6","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:39.556726-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.6","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.528122-08:00","created_by":"daemon"}]}
{"id":"gt-6z2.2","title":"Test Task 2: Add comment to version.go","status":"closed","issue_type":"task","created_at":"2025-12-16T21:57:43.693217-08:00","updated_at":"2025-12-16T22:06:41.127126-08:00","closed_at":"2025-12-16T22:06:41.127126-08:00","dependencies":[{"issue_id":"gt-6z2.2","depends_on_id":"gt-6z2","type":"parent-child","created_at":"2025-12-16T21:57:43.69361-08:00","created_by":"daemon"}]}
{"id":"gt-cr0","title":"Consolidate design docs into beads descriptions","description":"The markdown design docs (swarm-shutdown-design.md, polecat-beads-access-design.md, mayor-handoff-design.md) will decay. Extract key decisions and prompting templates into the beads descriptions themselves, then archive or remove the markdown files. Beads are the source of truth.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:05.45131-08:00","updated_at":"2025-12-15T20:51:52.083465-08:00","closed_at":"2025-12-15T20:51:52.083465-08:00"}
{"id":"gt-4nn.3","title":"Molecule CLI: bd molecule commands","description":"Add molecule commands to bd:\n\n## Commands\n\n```bash\nbd molecule list # List molecules (type: molecule)\nbd molecule show \u003cid\u003e # Show molecule with parsed steps\nbd molecule parse \u003cid\u003e # Validate and show parsed structure \nbd molecule instantiate \u003cmol-id\u003e --parent=\u003cissue-id\u003e # Create steps\nbd molecule instances \u003cmol-id\u003e # Show all instantiations\n```\n\n## gt spawn integration\n\n```bash\ngt spawn --issue \u003cid\u003e --molecule \u003cmol-id\u003e\n```\n\nThis should:\n1. Call `bd molecule instantiate` (creates child beads atomically)\n2. Spawn polecat on first ready step\n3. Polecat grinds through via `bd ready`\n\n## Output Examples\n\n```\n$ bd molecule show mol-abc\n\nmol-abc: Engineer in a Box\nType: molecule\n\nSteps (5):\n design → (ready first)\n implement → Needs: design\n review → Needs: implement\n test → Needs: implement \n submit → Needs: review, test\n \nInstances: 3\n```\n\n```\n$ bd molecule instances mol-abc\n\nParent Status Created\ngt-xyz done 2025-12-15\ngt-abc active 2025-12-17 (3/5 complete)\ngt-def pending 2025-12-18\n```","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:53.919884-08:00","updated_at":"2025-12-19T12:56:15.200815-08:00","closed_at":"2025-12-19T12:00:37.165927-08:00","dependencies":[{"issue_id":"gt-4nn.3","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:53.921621-08:00","created_by":"daemon"},{"issue_id":"gt-4nn.3","depends_on_id":"gt-4nn.2","type":"blocks","created_at":"2025-12-18T18:07:03.048941-08:00","created_by":"daemon"}]}
{"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-u1j.9","title":"Witness daemon: heartbeat loop, spawn ephemeral agent","description":"Background daemon for agent lifecycle and monitoring.\n\n## Core Responsibilities\n\n1. **Heartbeat monitoring**: Check agent health periodically\n2. **Session lifecycle**: Restart agents after handoff (Witness Protection)\n3. **Polecat monitoring**: Track worker progress, nudging\n4. **Escalation**: Report failures to Mayor\n\n## Session Lifecycle (Witness Protection)\n\nThe daemon enables autonomous long-running operation by cycling agent sessions:\n\n```go\ntype SessionLifecycle struct {\n AgentType string // \"witness\", \"refinery\"\n StatePath string // path to state.json\n}\n\nfunc (d *Daemon) monitorSessionLifecycle(agent SessionLifecycle) {\n // 1. Detect session exit\n // 2. Check state.json for requesting_cycle: true\n // 3. If cycle requested: start new session, clear flag\n // 4. If unexpected exit: escalate to Mayor\n}\n```\n\nSee architecture.md Key Decision #12: Agent Session Lifecycle.\n\n## Interface\n\n```go\ntype Daemon struct {\n rig *Rig\n polecats *PolecatManager\n sessions *SessionManager\n config DaemonConfig\n}\n\ntype DaemonConfig struct {\n HeartbeatInterval time.Duration // default: 30s\n NudgeThreshold int // nudges before escalation\n MaxWorkers int // from rig config\n}\n\nfunc NewDaemon(rig *Rig) *Daemon\nfunc (d *Daemon) Start() error\nfunc (d *Daemon) Stop() error\n\n// Lifecycle\nfunc (d *Daemon) CycleSession(agentType string) error\nfunc (d *Daemon) SpawnWorker(issueID string) error\nfunc (d *Daemon) ShutdownWorker(polecat string) error\n```\n\n## Heartbeat Loop\n\nEvery HeartbeatInterval:\n1. Check Witness session (restart if cycle requested)\n2. Check Refinery session (restart if cycle requested)\n3. For each active polecat: assess progress, nudge if stuck\n4. Query `bd ready` for new work, spawn up to max_workers","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T17:12:29.389103-08:00","updated_at":"2025-12-18T12:38:32.125316-08:00","closed_at":"2025-12-18T11:50:12.047959-08:00","dependencies":[{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:29.389428-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T17:14:04.353775-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:04.440363-08:00","created_by":"daemon"}]}
{"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-72so","title":"gt mq list: doesn't show submitted MRs","description":"After submitting MRs with gt mq submit, gt mq list gastown shows empty queue.\n\n## Reproduction\n1. gt mq submit --issue gt-h5n.5 --branch polecat/Scabrous\n2. gt mq list gastown → (empty)\n3. bd list --type=merge-request → shows the MR\n\n## Expected\ngt mq list should show submitted MRs\n\n## MR example\ngt-ts4u has rig: gastown in description, type=merge-request, status=open","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:54:26.731813-08:00","updated_at":"2025-12-19T17:22:52.552662-08:00","closed_at":"2025-12-19T16:19:53.82455-08:00"}
{"id":"gt-974","title":"Refinery background daemon mode","description":"The refinery 'gt refinery start' command only works in foreground mode (--foreground). Need to implement background daemon mode for production use.\n\nOptions:\n1. Use a separate tmux session for the refinery\n2. Implement proper daemonization\n3. Use Claude Code session for the refinery agent\n\nFor MVP, option 1 (tmux session) is probably simplest.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T22:08:04.799753-08:00","updated_at":"2025-12-19T15:06:22.393972-08:00","closed_at":"2025-12-19T14:27:33.858745-08:00"}
{"id":"gt-9a2.10","title":"VM outpost setup: Terraform and documentation","description":"## Overview\n\nDocumentation and optional Terraform for setting up VM outposts.\n\n## Manual Setup Guide\n\n```markdown\n# Setting Up a VM Outpost\n\n## Prerequisites\n- GCE VM (or any Linux machine with SSH access)\n- SSH key pair\n- Git configured on VM\n\n## Steps\n\n1. Install Claude Code on VM:\n ```bash\n ssh user@vm\n npm install -g @anthropic-ai/claude-code\n ```\n\n2. Clone Gas Town:\n ```bash\n mkdir -p ~/ai\n cd ~/ai\n gt install .\n ```\n\n3. Configure Git credentials:\n ```bash\n git config --global user.name \"Your Name\"\n git config --global credential.helper store\n ```\n\n4. Add outpost to local config:\n ```bash\n gt outpost add ssh \\\n --name gce-burst \\\n --host 10.0.0.5 \\\n --user steve \\\n --key ~/.ssh/gce_worker \\\n --town-path /home/steve/ai \\\n --max-workers 8\n ```\n\n5. Test connectivity:\n ```bash\n gt outpost ping gce-burst\n ```\n```\n\n## Terraform Module (Optional)\n\n```hcl\n# deploy/terraform/vm-outpost/main.tf\n\nvariable \"project\" {}\nvariable \"zone\" { default = \"us-central1-a\" }\nvariable \"machine_type\" { default = \"e2-standard-4\" }\n\nresource \"google_compute_instance\" \"outpost\" {\n name = \"gastown-outpost\"\n machine_type = var.machine_type\n zone = var.zone\n\n boot_disk {\n initialize_params {\n image = \"ubuntu-2204-lts\"\n size = 100\n }\n }\n\n network_interface {\n network = \"default\"\n access_config {}\n }\n\n metadata_startup_script = file(\"${path.module}/startup.sh\")\n}\n\noutput \"external_ip\" {\n value = google_compute_instance.outpost.network_interface[0].access_config[0].nat_ip\n}\n```\n\n## Files\n\n- `docs/vm-outpost-setup.md`\n- `deploy/terraform/vm-outpost/` (optional)\n\nDepends on: gt-9a2.5 (SSHOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:34.782908-08:00","updated_at":"2025-12-16T18:03:34.782908-08:00","dependencies":[{"issue_id":"gt-9a2.10","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:34.78496-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.10","depends_on_id":"gt-9a2.5","type":"blocks","created_at":"2025-12-16T18:03:46.408609-08:00","created_by":"daemon"}]}
{"id":"gt-eqys","title":"gt spawn: pasted work assignment needs manual Enter to start","description":"## Problem\n\nAfter `gt spawn` pastes the work assignment into Claude, the session waits for Enter.\n\n## Current Behavior\n\n1. `gt spawn gastown/Rictus --issue gt-xxx`\n2. Session starts, work is pasted\n3. Claude shows 'Pasted text #1 +53 lines' but doesn't start\n4. Must manually send Enter or attach and press Enter\n\n## Expected\n\nThe spawn should send Enter after pasting to kick off the work.\n\n## Related\n\nSame debounce issue as tmux notifications (gt-vnp9).","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:54:14.111101-08:00","updated_at":"2025-12-19T12:01:32.74364-08:00","closed_at":"2025-12-19T12:01:32.74364-08:00"}
{"id":"gt-9a2.13","title":"CloudRun persistent connections: HTTP/2 keepalive","description":"## Overview\n\nImplement persistent HTTP/2 connections to keep Cloud Run containers warm.\n\n## Problem\n\nCloud Run has cold start latency when scaling from 0. Persistent connections keep containers warm.\n\n## Implementation\n\n```go\ntype PersistentConnectionManager struct {\n serviceURL string\n conn net.Conn\n client *http2.ClientConn\n mu sync.Mutex\n lastUsed time.Time\n keepAlive time.Duration\n}\n\nfunc (m *PersistentConnectionManager) GetConnection() (*http2.ClientConn, error) {\n m.mu.Lock()\n defer m.mu.Unlock()\n \n // Reuse existing connection if healthy\n if m.client != nil \u0026\u0026 m.client.CanTakeNewRequest() {\n m.lastUsed = time.Now()\n return m.client, nil\n }\n \n // Create new connection\n return m.dial()\n}\n\nfunc (m *PersistentConnectionManager) keepAliveLoop() {\n ticker := time.NewTicker(m.keepAlive / 2)\n for range ticker.C {\n m.mu.Lock()\n if time.Since(m.lastUsed) \u003e m.keepAlive {\n // Connection idle too long, close it\n m.close()\n } else {\n // Send ping to keep alive\n m.ping()\n }\n m.mu.Unlock()\n }\n}\n```\n\n## Integration with CloudRunOutpost\n\n```go\ntype CloudRunOutpost struct {\n // ...existing fields...\n connMgr *PersistentConnectionManager\n}\n\nfunc (o *CloudRunOutpost) Spawn(...) {\n conn, err := o.connMgr.GetConnection()\n // Use connection for work dispatch\n}\n```\n\n## Config\n\n```yaml\noutposts:\n - name: cloudrun-burst\n type: cloudrun\n # ...\n keep_alive: 5m # Keep connection warm for 5 minutes\n```\n\n## Files\n\n- `internal/cloudrun/connection.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (basic CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:57.082691-08:00","updated_at":"2025-12-16T18:15:57.082691-08:00","dependencies":[{"issue_id":"gt-9a2.13","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:12.190542-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.13","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:57.084539-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.5","title":"Swarm beads naming convention and auto-filing","description":"Beads naming convention for swarm lifecycle events.\n\n## Bead IDs\n\n- swarm-started:\u003cswarm-id\u003e # Filed when swarm begins\n- swarm-task-merged:\u003cswarm-id\u003e:\u003ctask-id\u003e # Filed per task merge\n- swarm-landed:\u003cswarm-id\u003e # Filed when merged to main\n- swarm-failed:\u003cswarm-id\u003e # Filed on unrecoverable failure\n\n## swarm-started Bead\n\nFiled by: Mayor/Refinery at swarm creation\nContains:\n- Swarm title and description\n- List of tasks (issue IDs)\n- List of workers (polecat names)\n- Base commit SHA\n\n## swarm-task-merged Bead\n\nFiled by: Refinery after each successful merge\nContains:\n- Task issue ID and title\n- Polecat name\n- Merge commit SHA\n- Test results summary\n\n## swarm-landed Bead\n\nFiled by: Refinery after landing to main\nContains:\n- Final merge commit SHA\n- Stats: tasks completed, time taken\n- List of all merged task beads\n- Integration branch name (now deleted)\n\n## swarm-failed Bead\n\nFiled by: Refinery on unrecoverable failure\nContains:\n- Failure reason\n- Tasks merged vs not merged\n- Recovery guidance\n\n## Why Beads (not just mail)\n\n- Persistent, queryable, synced to git\n- Other agents can check status without mail\n- Creates audit trail\n- Works when agents offline","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:46.930708-08:00","updated_at":"2025-12-16T17:23:21.089822-08:00","closed_at":"2025-12-16T17:23:21.089822-08:00","dependencies":[{"issue_id":"gt-kmn.5","depends_on_id":"gt-u1j.13","type":"blocks","created_at":"2025-12-16T00:11:24.81726-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.5","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:46.931086-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.5","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:24.746439-08:00","created_by":"daemon"}]}
{"id":"gt-cr9","title":"Harness Design \u0026 Documentation","description":"The harness (Gas Town installation directory) needs design cleanup, documentation, and tooling.\n\n## Current Problems\n\n1. **Shared harness confusion**: ~/ai is shared by PGT and GGT with overlapping structures\n - PGT uses ~/ai/mayor/ as town-level Mayor home\n - GGT Mayor works in ~/ai/mayor/rigs/gastown/\n - ~/ai/gastown/ has both .gastown/ (PGT) and mayor/ (git clone)\n\n2. **Beads redirect**: ~/ai/.beads/redirect → mayor/rigs/gastown/.beads\n - This is specific to GGT's decentralized structure\n - Should be documented as an example\n\n3. **architecture.md**: Verify rig-level mayor/rig/ is shown correctly\n\n4. **No harness creation tooling**: Users must manually set up\n\n## Proposed Work\n\n- Document what a harness IS (installation directory)\n- Create harness creation command or template repo\n- Update architecture.md if needed \n- Create example harness configuration for docs\n- Resolve PGT/GGT sharing issue","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T17:15:08.769961-08:00","updated_at":"2025-12-19T12:56:15.206358-08:00","closed_at":"2025-12-19T12:02:12.135837-08:00"}
{"id":"gt-szsq","title":"gt spawn --create should auto-add polecat if missing","description":"## Problem\n\n`gt spawn gastown --issue gt-xxx --create` fails if no polecats exist.\n\n## Current Behavior\n\n```\nError: auto-select polecat: no available polecats in rig 'gastown'\n```\n\n## Expected Behavior\n\n`--create` should:\n1. Create a new polecat if none exist\n2. Or create the specified polecat if `gt spawn gastown/NewName --create`\n\n## Workaround\n\nMust manually run `gt polecat add gastown Name` first.\n\n## Principle\n\nAgent UX should be forgiving - if I say spawn with --create, make it work.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:52:07.75062-08:00","updated_at":"2025-12-19T01:33:49.859926-08:00","closed_at":"2025-12-19T01:33:49.859926-08:00"}
{"id":"gt-yx4","title":"Town root .beads has schema mismatch with bd","description":"The .beads directory at town root (/Users/stevey/gt/.beads) has an incompatible schema:\n\n```\nError: failed to open database: failed to initialize schema: sqlite3: SQL logic error: no such column: thread_id\n```\n\nMeanwhile, gastown/.beads (symlinked to mayor/rig/.beads) works fine.\n\n## Impact\n\n- gt mail inbox fails at town root\n- gt handoff sends mail to broken db\n- Daemon can't check its inbox\n\n## Options\n\n1. Delete town root .beads/beads.db and let it recreate\n2. Symlink town root .beads to gastown/.beads\n3. Run schema migration on existing db\n\n## Root Cause\n\nLikely a beads version upgrade that added thread_id column, but the town root db was created before that.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T14:31:35.559042-08:00","updated_at":"2025-12-19T12:56:15.218062-08:00","closed_at":"2025-12-19T00:39:32.211083-08:00"}
{"id":"gt-43qg","title":"Test: release command verification","notes":"Released: testing release command","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-19T16:15:30.845537-08:00","updated_at":"2025-12-19T16:15:55.084052-08:00","closed_at":"2025-12-19T16:15:55.084052-08:00"}
{"id":"gt-h5n.2","title":"MR ID generation: prefix-mr-hash convention","description":"Generate merge-request IDs following the convention: \u003cprefix\u003e-mr-\u003chash\u003e\n\nExample: gt-mr-abc123 for a gastown merge request.\n\nThis distinguishes MRs from regular issues while keeping them in the same namespace.\nThe hash should be derived from branch name + timestamp for uniqueness.\n\nImplement: GenerateMRID(prefix, branch string) string\n\nReference: docs/merge-queue-design.md#id-convention","status":"closed","issue_type":"task","created_at":"2025-12-17T13:47:59.023788-08:00","updated_at":"2025-12-19T12:56:15.208684-08:00","closed_at":"2025-12-18T20:00:33.789237-08:00","dependencies":[{"issue_id":"gt-h5n.2","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:47:59.027042-08:00","created_by":"daemon"}]}
{"id":"gt-ktf3","title":"bd ready --type: missing type filter for MQ integration","description":"bd ready lacks --type flag that engineer.go expects.\n\n## Code (internal/refinery/engineer.go)\nreadyMRs, err := e.beads.ReadyWithType(\"merge-request\")\n\n## Actual bd ready\nNo --type flag - only supports assignee, label, priority filters.\n\n## Impact\nRefinery can't find merge-requests in queue, so MQ doesn't process anything.\n\n## Fix Options\n1. Add --type flag to bd ready\n2. Use bd list --type=merge-request --status=open instead\n3. Both (ready filters for unblocked, list for all)\n\nThis is blocking the entire MQ pipeline.","status":"closed","issue_type":"bug","created_at":"2025-12-19T14:57:16.297847-08:00","updated_at":"2025-12-19T15:04:17.322508-08:00","closed_at":"2025-12-19T15:04:17.322508-08:00"}
{"id":"gt-u82","title":"Design: Mayor session cycling and handoff","description":"Design for Mayor session cycling and structured handoff.\n\n## Overview\n\nMayor coordinates across all rigs and runs for extended periods. Needs session cycling pattern with structured handoff notes.\n\n## Key Elements\n\n1. Session cycling recognition (when to cycle)\n2. Handoff note format (structured state capture)\n3. Handoff delivery (mail to self)\n4. Fresh session startup (reading and resuming)\n\n## Subtasks (implementation)\n\n- gt-g2d: Mayor session cycling prompting\n- gt-sye: Mayor startup protocol prompting\n- gt-vci: Mayor handoff mail template\n- gt-1le: town handoff command (optional, P2)\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T20:03:16.125725-08:00","updated_at":"2025-12-15T20:49:26.203276-08:00","closed_at":"2025-12-15T20:16:10.772149-08:00"}
{"id":"gt-6t0","title":"gt swarm: Not discovering tasks from epic dependents","description":"gt swarm create/start shows '0 tasks loaded' even when epic has dependents.\n\nRepro:\n1. Create epic gt-hw6\n2. Create tasks and add deps: bd dep add gt-xxx gt-hw6\n3. gt swarm create gastown --epic gt-hw6 --worker Toast\n4. Swarm shows 'Tasks: 0'\n\nExpected: Swarm should discover tasks that depend on the epic.\nActual: Shows '(no tasks loaded)'","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:25:41.653628-08:00","updated_at":"2025-12-17T22:31:58.848858-08:00","closed_at":"2025-12-17T22:31:58.848858-08:00"}
{"id":"gt-axz","title":"Design: Plugin architecture (agents-as-plugins)","description":"Plugin system where plugins are just additional agents with identities, mailboxes, and beads access. See docs/architecture.md Plugins section. No special framework - just directory conventions and mail-based invocation.","status":"open","priority":3,"issue_type":"epic","created_at":"2025-12-15T22:52:43.614095-08:00","updated_at":"2025-12-15T23:17:04.627865-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:02.32832-08:00","updated_at":"2025-12-17T13:52:02.32832-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-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-g44u.5","title":"Spawn --molecule integration","description":"Implement gt spawn --molecule flag for molecule-based polecat workflows.\n\nUsage: gt spawn --issue gt-xyz --molecule mol-gastown-polecat\n\nBehavior:\n1. Validate molecule exists and is well-formed\n2. Create molecule instance (child beads) under the issue \n3. Find first ready step(s) in the instance\n4. Spawn polecat with first ready step as initial work\n\nImplementation:\n1. Add --molecule flag to spawn command\n2. Call molecule.Instantiate()\n3. Query ready steps from instance\n4. Pass first ready step to polecat context\n\nFiles: internal/cmd/spawn.go\n\nAcceptance:\n- --molecule flag works\n- Creates proper molecule instance\n- Polecat starts on first ready step\n- End-to-end test with actual polecat","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:24.519069-08:00","updated_at":"2025-12-19T16:13:10.086807-08:00","closed_at":"2025-12-19T16:13:10.086807-08:00","dependencies":[{"issue_id":"gt-g44u.5","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:24.521029-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.5","depends_on_id":"gt-g44u.1","type":"blocks","created_at":"2025-12-19T15:50:31.275526-08:00","created_by":"daemon"}]}
{"id":"gt-70b3","title":"detectSender() doesn't recognize crew workers","description":"## Problem\n\n`detectSender()` in mail.go only detects polecats, not crew workers.\n\n## Current Code (line 445)\n\n```go\n// If in a rig's polecats directory, extract address\nif strings.Contains(cwd, \"/polecats/\") {\n // extract rig/polecat\n}\n\n// Default to mayor\nreturn \"mayor/\"\n```\n\n## Symptom\n\nEmma (crew worker at `/Users/stevey/gt/beads/crew/emma`) runs:\n- `gt mail inbox` → checks `mayor/` inbox (wrong!)\n- Should check `beads/emma` or `beads/crew/emma`\n\n## Fix\n\nAdd crew detection:\n```go\n// If in a rig's crew directory, extract address \nif strings.Contains(cwd, \"/crew/\") {\n parts := strings.Split(cwd, \"/crew/\")\n if len(parts) \u003e= 2 {\n rigPath := parts[0]\n crewName := strings.Split(parts[1], \"/\")[0]\n rigName := filepath.Base(rigPath)\n return fmt.Sprintf(\"%s/%s\", rigName, crewName)\n }\n}\n```\n\n## Also Check\n\n- `gt prime` correctly detects role, so there may be another detection function that works\n- Should unify detection logic","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:40:26.520559-08:00","updated_at":"2025-12-18T21:55:54.679969-08:00","closed_at":"2025-12-18T21:55:54.679969-08:00","dependencies":[{"issue_id":"gt-70b3","depends_on_id":"gt-l4gm","type":"blocks","created_at":"2025-12-18T21:50:04.812663-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.1","title":"Config package: Config, State types and JSON serialization","description":"Config and state types with JSON serialization.\n\n## Town Config (config/town.json)\n\n```go\ntype TownConfig struct {\n Type string `json:\"type\"` // \"town\"\n Version int `json:\"version\"` // schema version\n Name string `json:\"name\"` // town identifier\n CreatedAt time.Time `json:\"created_at\"`\n}\n```\n\n## Rigs Registry (config/rigs.json)\n\n```go\ntype RigsConfig struct {\n Version int `json:\"version\"`\n Rigs map[string]RigEntry `json:\"rigs\"`\n}\n\ntype RigEntry struct {\n GitURL string `json:\"git_url\"`\n AddedAt time.Time `json:\"added_at\"`\n BeadsConfig *BeadsConfig `json:\"beads,omitempty\"`\n}\n\ntype BeadsConfig struct {\n Repo string `json:\"repo\"` // \"local\" | path | git-url\n Prefix string `json:\"prefix\"` // issue prefix\n}\n```\n\n## Agent State (*/state.json)\n\n```go\ntype AgentState struct {\n Role string `json:\"role\"` // \"mayor\", \"witness\", etc.\n LastActive time.Time `json:\"last_active\"`\n Session string `json:\"session,omitempty\"`\n Extra map[string]any `json:\"extra,omitempty\"`\n}\n```\n\n## Interface\n\n```go\nfunc LoadTownConfig(path string) (*TownConfig, error)\nfunc SaveTownConfig(path string, config *TownConfig) error\n\nfunc LoadRigsConfig(path string) (*RigsConfig, error)\nfunc SaveRigsConfig(path string, config *RigsConfig) error\n\nfunc LoadAgentState(path string) (*AgentState, error)\nfunc SaveAgentState(path string, state *AgentState) error\n```\n\n## Validation\n\n- Version compatibility checks\n- Required field validation\n- Path existence verification","status":"closed","issue_type":"task","created_at":"2025-12-15T16:36:50.163851-08:00","updated_at":"2025-12-16T13:24:26.497685-08:00","closed_at":"2025-12-16T13:24:26.497685-08:00"}
{"id":"gt-vdp0","title":"Crew workers getting wrong CLAUDE.md (shows Refinery)","description":"## Problem\n\nCrew workers (emma, dave) have CLAUDE.md that says they're the Refinery.\n\n## Evidence\n\n```\n$ head -5 /Users/stevey/gt/beads/crew/emma/CLAUDE.md\n# Claude: Beads Refinery\nYou are the **Refinery** for the **beads** rig...\n```\n\n## Expected\n\nShould use crew.md.tmpl which correctly says:\n```\n# Crew Worker Context\nYou are a **crew worker** - the overseer's (human's) personal workspace...\n```\n\n## Impact\n\n- Crew workers have wrong identity in static context\n- `gt prime` correctly outputs crew context, but CLAUDE.md conflicts\n- Confusing role information\n\n## Fix\n\nCheck `gt crew create` or whatever populates CLAUDE.md for crew workers.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:40:56.518032-08:00","updated_at":"2025-12-19T01:33:49.863259-08:00","closed_at":"2025-12-19T01:33:49.863259-08:00","dependencies":[{"issue_id":"gt-vdp0","depends_on_id":"gt-l4gm","type":"blocks","created_at":"2025-12-18T21:50:04.955247-08:00","created_by":"daemon"}]}
{"id":"gt-rixa","title":"Bug: parseLifecycleRequest always matches 'cycle' due to LIFECYCLE prefix","description":"In lifecycle.go, parseLifecycleRequest checks strings.Contains(title, \"cycle\") first, but the prefix \"LIFECYCLE:\" contains the word \"cycle\". This means ALL lifecycle messages match the cycle action, making restart and shutdown unreachable. Fix: check for restart/shutdown before cycle, or use word boundaries.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-19T16:17:16.083512-08:00","updated_at":"2025-12-19T16:17:24.480543-08:00"}
{"id":"gt-cik.3","title":"gt crew list: List crew workspaces","description":"Implement 'gt crew list [--rig \u003crig\u003e]' command:\n- List all crew workers in rig(s)\n- Show status (session running, last activity)\n- Show current branch and git status summary\n- Support --json output","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:03.53109-08:00","updated_at":"2025-12-16T20:59:33.356024-08:00","closed_at":"2025-12-16T20:53:16.668788-08:00","dependencies":[{"issue_id":"gt-cik.3","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:03.532953-08:00","created_by":"daemon"}]}
{"id":"gt-5af","title":"Deacon: Hierarchical health-check orchestrator","description":"Replace daemon heartbeats with Deacon - an AI agent that keeps Gas Town running.\n\n## Core Concept\n\nThe Deacon is a **Claude agent** (not just a Go process) that:\n- Lives at town root in gt-deacon session\n- Has its own mailbox (deacon/ identity in town beads)\n- Is poked by a minimal Go daemon every ~60s (if idle)\n- Monitors Mayor and Witnesses proactively\n- Handles lifecycle requests (restart/cycle) from Mayor, Witnesses, AND Crew\n\n## Architecture\n\n```\nMinimal Go Daemon (just watches Deacon)\n |\n v\n Deacon (Claude agent)\n |\n +----+----+\n v v\n Mayor Witnesses --\u003e Polecats (Witness-managed)\n | |\n +----+----+\n |\n Crew (lifecycle only, not monitored)\n```\n\n## Deacon Responsibilities\n\n**Proactive monitoring:**\n- Mayor health (tmux session, keepalive freshness)\n- Witness health (tmux sessions, keepalive freshness)\n\n**Reactive lifecycle:**\n- Process restart/cycle requests from Mayor, Witnesses, Crew\n- Kill session, create new, prime, verify startup\n\n**Escalation:**\n- Mail human (configurable) if issues can't be resolved\n\n## Key Files\n\n- ~/gt/DEACON.md - Role context\n- ~/gt/deacon/ - State directory\n - heartbeat.json - Written each wake cycle (daemon checks this)\n - state.json - Health tracking, last scan results\n- ~/gt/.beads/ - Town beads with deacon/ mail identity\n\n## Wake Cycle\n\n1. Write heartbeat (prevents daemon from poking)\n2. Check mail (lifecycle requests)\n3. Quick health scan (Mayor, Witnesses)\n4. Process lifecycle requests\n5. Remediate unhealthy agents\n6. Update state\n\n## Session Patterns\n\n- Deacon: gt-deacon\n- Mayor: gt-mayor\n- Witness: gt-\u003crig\u003e-witness\n- Crew: gt-\u003crig\u003e-\u003cname\u003e (e.g., gt-gastown-max)\n\n## Relation to Policy Beads\n\nFuture: Deacon behavior configurable via policy beads (gt-3zw).\nInitial implementation uses sensible defaults.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-12-18T18:32:28.083305-08:00","updated_at":"2025-12-19T17:22:52.553992-08:00","dependencies":[{"issue_id":"gt-5af","depends_on_id":"gt-3zw","type":"blocks","created_at":"2025-12-18T18:32:36.617594-08:00","created_by":"daemon"}]}
{"id":"gt-690z","title":"Test MR","description":"test","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-18T20:15:16.685471-08:00","updated_at":"2025-12-18T20:21:54.161643-08:00","closed_at":"2025-12-18T20:21:54.161643-08:00"}
{"id":"gt-b5sh","title":"test-after-fix","description":"test","status":"open","priority":2,"issue_type":"message","created_at":"2025-12-19T16:05:08.538763-08:00","updated_at":"2025-12-19T16:05:08.538763-08:00"}
{"id":"gt-qivm","title":"gt crew at: auto-prime when exec'ing Claude in-session","description":"When running 'gt crew at \u003cname\u003e' from inside the target session, we exec Claude directly. But this means we can't send 'gt prime' afterward since we ARE the process.\n\nPossible solutions:\n1. Claude startup hook that runs gt prime\n2. Pass prompt as argument to claude CLI\n3. Wrapper script approach\n\nRelated: crew resume prompt also can't be sent in this path.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T15:13:38.035775-08:00","updated_at":"2025-12-19T15:13:38.035775-08:00"}
{"id":"gt-r01","title":"EXTERNAL: Beads Messaging \u0026 Knowledge Graph (bd-kwro)","description":"Tracking issue for external dependency on Beads v0.30.2 messaging features.\n\nBeads epic: bd-kwro in ~/src/beads (steveyegge/beads repo)\n\nThis blocks GGT work that depends on:\n- bd mail send/inbox/read/ack commands\n- message issue type\n- replies_to threading\n- Hooks system for notifications\n- Identity configuration\n\nGGT mail commands will be thin wrappers around bd mail once available.\n\nWhen bd-kwro ships in Beads v0.30.2, close this and unblock dependent work.","status":"closed","issue_type":"task","created_at":"2025-12-16T13:12:02.676883-08:00","updated_at":"2025-12-16T21:35:05.795776-08:00","closed_at":"2025-12-16T21:35:05.795776-08:00"}
{"id":"gt-u1j.21","title":"Test infrastructure: fixtures, mocks, integration tests","description":"Test infrastructure for Gas Town.\n\n## Test Categories\n\n### Unit Tests\n- Config parsing\n- Mail operations\n- Merge queue operations\n- Template rendering\n\n### Integration Tests\n- Git operations (uses real git in temp dirs)\n- Full workflows (spawn → work → merge)\n- CLI command tests\n\n## Fixtures\n\n```go\npackage testutil\n\n// Creates temp town with minimal structure\nfunc NewTestTown(t *testing.T) *TestTown\n\n// Creates temp rig with git repo\nfunc NewTestRig(t *testing.T, town *TestTown, name string) *TestRig\n\n// Creates test polecat\nfunc NewTestPolecat(t *testing.T, rig *TestRig, name string) *TestPolecat\n```\n\n## Mocks\n\n```go\n// Mock tmux for session tests (avoid actual tmux)\ntype MockTmux struct {\n Sessions map[string][]string // captured send-keys\n}\n\nfunc (m *MockTmux) NewSession(name, dir string) error\nfunc (m *MockTmux) SendKeys(session, keys string) error\nfunc (m *MockTmux) CapturePane(session string, lines int) (string, error)\n```\n\n## Test Helpers\n\n```go\n// Run test in temp directory\nfunc InTempDir(t *testing.T, fn func(dir string))\n\n// Initialize git repo for testing\nfunc InitGitRepo(t *testing.T, dir string)\n\n// Assert file exists with content\nfunc AssertFileContains(t *testing.T, path, substr string)\n\n// Assert JSON file has field\nfunc AssertJSONField(t *testing.T, path, field string, expected any)\n```\n\n## CI Integration\n\n- go test ./... runs all tests\n- Integration tests skip with -short flag\n- Coverage report generation\n\n## Test Data\n\nEmbedded test fixtures:\n```go\n//go:embed testdata/*\nvar testdataFS embed.FS\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:28.755475-08:00","updated_at":"2025-12-15T21:21:56.470205-08:00","dependencies":[{"issue_id":"gt-u1j.21","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:28.755866-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.21","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.425389-08:00","created_by":"daemon"}]}
{"id":"gt-egu","title":"gt refinery attach: Attach to refinery session","description":"Add 'gt refinery attach [rig]' command to attach to refinery tmux session.\n\nMirrors 'gt mayor attach' pattern. If rig not specified, use current rig context.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:19.164342-08:00","updated_at":"2025-12-17T22:28:45.661097-08:00","closed_at":"2025-12-17T22:28:45.661097-08:00","dependencies":[{"issue_id":"gt-egu","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.578871-08:00","created_by":"daemon"}]}
{"id":"gt-bmjw","title":"gt polecat add: should handle existing branch gracefully","description":"## Problem\n\n`gt polecat add gastown Nux` fails if the branch `polecat/Nux` already exists.\n\n## Current Behavior\n\n```\nfatal: a branch named 'polecat/Nux' already exists\n```\n\n## Expected Behavior\n\nShould either:\n1. Reuse the existing branch\n2. Or prompt to delete/recreate\n3. Or auto-suffix: polecat/Nux-2\n\n## Context\n\nBranch may exist from previous polecat that was removed but branch wasn't cleaned up.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:52:09.361672-08:00","updated_at":"2025-12-18T21:52:09.361672-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-cik.8","title":"Crew worker CLAUDE.md prompting","description":"Create CLAUDE.md template for crew workers:\n- Explain crew worker role (overseer's personal workspace)\n- Include mail-to-self handoff instructions\n- Document gt crew refresh for context cycling\n- Explain no witness monitoring (user-managed)\n- Include beads usage if BEADS_DIR configured","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:48:12.108074-08:00","updated_at":"2025-12-16T20:59:02.00287-08:00","closed_at":"2025-12-16T20:59:02.00287-08:00","dependencies":[{"issue_id":"gt-cik.8","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:12.109654-08:00","created_by":"daemon"}]}
{"id":"gt-3x1.4","title":"Failure handling: assign back to worker, add labels","description":"Handle merge failures appropriately.\n\nFailure types and actions:\n| Failure | Action |\n|-------------|---------------------------------------------|\n| conflict | Add needs-rebase label, assign to worker |\n| tests_fail | Add needs-fix label, assign to worker |\n| build_fail | Add needs-fix label, assign to worker |\n| flaky_test | Retry once, then treat as tests_fail |\n| push_fail | Retry with backoff, escalate if persistent |\n\nActions:\n1. bd update \u003cid\u003e --status=open --assignee=\u003cworker\u003e\n2. bd update \u003cid\u003e --labels=\u003cfailure-label\u003e\n3. Send mail to worker explaining failure\n4. Log failure details\n\nReference: docs/merge-queue-design.md#handling-failures","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:17.238066-08:00","updated_at":"2025-12-19T15:27:45.509861-08:00","closed_at":"2025-12-19T14:48:36.428213-08:00","dependencies":[{"issue_id":"gt-3x1.4","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:17.240001-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.4","depends_on_id":"gt-3x1.1","type":"blocks","created_at":"2025-12-17T13:53:10.281038-08:00","created_by":"daemon"}]}
{"id":"gt-eu9","title":"Witness session cycling and handoff","description":"Add session cycling and handoff protocol to Witness CLAUDE.md template.\n\n## Session Cycling Protocol\n\n```markdown\n## Session Cycling\n\nYour context will fill over long swarms. Proactively cycle when:\n- Running for many hours\n- Losing track of which workers you've checked\n- Responses getting slower\n- About to start complex operation\n\n### Handoff Protocol\n\n1. **Capture current state**:\n```bash\ntown list . # Worker states\ntown all beads # Pending verifications \ntown inbox # Unprocessed messages\n```\n\n2. **Compose handoff note**:\n```\n[HANDOFF_TYPE]: witness_cycle\n[TIMESTAMP]: \u003cnow\u003e\n[RIG]: \u003crig\u003e\n\n## Active Workers\n\u003clist workers and status\u003e\n\n## Pending Verifications\n\u003cworkers signaled done but not verified\u003e\n\n## Recent Actions\n\u003clast 3-5 actions\u003e\n\n## Warnings/Notes\n\u003canything next session should know\u003e\n\n## Next Steps\n\u003cwhat should happen next\u003e\n```\n\n3. **Send handoff**:\n```bash\ntown mail send \u003crig\u003e/witness -s \"Session Handoff\" -m \"\u003cnote\u003e\"\n```\n\n4. **Exit cleanly**: End session, daemon spawns fresh one.\n\n### On Fresh Session Start\n\n1. Check for handoff: `town inbox | grep \"Session Handoff\"`\n2. If found, read it and resume from handoff state\n3. If not found, do full status check\n```\n\n## Implementation\n\nAdd to WITNESS_CLAUDE.md template.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:55.484911-08:00","updated_at":"2025-12-15T20:47:30.768506-08:00","dependencies":[{"issue_id":"gt-eu9","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.846443-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.7","title":"Session management: start, stop, attach, capture","description":"Polecat session lifecycle management.\n\n## Interface\n\n```go\ntype SessionManager struct {\n tmux *Tmux\n rig *Rig\n}\n\nfunc NewSessionManager(tmux *Tmux, rig *Rig) *SessionManager\n\n// Lifecycle\nfunc (sm *SessionManager) Start(polecat string, opts StartOptions) error\nfunc (sm *SessionManager) Stop(polecat string) error\nfunc (sm *SessionManager) IsRunning(polecat string) (bool, error)\nfunc (sm *SessionManager) List() ([]SessionInfo, error)\n\n// Interaction\nfunc (sm *SessionManager) Attach(polecat string) error\nfunc (sm *SessionManager) Capture(polecat string, lines int) (string, error)\nfunc (sm *SessionManager) Inject(polecat string, message string) error\n\ntype StartOptions struct {\n WorkDir string // defaults to polecat clone dir\n Issue string // optional: issue to work on\n Command string // optional: override claude command\n}\n\ntype SessionInfo struct {\n Polecat string\n SessionID string\n Running bool\n StartedAt time.Time\n}\n```\n\n## Session Naming\n\n`gt-\u003crig\u003e-\u003cpolecat\u003e` (e.g., `gt-wyvern-Toast`)\n\n## Start Flow\n\n1. Verify polecat clone exists\n2. Check no existing session\n3. Create tmux session in polecat workdir\n4. Send initial command: `claude` or custom\n5. If issue provided, inject initial prompt\n\n## Stop Flow\n\n1. Capture final output (for logging)\n2. Send exit/quit command\n3. Wait briefly for graceful shutdown\n4. Kill session if still running\n\n## Capture\n\nUses tmux capture-pane to get recent output. Returns last N lines.\n\n## Inject\n\nSends text to session via tmux send-keys. Used for:\n- Mail notifications\n- Witness nudges\n- User messages","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:25.473674-08:00","updated_at":"2025-12-16T13:35:22.862077-08:00","closed_at":"2025-12-16T13:35:22.862077-08:00","dependencies":[{"issue_id":"gt-u1j.7","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:25.473993-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.7","depends_on_id":"gt-u1j.4","type":"blocks","created_at":"2025-12-15T17:13:52.081053-08:00","created_by":"daemon"}]}
{"id":"gt-sd6","title":"Enhanced polecat decommission prompting","description":"Add decommission checklist to polecat AGENTS.md.template. Make crystal clear: verify ALL before signaling done.\n\n## Checklist for AGENTS.md.template\n\n```markdown\n## Decommission Checklist\n\n**CRITICAL**: Before signaling done, you MUST complete this checklist.\nThe Witness will verify each item and bounce you back if dirty.\n\n### Pre-Done Verification\n\n```bash\n# 1. Git status - must be clean\ngit status\n# Expected: \"nothing to commit, working tree clean\"\n\n# 2. Stash list - must be empty\ngit stash list\n# Expected: (empty output)\n\n# 3. Beads sync - must be up to date\nbd sync --status\n# Expected: \"Up to date\" or \"Nothing to sync\"\n\n# 4. Branch merged - your work must be on main\ngit log main --oneline -1\ngit log HEAD --oneline -1\n# Expected: Same commit\n```\n\n### If Any Check Fails\n\n- **Uncommitted changes**: Commit them or discard if unnecessary\n- **Stashes**: Pop and commit, or drop if obsolete\n- **Beads out of sync**: Run `bd sync`\n- **Branch not merged**: Complete the merge workflow\n\n### Signaling Done\n\nOnly after ALL checks pass:\n\n```bash\nbd close \u003cissue-id\u003e\nbd sync\ntown mail send \u003crig\u003e/witness -s \"Work Complete\" -m \"Issue \u003cid\u003e done.\"\n```\n```\n\n## Implementation\n\nAdd to AGENTS.md.template in the polecat prompting section.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:57.911311-08:00","updated_at":"2025-12-15T20:47:30.062333-08:00","dependencies":[{"issue_id":"gt-sd6","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:06.008061-08:00","created_by":"daemon"}]}
{"id":"gt-3tz","title":"CLI: polecat commands (add, list, wake, sleep, decommission)","description":"GGT is missing most polecat management commands that PGT has.\n\nMissing Commands:\n- gt polecat add \u003crig\u003e \u003cname\u003e - Add polecat to rig (creates clone)\n- gt polecat list [\u003crig\u003e] - List polecats with state\n- gt polecat info \u003cpolecat\u003e - Show detailed info\n- gt polecat wake \u003cpolecat\u003e - Mark available\n- gt polecat sleep \u003cpolecat\u003e - Mark unavailable \n- gt polecat decommission \u003cpolecat\u003e - Remove polecat safely\n\nPGT Reference: gastown-py/src/gastown/cli/polecat_cmd.py\n\nNotes:\n- spawn exists but doesn't cover management\n- wake/sleep are in polecat manager but not CLI\n- decommission should check for uncommitted work","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:31.326692-08:00","updated_at":"2025-12-16T16:03:14.462338-08:00","closed_at":"2025-12-16T16:03:14.462338-08:00"}
{"id":"gt-jpt","title":"Town-level beads: Real DB for coordination mail","description":"Implement Option A from mail redesign: Town gets real beads DB for coordination.\n\n## Background\n\nMail is now Beads. But currently:\n- Town .beads/redirect points to rig beads\n- mayor/mail/ has legacy JSONL files\n- Cross-rig coordination has no clear home\n\n## Design\n\nTown beads = coordination, cross-rig mail, mayor inbox, handoffs\nRig beads = project issues, work items\n\nMatches HOP hierarchy: platform \u003e project \u003e worker\n\n## Structure\n\n~/gt/\n .beads/ # REAL beads DB (prefix: gm-)\n mayor/\n town.json\n state.json # NO mail/ directory\n gastown/\n .beads/ # Rig beads (prefix: ga-)\n\n## Tasks\n\n1. Delete ~/gt/.beads/redirect\n2. Run bd init --prefix gm at ~/gt/ (town beads)\n3. Delete ~/gt/mayor/mail/ directory\n4. Update gt mail to use beads not JSONL\n5. Add mail fields (thread_id, reply_to, msg_type)\n6. Update gt prime for two-tier model\n7. Update docs/architecture.md\n\n## Addressing\n\n- mayor/ -\u003e town beads\n- rig/agent -\u003e rig beads\n- Cross-rig -\u003e town beads","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T19:09:55.855955-08:00","updated_at":"2025-12-19T12:56:15.212847-08:00","closed_at":"2025-12-19T01:57:17.032558-08:00"}
{"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-5qc","title":"Document how to configure a Gas Town Harness","description":"Create docs explaining what a harness is (private repo containing GT installation with rigs gitignored), why you'd want one, and how to set it up with beads redirects","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T16:42:43.370167-08:00","updated_at":"2025-12-19T12:56:15.202473-08:00","closed_at":"2025-12-19T12:00:39.274285-08:00","dependencies":[{"issue_id":"gt-5qc","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:59.17545-08:00","created_by":"daemon"},{"issue_id":"gt-5qc","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.620984-08:00","created_by":"daemon"}]}
{"id":"gt-h5n","title":"Merge Queue in Beads: Universal chit system for all work","description":"\n\n**Design doc**: docs/merge-queue-design.md","status":"open","issue_type":"epic","created_at":"2025-12-16T23:01:45.782171-08:00","updated_at":"2025-12-17T13:43:43.211867-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-17T13:52:34.770778-08:00","updated_at":"2025-12-17T13:52:34.770778-08:00","dependencies":[{"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-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"}]}
{"id":"gt-iib","title":"Architecture: Decentralized rig structure with per-rig agents","description":"## Decision\n\nAdopt decentralized architecture where each rig contains all its agents (mayor/, witness/, refinery/, polecats/) rather than centralizing mayor clones at town level.\n\n## Town Level Structure\n\n```\n~/ai/ # Town root\n├── config/ # Town config (VISIBLE, not hidden)\n│ ├── town.json # {\"type\": \"town\"}\n│ ├── rigs.json # Registry of managed rigs\n│ └── federation.json # Wasteland config (future)\n│\n├── mayor/ # Mayor's HOME at town level\n│ ├── CLAUDE.md\n│ ├── mail/inbox.jsonl\n│ └── state.json\n│\n└── \u003crigs\u003e/ # Managed projects\n```\n\n## Rig Level Structure (e.g., wyvern)\n\n```\nwyvern/ # Rig = clone of project repo\n├── .git/info/exclude # Gas Town adds: polecats/ refinery/ witness/ mayor/\n├── .beads/ # Beads (if project uses it)\n├── [project files] # Clean project code on main\n│\n├── polecats/ # Worker clones\n│ └── \u003cname\u003e/ # Each is a git clone\n│\n├── refinery/\n│ ├── rig/ # Refinery's clone\n│ ├── state.json\n│ └── mail/inbox.jsonl\n│\n├── witness/ # NEW: Per-rig pit boss\n│ ├── rig/ # Witness's clone\n│ ├── state.json\n│ └── mail/inbox.jsonl\n│\n└── mayor/\n ├── rig/ # Mayor's clone for this rig\n └── state.json\n```\n\n## Key Decisions\n\n1. **Visible config dir**: `config/` not `.gastown/` (models don't find hidden dirs)\n2. **Witness per-rig**: Each rig has its own Witness (pit boss) with its own clone\n3. **Mayor decentralized**: Mayor's clones live IN each rig at `\u003crig\u003e/mayor/rig/`\n4. **Minimal invasiveness**: Only `.git/info/exclude` modified, no commits to project\n5. **Clone subdir name**: Keep `rig/` for consistency (refinery/rig/, witness/rig/, mayor/rig/)\n\n## Role Detection\n\n- Town root or mayor/ → Mayor (town level)\n- Rig root → Mayor (canonical main)\n- \u003crig\u003e/mayor/rig/ → Mayor (rig-specific)\n- \u003crig\u003e/refinery/rig/ → Refinery\n- \u003crig\u003e/witness/rig/ → Witness\n- \u003crig\u003e/polecats/\u003cname\u003e/ → Polecat\n\n## Migration from PGT\n\n- `mayor/rigs/\u003crig\u003e/` → `\u003crig\u003e/mayor/rig/`\n- `\u003crig\u003e/town/` → eliminated (rig root IS the clone)\n- Add `witness/` to each rig","status":"closed","issue_type":"task","created_at":"2025-12-15T19:21:19.913928-08:00","updated_at":"2025-12-15T19:21:40.461186-08:00","closed_at":"2025-12-15T19:21:40.461186-08:00","dependencies":[{"issue_id":"gt-iib","depends_on_id":"gt-u1j","type":"blocks","created_at":"2025-12-15T19:21:40.374551-08:00","created_by":"daemon"}]}
{"id":"gt-cik.7","title":"gt crew status: Show workspace status","description":"Implement 'gt crew status [\u003cname\u003e]' command:\n- Show session state (running/stopped)\n- Show git status (branch, uncommitted changes, unpushed)\n- Show last commit info\n- Show mail inbox status (unread count)\n- If no name given, show all crew workers","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:48:10.476059-08:00","updated_at":"2025-12-16T20:53:16.70417-08:00","closed_at":"2025-12-16T20:53:16.70417-08:00","dependencies":[{"issue_id":"gt-cik.7","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:10.477638-08:00","created_by":"daemon"}]}
{"id":"gt-xpq","title":"Add gt crew rename command","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T19:45:32.599846-08:00","updated_at":"2025-12-18T19:46:17.780981-08:00","closed_at":"2025-12-18T19:46:17.780981-08:00"}
{"id":"gt-fko","title":"Add Gas Town theory of operation to all role primings","description":"All roles (Mayor, Witness, Refinery, Polecat) should get basic GT architecture context: harness, rigs, agents, mail, beads workflow","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T16:42:46.445526-08:00","updated_at":"2025-12-17T17:00:36.466742-08:00","closed_at":"2025-12-17T17:00:36.466742-08:00","dependencies":[{"issue_id":"gt-fko","depends_on_id":"gt-dkc","type":"blocks","created_at":"2025-12-17T16:42:56.409618-08:00","created_by":"daemon"},{"issue_id":"gt-fko","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.87032-08:00","created_by":"daemon"}]}
{"id":"gt-4nn.2","title":"Molecule instantiation: create child beads from template","description":"When instantiating a molecule on a work bead:\n\n## Transaction Flow\n\n1. Parse molecule's `## Step:` sections from description\n2. Begin SQLite transaction\n3. For each step, create child issue:\n - ID: `{parent-id}.{step-ref}` or generated\n - Title: step title (from header or first line)\n - Description: step prose instructions\n - Type: task\n - Priority: inherit from parent\n4. Add `instantiated-from` edge from each step to molecule:\n ```sql\n INSERT INTO dependencies (issue_id, depends_on_id, type, metadata)\n VALUES (step_id, mol_id, 'instantiated-from', '{\"step\": \"implement\"}');\n ```\n5. Wire inter-step dependencies from `Needs:` lines\n6. Commit transaction (atomic - all or nothing)\n\n## Parsing Conventions\n\n```markdown\n## Step: \u003cref\u003e\n\u003cprose instructions\u003e\nNeeds: \u003cstep\u003e, \u003cstep\u003e # optional\nTier: haiku|sonnet|opus # optional hint\n```\n\n## Parameterization\n\nSteps can have `{{variable}}` placeholders:\n```markdown\n## Step: implement\nImplement {{feature_name}} in {{target_file}}.\n```\n\nContext map provided at instantiation time.\n\n## API\n\n```go\nfunc (s *Store) InstantiateMolecule(mol *Issue, parent *Issue, ctx map[string]string) ([]*Issue, error)\nfunc ParseMoleculeSteps(description string) ([]MoleculeStep, error)\n```\n\nImplementation lives in `internal/beads/molecule.go`.","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:52.071066-08:00","updated_at":"2025-12-19T12:56:15.200215-08:00","closed_at":"2025-12-19T01:57:17.028198-08:00","dependencies":[{"issue_id":"gt-4nn.2","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:52.072554-08:00","created_by":"daemon"},{"issue_id":"gt-4nn.2","depends_on_id":"gt-4nn.1","type":"blocks","created_at":"2025-12-18T18:07:02.949242-08:00","created_by":"daemon"}]}
{"id":"gt-98oo","title":"Merge: gt-y5o","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-y5o\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:29:03.837448-08:00","updated_at":"2025-12-19T18:26:14.102603-08:00","closed_at":"2025-12-19T17:47:03.619784-08:00"}
{"id":"gt-cik","title":"Overseer Crew: User-managed persistent workspaces","description":"## Overview\n\nCrew workers are the overseer's (human's) personal workspaces within a rig. Unlike polecats which are witness-managed and ephemeral, crew workers are:\n\n- **Persistent**: Not auto-garbage-collected\n- **User-managed**: Overseer controls lifecycle\n- **Long-lived identities**: dave, emma, fred - recognizable names\n- **Gas Town integrated**: Mail, handoff mechanics work\n- **Tmux optional**: Can work in terminal directly\n\n## Directory Structure\n\n```\n\u003crig\u003e/\n polecats/ # Managed workers (witness controls)\n refinery/ # Merge queue processor\n witness/ # Pit boss\n crew/ # Overseer's personal workspaces\n dave/ # Full clone, persistent\n emma/ # Full clone, persistent\n fred/ # Full clone, persistent\n```\n\n## Key Differences from Polecats\n\n- Location: crew/ instead of polecats/\n- Lifecycle: User-managed, not witness-managed\n- Auto-cleanup: Never (polecats auto-cleanup on swarm land)\n- Issue assignment: Optional (polecats require it)\n- Tmux: Optional (polecats require it)\n- Mail \u0026 Handoff: Yes for both\n- Identity: Persistent (polecats are ephemeral)\n\n## CLI Commands\n\n- gt crew add \u003cname\u003e [--rig \u003crig\u003e] - Create crew workspace\n- gt crew list [--rig \u003crig\u003e] - List crew workspaces\n- gt crew at \u003crig\u003e/\u003cname\u003e - Attach to workspace (start session)\n- gt crew attach \u003cname\u003e - Attach (infer rig from cwd)\n- gt crew refresh \u003cname\u003e - Handoff + restart (context cycling)\n- gt crew remove \u003cname\u003e [--force] - Remove workspace\n- gt crew status [\u003cname\u003e] - Show workspace status\n\n## Design Notes\n\n- Crew workers use full git clones (not worktrees)\n- Optional beads integration via BEADS_DIR\n- Mail-to-self handoff works for context cycling\n- No witness monitoring or nudging\n- No automatic issue assignment required\n\n## Background\n\nUsers often maintain separate repo clones for serial agent work. This is tedious to set up manually. Crew workspaces bring these into Gas Town's infrastructure while keeping user control.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-16T16:47:37.529887-08:00","updated_at":"2025-12-16T20:59:46.13518-08:00","closed_at":"2025-12-16T20:59:46.13518-08:00"}
{"id":"gt-cik.9","title":"Complete gt crew commands (list, attach, remove, refresh, status)","description":"Add remaining crew subcommands to internal/cmd/crew.go:\n\n1. gt crew list - List crew workspaces with status\n2. gt crew at/attach - Start tmux session in crew workspace \n3. gt crew remove - Remove crew workspace (with safety checks)\n4. gt crew refresh - Context cycling with mail-to-self handoff\n5. gt crew status - Show detailed workspace status\n\nBuild on existing crew add implementation in internal/cmd/crew.go.\nReference closed issues gt-cik.3-7 for original requirements.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T20:53:25.564877-08:00","updated_at":"2025-12-16T20:59:02.001789-08:00","closed_at":"2025-12-16T20:59:02.001789-08:00","dependencies":[{"issue_id":"gt-cik.9","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T20:53:25.566962-08:00","created_by":"daemon"}]}
{"id":"gt-xkbm","title":"Merge: gt-g44u.1","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-g44u.1\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:04:14.367493-08:00","updated_at":"2025-12-19T17:35:38.210747-08:00","closed_at":"2025-12-19T17:35:38.210747-08:00"}
{"id":"gt-l3c","title":"Design: Polecat Beads write access","description":"Design for granting polecats direct beads write access.\n\n## Background\n\nWith Beads v0.30.0 tombstone-based rearchitecture, we have solid multi-agent support. Reversing the original read-only decision.\n\n## Benefits\n\n- Simplifies architecture (no mail-based issue filing proxy)\n- Empowers polecats to file discovered work\n- Beads handles work-disavowal\n\n## Complications\n\nFor OSS projects where you cannot commit to project .beads/, need per-rig beads repo configuration.\n\n## Subtasks (implementation)\n\n- gt-zx3: Per-rig beads configuration schema\n- gt-e1y: Worker prompting updates for beads access\n- gt-cjb: Witness proxy removal\n- gt-082: Beads sync in decommission checklist\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T19:37:42.191734-08:00","updated_at":"2025-12-15T20:49:24.598429-08:00","closed_at":"2025-12-15T20:14:04.174535-08:00"}
{"id":"gt-u1j.5","title":"Rig management: discover, load, create rigs","description":"Rig discovery, loading, and creation.\n\n## Interface\n\n```go\ntype Rig struct {\n Name string\n Path string\n GitURL string\n Config RigConfig\n Polecats []string\n HasWitness bool\n HasRefinery bool\n}\n\ntype RigManager struct {\n townRoot string\n config *Config\n git *Git\n}\n\nfunc NewRigManager(townRoot string, config *Config, git *Git) *RigManager\n\n// Discovery\nfunc (rm *RigManager) DiscoverRigs() ([]*Rig, error)\nfunc (rm *RigManager) GetRig(name string) (*Rig, error)\nfunc (rm *RigManager) RigExists(name string) bool\n\n// Creation\nfunc (rm *RigManager) AddRig(name, gitURL string) (*Rig, error)\nfunc (rm *RigManager) RemoveRig(name string) error\n\n// Rig state\nfunc (rm *RigManager) LoadRigConfig(rig *Rig) error\nfunc (rm *RigManager) SaveRigConfig(rig *Rig) error\n```\n\n## Discovery Logic\n\n1. Read rigs.json from config/\n2. For each registered rig, verify directory exists\n3. Load rig-level config if present\n4. Scan for polecats/ subdirectory\n5. Check for witness/, refinery/ directories\n\n## Rig Creation\n\n1. Clone repo to town root\n2. Add entry to rigs.json\n3. Create agent directories (polecats/, witness/, refinery/, mayor/)\n4. Update .git/info/exclude to ignore agent dirs\n5. Initialize rig config\n\n## Rig Structure\n\nPer docs/architecture.md:\n```\n\u003crig\u003e/\n├── polecats/\n├── refinery/rig/\n├── witness/rig/\n└── mayor/rig/\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:15.034694-08:00","updated_at":"2025-12-16T13:33:52.924291-08:00","closed_at":"2025-12-16T13:33:52.924291-08:00","dependencies":[{"issue_id":"gt-u1j.5","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:15.035022-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.5","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:13:49.93957-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.5","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T17:13:50.047236-08:00","created_by":"daemon"}]}
{"id":"gt-n508","title":"Merge: gt-70b3","description":"type: merge-request\nbranch: polecat/Rictus\ntarget: main\nsource_issue: gt-70b3\nrig: gastown","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T21:56:57.840796-08:00","updated_at":"2025-12-18T22:16:39.940524-08:00","closed_at":"2025-12-18T22:16:39.940524-08:00"}
{"id":"gt-h5n.4","title":"gt mq integration create: create integration branch for epic","description":"Implement 'gt mq integration create \u003cepic\u003e' command.\n\nActions:\n1. Verify epic exists\n2. Create branch: integration/\u003cepic-id\u003e from main\n3. Push to origin\n4. Store integration branch info in epic metadata\n\nUsage:\n gt mq integration create gt-auth-epic\n # Creates integration/gt-auth-epic from main\n\nFuture MRs for this epic's children will auto-target this branch.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:35.679837-08:00","updated_at":"2025-12-19T12:56:15.209731-08:00","closed_at":"2025-12-19T01:57:17.029802-08:00","dependencies":[{"issue_id":"gt-h5n.4","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:35.681828-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.4","depends_on_id":"gt-svi.1","type":"blocks","created_at":"2025-12-17T13:53:16.28634-08:00","created_by":"daemon"}]}
{"id":"gt-cjb","title":"Witness updates: Remove issue filing proxy","description":"Update Witness prompting to remove issue filing proxy, since polecats now have direct beads access.\n\n## Remove from Witness Prompting\n\nThe following is NO LONGER Witness responsibility:\n- Processing polecat 'file issue' mail requests\n- Creating issues on behalf of polecats\n- Forwarding issue creation requests\n\n## Add: Legacy Request Handling\n\nIf Witness receives an old-style 'please file issue' request:\n\n1. Respond with update:\n town inject \u003cpolecat\u003e \"UPDATE: You have direct beads access now. Use bd create to file issues yourself.\"\n\n2. Do not file the issue - let the polecat learn the new workflow.\n\n## Keep in Witness Prompting\n\n- Monitoring polecat progress\n- Nudge protocol\n- Pre-kill verification\n- Session lifecycle management","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:19.921561-08:00","updated_at":"2025-12-15T20:48:36.020922-08:00","dependencies":[{"issue_id":"gt-cjb","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.896691-08:00","created_by":"daemon"}]}
{"id":"gt-99m","title":"gt daemon: Background service management","description":"## Summary\n\nONE daemon for all Gas Town - a simple Go process (not a Claude agent) that:\n1. Pokes agents periodically (heartbeat)\n2. Processes lifecycle requests\n3. Restarts sessions when agents request cycling\n\n## Architecture\n\nDaemon (gt daemon)\n- Pokes Mayor: \"HEARTBEAT: check your rigs\"\n- Pokes each Witness: \"HEARTBEAT: check your workers\"\n- Has inbox at daemon/ for lifecycle requests\n- Restarts sessions on cycle requests\n\n## NOT the daemon's job:\n- Making decisions (Witnesses do that)\n- Running Claude (it's a Go process)\n- Processing work (polecats do that)\n- Direct polecat management (Witnesses do that)\n\nThe daemon is a **dumb scheduler** - poke things, execute lifecycle requests. All intelligence is in agents.\n\n## Commands\n\n- gt daemon start: Start daemon (background)\n- gt daemon stop: Stop daemon\n- gt daemon status: Show daemon status\n- gt daemon logs: View daemon logs\n\n## Daemon Loop\n\nEvery heartbeat interval:\n1. Poke Mayor\n2. For each rig: Poke Witness\n3. Process lifecycle requests from daemon/ inbox\n4. Check for dead sessions, restart if cycle requested\n\n## Lifecycle Request Handling\n\nDaemon checks its inbox (daemon/) for lifecycle requests:\n- From Mayor: cycle/restart Mayor session\n- From Witnesses: cycle/restart Witness session\n\nOn request:\n1. Verify agent state shows requesting_cycle\n2. Kill session\n3. Start new session\n4. Clear requesting_cycle flag\n\n## Poke Protocol\n\nPoke = tmux inject \"HEARTBEAT: do your job\"\n- Agent ignores if already working\n- Agent wakes up if idle\n- Idempotent - multiple pokes are fine\n\n## Lifecycle Hierarchy\n\n- Daemon manages: Mayor, all Witnesses\n- Witness manages: Polecats, Refinery (per rig)\n- Crew: self-managed (human workspace)\n\n## Related Issues\n\n- gt-kmn.11: Daemon heartbeat details\n- gt-gby: gt handoff command (unified lifecycle)\n- gt-u1j.9: Fold witness daemon into this","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:50:09.763719-08:00","updated_at":"2025-12-19T12:56:15.205355-08:00","closed_at":"2025-12-19T12:05:27.33958-08:00","dependencies":[{"issue_id":"gt-99m","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.253877-08:00","created_by":"daemon"}]}
{"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-3x1.1","title":"Engineer main loop: poll for ready merge-requests","description":"Implement the Engineer's main processing loop.\n\nLoop structure:\n1. Query: bd ready --type=merge-request\n2. If empty: sleep(poll_interval), continue\n3. Select highest priority, oldest MR\n4. Claim: bd update \u003cid\u003e --status=in_progress\n5. Process (delegate to other subtasks)\n6. Repeat\n\nConfiguration:\n- poll_interval: from rig config (default 30s)\n- max_concurrent: from rig config (default 1)\n\nThe loop should be interruptible and handle graceful shutdown.\n\nReference: docs/merge-queue-design.md#engineer-processing-loop","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:57.022367-08:00","updated_at":"2025-12-19T12:56:15.197296-08:00","closed_at":"2025-12-18T20:14:35.321731-08:00","dependencies":[{"issue_id":"gt-3x1.1","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:50:57.024225-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-svi.1","type":"blocks","created_at":"2025-12-17T13:53:09.832586-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-svi.2","type":"blocks","created_at":"2025-12-17T13:53:09.9547-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-h5n.8","type":"blocks","created_at":"2025-12-17T13:53:16.770078-08:00","created_by":"daemon"}]}
{"id":"gt-61o","title":"Review and audit all GGT beads","description":"Thorough review of all filed beads in gastown GGT repo. Check for: consistency, completeness, correct dependencies, accurate descriptions, proper prioritization. Ensure beads are self-contained and dont rely on external docs.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:07.152386-08:00","updated_at":"2025-12-15T21:23:58.255447-08:00","closed_at":"2025-12-15T21:23:58.255447-08:00"}
{"id":"gt-3x1.5","title":"Success handling: close MR, close source issue, cleanup","description":"Handle successful merge completion.\n\nSteps:\n1. Update MR with merge_commit SHA:\n bd update \u003cid\u003e --body='...\\nmerge_commit: \u003csha\u003e'\n2. Close MR with reason:\n bd close \u003cid\u003e --reason='merged'\n3. Close source issue (the work item):\n bd close \u003csource_issue\u003e --reason='Merged in \u003cmr_id\u003e'\n4. Delete source branch (if configured):\n git push origin --delete \u003cmr.branch\u003e\n5. Log success\n\nConfiguration:\n- delete_merged_branches: bool (default true)\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:19.054425-08:00","updated_at":"2025-12-19T15:27:45.508755-08:00","closed_at":"2025-12-19T14:47:47.062475-08:00","dependencies":[{"issue_id":"gt-3x1.5","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:19.056461-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.5","depends_on_id":"gt-3x1.3","type":"blocks","created_at":"2025-12-17T13:53:10.398758-08:00","created_by":"daemon"}]}
{"id":"gt-s3m0","title":"gt polecat: add 'done' or 'finish' command to transition from working to idle","description":"When a polecat finishes work but session wasn't properly cleaned up, there's no way to reset it from 'working' state back to 'idle'.\n\nTried:\n```\ngt polecat sleep gastown/Angharad\nError: sleeping polecat: polecat is not active (state: working)\n```\n\nThe sleep command only works on 'active' polecats, not 'working' ones.\n\nHad to manually edit state.json to reset:\n```\njq '.state = \"idle\" | .issue = \"\"' state.json\n```\n\nNeed a command like:\n```\ngt polecat done gastown/Angharad # working -\u003e idle\ngt polecat finish gastown/Angharad # working -\u003e idle \ngt polecat reset gastown/Angharad # any state -\u003e idle (force)\n```","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T01:41:39.851037-08:00","updated_at":"2025-12-19T01:57:17.031611-08:00","closed_at":"2025-12-19T01:57:17.031611-08:00"}
{"id":"gt-j4nu","title":"Merge: gt-g44u.3","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-g44u.3\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:14:52.767156-08:00","updated_at":"2025-12-19T17:35:36.663796-08:00","closed_at":"2025-12-19T17:35:36.663796-08:00"}
{"id":"gt-kmn.2","title":"SwarmManager: create, start, update, query operations","description":"SwarmManager operations for creating and managing swarms.\n\n## Interface\n\n```go\ntype SwarmManager struct {\n rig *Rig\n beads *BeadsWrapper // shells out to bd CLI\n}\n\nfunc NewSwarmManager(rig *Rig) *SwarmManager\n\n// Lifecycle\nfunc (m *SwarmManager) Create(epicID string, workers []string) (*Swarm, error)\nfunc (m *SwarmManager) Start(swarmID string) error\nfunc (m *SwarmManager) UpdateState(swarmID string, state SwarmState) error\nfunc (m *SwarmManager) Cancel(swarmID string, reason string) error\n\n// Queries (delegate to beads)\nfunc (m *SwarmManager) GetSwarm(id string) (*Swarm, error)\nfunc (m *SwarmManager) GetReadyTasks(swarmID string) ([]SwarmTask, error)\nfunc (m *SwarmManager) GetActiveTasks(swarmID string) ([]SwarmTask, error)\nfunc (m *SwarmManager) IsComplete(swarmID string) (bool, error)\n```\n\n## Implementation Notes\n\n- `GetReadyTasks` wraps `bd ready --parent \u003cepicID\u003e`\n- `IsComplete` checks if all child issues are closed\n- State transitions update the epic's description or a tag field\n- No separate manifest files - beads IS the source of truth","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:04.814385-08:00","updated_at":"2025-12-16T14:00:13.663624-08:00","closed_at":"2025-12-16T14:00:13.663624-08:00","dependencies":[{"issue_id":"gt-kmn.2","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:04.814876-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.2","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:20.744039-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.8","title":"Git safety audit module","description":"Port git_audit.py safety checks to Go.\n\n## Purpose\n\nBefore destroying polecat clones, verify no code is at risk.\n\n## Checks\n\n1. Uncommitted changes (staged and unstaged)\n2. Unpushed commits\n3. Git stashes\n4. Local-only branches (not tracking remote)\n\n## Beads-Only Classification\n\nSome files are safe to discard:\n- .beads/*\n- .claude/settings.json\n\nChanges only affecting these = \"beads-only\" = safe to destroy.\n\n## Interface\n\n```go\ntype GitAuditResult struct {\n Polecat string\n Path string\n UncommittedFiles []string\n UncommittedIsBeadsOnly bool\n UnpushedCommits int\n Stashes []StashInfo\n StashesAreBeadsOnly bool\n LocalBranches []string\n Error error\n}\n\nfunc (r *GitAuditResult) HasCodeAtRisk() bool\n\nfunc AuditPolecat(name string, path string) *GitAuditResult\nfunc AuditPolecats(polecats []PolecatInfo) []*GitAuditResult\n```\n\n## Reference\n\nPGT: swarm/git_audit.py","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:19.52029-08:00","updated_at":"2025-12-16T00:10:19.52029-08:00","dependencies":[{"issue_id":"gt-kmn.8","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:29.174184-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.8","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:19.520646-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.4","title":"Outpost CLI commands: gt outpost list/status/add","description":"## Overview\n\nCLI commands for managing outposts.\n\n## Commands\n\n```bash\n# List configured outposts\ngt outpost list\nNAME TYPE WORKERS STATUS\nlocal local 2/4 healthy\ngce-burst ssh 0/8 healthy\ncloudrun-burst cloudrun 0/20 healthy\n\n# Detailed status\ngt outpost status [name]\nOutpost: cloudrun-burst\nType: cloudrun\nProject: my-gcp-project\nRegion: us-central1\nService: gastown-worker\nActive Workers: 3/20\nCost (today): $0.42\nStatus: healthy\n\n# Add new outpost interactively\ngt outpost add\n? Outpost type: [local/ssh/cloudrun]\n\u003e cloudrun\n? Name: cloudrun-burst\n? GCP Project: my-gcp-project\n...\n\n# Add via flags\ngt outpost add cloudrun --name burst --project my-proj --region us-central1\n\n# Remove outpost\ngt outpost remove \u003cname\u003e\n\n# Test connectivity\ngt outpost ping \u003cname\u003e\n```\n\n## Files\n\n- `cmd/gt/outpost.go` - Cobra command group\n- `cmd/gt/outpost_list.go`\n- `cmd/gt/outpost_status.go`\n- `cmd/gt/outpost_add.go`\n\nDepends on: gt-9a2.3 (config/manager)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:12.317032-08:00","updated_at":"2025-12-16T18:02:12.317032-08:00","dependencies":[{"issue_id":"gt-9a2.4","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:12.319322-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.4","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:03:45.55722-08:00","created_by":"daemon"}]}
{"id":"gt-vjv","title":"Add bulk session stop command (gt session stop --all)","description":"When decommissioning a rig, need to stop multiple sessions one at a time. A --all or --rig flag would allow: gt session stop --rig gastown","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-18T11:33:33.394649-08:00","updated_at":"2025-12-18T11:38:51.399298-08:00","closed_at":"2025-12-18T11:38:51.399298-08:00"}
{"id":"gt-3x1.2","title":"Fetch and conflict check: git operations for MR","description":"Implement git operations for MR processing.\n\nSteps:\n1. git fetch origin \u003cmr.branch\u003e\n2. git checkout \u003cmr.target\u003e (main or integration/xxx)\n3. git merge --no-commit --no-ff \u003cmr.branch\u003e (test merge)\n4. Check for conflicts\n5. If conflicts: abort and return Failure(conflict, files)\n6. If clean: abort (actual merge in next step)\n\nHelper functions:\n- FetchBranch(branch string) error\n- CheckConflicts(source, target string) ([]string, error)\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:58.99193-08:00","updated_at":"2025-12-19T12:56:15.197864-08:00","closed_at":"2025-12-18T20:17:47.781432-08:00","dependencies":[{"issue_id":"gt-3x1.2","depends_on_id":"gt-3x1.1","type":"blocks","created_at":"2025-12-17T13:53:10.066159-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.2","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:50:58.993973-08:00","created_by":"daemon"}]}
{"id":"gt-56po","title":"Merge: gt-g44u.2","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-g44u.2\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:03:10.388461-08:00","updated_at":"2025-12-19T17:35:39.482476-08:00","closed_at":"2025-12-19T17:35:39.482476-08:00"}
{"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-dck","title":"Update config location: .gastown/ → config/","description":"Move rig configuration from hidden .gastown/ to visible config/:\n- config/rig.json: Rig configuration\n- config/engineer.json: Engineer settings (test command, etc.)\n- config/witness.json: Witness settings (heartbeat interval, etc.)\n\nHidden directories are poorly discovered by AI agents.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:20.400818-08:00","updated_at":"2025-12-16T23:02:20.400818-08:00","dependencies":[{"issue_id":"gt-dck","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.69517-08:00","created_by":"daemon"}]}
{"id":"gt-g2d","title":"Mayor session cycling prompting","description":"Add session cycling section to Mayor CLAUDE.md template.\n\n## When to Cycle\n\nCycle proactively when:\n- Running for several hours\n- Context feels crowded (losing track of earlier state)\n- Major phase completed\n- About to start complex new work\n\n## Composing Handoff Notes\n\n1. Gather information:\n town status # Overall health\n town rigs # Each rig state\n town inbox # Pending messages\n bd ready # Work items\n\n2. Compose note with this structure:\n\n[HANDOFF_TYPE]: mayor_cycle\n[TIMESTAMP]: \u003ccurrent time\u003e\n[SESSION_DURATION]: \u003chow long running\u003e\n\n## Active Swarms\n\u003cper-rig swarm status\u003e\n\n## Rig Status\n\u003ctable of rig health\u003e\n\n## Pending Escalations\n\u003cissues needing your decision\u003e\n\n## In-Flight Decisions\n\u003cdecisions being made\u003e\n\n## Recent Actions\n\u003clast 5-10 things you did\u003e\n\n## Delegated Work\n\u003cwork sent to refineries\u003e\n\n## User Requests\n\u003cpending user asks\u003e\n\n## Next Steps\n\u003cwhat next session should do\u003e\n\n## Warnings/Notes\n\u003ccritical info for next session\u003e\n\n3. Send handoff:\n town mail send mayor/ -s \"Session Handoff\" -m \"\u003cnote\u003e\"\n\n4. End session - next instance picks up from handoff.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:26.188561-08:00","updated_at":"2025-12-15T20:48:39.861022-08:00","dependencies":[{"issue_id":"gt-g2d","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.361163-08:00","created_by":"daemon"}]}
{"id":"gt-2tp","title":"init.go: Replace custom contains() with strings.Contains","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-16T13:55:11.326407-08:00","updated_at":"2025-12-16T13:56:39.089057-08:00","closed_at":"2025-12-16T13:56:39.089057-08:00"}
{"id":"gt-bxi8","title":"bd mail send: pinned column missing from schema","description":"gt mail send fails with: sqlite3: SQL logic error: table issues has no column named pinned\n\nLikely a schema migration issue - bd schema has 'pinned' field but SQLite table doesn't.\n\n## Reproduction\ngt mail send gastown/Immortan -s 'test' -m 'test'\n\n## Error\ntable issues has no column named pinned\n\n## Fix\nEither:\n1. Add migration to add pinned column\n2. Remove pinned from insert if not present\n3. Regenerate DB from JSONL","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:53:09.262403-08:00","updated_at":"2025-12-19T17:22:52.553097-08:00","closed_at":"2025-12-19T16:17:03.637686-08:00"}
{"id":"gt-92l","title":"Daemon: integration test with real lifecycle","description":"Need an end-to-end test that:\n1. Starts daemon\n2. Starts a test agent session\n3. Sends lifecycle request to daemon\n4. Verifies session was killed and restarted\n5. Cleans up\n\nCould use a mock 'agent' that's just a shell script.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:17.261096-08:00","updated_at":"2025-12-19T17:22:52.555739-08:00","closed_at":"2025-12-19T16:31:23.543204-08:00","dependencies":[{"issue_id":"gt-92l","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.962642-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.7","title":"CLI: gt swarm commands (create, status, list, land)","description":"CLI commands for swarm management.\n\n## Commands\n\n### gt swarm create\nCreate a new swarm in a rig.\n\n```\ngt swarm create \u003crig\u003e --title \"Fix all P1 bugs\" \\\n --task gt-abc --task gt-def \\\n --worker Toast --worker Nux\n```\n\nOptions:\n- --title: Swarm title (required)\n- --task: Beads issue IDs to include (repeatable)\n- --worker: Polecat names (repeatable, or --workers=3 to auto-assign)\n- --start: Start swarm immediately after creation\n\n### gt swarm status \u003cswarm-id\u003e\nShow swarm status and progress.\n\nOutput:\n- Swarm metadata (title, created, workers)\n- Task status (pending/in_progress/completed/merged)\n- Integration branch status\n- Overall progress percentage\n\n### gt swarm list [rig]\nList swarms, optionally filtered by rig or status.\n\n```\ngt swarm list --status=active\ngt swarm list gastown --status=landed\n```\n\n### gt swarm land \u003cswarm-id\u003e\nTrigger manual landing (normally automatic).\n\n### gt swarm cancel \u003cswarm-id\u003e\nCancel a swarm in progress.\n\n## Output Format\n\nSupport --json for machine-readable output.\n\n## Dependencies\n\nNeeds: gt-kmn.1 (types), gt-kmn.2 (manager)","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:50.57674-08:00","updated_at":"2025-12-16T14:11:46.038524-08:00","closed_at":"2025-12-16T14:11:46.038524-08:00","dependencies":[{"issue_id":"gt-kmn.7","depends_on_id":"gt-kmn.2","type":"blocks","created_at":"2025-12-16T00:11:29.0905-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.7","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:50.577096-08:00","created_by":"daemon"}]}
{"id":"gt-g44u.1","title":"Molecule composition: Includes directive","description":"Add support for molecule composition via the Includes directive.\n\n## Format\n\\`\\`\\`markdown\n## Molecule: derived-name\nIncludes: mol-base-molecule\n\n## Step: additional-step\nAdditional instructions here.\nNeeds: step-from-base\n\\`\\`\\`\n\n## Implementation\n1. Add \\`Includes:\\` parsing to ParseMoleculeSteps()\n2. Resolve included molecule by ID\n3. Merge steps from included molecule\n4. Allow new steps to depend on included steps\n5. Support multiple includes (polymers)\n\n## Files to modify\n- internal/beads/molecule.go\n- internal/beads/molecule_test.go\n\n## Acceptance\n- [ ] Parse Includes directive\n- [ ] Resolve and merge included steps\n- [ ] Dependencies across molecules work\n- [ ] Multiple includes supported\n- [ ] Tests cover composition scenarios","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:08.981634-08:00","updated_at":"2025-12-19T16:03:55.055353-08:00","closed_at":"2025-12-19T16:03:55.055353-08:00","dependencies":[{"issue_id":"gt-g44u.1","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:08.983662-08:00","created_by":"daemon"}]}
{"id":"gt-caz","title":"Timed Beads: Scheduled recurring work","description":"## Summary\n\nTimed beads wake up periodically and get injected into the ready queue by the daemon.\n\n## Schema Extension\n\n```yaml\nid: gt-weekly-sync\ntype: task # or sentinel\nschedule: \"0 9 * * 1\" # cron: Monday 9am\n# OR\ninterval: 24h # every 24 hours\ntier: haiku # cheap model for routine checks\nnext_run: 2025-12-20T09:00:00Z\n```\n\n## Daemon Integration\n\nDaemon heartbeat loop:\n1. Check timed beads where `next_run \u003c= now`\n2. For each due bead:\n - Inject into ready queue (set status to open if needed)\n - Update `next_run` based on schedule/interval\n3. Witnesses pick up work via `bd ready`\n\n## Use Cases\n\n- Weekly team sync reminders\n- Daily health checks\n- Periodic cleanup tasks\n- Scheduled reports\n\n## Interaction with Pinned Beads\n\nA pinned bead can be timed - it wakes up periodically but never closes.\nThis is how you model \"background services\" in Gas Town.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:07:39.665294-08:00","updated_at":"2025-12-18T18:07:39.665294-08:00"}
{"id":"gt-346","title":"Update harness beads redirect for GGT","description":"Change ~/ai/.beads/redirect from mayor/rigs/gastown/.beads to gastown/mayor/.beads for the GGT directory structure","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T16:42:41.650571-08:00","updated_at":"2025-12-19T12:56:15.19675-08:00","closed_at":"2025-12-19T12:00:39.272977-08:00","dependencies":[{"issue_id":"gt-346","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:59.04264-08:00","created_by":"daemon"},{"issue_id":"gt-346","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.495061-08:00","created_by":"daemon"}]}
{"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-oc2","title":"Daemon: proper rig discovery","description":"Currently discovers rigs by scanning tmux session names for gt-*-witness pattern. Should instead:\n- Read rigs from mayor/rigs.json\n- Or scan town directory for .gastown subdirs\n- Handle rigs that exist but don't have running witnesses","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:15.825299-08:00","updated_at":"2025-12-19T17:22:52.554474-08:00","closed_at":"2025-12-19T16:28:39.497935-08:00","dependencies":[{"issue_id":"gt-oc2","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.826697-08:00","created_by":"daemon"}]}
{"id":"gt-hgk","title":"Mail system: message types and threading","description":"GGT mail system needs message types and threading like PGT.\n\n## 1. Message Types\nAdd to internal/mail/types.go:\n```go\ntype MessageType string\nconst (\n TypeTask MessageType = \"task\" // Required processing\n TypeScavenge MessageType = \"scavenge\" // Optional first-come work\n TypeNotification MessageType = \"notification\" // Informational\n TypeReply MessageType = \"reply\" // Response to message\n)\n\n// Update Message struct\ntype Message struct {\n // existing fields...\n Type MessageType `json:\"type\"`\n ThreadID string `json:\"thread_id,omitempty\"`\n ReplyTo string `json:\"reply_to,omitempty\"`\n}\n```\n\n## 2. Priority Levels\nExpand from 2 to 4:\n```go\ntype Priority string\nconst (\n PriorityLow Priority = \"low\"\n PriorityNormal Priority = \"normal\"\n PriorityHigh Priority = \"high\"\n PriorityUrgent Priority = \"urgent\"\n)\n```\n\n## 3. CLI Updates\ninternal/cmd/mail.go:\n- Add --type flag to send: `gt mail send ... --type task`\n- Add --reply-to flag: `gt mail send ... --reply-to \u003cmsg-id\u003e`\n- Add thread command: `gt mail thread \u003cthread-id\u003e`\n\n## 4. Threading Logic\nNewMessage() should auto-generate thread_id if not a reply.\nReply messages inherit thread_id from original.\n\n## Files to Modify\n- internal/mail/types.go: Add types, expand Priority\n- internal/mail/mailbox.go: Thread filtering\n- internal/cmd/mail.go: CLI flags and thread command\n\n## PGT Reference\ngastown-py/src/gastown/mail/message.py\n\n## Acceptance Criteria\n- [ ] Messages have type field (default: notification)\n- [ ] 4 priority levels supported\n- [ ] Reply creates thread with shared thread_id\n- [ ] gt mail thread \u003cid\u003e shows conversation","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:55.29463-08:00","updated_at":"2025-12-19T12:56:15.211543-08:00","closed_at":"2025-12-18T20:14:28.308997-08:00"}
{"id":"gt-lno","title":"Swarm state persistence: manifest + state + events","description":"Upgrade swarm persistence to match PGT pattern.\n\n## Current State\nSingle .gastown/swarms.json with all swarms.\n\n## Target State (per-swarm)\n```\n.gastown/swarms/\n└── \u003cswarm-id\u003e/\n ├── manifest.json # Immutable config\n ├── state.json # Mutable progress\n ├── events.jsonl # Audit log\n └── report.md # Generated report\n```\n\n## File Schemas\n\n### manifest.json (immutable after creation)\n```json\n{\n \"id\": \"sw-1\",\n \"title\": \"Epic description\",\n \"epic_id\": \"gt-abc\",\n \"rig\": \"gastown\",\n \"base_commit\": \"abc123\",\n \"integration_branch\": \"swarm/sw-1\",\n \"target_branch\": \"main\",\n \"workers\": [\"Toast\", \"Nux\"],\n \"tasks\": [{\"id\": \"gt-xyz\", \"title\": \"...\"}],\n \"created_at\": \"2024-01-01T00:00:00Z\"\n}\n```\n\n### state.json (mutable)\n```json\n{\n \"state\": \"active\",\n \"task_states\": {\n \"gt-xyz\": {\"state\": \"merged\", \"assignee\": \"Toast\"}\n },\n \"updated_at\": \"2024-01-01T01:00:00Z\",\n \"error\": null\n}\n```\n\n### events.jsonl (append-only audit)\n```jsonl\n{\"event\": \"created\", \"ts\": \"...\", \"data\": {...}}\n{\"event\": \"task_assigned\", \"ts\": \"...\", \"data\": {...}}\n{\"event\": \"task_merged\", \"ts\": \"...\", \"data\": {...}}\n```\n\n## Benefits\n- Audit trail via events.jsonl\n- Manifest immutability prevents corruption\n- Cleaner separation of concerns\n- Per-swarm isolation\n\n## Migration\nKeep backward compat with swarms.json during transition.\n\n## Files to Modify\n- internal/swarm/manager.go: Refactor persistence\n- internal/cmd/swarm.go: SwarmStore → directory-based\n\n## Acceptance Criteria\n- [ ] Per-swarm directory structure\n- [ ] Events logged to JSONL\n- [ ] Manifest immutable after creation\n- [ ] List command aggregates from directories","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:48:14.151538-08:00","updated_at":"2025-12-16T17:23:19.716405-08:00","closed_at":"2025-12-16T17:23:19.716405-08:00"}
{"id":"gt-082","title":"Worker cleanup: Beads sync on shutdown","description":"Add beads sync verification to worker cleanup checklist and Witness verification.\n\n## Update to Decommission Checklist (gt-sd6)\n\nAdd to pre-done verification:\n- bd sync --status must show 'Up to date'\n- git status .beads/ must show no changes\n\n## Beads Edge Cases\n\nUncommitted beads changes:\n bd sync\n git add .beads/\n git commit -m 'beads: final sync'\n\nBeads sync conflict (rare):\n git fetch origin main\n git checkout main -- .beads/\n bd sync --force\n git add .beads/\n git commit -m 'beads: resolve sync conflict'\n\n## Update to Witness Verification (gt-f8v)\n\nWhen capturing worker state:\n town capture \u003cpolecat\u003e \"bd sync --status \u0026\u0026 git status .beads/\"\n\nCheck for:\n- bd sync --status shows 'Up to date'\n- git status .beads/ shows no changes\n\nIf beads not synced, nudge:\n WITNESS CHECK: Beads not synced. Run 'bd sync' then commit .beads/. Signal done when complete.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:21.757756-08:00","updated_at":"2025-12-15T20:48:37.663168-08:00","dependencies":[{"issue_id":"gt-082","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.977804-08:00","created_by":"daemon"}]}
{"id":"gt-a95","title":"Refinery background daemon mode","description":"Refinery currently only works in foreground mode. Background daemon is stubbed.\n\n## Current State\nmanager.go line 128-129:\n```go\n// Background mode: spawn a new process\n// For MVP, we just mark as running - actual daemon implementation in gt-ov2\nreturn nil\n```\n\n## Requirements\n\n### 1. Background Process Spawning\n```go\nfunc (m *Manager) Start(foreground bool) error {\n if !foreground {\n // Spawn gt refinery start --foreground as subprocess\n cmd := exec.Command(os.Args[0], \"refinery\", \"start\", m.rig.Name, \"--foreground\")\n cmd.Start() // Don't wait\n // Record PID\n }\n}\n```\n\n### 2. PID File Management\n- Write PID to .gastown/refinery.pid\n- Check PID validity on status\n- Clean up stale PID files\n\n### 3. Log Output\n- Redirect stdout/stderr to .gastown/refinery.log\n- Log rotation (optional for MVP)\n\n### 4. Graceful Shutdown\n- Handle SIGTERM/SIGINT\n- Complete current merge before exit\n- Update state to stopped\n\n### 5. Health Check\n- Process existence check via kill -0\n- Optional: heartbeat file with timestamp\n\n## Files to Modify\n- internal/refinery/manager.go: Start(), Status(), process spawning\n\n## Acceptance Criteria\n- [ ] gt refinery start \u003crig\u003e spawns background process\n- [ ] gt refinery status shows running with PID\n- [ ] gt refinery stop sends SIGTERM and waits\n- [ ] Logs written to .gastown/refinery.log\n- [ ] Survives terminal close","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:53.366619-08:00","updated_at":"2025-12-19T15:27:45.508176-08:00","closed_at":"2025-12-19T14:47:40.165105-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:52:02.390539-08:00","updated_at":"2025-12-15T23:17:16.487399-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"}]}
{"id":"gt-5ft3","title":"Merge: gt-99a","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-99a\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:18:15.329358-08:00","updated_at":"2025-12-19T18:26:14.101606-08:00","closed_at":"2025-12-19T17:48:44.671082-08:00"}
{"id":"gt-662","title":"Swarm: report generation","description":"Generate markdown reports for completed swarms.\n\n## Command\n```\ngt swarm report \u003cswarm-id\u003e [--save \u003cfile\u003e]\n```\n\n## Report Content\n\n### Header\n- Swarm ID and title\n- Created/completed timestamps\n- Duration\n- Rig name\n\n### Task Summary\n| Task | Assignee | Status | Duration |\n|------|----------|--------|----------|\n| gt-xxx | Toast | merged | 15m |\n| gt-yyy | Nux | merged | 22m |\n\n### Worker Contributions\n- Commits per worker\n- Issues closed per worker\n- Lines changed (optional)\n\n### Timeline\n- Chronological events from events.jsonl\n- Key milestones (started, first merge, landing)\n\n### Issues Encountered\n- Conflicts resolved\n- Failed tasks (if any)\n- Escalations\n\n## Implementation\n```go\nfunc GenerateReport(swarmID string) (*SwarmReport, error)\nfunc (r *SwarmReport) ToMarkdown() string\n```\n\n## Storage\n- Save to \u003crig\u003e/.gastown/swarms/\u003cid\u003e/report.md\n- Or user-specified path with --save\n\n## PGT Reference\ngastown-py/src/gastown/swarm/manager.py generate_report()\n\n## Acceptance Criteria\n- [ ] Markdown report generated\n- [ ] Includes all sections above\n- [ ] Auto-saved to swarm directory\n- [ ] --save allows custom path","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:17.96767-08:00","updated_at":"2025-12-16T17:23:22.330075-08:00","closed_at":"2025-12-16T17:23:22.330075-08:00"}
{"id":"gt-8j8e","title":"gt mail send: --priority flag should work like bd mail send","description":"UX inconsistency: gt mail send passes flags that bd mail send doesn't support.\n\n## Root Cause\n\nrouter.go line 42 passes `--priority` to bd:\n```go\nargs = append(args, \"--priority\", fmt.Sprintf(\"%d\", beadsPriority))\n```\n\nBut `bd mail send` only has `--urgent` (boolean), not `--priority`.\n\n## Fix Options\n\n1. Add `--priority` flag to `bd mail send` (preferred - more expressive)\n2. Change router to only use `--urgent` when priority=0\n\n## Also Affected\n\n- `--type` flag (line 46) - bd mail send doesn't have this\n- `--thread-id` flag (line 51) - bd mail send doesn't have this \n- `--reply-to` flag (line 56) - bd mail send doesn't have this\n\nThe router assumes bd mail send has features it doesn't have.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:31:05.486487-08:00","updated_at":"2025-12-19T12:07:28.918346-08:00","closed_at":"2025-12-19T12:07:28.918346-08:00"}
{"id":"gt-gby","title":"gt handoff: Unified agent lifecycle command","description":"## Summary\n\nUnified `gt handoff` command for ALL agent types to request lifecycle actions.\n\n## Usage\n\ngt handoff # Context-aware default\ngt handoff --shutdown # Terminate, cleanup, don't restart\ngt handoff --cycle # Restart with handoff mail\ngt handoff --restart # Fresh restart, no handoff\n\n## Context-Aware Defaults\n\n| Agent Type | Default | Reason |\n|------------|---------|--------|\n| Polecat | --shutdown | Ephemeral, work is done |\n| Witness | --cycle | Long-running, context full |\n| Refinery | --cycle | Long-running, context full |\n| Mayor | --cycle | Long-running, context full |\n| Crew | (sends mail only) | Human-managed |\n\n## What gt handoff Does\n\n1. **Verify safe to stop**\n - Git state clean (no uncommitted changes)\n - Work handed off (PR exists for polecats)\n\n2. **Send handoff mail to self** (for cycle/restart)\n - Captures current state\n - New session will read this\n\n3. **Send lifecycle request to manager**\n - Polecats/Refinery → Witness\n - Witness/Mayor → Daemon\n - Format: mail to \u003cmanager\u003e with action type\n\n4. **Set state: requesting_\u003caction\u003e**\n - Lifecycle manager checks this before acting\n\n5. **Wait for termination**\n - Don't self-exit - let manager kill session\n - Ensures clean handoff\n\n## Lifecycle Request Flow\n\nAgent Lifecycle Manager\n | |\n | 1. gt handoff --cycle |\n | a. Verify git clean |\n | b. Send handoff mail to self |\n | c. Set requesting_cycle=true |\n | d. Send lifecycle request |\n |------------------------------------→|\n | |\n | 2. Receive request\n | 3. Verify state |\n | 4. Kill session |\n | 5. Start new |\n | (for cycle) |\n | |\n | New session reads handoff |\n | Resumes work |\n\n## Who Manages Whom\n\n| Agent | Sends lifecycle request to |\n|-------|---------------------------|\n| Polecat | \u003crig\u003e/witness |\n| Refinery | \u003crig\u003e/witness |\n| Witness | daemon/ |\n| Mayor | daemon/ |\n\n## Implementation\n\n1. Detect current role (polecat, witness, refinery, mayor, crew)\n2. Apply context-aware default if no flag specified\n3. Run pre-flight checks (git clean, work handed off)\n4. Send handoff mail to self (if cycling)\n5. Send lifecycle request to appropriate manager\n6. Set requesting_\u003caction\u003e in state.json\n7. Wait (manager will kill us)\n\n## For Polecats (--shutdown)\n\nAdditional cleanup after kill:\n- Witness removes worktree\n- Witness deletes polecat branch\n- Polecat ceases to exist\n\n## Related Issues\n\n- gt-99m: Daemon (handles Mayor/Witness lifecycle)\n- gt-7ik: Ephemeral polecats (polecat cleanup)\n- gt-eu9: Witness session cycling","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-18T11:39:40.806863-08:00","updated_at":"2025-12-18T18:18:22.35369-08:00","dependencies":[{"issue_id":"gt-gby","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T11:50:24.142182-08:00","created_by":"daemon"},{"issue_id":"gt-gby","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-18T11:39:46.423945-08:00","created_by":"daemon"},{"issue_id":"gt-gby","depends_on_id":"gt-eu9","type":"blocks","created_at":"2025-12-18T11:39:46.547204-08:00","created_by":"daemon"}]}
{"id":"gt-hw6","title":"GGT Command Parity: Complete gt command coverage","description":"Complete gt command set to match/exceed PGT town commands.\n\nCovers: uninstall, rig info, refinery attach, witness, session mgmt, mail UX, daemon.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T22:22:21.720078-08:00","updated_at":"2025-12-19T12:56:15.211995-08:00","closed_at":"2025-12-19T12:05:36.723692-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-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-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:21.968099-08:00","updated_at":"2025-12-15T23:17:18.644857-08:00","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-9a2.16","title":"Outpost integration tests: Mock and E2E testing","description":"## Overview\n\nIntegration tests for the outpost system.\n\n## Mock Outpost\n\n```go\ntype MockOutpost struct {\n name string\n maxWorkers int\n spawnDelay time.Duration\n spawnError error\n workers []*MockWorker\n}\n\nfunc (o *MockOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n if o.spawnError != nil {\n return nil, o.spawnError\n }\n time.Sleep(o.spawnDelay)\n worker := \u0026MockWorker{id: uuid.New().String(), issue: issue}\n o.workers = append(o.workers, worker)\n return worker, nil\n}\n```\n\n## Unit Tests\n\n```go\nfunc TestOutpostManager_SelectOutpost(t *testing.T) {\n // Test policy-based selection\n}\n\nfunc TestOutpostManager_SpawnWithRetry(t *testing.T) {\n // Test retry logic with transient failures\n}\n\nfunc TestCloudRunOutpost_CostTracking(t *testing.T) {\n // Test cost calculation and caps\n}\n```\n\n## Integration Tests (with mocked Cloud Run)\n\n```go\nfunc TestCloudRunOutpost_Integration(t *testing.T) {\n // Start mock HTTP server\n server := httptest.NewServer(mockWorkHandler())\n defer server.Close()\n \n outpost := NewCloudRunOutpost(OutpostConfig{\n ServiceURL: server.URL,\n })\n \n worker, err := outpost.Spawn(\"test-issue\", WorkerConfig{})\n // Assert worker created, events streamed\n}\n```\n\n## E2E Tests (requires real Cloud Run)\n\n```go\n// +build e2e\n\nfunc TestCloudRunOutpost_E2E(t *testing.T) {\n if os.Getenv(\"CLOUDRUN_SERVICE_URL\") == \"\" {\n t.Skip(\"CLOUDRUN_SERVICE_URL not set\")\n }\n // Test against real Cloud Run service\n}\n```\n\n## Files\n\n- `internal/outpost/mock_test.go`\n- `internal/outpost/manager_test.go`\n- `internal/outpost/cloudrun_test.go`\n- `internal/cloudrun/integration_test.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (CloudRunOutpost), gt-9a2.15 (error handling)\nLower priority - can be done after implementations work.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-16T18:16:48.019386-08:00","updated_at":"2025-12-16T18:16:48.019386-08:00","dependencies":[{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:55.90113-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2.15","type":"blocks","created_at":"2025-12-16T18:16:56.013753-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:48.021933-08:00","created_by":"daemon"}]}
{"id":"gt-l1o","title":"Harness \u0026 Priming: Document architecture and update all role contexts","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T16:42:29.314113-08:00","updated_at":"2025-12-19T12:56:15.213669-08:00","closed_at":"2025-12-19T12:00:51.410053-08:00"}
{"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-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T17:12:59.200876-08:00","updated_at":"2025-12-15T23:17:22.102624-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-g44u.2","title":"Create mol-install-go-binary molecule","description":"Create a single-step molecule for building and installing the gt binary.\n\n## Molecule Definition\n\\`\\`\\`markdown\n## Molecule: install-go-binary\nSingle step to rebuild and install the gt binary after code changes.\n\n## Step: install\nBuild and install the gt binary locally.\n\nRun from the rig directory:\n\\`\\`\\`\ngo build -o gt ./cmd/gt\ngo install ./cmd/gt\n\\`\\`\\`\n\nVerify the installed binary is updated:\n\\`\\`\\`\nwhich gt\ngt --version # if we have version command\n\\`\\`\\`\n\\`\\`\\`\n\n## Implementation\n1. Add to builtin_molecules.go\n2. Update SeedBuiltinMolecules to include it\n3. Run gt molecule seed\n\n## Acceptance\n- [ ] mol-install-go-binary exists in beads\n- [ ] Can be instantiated standalone\n- [ ] Can be included by other molecules","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:11.178225-08:00","updated_at":"2025-12-19T16:02:36.758908-08:00","closed_at":"2025-12-19T16:02:36.758908-08:00","dependencies":[{"issue_id":"gt-g44u.2","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:11.180129-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.16","title":"CLI: rig commands (list, show, add)","description":"Rig management CLI commands.\n\n## Commands\n\n### gt rig list\nList all registered rigs.\n```\ngt rig list [--json]\n```\nOutput:\n- Rig name\n- Git URL\n- Polecat count\n- Witness/Refinery status\n\n### gt rig show\nShow details for a specific rig.\n```\ngt rig show \u003cname\u003e [--json]\n```\nOutput:\n- Full rig info\n- Polecats with status\n- Recent activity\n- Beads summary (open issues)\n\n### gt rig add\nAdd a new rig to the town.\n```\ngt rig add \u003cname\u003e \u003cgit-url\u003e\ngt rig add \u003cname\u003e --local \u003cpath\u003e\n```\nSteps:\n- Clone repo to town root (or link local)\n- Register in rigs.json\n- Create agent directories\n- Configure git exclude\n\n### gt rig remove\nRemove a rig from the town.\n```\ngt rig remove \u003cname\u003e [--force]\n```\n- Warns if active polecats\n- --force required if uncommitted changes\n\n## Implementation\n\n```go\nvar rigCmd = \u0026cobra.Command{Use: \"rig\"}\nrigCmd.AddCommand(rigListCmd, rigShowCmd, rigAddCmd, rigRemoveCmd)\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:01.075697-08:00","updated_at":"2025-12-15T21:20:44.918399-08:00","dependencies":[{"issue_id":"gt-u1j.16","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:08.30402-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.16","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:01.076033-08:00","created_by":"daemon"}]}
{"id":"gt-1gy","title":"gt mail read: Support numeric indices for message ID","description":"Allow 'gt mail read 1' to read the first message in inbox.\n\nCurrent behavior requires full message ID like 'msg-abc123'.\nShould support:\n- Numeric index: 'gt mail read 1' reads first/newest message\n- Partial ID match: 'gt mail read abc' matches 'msg-abc123'\n\nThis is a UX improvement - agents frequently type 'gt mail read 1'.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:49:54.60582-08:00","updated_at":"2025-12-17T22:28:59.846038-08:00","closed_at":"2025-12-17T22:28:59.846038-08:00","dependencies":[{"issue_id":"gt-1gy","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.658947-08:00","created_by":"daemon"}]}
{"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-u1j.3","title":"Git wrapper: shell out to git","description":"Wrapper for git operations via subprocess.\n\n## Interface\n\n```go\ntype Git struct {\n workDir string\n}\n\nfunc NewGit(workDir string) *Git\n\n// Core operations\nfunc (g *Git) Clone(url, dest string) error\nfunc (g *Git) Checkout(ref string) error\nfunc (g *Git) Fetch(remote string) error\nfunc (g *Git) Pull(remote, branch string) error\nfunc (g *Git) Push(remote, branch string, force bool) error\n\n// Commit operations\nfunc (g *Git) Add(paths ...string) error\nfunc (g *Git) Commit(message string) error\nfunc (g *Git) CommitAll(message string) error\n\n// Query operations\nfunc (g *Git) Status() (*GitStatus, error)\nfunc (g *Git) CurrentBranch() (string, error)\nfunc (g *Git) HasUncommittedChanges() (bool, error)\nfunc (g *Git) RemoteURL(remote string) (string, error)\n\n// Merge operations\nfunc (g *Git) Merge(branch string) error\nfunc (g *Git) Rebase(onto string) error\nfunc (g *Git) AbortMerge() error\nfunc (g *Git) AbortRebase() error\n```\n\n## Implementation\n\nShell out to git binary via exec.Command. Parse output where needed (Status, CurrentBranch).\n\n## Error Handling\n\n- Wrap git stderr in error messages\n- Detect specific failures (merge conflict, auth failure, not a repo)\n- Return structured errors for callers to handle\n\n## Testing\n\n- Use temp directories with real git repos\n- Test both success and failure paths","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:11.907807-08:00","updated_at":"2025-12-16T13:27:03.639659-08:00","closed_at":"2025-12-16T13:27:03.639659-08:00","dependencies":[{"issue_id":"gt-u1j.3","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:11.908262-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.3","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:13:47.220423-08:00","created_by":"daemon"}]}
{"id":"gt-kcee","title":"Witness commands: gt witness start/stop/status needed","description":"## Summary\n\nNo `gt witness` command exists. The witness should:\n- Monitor polecats for stuck/idle state\n- Nudge polecats that seem blocked\n- Report status to mayor\n- Handle polecat lifecycle\n\n## Expected Commands\n\n```bash\ngt witness start gastown # Start witness for rig\ngt witness stop gastown # Stop witness\ngt witness status # Show witness status\n```\n\n## Current State\n\n- Witness directory exists: /Users/stevey/gt/gastown/witness/\n- Has state.json but no active process\n- gt status shows 'Witnesses: 0'\n\n## Context\n\nFull polecat flow needs witness monitoring for production use.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-18T21:55:24.079671-08:00","updated_at":"2025-12-19T01:33:49.856942-08:00","closed_at":"2025-12-19T01:33:49.856942-08:00"}
{"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-g44u.1","title":"Molecule composition: Includes directive","description":"Add support for molecule composition via the Includes directive.\n\n## Format\n\\`\\`\\`markdown\n## Molecule: derived-name\nIncludes: mol-base-molecule\n\n## Step: additional-step\nAdditional instructions here.\nNeeds: step-from-base\n\\`\\`\\`\n\n## Implementation\n1. Add \\`Includes:\\` parsing to ParseMoleculeSteps()\n2. Resolve included molecule by ID\n3. Merge steps from included molecule\n4. Allow new steps to depend on included steps\n5. Support multiple includes (polymers)\n\n## Files to modify\n- internal/beads/molecule.go\n- internal/beads/molecule_test.go\n\n## Acceptance\n- [ ] Parse Includes directive\n- [ ] Resolve and merge included steps\n- [ ] Dependencies across molecules work\n- [ ] Multiple includes supported\n- [ ] Tests cover composition scenarios","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:08.981634-08:00","updated_at":"2025-12-19T16:03:55.055353-08:00","closed_at":"2025-12-19T16:03:55.055353-08:00","dependencies":[{"issue_id":"gt-g44u.1","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:08.983662-08:00","created_by":"daemon"}]}
{"id":"gt-jpt","title":"Town-level beads: Real DB for coordination mail","description":"Implement Option A from mail redesign: Town gets real beads DB for coordination.\n\n## Background\n\nMail is now Beads. But currently:\n- Town .beads/redirect points to rig beads\n- mayor/mail/ has legacy JSONL files\n- Cross-rig coordination has no clear home\n\n## Design\n\nTown beads = coordination, cross-rig mail, mayor inbox, handoffs\nRig beads = project issues, work items\n\nMatches HOP hierarchy: platform \u003e project \u003e worker\n\n## Structure\n\n~/gt/\n .beads/ # REAL beads DB (prefix: gm-)\n mayor/\n town.json\n state.json # NO mail/ directory\n gastown/\n .beads/ # Rig beads (prefix: ga-)\n\n## Tasks\n\n1. Delete ~/gt/.beads/redirect\n2. Run bd init --prefix gm at ~/gt/ (town beads)\n3. Delete ~/gt/mayor/mail/ directory\n4. Update gt mail to use beads not JSONL\n5. Add mail fields (thread_id, reply_to, msg_type)\n6. Update gt prime for two-tier model\n7. Update docs/architecture.md\n\n## Addressing\n\n- mayor/ -\u003e town beads\n- rig/agent -\u003e rig beads\n- Cross-rig -\u003e town beads","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T19:09:55.855955-08:00","updated_at":"2025-12-19T12:56:15.212847-08:00","closed_at":"2025-12-19T01:57:17.032558-08:00"}
{"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-dkc","title":"Add harness overview to Mayor priming","description":"Update gt prime Mayor context to explain the harness concept: umbrella repo for GT installation, rigs underneath, Mayor sits above all rigs","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T16:42:44.864606-08:00","updated_at":"2025-12-17T16:44:12.568963-08:00","closed_at":"2025-12-17T16:44:12.568963-08:00","dependencies":[{"issue_id":"gt-dkc","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.736437-08:00","created_by":"daemon"}]}
{"id":"gt-3x1.2","title":"Fetch and conflict check: git operations for MR","description":"Implement git operations for MR processing.\n\nSteps:\n1. git fetch origin \u003cmr.branch\u003e\n2. git checkout \u003cmr.target\u003e (main or integration/xxx)\n3. git merge --no-commit --no-ff \u003cmr.branch\u003e (test merge)\n4. Check for conflicts\n5. If conflicts: abort and return Failure(conflict, files)\n6. If clean: abort (actual merge in next step)\n\nHelper functions:\n- FetchBranch(branch string) error\n- CheckConflicts(source, target string) ([]string, error)\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:58.99193-08:00","updated_at":"2025-12-19T12:56:15.197864-08:00","closed_at":"2025-12-18T20:17:47.781432-08:00","dependencies":[{"issue_id":"gt-3x1.2","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:50:58.993973-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.2","depends_on_id":"gt-3x1.1","type":"blocks","created_at":"2025-12-17T13:53:10.066159-08:00","created_by":"daemon"}]}
{"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-bmjw","title":"gt polecat add: should handle existing branch gracefully","description":"## Problem\n\n`gt polecat add gastown Nux` fails if the branch `polecat/Nux` already exists.\n\n## Current Behavior\n\n```\nfatal: a branch named 'polecat/Nux' already exists\n```\n\n## Expected Behavior\n\nShould either:\n1. Reuse the existing branch\n2. Or prompt to delete/recreate\n3. Or auto-suffix: polecat/Nux-2\n\n## Context\n\nBranch may exist from previous polecat that was removed but branch wasn't cleaned up.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:52:09.361672-08:00","updated_at":"2025-12-18T21:52:09.361672-08:00"}
{"id":"gt-4nn.3","title":"Molecule CLI: bd molecule commands","description":"Add molecule commands to bd:\n\n## Commands\n\n```bash\nbd molecule list # List molecules (type: molecule)\nbd molecule show \u003cid\u003e # Show molecule with parsed steps\nbd molecule parse \u003cid\u003e # Validate and show parsed structure \nbd molecule instantiate \u003cmol-id\u003e --parent=\u003cissue-id\u003e # Create steps\nbd molecule instances \u003cmol-id\u003e # Show all instantiations\n```\n\n## gt spawn integration\n\n```bash\ngt spawn --issue \u003cid\u003e --molecule \u003cmol-id\u003e\n```\n\nThis should:\n1. Call `bd molecule instantiate` (creates child beads atomically)\n2. Spawn polecat on first ready step\n3. Polecat grinds through via `bd ready`\n\n## Output Examples\n\n```\n$ bd molecule show mol-abc\n\nmol-abc: Engineer in a Box\nType: molecule\n\nSteps (5):\n design → (ready first)\n implement → Needs: design\n review → Needs: implement\n test → Needs: implement \n submit → Needs: review, test\n \nInstances: 3\n```\n\n```\n$ bd molecule instances mol-abc\n\nParent Status Created\ngt-xyz done 2025-12-15\ngt-abc active 2025-12-17 (3/5 complete)\ngt-def pending 2025-12-18\n```","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:53.919884-08:00","updated_at":"2025-12-19T12:56:15.200815-08:00","closed_at":"2025-12-19T12:00:37.165927-08:00","dependencies":[{"issue_id":"gt-4nn.3","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:53.921621-08:00","created_by":"daemon"},{"issue_id":"gt-4nn.3","depends_on_id":"gt-4nn.2","type":"blocks","created_at":"2025-12-18T18:07:03.048941-08:00","created_by":"daemon"}]}
{"id":"gt-fko","title":"Add Gas Town theory of operation to all role primings","description":"All roles (Mayor, Witness, Refinery, Polecat) should get basic GT architecture context: harness, rigs, agents, mail, beads workflow","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T16:42:46.445526-08:00","updated_at":"2025-12-17T17:00:36.466742-08:00","closed_at":"2025-12-17T17:00:36.466742-08:00","dependencies":[{"issue_id":"gt-fko","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.87032-08:00","created_by":"daemon"},{"issue_id":"gt-fko","depends_on_id":"gt-dkc","type":"blocks","created_at":"2025-12-17T16:42:56.409618-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:48.952108-08:00","updated_at":"2025-12-17T13:52:48.952108-08:00","dependencies":[{"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"},{"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"}]}
{"id":"gt-u1j.14","title":"Merge queue: per-rig queue management","description":"Per-rig merge queue for coordinating polecat work.\n\n## Concept\n\nWhen polecats complete work, they submit to the merge queue. The Refinery processes the queue, merging work to main in order.\n\n## Data Model\n\n```go\ntype MergeRequest struct {\n ID string `json:\"id\"`\n Polecat string `json:\"polecat\"`\n Branch string `json:\"branch\"`\n Issue string `json:\"issue,omitempty\"`\n Status MRStatus `json:\"status\"`\n CreatedAt time.Time `json:\"created_at\"`\n UpdatedAt time.Time `json:\"updated_at\"`\n}\n\ntype MRStatus string\nconst (\n MRPending MRStatus = \"pending\"\n MRReviewing MRStatus = \"reviewing\"\n MRMerged MRStatus = \"merged\"\n MRRejected MRStatus = \"rejected\"\n)\n```\n\n## Interface\n\n```go\ntype MergeQueue struct {\n rig *Rig\n path string // \u003crig\u003e/refinery/queue.jsonl\n}\n\nfunc NewMergeQueue(rig *Rig) *MergeQueue\n\n// Queue operations\nfunc (mq *MergeQueue) Submit(polecat, branch string, issue string) (*MergeRequest, error)\nfunc (mq *MergeQueue) List() ([]*MergeRequest, error)\nfunc (mq *MergeQueue) Next() (*MergeRequest, error) // oldest pending\nfunc (mq *MergeQueue) Get(id string) (*MergeRequest, error)\n\n// Status updates\nfunc (mq *MergeQueue) SetStatus(id string, status MRStatus) error\nfunc (mq *MergeQueue) MarkMerged(id string) error\nfunc (mq *MergeQueue) MarkRejected(id, reason string) error\n```\n\n## Queue Storage\n\nJSONL file at `\u003crig\u003e/refinery/queue.jsonl`. FIFO ordering.\n\n## Git Coordination\n\nRefinery processes queue:\n1. Fetch polecat branch\n2. Attempt merge to main\n3. Run tests (if configured)\n4. Push to origin\n5. Update queue status\n\n## Conflict Handling\n\nIf merge fails:\n- Mark MR as rejected\n- Notify polecat to rebase","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:57.707908-08:00","updated_at":"2025-12-16T21:35:56.001929-08:00","closed_at":"2025-12-16T21:35:56.001929-08:00","dependencies":[{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:14:18.469302-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:18.549859-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.14","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:57.708254-08:00","created_by":"daemon"}]}
{"id":"gt-alx","title":"Swarm: ephemeral rig support","description":"PGT has ephemeral rigs for swarms - temporary worker groups that are destroyed after landing.\n\nMissing Features:\n- gt swarm init [--rig \u003cname\u003e|--git-url \u003curl\u003e] [--num-workers N]\n- gt swarm worker add/remove/list \u003crig-id\u003e\n- gt swarm rigs - List ephemeral rigs\n- gt swarm destroy \u003crig-id\u003e - Destroy ephemeral rig\n\nDirectory structure:\n\u003cworkspace\u003e/mayor/workers/\u003crig-id\u003e/\n├── rig.json (metadata)\n├── alice/ (git clone)\n├── bob/\n└── carol/\n\nPGT Reference: gastown-py/src/gastown/ephemeral.py\n\nNote: Beads issue gt-kmn.12 mentions this but implementation is missing.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:14.302762-08:00","updated_at":"2025-12-16T16:03:47.902849-08:00","closed_at":"2025-12-16T16:03:47.902849-08:00"}
{"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-j87","title":"Design: Work flow simulation and validation","description":"Validate GGT designs through simulation before implementation.\n\n## Validation Approaches\n\n### 1. Dry-Run Simulation (Recommended First)\nMayor walks through scenarios mentally/on paper:\n- \"If polecat Toast signals done with dirty git state, what happens?\"\n- \"If Witness context fills mid-verification, what state is lost?\"\n- \"If two polecats try to close same issue, what happens?\"\n\nCreate beads for any gaps discovered.\n\n### 2. Real Work in gastown-py\nUse Python Gas Town to stress-test assumptions:\n- Run actual batch work on test repos\n- Observe edge cases in practice\n- Document issues found\n\n### 3. Edge Case Analysis\nSystematic review of failure modes:\n- Agent crashes mid-operation\n- Network failures during sync\n- Concurrent access to shared state\n- Context limits hit at bad times\n\n## Key Scenarios to Validate\n\n- [ ] Witness session cycling (state preservation)\n- [ ] Polecat decommission with dirty state\n- [ ] Merge conflicts in queue\n- [ ] Beads sync conflicts between workers\n- [ ] Escalation path (stuck worker -\u003e Mayor)\n- [ ] Cross-rig communication\n- [ ] Federation mail routing (future)\n\n## Success Criteria\n\n- No data loss scenarios identified\n- Clear recovery paths for all failure modes\n- Edge cases either handled or documented as limitations\n- Design improves as model cognition improves\n\n## Output\n\nFor each scenario validated:\n1. Document in relevant bead if issue found\n2. Create new beads for missing functionality\n3. Update architecture.md if design changes","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-15T20:24:11.251841-08:00","updated_at":"2025-12-16T17:25:49.858717-08:00"}
{"id":"gt-1j6","title":"Document harness concept in docs/harness.md","description":"Create comprehensive harness documentation:\n- What is a harness (installation directory)\n- Recommended structure and naming\n- .beads/redirect for default project\n- config/ contents (rigs.json, town.json)\n- Mayor home vs rig-level mayor/\n- Example configurations\n- Relationship to rigs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:37.559374-08:00","updated_at":"2025-12-19T12:56:15.196155-08:00","closed_at":"2025-12-19T12:07:31.407299-08:00","dependencies":[{"issue_id":"gt-1j6","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.974059-08:00","created_by":"daemon"}]}
{"id":"gt-71i","title":"Update architecture.md: Engineer role and Beads merge queue","description":"Update docs/architecture.md with recent design decisions:\n\n1. Agent table: Change \"Refinery\" role to \"Engineer\"\n - Refinery = place/module/directory\n - Engineer = role (agent that works in the Refinery)\n\n2. Merge Queue section: Document Beads-native model\n - MRs are beads issues with --type=merge-request\n - gt mq commands (submit, list, next, process, reorder)\n - Ordering via depends-on links\n\n3. CLI section: Add gt mq commands\n\n4. Key Design Decisions: Add decisions for:\n - #15: Merge Queue in Beads\n - #16: Engineer role (distinct from Refinery place)\n - #17: Session restart protocol for Engineer","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:12:03.616159-08:00","updated_at":"2025-12-16T23:12:03.616159-08:00","dependencies":[{"issue_id":"gt-71i","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:12:14.92163-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.21","title":"Test infrastructure: fixtures, mocks, integration tests","description":"Test infrastructure for Gas Town.\n\n## Test Categories\n\n### Unit Tests\n- Config parsing\n- Mail operations\n- Merge queue operations\n- Template rendering\n\n### Integration Tests\n- Git operations (uses real git in temp dirs)\n- Full workflows (spawn → work → merge)\n- CLI command tests\n\n## Fixtures\n\n```go\npackage testutil\n\n// Creates temp town with minimal structure\nfunc NewTestTown(t *testing.T) *TestTown\n\n// Creates temp rig with git repo\nfunc NewTestRig(t *testing.T, town *TestTown, name string) *TestRig\n\n// Creates test polecat\nfunc NewTestPolecat(t *testing.T, rig *TestRig, name string) *TestPolecat\n```\n\n## Mocks\n\n```go\n// Mock tmux for session tests (avoid actual tmux)\ntype MockTmux struct {\n Sessions map[string][]string // captured send-keys\n}\n\nfunc (m *MockTmux) NewSession(name, dir string) error\nfunc (m *MockTmux) SendKeys(session, keys string) error\nfunc (m *MockTmux) CapturePane(session string, lines int) (string, error)\n```\n\n## Test Helpers\n\n```go\n// Run test in temp directory\nfunc InTempDir(t *testing.T, fn func(dir string))\n\n// Initialize git repo for testing\nfunc InitGitRepo(t *testing.T, dir string)\n\n// Assert file exists with content\nfunc AssertFileContains(t *testing.T, path, substr string)\n\n// Assert JSON file has field\nfunc AssertJSONField(t *testing.T, path, field string, expected any)\n```\n\n## CI Integration\n\n- go test ./... runs all tests\n- Integration tests skip with -short flag\n- Coverage report generation\n\n## Test Data\n\nEmbedded test fixtures:\n```go\n//go:embed testdata/*\nvar testdataFS embed.FS\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:28.755475-08:00","updated_at":"2025-12-15T21:21:56.470205-08:00","dependencies":[{"issue_id":"gt-u1j.21","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:28.755866-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.21","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.425389-08:00","created_by":"daemon"}]}
{"id":"gt-3x1","title":"Update Refinery to use Beads merge queue","description":"Replace branch discovery with Beads queue in the Refinery module:\n\nCurrent (internal/refinery/manager.go):\n- Scans for polecat/* branches\n- Creates MR objects on-the-fly\n\nNew:\n- Pull from Beads: bd ready --type=merge-request\n- Process each MR\n- Close with merge commit: bd close \u003cid\u003e --reason=\"Merged at \u003csha\u003e\"\n- Handle failures: bd update \u003cid\u003e --status=blocked --reason=\"...\"\n\nThe Engineer (agent) becomes Beads-native.\nThe Refinery (module) provides the infrastructure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:37.96436-08:00","updated_at":"2025-12-19T15:27:45.506132-08:00","closed_at":"2025-12-19T14:47:51.65991-08:00","dependencies":[{"issue_id":"gt-3x1","depends_on_id":"gt-svi","type":"blocks","created_at":"2025-12-16T23:03:12.814463-08:00","created_by":"daemon"},{"issue_id":"gt-3x1","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.812433-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.9","title":"Outpost assignment policy: Smart work routing","description":"## Overview\n\nPolicy engine for deciding which outpost gets which work.\n\n## Policy Configuration\n\n```yaml\npolicy:\n # Default order of preference\n default_preference: [local, gce-burst, cloudrun-burst]\n \n # Rules applied in order\n rules:\n # Background work → Cloud Run (cheap)\n - condition: \"priority \u003e= P3\"\n prefer: cloudrun-burst\n \n # Long tasks → VM (persistent)\n - condition: \"estimated_duration \u003e 30m\"\n prefer: gce-burst\n \n # Specific epic → specific outpost\n - condition: \"epic == gt-abc\"\n prefer: local\n```\n\n## Implementation\n\n```go\ntype AssignmentPolicy struct {\n DefaultPreference []string\n Rules []PolicyRule\n}\n\ntype PolicyRule struct {\n Condition string // Simple expression\n Prefer string // Outpost name\n Require string // Must use this outpost\n}\n\nfunc (p *AssignmentPolicy) SelectOutpost(\n issue Issue, \n outposts map[string]Outpost,\n) Outpost {\n // Check rules in order\n for _, rule := range p.Rules {\n if rule.Matches(issue) {\n if op, ok := outposts[rule.Prefer]; ok {\n if op.ActiveWorkers() \u003c op.MaxWorkers() {\n return op\n }\n }\n }\n }\n \n // Fall back to default preference\n for _, name := range p.DefaultPreference {\n if op, ok := outposts[name]; ok {\n if op.ActiveWorkers() \u003c op.MaxWorkers() {\n return op\n }\n }\n }\n \n return nil // All outposts at capacity\n}\n```\n\n## Condition Language\n\nSimple expressions, not a full DSL:\n\n```\npriority \u003e= P3\npriority == P0\nestimated_duration \u003e 30m\nepic == gt-abc\ntype == bug\nlabel contains \"urgent\"\n```\n\n## Files\n\n- `internal/outpost/policy.go`\n- `internal/outpost/condition.go`\n\nDepends on: gt-9a2.3 (config)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:21.08101-08:00","updated_at":"2025-12-16T18:03:21.08101-08:00","dependencies":[{"issue_id":"gt-9a2.9","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:03:46.300288-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.9","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:21.083256-08:00","created_by":"daemon"}]}
{"id":"gt-0pc","title":"Document Overseer role (human operator)","description":"Document the Overseer role in Gas Town architecture.\n\n## The Overseer\n\nThe **Overseer** is the human operator of Gas Town. Not an agent - a person.\n\n## Responsibilities\n\n| Area | Overseer Does | Mayor/Agents Do |\n|------|---------------|-----------------|\n| Strategy | Define project goals | Execute toward goals |\n| Priorities | Set priority order | Work in priority order |\n| Escalations | Final decision on stuck work | Escalate to Overseer |\n| Resources | Provision machines | Use allocated resources |\n| Quality | Review \u0026 approve swarm output | Produce output |\n| Operations | Run gt commands, monitor dashboards | Do the work |\n\n## Key Interactions\n\n### Overseer → Mayor\n- Start/stop Mayor sessions\n- Direct Mayor via conversation\n- Review Mayor recommendations\n- Approve cross-rig decisions\n\n### Mayor → Overseer (Escalations)\n- Stuck workers after retries\n- Resource decisions (add machines, polecats)\n- Ambiguous requirements\n- Architecture decisions\n\n## Operating Cadence\n\nTypical Overseer workflow:\n1. Morning: Check status, review overnight work\n2. During day: Monitor, respond to escalations, adjust priorities\n3. End of day: Review progress, plan next batch\n\n## Commands for Overseers\n\n```bash\ngt status # Quick health check\ngt doctor # Detailed diagnostics \ngt doctor --fix # Auto-repair issues\ngt inbox # Messages from agents\ngt stop --all # Emergency halt\n```\n\n## Documentation Updates\n\nAdd to docs/architecture.md:\n- Overseer section under Agent Roles\n- Clarify Mayor reports to Overseer\n- Add Overseer to workflow diagrams","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T23:18:03.177633-08:00","updated_at":"2025-12-15T23:22:51.477786-08:00","closed_at":"2025-12-15T23:22:51.477786-08:00"}
{"id":"gt-2n3f","title":"Merge conflicts: Buzzard/mq-status, Dementus/harness-docs","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T12:08:07.486349-08:00","updated_at":"2025-12-19T15:06:22.390602-08:00","closed_at":"2025-12-19T14:28:14.462028-08:00"}
{"id":"gt-4nn.2","title":"Molecule instantiation: create child beads from template","description":"When instantiating a molecule on a work bead:\n\n## Transaction Flow\n\n1. Parse molecule's `## Step:` sections from description\n2. Begin SQLite transaction\n3. For each step, create child issue:\n - ID: `{parent-id}.{step-ref}` or generated\n - Title: step title (from header or first line)\n - Description: step prose instructions\n - Type: task\n - Priority: inherit from parent\n4. Add `instantiated-from` edge from each step to molecule:\n ```sql\n INSERT INTO dependencies (issue_id, depends_on_id, type, metadata)\n VALUES (step_id, mol_id, 'instantiated-from', '{\"step\": \"implement\"}');\n ```\n5. Wire inter-step dependencies from `Needs:` lines\n6. Commit transaction (atomic - all or nothing)\n\n## Parsing Conventions\n\n```markdown\n## Step: \u003cref\u003e\n\u003cprose instructions\u003e\nNeeds: \u003cstep\u003e, \u003cstep\u003e # optional\nTier: haiku|sonnet|opus # optional hint\n```\n\n## Parameterization\n\nSteps can have `{{variable}}` placeholders:\n```markdown\n## Step: implement\nImplement {{feature_name}} in {{target_file}}.\n```\n\nContext map provided at instantiation time.\n\n## API\n\n```go\nfunc (s *Store) InstantiateMolecule(mol *Issue, parent *Issue, ctx map[string]string) ([]*Issue, error)\nfunc ParseMoleculeSteps(description string) ([]MoleculeStep, error)\n```\n\nImplementation lives in `internal/beads/molecule.go`.","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:52.071066-08:00","updated_at":"2025-12-19T12:56:15.200215-08:00","closed_at":"2025-12-19T01:57:17.028198-08:00","dependencies":[{"issue_id":"gt-4nn.2","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:52.072554-08:00","created_by":"daemon"},{"issue_id":"gt-4nn.2","depends_on_id":"gt-4nn.1","type":"blocks","created_at":"2025-12-18T18:07:02.949242-08:00","created_by":"daemon"}]}
{"id":"gt-lno","title":"Swarm state persistence: manifest + state + events","description":"Upgrade swarm persistence to match PGT pattern.\n\n## Current State\nSingle .gastown/swarms.json with all swarms.\n\n## Target State (per-swarm)\n```\n.gastown/swarms/\n└── \u003cswarm-id\u003e/\n ├── manifest.json # Immutable config\n ├── state.json # Mutable progress\n ├── events.jsonl # Audit log\n └── report.md # Generated report\n```\n\n## File Schemas\n\n### manifest.json (immutable after creation)\n```json\n{\n \"id\": \"sw-1\",\n \"title\": \"Epic description\",\n \"epic_id\": \"gt-abc\",\n \"rig\": \"gastown\",\n \"base_commit\": \"abc123\",\n \"integration_branch\": \"swarm/sw-1\",\n \"target_branch\": \"main\",\n \"workers\": [\"Toast\", \"Nux\"],\n \"tasks\": [{\"id\": \"gt-xyz\", \"title\": \"...\"}],\n \"created_at\": \"2024-01-01T00:00:00Z\"\n}\n```\n\n### state.json (mutable)\n```json\n{\n \"state\": \"active\",\n \"task_states\": {\n \"gt-xyz\": {\"state\": \"merged\", \"assignee\": \"Toast\"}\n },\n \"updated_at\": \"2024-01-01T01:00:00Z\",\n \"error\": null\n}\n```\n\n### events.jsonl (append-only audit)\n```jsonl\n{\"event\": \"created\", \"ts\": \"...\", \"data\": {...}}\n{\"event\": \"task_assigned\", \"ts\": \"...\", \"data\": {...}}\n{\"event\": \"task_merged\", \"ts\": \"...\", \"data\": {...}}\n```\n\n## Benefits\n- Audit trail via events.jsonl\n- Manifest immutability prevents corruption\n- Cleaner separation of concerns\n- Per-swarm isolation\n\n## Migration\nKeep backward compat with swarms.json during transition.\n\n## Files to Modify\n- internal/swarm/manager.go: Refactor persistence\n- internal/cmd/swarm.go: SwarmStore → directory-based\n\n## Acceptance Criteria\n- [ ] Per-swarm directory structure\n- [ ] Events logged to JSONL\n- [ ] Manifest immutable after creation\n- [ ] List command aggregates from directories","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:48:14.151538-08:00","updated_at":"2025-12-16T17:23:19.716405-08:00","closed_at":"2025-12-16T17:23:19.716405-08:00"}
{"id":"gt-bfd","title":"Keepalive signal from bd/gt commands","description":"Every bd and gt command should touch a keepalive file to signal 'agent is alive/working'.\n\n## Implementation\n\nTouch `\u003cworkspace\u003e/.gastown/keepalive.json`:\n```json\n{\"last_command\": \"bd show gt-99m\", \"timestamp\": \"2025-12-18T13:45:00Z\"}\n```\n\n## Usage by Daemon\n\n- Fresh (\u003c 2 min) → agent is working, skip heartbeat\n- Stale (2-5 min) → might be thinking, gentle poke\n- Very stale (\u003e 5 min) → likely idle, safe to interrupt\n\n## Benefits\n\n- Zero cost (just file I/O)\n- Works during long tool calls\n- Doesn't require agent cooperation\n- Foundation for smarter backoff strategies","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T14:19:26.241957-08:00","updated_at":"2025-12-19T12:56:15.205871-08:00","closed_at":"2025-12-18T20:03:43.816952-08:00","dependencies":[{"issue_id":"gt-bfd","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.407664-08:00","created_by":"daemon"}]}
{"id":"gt-l4gm","title":"Crew workers: design documentation and remaining work","description":"## Summary\n\nCrew workers are user-managed persistent workspaces within a rig, distinct from polecats.\n\n## Current Implementation\n\n### Commands (all working)\n- `gt crew add \u003cname\u003e` - Create workspace (git clone)\n- `gt crew list` - List workspaces with status\n- `gt crew at \u003cname\u003e` - Attach to tmux session\n- `gt crew remove \u003cname\u003e` - Remove workspace\n- `gt crew pristine [\u003cname\u003e]` - git pull + bd sync\n- `gt crew refresh \u003cname\u003e` - Context cycle with handoff mail\n- `gt crew status [\u003cname\u003e]` - Detailed status\n- `gt crew rename \u003cname\u003e` - Rename workspace\n\n### Crew vs Polecat\n\n| Aspect | Crew | Polecat |\n|--------|------|---------|\n| Lifecycle | User-managed | Witness-managed |\n| Scheduling | Manual | `gt spawn` |\n| Merge flow | Direct push OK | Integration branch → refinery |\n| Garbage collection | Never | Auto on completion |\n| Identity | Long-lived (emma, dave) | Ephemeral (Nux, Toast) |\n\n## Known Bugs\n\n- **gt-70b3**: detectSender() doesn't recognize crew workers\n- **gt-vdp0**: Crew CLAUDE.md shows Refinery template\n\n## Potential Enhancements\n\n1. Rebase helper in `gt crew pristine` for conflict resolution\n2. Cross-rig crew support (crew worker in multiple rigs?)\n3. Better mail identity auto-detection for crew","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T21:49:58.524424-08:00","updated_at":"2025-12-18T21:49:58.524424-08:00"}
{"id":"gt-1qti","title":"Mayor restart loop: auto-prime and mail check on attach","description":"When mayor session cycles (after /exit, gt mayor attach reconnects), the new session lacks context.\n\n## Current Behavior\n- Mayor exits, shell script loop restarts claude\n- New session starts cold - no gt prime, no mail check\n- Mayor is disoriented, doesn't know prior context\n- Strong 'antimemetic properties' - we discuss fixing it, then forget\n\n## Expected Behavior\nAfter restart, mayor should automatically:\n1. Run gt prime (load role context)\n2. Check gt mail inbox (find handoff messages)\n3. Look for 🤝 HANDOFF messages from predecessor\n\n## Possible Fixes\n1. Startup hook in Claude Code settings that runs gt prime\n2. CLAUDE.md instructions that say 'FIRST THING: run gt prime'\n3. Shell script wrapper that injects context before attach\n4. Modify gt mayor attach to inject prime command\n\n## Related\n- gt-vci: Mayor handoff mail template\n- gt-sye: Mayor startup protocol prompting","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:44:43.188588-08:00","updated_at":"2025-12-19T17:22:52.550264-08:00","closed_at":"2025-12-19T16:03:20.714077-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T17:12:59.200876-08:00","updated_at":"2025-12-15T23:17:22.102624-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-k7x0","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:42.318338-08:00","updated_at":"2025-12-19T14:54:35.021214-08:00","closed_at":"2025-12-19T14:54:35.021214-08:00"}
{"id":"gt-u1j.22","title":"CLI: gt stop --all (emergency swarm kill)","description":"Emergency kill command for swarm operations.\n\n## Commands\n\n```bash\ngt stop --all # Kill ALL sessions across all rigs\ngt stop --rig \u003cname\u003e # Kill all sessions in one rig\ngt stop --rig \u003cname\u003e --graceful # Try graceful first, then force\n```\n\n## Implementation\n\n### --all flag\n1. List all tmux sessions matching gt-*\n2. For each: capture final output, kill session\n3. Update all polecat states to idle\n4. Log all killed sessions\n5. Send mail to Mayor: \"Emergency stop executed\"\n\n### --rig flag\n1. List sessions for specific rig\n2. Same as above but scoped\n\n### --graceful flag\n1. First, try to inject \"exit\" command\n2. Wait 5 seconds\n3. If still running, force kill\n\n## Output\n\n```\nStopping all Gas Town sessions...\n [wyvern] Toast: captured output, killed\n [wyvern] Capable: captured output, killed\n [beads] Nux: captured output, killed\n \n3 sessions stopped.\nAll polecat states set to 'idle'.\nMail sent to mayor/.\n```\n\n## Safety\n\n- Always capture output before killing\n- Update state files to reflect reality\n- Log all operations to gt.log\n- Warn if uncommitted changes detected (but still kill)\n\n## Dependencies\n\nNeeds: Tmux wrapper, Session management, Polecat management","status":"closed","issue_type":"task","created_at":"2025-12-15T23:17:51.455669-08:00","updated_at":"2025-12-16T13:58:10.419696-08:00","closed_at":"2025-12-16T13:58:10.419696-08:00","dependencies":[{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T23:18:58.297176-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T23:17:51.456008-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.22","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T23:18:58.198873-08:00","created_by":"daemon"}]}
{"id":"gt-unrd","title":"Fix gt prime to give crew workers crew context","description":"gt prime currently gives Mayor context to all agents. Crew workers should get crew-specific context. Also extract shared theory of operation from mayor priming into shared context for all roles.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T15:37:49.671015-08:00","updated_at":"2025-12-19T17:22:52.551704-08:00","closed_at":"2025-12-19T15:41:38.806903-08:00"}
{"id":"gt-e1r","title":"CLI: rig commands (add, list, show, remove)","description":"GGT needs rig management commands.\n\nMissing Commands:\n- gt rig add \u003cgit-url\u003e [--name NAME] - Add rig to workspace\n- gt rig list - List all rigs with status\n- gt rig show \u003crig\u003e - Show detailed rig info\n- gt rig remove \u003crig\u003e - Remove a rig\n\nPGT Reference: gastown-py/src/gastown/cli/rig_cmd.py\n\nCurrent State:\n- gt init creates rig structure but no ongoing management\n- Rig discovery in internal/rig/manager.go but not exposed via CLI","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:33.23951-08:00","updated_at":"2025-12-16T16:03:15.727426-08:00","closed_at":"2025-12-16T16:03:15.727426-08:00"}
{"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-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-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T00:10:44.915982-08:00","updated_at":"2025-12-16T17:26:30.080125-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-cik.4","title":"gt crew at/attach: Start session in crew workspace","description":"Implement 'gt crew at \u003crig\u003e/\u003cname\u003e' and 'gt crew attach \u003cname\u003e' commands:\n- Start tmux session (optional - could just print cd instructions)\n- Launch claude code in the workspace\n- Deliver any pending mail\n- Support --no-tmux to just print directory path\n- 'attach' infers rig from cwd","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:04.96786-08:00","updated_at":"2025-12-16T20:59:33.355591-08:00","closed_at":"2025-12-16T20:53:16.677693-08:00","dependencies":[{"issue_id":"gt-cik.4","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:04.969488-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.13","title":"CloudRun persistent connections: HTTP/2 keepalive","description":"## Overview\n\nImplement persistent HTTP/2 connections to keep Cloud Run containers warm.\n\n## Problem\n\nCloud Run has cold start latency when scaling from 0. Persistent connections keep containers warm.\n\n## Implementation\n\n```go\ntype PersistentConnectionManager struct {\n serviceURL string\n conn net.Conn\n client *http2.ClientConn\n mu sync.Mutex\n lastUsed time.Time\n keepAlive time.Duration\n}\n\nfunc (m *PersistentConnectionManager) GetConnection() (*http2.ClientConn, error) {\n m.mu.Lock()\n defer m.mu.Unlock()\n \n // Reuse existing connection if healthy\n if m.client != nil \u0026\u0026 m.client.CanTakeNewRequest() {\n m.lastUsed = time.Now()\n return m.client, nil\n }\n \n // Create new connection\n return m.dial()\n}\n\nfunc (m *PersistentConnectionManager) keepAliveLoop() {\n ticker := time.NewTicker(m.keepAlive / 2)\n for range ticker.C {\n m.mu.Lock()\n if time.Since(m.lastUsed) \u003e m.keepAlive {\n // Connection idle too long, close it\n m.close()\n } else {\n // Send ping to keep alive\n m.ping()\n }\n m.mu.Unlock()\n }\n}\n```\n\n## Integration with CloudRunOutpost\n\n```go\ntype CloudRunOutpost struct {\n // ...existing fields...\n connMgr *PersistentConnectionManager\n}\n\nfunc (o *CloudRunOutpost) Spawn(...) {\n conn, err := o.connMgr.GetConnection()\n // Use connection for work dispatch\n}\n```\n\n## Config\n\n```yaml\noutposts:\n - name: cloudrun-burst\n type: cloudrun\n # ...\n keep_alive: 5m # Keep connection warm for 5 minutes\n```\n\n## Files\n\n- `internal/cloudrun/connection.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (basic CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:57.082691-08:00","updated_at":"2025-12-16T18:15:57.082691-08:00","dependencies":[{"issue_id":"gt-9a2.13","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:57.084539-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.13","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:12.190542-08:00","created_by":"daemon"}]}
{"id":"gt-hzr","title":"gt witness: Witness management commands","description":"Add 'gt witness' command group for witness lifecycle management.\n\nSubcommands:\n- gt witness start [rig] - Start witness for a rig\n- gt witness stop [rig] - Stop witness\n- gt witness status [rig] - Show witness status\n- gt witness attach [rig] - Attach to witness session\n\nWitness monitors polecats and handles:\n- Idle detection and cleanup\n- Session health checks\n- Nudging stuck agents","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:47:32.210917-08:00","updated_at":"2025-12-19T12:56:15.212423-08:00","closed_at":"2025-12-19T12:05:27.343254-08:00","dependencies":[{"issue_id":"gt-hzr","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:42.955006-08:00","created_by":"daemon"}]}
{"id":"gt-6t0","title":"gt swarm: Not discovering tasks from epic dependents","description":"gt swarm create/start shows '0 tasks loaded' even when epic has dependents.\n\nRepro:\n1. Create epic gt-hw6\n2. Create tasks and add deps: bd dep add gt-xxx gt-hw6\n3. gt swarm create gastown --epic gt-hw6 --worker Toast\n4. Swarm shows 'Tasks: 0'\n\nExpected: Swarm should discover tasks that depend on the epic.\nActual: Shows '(no tasks loaded)'","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:25:41.653628-08:00","updated_at":"2025-12-17T22:31:58.848858-08:00","closed_at":"2025-12-17T22:31:58.848858-08:00"}
{"id":"gt-7we","title":"Swarms of One: Lightweight single-worker task dispatch","description":"Design and implement a lightweight pattern for firing off single workers to handle tasks without full swarm overhead.\n\n## Context\n\nCurrently we have:\n- town spawn: Creates a polecat in a rig with issue assignment\n- Swarms (sw-*): Full lifecycle tracking with manifest, state, events, reports\n- Ephemeral rigs (rig-*): Temporary worker groups for swarms\n\nWhat's missing: A simple way to say 'fire off a worker to do X' without swarm ceremony.\n\n## Design Questions\n\n1. Should this be a new command like 'gt fire' or an option on existing commands?\n2. Should single tasks still get swarm IDs (sw-N) for consistency/queryability?\n3. Should it default to creating new workers or support --reuse for idle polecats?\n4. How does this relate to crew workers (gt-cik)?\n\n## Possible Interface\n\ngt fire --rig gastown --issue gt-xyz [--prompt '...']\ngt fire gastown/QuickTask --issue gt-xyz\n\n## Related\n\n- gt-cik: Overseer Crew (user-managed persistent workspaces)\n- gt-kmn: Swarm System epic","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:51:02.716629-08:00","updated_at":"2025-12-16T17:23:18.589027-08:00","closed_at":"2025-12-16T17:23:18.589027-08:00"}
{"id":"gt-35s","title":"Architecture: beads config and direct landing docs","description":"Added to architecture.md:\n- Beads multi-agent configuration table (daemon, worktree, sync-branch)\n- ASCII directory layout for non-mermaid rendering\n- Direct landing workflow (bypass merge queue)\n- Design decisions 9 and 10 for direct landing and daemon awareness\n- CLI commands for gt land","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T00:29:52.395906-08:00","updated_at":"2025-12-16T00:29:59.188921-08:00","closed_at":"2025-12-16T00:29:59.188921-08:00"}
{"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":"open","priority":1,"issue_type":"epic","created_at":"2025-12-15T16:36:37.344283-08:00","updated_at":"2025-12-15T21:15:13.120038-08:00","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-2p2","title":"Test message","description":"Testing GGT mail integration","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-17T14:04:50.045948-08:00","updated_at":"2025-12-17T14:05:03.125655-08:00","closed_at":"2025-12-17T14:05:03.125655-08:00"}
{"id":"gt-cik.1","title":"Crew directory structure and config","description":"Add crew/ directory support to rig structure. Include:\n- crew/ as peer to polecats/, refinery/, witness/\n- Crew worker subdirectories with full git clones\n- Optional BEADS_DIR configuration for beads integration\n- Crew state tracking (separate from polecat state)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:00.285499-08:00","updated_at":"2025-12-16T20:47:23.003869-08:00","closed_at":"2025-12-16T20:31:23.558027-08:00","dependencies":[{"issue_id":"gt-cik.1","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:00.28789-08:00","created_by":"daemon"}]}
{"id":"gt-2ux","title":"gt uninstall: Clean removal of Gas Town harness","description":"Add 'gt uninstall' command to cleanly remove a Gas Town installation.\n\nShould:\n- Remove harness directory structure\n- Optionally preserve rigs/data with --keep-data flag\n- Warn about running sessions\n- Clean up any global config references","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:16.175246-08:00","updated_at":"2025-12-17T22:31:12.816428-08:00","closed_at":"2025-12-17T22:31:12.816428-08:00","dependencies":[{"issue_id":"gt-2ux","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.419553-08:00","created_by":"daemon"}]}
{"id":"gt-g44u","title":"Molecule Workflow Engine: Composable Crystallized Workflows","description":"# Epic: Molecule Workflow Engine\n\n**Vision**: Molecules are crystallized, composable, nondeterministic-idempotent workflow templates. Any worker can pick up where any other worker was interrupted and continue along the molecule.\n\n**Christmas Target**: Full molecule-based workflow engine operational by Dec 25, 2025.\n\n## The Core Concepts\n\n1. **Molecule**: Read-only workflow template (beads issue with type=molecule)\n2. **Atom/Step**: Individual work unit with prose instructions\n3. **Bond**: Dependency between steps\n4. **Polymer/Derived**: Molecule composed from other molecules\n5. **Instance**: Concrete beads created when molecule is attached to work\n\n## Key Features Needed\n\n### 1. Molecule Composition (Includes Directive)\nMolecules can include other molecules:\n\\`\\`\\`markdown\n## Molecule: gastown-polecat\nIncludes: mol-engineer-in-box\n\n## Step: install-binary\nBuild and install the local gt binary.\nNeeds: submit\n\\`\\`\\`\n\n### 2. Standard Molecules\n- mol-install-go-binary: Single step to build/install gt\n- mol-gastown-polecat: engineer-in-box + install-binary\n\n### 3. Spawn Integration\n\\`gt spawn --issue \u003cid\u003e --molecule \u003cmol-id\u003e\\` creates molecule instance then starts polecat on first ready step.\n\n### 4. Nondeterministic Idempotence\n- Steps are atomic (pending → in_progress → completed)\n- Any worker can pick up any ready step\n- Step timeout/recovery for stuck workers\n\n## Success Criteria\n- [ ] Polecats can be spawned with mol-gastown-polecat\n- [ ] Derived molecules work end-to-end\n- [ ] 10+ polecat swarm completes molecule workflows\n- [ ] install-go-binary step runs after successful merges","status":"closed","issue_type":"epic","created_at":"2025-12-19T15:49:32.005023-08:00","updated_at":"2025-12-19T16:23:08.857768-08:00","closed_at":"2025-12-19T16:23:08.857768-08:00"}
{"id":"gt-6z2.1","title":"Test Task 1: Add comment to gt.go","status":"closed","issue_type":"task","created_at":"2025-12-16T21:57:43.554166-08:00","updated_at":"2025-12-16T22:06:41.126547-08:00","closed_at":"2025-12-16T22:06:41.126547-08:00","dependencies":[{"issue_id":"gt-6z2.1","depends_on_id":"gt-6z2","type":"parent-child","created_at":"2025-12-16T21:57:43.55748-08:00","created_by":"daemon"}]}
{"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-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-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-tl54","title":"MR: gt-test (main)","description":"branch: main\ntarget: main\nsource_issue: gt-test","status":"closed","priority":3,"issue_type":"merge-request","created_at":"2025-12-18T20:16:41.125975-08:00","updated_at":"2025-12-18T20:21:54.162843-08:00","closed_at":"2025-12-18T20:21:54.162843-08:00"}
{"id":"gt-1su","title":"Spawn inject: Enter not submitted after multiline paste","description":"When gt spawn injects a multiline context (85+ lines), Claude Code shows \n'[Pasted text #1 +85 lines]' but the prompt is not submitted.\n\nThe tmux SendKeys function does include 'Enter' but it appears to not work\nfor long pasted text:\n\n```go\nfunc (t *Tmux) SendKeys(session, keys string) error {\n _, err := t.run(\"send-keys\", \"-t\", session, keys, \"Enter\")\n return err\n}\n```\n\nPossible fixes:\n1. Use tmux paste-buffer instead of send-keys for long text\n2. Send Enter separately after the text\n3. Use bracketed paste mode correctly\n\nReproduction:\n```bash\ngt spawn gastown/Nux --issue gt-u1j.13 --create\n# Session shows pasted text but waits at prompt\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-17T14:09:20.774203-08:00","updated_at":"2025-12-17T14:21:52.981381-08:00","closed_at":"2025-12-17T14:21:52.981381-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:21.968099-08:00","updated_at":"2025-12-15T23:17:18.644857-08:00","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-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-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-g44u.3","title":"Create mol-gastown-polecat derived molecule","description":"Create the standard Gas Town polecat workflow molecule.\n\n## Molecule Definition\n\\`\\`\\`markdown\n## Molecule: gastown-polecat\nFull workflow for Gas Town polecats including binary installation.\n\nIncludes: mol-engineer-in-box\n\n## Step: install-binary\nAfter merge is submitted, rebuild and install the local gt binary.\nThis ensures the latest code is available to all local agents.\n\nRun from the rig directory:\n\\`\\`\\`\ngo build -o gt ./cmd/gt\ngo install ./cmd/gt\n\\`\\`\\`\n\nNeeds: submit\n\\`\\`\\`\n\n## Why This Molecule\nEvery polecat that pushes to main should also rebuild the binary.\nThis ensures the installed gt is always current with main.\n\n## Implementation\n1. Add to builtin_molecules.go (after Includes support lands)\n2. Update SeedBuiltinMolecules\n3. Run gt molecule seed\n\n## Acceptance\n- [ ] mol-gastown-polecat exists\n- [ ] Includes all engineer-in-box steps\n- [ ] Adds install-binary step after submit\n- [ ] Can be used with gt spawn --molecule","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:12.702275-08:00","updated_at":"2025-12-19T16:14:43.859946-08:00","closed_at":"2025-12-19T16:14:43.859946-08:00","dependencies":[{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:12.704439-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u.1","type":"blocks","created_at":"2025-12-19T15:50:31.019186-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.3","depends_on_id":"gt-g44u.2","type":"blocks","created_at":"2025-12-19T15:50:31.14432-08:00","created_by":"daemon"}]}
{"id":"gt-oc2","title":"Daemon: proper rig discovery","description":"Currently discovers rigs by scanning tmux session names for gt-*-witness pattern. Should instead:\n- Read rigs from mayor/rigs.json\n- Or scan town directory for .gastown subdirs\n- Handle rigs that exist but don't have running witnesses","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:15.825299-08:00","updated_at":"2025-12-19T17:22:52.554474-08:00","closed_at":"2025-12-19T16:28:39.497935-08:00","dependencies":[{"issue_id":"gt-oc2","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.826697-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.12","title":"HTTP work client: CloudRun dispatch client","description":"## Overview\n\nHTTP client for dispatching work to Cloud Run and streaming results back.\n\n## Implementation\n\n```go\ntype WorkClient struct {\n serviceURL string\n httpClient *http.Client // HTTP/2 enabled\n}\n\nfunc NewWorkClient(serviceURL string) *WorkClient {\n return \u0026WorkClient{\n serviceURL: serviceURL,\n httpClient: \u0026http.Client{\n Transport: \u0026http2.Transport{},\n Timeout: 0, // No timeout for streaming\n },\n }\n}\n\nfunc (c *WorkClient) DispatchWork(ctx context.Context, req WorkRequest) (\u003c-chan WorkEvent, error) {\n // 1. POST to /work\n // 2. Return channel that streams WorkEvents\n // 3. Close channel when done/error\n}\n```\n\n## Streaming Reader\n\n```go\nfunc (c *WorkClient) streamEvents(body io.Reader, events chan\u003c- WorkEvent) {\n defer close(events)\n decoder := json.NewDecoder(body)\n for {\n var event WorkEvent\n if err := decoder.Decode(\u0026event); err != nil {\n return\n }\n events \u003c- event\n }\n}\n```\n\n## Files\n\n- `internal/cloudrun/client.go`\n\n## Dependencies\n\nDepends on: gt-9a2.7 (protocol types)\nUsed by: gt-9a2.8 (CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:10.881936-08:00","updated_at":"2025-12-16T18:15:10.881936-08:00","dependencies":[{"issue_id":"gt-9a2.12","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:10.882339-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.12","depends_on_id":"gt-9a2.7","type":"blocks","created_at":"2025-12-16T18:15:20.974167-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.8","title":"Polecat management: add, remove, list, state","description":"Polecat lifecycle: add, remove, list, state tracking.\n\n## Data Model\n\n```go\ntype Polecat struct {\n Name string `json:\"name\"`\n Rig string `json:\"rig\"`\n State PolecatState `json:\"state\"`\n ClonePath string `json:\"clone_path\"`\n Branch string `json:\"branch\"`\n Issue string `json:\"issue,omitempty\"`\n CreatedAt time.Time `json:\"created_at\"`\n UpdatedAt time.Time `json:\"updated_at\"`\n}\n\ntype PolecatState string\nconst (\n StateIdle PolecatState = \"idle\"\n StateActive PolecatState = \"active\"\n StateWorking PolecatState = \"working\"\n StateDone PolecatState = \"done\"\n StateStuck PolecatState = \"stuck\"\n)\n```\n\n## Interface\n\n```go\ntype PolecatManager struct {\n rig *Rig\n git *Git\n}\n\nfunc NewPolecatManager(rig *Rig, git *Git) *PolecatManager\n\n// Lifecycle\nfunc (pm *PolecatManager) Add(name string) (*Polecat, error)\nfunc (pm *PolecatManager) Remove(name string) error\nfunc (pm *PolecatManager) List() ([]*Polecat, error)\nfunc (pm *PolecatManager) Get(name string) (*Polecat, error)\n\n// State\nfunc (pm *PolecatManager) SetState(name string, state PolecatState) error\nfunc (pm *PolecatManager) AssignIssue(name, issue string) error\nfunc (pm *PolecatManager) ClearIssue(name string) error\n\n// Convenience\nfunc (pm *PolecatManager) Wake(name string) error // idle → active\nfunc (pm *PolecatManager) Sleep(name string) error // active → idle\n```\n\n## Add Flow\n\n1. Create directory: `\u003crig\u003e/polecats/\u003cname\u003e/`\n2. Clone rig repo into it (or copy from rig root)\n3. Create new branch: `polecat/\u003cname\u003e`\n4. Initialize polecat state file\n5. Create mail inbox\n\n## Remove Flow\n\n1. Verify session not running\n2. Check for uncommitted changes (warn/error)\n3. Remove directory\n4. Clean up state\n\n## State Persistence\n\nStore in `\u003crig\u003e/polecats/\u003cname\u003e/state.json`","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:27.402824-08:00","updated_at":"2025-12-16T13:37:34.912049-08:00","closed_at":"2025-12-16T13:37:34.912049-08:00","dependencies":[{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:27.403171-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:13:53.747126-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.8","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:13:53.831197-08:00","created_by":"daemon"}]}
{"id":"gt-w3bu","title":"gt spawn: Enter key needs debounce delay after paste","description":"## Problem\n\nWhen spawning polecats via `gt spawn`, instructions are pasted into tmux but workers often sit idle at prompt because the Enter key arrives before the paste is fully processed.\n\n## Observed Behavior\n\n- Instructions pasted via tmux send-keys\n- Enter key sent immediately after\n- Worker session shows prompt with no input (paste not submitted)\n- Requires manual intervention to nudge workers\n\n## Expected Behavior\n\n- Paste completes fully\n- Enter key submits the pasted instructions\n- Worker begins executing immediately\n\n## Root Cause\n\nLikely a race condition between paste buffer processing and keypress handling. Need either:\n1. Debounce delay before sending Enter\n2. Longer delay (Tmax) to ensure paste completes\n3. Alternative submission mechanism\n\n## Impact\n\n- Swarm of 10 workers had multiple stalls at startup\n- Required manual tmux send-keys to unstick them\n- Defeats purpose of automated spawning\n\n## References\n\n- Observed during Mad Max swarm (Dec 18, 2025)\n- Affects gt spawn command in internal/cmd/spawn.go","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:06:50.734123-08:00","updated_at":"2025-12-18T21:08:22.400899-08:00","closed_at":"2025-12-18T21:08:22.400899-08:00"}
{"id":"gt-ye8l","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:52.344849-08:00","updated_at":"2025-12-19T19:12:58.575707-08:00","closed_at":"2025-12-19T17:48:44.637297-08:00"}
{"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-u1j.12","title":"CLI: mail commands (send, inbox, read)","description":"CLI: mail commands wrapping bd mail.\n\n## Status\n\nCurrent implementation works with JSONL files. Refactor to wrap bd mail CLI.\n\n## Commands\n\n### gt mail inbox\n```\ngt mail inbox [--unread] [--json]\n```\nWraps: `bd mail inbox [--json]`\n\n### gt mail read\n```\ngt mail read \u003cid\u003e\n```\nWraps: `bd mail read \u003cid\u003e \u0026\u0026 bd mail ack \u003cid\u003e`\nNote: bd mail read + ack marks as read.\n\n### gt mail send\n```\ngt mail send \u003caddress\u003e -s \"Subject\" -m \"Body\" [--notify]\n```\nWraps: `bd mail send \u003crecipient\u003e -s \"Subject\" -m \"Body\"`\nIf --notify: inject tmux notification after send.\n\n### gt mail delete\n```\ngt mail delete \u003cid\u003e\n```\nWraps: `bd mail ack \u003cid\u003e` (closes the message issue)\n\n## Address Translation\n\nSame as gt-u1j.6:\n- `mayor/` → `mayor`\n- `\u003crig\u003e/refinery` → `\u003crig\u003e-refinery`\n- `\u003crig\u003e/\u003cpolecat\u003e` → `\u003crig\u003e-\u003cpolecat\u003e`\n\n## Dependencies\n\n- gt-u1j.6: Mail system backend","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:42.038558-08:00","updated_at":"2025-12-16T21:45:22.218817-08:00","closed_at":"2025-12-16T21:45:22.218817-08:00","dependencies":[{"issue_id":"gt-u1j.12","depends_on_id":"gt-r01","type":"blocks","created_at":"2025-12-16T13:12:08.639736-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.12","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:42.038885-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.12","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T17:14:06.328188-08:00","created_by":"daemon"}]}
{"id":"gt-g2d","title":"Mayor session cycling prompting","description":"Add session cycling section to Mayor CLAUDE.md template.\n\n## When to Cycle\n\nCycle proactively when:\n- Running for several hours\n- Context feels crowded (losing track of earlier state)\n- Major phase completed\n- About to start complex new work\n\n## Composing Handoff Notes\n\n1. Gather information:\n town status # Overall health\n town rigs # Each rig state\n town inbox # Pending messages\n bd ready # Work items\n\n2. Compose note with this structure:\n\n[HANDOFF_TYPE]: mayor_cycle\n[TIMESTAMP]: \u003ccurrent time\u003e\n[SESSION_DURATION]: \u003chow long running\u003e\n\n## Active Swarms\n\u003cper-rig swarm status\u003e\n\n## Rig Status\n\u003ctable of rig health\u003e\n\n## Pending Escalations\n\u003cissues needing your decision\u003e\n\n## In-Flight Decisions\n\u003cdecisions being made\u003e\n\n## Recent Actions\n\u003clast 5-10 things you did\u003e\n\n## Delegated Work\n\u003cwork sent to refineries\u003e\n\n## User Requests\n\u003cpending user asks\u003e\n\n## Next Steps\n\u003cwhat next session should do\u003e\n\n## Warnings/Notes\n\u003ccritical info for next session\u003e\n\n3. Send handoff:\n town mail send mayor/ -s \"Session Handoff\" -m \"\u003cnote\u003e\"\n\n4. End session - next instance picks up from handoff.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:26.188561-08:00","updated_at":"2025-12-15T20:48:39.861022-08:00","dependencies":[{"issue_id":"gt-g2d","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.361163-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-56fv","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:36:24.884931-08:00","updated_at":"2025-12-19T18:30:24.049689-08:00","closed_at":"2025-12-19T18:30:24.049694-08:00"}
{"id":"gt-5af.1","title":"Create DEACON.md role context","description":"Create ~/gt/DEACON.md with the Deacon's role context, wake cycle instructions, and command reference. Model after existing CLAUDE.md for Mayor.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:22.602567-08:00","updated_at":"2025-12-19T17:30:27.897108-08:00","closed_at":"2025-12-19T17:30:27.897108-08:00","dependencies":[{"issue_id":"gt-5af.1","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:22.605373-08:00","created_by":"daemon"}]}
{"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-19T17:49:09.254329-08:00","closed_at":"2025-12-19T17:49:09.254329-08:00"}
{"id":"gt-u1j.13","title":"Beads CLI wrapper: shell out to bd","description":"Wrapper for bd (beads CLI) commands.\n\n## Interface\n\n```go\ntype Beads struct {\n workDir string\n}\n\nfunc NewBeads(workDir string) *Beads\n\n// Query\nfunc (b *Beads) List(opts ListOptions) ([]*Issue, error)\nfunc (b *Beads) Ready() ([]*Issue, error)\nfunc (b *Beads) Show(id string) (*Issue, error)\nfunc (b *Beads) Blocked() ([]*Issue, error)\n\n// Mutations\nfunc (b *Beads) Create(opts CreateOptions) (*Issue, error)\nfunc (b *Beads) Update(id string, opts UpdateOptions) error\nfunc (b *Beads) Close(ids ...string) error\n\n// Sync\nfunc (b *Beads) Sync() error\nfunc (b *Beads) SyncStatus() (*SyncStatus, error)\n```\n\n## Data Types\n\n```go\ntype Issue struct {\n ID string\n Title string\n Status string\n Priority int\n Type string\n Description string\n Parent string\n Children []string\n DependsOn []string\n Blocks []string\n}\n\ntype ListOptions struct {\n Status string // \"open\", \"closed\", \"all\"\n Type string\n Priority int\n}\n\ntype CreateOptions struct {\n Title string\n Type string\n Priority int\n Description string\n Parent string\n}\n```\n\n## Implementation\n\nShell out to bd binary, parse JSON output where available.\n```go\nfunc (b *Beads) runBd(args ...string) ([]byte, error) {\n cmd := exec.Command(\"bd\", args...)\n cmd.Dir = b.workDir\n return cmd.Output()\n}\n```\n\n## Error Handling\n\n- bd not installed: Clear error with install instructions\n- Not a beads repo: Detect and report\n- Sync conflicts: Parse and report","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-15T17:12:55.926393-08:00","updated_at":"2025-12-17T14:33:08.059329-08:00","dependencies":[{"issue_id":"gt-u1j.13","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:55.926744-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.13","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.168049-08:00","created_by":"daemon"}]}
{"id":"gt-dt5","title":"Define Engineer as the Refinery agent role","description":"Clarify the distinction:\n\n- **Refinery** = place/module/directory/workspace\n - `\u003crig\u003e/refinery/` directory structure\n - `gt refinery start/stop/status` commands\n - tmux session name: `refinery` or `\u003crig\u003e-refinery`\n\n- **Engineer** = role/agent who works in the Refinery\n - CLAUDE.md prompting: \"You are an Engineer...\"\n - Documentation: \"The Engineer processes merge requests...\"\n - Mail address: `\u003crig\u003e/engineer` (or `\u003crig\u003e/refinery`?)\n\nUpdates needed:\n- Add Engineer role description to docs\n- Update CLAUDE.md templates for refinery agents\n- Keep `gt refinery` commands as-is (they manage the place)\n- Internal code stays `internal/refinery/` (the module)\n\nFuture consideration: Multiple Engineers in one Refinery for parallel merge processing.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:18.591842-08:00","updated_at":"2025-12-16T23:07:21.93783-08:00","dependencies":[{"issue_id":"gt-dt5","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.577196-08:00","created_by":"daemon"}]}
{"id":"gt-u41w","title":"Merge: gt-5af.1","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-5af.1\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:30:40.48203-08:00","updated_at":"2025-12-19T18:26:14.105767-08:00","closed_at":"2025-12-19T17:48:09.550789-08:00"}
{"id":"gt-b5sh","title":"test-after-fix","description":"test","status":"open","priority":2,"issue_type":"message","created_at":"2025-12-19T16:05:08.538763-08:00","updated_at":"2025-12-19T16:05:08.538763-08:00"}
{"id":"gt-dd8s","title":"gt molecule seed: create built-in molecules as beads","description":"The molecule infrastructure is complete but built-in molecules (engineer-in-box, quick-fix, research) need to be seeded into the beads database.\n\n## Current State\n- `gt molecule list` works but shows 0 molecules\n- BuiltinMolecules() in internal/beads/builtin_molecules.go has 3 molecules defined\n- No way to create them as beads\n\n## Needed\nAdd `gt molecule seed` command that:\n1. Reads BuiltinMolecules()\n2. Creates each as a bead with type: molecule\n3. Uses well-known IDs (mol-engineer-in-box, mol-quick-fix, mol-research)\n4. Idempotent (skip if already exists)\n\n## Acceptance Criteria\n```\ngt molecule seed\ngt molecule list # Shows 3 built-in molecules\n```\n\n## Parent\ngt-4nn: Molecules epic","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T14:13:27.432957-08:00","updated_at":"2025-12-19T15:27:45.507048-08:00","closed_at":"2025-12-19T14:44:40.092009-08:00"}
{"id":"gt-9a2.4","title":"Outpost CLI commands: gt outpost list/status/add","description":"## Overview\n\nCLI commands for managing outposts.\n\n## Commands\n\n```bash\n# List configured outposts\ngt outpost list\nNAME TYPE WORKERS STATUS\nlocal local 2/4 healthy\ngce-burst ssh 0/8 healthy\ncloudrun-burst cloudrun 0/20 healthy\n\n# Detailed status\ngt outpost status [name]\nOutpost: cloudrun-burst\nType: cloudrun\nProject: my-gcp-project\nRegion: us-central1\nService: gastown-worker\nActive Workers: 3/20\nCost (today): $0.42\nStatus: healthy\n\n# Add new outpost interactively\ngt outpost add\n? Outpost type: [local/ssh/cloudrun]\n\u003e cloudrun\n? Name: cloudrun-burst\n? GCP Project: my-gcp-project\n...\n\n# Add via flags\ngt outpost add cloudrun --name burst --project my-proj --region us-central1\n\n# Remove outpost\ngt outpost remove \u003cname\u003e\n\n# Test connectivity\ngt outpost ping \u003cname\u003e\n```\n\n## Files\n\n- `cmd/gt/outpost.go` - Cobra command group\n- `cmd/gt/outpost_list.go`\n- `cmd/gt/outpost_status.go`\n- `cmd/gt/outpost_add.go`\n\nDepends on: gt-9a2.3 (config/manager)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:12.317032-08:00","updated_at":"2025-12-16T18:02:12.317032-08:00","dependencies":[{"issue_id":"gt-9a2.4","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:03:45.55722-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.4","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:12.319322-08:00","created_by":"daemon"}]}
{"id":"gt-dck","title":"Update config location: .gastown/ → config/","description":"Move rig configuration from hidden .gastown/ to visible config/:\n- config/rig.json: Rig configuration\n- config/engineer.json: Engineer settings (test command, etc.)\n- config/witness.json: Witness settings (heartbeat interval, etc.)\n\nHidden directories are poorly discovered by AI agents.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:20.400818-08:00","updated_at":"2025-12-16T23:02:20.400818-08:00","dependencies":[{"issue_id":"gt-dck","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.69517-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:23.426567-08:00","updated_at":"2025-12-15T23:17:18.734281-08:00","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-8j8e","title":"gt mail send: --priority flag should work like bd mail send","description":"UX inconsistency: gt mail send passes flags that bd mail send doesn't support.\n\n## Root Cause\n\nrouter.go line 42 passes `--priority` to bd:\n```go\nargs = append(args, \"--priority\", fmt.Sprintf(\"%d\", beadsPriority))\n```\n\nBut `bd mail send` only has `--urgent` (boolean), not `--priority`.\n\n## Fix Options\n\n1. Add `--priority` flag to `bd mail send` (preferred - more expressive)\n2. Change router to only use `--urgent` when priority=0\n\n## Also Affected\n\n- `--type` flag (line 46) - bd mail send doesn't have this\n- `--thread-id` flag (line 51) - bd mail send doesn't have this \n- `--reply-to` flag (line 56) - bd mail send doesn't have this\n\nThe router assumes bd mail send has features it doesn't have.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:31:05.486487-08:00","updated_at":"2025-12-19T12:07:28.918346-08:00","closed_at":"2025-12-19T12:07:28.918346-08:00"}
{"id":"gt-h5n.6","title":"gt mq integration status: show integration branch status","description":"Implement 'gt mq integration status \u003cepic\u003e' command.\n\nDisplay:\n- Integration branch name and creation date\n- Commits ahead of main\n- MRs merged to integration (closed)\n- MRs pending (open, targeting integration)\n- Comparison: main..integration/\u003cepic\u003e\n\nOutput example:\n Integration: integration/gt-auth-epic\n Created: 2025-12-17\n Ahead of main: 5 commits\n \n Merged MRs (3):\n gt-mr-001 Fix login timeout\n gt-mr-002 Fix session expiry \n gt-mr-003 Update auth config\n \n Pending MRs (1):\n gt-mr-004 Update auth tests (in_progress)\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:39.554771-08:00","updated_at":"2025-12-19T12:56:15.210196-08:00","closed_at":"2025-12-19T11:59:37.295064-08:00","dependencies":[{"issue_id":"gt-h5n.6","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:39.556726-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.6","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.528122-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:07.764838-08:00","updated_at":"2025-12-15T23:17:18.465919-08:00","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-u1j.6","title":"Mail system: JSONL inbox, delivery, tmux injection","description":"Refactor mail system to wrap bd mail commands.\n\n## Status\n\nCurrent implementation uses JSONL files directly. Now that Beads mail is available (gt-r01 closed), refactor to use bd mail as the backend.\n\n## Implementation\n\nReplace internal/mail/* with thin wrappers around bd CLI:\n\n```go\n// Send wraps: bd mail send \u003cto\u003e -s \u003csubject\u003e -m \u003cbody\u003e\nfunc (r *Router) Send(msg *Message) error\n\n// List wraps: bd mail inbox --json\nfunc (m *Mailbox) List() ([]*Message, error)\n\n// Get wraps: bd mail read \u003cid\u003e --json\nfunc (m *Mailbox) Get(id string) (*Message, error)\n\n// MarkRead wraps: bd mail ack \u003cid\u003e\nfunc (m *Mailbox) MarkRead(id string) error\n```\n\n## Address Translation\n\nGGT addresses → Beads recipients:\n- `mayor/` → `mayor`\n- `\u003crig\u003e/refinery` → `\u003crig\u003e-refinery`\n- `\u003crig\u003e/\u003cpolecat\u003e` → `\u003crig\u003e-\u003cpolecat\u003e`\n\n## Tmux Notification\n\nKeep the tmux injection for --notify flag. After bd mail send, optionally inject notification into tmux session.\n\n## Migration\n\nNo migration needed - bd mail creates messages as beads issues with type=message. Old JSONL inboxes can be ignored or cleaned up.\n\n## Dependencies\n\n- gt-r01: CLOSED (Beads mail available)\n- gt-u1j.4: Tmux wrapper (for notifications)","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:16.226478-08:00","updated_at":"2025-12-16T21:45:20.397855-08:00","closed_at":"2025-12-16T21:45:20.397855-08:00","dependencies":[{"issue_id":"gt-u1j.6","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:16.226821-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.6","depends_on_id":"gt-u1j.4","type":"blocks","created_at":"2025-12-15T17:13:51.98774-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.6","depends_on_id":"gt-r01","type":"blocks","created_at":"2025-12-16T13:12:08.753309-08:00","created_by":"daemon"}]}
{"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-9a2.6","title":"CloudRun worker container: Dockerfile and entrypoint","description":"## Overview\n\nDocker container image for Cloud Run workers.\n\n## Dockerfile\n\n```dockerfile\nFROM golang:1.21-alpine AS builder\nWORKDIR /app\nCOPY . .\nRUN go build -o gt ./cmd/gt\n\nFROM ubuntu:22.04\n\n# Install Claude Code\nRUN apt-get update \u0026\u0026 apt-get install -y curl git nodejs npm \u0026\u0026 npm install -g @anthropic-ai/claude-code \u0026\u0026 apt-get clean\n\n# Install gt\nCOPY --from=builder /app/gt /usr/local/bin/gt\n\n# Worker entrypoint\nCOPY deploy/cloudrun/entrypoint.sh /entrypoint.sh\nRUN chmod +x /entrypoint.sh\n\nEXPOSE 8080\nENTRYPOINT [\"/entrypoint.sh\"]\n```\n\n## Entrypoint\n\n```bash\n#!/bin/bash\ngit config --global user.name \"$GIT_USER\"\ngit config --global user.email \"$GIT_EMAIL\"\nexec gt worker serve --port 8080\n```\n\n## Files\n\n- `deploy/cloudrun/Dockerfile`\n- `deploy/cloudrun/entrypoint.sh`\n- `deploy/cloudrun/README.md`\n\n## Dependencies\n\nDepends on: gt-9a2.11 (HTTP server - gt worker serve)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:37.583941-08:00","updated_at":"2025-12-16T18:15:22.781294-08:00","dependencies":[{"issue_id":"gt-9a2.6","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:37.585955-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.6","depends_on_id":"gt-9a2.11","type":"blocks","created_at":"2025-12-16T18:15:38.208009-08:00","created_by":"daemon"}]}
{"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-kp2","title":"Add merge-request type to Beads schema","description":"Define the merge-request bead type with fields:\n- branch: source branch (e.g., polecat/Nux/gt-xxx)\n- target_branch: destination (main or integration/xxx)\n- source_issue: the work being merged (gt-xxx)\n- worker: who did the work\n- rig: which rig\n- merge_commit: (filled on close) SHA of merge commit\n- close_reason: (filled on close) success/failure details\n\nThis may require beads schema changes or just convention.","status":"closed","issue_type":"task","created_at":"2025-12-16T23:02:14.471248-08:00","updated_at":"2025-12-19T12:56:15.213256-08:00","closed_at":"2025-12-18T20:09:04.684996-08:00","dependencies":[{"issue_id":"gt-kp2","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.338148-08:00","created_by":"daemon"}]}
{"id":"gt-5af.7","title":"Add crew session pattern to lifecycle handling","description":"Update identityToSession and restartSession to handle crew patterns: gastown/max -\u003e gt-gastown-max. Crew workers can request lifecycle but are not proactively monitored.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:57.662197-08:00","updated_at":"2025-12-19T17:22:52.554917-08:00","dependencies":[{"issue_id":"gt-5af.7","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:57.664036-08:00","created_by":"daemon"}]}
{"id":"gt-dq3","title":"Split PGT/GGT harness or migrate to GGT-only","description":"Current ~/ai harness is shared by PGT and GGT with confusing overlap. Options:\n1. Keep separate (document the coexistence)\n2. Migrate fully to GGT structure\n3. Create separate harnesses\n\nThis affects the beads redirect, Mayor home location, and rig structure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T17:15:32.308192-08:00","updated_at":"2025-12-19T12:56:15.207324-08:00","closed_at":"2025-12-19T12:08:48.653114-08:00","dependencies":[{"issue_id":"gt-dq3","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.717903-08:00","created_by":"daemon"}]}
{"id":"gt-6z2","title":"Test Epic: GGT MVP Validation","status":"closed","issue_type":"epic","created_at":"2025-12-16T21:57:37.355269-08:00","updated_at":"2025-12-16T22:06:41.124727-08:00","closed_at":"2025-12-16T22:06:41.124727-08:00"}
{"id":"gt-f9x.1","title":"Config package: Config, State types and JSON serialization","description":"Config and state types with JSON serialization.\n\n## Town Config (config/town.json)\n\n```go\ntype TownConfig struct {\n Type string `json:\"type\"` // \"town\"\n Version int `json:\"version\"` // schema version\n Name string `json:\"name\"` // town identifier\n CreatedAt time.Time `json:\"created_at\"`\n}\n```\n\n## Rigs Registry (config/rigs.json)\n\n```go\ntype RigsConfig struct {\n Version int `json:\"version\"`\n Rigs map[string]RigEntry `json:\"rigs\"`\n}\n\ntype RigEntry struct {\n GitURL string `json:\"git_url\"`\n AddedAt time.Time `json:\"added_at\"`\n BeadsConfig *BeadsConfig `json:\"beads,omitempty\"`\n}\n\ntype BeadsConfig struct {\n Repo string `json:\"repo\"` // \"local\" | path | git-url\n Prefix string `json:\"prefix\"` // issue prefix\n}\n```\n\n## Agent State (*/state.json)\n\n```go\ntype AgentState struct {\n Role string `json:\"role\"` // \"mayor\", \"witness\", etc.\n LastActive time.Time `json:\"last_active\"`\n Session string `json:\"session,omitempty\"`\n Extra map[string]any `json:\"extra,omitempty\"`\n}\n```\n\n## Interface\n\n```go\nfunc LoadTownConfig(path string) (*TownConfig, error)\nfunc SaveTownConfig(path string, config *TownConfig) error\n\nfunc LoadRigsConfig(path string) (*RigsConfig, error)\nfunc SaveRigsConfig(path string, config *RigsConfig) error\n\nfunc LoadAgentState(path string) (*AgentState, error)\nfunc SaveAgentState(path string, state *AgentState) error\n```\n\n## Validation\n\n- Version compatibility checks\n- Required field validation\n- Path existence verification","status":"closed","issue_type":"task","created_at":"2025-12-15T16:36:50.163851-08:00","updated_at":"2025-12-16T13:24:26.497685-08:00","closed_at":"2025-12-16T13:24:26.497685-08:00"}
{"id":"gt-iib","title":"Architecture: Decentralized rig structure with per-rig agents","description":"## Decision\n\nAdopt decentralized architecture where each rig contains all its agents (mayor/, witness/, refinery/, polecats/) rather than centralizing mayor clones at town level.\n\n## Town Level Structure\n\n```\n~/ai/ # Town root\n├── config/ # Town config (VISIBLE, not hidden)\n│ ├── town.json # {\"type\": \"town\"}\n│ ├── rigs.json # Registry of managed rigs\n│ └── federation.json # Wasteland config (future)\n│\n├── mayor/ # Mayor's HOME at town level\n│ ├── CLAUDE.md\n│ ├── mail/inbox.jsonl\n│ └── state.json\n│\n└── \u003crigs\u003e/ # Managed projects\n```\n\n## Rig Level Structure (e.g., wyvern)\n\n```\nwyvern/ # Rig = clone of project repo\n├── .git/info/exclude # Gas Town adds: polecats/ refinery/ witness/ mayor/\n├── .beads/ # Beads (if project uses it)\n├── [project files] # Clean project code on main\n│\n├── polecats/ # Worker clones\n│ └── \u003cname\u003e/ # Each is a git clone\n│\n├── refinery/\n│ ├── rig/ # Refinery's clone\n│ ├── state.json\n│ └── mail/inbox.jsonl\n│\n├── witness/ # NEW: Per-rig pit boss\n│ ├── rig/ # Witness's clone\n│ ├── state.json\n│ └── mail/inbox.jsonl\n│\n└── mayor/\n ├── rig/ # Mayor's clone for this rig\n └── state.json\n```\n\n## Key Decisions\n\n1. **Visible config dir**: `config/` not `.gastown/` (models don't find hidden dirs)\n2. **Witness per-rig**: Each rig has its own Witness (pit boss) with its own clone\n3. **Mayor decentralized**: Mayor's clones live IN each rig at `\u003crig\u003e/mayor/rig/`\n4. **Minimal invasiveness**: Only `.git/info/exclude` modified, no commits to project\n5. **Clone subdir name**: Keep `rig/` for consistency (refinery/rig/, witness/rig/, mayor/rig/)\n\n## Role Detection\n\n- Town root or mayor/ → Mayor (town level)\n- Rig root → Mayor (canonical main)\n- \u003crig\u003e/mayor/rig/ → Mayor (rig-specific)\n- \u003crig\u003e/refinery/rig/ → Refinery\n- \u003crig\u003e/witness/rig/ → Witness\n- \u003crig\u003e/polecats/\u003cname\u003e/ → Polecat\n\n## Migration from PGT\n\n- `mayor/rigs/\u003crig\u003e/` → `\u003crig\u003e/mayor/rig/`\n- `\u003crig\u003e/town/` → eliminated (rig root IS the clone)\n- Add `witness/` to each rig","status":"closed","issue_type":"task","created_at":"2025-12-15T19:21:19.913928-08:00","updated_at":"2025-12-15T19:21:40.461186-08:00","closed_at":"2025-12-15T19:21:40.461186-08:00","dependencies":[{"issue_id":"gt-iib","depends_on_id":"gt-u1j","type":"blocks","created_at":"2025-12-15T19:21:40.374551-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:51.440782-08:00","updated_at":"2025-12-17T13:52:51.440782-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-rixa","title":"Bug: parseLifecycleRequest always matches 'cycle' due to LIFECYCLE prefix","description":"In lifecycle.go, parseLifecycleRequest checks strings.Contains(title, \"cycle\") first, but the prefix \"LIFECYCLE:\" contains the word \"cycle\". This means ALL lifecycle messages match the cycle action, making restart and shutdown unreachable. Fix: check for restart/shutdown before cycle, or use word boundaries.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-19T16:17:16.083512-08:00","updated_at":"2025-12-19T16:17:24.480543-08:00"}
{"id":"gt-wpg","title":"Replaceable notifications via Claude Code queue","description":"Leverage Claude Code's ability to replace queued text for notifications that supersede previous ones.\n\n## Problem\n\nIf daemon sends 10 heartbeats while agent is busy, agent returns to see 10 stacked messages. Wasteful and noisy.\n\n## Solution\n\nUse Claude Code's queue replacement for:\n- Heartbeat messages (only latest matters)\n- Status updates that supersede previous\n- Progress notifications\n\n## Implementation\n\nNotifications get a 'slot' identifier. New notification in same slot replaces old one:\n- Slot: 'heartbeat' → only one heartbeat queued at a time\n- Slot: 'status-\u003crig\u003e' → latest status per rig\n- No slot → stacks normally (for unique messages)\n\n## Research Needed\n\n- How does Claude Code expose queue replacement?\n- tmux send-keys behavior with pending input\n- Alternative: clear + resend pattern","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:29.821949-08:00","updated_at":"2025-12-18T14:19:29.821949-08:00","dependencies":[{"issue_id":"gt-wpg","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.656972-08:00","created_by":"daemon"}]}
{"id":"gt-48bs","title":"gt rig reset: clear stale mail on reset/land","description":"## Problem\n\nWhen resetting or landing a rig/town, stale mail messages can confuse agents on startup. Old handoff messages, daemon notifications, and inter-agent mail should be cleaned up as part of reset.\n\n## Current State\n\n- `gt rig reset` exists but doesn't clear mail\n- Stale messages accumulate (e.g., daemon SHUTDOWN messages)\n- Agents may read outdated context on startup\n\n## Proposed Behavior\n\n`gt rig reset` and `gt town reset` should:\n1. Close all open messages (`--type=message`) in the relevant beads\n2. Optionally preserve pinned handoff beads (clear content, keep bead)\n3. Log what was cleaned up\n\n```bash\ngt rig reset gastown # Clears gastown mail\ngt rig reset gastown --mail # Only clear mail, keep other state\ngt town reset # Clears all town-level mail\ngt town reset --all # Clears mail in all rigs too\n```\n\n## Implementation\n\n1. Query `bd list --type=message --status=open`\n2. Close each with reason 'Cleared during reset'\n3. For pinned handoffs: `bd update \u003cid\u003e --description=''` instead of close","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T11:42:17.769674-08:00","updated_at":"2025-12-19T11:42:17.769674-08:00"}
{"id":"gt-njr","title":"Engineer session restart protocol","description":"Implement session restart flow for when the Engineer needs to split work:\n\n1. Engineer creates subtask(s) in Beads assigned to self\n2. Engineer sends handoff mail to self (🤝 HANDOFF)\n3. Engineer sends restart request to Witness\n4. Witness verifies:\n - Handoff mail exists in Engineer outbox/sent\n - Subtasks filed in Beads\n5. Witness restarts the Refinery session (new Engineer context)\n\nThis enables \"occasionally consistent, eventually convergent\" work patterns.\nThe Refinery continues; the Engineer gets fresh context.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T23:02:48.22994-08:00","updated_at":"2025-12-16T23:07:42.05363-08:00","dependencies":[{"issue_id":"gt-njr","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:56.148564-08:00","created_by":"daemon"}]}
{"id":"gt-98oo","title":"Merge: gt-y5o","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-y5o\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:29:03.837448-08:00","updated_at":"2025-12-19T18:26:14.102603-08:00","closed_at":"2025-12-19T17:47:03.619784-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:37:19.879102-08:00","updated_at":"2025-12-15T23:17:18.556669-08:00","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-u82","title":"Design: Mayor session cycling and handoff","description":"Design for Mayor session cycling and structured handoff.\n\n## Overview\n\nMayor coordinates across all rigs and runs for extended periods. Needs session cycling pattern with structured handoff notes.\n\n## Key Elements\n\n1. Session cycling recognition (when to cycle)\n2. Handoff note format (structured state capture)\n3. Handoff delivery (mail to self)\n4. Fresh session startup (reading and resuming)\n\n## Subtasks (implementation)\n\n- gt-g2d: Mayor session cycling prompting\n- gt-sye: Mayor startup protocol prompting\n- gt-vci: Mayor handoff mail template\n- gt-1le: town handoff command (optional, P2)\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T20:03:16.125725-08:00","updated_at":"2025-12-15T20:49:26.203276-08:00","closed_at":"2025-12-15T20:16:10.772149-08:00"}
{"id":"gt-kmn.7","title":"CLI: gt swarm commands (create, status, list, land)","description":"CLI commands for swarm management.\n\n## Commands\n\n### gt swarm create\nCreate a new swarm in a rig.\n\n```\ngt swarm create \u003crig\u003e --title \"Fix all P1 bugs\" \\\n --task gt-abc --task gt-def \\\n --worker Toast --worker Nux\n```\n\nOptions:\n- --title: Swarm title (required)\n- --task: Beads issue IDs to include (repeatable)\n- --worker: Polecat names (repeatable, or --workers=3 to auto-assign)\n- --start: Start swarm immediately after creation\n\n### gt swarm status \u003cswarm-id\u003e\nShow swarm status and progress.\n\nOutput:\n- Swarm metadata (title, created, workers)\n- Task status (pending/in_progress/completed/merged)\n- Integration branch status\n- Overall progress percentage\n\n### gt swarm list [rig]\nList swarms, optionally filtered by rig or status.\n\n```\ngt swarm list --status=active\ngt swarm list gastown --status=landed\n```\n\n### gt swarm land \u003cswarm-id\u003e\nTrigger manual landing (normally automatic).\n\n### gt swarm cancel \u003cswarm-id\u003e\nCancel a swarm in progress.\n\n## Output Format\n\nSupport --json for machine-readable output.\n\n## Dependencies\n\nNeeds: gt-kmn.1 (types), gt-kmn.2 (manager)","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:50.57674-08:00","updated_at":"2025-12-16T14:11:46.038524-08:00","closed_at":"2025-12-16T14:11:46.038524-08:00","dependencies":[{"issue_id":"gt-kmn.7","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:50.577096-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.7","depends_on_id":"gt-kmn.2","type":"blocks","created_at":"2025-12-16T00:11:29.0905-08:00","created_by":"daemon"}]}
{"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-19T17:48:09.608699-08:00","closed_at":"2025-12-19T17:48:09.608699-08:00"}
{"id":"gt-slo","title":"Fix TestHasPolecat test failure","status":"closed","issue_type":"bug","created_at":"2025-12-17T17:30:19.474356-08:00","updated_at":"2025-12-18T12:38:32.124804-08:00","closed_at":"2025-12-17T21:12:07.625984-08:00"}
{"id":"gt-5gkd","title":"Refinery Engineer: Role prompting and CLAUDE.md","description":"Create refinery/CLAUDE.md with Chief Merge Engineer role context. Include:\n- Role identity and responsibilities\n- Decision authority (merge order, test frequency, binary rebuilds)\n- Communication patterns (Witness, Deacon)\n- Session lifecycle (handoff bead protocol)\n- Key commands reference","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:06.423153-08:00","updated_at":"2025-12-19T18:09:06.423153-08:00","dependencies":[{"issue_id":"gt-5gkd","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.217523-08:00","created_by":"daemon"}]}
{"id":"gt-cik.2","title":"gt crew add: Create crew workspace","description":"Implement 'gt crew add \u003cname\u003e [--rig \u003crig\u003e]' command:\n- Clone repo into \u003crig\u003e/crew/\u003cname\u003e/\n- Create feature branch (optional, or stay on main)\n- Register for mail delivery\n- Initialize CLAUDE.md with crew worker prompting\n- Do NOT register with witness (user-managed)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:02.208618-08:00","updated_at":"2025-12-16T20:47:23.004728-08:00","closed_at":"2025-12-16T20:46:19.873949-08:00","dependencies":[{"issue_id":"gt-cik.2","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:02.210603-08:00","created_by":"daemon"}]}
{"id":"gt-8h4","title":"Pinned Beads: Ongoing concerns and anchors","description":"Pinned beads represent persistent concerns that do not close traditionally. Stay out of bd ready. Examples: Monitor production, Weekly syncs. Implementation: pinned: true field on bead.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:08:11.314086-08:00","updated_at":"2025-12-18T18:08:11.314086-08:00"}
{"id":"gt-qivm","title":"gt crew at: auto-prime when exec'ing Claude in-session","description":"When running 'gt crew at \u003cname\u003e' from inside the target session, we exec Claude directly. But this means we can't send 'gt prime' afterward since we ARE the process.\n\nPossible solutions:\n1. Claude startup hook that runs gt prime\n2. Pass prompt as argument to claude CLI\n3. Wrapper script approach\n\nRelated: crew resume prompt also can't be sent in this path.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T15:13:38.035775-08:00","updated_at":"2025-12-19T15:13:38.035775-08:00"}
{"id":"gt-5af.8","title":"Add human escalation configuration","description":"Add overseer contact config to mayor/town.json. Deacon uses this for escalation when it cannot resolve issues. Support email and/or other notification methods.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T17:14:02.770713-08:00","updated_at":"2025-12-19T17:22:52.549362-08:00","dependencies":[{"issue_id":"gt-5af.8","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:14:02.772612-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.3","title":"MR state transitions: validate open→in_progress→closed","description":"Enforce valid state transitions for merge-requests:\n\nValid transitions:\n- open → in_progress (Engineer claims MR)\n- in_progress → closed (merge success or rejection)\n- in_progress → open (failure, reassign to worker)\n- open → closed (manual rejection)\n\nInvalid:\n- closed → anything (immutable once closed)\n\nImplement validation in MR update operations.\n\nReference: docs/merge-queue-design.md#state-machine","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:00.417825-08:00","updated_at":"2025-12-19T12:56:15.209219-08:00","closed_at":"2025-12-18T20:00:58.572216-08:00","dependencies":[{"issue_id":"gt-h5n.3","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:50:00.419924-08:00","created_by":"daemon"}]}
{"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 gt-u82.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T20:15:31.954724-08:00","updated_at":"2025-12-15T23:17:23.967562-08:00","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-0asj","title":"Merge: gt-5af.5","description":"branch: polecat/Scabrous\ntarget: main\nsource_issue: gt-5af.5\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:50:25.227909-08:00","updated_at":"2025-12-19T18:00:37.365009-08:00","closed_at":"2025-12-19T18:00:37.365009-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-9a2.7","title":"CloudRun protocol types: WorkRequest, WorkEvent, WorkResult","description":"## Overview\n\nHTTP protocol types for Cloud Run work dispatch. **Types only** - server and client are separate tasks.\n\n## Request Type\n\n```go\ntype WorkRequest struct {\n IssueID string `json:\"issue_id\"`\n Rig RigConfig `json:\"rig\"`\n Beads BeadsConfig `json:\"beads\"`\n Branch string `json:\"worker_branch\"`\n Context map[string]any `json:\"context,omitempty\"`\n}\n\ntype RigConfig struct {\n URL string `json:\"url\"`\n Branch string `json:\"branch\"`\n}\n\ntype BeadsConfig struct {\n URL string `json:\"url\"`\n Branch string `json:\"branch\"`\n}\n```\n\n## Response Types (streaming NDJSON)\n\n```go\ntype WorkEvent struct {\n Type string `json:\"type\"` // status, log, progress, result, error\n Status string `json:\"status,omitempty\"`\n Line string `json:\"line,omitempty\"`\n Percent int `json:\"percent,omitempty\"`\n Branch string `json:\"branch,omitempty\"`\n PRURL string `json:\"pr_url,omitempty\"`\n Code string `json:\"code,omitempty\"`\n Message string `json:\"message,omitempty\"`\n}\n\ntype WorkResult struct {\n Status string `json:\"status\"` // done, failed\n Branch string `json:\"branch\"`\n PRURL string `json:\"pr_url,omitempty\"`\n Error string `json:\"error,omitempty\"`\n}\n```\n\n## Files\n\n- `internal/cloudrun/protocol.go` - All types above\n\n## Notes\n\nThis is just types. Server (gt-9a2.7b) and client (gt-9a2.7c) are separate tasks.\nSmall, focused task - can complete quickly.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:51.480019-08:00","updated_at":"2025-12-16T18:14:49.196218-08:00","dependencies":[{"issue_id":"gt-9a2.7","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:51.48197-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.7","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.984572-08:00","created_by":"daemon"}]}
{"id":"gt-shnp","title":"Create Refinery role template","description":"Add Refinery template to internal/templates/roles/:\n- refinery.md.tmpl with full role context\n- Variables: rig name, working directory, handoff bead ID\n- Update SeedRoleTemplates to include it\n- gt prime uses this template for Refinery context","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:28.951284-08:00","updated_at":"2025-12-19T18:09:28.951284-08:00","dependencies":[{"issue_id":"gt-shnp","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.706849-08:00","created_by":"daemon"}]}
{"id":"gt-95x","title":"Remove stale migration docs from gastown-py","description":"The gastown-py repo has migration-related documentation that is now misinformation since we have made design decisions. Remove or clearly mark as obsolete: any docs about migration paths, old architecture assumptions, or superseded designs.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:08.642373-08:00","updated_at":"2025-12-15T21:04:39.516436-08:00","closed_at":"2025-12-15T21:04:39.516436-08:00"}
{"id":"gt-7hz3","title":"Merge: gt-92l","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-92l\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:31:37.716367-08:00","updated_at":"2025-12-19T18:26:14.102101-08:00","closed_at":"2025-12-19T17:48:09.627376-08:00"}
{"id":"gt-vdp0","title":"Crew workers getting wrong CLAUDE.md (shows Refinery)","description":"## Problem\n\nCrew workers (emma, dave) have CLAUDE.md that says they're the Refinery.\n\n## Evidence\n\n```\n$ head -5 /Users/stevey/gt/beads/crew/emma/CLAUDE.md\n# Claude: Beads Refinery\nYou are the **Refinery** for the **beads** rig...\n```\n\n## Expected\n\nShould use crew.md.tmpl which correctly says:\n```\n# Crew Worker Context\nYou are a **crew worker** - the overseer's (human's) personal workspace...\n```\n\n## Impact\n\n- Crew workers have wrong identity in static context\n- `gt prime` correctly outputs crew context, but CLAUDE.md conflicts\n- Confusing role information\n\n## Fix\n\nCheck `gt crew create` or whatever populates CLAUDE.md for crew workers.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:40:56.518032-08:00","updated_at":"2025-12-19T01:33:49.863259-08:00","closed_at":"2025-12-19T01:33:49.863259-08:00","dependencies":[{"issue_id":"gt-vdp0","depends_on_id":"gt-l4gm","type":"blocks","created_at":"2025-12-18T21:50:04.955247-08:00","created_by":"daemon"}]}
{"id":"gt-rm3","title":"CLI: gt refinery commands (start, stop, status, queue)","description":"CLI commands for managing the Refinery agent.\n\n## Commands\n\n```bash\ngt refinery start \u003crig\u003e # Start refinery for a rig\ngt refinery stop \u003crig\u003e # Stop refinery\ngt refinery status \u003crig\u003e # Show refinery status\ngt refinery queue \u003crig\u003e # Show merge queue\n```\n\n## gt refinery start\n\nStarts the Refinery daemon for the specified rig.\n\nOptions:\n- --foreground: Run in foreground (default: background)\n- --auto-merge: Enable auto-merge (default: from config)\n\n## gt refinery stop\n\nStops a running Refinery. Gracefully finishes current MR if processing.\n\n## gt refinery status\n\nShows:\n- Running state (running/stopped)\n- Current MR being processed (if any)\n- Queue length\n- Last merge time\n- Recent activity\n\n## gt refinery queue\n\nShows the merge queue:\n```\nMerge queue for 'wyvern':\n 1. [pending] Toast/polecat-auth-fix (15m ago)\n 2. [pending] Capable/polecat-new-feature (5m ago)\n \n1 merged today, 0 rejected\n```\n\n## Implementation\n\nUses gt-ov2 (Refinery agent) for daemon functionality.","status":"closed","issue_type":"task","created_at":"2025-12-15T23:22:24.754361-08:00","updated_at":"2025-12-16T14:16:34.593637-08:00","closed_at":"2025-12-16T14:16:34.593637-08:00","dependencies":[{"issue_id":"gt-rm3","depends_on_id":"gt-ov2","type":"blocks","created_at":"2025-12-15T23:22:30.679909-08:00","created_by":"daemon"}]}
{"id":"gt-qn4l","title":"bd create should support molecule type","description":"gt molecule commands expect type=molecule but bd validates against bug|feature|task|epic|chore|merge-request only","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T18:25:31.591953-08:00","updated_at":"2025-12-19T18:41:15.654491-08:00","closed_at":"2025-12-19T18:41:15.654491-08:00"}
{"id":"gt-99m","title":"gt daemon: Background service management","description":"## Summary\n\nONE daemon for all Gas Town - a simple Go process (not a Claude agent) that:\n1. Pokes agents periodically (heartbeat)\n2. Processes lifecycle requests\n3. Restarts sessions when agents request cycling\n\n## Architecture\n\nDaemon (gt daemon)\n- Pokes Mayor: \"HEARTBEAT: check your rigs\"\n- Pokes each Witness: \"HEARTBEAT: check your workers\"\n- Has inbox at daemon/ for lifecycle requests\n- Restarts sessions on cycle requests\n\n## NOT the daemon's job:\n- Making decisions (Witnesses do that)\n- Running Claude (it's a Go process)\n- Processing work (polecats do that)\n- Direct polecat management (Witnesses do that)\n\nThe daemon is a **dumb scheduler** - poke things, execute lifecycle requests. All intelligence is in agents.\n\n## Commands\n\n- gt daemon start: Start daemon (background)\n- gt daemon stop: Stop daemon\n- gt daemon status: Show daemon status\n- gt daemon logs: View daemon logs\n\n## Daemon Loop\n\nEvery heartbeat interval:\n1. Poke Mayor\n2. For each rig: Poke Witness\n3. Process lifecycle requests from daemon/ inbox\n4. Check for dead sessions, restart if cycle requested\n\n## Lifecycle Request Handling\n\nDaemon checks its inbox (daemon/) for lifecycle requests:\n- From Mayor: cycle/restart Mayor session\n- From Witnesses: cycle/restart Witness session\n\nOn request:\n1. Verify agent state shows requesting_cycle\n2. Kill session\n3. Start new session\n4. Clear requesting_cycle flag\n\n## Poke Protocol\n\nPoke = tmux inject \"HEARTBEAT: do your job\"\n- Agent ignores if already working\n- Agent wakes up if idle\n- Idempotent - multiple pokes are fine\n\n## Lifecycle Hierarchy\n\n- Daemon manages: Mayor, all Witnesses\n- Witness manages: Polecats, Refinery (per rig)\n- Crew: self-managed (human workspace)\n\n## Related Issues\n\n- gt-kmn.11: Daemon heartbeat details\n- gt-gby: gt handoff command (unified lifecycle)\n- gt-u1j.9: Fold witness daemon into this","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:50:09.763719-08:00","updated_at":"2025-12-19T12:56:15.205355-08:00","closed_at":"2025-12-19T12:05:27.33958-08:00","dependencies":[{"issue_id":"gt-99m","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.253877-08:00","created_by":"daemon"}]}
{"id":"gt-w775","title":"MR: gt-svi.1 (polecat/Furiosa)","description":"branch: polecat/Furiosa\ntarget: main\nsource_issue: gt-svi.1","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-18T20:21:40.921429-08:00","updated_at":"2025-12-18T20:21:54.163532-08:00","closed_at":"2025-12-18T20:21:54.163532-08:00"}
{"id":"gt-kmn","title":"Batch Work System: Integration branch, merge queue, landing","description":"## Overview\n\nThis epic tracks batch work coordination in GGT. Key insight: **work is a stream, not discrete swarms**.\n\nThere are no \"swarm IDs\" - the epic IS the grouping, the merge queue IS the coordination. \"Swarming an epic\" is colloquial for spawning multiple workers on its children.\n\n## Architecture\n\n- **Epics** group related work\n- **Issues** are individual tasks \n- **Dependencies** encode ordering (multi-wave emerges automatically)\n- **Merge queue** coordinates completed work\n- **Workers** process issues independently\n\nSee Key Decision #11 in docs/architecture.md: \"Work is a Stream (No Swarm IDs)\"\n\n## What This Epic Covers\n\n1. Integration branch management for batch merges\n2. Refinery semantic merge processing\n3. Witness landing protocol (cleanup)\n4. Report generation (epic-based, not swarm-ID-based)\n5. Git safety auditing\n6. Work reconciliation\n\n## What Was Removed\n\n- Swarm IDs (sw-1, sw-2, etc.)\n- Per-swarm directories (.gastown/swarms/\u003cid\u003e/)\n- Swarm manifest/state/events files\n- swarm-started/swarm-landed beads\n\nThese were redundant - beads already provides hierarchy, status, dependencies, and history.\n\n## References\n\n- Architecture: docs/architecture.md (Key Decision #11, Multi-Wave Work Processing)\n- PGT: swarm/manager.py, swarm/landing.py (behavioral reference, but ignore swarm ID patterns)","status":"open","issue_type":"epic","created_at":"2025-12-16T00:08:15.339127-08:00","updated_at":"2025-12-16T17:25:33.208338-08:00"}
{"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":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:06.543281-08:00","updated_at":"2025-12-15T21:18:54.012863-08:00","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-a95","title":"Refinery background daemon mode","description":"Refinery currently only works in foreground mode. Background daemon is stubbed.\n\n## Current State\nmanager.go line 128-129:\n```go\n// Background mode: spawn a new process\n// For MVP, we just mark as running - actual daemon implementation in gt-ov2\nreturn nil\n```\n\n## Requirements\n\n### 1. Background Process Spawning\n```go\nfunc (m *Manager) Start(foreground bool) error {\n if !foreground {\n // Spawn gt refinery start --foreground as subprocess\n cmd := exec.Command(os.Args[0], \"refinery\", \"start\", m.rig.Name, \"--foreground\")\n cmd.Start() // Don't wait\n // Record PID\n }\n}\n```\n\n### 2. PID File Management\n- Write PID to .gastown/refinery.pid\n- Check PID validity on status\n- Clean up stale PID files\n\n### 3. Log Output\n- Redirect stdout/stderr to .gastown/refinery.log\n- Log rotation (optional for MVP)\n\n### 4. Graceful Shutdown\n- Handle SIGTERM/SIGINT\n- Complete current merge before exit\n- Update state to stopped\n\n### 5. Health Check\n- Process existence check via kill -0\n- Optional: heartbeat file with timestamp\n\n## Files to Modify\n- internal/refinery/manager.go: Start(), Status(), process spawning\n\n## Acceptance Criteria\n- [ ] gt refinery start \u003crig\u003e spawns background process\n- [ ] gt refinery status shows running with PID\n- [ ] gt refinery stop sends SIGTERM and waits\n- [ ] Logs written to .gastown/refinery.log\n- [ ] Survives terminal close","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:53.366619-08:00","updated_at":"2025-12-19T15:27:45.508176-08:00","closed_at":"2025-12-19T14:47:40.165105-08:00"}
{"id":"gt-5af.4","title":"Simplify Go daemon to Deacon-watcher","description":"Refactor internal/daemon to only: (1) check deacon/heartbeat.json every 60s, (2) poke gt-deacon if stale, (3) restart Deacon and mail for help if very stale. Remove all lifecycle processing and agent poking.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:40.493425-08:00","updated_at":"2025-12-19T17:22:52.556187-08:00","dependencies":[{"issue_id":"gt-5af.4","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:40.495569-08:00","created_by":"daemon"},{"issue_id":"gt-5af.4","depends_on_id":"gt-5af.6","type":"blocks","created_at":"2025-12-19T17:15:11.010382-08:00","created_by":"daemon"},{"issue_id":"gt-5af.4","depends_on_id":"gt-5af.2","type":"blocks","created_at":"2025-12-19T17:15:11.158303-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.4","title":"Refinery semantic merge processing loop","description":"Implement the Refinery semantic merge loop for processing polecat work.\n\n## Overview\n\nThe Refinery is a fully empowered Claude Code agent that:\n1. Fetches polecat branches\n2. Merges to integration branch\n3. Resolves conflicts semantically (re-implements if needed)\n4. Runs tests\n5. Escalates only when truly stuck\n\n## Processing Loop\n\n1. Check queue for completed tasks (polecat done, not yet merged)\n2. For each task:\n - Fetch polecat branch\n - Attempt merge to integration/\u003cswarm-id\u003e\n - On conflict: semantic resolution (understand intent, re-implement)\n - Run tests if configured\n - On success: mark merged, file bead, notify witness\n - On failure: notify polecat (test fail) or escalate (stuck)\n3. When all tasks merged: land integration to main\n\n## Semantic Merge\n\nWhen git merge fails, Refinery:\n1. Reads polecat changes and beads issue\n2. Understands intent\n3. Re-implements on current integration branch\n4. Only escalates if truly blocked\n\n## Daemon Poking\n\nRefinery is poked by:\n- Daemon heartbeat (periodic)\n- Witness notification (polecat done)\n- Mayor request (check queue)\n\n## Dependencies\n\nNeeds: gt-u1j.6 (mail), gt-u1j.3 (git), gt-u1j.14 (merge queue)\n\n## Reference\n\nSee PGT ephemeral.py for branch operations.","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:19.536429-08:00","updated_at":"2025-12-16T14:24:17.527982-08:00","closed_at":"2025-12-16T14:24:17.527982-08:00","dependencies":[{"issue_id":"gt-kmn.4","depends_on_id":"gt-kmn.3","type":"blocks","created_at":"2025-12-16T00:11:22.86454-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T00:11:22.952967-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:23.046741-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.4","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:19.536808-08:00","created_by":"daemon"}]}
{"id":"gt-cik","title":"Overseer Crew: User-managed persistent workspaces","description":"## Overview\n\nCrew workers are the overseer's (human's) personal workspaces within a rig. Unlike polecats which are witness-managed and ephemeral, crew workers are:\n\n- **Persistent**: Not auto-garbage-collected\n- **User-managed**: Overseer controls lifecycle\n- **Long-lived identities**: dave, emma, fred - recognizable names\n- **Gas Town integrated**: Mail, handoff mechanics work\n- **Tmux optional**: Can work in terminal directly\n\n## Directory Structure\n\n```\n\u003crig\u003e/\n polecats/ # Managed workers (witness controls)\n refinery/ # Merge queue processor\n witness/ # Pit boss\n crew/ # Overseer's personal workspaces\n dave/ # Full clone, persistent\n emma/ # Full clone, persistent\n fred/ # Full clone, persistent\n```\n\n## Key Differences from Polecats\n\n- Location: crew/ instead of polecats/\n- Lifecycle: User-managed, not witness-managed\n- Auto-cleanup: Never (polecats auto-cleanup on swarm land)\n- Issue assignment: Optional (polecats require it)\n- Tmux: Optional (polecats require it)\n- Mail \u0026 Handoff: Yes for both\n- Identity: Persistent (polecats are ephemeral)\n\n## CLI Commands\n\n- gt crew add \u003cname\u003e [--rig \u003crig\u003e] - Create crew workspace\n- gt crew list [--rig \u003crig\u003e] - List crew workspaces\n- gt crew at \u003crig\u003e/\u003cname\u003e - Attach to workspace (start session)\n- gt crew attach \u003cname\u003e - Attach (infer rig from cwd)\n- gt crew refresh \u003cname\u003e - Handoff + restart (context cycling)\n- gt crew remove \u003cname\u003e [--force] - Remove workspace\n- gt crew status [\u003cname\u003e] - Show workspace status\n\n## Design Notes\n\n- Crew workers use full git clones (not worktrees)\n- Optional beads integration via BEADS_DIR\n- Mail-to-self handoff works for context cycling\n- No witness monitoring or nudging\n- No automatic issue assignment required\n\n## Background\n\nUsers often maintain separate repo clones for serial agent work. This is tedious to set up manually. Crew workspaces bring these into Gas Town's infrastructure while keeping user control.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-16T16:47:37.529887-08:00","updated_at":"2025-12-16T20:59:46.13518-08:00","closed_at":"2025-12-16T20:59:46.13518-08:00"}
{"id":"gt-9a2.14","title":"CloudRun cost tracking: Usage monitoring and limits","description":"## Overview\n\nTrack Cloud Run usage costs and enforce spending limits.\n\n## Cost Model\n\nCloud Run pricing (approximate):\n- CPU: ~$0.000024/vCPU-second\n- Memory: ~$0.0000025/GiB-second\n- Requests: ~$0.40/million\n\nFor 5-minute worker (2 vCPU, 4GB):\n- CPU: 300 × 2 × $0.000024 = $0.0144\n- Memory: 300 × 4 × $0.0000025 = $0.003\n- **Total: ~$0.017 per session**\n\n## Implementation\n\n```go\ntype CostTracker struct {\n cpuRate float64 // per vCPU-second\n memRate float64 // per GiB-second\n sessions []SessionCost\n mu sync.RWMutex\n}\n\ntype SessionCost struct {\n WorkerID string\n StartTime time.Time\n EndTime time.Time\n CPUs float64\n MemoryGiB float64\n}\n\nfunc (t *CostTracker) RecordSession(workerID string, start, end time.Time, cpus, mem float64) {\n t.mu.Lock()\n defer t.mu.Unlock()\n t.sessions = append(t.sessions, SessionCost{...})\n}\n\nfunc (t *CostTracker) CurrentCost() float64 {\n t.mu.RLock()\n defer t.mu.RUnlock()\n var total float64\n for _, s := range t.sessions {\n duration := s.EndTime.Sub(s.StartTime).Seconds()\n total += duration * s.CPUs * t.cpuRate\n total += duration * s.MemoryGiB * t.memRate\n }\n return total\n}\n```\n\n## Cost Cap Enforcement\n\n```go\nfunc (o *CloudRunOutpost) Spawn(...) (Worker, error) {\n if o.costCap \u003e 0 \u0026\u0026 o.costTracker.CurrentCost() \u003e= o.costCap {\n return nil, ErrCostCapExceeded\n }\n // ... spawn worker\n}\n```\n\n## Config\n\n```yaml\noutposts:\n - name: cloudrun-burst\n type: cloudrun\n cost_cap_hourly: 5.00 # Stop spawning if hourly cost exceeds $5\n cost_cap_daily: 50.00 # Daily limit\n```\n\n## CLI\n\n```bash\ngt outpost status cloudrun-burst\n# Shows: Cost (today): $0.42 / $50.00 cap\n```\n\n## Files\n\n- `internal/cloudrun/cost.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (basic CloudRunOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:16:14.37154-08:00","updated_at":"2025-12-16T18:16:14.37154-08:00","dependencies":[{"issue_id":"gt-9a2.14","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:31.692724-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.14","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:14.373486-08:00","created_by":"daemon"}]}
{"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-caz","title":"Timed Beads: Scheduled recurring work","description":"## Summary\n\nTimed beads wake up periodically and get injected into the ready queue by the daemon.\n\n## Schema Extension\n\n```yaml\nid: gt-weekly-sync\ntype: task # or sentinel\nschedule: \"0 9 * * 1\" # cron: Monday 9am\n# OR\ninterval: 24h # every 24 hours\ntier: haiku # cheap model for routine checks\nnext_run: 2025-12-20T09:00:00Z\n```\n\n## Daemon Integration\n\nDaemon heartbeat loop:\n1. Check timed beads where `next_run \u003c= now`\n2. For each due bead:\n - Inject into ready queue (set status to open if needed)\n - Update `next_run` based on schedule/interval\n3. Witnesses pick up work via `bd ready`\n\n## Use Cases\n\n- Weekly team sync reminders\n- Daily health checks\n- Periodic cleanup tasks\n- Scheduled reports\n\n## Interaction with Pinned Beads\n\nA pinned bead can be timed - it wakes up periodically but never closes.\nThis is how you model \"background services\" in Gas Town.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:07:39.665294-08:00","updated_at":"2025-12-18T18:07:39.665294-08:00"}
{"id":"gt-h5n.5","title":"gt mq integration land: merge integration branch to main","description":"Implement 'gt mq integration land \u003cepic\u003e' command.\n\nActions:\n1. Verify all MRs targeting integration/\u003cepic\u003e are merged\n2. Verify integration branch exists\n3. Merge integration/\u003cepic\u003e to main (--no-ff)\n4. Run tests on main\n5. Push to origin\n6. Delete integration branch\n7. Update epic status\n\nOptions:\n- --force: land even if some MRs still open\n- --skip-tests: skip test run\n- --dry-run: preview only\n\nThis creates a single merge commit for the entire epic's work.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:37.465635-08:00","updated_at":"2025-12-19T15:27:45.509365-08:00","closed_at":"2025-12-19T14:49:21.051904-08:00","dependencies":[{"issue_id":"gt-h5n.5","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:37.467603-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.5","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.40717-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:28.300658-08:00","updated_at":"2025-12-17T13:52:28.300658-08:00","dependencies":[{"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"},{"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"}]}
{"id":"gt-g44u.4","title":"Step recovery: timeout and release","description":"Implement recovery mechanism for stuck molecule steps.\n\n## Problem\nWhen a worker dies mid-step, the step stays in_progress forever.\nNeed timeout/release mechanism for nondeterministic idempotence.\n\n## Solution\n1. Track step start time (claimed_at timestamp)\n2. Timeout: After 30 min in_progress, step returns to pending\n3. Manual release: bd release \u003cstep-id\u003e\n\n## Implementation Options\n\n### Option A: Beads-level timeout\n- Add claimed_at field to issues\n- bd ready excludes items in_progress \u003c 30 min\n- bd ready includes items in_progress \u003e 30 min (auto-recovery)\n\n### Option B: Daemon-level timeout \n- Daemon watches in_progress items\n- Moves back to pending after timeout\n\n### Option C: Manual only (MVP)\n- bd release \u003cid\u003e manually moves in_progress → pending\n- Document recovery procedure\n- Witness can automate for polecats\n\n## Recommendation\nStart with Option C (manual) for Christmas. Add Option A later.\n\n## Acceptance\n- [ ] bd release command works\n- [ ] Stuck steps can be recovered\n- [ ] Documented recovery procedure","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T15:50:15.072833-08:00","updated_at":"2025-12-19T16:16:32.325856-08:00","closed_at":"2025-12-19T16:16:32.325856-08:00","dependencies":[{"issue_id":"gt-g44u.4","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:15.07451-08:00","created_by":"daemon"}]}
{"id":"gt-l6r9","title":"Test molecule","description":"Test","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T14:29:43.985973-08:00","updated_at":"2025-12-19T14:30:00.084138-08:00","closed_at":"2025-12-19T14:30:00.084138-08:00"}
{"id":"gt-sr8","title":"Test merge request","description":"branch: polecat/Test/gt-test\ntarget: main\nsource_issue: gt-test\nworker: TestWorker\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-18T20:08:22.678439-08:00","updated_at":"2025-12-18T20:08:36.133169-08:00","closed_at":"2025-12-18T20:08:36.133169-08:00"}
{"id":"gt-ic0j","title":"🤝 HANDOFF: Timing fixes applied","description":"Fixed mayor attach timing bug. Completed: timing fix, gt-tulx, Emma beads-6v2. Remaining P1: gt-17zr, gt-kcee, gt-szsq. Run gt prime on startup.","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-18T22:19:57.731032-08:00","updated_at":"2025-12-18T23:28:33.950423-08:00","closed_at":"2025-12-18T23:28:33.950423-08:00"}
{"id":"gt-cu7r","title":"Implement handoffs using pinned beads","description":"Replace the current mail-based handoff system with pinned beads.\n\n## Current Problem\n\nHandoff messages get closed before the successor can read them because:\n1. `gt mail read` auto-acks (closes) messages\n2. `bd mail inbox` only shows open messages\n3. Successor sees empty inbox\n\n## Solution\n\nUse pinned beads for handoffs:\n- One pinned bead per role: `mayor-handoff`, `\u003crig\u003e-refinery-handoff`, etc.\n- Predecessor updates the content before cycling\n- Successor reads on startup via `gt prime`\n- Never closes - always available\n\n## Implementation\n\n### 1. Create handoff beads on first cycle\n- `bd create --title='Mayor Handoff' --type=task --status=pinned --assignee=mayor`\n- Store ID in role config or use well-known naming convention\n\n### 2. Update gt handoff command\n- Instead of `bd mail send`, update the pinned handoff bead\n- `bd update \u003chandoff-id\u003e --description='...handoff content...'`\n\n### 3. Update gt prime\n- Read the role's handoff bead\n- Display content to successor\n\n### 4. Compression/reset\n- `gt rig reset` clears handoff content\n- Or manual: `bd update \u003chandoff-id\u003e --description=''`\n\n## Dependencies\n\nRequires beads-6v2 (StatusPinned) to be implemented first.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T21:28:05.738035-08:00","updated_at":"2025-12-19T01:57:17.034513-08:00","closed_at":"2025-12-19T01:57:17.034513-08:00"}
{"id":"gt-kmn.5","title":"Swarm beads naming convention and auto-filing","description":"Beads naming convention for swarm lifecycle events.\n\n## Bead IDs\n\n- swarm-started:\u003cswarm-id\u003e # Filed when swarm begins\n- swarm-task-merged:\u003cswarm-id\u003e:\u003ctask-id\u003e # Filed per task merge\n- swarm-landed:\u003cswarm-id\u003e # Filed when merged to main\n- swarm-failed:\u003cswarm-id\u003e # Filed on unrecoverable failure\n\n## swarm-started Bead\n\nFiled by: Mayor/Refinery at swarm creation\nContains:\n- Swarm title and description\n- List of tasks (issue IDs)\n- List of workers (polecat names)\n- Base commit SHA\n\n## swarm-task-merged Bead\n\nFiled by: Refinery after each successful merge\nContains:\n- Task issue ID and title\n- Polecat name\n- Merge commit SHA\n- Test results summary\n\n## swarm-landed Bead\n\nFiled by: Refinery after landing to main\nContains:\n- Final merge commit SHA\n- Stats: tasks completed, time taken\n- List of all merged task beads\n- Integration branch name (now deleted)\n\n## swarm-failed Bead\n\nFiled by: Refinery on unrecoverable failure\nContains:\n- Failure reason\n- Tasks merged vs not merged\n- Recovery guidance\n\n## Why Beads (not just mail)\n\n- Persistent, queryable, synced to git\n- Other agents can check status without mail\n- Creates audit trail\n- Works when agents offline","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:46.930708-08:00","updated_at":"2025-12-16T17:23:21.089822-08:00","closed_at":"2025-12-16T17:23:21.089822-08:00","dependencies":[{"issue_id":"gt-kmn.5","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:46.931086-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.5","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:24.746439-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.5","depends_on_id":"gt-u1j.13","type":"blocks","created_at":"2025-12-16T00:11:24.81726-08:00","created_by":"daemon"}]}
{"id":"gt-5af","title":"Deacon: Hierarchical health-check orchestrator","description":"Replace daemon heartbeats with Deacon - an AI agent that keeps Gas Town running.\n\n## Core Concept\n\nThe Deacon is a **Claude agent** (not just a Go process) that:\n- Lives at town root in gt-deacon session\n- Has its own mailbox (deacon/ identity in town beads)\n- Is poked by a minimal Go daemon every ~60s (if idle)\n- Monitors Mayor and Witnesses proactively\n- Handles lifecycle requests (restart/cycle) from Mayor, Witnesses, AND Crew\n\n## Architecture\n\n```\nMinimal Go Daemon (just watches Deacon)\n |\n v\n Deacon (Claude agent)\n |\n +----+----+\n v v\n Mayor Witnesses --\u003e Polecats (Witness-managed)\n | |\n +----+----+\n |\n Crew (lifecycle only, not monitored)\n```\n\n## Deacon Responsibilities\n\n**Proactive monitoring:**\n- Mayor health (tmux session, keepalive freshness)\n- Witness health (tmux sessions, keepalive freshness)\n\n**Reactive lifecycle:**\n- Process restart/cycle requests from Mayor, Witnesses, Crew\n- Kill session, create new, prime, verify startup\n\n**Escalation:**\n- Mail human (configurable) if issues can't be resolved\n\n## Key Files\n\n- ~/gt/DEACON.md - Role context\n- ~/gt/deacon/ - State directory\n - heartbeat.json - Written each wake cycle (daemon checks this)\n - state.json - Health tracking, last scan results\n- ~/gt/.beads/ - Town beads with deacon/ mail identity\n\n## Wake Cycle\n\n1. Write heartbeat (prevents daemon from poking)\n2. Check mail (lifecycle requests)\n3. Quick health scan (Mayor, Witnesses)\n4. Process lifecycle requests\n5. Remediate unhealthy agents\n6. Update state\n\n## Session Patterns\n\n- Deacon: gt-deacon\n- Mayor: gt-mayor\n- Witness: gt-\u003crig\u003e-witness\n- Crew: gt-\u003crig\u003e-\u003cname\u003e (e.g., gt-gastown-max)\n\n## Relation to Policy Beads\n\nFuture: Deacon behavior configurable via policy beads (gt-3zw).\nInitial implementation uses sensible defaults.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-12-18T18:32:28.083305-08:00","updated_at":"2025-12-19T17:22:52.553992-08:00","dependencies":[{"issue_id":"gt-5af","depends_on_id":"gt-3zw","type":"blocks","created_at":"2025-12-18T18:32:36.617594-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.3","title":"Outpost configuration: YAML config and OutpostManager","description":"## Overview\n\nConfiguration file for outposts and manager to load/track them.\n\n## Config File\n\n`~/ai/config/outposts.yaml`:\n\n```yaml\noutposts:\n - name: local\n type: local\n max_workers: 4\n\n - name: gce-burst\n type: ssh\n host: 10.0.0.5\n user: steve\n ssh_key: ~/.ssh/gce_worker\n town_path: /home/steve/ai\n max_workers: 8\n\n - name: cloudrun-burst\n type: cloudrun\n project: my-gcp-project\n region: us-central1\n service: gastown-worker\n max_workers: 20\n cost_cap_hourly: 5.00\n\npolicy:\n default_preference: [local, gce-burst, cloudrun-burst]\n overrides:\n - condition: \"priority \u003e= P3\"\n prefer: cloudrun-burst\n```\n\n## OutpostManager\n\n```go\ntype OutpostManager struct {\n outposts map[string]Outpost\n policy AssignmentPolicy\n}\n\nfunc NewOutpostManager(configPath string) (*OutpostManager, error)\nfunc (m *OutpostManager) Get(name string) (Outpost, bool)\nfunc (m *OutpostManager) List() []Outpost\nfunc (m *OutpostManager) SelectOutpost(issue Issue) Outpost\n```\n\n## Files\n\n- `internal/outpost/manager.go`\n- `internal/outpost/config.go` (extend)\n- `internal/outpost/policy.go`\n\nDepends on: gt-9a2.1 (interfaces)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:01.595784-08:00","updated_at":"2025-12-16T18:02:01.595784-08:00","dependencies":[{"issue_id":"gt-9a2.3","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:01.598029-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.3","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.448178-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.10","title":"Batch work landing report generation","description":"Generate reports on batch work completion.\n\n## Trigger\n\nWhen all children of an epic are closed, generate a completion report.\n\n## Report Contents\n\n- Epic metadata (ID, title, created by, duration)\n- Task summary (completed counts, timing)\n- Per-task details (issue, assignee, time taken)\n- Git stats (commits merged, lines changed)\n- Cleanup stats (branches deleted)\n\n## Output Locations\n\n1. Mail to Mayor - summary report\n2. Optional: save to file with --save flag\n\n## Command\n\n```bash\ngt report --epic \u003cepic-id\u003e [--save report.md]\n```\n\n## Format\n\nMarkdown with sections:\n- Summary\n- Tasks\n- Workers\n- Timeline\n\n## Note\n\nThis replaces the swarm-based reporting (gt-662). Reports are generated from epic/issue data, not from separate swarm state files.\n\n## Reference\n\nPGT: swarm/report.py (for format ideas, ignore swarm ID patterns)","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:23.242931-08:00","updated_at":"2025-12-16T17:26:27.99208-08:00","dependencies":[{"issue_id":"gt-kmn.10","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:23.243287-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.5","title":"SSHOutpost: Full Gas Town clone on remote VM","description":"## Overview\n\nImplement SSHOutpost for running workers on remote VMs via SSH.\n\n## Model\n\nRemote VM has a full Gas Town clone. SSHOutpost:\n- Connects via SSH\n- Spawns tmux sessions on remote\n- Uses remote git clone for code/beads\n- Syncs via git push/pull\n\n## Implementation\n\n```go\ntype SSHOutpost struct {\n name string\n host string\n user string\n keyPath string\n townPath string // e.g., /home/steve/ai\n maxWorkers int\n conn *ssh.Client\n}\n\nfunc NewSSHOutpost(config OutpostConfig) (*SSHOutpost, error)\n\nfunc (o *SSHOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n // SSH: create tmux session on remote\n // SSH: start claude in session\n // Return SSHWorker\n}\n\nfunc (o *SSHOutpost) Ping() error {\n // Test SSH connectivity\n}\n```\n\n## SSHWorker\n\n```go\ntype SSHWorker struct {\n outpost *SSHOutpost\n id string\n session string\n issue string\n}\n\nfunc (w *SSHWorker) Attach() error {\n // SSH + tmux attach (opens terminal)\n}\n\nfunc (w *SSHWorker) Logs() (io.Reader, error) {\n // SSH: tmux capture-pane\n}\n```\n\n## Prerequisites on Remote VM\n\n1. Gas Town clone at townPath\n2. Claude Code installed\n3. Git credentials configured\n4. SSH key access\n\n## Integration with gt-f9x.7-8\n\nThis builds on the Connection interface from gt-f9x.7/8. SSHOutpost uses SSHConnection internally for remote operations.\n\nDepends on: gt-9a2.1 (interfaces), gt-f9x.7 (Connection interface)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:02:24.507039-08:00","updated_at":"2025-12-16T18:02:24.507039-08:00","dependencies":[{"issue_id":"gt-9a2.5","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.665254-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.5","depends_on_id":"gt-f9x.7","type":"blocks","created_at":"2025-12-16T18:03:45.770134-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.5","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:02:24.508937-08:00","created_by":"daemon"}]}
{"id":"gt-zx3","title":"Per-rig beads repo configuration","description":"Add per-rig beads configuration to rig config schema.\n\n## Config Schema\n\nIn each rig's config.json:\n\n```json\n{\n \"version\": 1,\n \"name\": \"wyvern\",\n \"git_url\": \"https://github.com/steveyegge/wyvern\",\n \"beads\": {\n \"repo\": \"local\", // \"local\" | \"\u003cpath\u003e\" | \"\u003cgit-url\u003e\"\n \"root\": null, // Override bd --root (optional)\n \"prefix\": \"wyv\" // Issue prefix for this rig\n }\n}\n```\n\n## Repo Options\n\n| Value | Meaning | Use Case |\n|-------|---------|----------|\n| `\"local\"` | Use project's `.beads/` | Own projects, full commit access |\n| `\"\u003cpath\u003e\"` | Use beads at path | OSS contributions |\n| `\"\u003cgit-url\u003e\"` | Clone and use repo | Team shared beads |\n\n## Environment Injection\n\nWhen spawning polecats, Gas Town sets:\n```bash\nexport BEADS_ROOT=\"\u003cresolved-path\u003e\"\n```\n\n## Resolution Logic\n\n```go\nfunc ResolveBeadsRoot(rigConfig *RigConfig, rigPath string) (string, error) {\n beads := rigConfig.Beads\n switch {\n case beads.Root != \"\":\n return beads.Root, nil\n case beads.Repo == \"local\" || beads.Repo == \"\":\n return filepath.Join(rigPath, \".beads\"), nil\n case strings.HasPrefix(beads.Repo, \"/\"):\n return beads.Repo, nil\n case strings.Contains(beads.Repo, \"://\"):\n return cloneAndResolve(beads.Repo)\n default:\n return filepath.Join(rigPath, beads.Repo), nil\n }\n}\n```\n\n## Backwards Compatibility\n\nIf `beads` section missing, assume `\"repo\": \"local\"`.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:16.660049-08:00","updated_at":"2025-12-15T20:48:02.122203-08:00","dependencies":[{"issue_id":"gt-zx3","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.726502-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.1","title":"MR field parsing: extract structured fields from description","description":"Parse merge-request beads to extract structured fields:\n- branch: source branch name\n- target: target branch (main or integration/xxx)\n- source_issue: the work item being merged\n- worker: who did the work\n- rig: which rig\n- merge_commit: (set on close)\n- close_reason: (set on close)\n\nFields stored in description as YAML block or key: value lines.\nProvide helper functions: ParseMRFields(issue) and SetMRFields(issue, fields).\n\nReference: docs/merge-queue-design.md#merge-request-schema","status":"closed","issue_type":"task","created_at":"2025-12-17T13:47:46.682379-08:00","updated_at":"2025-12-18T19:00:03.189669-08:00","closed_at":"2025-12-18T11:46:18.970805-08:00","dependencies":[{"issue_id":"gt-h5n.1","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:47:46.682911-08:00","created_by":"daemon"}]}
{"id":"gt-hcc0","title":"gt polecat remove --all: bulk polecat teardown","description":"Currently gt polecat remove only accepts one polecat at a time. Need bulk operations:\n\n## Requested\n- `gt polecat remove gastown --all` - remove all polecats from a rig\n- `gt polecat remove gastown/A gastown/B ...` - remove multiple by name\n\n## Context\nAfter a swarm completes, tearing down 20 polecats one at a time is tedious.\nEphemeral workers should be easy to create and destroy in bulk.\n\n## Related\n- gt-c92: CLI: all command for batch polecat operations","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-19T14:06:43.892225-08:00","updated_at":"2025-12-19T14:06:43.892225-08:00"}
{"id":"gt-gby","title":"gt handoff: Unified agent lifecycle command","description":"## Summary\n\nUnified `gt handoff` command for ALL agent types to request lifecycle actions.\n\n## Usage\n\ngt handoff # Context-aware default\ngt handoff --shutdown # Terminate, cleanup, don't restart\ngt handoff --cycle # Restart with handoff mail\ngt handoff --restart # Fresh restart, no handoff\n\n## Context-Aware Defaults\n\n| Agent Type | Default | Reason |\n|------------|---------|--------|\n| Polecat | --shutdown | Ephemeral, work is done |\n| Witness | --cycle | Long-running, context full |\n| Refinery | --cycle | Long-running, context full |\n| Mayor | --cycle | Long-running, context full |\n| Crew | (sends mail only) | Human-managed |\n\n## What gt handoff Does\n\n1. **Verify safe to stop**\n - Git state clean (no uncommitted changes)\n - Work handed off (PR exists for polecats)\n\n2. **Send handoff mail to self** (for cycle/restart)\n - Captures current state\n - New session will read this\n\n3. **Send lifecycle request to manager**\n - Polecats/Refinery → Witness\n - Witness/Mayor → Daemon\n - Format: mail to \u003cmanager\u003e with action type\n\n4. **Set state: requesting_\u003caction\u003e**\n - Lifecycle manager checks this before acting\n\n5. **Wait for termination**\n - Don't self-exit - let manager kill session\n - Ensures clean handoff\n\n## Lifecycle Request Flow\n\nAgent Lifecycle Manager\n | |\n | 1. gt handoff --cycle |\n | a. Verify git clean |\n | b. Send handoff mail to self |\n | c. Set requesting_cycle=true |\n | d. Send lifecycle request |\n |------------------------------------→|\n | |\n | 2. Receive request\n | 3. Verify state |\n | 4. Kill session |\n | 5. Start new |\n | (for cycle) |\n | |\n | New session reads handoff |\n | Resumes work |\n\n## Who Manages Whom\n\n| Agent | Sends lifecycle request to |\n|-------|---------------------------|\n| Polecat | \u003crig\u003e/witness |\n| Refinery | \u003crig\u003e/witness |\n| Witness | daemon/ |\n| Mayor | daemon/ |\n\n## Implementation\n\n1. Detect current role (polecat, witness, refinery, mayor, crew)\n2. Apply context-aware default if no flag specified\n3. Run pre-flight checks (git clean, work handed off)\n4. Send handoff mail to self (if cycling)\n5. Send lifecycle request to appropriate manager\n6. Set requesting_\u003caction\u003e in state.json\n7. Wait (manager will kill us)\n\n## For Polecats (--shutdown)\n\nAdditional cleanup after kill:\n- Witness removes worktree\n- Witness deletes polecat branch\n- Polecat ceases to exist\n\n## Related Issues\n\n- gt-99m: Daemon (handles Mayor/Witness lifecycle)\n- gt-7ik: Ephemeral polecats (polecat cleanup)\n- gt-eu9: Witness session cycling","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-18T11:39:40.806863-08:00","updated_at":"2025-12-18T18:18:22.35369-08:00","dependencies":[{"issue_id":"gt-gby","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T11:50:24.142182-08:00","created_by":"daemon"},{"issue_id":"gt-gby","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-18T11:39:46.423945-08:00","created_by":"daemon"},{"issue_id":"gt-gby","depends_on_id":"gt-eu9","type":"blocks","created_at":"2025-12-18T11:39:46.547204-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-5af.6","title":"Add Deacon heartbeat mechanism","description":"Deacon writes deacon/heartbeat.json on each wake. Go daemon reads it to decide whether to poke. Add heartbeat read/write helpers.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:52.057582-08:00","updated_at":"2025-12-19T17:26:36.573141-08:00","closed_at":"2025-12-19T17:26:36.573141-08:00","dependencies":[{"issue_id":"gt-5af.6","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:52.059708-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.4","title":"Doctor framework: Check interface, Result types, Report","description":"Framework for gt doctor health checks.\n\n## Check Interface\n\n```go\ntype Check interface {\n Name() string\n Description() string\n Run(ctx *CheckContext) *CheckResult\n Fix(ctx *CheckContext) error // optional auto-fix\n CanFix() bool\n}\n\ntype CheckContext struct {\n TownRoot string\n RigName string // empty for town-level checks\n Verbose bool\n}\n\ntype CheckResult struct {\n Status CheckStatus\n Message string\n Details []string // additional info\n FixHint string // suggestion if not auto-fixable\n}\n\ntype CheckStatus int\nconst (\n StatusOK CheckStatus = iota\n StatusWarning\n StatusError\n)\n```\n\n## Report\n\n```go\ntype Report struct {\n Timestamp time.Time\n Checks []CheckResult\n Summary ReportSummary\n}\n\ntype ReportSummary struct {\n Total int\n OK int\n Warnings int\n Errors int\n}\n\nfunc (r *Report) Print(w io.Writer, verbose bool)\n```\n\n## Doctor Runner\n\n```go\ntype Doctor struct {\n checks []Check\n}\n\nfunc NewDoctor() *Doctor\nfunc (d *Doctor) Register(check Check)\nfunc (d *Doctor) Run(ctx *CheckContext) *Report\nfunc (d *Doctor) Fix(ctx *CheckContext) *Report // run with auto-fix\n```\n\n## Built-in Checks\n\nTown-level (gt-f9x.5):\n- ConfigExists, ConfigValid\n- StateExists, StateValid\n- MayorMailboxExists\n- RigsRegistryValid\n\nRig-level (gt-f9x.6):\n- RigCloneExists\n- GitExcludeConfigured\n- WitnessExists, RefineryExists\n- PolecatClonesValid","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:03.81542-08:00","updated_at":"2025-12-17T16:14:33.83426-08:00","closed_at":"2025-12-17T15:48:19.92644-08:00","dependencies":[{"issue_id":"gt-f9x.4","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:37:03.815763-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.2","title":"Workspace detection: Find() walking up directory tree","description":"Find workspace root by walking up directory tree looking for Gas Town markers.\n\n## Detection Logic\n\nWalk up from current directory, looking for:\n1. `config/town.json` - Primary marker (visible config dir per gt-iib)\n2. `mayor/` directory at town level - Secondary marker\n\nStop at filesystem root if neither found.\n\n## Interface\n\n```go\n// Find locates the town root from the given directory\nfunc Find(startDir string) (string, error)\n\n// FindOrError is like Find but returns a user-friendly error\nfunc FindOrError(startDir string) (string, error)\n```\n\n## Return Values\n\n- Success: Absolute path to town root\n- Not found: Empty string + specific error\n- Error: Empty string + wrapped error\n\n## Edge Cases\n\n- Symlinks: Follow them (use filepath.EvalSymlinks)\n- Permissions: Return error if can't read directory\n- Nested towns: Return nearest ancestor (shouldn't happen in practice\nEOF\n)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:36:51.419316-08:00","updated_at":"2025-12-16T13:30:25.699054-08:00","closed_at":"2025-12-16T13:30:25.699054-08:00","dependencies":[{"issue_id":"gt-f9x.2","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:36:51.419635-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.2","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T16:37:32.426416-08:00","created_by":"daemon"}]}
{"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-b1g","title":"MVP Cutover: GGT replaces PGT for batch work","description":"When this is closed, stop using town and start using gt.\n\n## Acceptance Criteria\n\n1. gt spawn assigns issue to polecat and starts session\n2. gt spawn --epic spawns workers for all epic children\n3. gt session manages tmux lifecycle \n4. gt send / gt inbox work for mail\n5. Refinery processes merge queue with semantic merges\n6. Integration branches created and landed correctly\n7. gt stop --all halts all sessions\n8. One successful test batch completed end-to-end\n\n## What Must Work\n\n- Spawn polecat with issue assignment\n- Spawn workers for epic children\n- Session start/stop/attach\n- Mail send/inbox/read\n- Refinery merge loop (semantic)\n- Integration branch → main landing\n- Witness cleanup protocol\n- Emergency stop\n\n## What Can Be Deferred\n\n- Doctor checks (use PGT)\n- TUI dashboard\n- Plugin system\n- Federation\n- Ephemeral rigs\n- Detailed landing reports\n\n## Test Plan\n\n1. Create epic with 2 tasks, spawn 2 workers\n2. Verify polecats get assigned and sessions start\n3. Simulate task completion\n4. Verify Refinery merges to integration\n5. Verify landing to main\n6. Verify cleanup\n\n## Validation\n\nRun one real batch implementing GGT issues using GGT.\n\n## Note\n\nNo \"swarm IDs\" - just spawn workers for epic, let merge queue coordinate.","status":"open","issue_type":"epic","created_at":"2025-12-16T00:11:09.148751-08:00","updated_at":"2025-12-16T17:26:58.140535-08:00","dependencies":[{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.12","type":"blocks","created_at":"2025-12-16T21:36:35.053559-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.7","type":"blocks","created_at":"2025-12-16T00:11:36.431641-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.19","type":"blocks","created_at":"2025-12-16T00:11:36.196292-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T21:36:32.942855-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.6","type":"blocks","created_at":"2025-12-16T00:11:36.351097-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-ov2","type":"blocks","created_at":"2025-12-16T00:11:51.609649-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-rm3","type":"blocks","created_at":"2025-12-16T00:11:51.69062-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-u1j.22","type":"blocks","created_at":"2025-12-16T00:11:36.511124-08:00","created_by":"daemon"},{"issue_id":"gt-b1g","depends_on_id":"gt-kmn.4","type":"blocks","created_at":"2025-12-16T00:11:36.273483-08:00","created_by":"daemon"}]}
{"id":"gt-5af.5","title":"Update lifecycle mail targets to deacon/","description":"Update Mayor, Witness, and Crew handoff code to send lifecycle requests to deacon/ instead of daemon/. Update internal/cmd/handoff.go and related code.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:47.632827-08:00","updated_at":"2025-12-19T17:26:23.607176-08:00","closed_at":"2025-12-19T17:26:23.607176-08:00","dependencies":[{"issue_id":"gt-5af.5","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:47.63482-08:00","created_by":"daemon"}]}
{"id":"gt-cnt","title":"Swarm cleanup: delete merged polecat branches and reset state","description":"After a swarm completes and branches are merged, leftover state remains:\n\n## Current Problem\n\n1. **Remote branches not deleted** - polecat/* branches stay on origin after merge\n2. **Polecat clones not reset** - still on old branch with completed work\n3. **No cleanup command** - manual cleanup required\n\n## Observed After Swarm\n\nRemote branches still present:\n- origin/polecat/Morsov\n- origin/polecat/Nux \n- origin/polecat/Rictus\n- origin/polecat/Slit\n- origin/polecat/Toast\n\n## Proposed Solution\n\nAdd cleanup commands:\n\n1. gt swarm cleanup \u003cswarm-id\u003e - Clean up after swarm completion\n - Delete remote polecat branches that were merged\n - Reset polecat clones to main\n - Clear issue assignments\n \n2. gt polecat reset \u003crig\u003e/\u003cpolecat\u003e - Reset single polecat\n - git checkout main \u0026\u0026 git pull\n - Delete local polecat branch\n - Clear current issue assignment\n\n3. Auto-cleanup option on gt session stop --cleanup\n\n## Manual Cleanup For Now\n\ngit push origin --delete polecat/Nux polecat/Toast ...\ncd polecats/Nux \u0026\u0026 git checkout main \u0026\u0026 git pull","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T15:09:08.739193-08:00","updated_at":"2025-12-18T12:38:32.124192-08:00","closed_at":"2025-12-18T11:38:56.305923-08:00"}
{"id":"gt-kmn.3","title":"Integration branch management for swarms","description":"Manage integration branches for swarm merging strategy.\n\n## Branch Naming\n\n- Integration branch: `integration/\u003cswarm-id\u003e` (e.g., integration/sw-1)\n- Worker branches: `\u003cswarm-id\u003e/\u003cpolecat\u003e` (e.g., sw-1/Toast)\n\n## Operations\n\n```go\n// Create integration branch at swarm start\nfunc (m *SwarmManager) CreateIntegrationBranch(swarmID string) error\n// - Creates from BaseCommit\n// - Pushes to origin\n\n// Merge worker branch to integration\nfunc (r *Refinery) MergeToIntegration(swarmID, workerBranch string) error\n// - Fetches worker branch\n// - Merges to integration/\u003cswarm-id\u003e\n// - Handles conflicts (semantic merge)\n\n// Land integration to main\nfunc (r *Refinery) LandToMain(swarmID string) error\n// - Merges integration/\u003cswarm-id\u003e to main\n// - Pushes to origin\n// - Triggers cleanup\n\n// Cleanup branches after landing\nfunc (m *SwarmManager) CleanupBranches(swarmID string) error\n// - Deletes integration/\u003cswarm-id\u003e (local + remote)\n// - Deletes all \u003cswarm-id\u003e/\u003cpolecat\u003e branches\n```\n\n## All Workers Same Base\n\nWhen swarm starts:\n1. Record current main HEAD as BaseCommit\n2. All polecats branch from BaseCommit\n3. Integration branch also starts at BaseCommit\n\nThis ensures clean merges within the swarm.\n\n## Reference\n\nPGT: ephemeral.py (create_integration_branch, merge_integration_to_main)","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:06.825718-08:00","updated_at":"2025-12-16T14:01:52.85894-08:00","closed_at":"2025-12-16T14:01:52.85894-08:00","dependencies":[{"issue_id":"gt-kmn.3","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:20.848983-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.3","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:20.943465-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.3","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:06.82608-08:00","created_by":"daemon"}]}
{"id":"gt-7ik","title":"Ephemeral polecats: spawn fresh, delete on completion","description":"## Design Decision\n\nSwitch from pooled/idle polecats to ephemeral model:\n- Spawn creates fresh worktree from main\n- Polecat requests shutdown when done (bottom-up)\n- Witness verifies handoff, kills session, deletes worktree\n- No 'idle' state - polecats exist only while working\n\n## Rationale\n\n1. **Git worktrees are fast** - pooling optimization is obsolete\n2. **Pooling creates maintenance burden:**\n - Git stashes accumulate\n - Untracked artifacts pile up\n - Branches drift from main\n - Beads DB gets stale\n3. **PGT sync problems** came from persistent branches\n4. **Support infrastructure exists** - Witness, Refinery, Mayor handle continuity\n5. **Simpler mental model** - polecat exists = work in progress\n\n## Lifecycle\n\n```\nSpawn:\n gt spawn --issue \u003cid\u003e\n → Creates fresh worktree: git worktree add polecats/\u003cname\u003e -b polecat/\u003cname\u003e\n → Initializes beads in worktree\n → Starts session, assigns work\n\nWorking:\n Polecat does task\n → Pushes to polecat/\u003cname\u003e branch\n → Submits to merge queue when ready\n\nCompletion (POLECAT-INITIATED):\n Polecat runs: gt handoff\n → Verifies git state clean\n → Sends mail to Witness: \"Ready for shutdown\"\n → Marks itself done, waits for termination\n\nCleanup (WITNESS-OWNED):\n Witness receives shutdown request\n → Verifies PR merged or in queue\n → Verifies no uncommitted changes\n → Kills session: gt session stop \u003crig\u003e/\u003cpolecat\u003e\n → Deletes worktree: git worktree remove polecats/\u003cname\u003e\n → Deletes branch: git branch -d polecat/\u003cname\u003e\n → Optionally: Notifies Mayor of completion\n```\n\n## Key Insight: Bottom-Up Shutdown\n\n**Old model (wrong)**: Top-down batch shutdown - \"cancel the swarm\"\n**New model (right)**: Bottom-up individual shutdown - polecat requests, Witness executes\n\nThis enables streaming:\n- Workers come and go continuously\n- No \"swarm end\" to trigger cleanup\n- Each worker manages its own lifecycle\n- Witness is the lifecycle authority\n\n## Implementation\n\n1. Add `gt handoff` command for polecats to request shutdown\n2. Modify gt spawn to always create fresh worktree\n3. Run bd init in new worktree (beads needs initialization)\n4. Add shutdown request handler to Witness\n5. Witness verifies handoff, then cleans up:\n - Kill session\n - Remove worktree\n - Delete branch\n6. Remove 'idle' state from polecat state machine\n7. Simplify gt polecat list (only shows active)\n\n## Impact on Other Tasks\n\n- gt-17r (Zombie cleanup): Becomes trivial - orphan worktrees\n- gt-4my (Worker health): Simpler - no idle/stuck ambiguity\n- gt-f9x.5/f9x.6 (Doctor): Fewer states to validate\n- gt-eu9 (Witness handoff): Witness receives polecat shutdown requests","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-17T15:44:31.139964-08:00","updated_at":"2025-12-19T12:56:15.203738-08:00","closed_at":"2025-12-19T01:57:17.033547-08:00"}
{"id":"gt-5af.2","title":"Add gt deacon start/stop/status commands","description":"Add CLI commands: gt deacon start (spawn gt-deacon session), gt deacon stop (kill session), gt deacon status (show health state). Similar to gt mayor commands.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:26.617077-08:00","updated_at":"2025-12-19T17:25:12.114616-08:00","closed_at":"2025-12-19T17:25:12.114616-08:00","dependencies":[{"issue_id":"gt-5af.2","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:26.618912-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.11","title":"Daemon heartbeat: worker and queue monitoring","description":"Daemon periodic checks for work progress.\n\n## Heartbeat Actions\n\nEvery N seconds (configurable):\n\n1. Check Witness health per rig\n - Poke if witness needs to nudge workers\n \n2. Check Refinery queue per rig\n - Poke if pending work in queue\n \n3. Check work completion\n - If epic children all closed, notify Mayor\n\n## Eventually Convergent\n\nMultiple signals reinforce state:\n- Polecat signals done → Witness notices → pokes Refinery\n- Daemon heartbeat → checks queue → pokes Refinery\n- Beads status → queryable by any agent\n\nEven if one signal missed, system converges.\n\n## Interface\n\n```go\nfunc (d *Daemon) HeartbeatLoop() {\n for {\n for _, rig := range d.rigs {\n d.CheckWitness(rig)\n d.CheckRefinery(rig)\n d.CheckWorkProgress(rig)\n }\n time.Sleep(d.config.HeartbeatInterval)\n }\n}\n```\n\n## Notifications\n\nUse mail with low priority for heartbeat pokes.\nAgents can ignore if already processing.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:25.169417-08:00","updated_at":"2025-12-16T17:24:46.380497-08:00","dependencies":[{"issue_id":"gt-kmn.11","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T11:50:17.699125-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.11","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:25.169767-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.19","title":"CLI: spawn command","description":"High-level command to spawn a polecat with work assignment.\n\n## Command\n\n```\ngt spawn \u003crig\u003e/\u003cpolecat\u003e --issue \u003cid\u003e\ngt spawn \u003crig\u003e --issue \u003cid\u003e # auto-select available polecat\ngt spawn \u003crig\u003e/\u003cpolecat\u003e -m \"Work on X\" # free-form task\n```\n\n## What It Does\n\n1. Select or create polecat\n2. Ensure polecat is in idle/active state\n3. Assign the issue (update beads, set polecat state)\n4. Start session (gt session start)\n5. Inject initial context\n\n## Options\n\n- `--issue \u003cid\u003e`: Beads issue to assign\n- `-m \"message\"`: Free-form work description\n- `--create`: Create polecat if it does not exist\n- `--no-start`: Assign work but do not start session\n\n## Auto-Select Logic\n\nIf polecat not specified:\n1. Look for idle polecats in rig\n2. Prefer ones that worked on similar issues before\n3. If none available, fail (or create if --create)\n\n## Initial Context\n\nInjects into session:\n```\n[SPAWN] You have been assigned: \u003cissue-title\u003e\nIssue: \u003cid\u003e\nPriority: \u003cpriority\u003e\n\n\u003cdescription\u003e\n\nWork on this issue. Signal DONE when complete.\n```\n\n## Implementation\n\nOrchestrates PolecatManager + SessionManager + Beads:\n```go\nfunc Spawn(rig, polecat, issue string, opts SpawnOptions) error\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:13:16.676891-08:00","updated_at":"2025-12-16T14:13:52.489435-08:00","closed_at":"2025-12-16T14:13:52.489435-08:00","dependencies":[{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:16.677248-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:09.726436-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.19","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T17:14:09.821801-08:00","created_by":"daemon"}]}
{"id":"gt-cik.3","title":"gt crew list: List crew workspaces","description":"Implement 'gt crew list [--rig \u003crig\u003e]' command:\n- List all crew workers in rig(s)\n- Show status (session running, last activity)\n- Show current branch and git status summary\n- Support --json output","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:03.53109-08:00","updated_at":"2025-12-16T20:59:33.356024-08:00","closed_at":"2025-12-16T20:53:16.668788-08:00","dependencies":[{"issue_id":"gt-cik.3","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:03.532953-08:00","created_by":"daemon"}]}
{"id":"gt-ct0u","title":"Merge: gt-3x1.4","description":"branch: polecat/Nux\ntarget: main\nsource_issue: gt-3x1.4\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:53.140259-08:00","updated_at":"2025-12-19T18:26:14.104002-08:00","closed_at":"2025-12-19T17:49:09.234713-08:00"}
{"id":"gt-g44u.2","title":"Create mol-install-go-binary molecule","description":"Create a single-step molecule for building and installing the gt binary.\n\n## Molecule Definition\n\\`\\`\\`markdown\n## Molecule: install-go-binary\nSingle step to rebuild and install the gt binary after code changes.\n\n## Step: install\nBuild and install the gt binary locally.\n\nRun from the rig directory:\n\\`\\`\\`\ngo build -o gt ./cmd/gt\ngo install ./cmd/gt\n\\`\\`\\`\n\nVerify the installed binary is updated:\n\\`\\`\\`\nwhich gt\ngt --version # if we have version command\n\\`\\`\\`\n\\`\\`\\`\n\n## Implementation\n1. Add to builtin_molecules.go\n2. Update SeedBuiltinMolecules to include it\n3. Run gt molecule seed\n\n## Acceptance\n- [ ] mol-install-go-binary exists in beads\n- [ ] Can be instantiated standalone\n- [ ] Can be included by other molecules","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:11.178225-08:00","updated_at":"2025-12-19T16:02:36.758908-08:00","closed_at":"2025-12-19T16:02:36.758908-08:00","dependencies":[{"issue_id":"gt-g44u.2","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:11.180129-08:00","created_by":"daemon"}]}
{"id":"gt-q8du","title":"Configuration in Beads: use pinned beads for rig/agent config","description":"## Summary\n\nMove configuration from JSON files into Beads data plane using pinned beads.\n\n## Motivation\n\n- Config becomes versionable and syncable like issues\n- Agents can read config via `bd show`\n- Unified data model for everything\n- Supports the 'Beads as Universal Data Plane' vision (gt-aqm)\n\n## Config Types to Migrate\n\n### Rig-level (pinned per rig)\n- Theme/colors for tmux status line\n- Default branch naming conventions\n- Merge queue settings\n- Witness thresholds\n\n### Agent-level (pinned per role)\n- Handoffs (already planned - gt-cu7r)\n- Agent preferences\n- Current focus/context\n\n### Town-level (pinned at town root)\n- Cross-rig settings\n- Federation config\n- Global themes\n\n## Implementation\n\n1. Implement StatusPinned (beads-6v2) ✓ in progress\n2. Create config pinned beads on rig init\n3. Add `bd config get/set` commands that read/write pinned beads\n4. Migrate existing config.json fields\n\n## Naming Convention\n\n```\n\u003cprefix\u003e-cfg-\u003cscope\u003e\ngt-cfg-theme # gastown theme\nbd-cfg-merge # beads merge settings\ngm-cfg-town # town-level config\n```\n\n## Dependencies\n\n- beads-6v2: Add StatusPinned to beads schema\n- gm-w13: Pinned Beads epic","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T21:58:59.898116-08:00","updated_at":"2025-12-18T21:58:59.898116-08:00"}
{"id":"gt-3zg","title":"Verify architecture.md shows correct harness and rig structure","description":"Review architecture.md diagrams:\n- Verify town-level structure shows harness correctly\n- Confirm rig-level mayor/rig/ is shown (it appears to be there at line 197)\n- Check mermaid diagrams match ASCII diagrams\n- Update if any inconsistencies found\n- Cross-reference with new harness.md docs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:45.10268-08:00","updated_at":"2025-12-19T12:56:15.198431-08:00","closed_at":"2025-12-19T12:06:49.800234-08:00","dependencies":[{"issue_id":"gt-3zg","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:52.090317-08:00","created_by":"daemon"}]}
{"id":"gt-cr9","title":"Harness Design \u0026 Documentation","description":"The harness (Gas Town installation directory) needs design cleanup, documentation, and tooling.\n\n## Current Problems\n\n1. **Shared harness confusion**: ~/ai is shared by PGT and GGT with overlapping structures\n - PGT uses ~/ai/mayor/ as town-level Mayor home\n - GGT Mayor works in ~/ai/mayor/rigs/gastown/\n - ~/ai/gastown/ has both .gastown/ (PGT) and mayor/ (git clone)\n\n2. **Beads redirect**: ~/ai/.beads/redirect → mayor/rigs/gastown/.beads\n - This is specific to GGT's decentralized structure\n - Should be documented as an example\n\n3. **architecture.md**: Verify rig-level mayor/rig/ is shown correctly\n\n4. **No harness creation tooling**: Users must manually set up\n\n## Proposed Work\n\n- Document what a harness IS (installation directory)\n- Create harness creation command or template repo\n- Update architecture.md if needed \n- Create example harness configuration for docs\n- Resolve PGT/GGT sharing issue","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T17:15:08.769961-08:00","updated_at":"2025-12-19T12:56:15.206358-08:00","closed_at":"2025-12-19T12:02:12.135837-08:00"}
{"id":"gt-kmn.6","title":"Witness swarm landing protocol","description":"Witness responsibilities for swarm landing cleanup.\n\n## Trigger\n\nWitness receives \"swarm-landed\" mail from Refinery containing:\n- swarm_id\n- merge_commit\n- action: \"cleanup\"\n\n## Landing Protocol\n\n### Phase 1: Preflight\nVerify all polecat sessions stopped:\n- Check tmux for active sessions\n- Kill any remaining sessions\n- Wait for graceful shutdown\n\n### Phase 2: Git Audit\nFor each polecat in swarm:\n- Check for uncommitted changes\n- Check for unpushed commits\n- Check for stashes\n- Classify as \"beads-only\" (safe) or \"code at risk\"\n- If code at risk: escalate, abort landing\n\n### Phase 3: Cleanup\nFor each polecat:\n- Clear state entry (mark as idle)\n- Delete inbox (or archive)\n- Delete worker branch (local + remote)\n\n### Phase 4: Final Report\n- Update swarm state to \"landed\"\n- File landing report bead\n- Mail Mayor with summary\n\n## Code at Risk Handling\n\nIf git audit finds code at risk:\n1. Abort cleanup for that polecat\n2. Mail Mayor with details\n3. Human intervention required\n\n## Reference\n\nPGT: swarm/landing.py (6-phase protocol), swarm/git_audit.py","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:49.002317-08:00","updated_at":"2025-12-16T14:22:50.525639-08:00","closed_at":"2025-12-16T14:22:50.525639-08:00","dependencies":[{"issue_id":"gt-kmn.6","depends_on_id":"gt-kmn.8","type":"blocks","created_at":"2025-12-16T00:11:26.758388-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.6","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-16T00:11:26.839345-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.6","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:49.002696-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.4","title":"Tmux wrapper: session operations","description":"Wrapper for tmux session operations via subprocess.\n\n## Interface\n\n```go\ntype Tmux struct{}\n\nfunc NewTmux() *Tmux\n\n// Session lifecycle\nfunc (t *Tmux) NewSession(name, workDir string) error\nfunc (t *Tmux) KillSession(name string) error\nfunc (t *Tmux) HasSession(name string) (bool, error)\nfunc (t *Tmux) ListSessions() ([]string, error)\n\n// Session interaction\nfunc (t *Tmux) SendKeys(session, keys string) error\nfunc (t *Tmux) CapturePane(session string, lines int) (string, error)\nfunc (t *Tmux) AttachSession(session string) error\n\n// Window operations (if needed)\nfunc (t *Tmux) SelectWindow(session string, index int) error\n```\n\n## Session Naming\n\nConvention: `gt-\u003crig\u003e-\u003cpolecat\u003e` (e.g., `gt-wyvern-Toast`)\n\n## Implementation\n\n- Shell out to tmux binary\n- CapturePane uses `tmux capture-pane -p -t \u003csession\u003e -S -\u003clines\u003e`\n- SendKeys uses `tmux send-keys -t \u003csession\u003e '\u003ckeys\u003e' Enter`\n\n## Error Handling\n\n- \"no server running\": tmux not started (not an error for HasSession)\n- \"session not found\": session doesn't exist\n- Wrap all tmux errors with context\n\n## Environment\n\nRequires TMUX_TMPDIR or uses default socket. Don't assume tmux is running.","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:13.432706-08:00","updated_at":"2025-12-16T13:28:35.516697-08:00","closed_at":"2025-12-16T13:28:35.516697-08:00","dependencies":[{"issue_id":"gt-u1j.4","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:13:47.298442-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.4","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:13.433043-08:00","created_by":"daemon"}]}
{"id":"gt-ktal","title":"Epic: Refinery Engineer Autonomy","description":"Make Refinery Engineer fully autonomous:\n\n## Goal\nRefinery can run indefinitely, processing all polecat work through merge queue, cycling sessions as needed, without human intervention.\n\n## Key Components\n1. Role prompting (CLAUDE.md, templates)\n2. Handoff mechanism (pinned beads)\n3. Context detection (gt prime)\n4. Communication protocol (Witness, Deacon)\n5. Future: Merge orchestration plugins\n\n## Success Criteria\n- Refinery starts, reads handoff, knows what to do\n- Processes merges sequentially with conflict resolution\n- Cycles sessions cleanly via Deacon\n- Communicates results to Witness\n- No work left behind","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-19T18:09:30.84543-08:00","updated_at":"2025-12-19T18:09:30.84543-08:00"}
{"id":"gt-u1j.1","title":"Go scaffolding: cmd/gt, go.mod, Cobra setup","description":"Set up Go project structure with CLI framework.\n\n**Stack:**\n- Cobra for command/flag handling\n- Lipgloss for styled terminal output\n\n**Deliverables:**\n- cmd/gt/main.go with Cobra root command\n- Basic subcommands: version, help\n- Lipgloss styles for status output (success, warning, error)\n- go.mod with dependencies","status":"closed","issue_type":"task","created_at":"2025-12-15T16:36:48.376267-08:00","updated_at":"2025-12-16T13:19:16.463491-08:00","closed_at":"2025-12-16T13:19:16.463491-08:00","dependencies":[{"issue_id":"gt-u1j.1","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T16:36:48.376622-08:00","created_by":"daemon"}]}
{"id":"gt-j4nu","title":"Merge: gt-g44u.3","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-g44u.3\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:14:52.767156-08:00","updated_at":"2025-12-19T17:35:36.663796-08:00","closed_at":"2025-12-19T17:35:36.663796-08:00"}
{"id":"gt-6db","title":"gt rig shutdown: Gracefully stop all rig agents","description":"Add 'gt rig shutdown \u003crig\u003e' command to gracefully stop all agents in a rig.\n\nShould:\n- Stop all polecat sessions\n- Stop refinery\n- Stop witness\n- Optionally wait for graceful shutdown with timeout","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:50:07.938698-08:00","updated_at":"2025-12-19T12:56:15.203164-08:00","closed_at":"2025-12-19T12:05:27.341209-08:00","dependencies":[{"issue_id":"gt-6db","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.179236-08:00","created_by":"daemon"}]}
{"id":"gt-56po","title":"Merge: gt-g44u.2","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-g44u.2\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:03:10.388461-08:00","updated_at":"2025-12-19T17:35:39.482476-08:00","closed_at":"2025-12-19T17:35:39.482476-08:00"}
{"id":"gt-86w","title":"CLI: doctor diagnostics and auto-repair","description":"GGT completely lacks the doctor command which is critical for debugging.\n\nRequired Commands:\n- gt doctor [\u003crig\u003e] - Run diagnostic checks\n- gt doctor --fix - Auto-repair common issues\n\nChecks to Implement:\nWorkspace Level: Config validity, Mayor mailbox, Rig registry\nRig Level: Git state, clone health, witness/refinery presence, beads sync\nSwarm Level: Stuck detection, zombie sessions, heartbeat health\n\nPGT Reference: gastown-py/src/gastown/cli/dashboard_cmd.py","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:34.721484-08:00","updated_at":"2025-12-16T16:03:17.405433-08:00","closed_at":"2025-12-16T16:03:17.405433-08:00"}
{"id":"gt-ctr","title":"GGT vs PGT Gap Analysis Summary","description":"Summary of gaps comparing GGT (~4,500 LOC) to PGT (~27,700 LOC).\n\n## Critical Gaps (P1) - Existing Issues\n- gt-u1j.17: Polecat CLI (add, list, wake, sleep) - DETAILED\n- gt-u1j.16: Rig CLI (add, list, show, remove) - DETAILED\n- gt-u1j.18: Witness CLI (start, stop, status) - DETAILED\n- gt-f9x.4: Doctor framework - DETAILED\n- gt-f9x.5: Workspace doctor checks - DETAILED\n- gt-f9x.6: Rig doctor checks - DETAILED\n\n## Critical Gaps (P1) - New Issues\n- gt-a95: Refinery background daemon mode - ENHANCED\n- gt-hgk: Mail message types and threading - ENHANCED\n\n## Significant Gaps (P2) - New Issues\n- gt-d46: Mail CLI archive/purge/search - ENHANCED\n- gt-e9k: Swarm preflight/postflight - ENHANCED\n- gt-662: Swarm report generation - ENHANCED\n- gt-69l: Hook system - ENHANCED\n- gt-3yj: Agent monitoring - ENHANCED\n- gt-1ky: Workspace CLI (may overlap f9x.3) - ENHANCED\n- gt-9j9: Worker status reporting - ENHANCED\n- gt-qao: Mayor CLI - ENHANCED\n- gt-7o7: Session pre-shutdown checks - ENHANCED\n- gt-c92: Batch all command - ENHANCED\n- gt-lno: Swarm state persistence - ENHANCED\n- gt-a9y: File locking - ENHANCED\n- gt-30o: Error handling improvements - ENHANCED\n\n## Significant Gaps (P2) - Existing Issues\n- gt-kmn.12: Ephemeral rig support - DETAILED\n\n## Lower Priority (P3) - New Issues\n- gt-3fm: Mail orchestrator daemon - ENHANCED\n- gt-2kz: Cleanup commands - ENHANCED\n- gt-ebl: Names commands - ENHANCED\n- gt-1u9: Interactive prompts - ENHANCED\n- gt-8lz: Help text improvements - ENHANCED\n\n## Closed as Duplicates\n- gt-3tz → gt-u1j.17 (polecat CLI)\n- gt-e1r → gt-u1j.16 (rig CLI)\n- gt-86w → gt-f9x.4/5/6 (doctor)\n- gt-alx → gt-kmn.12 (ephemeral rigs)\n\n## Execution Order Recommendation\n1. P1 CLI commands (existing detailed issues ready to implement)\n2. gt-a95: Refinery daemon (blocks autonomous operation)\n3. gt-7o7: Pre-shutdown checks (prevents data loss)\n4. gt-a9y: File locking (prevents corruption)\n5. gt-hgk + gt-d46: Mail improvements\n6. gt-69l: Hook system (enables extensibility)\n7. Remaining P2s in any order\n8. P3s as time permits","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-16T14:49:09.555759-08:00","updated_at":"2025-12-16T16:07:58.413016-08:00"}
{"id":"gt-bxi8","title":"bd mail send: pinned column missing from schema","description":"gt mail send fails with: sqlite3: SQL logic error: table issues has no column named pinned\n\nLikely a schema migration issue - bd schema has 'pinned' field but SQLite table doesn't.\n\n## Reproduction\ngt mail send gastown/Immortan -s 'test' -m 'test'\n\n## Error\ntable issues has no column named pinned\n\n## Fix\nEither:\n1. Add migration to add pinned column\n2. Remove pinned from insert if not present\n3. Regenerate DB from JSONL","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:53:09.262403-08:00","updated_at":"2025-12-19T17:22:52.553097-08:00","closed_at":"2025-12-19T16:17:03.637686-08:00"}
{"id":"gt-cr0","title":"Consolidate design docs into beads descriptions","description":"The markdown design docs (swarm-shutdown-design.md, polecat-beads-access-design.md, mayor-handoff-design.md) will decay. Extract key decisions and prompting templates into the beads descriptions themselves, then archive or remove the markdown files. Beads are the source of truth.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:05.45131-08:00","updated_at":"2025-12-15T20:51:52.083465-08:00","closed_at":"2025-12-15T20:51:52.083465-08:00"}
{"id":"gt-2c1","title":"Swarm learning: Spawn should auto-notify polecats","description":"town spawn assigns issues but doesn't notify polecats. Required separate 'town session send' to inject prompts. This should be one atomic operation - spawn assigns AND pokes the polecat to start working.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T01:21:47.223608-08:00","updated_at":"2025-12-16T01:27:48.746346-08:00","closed_at":"2025-12-16T01:27:48.746346-08:00"}
{"id":"gt-99a","title":"Add unit tests for daemon package","description":"The daemon package has no unit tests. Need tests for:\n- Config and state serialization\n- Session name pattern matching (isWitnessSession)\n- Lifecycle request parsing\n- Identity to session mapping","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:10.458609-08:00","updated_at":"2025-12-19T17:22:52.552189-08:00","closed_at":"2025-12-19T16:17:43.92102-08:00","dependencies":[{"issue_id":"gt-99a","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.466501-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.20","title":"Prompt templates: role contexts, nudge messages","description":"Prompt templates for role contexts and messages.\n\n## Template Types\n\n### Role CLAUDE.md Templates\n\nFor gt prime and CLAUDE.md generation:\n- Mayor template\n- Witness template\n- Refinery template\n- Polecat template\n\n### Message Templates\n\nFor notifications and nudges:\n- Spawn assignment\n- Witness nudge\n- Escalation to Mayor\n- Session handoff\n\n## Implementation\n\n```go\n//go:embed templates/*.md.tmpl\nvar templateFS embed.FS\n\ntype Templates struct {\n fs embed.FS\n}\n\nfunc NewTemplates() *Templates\nfunc (t *Templates) RenderRole(role string, data RoleData) (string, error)\nfunc (t *Templates) RenderMessage(name string, data any) (string, error)\n```\n\n## Template Data\n\n```go\ntype RoleData struct {\n Role string\n RigName string\n TownRoot string\n Polecats []string\n Commands []CommandHelp\n}\n\ntype SpawnData struct {\n Issue string\n Title string\n Priority int\n Description string\n}\n\ntype NudgeData struct {\n Polecat string\n Reason string\n NudgeCount int\n MaxNudges int\n}\n```\n\n## Template Location\n\nEmbedded in binary via go:embed:\n```\ninternal/templates/\n├── roles/\n│ ├── mayor.md.tmpl\n│ ├── witness.md.tmpl\n│ ├── refinery.md.tmpl\n│ └── polecat.md.tmpl\n└── messages/\n ├── spawn.md.tmpl\n ├── nudge.md.tmpl\n └── escalation.md.tmpl\n```\n\n## Usage\n\ngt prime uses role templates.\ngt spawn uses spawn template.\nWitness uses nudge/escalation templates.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:18.711762-08:00","updated_at":"2025-12-17T16:59:30.686496-08:00","closed_at":"2025-12-17T16:59:30.686496-08:00","dependencies":[{"issue_id":"gt-u1j.20","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-15T17:14:21.32864-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.20","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:18.712116-08:00","created_by":"daemon"}]}
{"id":"gt-e5o","title":"Fix role detection for nested rig structures","description":"When gastown/ has its own mayor/ dir, workspace detection finds it as town root instead of ~/ai. This breaks polecat/refinery/witness detection when running from within a rig.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-17T16:47:18.519581-08:00","updated_at":"2025-12-17T17:02:51.8271-08:00","closed_at":"2025-12-17T17:02:51.8271-08:00"}
{"id":"gt-3x1.4","title":"Failure handling: assign back to worker, add labels","description":"Handle merge failures appropriately.\n\nFailure types and actions:\n| Failure | Action |\n|-------------|---------------------------------------------|\n| conflict | Add needs-rebase label, assign to worker |\n| tests_fail | Add needs-fix label, assign to worker |\n| build_fail | Add needs-fix label, assign to worker |\n| flaky_test | Retry once, then treat as tests_fail |\n| push_fail | Retry with backoff, escalate if persistent |\n\nActions:\n1. bd update \u003cid\u003e --status=open --assignee=\u003cworker\u003e\n2. bd update \u003cid\u003e --labels=\u003cfailure-label\u003e\n3. Send mail to worker explaining failure\n4. Log failure details\n\nReference: docs/merge-queue-design.md#handling-failures","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:17.238066-08:00","updated_at":"2025-12-19T15:27:45.509861-08:00","closed_at":"2025-12-19T14:48:36.428213-08:00","dependencies":[{"issue_id":"gt-3x1.4","depends_on_id":"gt-3x1.1","type":"blocks","created_at":"2025-12-17T13:53:10.281038-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.4","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:17.240001-08:00","created_by":"daemon"}]}
{"id":"gt-kmn.9","title":"Work reconciliation module","description":"Port reconcile.py work verification to Go.\n\n## Purpose\n\nVerify assigned issues are completed before landing.\n\n## Interface\n\n```go\ntype ReconcileResult struct {\n CompletedIssues []IssueInfo\n IncompleteIssues []IssueInfo\n AllComplete bool\n PolecatsChecked []string\n Errors []string\n}\n\nfunc ReconcileWork(rig string, polecats []string) *ReconcileResult\nfunc GetAssignedIssues(assignee string) []IssueInfo\nfunc UnassignIssue(issueID string, resetStatus bool) error\n```\n\n## Logic\n\n1. Get list of polecats in swarm\n2. For each polecat, query beads for assigned issues\n3. Categorize as completed (closed) or incomplete (open/in_progress)\n4. Return summary for landing decision\n\n## Handling Incomplete Work\n\nIf issues incomplete:\n- Abort landing (default)\n- Or force landing (leaves work unfinished)\n- Unassign incomplete issues for future work\n\n## Reference\n\nPGT: swarm/reconcile.py","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:21.351476-08:00","updated_at":"2025-12-16T00:10:21.351476-08:00","dependencies":[{"issue_id":"gt-kmn.9","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:21.351869-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.9","depends_on_id":"gt-u1j.13","type":"blocks","created_at":"2025-12-16T00:11:29.259187-08:00","created_by":"daemon"}]}
{"id":"gt-2jl","title":"Add bulk polecat remove command (gt polecat remove --all)","description":"When decommissioning a rig, need to remove multiple polecats one at a time. A --all or --rig flag would allow: gt polecat remove --rig gastown --force","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-18T11:33:35.206637-08:00","updated_at":"2025-12-18T11:38:53.829321-08:00","closed_at":"2025-12-18T11:38:53.829321-08:00"}
{"id":"gt-cik.9","title":"Complete gt crew commands (list, attach, remove, refresh, status)","description":"Add remaining crew subcommands to internal/cmd/crew.go:\n\n1. gt crew list - List crew workspaces with status\n2. gt crew at/attach - Start tmux session in crew workspace \n3. gt crew remove - Remove crew workspace (with safety checks)\n4. gt crew refresh - Context cycling with mail-to-self handoff\n5. gt crew status - Show detailed workspace status\n\nBuild on existing crew add implementation in internal/cmd/crew.go.\nReference closed issues gt-cik.3-7 for original requirements.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T20:53:25.564877-08:00","updated_at":"2025-12-16T20:59:02.001789-08:00","closed_at":"2025-12-16T20:59:02.001789-08:00","dependencies":[{"issue_id":"gt-cik.9","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T20:53:25.566962-08:00","created_by":"daemon"}]}
{"id":"gt-51x","title":"Fix golangci-lint errcheck warnings (~160 issues)","description":"Running golangci-lint shows ~160 errcheck warnings for unchecked error returns.\n\nCommon patterns:\n- t.SetEnvironment() return values\n- os.WriteFile(), os.RemoveAll() \n- MarkFlagRequired() on cobra commands\n- Various manager methods\n\nRun: golangci-lint run ./...\n\nCould batch fix with:\n1. Add explicit _ = for intentionally ignored errors\n2. Handle errors properly where they matter\n3. Consider adding //nolint:errcheck for cobra flag setup","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T15:02:39.807659-08:00","updated_at":"2025-12-19T12:56:15.201923-08:00","closed_at":"2025-12-19T12:09:58.544102-08:00"}
{"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-0qki","title":"Refinery-Witness communication protocol","description":"Define mail protocol between Refinery and Witness:\n\nFROM Witness → Refinery:\n- 'Polecat ready': polecat X completed work, ready for merge\n- 'Rework complete': polecat Y finished requested rework\n\nFROM Refinery → Witness:\n- 'Merge success': polecat X merged, can be cleaned up\n- 'Merge failed': polecat X needs rework on \u003creason\u003e\n- 'Rework request': please have a polecat rebase X on current main\n\nImplement as structured mail with parseable format.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-19T18:09:27.451344-08:00","updated_at":"2025-12-19T18:09:27.451344-08:00","dependencies":[{"issue_id":"gt-0qki","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.58445-08:00","created_by":"daemon"}]}
{"id":"gt-egu","title":"gt refinery attach: Attach to refinery session","description":"Add 'gt refinery attach [rig]' command to attach to refinery tmux session.\n\nMirrors 'gt mayor attach' pattern. If rig not specified, use current rig context.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:19.164342-08:00","updated_at":"2025-12-17T22:28:45.661097-08:00","closed_at":"2025-12-17T22:28:45.661097-08:00","dependencies":[{"issue_id":"gt-egu","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.578871-08:00","created_by":"daemon"}]}
{"id":"gt-5ft3","title":"Merge: gt-99a","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-99a\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:18:15.329358-08:00","updated_at":"2025-12-19T18:26:14.101606-08:00","closed_at":"2025-12-19T17:48:44.671082-08:00"}
{"id":"gt-vjv","title":"Add bulk session stop command (gt session stop --all)","description":"When decommissioning a rig, need to stop multiple sessions one at a time. A --all or --rig flag would allow: gt session stop --rig gastown","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-18T11:33:33.394649-08:00","updated_at":"2025-12-18T11:38:51.399298-08:00","closed_at":"2025-12-18T11:38:51.399298-08:00"}
{"id":"gt-y0t","title":"session stop: --force flag is defined but not used","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-16T13:55:12.848848-08:00","updated_at":"2025-12-16T13:56:39.09003-08:00","closed_at":"2025-12-16T13:56:39.09003-08:00"}
{"id":"gt-346","title":"Update harness beads redirect for GGT","description":"Change ~/ai/.beads/redirect from mayor/rigs/gastown/.beads to gastown/mayor/.beads for the GGT directory structure","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T16:42:41.650571-08:00","updated_at":"2025-12-19T12:56:15.19675-08:00","closed_at":"2025-12-19T12:00:39.272977-08:00","dependencies":[{"issue_id":"gt-346","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:59.04264-08:00","created_by":"daemon"},{"issue_id":"gt-346","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.495061-08:00","created_by":"daemon"}]}
{"id":"gt-ov2","title":"Refinery agent: merge queue processing loop","description":"The Refinery agent processes the merge queue, merging polecat work to main.\n\n## Interface\n\n```go\ntype Refinery struct {\n rig *Rig\n queue *MergeQueue\n git *Git\n mail *Mailbox\n config RefineryConfig\n}\n\ntype RefineryConfig struct {\n AutoMerge bool // Auto-merge passing MRs\n RunTests bool // Run tests before merge\n TestCommand string // Command to run tests\n RequireReview bool // Require review before merge (future)\n}\n\nfunc NewRefinery(rig *Rig, ...) *Refinery\n\n// Lifecycle\nfunc (r *Refinery) Start() error\nfunc (r *Refinery) Stop() error\nfunc (r *Refinery) IsRunning() bool\n\n// Processing\nfunc (r *Refinery) ProcessQueue() error\nfunc (r *Refinery) ProcessMR(mr *MergeRequest) error\n```\n\n## Processing Loop\n\n1. Check queue for pending MRs\n2. For each pending MR:\n a. Fetch polecat branch\n b. Attempt merge to refinery/rig (local main)\n c. Run tests if configured\n d. If pass: push to origin, mark merged\n e. If fail: mark rejected, notify polecat\n3. Sleep, repeat\n\n## Merge Strategy\n\n- Fast-forward when possible\n- Merge commit when not\n- On conflict: reject MR, polecat must rebase\n\n## Test Integration\n\nIf tests configured:\n```bash\ncd refinery/rig\ngit merge polecat/branch\n\u003ctest_command\u003e # e.g., go test ./...\n```\nResult determines merge/reject.\n\n## Notifications\n\nOn merge success:\n- Mail to polecat: \"Your work merged\"\n- Update bead if issue tracked\n\nOn merge failure:\n- Mail to polecat: \"Merge failed: \u003creason\u003e\"\n- Include conflict details if applicable\n\n## Dependencies\n\nNeeds: Rig management, Git wrapper, Mail system, Merge queue","status":"closed","issue_type":"task","created_at":"2025-12-15T23:22:08.498771-08:00","updated_at":"2025-12-16T14:20:35.032221-08:00","closed_at":"2025-12-16T14:20:35.032221-08:00","dependencies":[{"issue_id":"gt-ov2","depends_on_id":"gt-u1j.14","type":"blocks","created_at":"2025-12-15T23:22:21.801826-08:00","created_by":"daemon"},{"issue_id":"gt-ov2","depends_on_id":"gt-u1j.6","type":"blocks","created_at":"2025-12-15T23:22:21.89716-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.10","title":"VM outpost setup: Terraform and documentation","description":"## Overview\n\nDocumentation and optional Terraform for setting up VM outposts.\n\n## Manual Setup Guide\n\n```markdown\n# Setting Up a VM Outpost\n\n## Prerequisites\n- GCE VM (or any Linux machine with SSH access)\n- SSH key pair\n- Git configured on VM\n\n## Steps\n\n1. Install Claude Code on VM:\n ```bash\n ssh user@vm\n npm install -g @anthropic-ai/claude-code\n ```\n\n2. Clone Gas Town:\n ```bash\n mkdir -p ~/ai\n cd ~/ai\n gt install .\n ```\n\n3. Configure Git credentials:\n ```bash\n git config --global user.name \"Your Name\"\n git config --global credential.helper store\n ```\n\n4. Add outpost to local config:\n ```bash\n gt outpost add ssh \\\n --name gce-burst \\\n --host 10.0.0.5 \\\n --user steve \\\n --key ~/.ssh/gce_worker \\\n --town-path /home/steve/ai \\\n --max-workers 8\n ```\n\n5. Test connectivity:\n ```bash\n gt outpost ping gce-burst\n ```\n```\n\n## Terraform Module (Optional)\n\n```hcl\n# deploy/terraform/vm-outpost/main.tf\n\nvariable \"project\" {}\nvariable \"zone\" { default = \"us-central1-a\" }\nvariable \"machine_type\" { default = \"e2-standard-4\" }\n\nresource \"google_compute_instance\" \"outpost\" {\n name = \"gastown-outpost\"\n machine_type = var.machine_type\n zone = var.zone\n\n boot_disk {\n initialize_params {\n image = \"ubuntu-2204-lts\"\n size = 100\n }\n }\n\n network_interface {\n network = \"default\"\n access_config {}\n }\n\n metadata_startup_script = file(\"${path.module}/startup.sh\")\n}\n\noutput \"external_ip\" {\n value = google_compute_instance.outpost.network_interface[0].access_config[0].nat_ip\n}\n```\n\n## Files\n\n- `docs/vm-outpost-setup.md`\n- `deploy/terraform/vm-outpost/` (optional)\n\nDepends on: gt-9a2.5 (SSHOutpost)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:34.782908-08:00","updated_at":"2025-12-16T18:03:34.782908-08:00","dependencies":[{"issue_id":"gt-9a2.10","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:34.78496-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.10","depends_on_id":"gt-9a2.5","type":"blocks","created_at":"2025-12-16T18:03:46.408609-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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:30.716666-08:00","updated_at":"2025-12-17T13:52:30.716666-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-foct","title":"Merge: gt-5af.6","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-5af.6\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T17:27:12.608473-08:00","updated_at":"2025-12-19T18:26:14.104443-08:00","closed_at":"2025-12-19T17:48:44.619449-08:00"}
{"id":"gt-l1o","title":"Harness \u0026 Priming: Document architecture and update all role contexts","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T16:42:29.314113-08:00","updated_at":"2025-12-19T12:56:15.213669-08:00","closed_at":"2025-12-19T12:00:51.410053-08:00"}
{"id":"gt-9a2","title":"Federation: Wasteland architecture for cross-town coordination","description":"## Overview\n\nFederation enables Gas Town to scale across machines via **Outposts** - remote compute environments that can run workers.\n\n**Design doc**: docs/federation-design.md\n\n## Outpost Types\n\n| Type | Description | Cost Model |\n|------|-------------|------------|\n| Local | Current model (tmux panes) | Free |\n| SSH/VM | Full Gas Town clone on VM | Always-on |\n| CloudRun | Container workers on GCP | Pay-per-use |\n\n## Key Concepts\n\n### Outpost Abstraction\n```go\ntype Outpost interface {\n Name() string\n Type() OutpostType // local, ssh, cloudrun\n MaxWorkers() int\n Spawn(issue string, config WorkerConfig) (Worker, error)\n Workers() []Worker\n Ping() error\n}\n```\n\n### Cloud Run Workers\n- Persistent HTTP/2 connections solve zero-to-one cold start\n- Pay only when working (~$0.017 per 5-min session)\n- Scale 0→N automatically\n- Git clone via persistent volumes\n\n### SSH/VM Outposts \n- Full Gas Town clone on remote machine\n- SSH for commands, git for sync\n- Good for long-running autonomous work\n\n## Design Principles\n\n1. **Outpost abstraction** - support multiple backends\n2. **Local-first** - remote is for overflow/burst\n3. **Git as source of truth** - code and beads sync everywhere\n4. **HTTP for Cloud Run** - dont force mail onto containers\n5. **Graceful degradation** - works with any subset of outposts\n\n## Related\n\n- gt-f9x.7-10: Connection interface (lower-level abstraction)\n- docs/federation-design.md: Full architectural analysis","status":"open","priority":3,"issue_type":"epic","created_at":"2025-12-15T19:21:32.462063-08:00","updated_at":"2025-12-16T18:01:24.224349-08:00"}
{"id":"gt-kmn.1","title":"Swarm package: Swarm, SwarmTask, SwarmState types","description":"Define core swarm types.\n\n## Types (in `internal/swarm/`)\n\n```go\n// SwarmState represents swarm lifecycle\ntype SwarmState string\nconst (\n SwarmCreated SwarmState = \"created\"\n SwarmActive SwarmState = \"active\"\n SwarmMerging SwarmState = \"merging\"\n SwarmLanded SwarmState = \"landed\"\n SwarmFailed SwarmState = \"failed\"\n SwarmCancelled SwarmState = \"cancelled\"\n)\n\n// Swarm references a beads epic that tracks swarm work\ntype Swarm struct {\n ID string // matches beads epic ID\n RigName string\n EpicID string // beads epic tracking this swarm\n BaseCommit string // git SHA all workers branch from\n Integration string // integration branch name\n State SwarmState\n CreatedAt time.Time\n Workers []string // polecat names assigned\n}\n\n// SwarmTask represents a single task in the swarm (maps to beads issue)\ntype SwarmTask struct {\n IssueID string // beads issue ID\n Assignee string // polecat name\n Branch string // worker branch name\n State string // mirrors beads status\n}\n```\n\n## Note\n\nSwarm state is primarily stored IN beads. These types are in-memory representations for the SwarmManager to work with. No separate manifest.json files.","status":"closed","issue_type":"task","created_at":"2025-12-16T00:08:30.364047-08:00","updated_at":"2025-12-16T13:31:56.20815-08:00","closed_at":"2025-12-16T13:31:56.20815-08:00","dependencies":[{"issue_id":"gt-kmn.1","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:08:30.364431-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.1","depends_on_id":"gt-u1j.1","type":"blocks","created_at":"2025-12-16T00:11:20.646487-08:00","created_by":"daemon"}]}
{"id":"gt-frs","title":"Polecat name pooling: Bounded reusable names","description":"Polecats reuse names from a bounded pool (50) with overflow to sequence numbers.\n\n## Naming Scheme\n- Pool: polecat-01 through polecat-50 (prefer low numbers)\n- Overflow: \u003crigname\u003e-\u003csequenceNumber\u003e (e.g., beads-51, gastown-52)\n\n## Design\n- Witness tracks which pool names are in use\n- On spawn: pick first available from pool\n- If pool exhausted: use rigname-N format\n- On completion: pool name returns, sequence numbers don't\n\n## Why?\n- User experience: tmux sessions survive polecat restarts\n- Users stay attached, see new polecat start (like mayor respawn loop)\n- Bounded resource usage for common case\n- Scales beyond 50 when needed\n\n## Implementation\n- Witness maintains name allocation in beads or local state\n- Tmux session runs respawn loop (like mayor)\n- Name released on graceful exit or when witness detects dead session","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-18T18:32:28.43866-08:00","updated_at":"2025-12-19T17:22:52.551244-08:00","closed_at":"2025-12-19T16:29:30.648439-08:00"}
{"id":"gt-u1j.10","title":"CLI: core commands (status, prime, version, init)","description":"Essential CLI commands for Gas Town operation.\n\n## Commands\n\n### gt status\nShow overall town status.\n```\ngt status [--json]\n```\nOutput:\n- Town name and location\n- Number of rigs\n- Active polecats across all rigs\n- Witness status per rig\n- Recent activity summary\n\n### gt prime\nOutput role context for current directory.\n```\ngt prime\n```\nDetects role from directory:\n- Town root or mayor/ → Mayor context\n- \u003crig\u003e/witness/rig/ → Witness context\n- \u003crig\u003e/refinery/rig/ → Refinery context\n- \u003crig\u003e/polecats/\u003cname\u003e/ → Polecat context\n\n### gt version\nShow version information.\n```\ngt version [--short]\n```\nOutput: version, git commit, build date.\n\n### gt init\nInitialize current rig for Gas Town (alternative to gt install for existing repos).\n```\ngt init [--force]\n```\nCreates Gas Town structure in existing git repo.\n\n## Implementation\n\nEach command is a Cobra subcommand under root:\n```go\nvar statusCmd = \u0026cobra.Command{...}\nvar primeCmd = \u0026cobra.Command{...}\nvar versionCmd = \u0026cobra.Command{...}\nvar initCmd = \u0026cobra.Command{...}\n```\n\nRegister in cmd/gt/main.go.","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:38.367667-08:00","updated_at":"2025-12-16T13:49:54.801859-08:00","closed_at":"2025-12-16T13:49:54.801859-08:00","dependencies":[{"issue_id":"gt-u1j.10","depends_on_id":"gt-u1j.5","type":"blocks","created_at":"2025-12-15T17:14:06.123332-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.10","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:38.368006-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.7","title":"Session management: start, stop, attach, capture","description":"Polecat session lifecycle management.\n\n## Interface\n\n```go\ntype SessionManager struct {\n tmux *Tmux\n rig *Rig\n}\n\nfunc NewSessionManager(tmux *Tmux, rig *Rig) *SessionManager\n\n// Lifecycle\nfunc (sm *SessionManager) Start(polecat string, opts StartOptions) error\nfunc (sm *SessionManager) Stop(polecat string) error\nfunc (sm *SessionManager) IsRunning(polecat string) (bool, error)\nfunc (sm *SessionManager) List() ([]SessionInfo, error)\n\n// Interaction\nfunc (sm *SessionManager) Attach(polecat string) error\nfunc (sm *SessionManager) Capture(polecat string, lines int) (string, error)\nfunc (sm *SessionManager) Inject(polecat string, message string) error\n\ntype StartOptions struct {\n WorkDir string // defaults to polecat clone dir\n Issue string // optional: issue to work on\n Command string // optional: override claude command\n}\n\ntype SessionInfo struct {\n Polecat string\n SessionID string\n Running bool\n StartedAt time.Time\n}\n```\n\n## Session Naming\n\n`gt-\u003crig\u003e-\u003cpolecat\u003e` (e.g., `gt-wyvern-Toast`)\n\n## Start Flow\n\n1. Verify polecat clone exists\n2. Check no existing session\n3. Create tmux session in polecat workdir\n4. Send initial command: `claude` or custom\n5. If issue provided, inject initial prompt\n\n## Stop Flow\n\n1. Capture final output (for logging)\n2. Send exit/quit command\n3. Wait briefly for graceful shutdown\n4. Kill session if still running\n\n## Capture\n\nUses tmux capture-pane to get recent output. Returns last N lines.\n\n## Inject\n\nSends text to session via tmux send-keys. Used for:\n- Mail notifications\n- Witness nudges\n- User messages","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:25.473674-08:00","updated_at":"2025-12-16T13:35:22.862077-08:00","closed_at":"2025-12-16T13:35:22.862077-08:00","dependencies":[{"issue_id":"gt-u1j.7","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:25.473993-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.7","depends_on_id":"gt-u1j.4","type":"blocks","created_at":"2025-12-15T17:13:52.081053-08:00","created_by":"daemon"}]}
{"id":"gt-17r","title":"Doctor check: Zombie session cleanup","description":"Detect and clean up zombie tmux sessions via gt doctor.\n\n## Problem\n\nZombie sessions occur when:\n- Agent crashes without cleanup\n- gt kill fails mid-operation\n- System restart leaves orphan sessions\n- Session naming collision\n\n## Checks\n\n### ZombieSessionCheck\n- List all tmux sessions matching gt-* pattern\n- Cross-reference with known polecats\n- Flag sessions with no corresponding polecat state\n- Flag sessions for removed polecats\n- Check session age vs polecat creation time\n\n### Detection Criteria\n- Session exists but polecat directory doesn't\n- Session name doesn't match any registered polecat\n- Polecat state=idle but session running\n- Multiple sessions for same polecat\n\n## Output\n\n```\n[WARN] Zombie tmux sessions detected:\n - gt-wyvern-OldPolecat (polecat removed)\n - gt-beads-Unknown (no matching polecat)\n - gt-wyvern-Toast (duplicate session)\n\n Run 'gt doctor --fix' to clean up\n```\n\n## Auto-Fix (--fix flag)\n\n- Kill orphan tmux sessions\n- Update polecat state to match reality\n- Log all cleanup actions\n\n## Safety\n\n- Never kill sessions where polecat state=working\n- Prompt before killing if --fix used without --force\n- Create audit log of killed sessions","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:18:01.446702-08:00","updated_at":"2025-12-15T23:18:39.517644-08:00","dependencies":[{"issue_id":"gt-17r","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T23:19:05.66301-08:00","created_by":"daemon"},{"issue_id":"gt-17r","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-17T15:44:41.945064-08:00","created_by":"daemon"}]}
{"id":"gt-cxx","title":"Swarm learning: Witness needs automated context cycling","description":"Furiosa hit 2% context during swarm work. Witness role needs automated detection of low context and should trigger session cycling before agents get stuck. Add to Witness responsibilities in prompts.md.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:21:49.67756-08:00","updated_at":"2025-12-16T01:51:39.2553-08:00","closed_at":"2025-12-16T01:51:39.2553-08:00"}
{"id":"gt-y2p6","title":"Merge: gt-3x1.5","description":"branch: polecat/Immortan\ntarget: main\nsource_issue: gt-3x1.5\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T14:53:53.544887-08:00","updated_at":"2025-12-19T18:26:14.106598-08:00","closed_at":"2025-12-19T17:49:09.215705-08:00"}
{"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":"open","priority":3,"issue_type":"task","created_at":"2025-12-17T13:52:34.770778-08:00","updated_at":"2025-12-17T13:52:34.770778-08:00","dependencies":[{"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-h5n","type":"parent-child","created_at":"2025-12-17T13:52:34.772838-08:00","created_by":"daemon"}]}
{"id":"gt-3x1.3","title":"Merge execution: merge, test, push","description":"Implement the actual merge execution.\n\nSteps:\n1. git checkout \u003cmr.target\u003e\n2. git merge \u003cmr.branch\u003e --no-ff -m 'Merge \u003cbranch\u003e: \u003ctitle\u003e'\n3. If config.run_tests:\n - Run test_command (from config)\n - If failed: git reset --hard HEAD~1, return Failure(tests_failed)\n4. git push origin \u003cmr.target\u003e\n5. Return Success(merge_commit=HEAD)\n\nConfiguration:\n- run_tests: bool (default true)\n- test_command: string (default 'go test ./...')\n\nHandle push failures with retry logic.\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:00.742994-08:00","updated_at":"2025-12-19T15:27:45.507657-08:00","closed_at":"2025-12-19T14:47:45.038129-08:00","dependencies":[{"issue_id":"gt-3x1.3","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:00.744975-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.3","depends_on_id":"gt-3x1.2","type":"blocks","created_at":"2025-12-17T13:53:10.163097-08:00","created_by":"daemon"}]}
{"id":"gt-59p","title":"Design GGT prompt architecture","description":"Audit PGT prompts and design canonical prompt system for GGT. Create docs/prompts.md with inventory, gap analysis, and Witness prompt design.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T00:46:16.916031-08:00","updated_at":"2025-12-16T00:47:38.105395-08:00","closed_at":"2025-12-16T00:47:38.105395-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-g44u.5","title":"Spawn --molecule integration","description":"Implement gt spawn --molecule flag for molecule-based polecat workflows.\n\nUsage: gt spawn --issue gt-xyz --molecule mol-gastown-polecat\n\nBehavior:\n1. Validate molecule exists and is well-formed\n2. Create molecule instance (child beads) under the issue \n3. Find first ready step(s) in the instance\n4. Spawn polecat with first ready step as initial work\n\nImplementation:\n1. Add --molecule flag to spawn command\n2. Call molecule.Instantiate()\n3. Query ready steps from instance\n4. Pass first ready step to polecat context\n\nFiles: internal/cmd/spawn.go\n\nAcceptance:\n- --molecule flag works\n- Creates proper molecule instance\n- Polecat starts on first ready step\n- End-to-end test with actual polecat","status":"closed","issue_type":"task","created_at":"2025-12-19T15:50:24.519069-08:00","updated_at":"2025-12-19T16:13:10.086807-08:00","closed_at":"2025-12-19T16:13:10.086807-08:00","dependencies":[{"issue_id":"gt-g44u.5","depends_on_id":"gt-g44u","type":"parent-child","created_at":"2025-12-19T15:50:24.521029-08:00","created_by":"daemon"},{"issue_id":"gt-g44u.5","depends_on_id":"gt-g44u.1","type":"blocks","created_at":"2025-12-19T15:50:31.275526-08:00","created_by":"daemon"}]}
{"id":"gt-qp98","title":"Refactor: Eliminate state.json, use beads assignee field for polecat state","description":"## Problem\n\nstate.json in each polecat worktree duplicates data that should be in beads:\n- `issue` field duplicates assignment (should be issue.assignee)\n- `state` field duplicates status (derivable from issue.status)\n- `name/rig/branch/clone_path` are all derivable from filesystem/git\n\nThis violates 'Beads as the data plane' (HOP Decision 001).\n\n## Current State\n\n```json\n{\n \"name\": \"Angharad\", // Derivable: basename(cwd)\n \"rig\": \"gastown\", // Derivable: parent dir name\n \"state\": \"working\", // Should be: issue.status\n \"clone_path\": \"/path\", // Derivable: cwd\n \"branch\": \"polecat/X\", // Derivable: git branch\n \"issue\": \"gt-xyz\", // Should be: issue.assignee\n \"timestamps\": \"...\" // Should be in beads history\n}\n```\n\n## Target State\n\n**Polecat identity**: Derived from worktree path\n**Polecat assignment**: `issue.assignee = 'gastown/Angharad'`\n**Polecat state**: Derived from issue.status (in_progress = working, closed = done)\n**Polecat existence**: Worktree directory exists\n\n## Benefits\n\n1. Single source of truth (no sync issues)\n2. Queryable: `bd list --assignee=gastown/Angharad`\n3. History tracking via beads\n4. Cross-agent coordination via beads sync\n5. Simpler code (no state file management)\n\n## Implementation\n\n1. Update `gt spawn` to set issue.assignee instead of writing state.json\n2. Update polecat list/status commands to query beads\n3. Update Witness to query beads for polecat state\n4. Remove state.json read/write code\n5. Keep state.json as optional bootstrap cache (perf optimization only)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T11:40:33.389689-08:00","updated_at":"2025-12-19T12:07:43.519059-08:00","closed_at":"2025-12-19T12:07:43.519059-08:00"}
{"id":"gt-662","title":"Swarm: report generation","description":"Generate markdown reports for completed swarms.\n\n## Command\n```\ngt swarm report \u003cswarm-id\u003e [--save \u003cfile\u003e]\n```\n\n## Report Content\n\n### Header\n- Swarm ID and title\n- Created/completed timestamps\n- Duration\n- Rig name\n\n### Task Summary\n| Task | Assignee | Status | Duration |\n|------|----------|--------|----------|\n| gt-xxx | Toast | merged | 15m |\n| gt-yyy | Nux | merged | 22m |\n\n### Worker Contributions\n- Commits per worker\n- Issues closed per worker\n- Lines changed (optional)\n\n### Timeline\n- Chronological events from events.jsonl\n- Key milestones (started, first merge, landing)\n\n### Issues Encountered\n- Conflicts resolved\n- Failed tasks (if any)\n- Escalations\n\n## Implementation\n```go\nfunc GenerateReport(swarmID string) (*SwarmReport, error)\nfunc (r *SwarmReport) ToMarkdown() string\n```\n\n## Storage\n- Save to \u003crig\u003e/.gastown/swarms/\u003cid\u003e/report.md\n- Or user-specified path with --save\n\n## PGT Reference\ngastown-py/src/gastown/swarm/manager.py generate_report()\n\n## Acceptance Criteria\n- [ ] Markdown report generated\n- [ ] Includes all sections above\n- [ ] Auto-saved to swarm directory\n- [ ] --save allows custom path","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T14:47:17.96767-08:00","updated_at":"2025-12-16T17:23:22.330075-08:00","closed_at":"2025-12-16T17:23:22.330075-08:00"}
{"id":"gt-01u","title":"Design: Collapse mail into beads","description":"## Proposal\n\nReplace the separate mail system (JSONL inboxes) with beads issues using a naming convention.\n\n## Rationale\n\nIf all state should be in beads (work items, swarm state, dependencies), why have a separate system for messages? Mail is just:\n- Handoffs (agent → self)\n- Commands (Mayor → Refinery)\n- Escalations (Witness → Mayor)\n\nThese can all be beads issues with a special prefix.\n\n## Design\n\n### Convention\n- Messages use `@-` prefix: `@-witness-1734012345`\n- Assignee = recipient\n- Status: open = unread, closed = read/acknowledged\n- Priority 0 = urgent\n\n### Commands (thin wrappers)\n```bash\ngt mail send witness -s \"Subject\" -m \"Body\"\n → bd create --prefix=@ --title=\"Subject\" --assignee=witness --description=\"Body\"\n\ngt mail inbox\n → bd list --prefix=@ --assignee=$(gt whoami) --status=open\n\ngt mail read @-abc\n → bd show @-abc \u0026\u0026 bd close @-abc\n```\n\n### Notification\nDaemon watches for new `@-` issues and pokes relevant sessions.\nOr: agents poll on heartbeat (simpler).\n\n## What We Remove\n- `mail/inbox.jsonl` files\n- Mail JSONL read/write code\n- Separate delivery mechanism\n\n## What We Keep\n- `gt mail` CLI (as wrapper)\n- Handoff semantics\n- Notification (via daemon or polling)\n\n## Benefits\n- One system, one sync, one query interface\n- All communication in git history\n- Simpler architecture\n\n## Risks\n- Beads prefix filtering must be efficient\n- Namespace collision with user prefixes\n- Performance for high-frequency messages (probably fine for handoffs)\n\n## Decision Point\nDo we need first-class mail support in beads (`bd mail` commands) or is convention sufficient?","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T02:10:18.32879-08:00","updated_at":"2025-12-16T13:12:16.46526-08:00","closed_at":"2025-12-16T13:12:16.46526-08:00"}
{"id":"gt-e1y","title":"Worker prompting: Beads write access","description":"Add beads write access section to polecat AGENTS.md.template.\n\n## Beads Access Section for Prompting\n\n```markdown\n## Beads Access\n\nYou have **full beads access** - create, update, and close issues.\n\n### Quick Reference\n\n```bash\n# View work\nbd ready # Issues ready (no blockers)\nbd list # All open issues\nbd show \u003cid\u003e # Issue details\n\n# Create issues\nbd create --title=\"Fix bug\" --type=bug --priority=2\nbd create --title=\"Add feature\" --type=feature\n\n# Update issues\nbd update \u003cid\u003e --status=in_progress # Claim work\nbd close \u003cid\u003e # Mark complete\n\n# Sync (required before merge!)\nbd sync # Commit beads changes to git\n```\n\n### When to Create Issues\n\nCreate beads issues when you discover work that:\n- Is outside your current task scope\n- Would benefit from tracking\n- Should be done by someone else\n\n**Good examples**:\n```bash\nbd create --title=\"Race condition in auth\" --type=bug --priority=1\nbd create --title=\"Document API rate limits\" --type=task --priority=3\n```\n\n**Don't create for**:\n- Tiny fixes you can do in 2 minutes\n- Vague \"improvements\" with no scope\n- Work already tracked elsewhere\n\n### Beads Sync Protocol\n\n**CRITICAL**: Always sync beads before merging!\n\n```bash\nbd sync # Commits beads changes\ngit add .beads/\ngit commit -m \"beads: sync\"\n```\n\nIf you forget to sync, beads changes are lost when session ends.\n```\n\n## Implementation\n\nAdd to AGENTS.md.template polecat section.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:18.459363-08:00","updated_at":"2025-12-15T20:48:03.813068-08:00","dependencies":[{"issue_id":"gt-e1y","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.81183-08:00","created_by":"daemon"}]}
{"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-2tp","title":"init.go: Replace custom contains() with strings.Contains","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-16T13:55:11.326407-08:00","updated_at":"2025-12-16T13:56:39.089057-08:00","closed_at":"2025-12-16T13:56:39.089057-08:00"}
{"id":"gt-s3m0","title":"gt polecat: add 'done' or 'finish' command to transition from working to idle","description":"When a polecat finishes work but session wasn't properly cleaned up, there's no way to reset it from 'working' state back to 'idle'.\n\nTried:\n```\ngt polecat sleep gastown/Angharad\nError: sleeping polecat: polecat is not active (state: working)\n```\n\nThe sleep command only works on 'active' polecats, not 'working' ones.\n\nHad to manually edit state.json to reset:\n```\njq '.state = \"idle\" | .issue = \"\"' state.json\n```\n\nNeed a command like:\n```\ngt polecat done gastown/Angharad # working -\u003e idle\ngt polecat finish gastown/Angharad # working -\u003e idle \ngt polecat reset gastown/Angharad # any state -\u003e idle (force)\n```","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T01:41:39.851037-08:00","updated_at":"2025-12-19T01:57:17.031611-08:00","closed_at":"2025-12-19T01:57:17.031611-08:00"}
{"id":"gt-8mbz","title":"Town Doctor molecule for harness health checks","description":"Create a Town Doctor molecule that any Gas Town agent can run to diagnose and repair harness issues.\n\n## Concept\n\nInstead of just `gt doctor` as a CLI command with hardcoded checks, create a **molecule** (checklist workflow) that:\n- Any agent (Mayor, Witness, Polecat) can instantiate\n- Walks the agent through diagnostic steps\n- Agent uses judgment to fix issues found\n- Works as a structured troubleshooting guide\n\n## Why a Molecule?\n\n1. **Agent-driven**: The agent running it becomes \"the doctor\" temporarily\n2. **Extensible**: Add new checks by updating the molecule, not code\n3. **Contextual**: Agent can reason about issues, not just run scripts\n4. **Self-healing**: Agent can fix problems it finds, not just report them\n\n## Proposed Checks (molecule steps)\n\n1. Verify harness structure (mayor/, .beads/, CLAUDE.md exist)\n2. Validate config files (town.json, rigs.json parse correctly)\n3. Check beads health (bd doctor, redirect validity)\n4. Verify git state (clean working tree, proper remotes)\n5. Check rig integrity (each registered rig exists, has config.json)\n6. Validate agent clones (mayor/rig/, refinery/rig/ exist and are valid)\n7. Check for orphaned worktrees/branches\n8. Verify daemon state (if running)\n\n## Integration\n\n- `gt doctor` could instantiate the molecule for the current agent\n- Or agent can run `bd ready` and pick up doctor tasks when prioritized\n- Results logged to beads for audit trail\n\n## Related\n\n- gt-cr9: Harness Design \u0026 Documentation (completed)\n- Molecules design in architecture.md","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-19T13:03:22.688851-08:00","updated_at":"2025-12-19T13:03:22.688851-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-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-v5k","title":"Design: Failure modes and recovery","description":"Document failure modes and recovery strategies for Gas Town operations.\n\n## Critical Failure Modes\n\n### 1. Agent Crash Mid-Operation\n\n**Scenario**: Polecat crashes while committing, Witness crashes while verifying\n\n**Detection**:\n- Session suddenly gone (tmux check fails)\n- State shows 'working' but no session\n- Heartbeat stops (for Witness)\n\n**Recovery**:\n- Doctor detects via ZombieSessionCheck\n- Capture any recoverable state\n- Reset agent state to 'idle'\n- For Witness: auto-restart via supervisor or manual gt witness start\n\n### 2. Git State Corruption\n\n**Scenario**: Merge conflict, failed rebase, detached HEAD\n\n**Detection**:\n- Git commands fail\n- Dirty state that won't commit\n- Branch diverged from origin\n\n**Recovery**:\n- gt doctor reports git health issues\n- Manual intervention recommended\n- Severe cases: remove clone, re-clone\n\n### 3. Beads Sync Conflict\n\n**Scenario**: Two polecats modify same issue\n\n**Detection**:\n- bd sync fails with conflict\n- Beads tombstone mechanism handles most cases\n\n**Recovery**:\n- Beads has last-write-wins semantics\n- bd sync --force in extreme cases\n- Issues may need manual dedup\n\n### 4. Tmux Failure\n\n**Scenario**: Tmux server crashes, socket issues\n\n**Detection**:\n- All sessions inaccessible\n- \"no server running\" errors\n\n**Recovery**:\n- Kill any orphan processes\n- tmux kill-server \u0026\u0026 tmux start-server\n- All agent states reset to idle\n- Re-spawn active work\n\n### 5. Claude API Issues\n\n**Scenario**: Rate limits, outages, context limits\n\n**Detection**:\n- Sessions hang or produce errors\n- Repeated failure patterns\n\n**Recovery**:\n- Exponential backoff (handled by Claude Code)\n- For context limits: session cycling (mail-to-self)\n- For outages: wait and retry\n\n### 6. Disk Full\n\n**Scenario**: Clones, logs, or beads fill disk\n\n**Detection**:\n- Write operations fail\n- git/bd commands error\n\n**Recovery**:\n- Clean up logs: rm ~/.gastown/logs/*\n- Remove old polecat clones\n- gt doctor --fix can clean some cruft\n\n### 7. Network Failure\n\n**Scenario**: Can't reach GitHub, API servers\n\n**Detection**:\n- git fetch/push fails\n- Claude sessions hang\n\n**Recovery**:\n- Work continues locally\n- Queue pushes for later\n- Sync when connectivity restored\n\n## Recovery Principles\n\n1. **Fail safe**: Prefer stopping over corrupting\n2. **State is recoverable**: Git and beads have recovery mechanisms\n3. **Doctor heals**: gt doctor --fix handles common issues\n4. **Emergency stop**: gt stop --all as last resort\n5. **Human escalation**: Some failures need Overseer intervention\n\n## Implementation\n\n- Document each failure mode in architecture.md\n- Ensure doctor checks cover detection\n- Add recovery hints to error messages\n- Log all failures for debugging","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:19:07.198289-08:00","updated_at":"2025-12-15T23:19:28.171942-08:00"}
{"id":"gt-2bz","title":"Swarm learning: Refinery merge queue automation","description":"Manually merging 15 polecat branches was painful and error-prone. Refinery should automate: detect completed work, run tests, merge to main, handle conflicts. This is core Refinery value prop.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:21:51.137974-08:00","updated_at":"2025-12-16T01:51:40.603737-08:00","closed_at":"2025-12-16T01:51:40.603737-08:00"}
{"id":"gt-9a2.16","title":"Outpost integration tests: Mock and E2E testing","description":"## Overview\n\nIntegration tests for the outpost system.\n\n## Mock Outpost\n\n```go\ntype MockOutpost struct {\n name string\n maxWorkers int\n spawnDelay time.Duration\n spawnError error\n workers []*MockWorker\n}\n\nfunc (o *MockOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n if o.spawnError != nil {\n return nil, o.spawnError\n }\n time.Sleep(o.spawnDelay)\n worker := \u0026MockWorker{id: uuid.New().String(), issue: issue}\n o.workers = append(o.workers, worker)\n return worker, nil\n}\n```\n\n## Unit Tests\n\n```go\nfunc TestOutpostManager_SelectOutpost(t *testing.T) {\n // Test policy-based selection\n}\n\nfunc TestOutpostManager_SpawnWithRetry(t *testing.T) {\n // Test retry logic with transient failures\n}\n\nfunc TestCloudRunOutpost_CostTracking(t *testing.T) {\n // Test cost calculation and caps\n}\n```\n\n## Integration Tests (with mocked Cloud Run)\n\n```go\nfunc TestCloudRunOutpost_Integration(t *testing.T) {\n // Start mock HTTP server\n server := httptest.NewServer(mockWorkHandler())\n defer server.Close()\n \n outpost := NewCloudRunOutpost(OutpostConfig{\n ServiceURL: server.URL,\n })\n \n worker, err := outpost.Spawn(\"test-issue\", WorkerConfig{})\n // Assert worker created, events streamed\n}\n```\n\n## E2E Tests (requires real Cloud Run)\n\n```go\n// +build e2e\n\nfunc TestCloudRunOutpost_E2E(t *testing.T) {\n if os.Getenv(\"CLOUDRUN_SERVICE_URL\") == \"\" {\n t.Skip(\"CLOUDRUN_SERVICE_URL not set\")\n }\n // Test against real Cloud Run service\n}\n```\n\n## Files\n\n- `internal/outpost/mock_test.go`\n- `internal/outpost/manager_test.go`\n- `internal/outpost/cloudrun_test.go`\n- `internal/cloudrun/integration_test.go`\n\n## Dependencies\n\nDepends on: gt-9a2.8 (CloudRunOutpost), gt-9a2.15 (error handling)\nLower priority - can be done after implementations work.","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-16T18:16:48.019386-08:00","updated_at":"2025-12-16T18:16:48.019386-08:00","dependencies":[{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:48.021933-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2.8","type":"blocks","created_at":"2025-12-16T18:16:55.90113-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.16","depends_on_id":"gt-9a2.15","type":"blocks","created_at":"2025-12-16T18:16:56.013753-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.17","title":"CLI: polecat commands (add, remove, list, wake, sleep)","description":"Polecat management CLI commands.\n\n## Commands\n\n### gt polecat list\nList polecats in a rig.\n```\ngt polecat list \u003crig\u003e [--json]\ngt polecat list --all [--json]\n```\nOutput:\n- Name\n- State (idle/active/working/done/stuck)\n- Current issue (if any)\n- Session status (running/stopped)\n\n### gt polecat add\nAdd a new polecat to a rig.\n```\ngt polecat add \u003crig\u003e \u003cname\u003e\n```\n- Creates polecat directory\n- Clones rig repo\n- Creates work branch\n- Initializes state\n\n### gt polecat remove\nRemove a polecat from a rig.\n```\ngt polecat remove \u003crig\u003e/\u003cpolecat\u003e [--force]\n```\n- Fails if session running\n- Warns if uncommitted changes\n- --force bypasses checks\n\n### gt polecat wake\nMark polecat as active (ready for work).\n```\ngt polecat wake \u003crig\u003e/\u003cpolecat\u003e\n```\nTransitions: idle → active\n\n### gt polecat sleep\nMark polecat as idle (not available).\n```\ngt polecat sleep \u003crig\u003e/\u003cpolecat\u003e\n```\nTransitions: active → idle\nFails if session running (stop first).\n\n## Address Format\n\n`\u003crig\u003e/\u003cpolecat\u003e` for operations on specific polecat.\n`\u003crig\u003e` for list command.\n\n## Implementation\n\n```go\nvar polecatCmd = \u0026cobra.Command{Use: \"polecat\"}\npolecatCmd.AddCommand(listCmd, addCmd, removeCmd, wakeCmd, sleepCmd)\n```","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:13.683142-08:00","updated_at":"2025-12-15T21:20:56.485805-08:00","dependencies":[{"issue_id":"gt-u1j.17","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:08.405807-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.17","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:13.683486-08:00","created_by":"daemon"}]}
{"id":"gt-82y","title":"Design: Swarm shutdown and worker cleanup","description":"Design for graceful swarm shutdown, worker cleanup, and session cycling.\n\n## Key Decisions\n\n1. Pre-kill verification uses model intelligence (not framework rules)\n2. Witness can request restart when context filling (mail self, exit)\n3. Mayor NOT involved in per-worker cleanup (Witness responsibility)\n4. Clear responsibility boundaries between Mayor/Witness/Polecat\n\n## Subtasks (implementation)\n\n- gt-sd6: Polecat decommission checklist prompting\n- gt-f8v: Witness pre-kill verification protocol\n- gt-eu9: Witness session cycling and handoff\n- gt-gl2: Mayor vs Witness cleanup responsibilities\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T19:47:44.936374-08:00","updated_at":"2025-12-15T20:49:22.849598-08:00","closed_at":"2025-12-15T20:12:05.441911-08:00"}
{"id":"gt-d7i","title":"gt session capture: Support positional line count argument","description":"Make 'gt session capture gastown/Toast 50' work.\n\nCurrently requires: gt session capture gastown/Toast -n 50\nShould also accept: gt session capture gastown/Toast 50\n\nAgent UX principle: commands should work the way agents guess they work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T22:28:44.291285-08:00","updated_at":"2025-12-19T12:56:15.206849-08:00","closed_at":"2025-12-19T01:33:49.860862-08:00"}
{"id":"gt-beqp","title":"Merge: gt-72so","description":"branch: polecat/Doof\ntarget: main\nsource_issue: gt-72so\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T16:19:11.814962-08:00","updated_at":"2025-12-19T18:26:14.103556-08:00","closed_at":"2025-12-19T17:47:03.61793-08:00"}
{"id":"gt-bj6f","title":"gt prime: Refinery context detection and output","description":"Update gt prime to detect Refinery role:\n- Detect from directory: refinery/rig/ = Refinery\n- Show handoff bead reference\n- Show merge queue status\n- Show polecat branches with unmerged commits\n- Show last actions summary","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:09.31791-08:00","updated_at":"2025-12-19T18:09:09.31791-08:00","dependencies":[{"issue_id":"gt-bj6f","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.462238-08:00","created_by":"daemon"}]}
{"id":"gt-cjb","title":"Witness updates: Remove issue filing proxy","description":"Update Witness prompting to remove issue filing proxy, since polecats now have direct beads access.\n\n## Remove from Witness Prompting\n\nThe following is NO LONGER Witness responsibility:\n- Processing polecat 'file issue' mail requests\n- Creating issues on behalf of polecats\n- Forwarding issue creation requests\n\n## Add: Legacy Request Handling\n\nIf Witness receives an old-style 'please file issue' request:\n\n1. Respond with update:\n town inject \u003cpolecat\u003e \"UPDATE: You have direct beads access now. Use bd create to file issues yourself.\"\n\n2. Do not file the issue - let the polecat learn the new workflow.\n\n## Keep in Witness Prompting\n\n- Monitoring polecat progress\n- Nudge protocol\n- Pre-kill verification\n- Session lifecycle management","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:47:19.921561-08:00","updated_at":"2025-12-15T20:48:36.020922-08:00","dependencies":[{"issue_id":"gt-cjb","depends_on_id":"gt-l3c","type":"blocks","created_at":"2025-12-15T19:47:35.896691-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.8","title":"CloudRunOutpost: Basic implementation","description":"## Overview\n\nBasic CloudRunOutpost implementation. Persistent connections and cost tracking are separate tasks.\n\n## Implementation\n\n```go\ntype CloudRunOutpost struct {\n name string\n project string\n region string\n service string\n maxWorkers int\n client *WorkClient\n workers map[string]*CloudRunWorker\n mu sync.RWMutex\n}\n\nfunc NewCloudRunOutpost(cfg OutpostConfig) (*CloudRunOutpost, error) {\n serviceURL := fmt.Sprintf(\n \"https://%s-%s.a.run.app\",\n cfg.Service, cfg.Region,\n )\n return \u0026CloudRunOutpost{\n name: cfg.Name,\n project: cfg.Project,\n region: cfg.Region,\n service: cfg.Service,\n maxWorkers: cfg.MaxWorkers,\n client: NewWorkClient(serviceURL),\n workers: make(map[string]*CloudRunWorker),\n }, nil\n}\n```\n\n## Spawn\n\n```go\nfunc (o *CloudRunOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n req := WorkRequest{\n IssueID: issue,\n Rig: RigConfig{URL: cfg.RigURL, Branch: cfg.GitBranch},\n Beads: BeadsConfig{URL: cfg.BeadsURL, Branch: \"beads-sync\"},\n Branch: \"polecat/\" + issue,\n }\n \n events, err := o.client.DispatchWork(context.Background(), req)\n if err != nil {\n return nil, err\n }\n \n worker := \u0026CloudRunWorker{\n id: uuid.New().String(),\n outpost: o.name,\n issue: issue,\n events: events,\n status: WorkerStatusWorking,\n }\n \n o.mu.Lock()\n o.workers[worker.id] = worker\n o.mu.Unlock()\n \n go worker.monitor()\n return worker, nil\n}\n```\n\n## CloudRunWorker\n\n```go\ntype CloudRunWorker struct {\n id string\n outpost string\n issue string\n status WorkerStatus\n events \u003c-chan WorkEvent\n logs []string\n}\n\nfunc (w *CloudRunWorker) Attach() error {\n return errors.New(\"Cloud Run workers do not support attach\")\n}\n\nfunc (w *CloudRunWorker) Logs() (io.Reader, error) {\n return strings.NewReader(strings.Join(w.logs, \"\\n\")), nil\n}\n```\n\n## Files\n\n- `internal/outpost/cloudrun.go`\n\n## Dependencies\n\nDepends on: gt-9a2.1 (interfaces), gt-9a2.12 (HTTP client)\nBlocks: gt-9a2.13 (persistent connections), gt-9a2.14 (cost tracking)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:03:06.803401-08:00","updated_at":"2025-12-16T18:15:39.752892-08:00","dependencies":[{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:03:06.805524-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:46.081721-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.8","depends_on_id":"gt-9a2.12","type":"blocks","created_at":"2025-12-16T18:15:54.915831-08:00","created_by":"daemon"}]}
{"id":"gt-0pl","title":"Polecat CLAUDE.md: configure auto-approve for bd and gt commands","description":"Polecats get stuck waiting for bash command approval when running\nbd and gt commands. Need to configure Claude Code to auto-approve these.\n\nOptions:\n1. Add allowedTools to polecat CLAUDE.md\n2. Configure .claude/settings.json in polecat directory\n3. Use --dangerously-skip-permissions flag (not recommended)\n\nShould auto-approve:\n- bd (beads commands)\n- gt (gastown commands)\n- go build/test\n- git status/add/commit/push\n\nShould still require approval:\n- rm -rf\n- Arbitrary commands outside project\n\nRelated to polecat prompting (gt-e1y, gt-sd6).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T14:10:27.611612-08:00","updated_at":"2025-12-17T14:22:00.715979-08:00","closed_at":"2025-12-17T14:22:00.715979-08:00"}
{"id":"gt-ox9","title":"Test from Mayor","description":"This is a test message via GGT mail","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-16T22:04:31.483843-08:00","updated_at":"2025-12-16T22:06:41.127633-08:00","closed_at":"2025-12-16T22:06:41.127633-08:00"}
{"id":"gt-9mb","title":"Recreate beads rigs with fresh clones","description":"## Problem\n\nBeads rigs have schema mismatches (missing thread_id column, etc.) from development iteration.\n\n## Tasks\n\n1. Shut down any active polecats\n2. Delete existing beads rigs: mayor/rig, refinery/rig, witness/rig, crew/*\n3. Re-clone from beads repo\n4. Run bd init in each new clone\n\n## Rigs to recreate\n\n- /Users/stevey/gt/beads/mayor/rig\n- /Users/stevey/gt/beads/refinery/rig\n- /Users/stevey/gt/beads/crew/* (if any)\n\n## Source\n\nClone from beads repo (need to confirm remote URL)","status":"closed","issue_type":"task","created_at":"2025-12-18T19:13:32.208448-08:00","updated_at":"2025-12-18T19:16:27.096311-08:00","closed_at":"2025-12-18T19:16:27.096311-08:00"}
{"id":"gt-r8ej","title":"Implement pinned beads for handoff state","description":"Add pinned bead support to beads:\n- Pinned beads never close, only update\n- Use for persistent state like Refinery handoffs\n- bd create --pinned flag\n- bd list --pinned to find them\n- Update description to change state","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-19T18:09:08.019293-08:00","updated_at":"2025-12-19T18:09:08.019293-08:00","dependencies":[{"issue_id":"gt-r8ej","depends_on_id":"gt-ktal","type":"blocks","created_at":"2025-12-19T18:09:39.340915-08:00","created_by":"daemon"}]}
{"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-3a4","title":"Add gt decommission command for clean swarm/worker shutdown","description":"Single command to cleanly shut down a swarm and its workers: cancel swarm, stop sessions, optionally remove polecats. E.g. gt decommission gt-hw6 --cleanup","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-18T11:33:37.217682-08:00","updated_at":"2025-12-18T11:38:55.092852-08:00","closed_at":"2025-12-18T11:38:55.092852-08:00"}
{"id":"gt-7lt","title":"gt mail send should tmux-notify recipient","description":"## Problem\n\nWhen mail is sent via gt mail send, the recipient session does not get a tmux notification. In Python Gas Town (PGT), mail delivery triggers a tmux display-message or similar notification so the agent knows mail arrived.\n\n## Expected Behavior\n\nWhen gt mail send \u003caddr\u003e is called:\n1. Mail is delivered to recipient inbox\n2. If recipient has an active tmux session, send notification\n3. Notification should be visible (display-message or bell)\n\n## Current Behavior\n\nMail is delivered but no notification. Agent has to poll inbox to discover new mail.\n\n## Impact\n\n- Agents miss time-sensitive messages\n- Heartbeat pokes from daemon will not wake agents\n- Coordination is slower (polling vs push)\n\n## Implementation Notes\n\nAfter successful mail delivery, check if recipient has active session:\n- gt session list can identify active sessions\n- tmux display-message or send-keys can notify\n- Could inject a visible prompt like \"[MAIL] New message from \u003csender\u003e\"\n\n## Reference\n\nCheck PGT implementation for how it handles this.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T12:28:50.142075-08:00","updated_at":"2025-12-19T12:56:15.204293-08:00","closed_at":"2025-12-18T20:09:53.112902-08:00"}
{"id":"gt-9a2.11","title":"HTTP work server: gt worker serve command","description":"## Overview\n\nHTTP server that runs inside Cloud Run containers, accepting work requests.\n\n## Command\n\n```bash\ngt worker serve --port 8080\n```\n\n## Implementation\n\n```go\ntype WorkServer struct {\n port int\n handler *WorkHandler\n}\n\nfunc (s *WorkServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n switch r.URL.Path {\n case \"/work\":\n s.handleWork(w, r)\n case \"/health\":\n s.handleHealth(w, r)\n default:\n http.NotFound(w, r)\n }\n}\n\nfunc (s *WorkServer) handleWork(w http.ResponseWriter, r *http.Request) {\n // 1. Parse WorkRequest\n // 2. Clone/pull repo\n // 3. Start Claude on issue\n // 4. Stream WorkEvents as NDJSON\n // 5. Return WorkResult\n}\n```\n\n## Streaming Response\n\n```go\nfunc (s *WorkServer) streamEvents(w http.ResponseWriter, events \u003c-chan WorkEvent) {\n flusher, _ := w.(http.Flusher)\n encoder := json.NewEncoder(w)\n for event := range events {\n encoder.Encode(event)\n flusher.Flush()\n }\n}\n```\n\n## Files\n\n- `internal/cloudrun/server.go`\n- `cmd/gt/worker_serve.go` - Cobra command\n\n## Dependencies\n\nDepends on: gt-9a2.7 (protocol types)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:15:00.244823-08:00","updated_at":"2025-12-16T18:15:00.244823-08:00","dependencies":[{"issue_id":"gt-9a2.11","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:15:00.246808-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.11","depends_on_id":"gt-9a2.7","type":"blocks","created_at":"2025-12-16T18:15:10.751351-08:00","created_by":"daemon"}]}
{"id":"gt-ouo","title":"gt swarm start: Does not spawn polecat sessions","description":"gt swarm start marks swarm as 'active' but doesn't start any polecat sessions.\n\nRepro:\n1. gt swarm create gastown --epic gt-hw6 --worker Toast --worker Nux\n2. gt swarm start gt-hw6\n3. gt session list - shows no new sessions\n\nExpected: Polecat sessions should start for each worker.\nActual: No sessions started, workers sit idle.","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:25:43.430981-08:00","updated_at":"2025-12-17T22:31:58.849531-08:00","closed_at":"2025-12-17T22:31:58.849531-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-3zw","title":"Policy beads: config in data plane","description":"Use sentinel/policy beads for configuration instead of external config. Examples: daemon notifications on/off, heartbeat intervals. Config lives in the bead graph, can be toggled by closing/opening policy beads.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-18T18:18:32.857389-08:00","updated_at":"2025-12-18T18:18:32.857389-08:00"}
{"id":"gt-svi","title":"Implement gt mq CLI commands","description":"Add gt mq subcommands as sugar over bd:\n\n- gt mq submit: Create MR for current branch\n- gt mq list: Show open merge requests\n- gt mq next: Show next MR ready to process\n- gt mq process: Engineer processes the queue\n- gt mq reorder \u003cid\u003e --after \u003cx\u003e: Change ordering via deps\n- gt mq status \u003cid\u003e: Show MR details\n\nAll commands should work with the Beads data plane.","status":"closed","issue_type":"task","created_at":"2025-12-16T23:02:16.649648-08:00","updated_at":"2025-12-19T12:56:15.215065-08:00","closed_at":"2025-12-18T20:22:54.684284-08:00","dependencies":[{"issue_id":"gt-svi","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:55.456462-08:00","created_by":"daemon"},{"issue_id":"gt-svi","depends_on_id":"gt-kp2","type":"blocks","created_at":"2025-12-16T23:03:12.689547-08:00","created_by":"daemon"}]}
{"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-19T17:47:03.618858-08:00","closed_at":"2025-12-19T17:47:03.618858-08:00"}
{"id":"gt-svi.5","title":"gt mq reject: manual MR rejection","description":"Implement 'gt mq reject \u003cid\u003e --reason \"...\"' for manual rejection.\n\nActions:\n1. Verify MR exists and is open\n2. Close MR with close_reason=rejected\n3. Notify worker via mail (optional)\n4. Do NOT close source issue (work not done)\n\nOptions:\n- --reason REASON: required explanation\n- --notify: send mail to worker\n\nReference: docs/merge-queue-design.md#cli-commands","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:38.691775-08:00","updated_at":"2025-12-19T12:56:15.217645-08:00","closed_at":"2025-12-18T20:10:46.524526-08:00","dependencies":[{"issue_id":"gt-svi.5","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:38.693749-08:00","created_by":"daemon"}]}
{"id":"gt-9a2.1","title":"Outpost/Worker interfaces: Core abstractions for remote compute","description":"## Overview\n\nDefine the core interfaces that all outpost types implement.\n\n## Interfaces\n\n```go\ntype OutpostType string\nconst (\n OutpostLocal OutpostType = \"local\"\n OutpostSSH OutpostType = \"ssh\"\n OutpostCloudRun OutpostType = \"cloudrun\"\n)\n\ntype Outpost interface {\n Name() string\n Type() OutpostType\n MaxWorkers() int\n ActiveWorkers() int\n Spawn(issue string, config WorkerConfig) (Worker, error)\n Workers() []Worker\n Ping() error\n SendMail(worker string, msg Message) error // optional\n}\n\ntype Worker interface {\n ID() string\n Outpost() string\n Status() WorkerStatus // idle, working, done, failed\n Issue() string\n Attach() error // for interactive outposts\n Logs() (io.Reader, error)\n Stop() error\n}\n\ntype WorkerConfig struct {\n RigPath string\n BeadsDir string\n GitBranch string\n Context map[string]string // hints for worker\n}\n```\n\n## Files\n\n- `internal/outpost/outpost.go` - Outpost interface\n- `internal/outpost/worker.go` - Worker interface\n- `internal/outpost/config.go` - WorkerConfig, OutpostType\n\n## Notes\n\nThis is the foundation for all federation work. Keep interfaces minimal - we can extend later.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:01:38.268086-08:00","updated_at":"2025-12-16T18:01:38.268086-08:00","dependencies":[{"issue_id":"gt-9a2.1","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:01:38.27131-08:00","created_by":"daemon"}]}
{"id":"gt-b3p","title":"Resource Beads: Leases, locks, and quotas","description":"Resource beads represent reserved resources. Types: vm, lock, slot, quota. Fields: holder, expires, renewable. Daemon monitors for expiry and manages contention.","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-18T18:08:12.745602-08:00","updated_at":"2025-12-18T18:08:12.745602-08:00"}
{"id":"gt-9a2.2","title":"LocalOutpost: Refactor current polecat spawning","description":"## Overview\n\nRefactor current local polecat spawning to implement the Outpost interface.\n\n## Current State\n\nPolecat spawning is ad-hoc. This task wraps it in LocalOutpost.\n\n## Implementation\n\n```go\ntype LocalOutpost struct {\n name string\n maxWorkers int\n tmux *Tmux\n workers map[string]*LocalWorker\n}\n\nfunc NewLocalOutpost(config OutpostConfig) *LocalOutpost\n\nfunc (o *LocalOutpost) Type() OutpostType { return OutpostLocal }\n\nfunc (o *LocalOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {\n // Create tmux session\n // Start claude in pane\n // Return LocalWorker\n}\n```\n\n## LocalWorker\n\n```go\ntype LocalWorker struct {\n id string\n session string // tmux session name\n issue string\n status WorkerStatus\n}\n\nfunc (w *LocalWorker) Attach() error {\n // tmux attach-session\n}\n```\n\n## Notes\n\n- This should be a refactor, not new functionality\n- Existing polecat code becomes LocalOutpost internals\n- Tests should pass before and after\n\nDepends on: gt-9a2.1 (interfaces)","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:01:49.551224-08:00","updated_at":"2025-12-16T18:01:49.551224-08:00","dependencies":[{"issue_id":"gt-9a2.2","depends_on_id":"gt-9a2.1","type":"blocks","created_at":"2025-12-16T18:03:45.338172-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.2","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:01:49.553291-08:00","created_by":"daemon"}]}
{"id":"gt-cik.7","title":"gt crew status: Show workspace status","description":"Implement 'gt crew status [\u003cname\u003e]' command:\n- Show session state (running/stopped)\n- Show git status (branch, uncommitted changes, unpushed)\n- Show last commit info\n- Show mail inbox status (unread count)\n- If no name given, show all crew workers","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:48:10.476059-08:00","updated_at":"2025-12-16T20:53:16.70417-08:00","closed_at":"2025-12-16T20:53:16.70417-08:00","dependencies":[{"issue_id":"gt-cik.7","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:10.477638-08:00","created_by":"daemon"}]}
{"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-3x1.5","title":"Success handling: close MR, close source issue, cleanup","description":"Handle successful merge completion.\n\nSteps:\n1. Update MR with merge_commit SHA:\n bd update \u003cid\u003e --body='...\\nmerge_commit: \u003csha\u003e'\n2. Close MR with reason:\n bd close \u003cid\u003e --reason='merged'\n3. Close source issue (the work item):\n bd close \u003csource_issue\u003e --reason='Merged in \u003cmr_id\u003e'\n4. Delete source branch (if configured):\n git push origin --delete \u003cmr.branch\u003e\n5. Log success\n\nConfiguration:\n- delete_merged_branches: bool (default true)\n\nReference: docs/merge-queue-design.md#process-merge-steps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:19.054425-08:00","updated_at":"2025-12-19T15:27:45.508755-08:00","closed_at":"2025-12-19T14:47:47.062475-08:00","dependencies":[{"issue_id":"gt-3x1.5","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:51:19.056461-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.5","depends_on_id":"gt-3x1.3","type":"blocks","created_at":"2025-12-17T13:53:10.398758-08:00","created_by":"daemon"}]}
{"id":"gt-6tf","title":"Implement gt harness create command","description":"Add scaffolding command to create a new harness:\n- gt harness create [path]\n- Creates config/, mayor/, .beads/redirect (optional)\n- Optionally initializes git\n- Generates CLAUDE.md with Mayor role\n- Could also offer a template repo alternative","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T17:15:34.342552-08:00","updated_at":"2025-12-17T17:20:36.774805-08:00","closed_at":"2025-12-17T17:20:36.774805-08:00","dependencies":[{"issue_id":"gt-6tf","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:51.845578-08:00","created_by":"daemon"}]}
{"id":"gt-6k8","title":"Interrupt vs Queue mail semantics","description":"Add priority/delivery semantics to mail messages.\n\n## Semantics\n\n| Type | Delivery | Use Case |\n|------|----------|----------|\n| Interrupt | tmux send-keys | Lifecycle, URGENT, stuck detection |\n| Queue | Create message only | Normal mail, status, heartbeat |\n\n## Implementation\n\n- `bd mail send --interrupt` uses tmux send-keys notification\n- Default is queue (agent checks with `gt mail check`)\n- Urgent flag on messages for interrupt delivery\n\n## Agent Side\n\n- `gt mail check --quiet` - non-blocking check for queued mail\n- `gt mail wait` - block until mail arrives (for idle agents)\n- Heartbeats become queued, agent checks at natural breakpoints","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:28.408196-08:00","updated_at":"2025-12-19T17:22:52.555329-08:00","closed_at":"2025-12-19T16:31:00.450061-08:00","dependencies":[{"issue_id":"gt-6k8","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T14:19:46.529252-08:00","created_by":"daemon"}]}
{"id":"gt-avq9","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:18.575204-08:00","updated_at":"2025-12-19T18:26:14.100966-08:00","closed_at":"2025-12-19T18:26:14.10097-08:00"}
{"id":"gt-1cuq","title":"Merge: gt-svi.1","description":"type: merge-request\nbranch: polecat/Max\ntarget: main\nsource_issue: gt-svi.1\nrig: gastown","status":"closed","issue_type":"task","created_at":"2025-12-18T20:15:31.738938-08:00","updated_at":"2025-12-18T20:15:49.759778-08:00","closed_at":"2025-12-18T20:15:49.759778-08:00"}
{"id":"gt-y5o","title":"Daemon: verify requesting_cycle before kill","description":"Per gt-gby spec, daemon should verify agent state shows requesting_cycle=true before killing session. Currently kills on any lifecycle request without verification.\n\nRequires state.json in agent workspace with requesting_cycle field.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:13.049988-08:00","updated_at":"2025-12-19T17:22:52.55078-08:00","closed_at":"2025-12-19T16:28:41.779271-08:00","dependencies":[{"issue_id":"gt-y5o","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.590883-08:00","created_by":"daemon"}]}
{"id":"gt-1fl","title":"gt crew restart command","description":"Add a 'gt crew restart' command that kills the tmux session and restarts fresh. Useful when a crew member gets confused or needs a clean slate.\n\nShould:\n- Kill existing tmux session if running\n- Start fresh session with claude\n- Run gt prime to reinitialize context\n\nAlias: gt crew rs","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T19:47:32.131386-08:00","updated_at":"2025-12-19T12:56:15.195247-08:00","closed_at":"2025-12-19T12:07:06.762207-08:00"}
{"id":"gt-5tp","title":"Test message","description":"Testing GGT mail via beads","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-16T21:44:27.546781-08:00","updated_at":"2025-12-16T21:45:11.465745-08:00","closed_at":"2025-12-16T21:45:11.465745-08:00"}
{"id":"gt-eqys","title":"gt spawn: pasted work assignment needs manual Enter to start","description":"## Problem\n\nAfter `gt spawn` pastes the work assignment into Claude, the session waits for Enter.\n\n## Current Behavior\n\n1. `gt spawn gastown/Rictus --issue gt-xxx`\n2. Session starts, work is pasted\n3. Claude shows 'Pasted text #1 +53 lines' but doesn't start\n4. Must manually send Enter or attach and press Enter\n\n## Expected\n\nThe spawn should send Enter after pasting to kick off the work.\n\n## Related\n\nSame debounce issue as tmux notifications (gt-vnp9).","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:54:14.111101-08:00","updated_at":"2025-12-19T12:01:32.74364-08:00","closed_at":"2025-12-19T12:01:32.74364-08:00"}
{"id":"gt-kmn.8","title":"Git safety audit module","description":"Port git_audit.py safety checks to Go.\n\n## Purpose\n\nBefore destroying polecat clones, verify no code is at risk.\n\n## Checks\n\n1. Uncommitted changes (staged and unstaged)\n2. Unpushed commits\n3. Git stashes\n4. Local-only branches (not tracking remote)\n\n## Beads-Only Classification\n\nSome files are safe to discard:\n- .beads/*\n- .claude/settings.json\n\nChanges only affecting these = \"beads-only\" = safe to destroy.\n\n## Interface\n\n```go\ntype GitAuditResult struct {\n Polecat string\n Path string\n UncommittedFiles []string\n UncommittedIsBeadsOnly bool\n UnpushedCommits int\n Stashes []StashInfo\n StashesAreBeadsOnly bool\n LocalBranches []string\n Error error\n}\n\nfunc (r *GitAuditResult) HasCodeAtRisk() bool\n\nfunc AuditPolecat(name string, path string) *GitAuditResult\nfunc AuditPolecats(polecats []PolecatInfo) []*GitAuditResult\n```\n\n## Reference\n\nPGT: swarm/git_audit.py","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-16T00:10:19.52029-08:00","updated_at":"2025-12-16T00:10:19.52029-08:00","dependencies":[{"issue_id":"gt-kmn.8","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-16T00:11:29.174184-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.8","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:10:19.520646-08:00","created_by":"daemon"}]}
{"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-hgk","title":"Mail system: message types and threading","description":"GGT mail system needs message types and threading like PGT.\n\n## 1. Message Types\nAdd to internal/mail/types.go:\n```go\ntype MessageType string\nconst (\n TypeTask MessageType = \"task\" // Required processing\n TypeScavenge MessageType = \"scavenge\" // Optional first-come work\n TypeNotification MessageType = \"notification\" // Informational\n TypeReply MessageType = \"reply\" // Response to message\n)\n\n// Update Message struct\ntype Message struct {\n // existing fields...\n Type MessageType `json:\"type\"`\n ThreadID string `json:\"thread_id,omitempty\"`\n ReplyTo string `json:\"reply_to,omitempty\"`\n}\n```\n\n## 2. Priority Levels\nExpand from 2 to 4:\n```go\ntype Priority string\nconst (\n PriorityLow Priority = \"low\"\n PriorityNormal Priority = \"normal\"\n PriorityHigh Priority = \"high\"\n PriorityUrgent Priority = \"urgent\"\n)\n```\n\n## 3. CLI Updates\ninternal/cmd/mail.go:\n- Add --type flag to send: `gt mail send ... --type task`\n- Add --reply-to flag: `gt mail send ... --reply-to \u003cmsg-id\u003e`\n- Add thread command: `gt mail thread \u003cthread-id\u003e`\n\n## 4. Threading Logic\nNewMessage() should auto-generate thread_id if not a reply.\nReply messages inherit thread_id from original.\n\n## Files to Modify\n- internal/mail/types.go: Add types, expand Priority\n- internal/mail/mailbox.go: Thread filtering\n- internal/cmd/mail.go: CLI flags and thread command\n\n## PGT Reference\ngastown-py/src/gastown/mail/message.py\n\n## Acceptance Criteria\n- [ ] Messages have type field (default: notification)\n- [ ] 4 priority levels supported\n- [ ] Reply creates thread with shared thread_id\n- [ ] gt mail thread \u003cid\u003e shows conversation","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:55.29463-08:00","updated_at":"2025-12-19T12:56:15.211543-08:00","closed_at":"2025-12-18T20:14:28.308997-08:00"}
{"id":"gt-17zr","title":"gt refinery start: doesn't actually start a session","description":"## Problem\n\n`gt refinery start gastown` reports success but doesn't start a tmux session.\n\n## Evidence\n\n```\n$ gt refinery start gastown\nStarting refinery for gastown...\n✓ Refinery started for gastown\n\n$ tmux list-sessions | grep refinery\n(nothing)\n\n$ gt refinery status gastown\nState: ○ stopped\n```\n\n## Expected\n\nShould start a tmux session (e.g., gt-gastown-refinery) with Claude processing the merge queue.\n\n## Related\n\n- gt-kcee: Witness commands also need implementation\n- The refinery 'start' may just be updating state.json without spawning a session","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:58:57.188389-08:00","updated_at":"2025-12-19T01:33:49.858934-08:00","closed_at":"2025-12-19T01:33:49.858934-08:00"}
{"id":"gt-vnp9","title":"tmux notifications: display-message too subtle, use send-keys instead","description":"## Problem\n\n`tmux display-message` notifications are not visible enough - they appear briefly in the status bar and are easy to miss.\n\n## Current Behavior\n\nrouter.go uses:\n```go\nr.tmux.DisplayMessageDefault(sessionID, notification)\n```\n\n## What Works\n\nSending echo commands directly to the terminal:\n```bash\ntmux send-keys -t \u003csession\u003e \"echo '📬 NEW MAIL from mayor'\" Enter\n```\n\n## Proposed Fix\n\nChange notification method to send visible output to the terminal, perhaps with a box/banner:\n```\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n📬 NEW MAIL from mayor\nSubject: \u003csubject\u003e\nRun: bd mail inbox\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n```\n\n## Considerations\n\n- This interrupts the terminal output (acceptable for important mail)\n- Could check if Claude is mid-response and queue notification\n- Or use tmux popup if available","notes":"Additional issues:\n1. Enter key not sent properly when chained with send-keys\n2. Need to debounce and send Enter separately\n3. Correct pattern: send text, sleep briefly, then send Enter","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-18T21:35:28.542985-08:00","updated_at":"2025-12-19T12:00:29.342381-08:00","closed_at":"2025-12-19T12:00:29.342381-08:00"}
{"id":"gt-svi.2","title":"gt mq list: show queue with status/priority/age","description":"Implement 'gt mq list' command to display the merge queue.\n\nOutput format:\nID STATUS PRIORITY BRANCH WORKER AGE\ngt-mr-001 ready P0 polecat/Nux/gt-xyz Nux 5m\ngt-mr-002 in_progress P1 polecat/Toast/gt-abc Toast 12m\ngt-mr-003 blocked P1 polecat/Capable/gt-def Capable 8m\n (waiting on gt-mr-001)\n\nOptions:\n- --ready: show only ready-to-merge (no blockers, not in progress)\n- --status STATUS: filter by status\n- --worker WORKER: filter by worker\n- --epic EPIC: show MRs targeting integration/EPIC\n\nUnder the hood: bd list --type=merge-request with filters.\n\nReference: docs/merge-queue-design.md#gt-mq-list","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:23.295587-08:00","updated_at":"2025-12-19T12:56:15.215956-08:00","closed_at":"2025-12-18T20:22:41.489063-08:00","dependencies":[{"issue_id":"gt-svi.2","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:23.297307-08:00","created_by":"daemon"},{"issue_id":"gt-svi.2","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.560128-08:00","created_by":"daemon"}]}
{"id":"gt-w5dj","title":"Merge: gt-unrd","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-unrd\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T15:42:06.600633-08:00","updated_at":"2025-12-19T18:26:14.106188-08:00","closed_at":"2025-12-19T17:48:09.590076-08:00"}
{"id":"gt-n508","title":"Merge: gt-70b3","description":"type: merge-request\nbranch: polecat/Rictus\ntarget: main\nsource_issue: gt-70b3\nrig: gastown","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T21:56:57.840796-08:00","updated_at":"2025-12-18T22:16:39.940524-08:00","closed_at":"2025-12-18T22:16:39.940524-08:00"}
{"id":"gt-cik.5","title":"gt crew refresh: Context cycling with handoff","description":"Implement 'gt crew refresh \u003cname\u003e' command:\n- Send handoff mail to self (context summary)\n- Kill current session cleanly\n- Start new session\n- New session reads handoff mail and resumes\n- Support --message to add custom handoff notes","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:06.934819-08:00","updated_at":"2025-12-16T20:53:16.685494-08:00","closed_at":"2025-12-16T20:53:16.685494-08:00","dependencies":[{"issue_id":"gt-cik.5","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:06.936381-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.8","title":"MQ config schema: merge_queue section in rig config.json","description":"Define and implement merge_queue configuration in rig config.\n\nSchema:\n{\n \"merge_queue\": {\n \"enabled\": true,\n \"target_branch\": \"main\",\n \"integration_branches\": true,\n \"on_conflict\": \"assign_back\", // or \"auto_rebase\"\n \"run_tests\": true,\n \"test_command\": \"go test ./...\",\n \"delete_merged_branches\": true,\n \"retry_flaky_tests\": 1,\n \"poll_interval\": \"30s\",\n \"max_concurrent\": 1\n }\n}\n\nImplement:\n- Config loading in rig package\n- Default values\n- Validation\n\nReference: docs/merge-queue-design.md#configuration","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:52:00.322779-08:00","updated_at":"2025-12-19T12:56:15.211099-08:00","closed_at":"2025-12-19T01:33:49.864359-08:00","dependencies":[{"issue_id":"gt-h5n.8","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:52:00.324781-08:00","created_by":"daemon"}]}
{"id":"gt-yx4","title":"Town root .beads has schema mismatch with bd","description":"The .beads directory at town root (/Users/stevey/gt/.beads) has an incompatible schema:\n\n```\nError: failed to open database: failed to initialize schema: sqlite3: SQL logic error: no such column: thread_id\n```\n\nMeanwhile, gastown/.beads (symlinked to mayor/rig/.beads) works fine.\n\n## Impact\n\n- gt mail inbox fails at town root\n- gt handoff sends mail to broken db\n- Daemon can't check its inbox\n\n## Options\n\n1. Delete town root .beads/beads.db and let it recreate\n2. Symlink town root .beads to gastown/.beads\n3. Run schema migration on existing db\n\n## Root Cause\n\nLikely a beads version upgrade that added thread_id column, but the town root db was created before that.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T14:31:35.559042-08:00","updated_at":"2025-12-19T12:56:15.218062-08:00","closed_at":"2025-12-19T00:39:32.211083-08:00"}
{"id":"gt-f8v","title":"Witness pre-kill verification protocol","description":"Add pre-kill verification protocol to Witness CLAUDE.md template.\n\n## Protocol for Witness Prompting\n\n```markdown\n## Pre-Kill Verification Protocol\n\nBefore killing any worker session, verify workspace is clean.\n\n### Verification Steps\n\nWhen a worker signals done:\n\n1. **Capture worker state**:\n```bash\ntown capture \u003cpolecat\u003e \"git status \u0026\u0026 git stash list \u0026\u0026 bd sync --status\"\n```\n\n2. **Assess the output** (use your judgment):\n- Is working tree clean?\n- Is stash list empty?\n- Is beads synced?\n\n3. **Decision**:\n- **CLEAN**: Proceed to kill session\n- **DIRTY**: Send nudge with specific issues\n\n### Nudge Templates\n\n**Uncommitted Changes**:\n```\ntown inject \u003cpolecat\u003e \"WITNESS CHECK: Uncommitted changes found. Please commit or discard: \u003cfiles\u003e. Signal done when clean.\"\n```\n\n**Beads Not Synced**:\n```\ntown inject \u003cpolecat\u003e \"WITNESS CHECK: Beads not synced. Run 'bd sync' then commit. Signal done when complete.\"\n```\n\n### Kill Sequence\n\nOnly after verification passes:\n```bash\ntown kill \u003cpolecat\u003e\ntown sleep \u003cpolecat\u003e\n```\n\n### Escalation\n\nIf worker fails verification 3+ times:\n```bash\ntown mail send mayor/ -s \"Escalation: \u003cpolecat\u003e stuck\" -m \"Cannot complete cleanup after 3 attempts. Issues: \u003clist\u003e.\"\n```\n```\n\n## Implementation\n\nAdd to WITNESS_CLAUDE.md template.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:54.065679-08:00","updated_at":"2025-12-15T20:47:30.415244-08:00","dependencies":[{"issue_id":"gt-f8v","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.763378-08:00","created_by":"daemon"}]}
{"id":"gt-f9x.3","title":"gt install command: Create workspace structure","description":"Create Gas Town workspace structure.\n\n## Command\n\n```\ngt install [path]\n```\n\nIf path omitted, uses current directory.\n\n## Created Structure\n\n```\n\u003cpath\u003e/\n├── config/\n│ ├── town.json # {\"type\": \"town\", \"version\": 1, ...}\n│ └── rigs.json # {\"version\": 1, \"rigs\": {}}\n│\n└── mayor/\n ├── CLAUDE.md # Mayor role prompting (from template)\n ├── mail/\n │ └── inbox.jsonl # Empty inbox\n └── state.json # Initial mayor state\n```\n\n## Implementation\n\n```go\nfunc Install(path string, opts InstallOptions) error\n\ntype InstallOptions struct {\n TownName string // defaults to directory name\n Force bool // overwrite existing\n}\n```\n\n## Steps\n\n1. Validate path (exists, writable)\n2. Check not already a town (unless --force)\n3. Create config/ directory\n4. Write town.json with name and timestamp\n5. Write empty rigs.json\n6. Create mayor/ directory structure\n7. Write CLAUDE.md from template\n8. Create empty inbox.jsonl\n9. Write initial state.json\n\n## Error Cases\n\n- Path does not exist: Create it (like mkdir -p)\n- Already a town: Error unless --force\n- Permission denied: Clear error message\n- Inside existing town: Warn (nested towns not recommended)\n\n## Templates\n\nMayor CLAUDE.md comes from embedded template (see gt-u1j.20).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T16:36:53.455589-08:00","updated_at":"2025-12-17T17:20:04.66874-08:00","closed_at":"2025-12-17T17:20:04.66874-08:00","dependencies":[{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T16:37:32.513796-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x.2","type":"blocks","created_at":"2025-12-15T16:37:32.597456-08:00","created_by":"daemon"},{"issue_id":"gt-f9x.3","depends_on_id":"gt-f9x","type":"parent-child","created_at":"2025-12-15T16:36:53.455924-08:00","created_by":"daemon"}]}
{"id":"gt-tulx","title":"gt mq submit: creates task type instead of merge-request type","description":"## Problem\n\n`gt mq submit` creates an issue with `type: task` but should be `type: merge-request`.\n\n## Evidence\n\n```\n$ bd show gt-n508\ngt-n508: Merge: gt-70b3\nStatus: open\nPriority: P1\nType: task \u003c-- WRONG, should be merge-request\n...\nDescription:\ntype: merge-request \u003c-- Correct type is in description, not in actual type field\n```\n\n## Impact\n\n`gt mq list` shows empty queue because it queries for `type: merge-request`\n\n## Fix\n\n`gt mq submit` should set `--type merge-request` when creating the bead.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:57:37.905848-08:00","updated_at":"2025-12-18T22:16:31.393114-08:00","closed_at":"2025-12-18T22:16:31.393114-08:00"}
{"id":"gt-3tz","title":"CLI: polecat commands (add, list, wake, sleep, decommission)","description":"GGT is missing most polecat management commands that PGT has.\n\nMissing Commands:\n- gt polecat add \u003crig\u003e \u003cname\u003e - Add polecat to rig (creates clone)\n- gt polecat list [\u003crig\u003e] - List polecats with state\n- gt polecat info \u003cpolecat\u003e - Show detailed info\n- gt polecat wake \u003cpolecat\u003e - Mark available\n- gt polecat sleep \u003cpolecat\u003e - Mark unavailable \n- gt polecat decommission \u003cpolecat\u003e - Remove polecat safely\n\nPGT Reference: gastown-py/src/gastown/cli/polecat_cmd.py\n\nNotes:\n- spawn exists but doesn't cover management\n- wake/sleep are in polecat manager but not CLI\n- decommission should check for uncommitted work","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T14:46:31.326692-08:00","updated_at":"2025-12-16T16:03:14.462338-08:00","closed_at":"2025-12-16T16:03:14.462338-08:00"}
{"id":"gt-4my","title":"Doctor check: Worker health and stuck detection","description":"Detect and report stuck workers via gt doctor.\n\n## Checks\n\n### WorkerHealthCheck\n- List all active workers (polecats with state=working)\n- Check last activity timestamp for each\n- Flag as potentially stuck if no progress for configurable threshold (default: 30 min)\n- Check if Witness is running for the rig\n- Verify Witness last heartbeat time\n\n### Stuck Detection Criteria\n- Polecat state=working but session not running\n- Polecat state=working but output unchanged for threshold\n- Witness not responding to health checks\n- Multiple polecats in same rig all stuck\n\n## Output\n\n```\n[WARN] Workers in rig 'wyvern' may be stuck:\n - Toast: working for 45m, no recent output\n - Capable: working for 52m, session not found\n - Witness: last heartbeat 20m ago\n \n Suggestions:\n - gt witness status wyvern\n - gt capture wyvern/Toast 50\n - gt stop --rig wyvern (kill all)\n```\n\n## Auto-Fix\n\nCannot auto-fix stuck workers (risk of data loss), but can:\n- Restart Witness daemon if crashed\n- Send warning mail to Mayor","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T23:17:59.265062-08:00","updated_at":"2025-12-16T17:24:34.882466-08:00","dependencies":[{"issue_id":"gt-4my","depends_on_id":"gt-f9x.4","type":"blocks","created_at":"2025-12-15T23:19:05.565606-08:00","created_by":"daemon"},{"issue_id":"gt-4my","depends_on_id":"gt-7ik","type":"blocks","created_at":"2025-12-17T15:44:42.068149-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.9","title":"Witness daemon: heartbeat loop, spawn ephemeral agent","description":"Background daemon for agent lifecycle and monitoring.\n\n## Core Responsibilities\n\n1. **Heartbeat monitoring**: Check agent health periodically\n2. **Session lifecycle**: Restart agents after handoff (Witness Protection)\n3. **Polecat monitoring**: Track worker progress, nudging\n4. **Escalation**: Report failures to Mayor\n\n## Session Lifecycle (Witness Protection)\n\nThe daemon enables autonomous long-running operation by cycling agent sessions:\n\n```go\ntype SessionLifecycle struct {\n AgentType string // \"witness\", \"refinery\"\n StatePath string // path to state.json\n}\n\nfunc (d *Daemon) monitorSessionLifecycle(agent SessionLifecycle) {\n // 1. Detect session exit\n // 2. Check state.json for requesting_cycle: true\n // 3. If cycle requested: start new session, clear flag\n // 4. If unexpected exit: escalate to Mayor\n}\n```\n\nSee architecture.md Key Decision #12: Agent Session Lifecycle.\n\n## Interface\n\n```go\ntype Daemon struct {\n rig *Rig\n polecats *PolecatManager\n sessions *SessionManager\n config DaemonConfig\n}\n\ntype DaemonConfig struct {\n HeartbeatInterval time.Duration // default: 30s\n NudgeThreshold int // nudges before escalation\n MaxWorkers int // from rig config\n}\n\nfunc NewDaemon(rig *Rig) *Daemon\nfunc (d *Daemon) Start() error\nfunc (d *Daemon) Stop() error\n\n// Lifecycle\nfunc (d *Daemon) CycleSession(agentType string) error\nfunc (d *Daemon) SpawnWorker(issueID string) error\nfunc (d *Daemon) ShutdownWorker(polecat string) error\n```\n\n## Heartbeat Loop\n\nEvery HeartbeatInterval:\n1. Check Witness session (restart if cycle requested)\n2. Check Refinery session (restart if cycle requested)\n3. For each active polecat: assess progress, nudge if stuck\n4. Query `bd ready` for new work, spawn up to max_workers","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T17:12:29.389103-08:00","updated_at":"2025-12-18T12:38:32.125316-08:00","closed_at":"2025-12-18T11:50:12.047959-08:00","dependencies":[{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T17:14:04.353775-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j.8","type":"blocks","created_at":"2025-12-15T17:14:04.440363-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.9","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:29.389428-08:00","created_by":"daemon"}]}
{"id":"gt-h5n","title":"Merge Queue in Beads: Universal chit system for all work","description":"\n\n**Design doc**: docs/merge-queue-design.md","status":"open","issue_type":"epic","created_at":"2025-12-16T23:01:45.782171-08:00","updated_at":"2025-12-17T13:43:43.211867-08:00"}
{"id":"gt-u1j.11","title":"CLI: session commands (start, stop, at, list, capture, inject)","description":"Session management CLI commands.\n\n## Commands\n\n### gt session start\nStart a polecat session.\n```\ngt session start \u003crig\u003e/\u003cpolecat\u003e [--issue \u003cid\u003e]\n```\n- Creates tmux session\n- Launches claude in polecat workdir\n- Optionally injects initial issue context\n\n### gt session stop\nStop a polecat session.\n```\ngt session stop \u003crig\u003e/\u003cpolecat\u003e [--force]\n```\n- Graceful shutdown by default\n- --force kills immediately\n\n### gt session at (attach)\nAttach to running session.\n```\ngt session at \u003crig\u003e/\u003cpolecat\u003e\n```\n- Attaches tmux session to current terminal\n- Detach with Ctrl-B D\n\n### gt session list\nList all sessions.\n```\ngt session list [--rig \u003crig\u003e] [--json]\n```\n- Shows running/stopped status\n- Optionally filter by rig\n\n### gt session capture\nCapture recent output from session.\n```\ngt session capture \u003crig\u003e/\u003cpolecat\u003e [--lines \u003cn\u003e]\n```\n- Default: last 100 lines\n- Useful for checking polecat progress\n\n### gt session inject\nSend message to session.\n```\ngt session inject \u003crig\u003e/\u003cpolecat\u003e -m \"message\"\ngt session inject \u003crig\u003e/\u003cpolecat\u003e -f \u003cfile\u003e\n```\n- Injects text via tmux send-keys\n- Used for nudges, notifications\n\n## Address Format\n\n`\u003crig\u003e/\u003cpolecat\u003e` e.g., `wyvern/Toast`\n\n## Implementation\n\nSession subcommand group:\n```go\nvar sessionCmd = \u0026cobra.Command{Use: \"session\"}\nsessionCmd.AddCommand(startCmd, stopCmd, atCmd, listCmd, captureCmd, injectCmd)\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:40.70671-08:00","updated_at":"2025-12-16T13:51:44.7613-08:00","closed_at":"2025-12-16T13:51:44.7613-08:00","dependencies":[{"issue_id":"gt-u1j.11","depends_on_id":"gt-u1j.7","type":"blocks","created_at":"2025-12-15T17:14:06.23195-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.11","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:40.707072-08:00","created_by":"daemon"}]}
{"id":"gt-4nn","title":"Molecules: Composable Workflow Beads","description":"## Summary\n\nMolecules are crystallized workflow patterns stored as Beads issues.\nWhen instantiated, the molecule creates child beads forming a DAG.\n\n## Key Insight: Molecules ARE Beads\n\nPer HOP Decision 001: Beads IS the ledger. Molecules don't get a separate YAML format - they're issues with `type: molecule` containing prose-based step definitions.\n\nAgents don't need rigid schemas. They parse natural language natively. A molecule is just instructions with enough structure for tooling.\n\n## Example: Engineer in a Box\n\n```markdown\nid: mol-xyz\ntype: molecule\ntitle: Engineer in a Box\n\nThis workflow takes a task from design to merge.\n\n## Step: design\nThink carefully about architecture. Consider existing patterns, \ntrade-offs, testability.\n\n## Step: implement\nWrite clean code. Follow codebase conventions.\nNeeds: design\n\n## Step: review \nReview for bugs, edge cases, style issues.\nNeeds: implement\n\n## Step: test\nWrite and run tests. Cover happy path and edge cases.\nNeeds: implement\n\n## Step: submit\nSubmit for merge via refinery.\nNeeds: review, test\n```\n\n## Instantiation\n\n```bash\n# Attach molecule when spawning\ngt spawn --issue gt-abc --molecule mol-xyz\n\n# Creates child beads atomically:\ngt-abc.design ← ready first\ngt-abc.implement ← blocked by design \ngt-abc.review ← blocked by implement\ngt-abc.test ← blocked by implement\ngt-abc.submit ← blocked by review, test\n```\n\nEach step issue gets an `instantiated-from` edge to the molecule (with step metadata).\n\n## Why This Matters\n\n1. **Unified data plane**: Everything in Beads, no parallel YAML channel\n2. **AI-native**: Prose instructions, not rigid schemas\n3. **Error isolation**: Each step is a checkpoint - failure doesn't lose progress\n4. **Scales with AI**: As agents get smarter, they handle more complex molecules\n\n## Implementation Primitives\n\n- `ParseMoleculeSteps()`: Extract steps from prose (convention-based)\n- `InstantiateMolecule()`: Atomic transaction creating all steps + edges \n- `instantiated-from` edge type: Track provenance\n- Parameterization: `{{variable}}` substitution from context map","status":"closed","issue_type":"epic","created_at":"2025-12-18T18:06:24.573068-08:00","updated_at":"2025-12-19T15:06:22.393412-08:00","closed_at":"2025-12-19T14:44:59.705427-08:00"}
{"id":"gt-zko","title":"gt rig info: Show detailed rig information","description":"Add 'gt rig info \u003crig\u003e' command to show detailed rig status.\n\nShould show:\n- Rig path and git URL\n- Active polecats with status\n- Refinery status\n- Witness status\n- Recent activity\n- Beads summary (open issues count)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T21:47:17.879255-08:00","updated_at":"2025-12-17T22:29:46.970197-08:00","closed_at":"2025-12-17T22:29:46.970197-08:00","dependencies":[{"issue_id":"gt-zko","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:22:47.502099-08:00","created_by":"daemon"}]}
{"id":"gt-u1j","title":"Port Gas Town to Go","description":"Complete rewrite of Gas Town in Go for improved performance and single-binary distribution.\n\n## Goals\n- Single installable binary (gt)\n- All Python functionality ported\n- Federation support built-in\n- Improved performance\n\n## Phases\n1. Core infrastructure (config, workspace, git wrapper)\n2. Rig \u0026 polecat management\n3. Session \u0026 tmux operations\n4. Mail system\n5. CLI commands\n6. TUI (optional)","status":"open","issue_type":"epic","created_at":"2025-12-15T16:36:28.769343-08:00","updated_at":"2025-12-15T16:36:28.769343-08:00"}
{"id":"gt-6z2.2","title":"Test Task 2: Add comment to version.go","status":"closed","issue_type":"task","created_at":"2025-12-16T21:57:43.693217-08:00","updated_at":"2025-12-16T22:06:41.127126-08:00","closed_at":"2025-12-16T22:06:41.127126-08:00","dependencies":[{"issue_id":"gt-6z2.2","depends_on_id":"gt-6z2","type":"parent-child","created_at":"2025-12-16T21:57:43.69361-08:00","created_by":"daemon"}]}
{"id":"gt-selw","title":"gt spawn: add --polecat flag for explicit worker selection","description":"Currently gt spawn requires positional arg format:\n```\ngt spawn gastown/Angharad --issue gt-xyz\n```\n\nBut I tried the more intuitive flag form:\n```\ngt spawn --issue gt-xyz --polecat Angharad\n```\n\nThis failed with 'unknown flag: --polecat'.\n\nThe flag form is more discoverable and consistent with other commands. Add --polecat flag as alternative to positional arg.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T01:41:38.540563-08:00","updated_at":"2025-12-19T01:57:17.0307-08:00","closed_at":"2025-12-19T01:57:17.0307-08:00"}
{"id":"gt-4nn.4","title":"Built-in molecules: engineer-in-box, quick-fix, research","description":"Create built-in molecules as Beads issues:\n\n## engineer-in-box\n\n```markdown\nid: mol-engineer-in-box\ntype: molecule\ntitle: Engineer in a Box\n\nFull workflow from design to merge.\n\n## Step: design\nThink carefully about architecture. Consider:\n- Existing patterns in the codebase\n- Trade-offs between approaches \n- Testability and maintainability\n\nWrite a brief design summary before proceeding.\n\n## Step: implement\nWrite the code. Follow codebase conventions.\nNeeds: design\n\n## Step: review\nSelf-review the changes. Look for:\n- Bugs and edge cases\n- Style issues\n- Missing error handling\nNeeds: implement\n\n## Step: test\nWrite and run tests. Cover happy path and edge cases.\nFix any failures before proceeding.\nNeeds: implement\n\n## Step: submit\nSubmit for merge via refinery.\nNeeds: review, test\n```\n\n## quick-fix\n\n```markdown\nid: mol-quick-fix\ntype: molecule \ntitle: Quick Fix\n\nFast path for small changes.\n\n## Step: implement\nMake the fix. Keep it focused.\n\n## Step: test\nRun relevant tests. Fix any regressions.\nNeeds: implement\n\n## Step: submit\nSubmit for merge.\nNeeds: test\n```\n\n## research\n\n```markdown\nid: mol-research\ntype: molecule\ntitle: Research\n\nInvestigation workflow.\n\n## Step: investigate\nExplore the question. Search code, read docs, \nunderstand context. Take notes.\n\n## Step: document\nWrite up findings. Include:\n- What you learned\n- Recommendations\n- Open questions\nNeeds: investigate\n```\n\n## Storage\n\nBuilt-in molecules live in `\u003ctown\u003e/.beads/` as regular issues.\nCreated during `gt install` or `bd init`.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T18:07:04.574565-08:00","updated_at":"2025-12-19T12:56:15.201354-08:00","closed_at":"2025-12-19T12:02:19.332406-08:00","dependencies":[{"issue_id":"gt-4nn.4","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:07:04.576587-08:00","created_by":"daemon"}]}
{"id":"gt-92l","title":"Daemon: integration test with real lifecycle","description":"Need an end-to-end test that:\n1. Starts daemon\n2. Starts a test agent session\n3. Sends lifecycle request to daemon\n4. Verifies session was killed and restarted\n5. Cleans up\n\nCould use a mock 'agent' that's just a shell script.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T13:38:17.261096-08:00","updated_at":"2025-12-19T17:22:52.555739-08:00","closed_at":"2025-12-19T16:31:23.543204-08:00","dependencies":[{"issue_id":"gt-92l","depends_on_id":"gt-99m","type":"blocks","created_at":"2025-12-18T13:38:26.962642-08:00","created_by":"daemon"}]}
{"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-vci","title":"Mayor handoff mail template","description":"Add MAYOR_HANDOFF mail template to templates.py.\n\n## Template Function\n\ndef mayor_handoff(\n active_swarms: List[SwarmStatus],\n rig_status: Dict[str, RigStatus],\n pending_escalations: List[Escalation],\n in_flight_decisions: List[Decision],\n recent_actions: List[str],\n delegated_work: List[DelegatedItem],\n user_requests: List[str],\n next_steps: List[str],\n warnings: Optional[str] = None,\n session_duration: Optional[str] = None,\n) -\u003e Message:\n metadata = {\n 'template': 'MAYOR_HANDOFF',\n 'timestamp': datetime.utcnow().isoformat(),\n 'session_duration': session_duration,\n 'active_swarm_count': len(active_swarms),\n 'pending_escalation_count': len(pending_escalations),\n }\n # ... format sections ...\n return Message.create(\n sender='mayor/',\n recipient='mayor/',\n subject='Session Handoff',\n body=body,\n priority='high',\n )\n\n## Metadata Fields\n\n- template: MAYOR_HANDOFF\n- timestamp: ISO format\n- session_duration: Human readable\n- active_swarm_count: Number of active swarms\n- pending_escalation_count: Number of escalations\n\n## Mail Priority\n\nUse priority='high' to ensure handoff is seen on startup.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:30.26323-08:00","updated_at":"2025-12-15T20:48:59.550689-08:00","dependencies":[{"issue_id":"gt-vci","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.554108-08:00","created_by":"daemon"}]}
{"id":"gt-h5n.7","title":"Auto-target: MRs for epic children target integration branch","description":"Automatically target integration branches for epic children.\n\nWhen 'gt mq submit' is called:\n1. Parse source issue from branch\n2. Check if issue has a parent epic\n3. Check if integration/\u003cepic\u003e branch exists\n4. If yes: set target=integration/\u003cepic\u003e\n5. If no: set target=main\n\nThis ensures batch work automatically flows to integration branches.\n\nAlso update 'gt mq submit --epic' to explicitly target an epic's integration branch.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:56.992465-08:00","updated_at":"2025-12-19T12:56:15.210654-08:00","closed_at":"2025-12-19T11:59:13.982658-08:00","dependencies":[{"issue_id":"gt-h5n.7","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:56.994579-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.7","depends_on_id":"gt-h5n.4","type":"blocks","created_at":"2025-12-17T13:53:16.648727-08:00","created_by":"daemon"}]}
{"id":"gt-d3d","title":"Design: Additional design issues (placeholder)","description":"Placeholder for additional design issues the user wants to raise and work through. Convert to specific subtasks as issues are identified.","status":"open","priority":4,"issue_type":"epic","created_at":"2025-12-15T20:24:12.601585-08:00","updated_at":"2025-12-15T23:17:32.467687-08:00"}
{"id":"gt-vc1n","title":"Tmux status line: rig color themes and worker identity display","description":"## Summary\n\nCustomize tmux status line for Gas Town workers with:\n1. Per-rig configurable color themes\n2. Clear worker name and role visibility\n\n## Current Problem\n\n- Only mayor shows in status line (and truncated)\n- Can't tell which rig/worker you're looking at\n- All sessions look the same\n\n## Proposed Design\n\n### Per-rig colors\n```yaml\n# In rig config or beads\ntheme:\n primary: '#ff6600' # Orange for gastown\n secondary: '#333333'\n accent: '#ffcc00'\n```\n\n### Status line format\n```\n[gastown/Rictus] polecat | gt-70b3 | branch: polecat/Rictus\n[beads/emma] crew | working | branch: main \n[mayor] coordinator | idle\n```\n\n### Components\n- Rig name with rig color\n- Worker name\n- Role (polecat/crew/mayor/witness/refinery)\n- Current issue or status\n- Branch name\n\n## Configuration\n\nCould use pinned beads for this (see gm-w13, beads-6v2):\n- `bd show \u003crig\u003e-theme` returns theme config\n- Stored as pinned bead, always available\n- Part of 'config in beads data plane' initiative","notes":"Implementation complete. Core features: per-rig color themes, dynamic status line with issue/mail indicators, gt theme/issue commands. Ready for testing.","status":"in_progress","priority":2,"issue_type":"feature","created_at":"2025-12-18T21:58:58.547188-08:00","updated_at":"2025-12-19T15:06:22.396098-08:00"}
{"id":"gt-61o","title":"Review and audit all GGT beads","description":"Thorough review of all filed beads in gastown GGT repo. Check for: consistency, completeness, correct dependencies, accurate descriptions, proper prioritization. Ensure beads are self-contained and dont rely on external docs.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:07.152386-08:00","updated_at":"2025-12-15T21:23:58.255447-08:00","closed_at":"2025-12-15T21:23:58.255447-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:26.397214-08:00","updated_at":"2025-12-17T13:52:26.397214-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-kmn.2","title":"SwarmManager: create, start, update, query operations","description":"SwarmManager operations for creating and managing swarms.\n\n## Interface\n\n```go\ntype SwarmManager struct {\n rig *Rig\n beads *BeadsWrapper // shells out to bd CLI\n}\n\nfunc NewSwarmManager(rig *Rig) *SwarmManager\n\n// Lifecycle\nfunc (m *SwarmManager) Create(epicID string, workers []string) (*Swarm, error)\nfunc (m *SwarmManager) Start(swarmID string) error\nfunc (m *SwarmManager) UpdateState(swarmID string, state SwarmState) error\nfunc (m *SwarmManager) Cancel(swarmID string, reason string) error\n\n// Queries (delegate to beads)\nfunc (m *SwarmManager) GetSwarm(id string) (*Swarm, error)\nfunc (m *SwarmManager) GetReadyTasks(swarmID string) ([]SwarmTask, error)\nfunc (m *SwarmManager) GetActiveTasks(swarmID string) ([]SwarmTask, error)\nfunc (m *SwarmManager) IsComplete(swarmID string) (bool, error)\n```\n\n## Implementation Notes\n\n- `GetReadyTasks` wraps `bd ready --parent \u003cepicID\u003e`\n- `IsComplete` checks if all child issues are closed\n- State transitions update the epic's description or a tag field\n- No separate manifest files - beads IS the source of truth","status":"closed","issue_type":"task","created_at":"2025-12-16T00:09:04.814385-08:00","updated_at":"2025-12-16T14:00:13.663624-08:00","closed_at":"2025-12-16T14:00:13.663624-08:00","dependencies":[{"issue_id":"gt-kmn.2","depends_on_id":"gt-kmn","type":"parent-child","created_at":"2025-12-16T00:09:04.814876-08:00","created_by":"daemon"},{"issue_id":"gt-kmn.2","depends_on_id":"gt-kmn.1","type":"blocks","created_at":"2025-12-16T00:11:20.744039-08:00","created_by":"daemon"}]}
{"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-vjw","title":"Swarm learning: Session cleanup missing from swarm workflow","description":"## Problem\n\nAfter Enders Game swarm completed (18 issues merged), 16 polecat sessions were left running but idle. No automated cleanup occurred.\n\n## What Should Happen\n\n1. Witness detects polecat completed work (idle at prompt)\n2. Witness verifies git state is clean\n3. Witness shuts down session\n4. Witness reports completion to Mayor\n\n## GGT Components\n\n- gt-cxx: Witness context cycling (covers self-cycling)\n- gt-u1j.9: Witness daemon heartbeat loop\n- gt-kmn.6: Witness swarm landing protocol\n\n## Recommendation\n\nAdd to Witness responsibilities:\n- Monitor for 'work complete' signals (DONE keyword, idle detection)\n- Automated session shutdown after verification\n- Swarm completion reporting to Mayor\n\nSee also: architecture.md 'Worker Cleanup (Witness-Owned)' section which describes this but it wasn't implemented in PGT.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T01:27:52.796587-08:00","updated_at":"2025-12-16T01:51:37.409965-08:00","closed_at":"2025-12-16T01:51:37.409965-08:00"}
{"id":"gt-gl2","title":"Clarify Mayor vs Witness cleanup responsibilities","description":"Document the cleanup authority model: Witness owns ALL per-worker cleanup, Mayor never involved.\n\n## The Rule\n\n**Witness handles ALL per-worker cleanup. Mayor is never involved.**\n\n## Why This Matters\n\n1. Separation of concerns: Mayor strategic, Witness operational\n2. Reduced coordination overhead: No back-and-forth for routine cleanup\n3. Faster shutdown: Witness kills workers immediately upon verification\n4. Cleaner escalation: Mayor only hears about problems\n\n## What Witness Handles\n\n- Verifying worker git state before kill\n- Nudging workers to fix dirty state\n- Killing worker sessions\n- Updating worker state (sleep/wake)\n- Logging verification results\n\n## What Mayor Handles\n\n- Receiving swarm complete notifications\n- Deciding whether to start new swarms\n- Handling escalations (stuck workers after 3 retries)\n- Cross-rig coordination\n\n## Escalation Path\n\nWorker stuck -\u003e Witness nudges (up to 3x) -\u003e Witness escalates to Mayor -\u003e Mayor decides: force kill, reassign, or human\n\n## Anti-Patterns\n\nDO NOT: Mayor asks Witness if worker X is clean\nDO: Witness reports swarm complete, all workers verified\n\nDO NOT: Mayor kills worker sessions directly\nDO: Mayor tells Witness to abort swarm, Witness handles cleanup\n\nDO NOT: Workers report done to Mayor\nDO: Workers report to Witness, Witness aggregates and reports up","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:56.678724-08:00","updated_at":"2025-12-15T20:48:12.068964-08:00","dependencies":[{"issue_id":"gt-gl2","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.929877-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.18","title":"CLI: witness commands (start, stop, status)","description":"Witness daemon CLI commands.\n\n## Commands\n\n### gt witness start\nStart the witness daemon for a rig.\n```\ngt witness start \u003crig\u003e [--interval \u003cseconds\u003e]\n```\n- Starts background daemon process\n- Default heartbeat interval: 30s\n- Logs to \u003crig\u003e/witness/witness.log\n\n### gt witness stop\nStop the witness daemon.\n```\ngt witness stop \u003crig\u003e\n```\n- Graceful shutdown\n- Completes current heartbeat cycle\n\n### gt witness status\nShow witness status.\n```\ngt witness status \u003crig\u003e [--json]\n```\nOutput:\n- Running/stopped\n- Last heartbeat time\n- Polecats being monitored\n- Recent nudges/escalations\n\n### gt witness logs\nView witness logs.\n```\ngt witness logs \u003crig\u003e [--follow] [--lines \u003cn\u003e]\n```\n- --follow: Continuous output (like tail -f)\n- --lines: Number of lines (default 50)\n\n## Daemon Management\n\nWitness runs as background process:\n- PID stored in \u003crig\u003e/witness/witness.pid\n- Uses nohup for persistence\n- Logs structured JSON events\n\n## Implementation\n\n```go\nvar witnessCmd = \u0026cobra.Command{Use: \"witness\"}\nwitnessCmd.AddCommand(startCmd, stopCmd, statusCmd, logsCmd)\n```\n\nStart launches daemon via exec, status reads PID file and pings process.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T17:13:15.022371-08:00","updated_at":"2025-12-15T21:21:07.27635-08:00","dependencies":[{"issue_id":"gt-u1j.18","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:13:15.022774-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.18","depends_on_id":"gt-u1j.9","type":"blocks","created_at":"2025-12-15T17:14:08.490417-08:00","created_by":"daemon"}]}
{"id":"gt-svi.4","title":"gt mq retry: retry a failed MR","description":"Implement 'gt mq retry \u003cid\u003e' to retry a failed merge request.\n\nActions:\n1. Verify MR exists and is in failed state (open with failure labels)\n2. Remove failure labels (needs-rebase, needs-fix)\n3. Reset to ready state\n4. Optionally re-run immediately (--now flag)\n\nOptions:\n- --now: immediately process (instead of waiting for Engineer loop)\n\nReference: docs/merge-queue-design.md#cli-commands","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:36.336017-08:00","updated_at":"2025-12-19T12:56:15.217204-08:00","closed_at":"2025-12-18T20:11:15.063571-08:00","dependencies":[{"issue_id":"gt-svi.4","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:36.3382-08:00","created_by":"daemon"}]}
{"id":"gt-iua8","title":"Merge: gt-frs","description":"branch: polecat/Slit\ntarget: main\nsource_issue: gt-frs\nrig: gastown","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T16:30:05.529099-08:00","updated_at":"2025-12-19T18:26:14.104887-08:00","closed_at":"2025-12-19T17:48:44.654109-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-17T13:52:02.32832-08:00","updated_at":"2025-12-17T13:52:02.32832-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-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-19T19:12:58.575085-08:00","closed_at":"2025-12-19T17:47:03.616174-08:00"}
{"id":"gt-hw6","title":"GGT Command Parity: Complete gt command coverage","description":"Complete gt command set to match/exceed PGT town commands.\n\nCovers: uninstall, rig info, refinery attach, witness, session mgmt, mail UX, daemon.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-17T22:22:21.720078-08:00","updated_at":"2025-12-19T12:56:15.211995-08:00","closed_at":"2025-12-19T12:05:36.723692-08:00"}
{"id":"gt-bzd","title":"beads: Stop searching upward when .beads found","description":"## Problem\n\nWhen running bd commands in a nested directory structure with multiple .beads directories, bd shows a confusing warning:\n\n```\n╔══════════════════════════════════════════════════════════════════════════╗\n║ WARNING: 2 beads databases detected in directory hierarchy ║\n╠══════════════════════════════════════════════════════════════════════════╣\n║ Multiple databases can cause confusion and database pollution. ║\n║ ║\n║ /Users/stevey/gt/gastown/.beads (261 issues) ║\n║ /Users/stevey/gt/.beads (21 issues) ║\n║ ║\n║ WARNING: Not using the closest database! Check your BEADS_DB setting. ║\n║ ║\n║ RECOMMENDED: Consolidate or remove unused databases to avoid confusion. ║\n╚══════════════════════════════════════════════════════════════════════════╝\n```\n\n## Why This Is Wrong\n\nIn Gas Town, nested .beads directories are **intentional and necessary**:\n- Town level: /Users/stevey/gt/.beads (mail, town-level issues)\n- Rig level: /Users/stevey/gt/gastown/.beads (gastown project issues)\n- Worker level: polecats have their own beads in worktrees\n\nThese are **unrelated** beads instances for different scopes. They should never be consolidated.\n\n## Expected Behavior\n\nWhen bd finds a .beads directory, it should:\n1. Use that directory (closest ancestor wins)\n2. **Stop searching upward** - do not look for parent .beads directories\n3. **No warning** about multiple databases\n\n## Current Behavior\n\nbd searches all the way up to root, finds all .beads directories, and warns about \"multiple databases\" even though they are separate, intentional instances.\n\n## Fix\n\nIn the database discovery code, stop the upward search as soon as a .beads directory is found. The first .beads found is the one to use, and parent directories are out of scope.\n\n## Note\n\nThis is a beads issue, filed here for tracking. Should be implemented in the beads codebase.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T19:09:44.295743-08:00","updated_at":"2025-12-19T00:44:28.741548-08:00","closed_at":"2025-12-19T00:44:28.741548-08:00"}
{"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":"open","priority":2,"issue_type":"task","created_at":"2025-12-16T14:46:57.158136-08:00","updated_at":"2025-12-16T16:04:32.922813-08:00"}
{"id":"gt-r01","title":"EXTERNAL: Beads Messaging \u0026 Knowledge Graph (bd-kwro)","description":"Tracking issue for external dependency on Beads v0.30.2 messaging features.\n\nBeads epic: bd-kwro in ~/src/beads (steveyegge/beads repo)\n\nThis blocks GGT work that depends on:\n- bd mail send/inbox/read/ack commands\n- message issue type\n- replies_to threading\n- Hooks system for notifications\n- Identity configuration\n\nGGT mail commands will be thin wrappers around bd mail once available.\n\nWhen bd-kwro ships in Beads v0.30.2, close this and unblock dependent work.","status":"closed","issue_type":"task","created_at":"2025-12-16T13:12:02.676883-08:00","updated_at":"2025-12-16T21:35:05.795776-08:00","closed_at":"2025-12-16T21:35:05.795776-08:00"}
{"id":"gt-cik.8","title":"Crew worker CLAUDE.md prompting","description":"Create CLAUDE.md template for crew workers:\n- Explain crew worker role (overseer's personal workspace)\n- Include mail-to-self handoff instructions\n- Document gt crew refresh for context cycling\n- Explain no witness monitoring (user-managed)\n- Include beads usage if BEADS_DIR configured","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T16:48:12.108074-08:00","updated_at":"2025-12-16T20:59:02.00287-08:00","closed_at":"2025-12-16T20:59:02.00287-08:00","dependencies":[{"issue_id":"gt-cik.8","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:12.109654-08:00","created_by":"daemon"}]}
{"id":"gt-3pp","title":"Support numeric shortcuts in mail read (e.g., 'mail read 1')","description":"When inbox shows numbered messages like:\n* 1. gm-19b29031... 2025-12-16 mayor Subject...\n* 2. gm-19b26d51... 2025-12-16 Subject...\n\nUsers should be able to run 'gt mail read 1' instead of needing the full message ID 'gt mail read gm-19b29031f6a172206'.\n\nImplementation:\n- Track inbox message order in display\n- Map numeric indices to actual message IDs\n- Accept both numeric shortcuts and full IDs in 'mail read' command","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-16T13:15:07.857939-08:00","updated_at":"2025-12-16T13:15:29.273066-08:00"}
{"id":"gt-690z","title":"Test MR","description":"test","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-18T20:15:16.685471-08:00","updated_at":"2025-12-18T20:21:54.161643-08:00","closed_at":"2025-12-18T20:21:54.161643-08:00"}
{"id":"gt-9a2.15","title":"Outpost error handling: Retry logic and resilience","description":"## Overview\n\nError handling and retry logic for outpost operations.\n\n## Error Types\n\n```go\nvar (\n ErrOutpostUnreachable = errors.New(\"outpost unreachable\")\n ErrWorkerSpawnFailed = errors.New(\"worker spawn failed\")\n ErrWorkerTimeout = errors.New(\"worker timed out\")\n ErrCostCapExceeded = errors.New(\"cost cap exceeded\")\n ErrAllOutpostsBusy = errors.New(\"all outposts at capacity\")\n)\n```\n\n## Retry Policy\n\n```go\ntype RetryPolicy struct {\n MaxAttempts int\n InitialBackoff time.Duration\n MaxBackoff time.Duration\n BackoffFactor float64\n RetryableErrors []error\n}\n\nfunc DefaultRetryPolicy() *RetryPolicy {\n return \u0026RetryPolicy{\n MaxAttempts: 3,\n InitialBackoff: 1 * time.Second,\n MaxBackoff: 30 * time.Second,\n BackoffFactor: 2.0,\n RetryableErrors: []error{\n ErrOutpostUnreachable,\n ErrWorkerSpawnFailed,\n },\n }\n}\n```\n\n## Retry Implementation\n\n```go\nfunc (m *OutpostManager) SpawnWithRetry(issue string, cfg WorkerConfig) (Worker, error) {\n var lastErr error\n backoff := m.retryPolicy.InitialBackoff\n \n for attempt := 0; attempt \u003c m.retryPolicy.MaxAttempts; attempt++ {\n outpost := m.policy.SelectOutpost(issue, m.outposts)\n if outpost == nil {\n return nil, ErrAllOutpostsBusy\n }\n \n worker, err := outpost.Spawn(issue, cfg)\n if err == nil {\n return worker, nil\n }\n \n if !m.isRetryable(err) {\n return nil, err\n }\n \n lastErr = err\n time.Sleep(backoff)\n backoff = min(backoff * m.retryPolicy.BackoffFactor, m.retryPolicy.MaxBackoff)\n }\n \n return nil, fmt.Errorf(\"spawn failed after %d attempts: %w\", \n m.retryPolicy.MaxAttempts, lastErr)\n}\n```\n\n## Outpost Health Tracking\n\n```go\ntype OutpostHealth struct {\n LastPing time.Time\n LastError error\n FailureCount int\n CircuitBreaker bool // If true, skip this outpost\n}\n\nfunc (m *OutpostManager) updateHealth(name string, err error) {\n // Track failures, open circuit breaker after N failures\n // Auto-reset after successful ping\n}\n```\n\n## Config\n\n```yaml\npolicy:\n retry:\n max_attempts: 3\n initial_backoff: 1s\n max_backoff: 30s\n \n circuit_breaker:\n failure_threshold: 5\n reset_timeout: 1m\n```\n\n## Files\n\n- `internal/outpost/retry.go`\n- `internal/outpost/health.go`\n\n## Dependencies\n\nDepends on: gt-9a2.3 (OutpostManager)\nCan be done after basic outpost implementations work.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T18:16:33.386008-08:00","updated_at":"2025-12-16T18:16:33.386008-08:00","dependencies":[{"issue_id":"gt-9a2.15","depends_on_id":"gt-9a2","type":"parent-child","created_at":"2025-12-16T18:16:33.387765-08:00","created_by":"daemon"},{"issue_id":"gt-9a2.15","depends_on_id":"gt-9a2.3","type":"blocks","created_at":"2025-12-16T18:16:46.064482-08:00","created_by":"daemon"}]}
{"id":"gt-aqm","title":"Beads as Universal Data Plane","description":"## Vision\n\nBeads is the data plane for all Gas Town operations. Everything flows through beads:\n- Work items (issues, tasks, epics)\n- Mail (messages between agents)\n- Merge requests (queue entries)\n- Workflows (composable execution patterns)\n- Resources (leases, locks, quotas)\n- Schedules (timed activities)\n\n## New Bead Categories\n\n### Molecules (Composable Workflows)\nCrystallized workflow patterns that can be attached to work items.\n\n### Timed Beads (Scheduled Work)\nBeads that wake up periodically via daemon.\n\n### Pinned Beads (Ongoing Concerns)\nBeads representing persistent concerns, not discrete tasks.\n\n### Resource Beads (Leases/Locks)\nBeads representing reserved resources.\n\n## v1 Priority\n\n- **P0**: Molecules (enables engineer-in-box)\n- **P2**: Timed, Pinned, Resource beads (post-v1)","status":"open","issue_type":"epic","created_at":"2025-12-18T18:05:57.847578-08:00","updated_at":"2025-12-18T18:06:10.898712-08:00","dependencies":[{"issue_id":"gt-aqm","depends_on_id":"gt-b3p","type":"blocks","created_at":"2025-12-18T18:08:20.026188-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-4nn","type":"blocks","created_at":"2025-12-18T18:06:29.881371-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-caz","type":"blocks","created_at":"2025-12-18T18:08:19.833603-08:00","created_by":"daemon"},{"issue_id":"gt-aqm","depends_on_id":"gt-8h4","type":"blocks","created_at":"2025-12-18T18:08:19.930166-08:00","created_by":"daemon"}]}
{"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-sye","title":"Mayor startup protocol prompting","description":"Add startup protocol to Mayor CLAUDE.md template.\n\n## On Session Start\n\n1. Check for handoff:\n town inbox | grep \"Session Handoff\"\n\n2. If handoff found:\n - Read it: town read \u003cmsg-id\u003e\n - Process pending escalations (highest priority)\n - Check status of noted swarms\n - Verify rig health matches notes\n - Continue with documented next steps\n\n3. If no handoff:\n town status # Overall health\n town rigs # Each rig\n bd ready # Work items\n town inbox # Any messages\n Build your own picture of current state.\n\n4. After processing handoff:\n - Archive or delete the handoff message\n - You now own the current state\n\n## Handoff Best Practices\n\n- Be specific: 'Toast has merge conflict in auth/middleware.go' not 'Toast is stuck'\n- Include context: Why decisions are pending, what you were thinking\n- Prioritize next steps: What is most urgent\n- Note time-sensitive items: Anything that might have changed since handoff","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T20:15:27.915484-08:00","updated_at":"2025-12-15T20:48:57.555724-08:00","dependencies":[{"issue_id":"gt-sye","depends_on_id":"gt-u82","type":"blocks","created_at":"2025-12-15T20:15:39.459108-08:00","created_by":"daemon"}]}
{"id":"gt-5qc","title":"Document how to configure a Gas Town Harness","description":"Create docs explaining what a harness is (private repo containing GT installation with rigs gitignored), why you'd want one, and how to set it up with beads redirects","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T16:42:43.370167-08:00","updated_at":"2025-12-19T12:56:15.202473-08:00","closed_at":"2025-12-19T12:00:39.274285-08:00","dependencies":[{"issue_id":"gt-5qc","depends_on_id":"gt-l1o","type":"blocks","created_at":"2025-12-17T16:42:54.620984-08:00","created_by":"daemon"},{"issue_id":"gt-5qc","depends_on_id":"gt-cr9","type":"blocks","created_at":"2025-12-17T17:15:59.17545-08:00","created_by":"daemon"}]}
{"id":"gt-u1j.5","title":"Rig management: discover, load, create rigs","description":"Rig discovery, loading, and creation.\n\n## Interface\n\n```go\ntype Rig struct {\n Name string\n Path string\n GitURL string\n Config RigConfig\n Polecats []string\n HasWitness bool\n HasRefinery bool\n}\n\ntype RigManager struct {\n townRoot string\n config *Config\n git *Git\n}\n\nfunc NewRigManager(townRoot string, config *Config, git *Git) *RigManager\n\n// Discovery\nfunc (rm *RigManager) DiscoverRigs() ([]*Rig, error)\nfunc (rm *RigManager) GetRig(name string) (*Rig, error)\nfunc (rm *RigManager) RigExists(name string) bool\n\n// Creation\nfunc (rm *RigManager) AddRig(name, gitURL string) (*Rig, error)\nfunc (rm *RigManager) RemoveRig(name string) error\n\n// Rig state\nfunc (rm *RigManager) LoadRigConfig(rig *Rig) error\nfunc (rm *RigManager) SaveRigConfig(rig *Rig) error\n```\n\n## Discovery Logic\n\n1. Read rigs.json from config/\n2. For each registered rig, verify directory exists\n3. Load rig-level config if present\n4. Scan for polecats/ subdirectory\n5. Check for witness/, refinery/ directories\n\n## Rig Creation\n\n1. Clone repo to town root\n2. Add entry to rigs.json\n3. Create agent directories (polecats/, witness/, refinery/, mayor/)\n4. Update .git/info/exclude to ignore agent dirs\n5. Initialize rig config\n\n## Rig Structure\n\nPer docs/architecture.md:\n```\n\u003crig\u003e/\n├── polecats/\n├── refinery/rig/\n├── witness/rig/\n└── mayor/rig/\n```","status":"closed","issue_type":"task","created_at":"2025-12-15T17:12:15.034694-08:00","updated_at":"2025-12-16T13:33:52.924291-08:00","closed_at":"2025-12-16T13:33:52.924291-08:00","dependencies":[{"issue_id":"gt-u1j.5","depends_on_id":"gt-u1j","type":"parent-child","created_at":"2025-12-15T17:12:15.035022-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.5","depends_on_id":"gt-u1j.3","type":"blocks","created_at":"2025-12-15T17:13:49.93957-08:00","created_by":"daemon"},{"issue_id":"gt-u1j.5","depends_on_id":"gt-f9x.1","type":"blocks","created_at":"2025-12-15T17:13:50.047236-08:00","created_by":"daemon"}]}
{"id":"gt-8bx","title":"Adaptive backoff for daemon heartbeat","description":"Track agent responsiveness and adjust heartbeat frequency.\n\n## Per-Agent State\n\n```go\ntype AgentBackoff struct {\n BaseInterval time.Duration // 60s default\n CurrentInterval time.Duration // grows when busy\n MaxInterval time.Duration // 10min cap\n ConsecutiveMiss int // pokes with no response\n}\n```\n\n## Strategy Options\n\n- **Fixed**: Always 60s (current, simple)\n- **Geometric**: 60s → 90s → 135s → 202s (factor 1.5)\n- **Exponential**: 60s → 120s → 240s (factor 2, aggressive)\n\n## Recovery\n\nWhen agent responds (runs a command):\n- Reset ConsecutiveMiss to 0\n- Return to BaseInterval immediately\n\n## Benefits\n\n- Reduces noise for busy agents\n- Saves resources during quiet periods\n- Still catches stuck agents (max interval cap)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T14:19:33.083844-08:00","updated_at":"2025-12-19T12:56:15.204827-08:00","closed_at":"2025-12-19T12:09:31.613912-08:00","dependencies":[{"issue_id":"gt-8bx","depends_on_id":"gt-bfd","type":"blocks","created_at":"2025-12-18T14:19:46.912289-08:00","created_by":"daemon"}]}
{"id":"gt-kut","title":"Test message","description":"Testing GGT mail system","status":"closed","priority":2,"issue_type":"message","created_at":"2025-12-17T16:12:11.437529-08:00","updated_at":"2025-12-17T16:12:28.176984-08:00","closed_at":"2025-12-17T16:12:28.176984-08:00"}
{"id":"gt-3x1.1","title":"Engineer main loop: poll for ready merge-requests","description":"Implement the Engineer's main processing loop.\n\nLoop structure:\n1. Query: bd ready --type=merge-request\n2. If empty: sleep(poll_interval), continue\n3. Select highest priority, oldest MR\n4. Claim: bd update \u003cid\u003e --status=in_progress\n5. Process (delegate to other subtasks)\n6. Repeat\n\nConfiguration:\n- poll_interval: from rig config (default 30s)\n- max_concurrent: from rig config (default 1)\n\nThe loop should be interruptible and handle graceful shutdown.\n\nReference: docs/merge-queue-design.md#engineer-processing-loop","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:50:57.022367-08:00","updated_at":"2025-12-19T12:56:15.197296-08:00","closed_at":"2025-12-18T20:14:35.321731-08:00","dependencies":[{"issue_id":"gt-3x1.1","depends_on_id":"gt-3x1","type":"parent-child","created_at":"2025-12-17T13:50:57.024225-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-svi.1","type":"blocks","created_at":"2025-12-17T13:53:09.832586-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-svi.2","type":"blocks","created_at":"2025-12-17T13:53:09.9547-08:00","created_by":"daemon"},{"issue_id":"gt-3x1.1","depends_on_id":"gt-h5n.8","type":"blocks","created_at":"2025-12-17T13:53:16.770078-08:00","created_by":"daemon"}]}
{"id":"gt-zly","title":"Swarm learning: Beads database locality gap","description":"## PGT Bug (GGT Design Already Correct)\n\nMayor created issues in `~/ai/mayor/rigs/beads/.beads/` but polecats use `~/ai/beads/.beads/`. Different databases = polecats can't see Mayor's beads.\n\n**GGT Fix**: architecture.md already specifies:\n- All agents use BEADS_DIR pointing to rig-level `.beads/`\n- Lines 116-143: Beads Configuration for Multi-Agent\n- Lines 573-586: Rig-Level Beads via BEADS_DIR\n\nThis is a PGT implementation gap, not a design issue. GGT spawn must set BEADS_DIR correctly.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T01:21:45.37072-08:00","updated_at":"2025-12-16T01:28:40.74469-08:00","closed_at":"2025-12-16T01:28:40.74469-08:00"}
{"id":"gt-szsq","title":"gt spawn --create should auto-add polecat if missing","description":"## Problem\n\n`gt spawn gastown --issue gt-xxx --create` fails if no polecats exist.\n\n## Current Behavior\n\n```\nError: auto-select polecat: no available polecats in rig 'gastown'\n```\n\n## Expected Behavior\n\n`--create` should:\n1. Create a new polecat if none exist\n2. Or create the specified polecat if `gt spawn gastown/NewName --create`\n\n## Workaround\n\nMust manually run `gt polecat add gastown Name` first.\n\n## Principle\n\nAgent UX should be forgiving - if I say spawn with --create, make it work.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:52:07.75062-08:00","updated_at":"2025-12-19T01:33:49.859926-08:00","closed_at":"2025-12-19T01:33:49.859926-08:00"}
{"id":"gt-xkbm","title":"Merge: gt-g44u.1","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-g44u.1\nrig: gastown","status":"closed","issue_type":"merge-request","created_at":"2025-12-19T16:04:14.367493-08:00","updated_at":"2025-12-19T17:35:38.210747-08:00","closed_at":"2025-12-19T17:35:38.210747-08:00"}
{"id":"gt-axz","title":"Design: Plugin architecture (agents-as-plugins)","description":"Plugin system where plugins are just additional agents with identities, mailboxes, and beads access. See docs/architecture.md Plugins section. No special framework - just directory conventions and mail-based invocation.","status":"open","priority":3,"issue_type":"epic","created_at":"2025-12-15T22:52:43.614095-08:00","updated_at":"2025-12-15T23:17:04.627865-08:00"}
{"id":"gt-wav5","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:30.210304-08:00","updated_at":"2025-12-19T18:26:14.103104-08:00","closed_at":"2025-12-19T18:26:14.103106-08:00"}
{"id":"gt-70b3","title":"detectSender() doesn't recognize crew workers","description":"## Problem\n\n`detectSender()` in mail.go only detects polecats, not crew workers.\n\n## Current Code (line 445)\n\n```go\n// If in a rig's polecats directory, extract address\nif strings.Contains(cwd, \"/polecats/\") {\n // extract rig/polecat\n}\n\n// Default to mayor\nreturn \"mayor/\"\n```\n\n## Symptom\n\nEmma (crew worker at `/Users/stevey/gt/beads/crew/emma`) runs:\n- `gt mail inbox` → checks `mayor/` inbox (wrong!)\n- Should check `beads/emma` or `beads/crew/emma`\n\n## Fix\n\nAdd crew detection:\n```go\n// If in a rig's crew directory, extract address \nif strings.Contains(cwd, \"/crew/\") {\n parts := strings.Split(cwd, \"/crew/\")\n if len(parts) \u003e= 2 {\n rigPath := parts[0]\n crewName := strings.Split(parts[1], \"/\")[0]\n rigName := filepath.Base(rigPath)\n return fmt.Sprintf(\"%s/%s\", rigName, crewName)\n }\n}\n```\n\n## Also Check\n\n- `gt prime` correctly detects role, so there may be another detection function that works\n- Should unify detection logic","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T21:40:26.520559-08:00","updated_at":"2025-12-18T21:55:54.679969-08:00","closed_at":"2025-12-18T21:55:54.679969-08:00","dependencies":[{"issue_id":"gt-70b3","depends_on_id":"gt-l4gm","type":"blocks","created_at":"2025-12-18T21:50:04.812663-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-16T00:10:46.139004-08:00","updated_at":"2025-12-16T17:25:14.424029-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-xpq","title":"Add gt crew rename command","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-18T19:45:32.599846-08:00","updated_at":"2025-12-18T19:46:17.780981-08:00","closed_at":"2025-12-18T19:46:17.780981-08:00"}
{"id":"gt-svi.1","title":"gt mq submit: create MR from current branch","description":"Implement 'gt mq submit' command that creates a merge-request bead.\n\nAuto-detection logic:\n1. Branch: current git branch\n2. Issue: parse from branch name (polecat/Nux/gt-xyz → gt-xyz)\n3. Target: main (or integration branch if --epic specified)\n4. Worker: parse from branch name\n5. Rig: current rig\n\nOptions:\n- --branch BRANCH: explicit source branch\n- --issue ISSUE: explicit source issue\n- --epic EPIC: target integration/EPIC instead of main\n- --priority P: override priority (default: inherit from source issue)\n\nCreates merge-request bead and prints MR ID.\n\nReference: docs/merge-queue-design.md#creating-merge-requests","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:21.652412-08:00","updated_at":"2025-12-19T12:56:15.215532-08:00","closed_at":"2025-12-18T20:22:41.487682-08:00","dependencies":[{"issue_id":"gt-svi.1","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:21.65435-08:00","created_by":"daemon"},{"issue_id":"gt-svi.1","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.317401-08:00","created_by":"daemon"},{"issue_id":"gt-svi.1","depends_on_id":"gt-h5n.2","type":"blocks","created_at":"2025-12-17T13:53:02.438987-08:00","created_by":"daemon"}]}
{"id":"gt-974","title":"Refinery background daemon mode","description":"The refinery 'gt refinery start' command only works in foreground mode (--foreground). Need to implement background daemon mode for production use.\n\nOptions:\n1. Use a separate tmux session for the refinery\n2. Implement proper daemonization\n3. Use Claude Code session for the refinery agent\n\nFor MVP, option 1 (tmux session) is probably simplest.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T22:08:04.799753-08:00","updated_at":"2025-12-19T15:06:22.393972-08:00","closed_at":"2025-12-19T14:27:33.858745-08:00"}
{"id":"gt-qscw","title":"Merge: gt-72so","description":"branch: polecat/Ace\ntarget: main\nsource_issue: gt-72so\nrig: gastown","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-19T16:20:02.203335-08:00","updated_at":"2025-12-19T18:26:14.105337-08:00","closed_at":"2025-12-19T17:48:09.571107-08:00"}
{"id":"gt-cik.6","title":"gt crew remove: Remove crew workspace","description":"Implement 'gt crew remove \u003cname\u003e [--force]' command:\n- Check for uncommitted changes, unpushed commits\n- Warn and require --force if dirty\n- Kill any running session\n- Remove directory\n- Unregister from mail","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-16T16:48:08.407212-08:00","updated_at":"2025-12-16T20:59:33.354764-08:00","closed_at":"2025-12-16T20:53:16.696352-08:00","dependencies":[{"issue_id":"gt-cik.6","depends_on_id":"gt-cik","type":"parent-child","created_at":"2025-12-16T16:48:08.408845-08:00","created_by":"daemon"}]}
{"id":"gt-ruw","title":"Fix TestHasPolecat test failure in internal/session","description":"TestHasPolecat in internal/session/manager_test.go fails because it expects\nspecific polecats (Toast, Cheedo) to exist in the test environment.\n\nError:\n```\nmanager_test.go:46: expected hasPolecat(Toast) = true\nmanager_test.go:49: expected hasPolecat(Cheedo) = true\n```\n\nFix: Either create test fixtures or mock the filesystem check.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-17T15:02:30.030032-08:00","updated_at":"2025-12-19T12:56:15.214131-08:00","closed_at":"2025-12-19T11:58:56.1846-08:00"}
{"id":"gt-4nn.1","title":"Molecule schema: YAML format for workflow definitions","description":"Define the YAML schema for molecule definitions:\n\n```yaml\nmolecule: \u003cname\u003e\nversion: 1\ndescription: \"Human description\"\nsteps:\n - id: \u003cstep-id\u003e\n title: \"Step title\"\n prompt: \"Instructions for agent\"\n depends: [\u003cother-step-ids\u003e] # optional\n tier: haiku|sonnet|opus # optional, default from config\n timeout: 30m # optional\n```\n\nStore molecules in:\n- `\u003crig\u003e/molecules/\u003cname\u003e.yaml` for rig-specific\n- `\u003ctown\u003e/molecules/\u003cname\u003e.yaml` for town-wide\n\nBuilt-in molecules to ship:\n- engineer-in-box: design→code→review→test→submit\n- quick-fix: implement→test→submit\n- research: investigate→document","status":"closed","issue_type":"task","created_at":"2025-12-18T18:06:49.441267-08:00","updated_at":"2025-12-19T12:56:15.199539-08:00","closed_at":"2025-12-18T20:14:32.629327-08:00","dependencies":[{"issue_id":"gt-4nn.1","depends_on_id":"gt-4nn","type":"parent-child","created_at":"2025-12-18T18:06:49.442723-08:00","created_by":"daemon"}]}
{"id":"gt-e76","title":"gt mail reply/thread: Conversation support","description":"Add mail conversation features:\n\n- gt mail reply \u003cid\u003e -m 'message' - Reply to a message\n- gt mail thread \u003cid\u003e - Show all messages in a thread\n\nEnables back-and-forth communication between agents.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:50:06.215773-08:00","updated_at":"2025-12-19T12:56:15.207793-08:00","closed_at":"2025-12-19T12:05:27.342212-08:00","dependencies":[{"issue_id":"gt-e76","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.106435-08:00","created_by":"daemon"}]}
{"id":"gt-l3c","title":"Design: Polecat Beads write access","description":"Design for granting polecats direct beads write access.\n\n## Background\n\nWith Beads v0.30.0 tombstone-based rearchitecture, we have solid multi-agent support. Reversing the original read-only decision.\n\n## Benefits\n\n- Simplifies architecture (no mail-based issue filing proxy)\n- Empowers polecats to file discovered work\n- Beads handles work-disavowal\n\n## Complications\n\nFor OSS projects where you cannot commit to project .beads/, need per-rig beads repo configuration.\n\n## Subtasks (implementation)\n\n- gt-zx3: Per-rig beads configuration schema\n- gt-e1y: Worker prompting updates for beads access\n- gt-cjb: Witness proxy removal\n- gt-082: Beads sync in decommission checklist\n\n**Design complete.** Each subtask has full specification in its description.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-15T19:37:42.191734-08:00","updated_at":"2025-12-15T20:49:24.598429-08:00","closed_at":"2025-12-15T20:14:04.174535-08:00"}
{"id":"gt-43qg","title":"Test: release command verification","notes":"Released: testing release command","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-19T16:15:30.845537-08:00","updated_at":"2025-12-19T16:15:55.084052-08:00","closed_at":"2025-12-19T16:15:55.084052-08:00"}
{"id":"gt-5af.3","title":"Add deacon/ mail identity support","description":"Ensure deacon/ works as a mail identity in town-level beads. Test with bd mail send deacon/ and bd mail inbox --identity deacon/.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:13:32.618418-08:00","updated_at":"2025-12-19T17:26:46.504422-08:00","closed_at":"2025-12-19T17:26:46.504422-08:00","dependencies":[{"issue_id":"gt-5af.3","depends_on_id":"gt-5af","type":"parent-child","created_at":"2025-12-19T17:13:32.620414-08:00","created_by":"daemon"}]}
{"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-w9o","title":"/restart: Personal slash command for in-place agent restart","description":"Create ~/.claude/commands/restart.md that restarts current Gas Town agent in place.\n\n## Detection\n- Read tmux session name: gt-mayor, gt-witness-*, gt-refinery-*, gt-polecat-*\n- Fallback: check GT_ROLE env var\n\n## Behavior by role\n- mayor: gt mayor restart (sends Ctrl-C, loop respawns)\n- witness: gt witness restart\n- refinery: gt refinery restart \n- polecat: gt polecat restart (or witness-mediated)\n\n## Command format\nUses backticks for inline bash to detect context, then instructs Claude to run appropriate restart.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T18:32:30.043125-08:00","updated_at":"2025-12-18T18:43:17.182303-08:00","closed_at":"2025-12-18T18:43:17.182303-08:00"}
{"id":"gt-av8","title":"Update Mayor prompting in gastown-py","description":"The Mayor CLAUDE.md and related prompting in gastown-py (still in production use) needs to reflect current design decisions: session cycling, handoff protocol, cleanup responsibilities, beads access model. Sync prompting with GGT design work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-15T20:24:09.953043-08:00","updated_at":"2025-12-15T21:07:29.858267-08:00","closed_at":"2025-12-15T21:07:29.858267-08:00"}
{"id":"gt-h5n.4","title":"gt mq integration create: create integration branch for epic","description":"Implement 'gt mq integration create \u003cepic\u003e' command.\n\nActions:\n1. Verify epic exists\n2. Create branch: integration/\u003cepic-id\u003e from main\n3. Push to origin\n4. Store integration branch info in epic metadata\n\nUsage:\n gt mq integration create gt-auth-epic\n # Creates integration/gt-auth-epic from main\n\nFuture MRs for this epic's children will auto-target this branch.\n\nReference: docs/merge-queue-design.md#integration-branches","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-17T13:51:35.679837-08:00","updated_at":"2025-12-19T12:56:15.209731-08:00","closed_at":"2025-12-19T01:57:17.029802-08:00","dependencies":[{"issue_id":"gt-h5n.4","depends_on_id":"gt-h5n","type":"parent-child","created_at":"2025-12-17T13:51:35.681828-08:00","created_by":"daemon"},{"issue_id":"gt-h5n.4","depends_on_id":"gt-svi.1","type":"blocks","created_at":"2025-12-17T13:53:16.28634-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":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T16:37:05.267701-08:00","updated_at":"2025-12-15T23:19:38.746608-08:00","dependencies":[{"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"},{"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"}]}
{"id":"gt-sd6","title":"Enhanced polecat decommission prompting","description":"Add decommission checklist to polecat AGENTS.md.template. Make crystal clear: verify ALL before signaling done.\n\n## Checklist for AGENTS.md.template\n\n```markdown\n## Decommission Checklist\n\n**CRITICAL**: Before signaling done, you MUST complete this checklist.\nThe Witness will verify each item and bounce you back if dirty.\n\n### Pre-Done Verification\n\n```bash\n# 1. Git status - must be clean\ngit status\n# Expected: \"nothing to commit, working tree clean\"\n\n# 2. Stash list - must be empty\ngit stash list\n# Expected: (empty output)\n\n# 3. Beads sync - must be up to date\nbd sync --status\n# Expected: \"Up to date\" or \"Nothing to sync\"\n\n# 4. Branch merged - your work must be on main\ngit log main --oneline -1\ngit log HEAD --oneline -1\n# Expected: Same commit\n```\n\n### If Any Check Fails\n\n- **Uncommitted changes**: Commit them or discard if unnecessary\n- **Stashes**: Pop and commit, or drop if obsolete\n- **Beads out of sync**: Run `bd sync`\n- **Branch not merged**: Complete the merge workflow\n\n### Signaling Done\n\nOnly after ALL checks pass:\n\n```bash\nbd close \u003cissue-id\u003e\nbd sync\ntown mail send \u003crig\u003e/witness -s \"Work Complete\" -m \"Issue \u003cid\u003e done.\"\n```\n```\n\n## Implementation\n\nAdd to AGENTS.md.template in the polecat prompting section.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:57.911311-08:00","updated_at":"2025-12-15T20:47:30.062333-08:00","dependencies":[{"issue_id":"gt-sd6","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:06.008061-08:00","created_by":"daemon"}]}
{"id":"gt-yls","title":"Document merge queue architecture","description":"Update docs/architecture.md with:\n\n- Merge Queue section explaining Beads-native approach\n- Engineer role (renamed from Refinery)\n- Session restart protocol\n- gt mq command reference\n- Federation considerations for queue\n\nAlso update any references to .gastown/ → config/.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-16T23:02:41.533065-08:00","updated_at":"2025-12-17T13:43:41.657433-08:00","closed_at":"2025-12-17T13:43:41.657433-08:00","dependencies":[{"issue_id":"gt-yls","depends_on_id":"gt-h5n","type":"blocks","created_at":"2025-12-16T23:02:56.043373-08:00","created_by":"daemon"}]}
{"id":"gt-72so","title":"gt mq list: doesn't show submitted MRs","description":"After submitting MRs with gt mq submit, gt mq list gastown shows empty queue.\n\n## Reproduction\n1. gt mq submit --issue gt-h5n.5 --branch polecat/Scabrous\n2. gt mq list gastown → (empty)\n3. bd list --type=merge-request → shows the MR\n\n## Expected\ngt mq list should show submitted MRs\n\n## MR example\ngt-ts4u has rig: gastown in description, type=merge-request, status=open","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-19T14:54:26.731813-08:00","updated_at":"2025-12-19T17:22:52.552662-08:00","closed_at":"2025-12-19T16:19:53.82455-08:00"}
{"id":"gt-sqi","title":"gt session restart/status: Complete session management","description":"Add missing session subcommands:\n\n- gt session restart \u003crig\u003e \u003cpolecat\u003e - Restart a session (stop + start)\n- gt session status \u003crig\u003e \u003cpolecat\u003e - Show session status details\n\nstatus should show:\n- Running state\n- Uptime\n- Current activity\n- Last output timestamp","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-17T21:47:34.700494-08:00","updated_at":"2025-12-19T12:56:15.214592-08:00","closed_at":"2025-12-19T12:05:27.344257-08:00","dependencies":[{"issue_id":"gt-sqi","depends_on_id":"gt-hw6","type":"blocks","created_at":"2025-12-17T22:23:43.034222-08:00","created_by":"daemon"}]}
{"id":"gt-bqbw","title":"detectSender() doesn't recognize crew workers","description":"## Problem\n\ndetectSender() in internal/cmd/mail.go only checks for /polecats/ directories. Crew workers in /crew/\u003cname\u003e/ fall through to the default 'mayor/', so:\n- gt mail inbox shows mayor's inbox instead of the crew worker's\n- gt mail send sets the wrong From address\n\n## Fix\n\nAdd crew worker detection before the /polecats/ check:\n\nif strings.Contains(cwd, \"/crew/\") {\n parts := strings.Split(cwd, \"/crew/\")\n ...\n return fmt.Sprintf(\"%s/crew/%s\", rigName, crewMember)\n}\n\n## Affected\n- Any crew worker running gt mail inbox without explicit address\n- Crew worker handoffs (wrong sender)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-18T20:09:42.556373-08:00","updated_at":"2025-12-19T01:33:49.861756-08:00","closed_at":"2025-12-19T01:33:49.861756-08:00"}
{"id":"gt-svi.3","title":"gt mq status: detailed MR view","description":"Implement 'gt mq status \u003cid\u003e' command for detailed MR view.\n\nDisplay:\n- All MR fields (branch, target, source_issue, worker, rig)\n- Current status with timestamps\n- Dependencies (what it's waiting on)\n- Blockers (what's waiting on it)\n- Processing history (attempts, failures)\n\nUnder the hood: bd show \u003cid\u003e with MR-specific formatting.\n\nReference: docs/merge-queue-design.md#command-details","status":"closed","issue_type":"task","created_at":"2025-12-17T13:50:25.119914-08:00","updated_at":"2025-12-19T12:56:15.216589-08:00","closed_at":"2025-12-18T20:05:27.406362-08:00","dependencies":[{"issue_id":"gt-svi.3","depends_on_id":"gt-h5n.1","type":"blocks","created_at":"2025-12-17T13:53:02.676972-08:00","created_by":"daemon"},{"issue_id":"gt-svi.3","depends_on_id":"gt-svi","type":"parent-child","created_at":"2025-12-17T13:50:25.121848-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":"open","priority":3,"issue_type":"task","created_at":"2025-12-15T16:52:02.390539-08:00","updated_at":"2025-12-15T23:17:16.487399-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"}]}
{"id":"gt-ktf3","title":"bd ready --type: missing type filter for MQ integration","description":"bd ready lacks --type flag that engineer.go expects.\n\n## Code (internal/refinery/engineer.go)\nreadyMRs, err := e.beads.ReadyWithType(\"merge-request\")\n\n## Actual bd ready\nNo --type flag - only supports assignee, label, priority filters.\n\n## Impact\nRefinery can't find merge-requests in queue, so MQ doesn't process anything.\n\n## Fix Options\n1. Add --type flag to bd ready\n2. Use bd list --type=merge-request --status=open instead\n3. Both (ready filters for unblocked, list for all)\n\nThis is blocking the entire MQ pipeline.","status":"closed","issue_type":"bug","created_at":"2025-12-19T14:57:16.297847-08:00","updated_at":"2025-12-19T15:04:17.322508-08:00","closed_at":"2025-12-19T15:04:17.322508-08:00"}
{"id":"gt-85a","title":"gt spawn: Not injecting work instructions to session","description":"gt spawn starts session but doesn't inject the issue assignment.\n\nRepro:\n1. gt spawn gastown/Toast --issue gt-2ux\n2. Session starts but polecat just sees Claude prompt\n3. No issue context injected\n\nExpected: Polecat should receive issue details automatically.\nActual: Polecat sits at blank prompt, needs manual injection.","status":"closed","issue_type":"bug","created_at":"2025-12-17T22:28:02.583003-08:00","updated_at":"2025-12-17T22:31:58.847834-08:00","closed_at":"2025-12-17T22:31:58.847834-08:00"}
{"id":"gt-eu9","title":"Witness session cycling and handoff","description":"Add session cycling and handoff protocol to Witness CLAUDE.md template.\n\n## Session Cycling Protocol\n\n```markdown\n## Session Cycling\n\nYour context will fill over long swarms. Proactively cycle when:\n- Running for many hours\n- Losing track of which workers you've checked\n- Responses getting slower\n- About to start complex operation\n\n### Handoff Protocol\n\n1. **Capture current state**:\n```bash\ntown list . # Worker states\ntown all beads # Pending verifications \ntown inbox # Unprocessed messages\n```\n\n2. **Compose handoff note**:\n```\n[HANDOFF_TYPE]: witness_cycle\n[TIMESTAMP]: \u003cnow\u003e\n[RIG]: \u003crig\u003e\n\n## Active Workers\n\u003clist workers and status\u003e\n\n## Pending Verifications\n\u003cworkers signaled done but not verified\u003e\n\n## Recent Actions\n\u003clast 3-5 actions\u003e\n\n## Warnings/Notes\n\u003canything next session should know\u003e\n\n## Next Steps\n\u003cwhat should happen next\u003e\n```\n\n3. **Send handoff**:\n```bash\ntown mail send \u003crig\u003e/witness -s \"Session Handoff\" -m \"\u003cnote\u003e\"\n```\n\n4. **Exit cleanly**: End session, daemon spawns fresh one.\n\n### On Fresh Session Start\n\n1. Check for handoff: `town inbox | grep \"Session Handoff\"`\n2. If found, read it and resume from handoff state\n3. If not found, do full status check\n```\n\n## Implementation\n\nAdd to WITNESS_CLAUDE.md template.","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-15T19:48:55.484911-08:00","updated_at":"2025-12-15T20:47:30.768506-08:00","dependencies":[{"issue_id":"gt-eu9","depends_on_id":"gt-82y","type":"blocks","created_at":"2025-12-15T19:49:05.846443-08:00","created_by":"daemon"}]}

View File

@@ -10,6 +10,28 @@
}
]
}
],
"PreCompact": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "gt prime"
}
]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "gt mail check --inject"
}
]
}
]
}
}

View File

@@ -1,8 +1,10 @@
package cmd
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
@@ -79,6 +81,12 @@ func runPrime(cmd *cobra.Command, args []string) error {
// Output handoff content if present
outputHandoffContent(ctx)
// Run bd prime to output beads workflow context
runBdPrime(cwd)
// Run gt mail check --inject to inject any pending mail
runMailCheckInject(cwd)
return nil
}
@@ -343,3 +351,47 @@ func outputHandoffContent(ctx RoleContext) {
fmt.Println()
fmt.Println(style.Dim.Render("(Clear with: gt rig reset --handoff)"))
}
// runBdPrime runs `bd prime` and outputs the result.
// This provides beads workflow context to the agent.
func runBdPrime(workDir string) {
cmd := exec.Command("bd", "prime")
cmd.Dir = workDir
var stdout bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = nil // Ignore stderr
if err := cmd.Run(); err != nil {
// Silently skip if bd prime fails (beads might not be available)
return
}
output := strings.TrimSpace(stdout.String())
if output != "" {
fmt.Println()
fmt.Println(output)
}
}
// runMailCheckInject runs `gt mail check --inject` and outputs the result.
// This injects any pending mail into the agent's context.
func runMailCheckInject(workDir string) {
cmd := exec.Command("gt", "mail", "check", "--inject")
cmd.Dir = workDir
var stdout bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = nil // Ignore stderr
if err := cmd.Run(); err != nil {
// Silently skip if mail check fails
return
}
output := strings.TrimSpace(stdout.String())
if output != "" {
fmt.Println()
fmt.Println(output)
}
}