feat: Witness reads polecat state from agent beads (gt-gizsv)
Changes: 1. Fix reportAgentState in prime.go to use beads API directly instead of non-existent `bd agent state` command. Agents now properly self-report their state to their agent beads on startup. 2. Update witness patrol survey-workers step to use agent beads: - List polecats via `bd list --type=agent --json` - Filter by role_type: polecat in description - Check agent_state field (running/idle/stuck/done) - Trust agent-reported state (ZFC principle) No more PID/tmux inference for polecat state - agents self-report. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -133,61 +133,71 @@ id = "survey-workers"
|
|||||||
title = "Inspect all active polecats"
|
title = "Inspect all active polecats"
|
||||||
needs = ["check-refinery"]
|
needs = ["check-refinery"]
|
||||||
description = """
|
description = """
|
||||||
Survey all polecats and take action on stuck workers.
|
Survey all polecats using agent beads (ZFC: trust what agents report).
|
||||||
|
|
||||||
|
**Step 1: List polecat agent beads**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gt polecat list <rig>
|
bd list --type=agent --json
|
||||||
```
|
```
|
||||||
|
|
||||||
**For each polecat, assess:**
|
Filter the JSON output for entries where description contains `role_type: polecat`.
|
||||||
|
Each polecat agent bead has fields in its description:
|
||||||
|
- `role_type: polecat`
|
||||||
|
- `rig: <rig-name>`
|
||||||
|
- `agent_state: running|idle|stuck|done`
|
||||||
|
- `hook_bead: <current-work-id>`
|
||||||
|
|
||||||
1. **Capture tmux state**:
|
**Step 2: For each polecat, check agent_state**
|
||||||
|
|
||||||
|
| agent_state | Meaning | Action |
|
||||||
|
|-------------|---------|--------|
|
||||||
|
| running | Actively working | Check progress (Step 3) |
|
||||||
|
| idle | No work assigned | Skip (no action needed) |
|
||||||
|
| stuck | Self-reported stuck | Handle stuck protocol |
|
||||||
|
| done | Work complete | Verify cleanup triggered |
|
||||||
|
|
||||||
|
**Step 3: For running polecats, assess progress**
|
||||||
|
|
||||||
|
Check the hook_bead field to see what they're working on:
|
||||||
```bash
|
```bash
|
||||||
tmux capture-pane -t gt-<rig>-<name> -p | tail -50
|
bd show <hook_bead> # See current step/issue
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Determine status** (ZFC - you make the judgment):
|
You can also verify they're responsive:
|
||||||
- **working**: Recent tool calls, active processing
|
|
||||||
- **idle**: At prompt, no recent activity
|
|
||||||
- **error**: Showing errors or stack traces
|
|
||||||
- **done**: Showing completion indicators (should have sent POLECAT_DONE)
|
|
||||||
|
|
||||||
3. **Check beads progress**:
|
|
||||||
```bash
|
```bash
|
||||||
bd hook --agent <rig>/polecats/<name> # What step are they on?
|
tmux capture-pane -t gt-<rig>-<name> -p | tail -20
|
||||||
```
|
```
|
||||||
- Has their step changed since you last looked?
|
|
||||||
- How long on current step? (Check step timestamps)
|
|
||||||
|
|
||||||
4. **Decide action** (fresh judgment each cycle, no counters):
|
Look for:
|
||||||
|
- Recent tool activity → making progress
|
||||||
|
- Idle at prompt → may need nudge
|
||||||
|
- Error messages → may need help
|
||||||
|
|
||||||
|
**Step 4: Decide action**
|
||||||
|
|
||||||
| Observation | Action |
|
| Observation | Action |
|
||||||
|-------------|--------|
|
|-------------|--------|
|
||||||
| Actively working | None |
|
| agent_state=running, recent activity | None |
|
||||||
| Just started step (<5 min) | None |
|
| agent_state=running, idle 5-15 min | Gentle nudge |
|
||||||
| Idle 5-15 min, same step | Gentle nudge |
|
| agent_state=running, idle 15+ min | Direct nudge with deadline |
|
||||||
| Idle 15+ min, same step | Direct nudge with deadline |
|
| agent_state=stuck | Assess and help or escalate |
|
||||||
| Idle 30+ min despite nudges | Escalate to Mayor |
|
| agent_state=done, cleanup pending | Verify cleanup wisp exists |
|
||||||
| Showing errors | Assess severity, help or escalate |
|
|
||||||
| Says "done" but no POLECAT_DONE | Nudge to send completion mail |
|
|
||||||
|
|
||||||
5. **Execute nudges**:
|
**Step 5: Execute nudges**
|
||||||
```bash
|
```bash
|
||||||
gt nudge <rig>/polecats/<name> "How's progress on <step>? Need help?"
|
gt nudge <rig>/polecats/<name> "How's progress? Need help?"
|
||||||
```
|
```
|
||||||
|
|
||||||
6. **Escalate stuck workers**:
|
**Step 6: Escalate if needed**
|
||||||
```bash
|
```bash
|
||||||
gt mail send mayor/ -s "Escalation: <polecat> stuck" \
|
gt mail send mayor/ -s "Escalation: <polecat> stuck" \\
|
||||||
-m "Polecat <name> has been idle on <step> for <duration>.
|
-m "Polecat <name> reports stuck. Please intervene."
|
||||||
Nudges ineffective. Please intervene."
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parallelism**: Use Task tool subagents to inspect multiple polecats concurrently.
|
**Parallelism**: Use Task tool subagents to inspect multiple polecats concurrently.
|
||||||
Launch one subagent per polecat for capture/assess/decide/act cycle.
|
|
||||||
|
|
||||||
**No persistent state**: Each cycle is a fresh observation.
|
**ZFC Principle**: Trust agent_state from beads. Don't infer state from PID/tmux."""
|
||||||
"Nudge count" is replaced by "how long stuck on same step" which is discoverable from beads timestamps."""
|
|
||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
id = "context-check"
|
id = "context-check"
|
||||||
|
|||||||
@@ -1052,7 +1052,7 @@ func acquireIdentityLock(ctx RoleContext) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// reportAgentState calls bd agent state to report the agent's current state.
|
// reportAgentState updates the agent bead to report the agent's current state.
|
||||||
// This implements ZFC-compliant self-reporting of agent state.
|
// This implements ZFC-compliant self-reporting of agent state.
|
||||||
// Agents call this on startup (running) and shutdown (stopped).
|
// Agents call this on startup (running) and shutdown (stopped).
|
||||||
func reportAgentState(ctx RoleContext, state string) {
|
func reportAgentState(ctx RoleContext, state string) {
|
||||||
@@ -1061,15 +1061,14 @@ func reportAgentState(ctx RoleContext, state string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call bd agent state <id> <state>
|
// Use the beads API directly to update agent state
|
||||||
// Use --no-daemon to avoid issues when daemon isn't running
|
// This is more reliable than shelling out to bd
|
||||||
cmd := exec.Command("bd", "--no-daemon", "agent", "state", agentBeadID, state)
|
bd := beads.New(ctx.WorkDir)
|
||||||
cmd.Dir = ctx.WorkDir
|
if err := bd.UpdateAgentState(agentBeadID, state, nil); err != nil {
|
||||||
cmd.Stdout = nil
|
// Silently ignore errors - don't fail prime if state reporting fails
|
||||||
cmd.Stderr = nil
|
// This can fail if beads isn't set up or agent bead doesn't exist
|
||||||
|
return
|
||||||
// Run silently - don't fail prime if state reporting fails
|
}
|
||||||
_ = cmd.Run()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAgentBeadID returns the agent bead ID for the current role.
|
// getAgentBeadID returns the agent bead ID for the current role.
|
||||||
|
|||||||
Reference in New Issue
Block a user