Commit Graph

61 Commits

Author SHA1 Message Date
mayor
94c2d71c13 fix(tmux): kill pane processes before all RespawnPane calls to prevent orphans
## Problem
Claude processes were accumulating as orphans, with 100+ processes piling up
daily. Every `gt handoff` (used dozens of times/hour by crew) left orphaned
processes because `tmux respawn-pane -k` only sends SIGHUP, which Node/Claude
ignores.

## Root Cause
Previous fixes (1043f00d, f89ac47f, 2feefd17, 1b036aad) were laser-focused on
specific symptoms (shutdown, setsid, done.go, molecule_step.go) but never did
a comprehensive audit of ALL RespawnPane call sites. handoff.go was never
fixed despite being the main source of orphans.

## Solution
Added KillPaneProcesses() call before every RespawnPane() in:
- handoff.go (self handoff and remote handoff)
- mayor.go (mayor restart)
- crew_at.go (new session and restart)

KillPaneProcesses explicitly kills all descendant processes with SIGTERM/SIGKILL
before respawning, preventing orphans regardless of SIGHUP handling.

molecule_step.go already had this fix from commit 1b036aad.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:09:30 -08:00
morsov
39b1c11bb6 fix(handoff): use env var fallback when town root detection fails
When the repo is in a broken state (wrong branch, detached HEAD, deleted
worktree), gt handoff would fail with "cannot detect town root" error.
This is exactly when handoff is most needed - to recover and hand off
to a fresh session.

Changes:
- detectTownRootFromCwd() now falls back to GT_TOWN_ROOT and GT_ROOT
  environment variables when cwd-based detection fails
- buildRestartCommand() now propagates GT_ROOT to ensure subsequent
  handoffs can also use the fallback
- Added tests for the fallback behavior

Fixes gt-x2q81.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:05:00 -08:00
joshuavial
48ace2cbf3 fix(handoff): preserve GT_AGENT across session restarts (#788)
Adds GT_AGENT env var to track agent override when using --agent flag.
Handoff reads and preserves GT_AGENT so non-default agents persist across restarts.

Co-authored-by: joshuavial <git@codewithjv.com>
2026-01-20 14:17:52 -08:00
aleiby
08cee416a4 fix(handoff): normalize identity in sendHandoffMail (#780)
The handoff mail bead was created with un-normalized assignee
(e.g., gastown/crew/holden) but mailbox queries use normalized identity
(gastown/holden), causing self-mail to be invisible to the inbox.

Export addressToIdentity as AddressToIdentity and call it in
sendHandoffMail() to normalize the agent identity before storing,
matching the normalization performed in Router.sendToSingle().

Fix handoff mail delivery (hq-snp8)
2026-01-20 14:09:54 -08:00
Julian Knutsen
1453b8b592 fix(handoff): use correct witness working directory (#444)
The witness role doesn't have a /rig worktree like the refinery does.
The handoff command was trying to cd to <rig>/witness/rig which doesn't
exist, causing the respawned pane to fail immediately and the session
to die.

Changed witness workdir from <rig>/witness/rig to <rig>/witness.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:39:55 -08:00
beads/crew/emma
bedccb1634 fix(handoff): use workspace.FindFromCwd for town root detection
detectTownRootFromCwd() only checked for mayor/town.json, but
workspace.FindFromCwd() also accepts mayor/ directory as a secondary
marker. This fixes handoff failing in workspaces without town.json.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:27:25 -08:00
gastown/crew/joe
716bab396f fix(sling): resolve crew members correctly with shorthand paths
When using gastown/max style paths, resolvePathToSession was treating
all non-role names as polecats, generating gt-gastown-max instead of
gt-gastown-crew-max.

Now checks if <townRoot>/<rig>/crew/<name> exists before defaulting
to polecat format. This fixes gt sling to crew members using the
shorthand rig/name syntax.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 03:04:05 -08:00
Tanwa Arpornthip
956f8cc5f0 fix(handoff): recognize polecat session pattern gt-<rig>-<name> (#373)
sessionWorkDir had cases for mayor, deacon, crew, witness, and refinery
but not polecats. When gt handoff was run from a polecat session like
gt-tanwa_info-slit, it failed with "unknown session type".

Fix uses session.ParseSessionName to parse the session name and extract
rig/name for polecat sessions, mapping to <townRoot>/<rig>/polecats/<name>.

Fixes: gm-lie6

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 22:36:14 -08:00
mayor
db353c247b feat: implement priming subsystem improvements
Phase 1 of dynamic priming subsystem:

1. PRIME.md provisioning for all workers (hq-5z76w, hq-ukjrr Part A)
   - Added ProvisionPrimeMD to beads package with Gas Town context template
   - Provision at rig level in AddRig() so all workers inherit it
   - Added fallback provisioning in crew and polecat managers
   - Created PRIME.md for existing rigs

2. Post-handoff detection to prevent handoff loop bug (hq-ukjrr Part B)
   - Added FileHandoffMarker constant (.runtime/handoff_to_successor)
   - gt handoff writes marker before respawn
   - gt prime detects marker and outputs "HANDOFF COMPLETE" warning
   - Marker cleared after detection to prevent duplicate warnings

3. Priming health checks for gt doctor (hq-5scnt)
   - New priming_check.go validates priming subsystem configuration
   - Checks: SessionStart hook, gt prime command, PRIME.md presence
   - Warns if CLAUDE.md is too large (should be bootstrap pointer)
   - Fixable: provisions missing PRIME.md files

This ensures crew workers get Gas Town context (GUPP, hooks, propulsion)
even if the gt prime hook fails, via bd prime fallback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 01:07:01 -08:00
rictus
b8075a5e06 fix(sling): accept bead IDs directly even when routing fails
When routing-based verification (verifyBeadExists) fails due to
routes.jsonl configuration issues, gt sling now falls back to pattern
matching via looksLikeBeadID to accept valid bead ID formats.

The fix ensures:
1. verifyBeadExists is tried first (routing-based lookup)
2. verifyFormulaExists is tried second (formula check)
3. looksLikeBeadID pattern match is used as final fallback

Also improved looksLikeBeadID to accept any 1-5 letter lowercase
prefix followed by hyphen and alphanumeric chars.

Fixes: gt sling bd-xxx failing with "not a valid bead or formula"
when the bead exists but routing cannot find it.

Closes: gt-9e8s5

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:13:11 -08:00
gastown/crew/george
86739556c2 fix(prime): use startup beacon instead of bare "gt prime" prompt
Agents were confused when receiving "gt prime" as their first prompt,
interpreting it as a command to investigate rather than understanding
they were starting a Gas Town session.

Changed crew_at.go, start.go, and handoff.go to use FormatStartupNudge()
which produces a proper beacon like:
  [GAS TOWN] george/crew/george <- human • 2026-01-09T10:30 • start

The SessionStart hook (gt prime --hook) still injects context - the
prompt just needs to be something agents recognize as a greeting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 13:30:11 -08:00
Ben Kraus
38adfa4d8b codex 2026-01-08 12:36:54 -05:00
gastown/crew/joe
1f44482ad0 fix: remove observable states from agent_state (discover, don't track)
The agent_state field was recording observable state like "running",
"dead", "idle" which violated the "Discover, Don't Track" principle.
This caused stale state bugs where agents were marked "dead" in beads
but actually running in tmux.

Changes:
- Remove daemon's checkStaleAgents() which marked agents "dead"
- Simplify ensureXxxRunning() to use tmux.IsClaudeRunning() directly
- Remove reportAgentState() calls from gt prime and gt handoff
- Add SetHookBead/ClearHookBead helpers that don't update agent_state
- Use ClearHookBead in gt done and gt unsling
- Simplify gt status to derive state from tmux, not bead

Non-observable states (stuck, awaiting-gate, muted, paused) are still
set because they represent intentional agent decisions that can't be
discovered from tmux state.

Fixes: gt-zecmc

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 20:32:02 -08:00
Martin Emde
9e416e9ff5 Fix handoff loses claude code environment variables (#216)
buildRestartCommand() now propagates Claude-related env vars when
respawning sessions via tmux. Fresh shells don't inherit parent env,
so CLAUDE_CODE_USE_BEDROCK, ANTHROPIC_API_KEY, AWS_*, etc. were lost.
This caused any tmux respawn to result in a non-functional claude.

Adds claudeEnvVars list and includes them in the export command when
building the restart command.
2026-01-06 12:59:45 -08:00
max
1b69576573 fix: Address golangci-lint errors (errcheck, gosec) (#76)
Apply PR #76 from dannomayernotabot:

- Add golangci exclusions for internal package false positives
- Tighten file permissions (0644 -> 0600) for sensitive files
- Add ReadHeaderTimeout to HTTP server (slowloris prevention)
- Explicit error ignoring with _ = for intentional cases
- Add //nolint comments with justifications
- Spelling: cancelled -> canceled (US locale)

Co-Authored-By: dannomayernotabot <noreply@github.com>

🤖 Generated with Claude Code
2026-01-03 16:11:55 -08:00
markov-kernel
e7145cfd77 fix: Make Mayor/Deacon session names include town name
Session names `gt-mayor` and `gt-deacon` were hardcoded, causing tmux
session name collisions when running multiple towns simultaneously.

Changed to `gt-{town}-mayor` and `gt-{town}-deacon` format (e.g.,
`gt-ai-mayor`) to allow concurrent multi-town operation.

Key changes:
- session.MayorSessionName() and DeaconSessionName() now take townName param
- Added workspace.GetTownName() helper to load town name from config
- Updated all callers in cmd/, daemon/, doctor/, mail/, rig/, templates/
- Updated tests with new session name format
- Bead IDs remain unchanged (already scoped by .beads/ directory)

Fixes #60

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:37:05 +01:00
furiosa
ff37d2213a feat(done): Add --exit flag for session self-termination (gt-lynar)
Add --exit flag to `gt done` that terminates the Claude session
immediately after submitting the MR to the merge queue. This prevents
polecats from sitting idle (and wasting money) while waiting for the
Witness to kill them.

Changes:
- Rename existing --exit flag to --status (for exit type)
- Add new --exit boolean flag for session self-termination
- Update docs and help text to reflect new flag names

Usage: gt done --exit

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 13:43:32 -08:00
valkyrie
1e2a068b2a feat(cmd): Add --collect to handoff and --handoff to resume (gt-1le)
- Add --collect/-c flag to gt handoff: auto-collects hooked work,
  inbox summary, ready beads, and in-progress items into the handoff
  message body
- Add --handoff flag to gt resume: checks inbox for messages with
  "HANDOFF" in subject and displays them formatted for continuation
- Supports both JSON and plain-text inbox output formats

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 19:11:04 -08:00
gastown/polecats/cal
3444e3acdc feat(handoff): Auto-hook mail bead when created with -m flag (gt-frhcq.3)
When gt handoff is run with -s and -m flags, it now:
- Creates the handoff mail bead directly using bd create
- Captures the created bead ID
- Auto-hooks the bead with status=hooked so the next session picks it up

This enables the handoff workflow:
  gt handoff -s "Title" -m "Instructions..."

The next session startup hook (gt prime) will detect the hooked bead
and present it to the agent for immediate execution.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 12:11:42 -08:00
gastown/crew/gus
626a24e013 Refactor startup paths to use RuntimeConfig (gt-j0546)
Replaced all hardcoded 'claude --dangerously-skip-permissions' invocations
with configurable helpers from internal/config:

- GetRuntimeCommand(rigPath) - simple command string
- GetRuntimeCommandWithPrompt(rigPath, prompt) - with initial prompt
- BuildAgentStartupCommand(role, bdActor, rigPath, prompt) - generic agent
- BuildPolecatStartupCommand(rigName, polecatName, rigPath, prompt) - polecat
- BuildCrewStartupCommand(rigName, crewName, rigPath, prompt) - crew
- BuildStartupCommand(envVars, rigPath, prompt) - custom env vars

Files updated:
- internal/cmd/start.go (4 locations)
- internal/cmd/crew_lifecycle.go (2 locations)
- internal/cmd/crew_at.go (2 locations)
- internal/cmd/deacon.go
- internal/cmd/witness.go
- internal/cmd/up.go (2 locations)
- internal/cmd/handoff.go (2 locations)
- internal/daemon/daemon.go (3 locations)
- internal/daemon/lifecycle.go
- internal/session/manager.go
- internal/refinery/manager.go
- internal/boot/boot.go

This enables future support for alternative LLM runtimes (aider, etc.)
via rig/town settings configuration.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 23:48:34 -08:00
gastown/crew/joe
d55858b554 Fix GUPP: inject "gt prime" as initial prompt in handoff
Agents weren't auto-executing after gt handoff because the SessionStart
hook only outputs text - it doesn't inject a prompt. Claude needs actual
user input to trigger a response.

The fix: pass "gt prime" as an argument to claude, just like gt crew at
already does. This treats the argument as the first user prompt, which
triggers GUPP execution immediately.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 19:25:50 -08:00
Steve Yegge
3099d99424 Set GIT_AUTHOR_NAME per agent session (gt-6r18e.1)
Export GIT_AUTHOR_NAME alongside BD_ACTOR in all agent session startup
locations. This enables git log --author queries for agent work while
keeping GIT_AUTHOR_EMAIL as the workspace owner.

Files updated:
- internal/session/manager.go (polecat sessions)
- internal/daemon/daemon.go (deacon, witness, polecat via daemon)
- internal/daemon/lifecycle.go (polecat lifecycle)
- internal/cmd/*.go (crew, mayor, deacon, witness, refinery, up, handoff)
- internal/session/manager_test.go (updated test expectations)
- docs/federation.md (marked feature as implemented)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 16:14:33 -08:00
Steve Yegge
2844edb541 Instrument gt commands to appear in activity feed (gt-7aw1m)
Phase 1 of activity feed improvements: gt commands now log events to
~/gt/.events.jsonl. This is the raw audit log that the feed daemon
(phase 2) will curate into the user-facing feed.

Instrumented commands:
- gt sling: logs sling events with bead and target
- gt hook: logs hook events with bead
- gt handoff: logs handoff events with subject
- gt done: logs done events with bead and branch
- gt mail send: logs mail events with to and subject

Event format follows the specification:
```json
{"ts":"2025-12-30T07:36:28Z","source":"gt","type":"mail",
 "actor":"gastown/crew/joe","payload":{...},"visibility":"feed"}
```

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 23:37:50 -08:00
Steve Yegge
d72e86493e Merge morsov: AgentIdentity, session helpers 2025-12-28 18:45:14 -08:00
Steve Yegge
5e9ca4c618 Standardize warning output to use style.PrintWarning (gt-g6kor)
- Add PrintWarning helper in internal/style/style.go
- Update 35 warning message outputs across 16 files to use consistent format
- All warnings now display as "⚠ Warning: <message>" in yellow/bold

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 16:38:04 -08:00
Steve Yegge
fa79d06d0e Add AgentIdentity type for session name parsing (gt-ov2uv)
Create AgentIdentity type to parse and construct session names, replacing
duplicated logic in sling.go and handoff.go.

- Add internal/session/identity.go with AgentIdentity type
- ParseSessionName handles: mayor, deacon, witness, refinery, crew, polecat
- SessionName() reconstructs valid tmux session name
- Address() returns mail-style address (e.g., "gastown/crew/max")
- GTRole() returns GT_ROLE env var format
- Update sling.go:sessionToAgentID to use ParseSessionName
- Update handoff.go:sessionToGTRole to use ParseSessionName
- Add comprehensive unit tests with round-trip verification

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 16:23:15 -08:00
Steve Yegge
31b663cec2 deacon patrol: 21 cycles complete 2025-12-28 02:07:33 -08:00
Steve Yegge
9d09a1f540 fix: Make sling target path parsing more forgiving (gt-e0u3r)
Now accepts:
- gastown/nux (polecat shorthand)
- gastown/Nux (case-insensitive)
- gastown/polecats/nux (explicit path)
- gastown/crew/max (unchanged)
- gastown/witness (unchanged)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 00:54:27 -08:00
Steve Yegge
8131052207 Deprecate hook files, use pinned beads for propulsion (gt-rgd9x)
Replace hook file mechanism with discovery-based pinned beads:
- gt hook: now runs bd update <bead> --status=pinned
- gt sling: same, plus nudge to target
- gt handoff: same when bead ID provided
- gt prime: checks pinned beads instead of hook files
- gt mol status: no longer checks hook files

Key changes:
- outputAttachmentStatus: extended to all roles (was Crew/Polecat only)
- checkSlungWork: now queries pinned beads instead of reading hook files
- wisp/io.go functions: marked deprecated with migration notes

This follows Gas Town discovery over explicit state principle.
Hook files are kept for backward compatibility but no longer written.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 15:56:11 -08:00
Steve Yegge
e2b8f16c48 Implement town activity logging (gt-ewzon)
Add centralized logging for Gas Town agent lifecycle events:
- spawn: new agent created
- wake: agent resumed
- nudge: message injected
- handoff: agent handed off
- done: agent finished work
- crash: agent exited unexpectedly
- kill: agent killed intentionally

Implementation:
- Add internal/townlog package with LogEvent() function
- Log to ~/gt/logs/town.log with human-readable format
- Add gt log command to view/tail/filter logs
- Integrate logging into spawn, nudge, handoff, done, stop, session commands

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 15:51:54 -08:00
Steve Yegge
f7d7f27d92 Fix gt sling code review issues (gt-z9qoo)
- Fix hook location for remote targets using tmux.GetPaneWorkDir()
- Add --var/--on conflict error check
- Add warning for JSON parse fallback (not yet fatal)
- Capture stderr for wisp command
- Remove dead code: detectAgentIdentity(), detectAgentIdentityForHook(),
  detectCloneRootForHook()
- Extract resolveSelfTarget() helper to reduce role-switching duplication

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 22:45:33 -08:00
Steve Yegge
f7e29236d1 Fix dry-run bug in gt handoff - check before side effects (gt-sq0t3) 2025-12-25 22:06:05 -08:00
Steve Yegge
9afd6c5572 feat: Set BD_ACTOR env var when spawning agents (gt-rhfji)
When gt spawns agents (polecats, crew, patrol roles), it now sets the
BD_ACTOR env var so that bd commands (like `bd hook`) know the agent
identity without coupling to gt.

Updated spawn points:
- gt up (mayor, deacon, witness via ensureSession/ensureWitness)
- gt deacon start
- gt witness start
- gt start refinery
- gt mayor start
- Daemon deacon restart
- Daemon lifecycle restart
- Handoff respawn
- Refinery manager start

BD_ACTOR uses slash format (e.g., gastown/witness, gastown/crew/max)
while GT_ROLE may use dash format internally.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 13:26:38 -08:00
Steve Yegge
f86a73c2f0 feat: Add gcloud-style command grouping to gt help output
Organize 43 commands into 7 logical groups using cobra's built-in
AddGroup/GroupID feature:

- Work Management: spawn, sling, hook, handoff, done, mol, mq, etc.
- Agent Management: mayor, witness, refinery, deacon, polecat, etc.
- Communication: mail, nudge, broadcast, peek
- Services: daemon, start, stop, up, down, shutdown
- Workspace: rig, crew, init, install, git-init, namepool
- Configuration: account, theme, hooks, issue, completion
- Diagnostics: status, doctor, prime, version, help

Also renamed molecule to mol as the primary command name
(molecule is now an alias).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:32:01 -08:00
Steve Yegge
818a8a41f9 Clear tmux scrollback on handoff
Adds ClearHistory method to tmux package and calls it before
respawn-pane during handoff. This resets copy-mode display
from [0/N] to [0/0] for a clean session start.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:07:23 -08:00
Steve Yegge
2f4a35392c Add gt role command group for env-based role detection (gt-1xsah)
- New gt role subcommands: show, home, detect, list, env
- Role detection now checks GT_ROLE env var first, falls back to cwd
- gt prime shows warning when role/cwd mismatch detected
- gt mol status uses env-aware role detection
- gt handoff injects GT_ROLE and resets to role canonical home
- Fixed witness/refinery home paths (was missing /rig suffix)

This prevents role confusion when agents wander to wrong directories.
After handoff, agents are always restored to their canonical home.
2025-12-25 00:58:42 -08:00
Steve Yegge
32cac078e5 refactor: split gt sling into gt hook + gt handoff <bead> (gt-z4bw)
- Add gt hook <bead>: durability primitive, attaches work to hook
- Update gt handoff: accept optional bead arg (detects bead vs role)
- Deprecate gt sling: shows warning, points to new commands
- Update doctor fix hint to reference new commands

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:41:51 -08:00
Steve Yegge
9c85b834cd Support full session paths in gt handoff (gt-tocb)
resolveRoleToSession now accepts paths like <rig>/crew/<name>,
<rig>/witness, and <rig>/refinery in addition to role shortcuts.
For example: 'gt handoff gastown/crew/max' now works.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:25:59 -08:00
Steve Yegge
1414081e10 Standardize session end with gt handoff (gt-yt6g)
- Update gt handoff to detect polecats (via GT_POLECAT env var) and
  call gt done instead of respawning - polecats have Witness-managed lifecycle
- Update CLAUDE.md Session End Checklist to use gt handoff
- This is the canonical way to end any agent session - it handles mail,
  respawn, and context restoration via SessionStart hook

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:07:26 -08:00
Steve Yegge
e3500543f3 Fix handoff to set correct working directory for each role
buildRestartCommand now detects the town root and includes a cd to the
appropriate directory before launching claude. This ensures each role
starts in its correct working directory:
- gt-mayor → town root (~/gt)
- gt-deacon → ~/gt/deacon
- crew sessions → ~/gt/<rig>/crew/<name>
- witness sessions → ~/gt/<rig>/witness
- refinery sessions → ~/gt/<rig>/refinery

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 12:59:41 -08:00
Steve Yegge
18fb0e05fe feat(handoff): add -s/-m flags for ergonomic handoff mail
Agents naturally expect `gt handoff -s "Subject" -m "Message"` to work
like `gt mail send`. Now it does:

- Added --subject/-s and --message/-m flags to gt handoff
- Added --self flag to gt mail send for sending to self
- Handoff auto-sends mail to self before respawning pane

This makes agent-initiated handoff more ergonomic - they can include
context in a single command instead of two separate steps.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:51:47 -08:00
Steve Yegge
a5a37f5d63 Fix: /handoff regression - use respawn-pane with direct claude command
Three related fixes:

1. lifecycle.go: Use gt mail delete instead of gt mail read to prevent
   lifecycle requests from accumulating.

2. handoff.go: Return exec claude command for respawn-pane instead of
   gt crew at which tries to attach to existing session.

3. handoff.md skill: Work without --cycle and -m flags, send mail separately.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:23:40 -08:00
Steve Yegge
f284941a5b Rename gt recycle to gt handoff
Consistent naming throughout:
- internal/cmd/recycle.go → handoff.go
- All variable/function names updated
- /handoff Claude Code command updated
- polecat.md prompt updated

Also includes session.go doc improvements (nudge preference).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:33:14 -08:00
Steve Yegge
97e0535bfe Implement three-tier config architecture (gt-k1lr tasks 1-5)
**Architecture changes:**
- Renamed `.gastown/` → `.runtime/` for runtime state (gitignored)
- Added `settings/` directory for rig behavioral config (git-tracked)
- Added `mayor/config.json` for town-level config (MayorConfig type)
- Separated RigConfig (identity) from RigSettings (behavioral)

**File location changes:**
- Town runtime: `~/.gastown/*` → `~/.runtime/*`
- Rig runtime: `<rig>/.gastown/*` → `<rig>/.runtime/*`
- Rig config: `<rig>/.gastown/config.json` → `<rig>/settings/config.json`
- Namepool state: `namepool.json` → `namepool-state.json`

**New types:**
- MayorConfig: town-level behavioral config
- RigSettings: rig behavioral config (merge_queue, theme, namepool)
- RigConfig now identity-only (name, git_url, beads, created_at)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 01:22:43 -08:00
Steve Yegge
ff654eee59 feat(mq): auto-cleanup polecats after MR submission
When `gt mq submit` is run from a polecat work branch (polecat/<worker>/<issue>),
it now automatically triggers polecat shutdown after submitting the MR. The
polecat sends a lifecycle request to its Witness and waits for termination.

This eliminates the need for polecats to manually run `gt handoff --shutdown`
after completing work - they can just run `gt mq submit` and the cleanup
happens automatically.

Added `--no-cleanup` flag to disable auto-cleanup when needed (e.g., for
submitting multiple MRs or continuing work).

Closes gt-tca

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 11:44:35 -08:00
Steve Yegge
199da5aa9b fix(handoff): write crew state.json to correct location
The daemon verifies requesting_cycle=true in state.json before
executing lifecycle actions. For crew workers, the state file
must be at <townRoot>/<rig>/crew/<name>/state.json.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 01:24:56 -08:00
Steve Yegge
dbecfe1d38 feat(handoff): route crew lifecycle requests to deacon
Crew workers now use deacon for lifecycle management instead of
requiring manual session termination. When a crew worker runs
'gt handoff', it sends a lifecycle request to the deacon which
handles session kill/restart like it does for Mayor and Witness.

Changes:
- Route crew manager to deacon/ instead of "human"
- Add getCrewIdentity() to extract <rig>-crew-<name> from session
- Include full crew identity in LIFECYCLE subject for daemon parsing
- Remove special case that skipped lifecycle flow for crew

Also fixes pre-existing test failures in daemon/lifecycle_test.go
where BeadsMessage field names were out of sync with the struct.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 01:17:32 -08:00
Steve Yegge
4073638fa1 fix: crew workers detected as polecat in gt handoff
- Add crew session detection before polecat (gt-*-crew-* pattern)
- Crew workers exit immediately after sending handoff mail
- No waiting for manager since crew is human-managed

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 23:35:22 -08:00
Steve Yegge
80aa280e04 fix: use gt mail instead of bd mail in handoff command
bd doesn't have a mail subcommand - mail routing goes through gt.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 23:31:25 -08:00
Steve Yegge
96c773f570 Merge beads-sync branch
Sync beads changes and code updates.

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 21:23:39 -08:00