Remove embedded molecule management from witness - this logic belongs
in molecule definitions (YAML + hooks), not Go code.
Removed:
- WitnessHandoffState, WorkerState types
- Handoff bead management (load/save/ensure)
- Patrol instance creation (ensurePatrolInstance)
- Polecat arm tracking (ensurePolecatArm, closePolecatArm)
- updateWorkerActivity function
Simplified:
- Nudge tracking now uses only SpawnedIssues (in-memory)
- run() no longer loads handoff state or creates patrol instances
- healthCheck() no longer manages tracking arms
Fixed:
- escalateToMayor: bd mail send → gt mail send
- ackMessage: bd mail ack → gt mail archive
The witness now does its core job (health checks, nudges, escalation,
cleanup) without trying to manage molecule state. Molecule tracking
should be handled by the molecule system itself via bd mol commands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add arm closing to witness cleanup:
- Add closePolecatArm(name, reason) method that:
- Looks up arm ID in handoff state
- Closes the arm issue with the given reason
- Clears arm ID from handoff state
- Call closePolecatArm() at end of cleanupPolecat()
This completes the arm lifecycle: created when polecat discovered,
closed when polecat cleaned up. The Christmas Ornament pattern now
tracks the full polecat lifecycle.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add arm bonding to witness health check:
- Add ensurePolecatArm() method that:
- Checks if arm already exists for polecat (ArmID in WorkerState)
- If not, calls `gt mol bond mol-polecat-arm` with template vars
- Parses arm ID from output and stores in handoff state
- Call ensurePolecatArm() in healthCheck() for each running polecat
This creates the Christmas Ornament pattern where mol-witness-patrol
has dynamically bonded mol-polecat-arm children, one per active polecat.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add patrol instance tracking to witness manager:
- Add PatrolInstanceID to WitnessHandoffState for tracking
- Add ArmID to WorkerState for per-polecat arm tracking
- Add ensurePatrolInstance() method that:
- Checks if patrol instance already exists (from previous session)
- Creates new patrol instance if needed
- Persists instance ID in handoff state
This enables the molecule-based tracking ledger pattern where the
Go-based witness creates beads issues to track its patrol state.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add BranchPushedToRemote() to git package that properly handles
polecat branches without upstream tracking. Update verifyPolecatState
in witness to check that branches are pushed before allowing cleanup.
This prevents the scenario where polecats close issues without pushing
their work, causing all commits to be lost when the worktree is deleted.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add handling for POLECAT_DONE messages in processShutdownRequests()
- Track which polecats have signaled done (using SpawnedIssues with "done:" prefix)
- For LIFECYCLE:shutdown requests, wait for POLECAT_DONE before cleanup
- Add checkPendingCompletions() to nudge polecats with closed issues
- Add 10-minute timeout with force-kill after waiting for POLECAT_DONE
- Protects against losing MR submissions when Witness cleans up too early
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add persistent state storage for Witness across wisp burns:
- Add WorkerState and WitnessHandoffState types
- Implement loadHandoffState/saveHandoffState for bead persistence
- Update getNudgeCount/recordNudge to use persistent state
- Add activity tracking integration into healthCheck
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- .beads-ephemeral/ -> .beads-wisp/
- Rename doctor checks: EphemeralCheck -> WispCheck
- Update all docs to use 'transient' for polecats, 'wisp' for molecules
- Preserve 'ephemeral' only as descriptive adjective for wisps
- Steam engine metaphor: wisps are steam vapors that dissipate
Part of Christmas launch wisp terminology unification.
Add isChildOfEpic() function that checks if an issue is a child of
the configured epic by verifying the issue has the epic in its
dependents with dependency_type="blocks".
When EpicID is configured in witness config, only issues that block
that epic will be considered for auto-spawning. Issues that cannot
be verified are safely skipped.
Closes gt-zhm5.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- docs/architecture.md: update mail routing explanation
- internal/witness/manager.go: fix actual bd mail calls to gt mail
- internal/cmd/mail.go: remove stale compatibility note
- internal/daemon/lifecycle.go: update comment
Add comprehensive uncommitted work checks before any polecat cleanup:
- Check for uncommitted changes (modified/untracked files)
- Check for stashes
- Check for unpushed commits
Affected commands:
- gt polecat remove: now refuses if uncommitted work exists
- gt rig shutdown: checks all polecats before shutdown
- Witness cleanup: refuses to clean polecats with uncommitted work
- gt spawn: warns if spawning to polecat with uncommitted work
Safety model:
- --force: bypasses uncommitted changes check only
- --nuclear: bypasses ALL safety checks (will lose work)
New git helpers:
- StashCount(): count stashes in repo
- UnpushedCommits(): count commits not pushed to upstream
- CheckUncommittedWork(): comprehensive work status check
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the core Witness functionality:
- gt witness start: Creates tmux session with Claude, theming, auto-priming
- gt witness stop: Kills tmux session and updates state
- gt witness status: Shows session state reconciled with tmux
- Shutdown handler: Verifies git clean state before cleanup, sends nudges
- Auto-spawn: Spawns polecats for ready work up to configurable capacity
- Health checks: Monitors polecat activity, nudges stuck workers, escalates
Also updates handoff to include polecat name in lifecycle requests.
Closes: gt-53w6, gt-mxyj, gt-5wtw, gt-cpm2, gt-es1i
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix ~50 errcheck warnings across the codebase:
- Add explicit `_ =` for intentionally ignored error returns (cleanup,
best-effort operations, etc.)
- Use `defer func() { _ = ... }()` pattern for defer statements
- Handle tmux SetEnvironment, KillSession, SendKeysRaw returns
- Handle mail router.Send returns
- Handle os.RemoveAll, os.Rename in cleanup paths
- Handle rand.Read returns for ID generation
- Handle fmt.Fprint* returns when writing to io.Writer
- Fix for-select with single case to use for-range
- Handle cobra MarkFlagRequired returns
All tests pass. Code compiles without errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This implements the ephemeral polecat model where polecats are spawned
fresh for each task and deleted upon completion.
Key changes:
**Spawn (internal/cmd/spawn.go):**
- Always create fresh worktree from main branch
- Run bd init in new worktree to initialize beads
- Remove --create flag (now implicit)
- Replace stale polecats with fresh worktrees
**Handoff (internal/cmd/handoff.go):**
- Add rig/polecat detection from environment and tmux session
- Send shutdown requests to correct witness (rig/witness)
- Include polecat name in lifecycle request body
**Witness (internal/witness/manager.go):**
- Add mail checking in monitoring loop
- Process LIFECYCLE shutdown requests
- Implement full cleanup sequence:
- Kill tmux session
- Remove git worktree
- Delete polecat branch
**Polecat state machine (internal/polecat/types.go):**
- Primary states: working, done, stuck
- Deprecate idle/active (kept for backward compatibility)
- New polecats start in working state
- ClearIssue transitions to done (not idle)
**Polecat commands (internal/cmd/polecat.go):**
- Update list to show "Active Polecats"
- Normalize legacy states for display
- Add deprecation warnings to wake/sleep commands
Closes gt-7ik
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the witness monitoring agent command with start, stop, and status
subcommands. The witness monitors polecats for stuck/idle states and
can nudge blocked workers.
Closes gt-kcee
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>