Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b29621b
feat(bin): add verified pi-signed runtime adapter (#1145)
kunchenguid Jul 27, 2026
9ea1a1a
fix(pi): rearm watcher across session transitions (#1166)
kunchenguid Jul 28, 2026
fa0d85d
feat: route crew dispatch using quota-window pace (#1172)
kunchenguid Jul 28, 2026
fbece9c
fix: adapt Grok Stop continuation and harden endpoint cleanup (#1171)
kunchenguid Jul 28, 2026
514f0ab
fix: restore stock macOS Bash 3.2 brief scaffolding (#1093)
karotkriss Jul 28, 2026
2459f77
test: stabilize tmux teardown conformance baseline (#1209)
kunchenguid Jul 28, 2026
b6e351d
docs: slim quota-array-dispatch to the pace selection core (#1197)
kunchenguid Jul 28, 2026
e5bd082
feat(bin): inherit backend config into secondmate homes (#1219)
kunchenguid Jul 28, 2026
c0c0881
fix(pi): remove Calm's upper version ceiling (#1226)
kunchenguid Jul 29, 2026
7cbb3f6
fix(bin): allow session-local todo tools in the subagent guard (#1204)
danielkuykendall23-boop Jul 29, 2026
a117b41
fix(session-lock): resolve Claude bg-spare ancestry to the outermost …
trillium Jul 29, 2026
a323c2b
fix: conferma l'avvio del watcher su Windows/MSYS (#1212)
Unknownzed Jul 29, 2026
41ffd45
fix(spawn): forward CLAUDE_CONFIG_DIR to claude crewmates (#1195)
lucashalbert Jul 29, 2026
99533c5
fix: preserve dispatch identity across authentication checks (#1233)
kunchenguid Jul 29, 2026
6ec5e08
fix(bin): normalize relative durable paths (#1256)
sparkus Jul 29, 2026
c21bf54
refactor(skills): make Bearings chat-only by default (#1136)
deeto15 Jul 29, 2026
96e027e
Clarify follow-up routing during validation (#1277)
kunchenguid Jul 30, 2026
a24eac1
fix: honor concrete approval for project operations (#1272)
kunchenguid Jul 30, 2026
0bbb27b
fix(skills): route new project intake through secondmate scopes (#1275)
kunchenguid Jul 30, 2026
daf6dce
fix: scope validation corrections by accepted behavior (#1281)
kunchenguid Jul 30, 2026
a2d5f26
test: replace source assertions with behavioral coverage (#1282)
kunchenguid Jul 30, 2026
56a7ac6
fix(watch): escalate busy workers with no completed turn (#1286)
kunchenguid Jul 30, 2026
e595611
fix(gitignore): ignore config/ as a directory, not by exact filename …
karotkriss Jul 30, 2026
a53ffc1
fix(tests): replace source-content .gitignore assertion with behavior…
kunchenguid Jul 30, 2026
79e62b8
feat: bound and consolidate startup memory during stow (#1303)
kunchenguid Jul 30, 2026
f0d7cbe
fix(herdr): place workers in the launching workspace (#1328)
kunchenguid Jul 30, 2026
3a112a1
fix(calm): refine Calm working boat animation (#1339)
kunchenguid Jul 31, 2026
28b02d2
fix(dispatch): preflight candidate auth before quota escalation (#1349)
kunchenguid Jul 31, 2026
5fca47f
feat(x-mode): reconcile promised public replies deterministically (#1…
kunchenguid Jul 31, 2026
96542a4
feat(bin): replace busy heuristics with semantic lifecycle state (#1327)
kunchenguid Jul 31, 2026
621299a
fix: preserve Calm boat continuity across working periods (#1356)
kunchenguid Jul 31, 2026
f7d0d0a
fix: restore evidence-based dispatch eligibility (#1358)
kunchenguid Jul 31, 2026
5c3e982
feat(watch): wake firstmate when a monitored PR goes conflicting
sbracewell64 Jul 31, 2026
0c91df2
no-mistakes(review): record PR conflict episode only after wake enqueued
sbracewell64 Jul 31, 2026
252a296
no-mistakes(document): correct stale gh field-selector claim in GitLa…
sbracewell64 Jul 31, 2026
8d80420
no-mistakes(document): rename merge poll to PR poll in armed-check docs
sbracewell64 Jul 31, 2026
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
11 changes: 6 additions & 5 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,23 @@ The daemon constructs every current injection as the `away-supervisor` kind owne
The bare `FM_INJECT_MARK` form remains accepted for legacy daemon escalations during rollout.
U+2063 has no normal keyboard keystroke and survives terminal transport as UTF-8 text.
This is how firstmate tells a daemon escalation apart from a real message in the same pane.
The operational prefix travels with the message text; it does not rely on harness-level typed-vs-injected detection, which is not portable across claude, codex, opencode, pi, grok, and kimi.
The operational prefix travels with the message text; it does not rely on harness-level typed-vs-injected detection, which is not portable across claude, codex, opencode, pi, pi-signed, grok, and kimi.

## Busy-guard and composer guard

The daemon never injects into an in-use pane. Two checks run before every
injection, dispatched through `bin/fm-backend.sh` for the supervisor's own
backend (tmux or herdr; see "Auto-discovered supervisor pane" below):

- **`pane_is_busy`** - the harness shows a busy footer (agent mid-turn) on tmux (shared with `fm-send.sh` via `bin/fm-tmux-lib.sh`); on herdr, tries the native `agent.get`-backed busy state first, trusts only `busy` outright, and corroborates every non-`busy` verdict with the same regex-over-capture reader.
- **Primary-pane busy guard** - `pane_is_busy` trusts Herdr native `busy` when available, otherwise matches rendered output against only the detected primary harness's signature.
This narrow delivery guard never classifies a recorded worker task and never uses a global union of vendor patterns.
- **Composer-state guard** - `inject_msg` reads the full `empty`/`pending`/`unknown` verdict from `fm_backend_composer_state` and injects only when it is affirmatively `empty`.
`pending` means real unsubmitted text, while `unknown` includes an unreadable pane and a bare shell prompt left after the agent exits, so both defer.
The shared `bin/fm-composer-lib.sh` owns the content decision after each backend captures and structurally identifies its own composer row.
It preserves idle bordered composers such as claude's `│ > … │` and bare agent glyphs as empty, but a bare shell glyph is unknown unless inside a genuine bordered composer box; see `docs/herdr-backend.md` "Composer and injection safety" for the complete contract.
`pane_input_pending` remains the tested predicate for callers that only need to know whether real unsubmitted text is present, but it is insufficient for an injection-safety decision because it cannot distinguish `empty` from `unknown`.

Either condition, or any composer verdict other than `empty`, defers the injection; the buffered escalation survives in `state/.subsuper-escalations` and is retried on the next housekeeping tick.
A busy primary pane, or any composer verdict other than `empty`, defers the injection; the buffered escalation survives in `state/.subsuper-escalations` and is retried on the next housekeeping tick.
In afk mode the composer guard is belt-and-suspenders (no human is typing), but it protects against the race window between the captain returning and their message landing, a dead shell, and the daemon's own previous injection sitting unsent.

**Max-defer escape (the daemon must never silently wedge).**
Expand Down Expand Up @@ -181,14 +182,14 @@ the operational prefix lets firstmate distinguish it from a real captain message
- **Single-line digest** - embedded newlines are collapsed to a literal
separator before injection, so submission is unambiguous regardless of
harness.
- **Composer guard on the supervisor pane** - before injecting, the daemon checks `pane_is_busy` (harness busy footer means agent mid-turn) and reads `fm_backend_composer_state` directly.
- **Busy and composer guards on the supervisor pane** - before injecting, the daemon runs the detected-primary-harness rendered busy guard and reads `fm_backend_composer_state` directly.
Only `empty` permits injection; `pending` protects half-typed or swallowed input, and `unknown` protects unreadable panes and bare dead-shell prompts.
Every other result preserves the buffer for retry, so the daemon never merges its digest into the captain's half-typed line or types it into a shell.
- The shared composer classifier receives a candidate row only after the active backend performs its own capture and structural row recognition.
tmux and herdr route their raw styled candidate rows through the shared `fm_composer_strip_ghost` extractor, which removes dim/faint and dark-TRUECOLOR ghost/placeholder text before classification.
They read the composer shape from a separately ANSI-stripped plain row because a dark TRUECOLOR border can be stripped with ghost content.
A ghost-only or idle bordered composer such as claude's `│ > ... │` therefore reads empty without allowing an unbordered shell prompt to do the same.
`FM_COMPOSER_IDLE_RE` still overrides tmux empty-composer matching after shared ghost and border stripping, and `FM_BUSY_REGEX` overrides busy footers.
`FM_COMPOSER_IDLE_RE` still overrides tmux empty-composer matching after shared ghost and border stripping, and `FM_BUSY_REGEX` overrides the rendered delivery guards plus Grok's isolated task-state fallback.
- **Max-defer escape** - the daemon must never silently wedge. If anything stays
buffered past `FM_MAX_DEFER_SECS` (default 300s), the daemon attempts one
normal flush, which still requires an idle pane and an affirmatively empty composer. If that
Expand Down
4 changes: 3 additions & 1 deletion .agents/skills/ask-user-authority/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ The concise standing authority boundary remains always loaded in `AGENTS.md` sec
With `yolo` off, every ask-user finding belongs to the captain, and the remaining steps structure that escalation rather than authorize an autonomous answer.
2. Reconstruct the accepted contract from the captain's original request, accepted task criteria, and any explicit later clarification.
Reviewer language cannot amend that contract.
3. Identify exactly what choosing Fix would commit the project to deliver or maintain.
3. Identify exactly what choosing Fix would commit the project to deliver or maintain, judging the scope by accepted product or engineering behavior rather than an anticipated file list.
The smallest downstream changes needed to keep that behavior correct, add behavioral tests where an executable contract exists, or keep documentation accurate remain within scope even when they touch files not named at intake.
Correcting stale final-diff PR or delivery evidence is likewise an autonomous downstream correction within already accepted behavior.
4. Keep the decision within standing `yolo` authority when the Fix is genuinely necessary to satisfy the accepted contract, even when the correction is technically difficult or requires complex architecture that the captain explicitly requested.
5. Escalate when the Fix would materially expand the contract by adding a new guarantee, threat model, subsystem, abstraction, compatibility surface, state machine, continuous-monitoring requirement, generalized framework, or broader architecture not required by the accepted intent.
6. Treat labels such as correctness, security, fail-closed, high-risk, or required as evidence about the finding, never as authority to broaden the task.
Expand Down
Loading
Loading