Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pi has no permission system - crewmates are always autonomous.
Keep the brief as ONE positional argument - multiple positional args become separate queued messages (fm-spawn's template does this correctly).
Project trust dialog can appear on the first pi run in any not-yet-trusted directory (observed even on clean worktrees); accept with Enter - the decision persists per path in `~/.pi/agent/trust.json`, so later spawns in the same worktree slot skip it.
fm-spawn keeps the turn-end extension in `state/`, outside the worktree, because project-local extension files make the trust gate strictly worse (and pollute the project).
The extension must listen for pi's `turn_end` event, not `agent_end`, so the watcher wakes after each completed turn instead of only when the whole agent run exits.
Environment marker for harness detection: pi sets `PI_CODING_AGENT=true` for its children.

## 5. Recovery (run at every session start, after bootstrap)
Expand Down
5 changes: 4 additions & 1 deletion bin/fm-spawn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,12 @@ EOF
# elsewhere loads without a dialog. Lives in state/, cleaned by teardown.
cat > "$FM_ROOT/state/$ID.pi-ext.ts" <<EOF
// Firstmate turn-end signal; written by fm-spawn.
// Use "turn_end" (fires after each turn the agent finishes), not "agent_end"
// (fires once, only when the whole run exits): the watcher needs a signal at
// every turn boundary so an idle crewmate is surfaced, not just at shutdown.
import { execFile } from "node:child_process";
export default function (pi: any) {
pi.on("agent_end", () => execFile("touch", ["$TURNEND"]));
pi.on("turn_end", () => execFile("touch", ["$TURNEND"]));
}
EOF
;;
Expand Down