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
12 changes: 6 additions & 6 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ batched digest rather than per-wake injections.
in as `FM_SUPERVISOR_TARGET` so the daemon injects into the captain, not its
own new pane. **Never manufacture a terminal by splitting the captain's
active pane** (`herdr pane split`): a split co-tenants the tab and visibly
shrinks the captain's pane (docs/herdr-backend.md "Away-mode daemon terminal
launch").
shrinks the captain's pane (docs/herdr-backend.md "Away-mode supervisor
support").
Both paths share `bin/fm-afk-start.sh` as the daemon entry.
The native path tells it that the launcher already prepared lifecycle state; the terminal-backed path lets the entry perform its existing state setup inside the new terminal.
It exits immediately if the identity-backed daemon lock already names a live process, otherwise it execs `bin/fm-supervise-daemon.sh` in the foreground.
Expand Down Expand Up @@ -96,7 +96,7 @@ backend (tmux or herdr; see "Auto-discovered supervisor pane" below):
- **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-emptiness safety" for the complete contract.
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.
Expand All @@ -110,7 +110,7 @@ If that submit cannot be confirmed, it raises a loud, rate-limited wedge alarm:
an ERROR in the daemon log, a durable
`state/.subsuper-inject-wedged` marker (surface it on the "while you were out"
catch-up if present), a tmux status-line flash when applicable, and a configurable backend-independent active alert.
`docs/wedge-alarm.md` owns the alert channel setup and verification record.
`docs/wedge-alarm.md` owns the alert channel setup, and `docs/verification/supervision.md` "Wedge-alarm channels" owns active evidence.
So a guard false-positive becomes a visible stall, never an unbounded silent no-op.

## Submit model
Expand Down Expand Up @@ -225,14 +225,14 @@ the operational prefix lets firstmate distinguish it from a real captain message
backends, including zellij, orca, and cmux, are not yet supported as
supervisor backends; the daemon refuses loudly at startup instead of
misapplying tmux primitives to a pane that isn't one
(docs/herdr-backend.md "Away-mode daemon: herdr supervisor-pane support").
(docs/herdr-backend.md "Away-mode supervisor support").

## Stale-artifact lifecycle

Treat `state/.subsuper-escalations`, its `.since` sidecar, and `state/.subsuper-inject-wedged` as session-scoped delivery artifacts, not as the durable work record.
Always enter through `bin/fm-afk-launch.sh`, which clears prior-session artifacts only for a fresh entry and preserves the current session's buffer on refresh.
Always exit through `bin/fm-afk-launch.sh stop`, which keeps `state/.afk` present through the daemon's shutdown flush and clears it last.
`docs/herdr-backend.md` "Stale-artifact lifecycle fix" owns the mechanism and verification evidence.
`docs/herdr-backend.md` "Away-mode supervisor support" owns the current mechanism, and `docs/verification/runtime-backends.md` "Away-mode transport" owns active evidence.

## Reliability properties

Expand Down
30 changes: 22 additions & 8 deletions .agents/skills/firstmate-coding-guidelines/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: firstmate-coding-guidelines
description: >-
Agent-only reference for changing firstmate's shared, tracked material per AGENTS.md section 1.
Use before editing any of that material, whether working as firstmate directly or as a crewmate briefed on a firstmate-repo task.
Covers the knowledge-placement decision tree, the one-owner rule for contracts, the inline-stub pattern for content moved into a skill, AGENTS.md size discipline, trigger hygiene for new skills, and repo style rules (one sentence per line, plain dash, no agent co-author, shellcheck-clean bin scripts, colocated tests, and backend-verification evidence).
Covers the knowledge-placement decision tree, the one-owner rule for contracts, the inline-stub pattern for content moved into a skill, AGENTS.md size discipline, trigger hygiene for new skills, and repo style rules (one sentence per line, plain dash, no agent co-author, shellcheck-clean bin scripts, colocated tests, and maintainer-verification evidence).
user-invocable: false
metadata:
internal: true
Expand All @@ -23,13 +23,20 @@ Before writing a new fact anywhere in this repo, ask where it belongs, in this o
If yes: `AGENTS.md`, inline.
2. Does the agent need it only in a nameable situation - a spawn, a recovery, a specific wake type, a specific lifecycle step?
If yes: an agent-only skill under `.agents/skills/`, plus a one-line trigger pointer left inline in `AGENTS.md` (usually section 13).
3. Is it human/reference detail - a wire format, a verification record, a mechanism narrative, an incident writeup?
If yes: `docs/`.
4. Is it mechanics - exact flags, exact commands, exact paths?
If yes: the script's own header comment plus its `--help` output, not prose in `AGENTS.md` or a skill.
3. Is it public product, setup, or user/operator reference?
If yes: the surface classified for that audience in [`docs/documentation-audiences.md`](../../../docs/documentation-audiences.md), limited to current behavior, setup, supported limits, stable invariants, concise rationale, and current verification entry points.
4. Is it contributor/maintainer architecture?
If yes: the classified maintainer-architecture owner for stable ownership, extension points, mechanism boundaries, and safety rationale.
5. Is it active reusable verification for a current guarantee?
If yes: an explicitly classified maintainer-verification record may keep current dates, versions, exact commands, and exact output.
6. Is it task or incident evidence - chronology, transcripts, branches, temporary paths, failed hypotheses, or delivery proof?
If yes: keep it in the private task report or PR evidence by default, after distilling every unique current fact into its authoritative owner.
7. Is it mechanics - exact flags, exact commands, exact paths?
If yes: the script's own header comment plus its `--help` output, not prose in `AGENTS.md`, a skill, or a second documentation owner.

Stop at the first tier that answers yes.
Do not place a fact at a more convenient tier than the one this tree gives you.
The machine-consumed inventory in [`docs/documentation-audiences.json`](../../../docs/documentation-audiences.json) is the single classification owner for maintained prose surfaces; do not add parallel front matter or a second audience list.

## One-owner rule

Expand Down Expand Up @@ -74,6 +81,13 @@ Mark an axis not applicable only after inspecting its integration surface, and u
For critical safety, routing, startup, and supervision infrastructure, prefer deterministic and idempotent enforcement over relying on agent memory alone.
Keep instructions as the authority and discovery layer, but make repeated execution converge safely and make invalid or unsafe states fail closed wherever the runtime can enforce them.

## Documentation change review

For every changed maintained prose surface, identify its inventory audience, authoritative owner, current-behavior relevance, destination for supporting evidence, and any unique safety fact that removal could lose.
Move or delete evidence only after the current owner and regression pointer are verified.
After all documentation, review-fix, and lint-fix commits, review the complete branch diff again against those criteria rather than reviewing only the latest commit.
Run `bin/fm-doc-audience-check.sh`; it enforces classification, README setup routing, local link targets, and owner pointers without keyword-linting legitimate evidence prose.

## Repo style rules

- Put one full sentence per line in tracked Markdown.
Expand All @@ -83,6 +97,6 @@ Keep instructions as the authority and discovery layer, but make repeated execut
- `bin/*.sh` and `bin/backends/*.sh` must pass `shellcheck`.
- Run `bin/fm-lint.sh` before treating a script change as done; it is the single owner of the lint definition (file set, config, and pinned shellcheck version) that CI and the no-mistakes pre-push gate both invoke, and it refuses to run under any other shellcheck version.
- Colocate tests with the existing pattern in `tests/`, name them `<subject>.test.sh`, and extend an existing script rather than inventing a new runner.
- A backend-verification doc (`docs/*-backend.md`) records empirical facts, not assumptions.
- Include the date, version, exact commands run, and exact output.
- Write incidents the same way, as evidence, not narrative alone.
- A maintainer-verification record under `docs/verification/` records active empirical facts, not assumptions or task chronology.
- Include the date, version, exact commands run, and exact output needed to support the current guarantee.
- Keep incident chronology and delivery evidence in private task reports or PR evidence unless a concise rationale is required to maintain a current safety boundary.
3 changes: 2 additions & 1 deletion .agents/skills/firstmate-orca/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ The runtime backend owns the task endpoint and, for Orca, the task worktree.
The harness is the agent process launched inside that endpoint, such as `claude`, `codex`, `opencode`, `pi`, or `grok`.
Load `harness-adapters` for harness-specific launch, interrupt, resume, trust-dialog, and skill-invocation facts.

Implementation details, metadata fields, teardown guarantees, limitations, and smoke evidence live in `docs/orca-backend.md`.
Implementation details, metadata fields, teardown guarantees, and limitations live in `docs/orca-backend.md`.
`docs/verification/runtime-backends.md` "Orca" owns active smoke evidence.
Prefer the `bin/fm-*` helpers over raw `orca` commands.
Use raw `orca` only when the helper surface cannot answer the inspection question, and keep the recorded firstmate metadata as the task identity.

Expand Down
10 changes: 6 additions & 4 deletions .agents/skills/harness-adapters/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Use that value for interrupt, exit, resume, and skill-invocation facts.
Every verified primary harness has an empirically validated hook path for the "no turn ends blind" guard.
`claude` and `codex` block directly through Stop hooks that preserve exit status 2 and stderr from `bin/fm-turnend-guard.sh`.
`opencode`, `pi`, and `grok` expose passive lifecycle callbacks for this purpose, so their tracked primary adapters force one bounded follow-up or resume when the shared predicate blocks.
The exact hook files, commands, validation transcripts, scoping rules, and fail-open tradeoffs are owned by `docs/turnend-guard.md`.
The exact hook files, commands, scoping rules, and fail-open tradeoffs are owned by `docs/turnend-guard.md`.
`docs/verification/supervision.md` "Turn-end guard" owns active validation evidence.
When changing any primary turn-end hook, validate the real harness behavior in a scratch project or throwaway home before trusting it, then update that doc and the relevant concise fact below.

## Primary pre-arm (PreToolUse) seatbelt
Expand All @@ -79,7 +80,8 @@ The subagent tool presents to the model as `Agent`, and on Claude Code 2.1.217 b

AGENTS.md section 3 remains the behavioral owner for session start, while tracked native adapters invoke `bin/fm-sessionstart-nudge.sh` as an idempotent enforcement layer.
The wrapper prints one canonically typed `session-start` instruction to run `bin/fm-session-start.sh`; it never runs the digest, wake drain, bootstrap sweeps, lock, or supervision arm itself.
Full mechanics, scoping, dated commands, payloads, and fail-open evidence live in `docs/sessionstart-nudge.md`.
Full mechanics, scoping, and fail-open behavior live in `docs/sessionstart-nudge.md`.
`docs/verification/supervision.md` "Native session-start delivery" owns active dated commands, payloads, and evidence.

- `claude`: verified native `SessionStart` stdout injection; `.claude/settings.json` matches `startup`, `resume`, and `clear`, but not `compact`.
- `codex`: verified on 0.144.4; `.codex/hooks.json` receives `source=startup`, and wrapper stdout reaches model context.
Expand Down Expand Up @@ -152,7 +154,7 @@ A plain `tmux capture-pane` cannot tell that ghost text apart from typed text.
Firstmate launches every claude crewmate and secondmate with `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false`, scoped to firstmate-launched agents through `bin/fm-spawn.sh`, so it never touches the captain's global config.
The CLI's `--prompt-suggestions` flag is print/SDK-mode only and does not suppress the interactive composer ghost text, verified empirically on v2.1.186.
As defense in depth for any pane that flag cannot reach, including the captain's own firstmate composer that away-mode reads, the shared `fm_composer_strip_ghost` extractor in `bin/fm-composer-lib.sh` removes dim/faint SGR 2 ghost runs before pending-input classification on both ANSI-capable readers (tmux and herdr).
Its broader dark-TRUECOLOR placeholder handling and dark-theme tradeoff are documented in `docs/herdr-backend.md`'s 2026-07-10 incident record.
Its broader dark-TRUECOLOR placeholder handling and dark-theme tradeoff are documented in `docs/herdr-backend.md` "Composer and injection safety", with active captures in `docs/verification/runtime-backends.md`.
That styled capture is internal to the boolean detector only.
`fm-peek` and every other human or LLM-facing capture path stays plain `tmux capture-pane` with no escape codes.

Expand Down Expand Up @@ -279,7 +281,7 @@ For Grok's supported reasoning-effort values and omission behavior, see the [lau
**Incident (2026-07-03, herdr backend only, grok 0.2.82):** two grok/herdr crewmates were sent `/no-mistakes` via `fm-send`; both left it fully typed but unsubmitted in the composer for minutes (footer still `Enter:send`), and `fm-send` exited 0 with no error.
Reproduced live: the herdr adapter's submit-verification at the time treated ANY pane-content change after Enter as "submitted", and the popup-close-with-placeholder-fill described above IS a visible content change even though nothing was actually sent.
The tmux backend was never affected - `fm_tmux_composer_state` reads the actual cursor row, correctly sees the placeholder text as still-pending, and its retry loop already sends the needed second Enter.
Fixed in the herdr adapter (`fm_backend_herdr_composer_state`, `bin/backends/herdr.sh`) by classifying the composer's own row structurally instead of diffing raw content; see `docs/herdr-backend.md`'s "Incident (2026-07-03)" section for the full account and `tests/fm-backend-herdr.test.sh` for the regression coverage.
Fixed in the Herdr adapter (`fm_backend_herdr_composer_state`, `bin/backends/herdr.sh`) by classifying the composer's own row structurally instead of diffing raw content; see `docs/herdr-backend.md` "Composer and injection safety" for the current boundary and `tests/fm-backend-herdr.test.sh` for regression coverage.

Startup dialog: the "Run Grok Build in a project directory?" project picker appears ONLY when grok is launched from a non-project directory (home, Desktop, Downloads, `/tmp`).
`fm-spawn` launches inside the treehouse worktree (a git repo root), so the picker never appears and grok treats the worktree as a trusted project automatically - no post-launch keystroke is needed.
Expand Down
13 changes: 13 additions & 0 deletions .no-mistakes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@
# HEAD-continuity guard; see docs/architecture.md "No-mistakes gate authority boundary."
disable_project_settings: true

# Trusted documentation placement policy for the Document step.
# The audience inventory and coding guideline own the detail; keep this as a
# pointer so gate instructions cannot become a second prose policy.
document:
instructions: |
Read docs/documentation-audiences.md and its machine-consumed
docs/documentation-audiences.json inventory before changing documentation.
Apply the knowledge-placement policy in
.agents/skills/firstmate-coding-guidelines/SKILL.md.
For changed prose, verify audience, authoritative owner, current relevance,
evidence destination, and unique safety facts, then review the complete
branch diff again after every documentation or lint fix.

# Pin lint to the same owner CI runs instead of leaving it to no-mistakes'
# default handling, which does not invoke the repository's canonical lint gate.
# `bin/fm-lint.sh` owns the complete lint definition and
Expand Down
Loading
Loading