Skip to content

feat(fleet): shrink always-loaded AGENTS.md and generate the skill index from frontmatter - #18

Open
sbracewell64 wants to merge 31 commits into
mainfrom
fm/doc-truth-fleet-lane
Open

feat(fleet): shrink always-loaded AGENTS.md and generate the skill index from frontmatter#18
sbracewell64 wants to merge 31 commits into
mainfrom
fm/doc-truth-fleet-lane

Conversation

@sbracewell64

@sbracewell64 sbracewell64 commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Intent

Execute Lane B of the captain-authorized documentation single-source-of-truth commission (2026-07-30) for the firstmate fleet repo. Lane B is defined by section 11 of data/doc-truth-review/report.md, a prior read-only scout review; this branch implements its B1, B4, B2, and B3 rows.

GOAL: shrink firstmate's always-loaded AGENTS.md contract to only what it alone can own, and convert the review's documentation-ownership table from prose into a mechanically enforced artifact.

B1+B4 - AGENTS.md section 2 was 10,777 bytes, of which a 9,407-byte fenced directory tree restated docs/configuration.md. docs/configuration.md already declares itself the single owner of the operational-home layout and explicitly delegates exact child fields to each producing script's header. Before deleting anything I verified every artifact the tree named has such an owner; several (check-trust, pr-poll-retirement, turnend-claude-blocks, the grok/kimi turn-end tokens, pr-check-quarantine) are documented ONLY in bin/ scripts and not in docs/, which is exactly what the owner's declared boundary prescribes, so their removal from AGENTS.md is correct rather than a loss. What deliberately survives is every fact with no other owner anywhere in the repo: the status-line-is-a-wake-event rule, the never-touch rule for watcher/Claude-auto-arm/sub-supervisor state under state/ (I grepped the whole repo and this instruction exists nowhere else), the check.sh execution-trust boundary, the scout report surviving teardown, and B4's corrected secondmates.md wording (created lazily by fm-home-seed.sh, so absence means no secondmate is registered rather than a lost registry). The plan targeted -6,907 bytes; the measured result is -8,019 because collapsing the tree to five safety bullets beat the estimate. The report's own section 15.2 marks its after-column byte figures as engineering targets, not measurements, so beating one is expected.

B2 - AGENTS.md section 13 was a hand-maintained 2,913-byte roster of 13 agent-only skill triggers, duplicating each skill's own frontmatter description, which some harnesses inject into the session prompt unprompted. New bin/fm-skill-index.sh renders that roster from frontmatter, selecting on the existing user-invocable:false marker (verified to match the old roster exactly, 13 for 13). It is composed into the session-start digest by bin/fm-session-start.sh.

DELIBERATE DEPARTURE FROM THE REPORT, made on safety grounds and worth not flagging as a mistake: the report's section 7.3 table lists codex and kimi as 'likely' injecting skill descriptions, but its own section 15.2 admits those cells are unverified. I suppress the generated index ONLY where injection is positively verified - claude (proved by direct observation) and grok (harness-adapters records 'firstmate skills are discovered' plus a verified end-to-end invocation) - and emit it for every other harness including unknown. The asymmetry is intentional: a redundant index only costs bytes, whereas a wrongly suppressed one silently removes every agent-only skill's load trigger. The script header documents this and requires positive evidence before adding a harness to the suppression list.

Section 13 kept three sentences rather than collapsing to the report's suggested single sentence, so it fell 619 bytes short of the -2,927 target: the ownership pointer to fm-skill-index.sh and the register-once rule are contract facts a future maintainer needs, not roster. Net across AGENTS.md is -10,166 bytes, 332 better than the combined plan target.

Also honestly measured and contrary to the report's estimate: the report predicted the generated index would be byte-neutral on non-injecting harnesses. It actually costs 5,329 bytes there because frontmatter descriptions are richer than the old abridged roster. Net is therefore -10,166 on claude/grok and -4,837 elsewhere - still a reduction everywhere, but not the wash predicted. This is stated plainly rather than rounded away.

B3 - docs/documentation-audiences.json gains an injection field (always/lazy/generated/referenced/never) and a one-sentence responsibility for each of its 57 surfaces, and bin/fm-doc-audience-check.sh now REQUIRES both, refusing rather than defaulting a missing field. The one-sentence limit on responsibility is enforced by regex and is the point of the mechanism, per the commission: a surface that needs two sentences owns too much and should be split. This makes the always-loaded set a queryable list rather than a claim, and a test asserts it stays bounded to AGENTS.md plus its CLAUDE.md symlink.

CROSS-REFERENCES updated for the one-owner rule: firstmate-coding-guidelines and fmx-respond skills pointed at 'section 13' as the place to register a trigger; README.md said triggers are named in AGENTS.md; docs/scripts.md gains a row for the new script. All corrected in the same change.

CERTIFICATION already run locally: the plan requires a session-start smoke read for B1 proving no operator action lost its instruction - done under both a claude and an opencode primary, walking each instruction the removed tree carried. New tests/fm-skill-index.test.sh (6 cases) covers suppression, emission including unknown harnesses, roster derivation independently from frontmatter, folded multi-line description rendering, and digest composition. tests/fm-documentation-audiences.test.sh gains 2 cases for the required fields. bin/fm-lint.sh and bin/fm-doc-audience-check.sh are green.

KNOWN PRE-EXISTING FAILURE, not introduced here: tests/fm-session-start.test.sh has one failing case ('MISSING diagnostic did not appear at all'). I stashed this branch's changes and re-ran it on the base commit f0d7cbe, where it fails identically - it is environment-dependent tool detection, unrelated to this change.

CONSTRAINTS: this is firstmate's own shared tracked material, so repo style rules apply - one sentence per line in tracked Markdown, plain dash never em dash, no agent co-author on commits, bin/*.sh shellcheck-clean via bin/fm-lint.sh, tests colocated in tests/ as .test.sh extending existing runners, and tests must exercise behavior through executable interfaces rather than asserting implementation-source bytes.

What Changed

  • Cut AGENTS.md by 10,166 bytes: section 2's 9,407-byte directory tree that restated docs/configuration.md is collapsed to five safety bullets (keeping only facts with no other owner, e.g. the status-line wake rule, the never-touch state/ rule, and the check.sh trust boundary), and section 13's hand-maintained 2,913-byte roster of agent-only skill triggers is reduced to a three-sentence ownership pointer.
  • New bin/fm-skill-index.sh renders the agent-only skill roster from each skill's frontmatter (verified 13-for-13 against the old roster) and is composed into the session-start digest by bin/fm-session-start.sh; the generated index is suppressed only on harnesses positively verified to inject skill descriptions (claude, grok) and emitted everywhere else, including unknown harnesses.
  • docs/documentation-audiences.json gains required injection and one-sentence responsibility fields for all 57 surfaces, enforced by bin/fm-doc-audience-check.sh (refuses rather than defaults a missing field), with a test asserting the always-loaded set stays bounded to AGENTS.md plus its CLAUDE.md symlink; stale "section 13" cross-references in the firstmate-coding-guidelines and fmx-respond skills, README.md, and docs/scripts.md are updated, and new tests cover the skill index (6 cases) and the required audience fields.

Risk Assessment

✅ Low: A well-bounded documentation-consolidation and tooling change whose key claims I independently verified: the generated skill index matches the removed 13-entry roster exactly, suppression is limited to the two positively verified injecting harnesses per the stated intent, the stricter inventory check passes green on the updated 57-surface inventory, removed AGENTS.md facts have confirmed owners elsewhere, and new behavior-level tests cover the suppression/emission matrix and required-field enforcement.

Testing

Ran the two new/extended test suites (12/12 cases green), then manually verified every intent claim end-to-end: skill-index emission/suppression per harness including the positive-evidence rule for unknown harnesses, real session-start digest composition under opencode vs claude primaries, doc-audience-check refusing missing injection and two-sentence responsibility fields while green on the real 57-surface inventory, exact 13-for-13 roster parity with the old hand-maintained section 13, byte deltas matching the claimed -10,166 net and -8,019 section 2, survival of all five no-other-owner facts, and corrected cross-references; the single fm-session-start.test.sh failure was reproduced identically at the base commit, confirming it pre-exists this change. No visual evidence applies - this is a CLI/docs repo and the transcripts captured are the end-user surface.

Evidence: Skill index emission/suppression transcript (opencode, claude, grok, unknown harness)
$ bin/fm-skill-index.sh --harness opencode
AGENT-ONLY SKILL TRIGGERS (harness opencode does not inject skill descriptions)
These skills are not captain-invocable; load one only at its trigger below.

- ask-user-authority - Agent-only decision procedure for ask-user findings. Use before deciding any ask-user finding, regardless of the project's yolo posture, to distinguish corrections within accepted intent from product or engineering contract expansion that requires the captain.
- bootstrap-diagnostics - Agent-only handling playbook for session-start bootstrap diagnostics. Use whenever the session-start digest's bootstrap section prints an actionable diagnostic line - MISSING, MISSING_MANUAL, BACKEND_INVALID, NEEDS_GH_AUTH, TANGLE, STARTUP_MEMORY_BUDGET, CREW_DISPATCH invalid, FLEET_SYNC, PR_CHECK_MIGRATION, SECONDMATE_SYNC, SECONDMATE_LIVENESS, NUDGE_SECONDMATES, or FMX - or when a standalone bin/fm-bootstrap.sh run prints one of those lines. A silent bootstrap section, or a BOOTSTRAP_INFO fact, means no skill load.
- decision-hold-lifecycle - Agent-only policy for completing investigations and visual reviews without losing unresolved captain decisions. Load before treating an investigation, scout report, structured review, or Lavish review as complete, before ending a visual review that exposed a decision, and when recording or routing the captain's answer.
- diagnostic-reasoning - Agent-only procedure for diagnosing reported bugs. Use before scoping a reported bug and before acting on a diagnostic report. Owns end-user-aligned reproduction, causal separation, divergent-path and history inspection, counterfactual testing, and disconfirming evidence.
- firstmate-codexapp - Agent-only playbook for coordinating visible Codex Desktop threads alongside Firstmate without pretending they are a selectable shell backend. Use before creating, reading, steering, archiving, debugging, or reviewing a Codex App visible thread for Firstmate work, and before responding to requests to make Codex App native to Firstmate.
- firstmate-coding-guidelines - 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 maintainer-verification evidence).
- firstmate-orca - Agent-only operator checklist for Firstmate's Orca runtime backend. Use when switching to Orca, spawning or supervising Orca-backed work, smoke-testing Orca backend behavior, debugging Orca task state, or reconciling Orca-backed task metadata.
- fmx-respond - Agent-only playbook for handling X mode mentions and follow-ups. Use on an "x-mention <request_id>" check wake to read the stashed mention, classify it, act autonomously on eligible requests, reply or dismiss, and link spawned work. Also use on an "x-mode-error ..." check wake to report the X-mode configuration blocker instead of answering a mention. Also use on milestone and terminal wakes for an X-mode-linked task before posting completion follow-ups, ending terminal outcomes with --final. Loaded only when X mode is enabled.
- harness-adapters - Agent-only reference for firstmate harness operations. Use before spawning or recovering a crewmate or secondmate, handling a trust dialog, sending a harness-specific skill invocation, interrupting or exiting an agent, resuming an exited agent, or verifying a new harness adapter. Contains verified facts for claude, codex, opencode, pi, pi-signed, grok, and kimi.
- project-management - Agent-only procedure for Firstmate project management. Use before adding, creating, removing, or initializing a project. Cloning or registering a project is add intake and uses the same trigger. Owns project add, create, clone, remove, initialization, registry, delivery-mode, autonomy, and outward-consent decisions.
- quota-array-dispatch - Agent-only decision procedure for resolving a matched crew-dispatch profile array from current quota-axi output, including quota-window pace signals. Load when a dispatch rule or default resolves to more than one profile candidate.
- secondmate-provisioning - Agent-only reference for persistent secondmate setup and retirement. Use when creating, seeding, validating, launching, recovering, handing backlog to, pushing inherited local material into, or retiring a secondmate home, or when editing data/secondmates.md. Covers home leases, transactional seeding, project clone restrictions, secondmate harness pins, inherited local-material push, idle charter, handoff helper, and teardown safety.
- stuck-crewmate-recovery - Agent-only playbook for stuck or missing ordinary Firstmate direct reports. Use when the session-start digest reports an ordinary direct report's endpoint dead or its metadata has no window, or after a stale wake, looping pane, repeated confusion, an answered-by-brief question, an unresponsive crewmate, or a failed steer. Reconciles recorded work before escalating from targeted inspection through safe relaunch or failure.

$ bin/fm-skill-index.sh --harness claude   # injects skill descriptions itself -> suppressed
(no output, exit 0)

$ bin/fm-skill-index.sh --harness grok     # verified injecting -> suppressed
(no output, exit 0)

$ bin/fm-skill-index.sh --harness some-future-harness   # unknown -> emitted (positive-evidence rule)
AGENT-ONLY SKILL TRIGGERS (harness some-future-harness does not inject skill descriptions)
These skills are not captain-invocable; load one only at its trigger below.

- ask-user-authority - Agent-only decision procedure for ask-user findings. Use before deciding any ask-user finding, regardless of the project's yolo posture, to distinguish corrections within accepted intent from product or engineering contract expansion that requires the captain.
- bootstrap-diagnostics - Agent-only handling playbook for session-start bootstrap diagnostics. Use whenever the session-start digest's bootstrap section prints an actionable diagnostic line - MISSING, MISSING_MANUAL, BACKEND_INVALID, NEEDS_GH_AUTH, TANGLE, STARTUP_MEMORY_BUDGET, CREW_DISPATCH invalid, FLEET_SYNC, PR_CHECK_MIGRATION, SECONDMATE_SYNC, SECONDMATE_LIVENESS, NUDGE_SECONDMATES, or FMX - or when a standalone bin/fm-bootstrap.sh run prints one of those lines. A silent bootstrap section, or a BOOTSTRAP_INFO fact, means no skill load.
- decision-hold-lifecycle - Agent-only policy for completing investigations and visual reviews without losing unresolved captain decisions. Load before treating an investigation, scout report, structured review, or Lavish review as complete, before ending a visual review that exposed a decision, and when recording or routing the captain's answer.
...
Evidence: Doc-audience-check: green run plus refusals for missing injection and two-sentence responsibility

$ bin/fm-doc-audience-check.sh fm-doc-audience-check: ok surfaces=57 local_links=162 exit 0 (green) $ bin/fm-doc-audience-check.sh --inventory <copy with one surface's injection field removed> fm-doc-audience-check: .agents/skills/afk/SKILL.md: unsupported injection None exit 1 $ bin/fm-doc-audience-check.sh --inventory <copy with a two-sentence responsibility> fm-doc-audience-check: .agents/skills/ahoy/SKILL.md: responsibility must be exactly one sentence - split the document instead of widening the field exit 1

$ bin/fm-doc-audience-check.sh          # real inventory: 57 surfaces, all fields required
fm-doc-audience-check: ok surfaces=57 local_links=162
exit 0 (green)

$ bin/fm-doc-audience-check.sh --inventory <copy with one surface's injection field removed>
fm-doc-audience-check: .agents/skills/afk/SKILL.md: unsupported injection None
exit 1

$ bin/fm-doc-audience-check.sh --inventory <copy with a two-sentence responsibility>
fm-doc-audience-check: .agents/skills/ahoy/SKILL.md: responsibility must be exactly one sentence - split the document instead of widening the field
exit 1
Evidence: Real session-start digest: AGENT-ONLY SKILLS section present under opencode primary, absent under claude
### Session-start digest under an opencode primary (non-injecting harness) - AGENT-ONLY SKILLS section:
AGENT-ONLY SKILLS
--------------------------------------------------------------------------------
AGENT-ONLY SKILL TRIGGERS (harness opencode does not inject skill descriptions)
These skills are not captain-invocable; load one only at its trigger below.

- ask-user-authority - Agent-only decision procedure for ask-user findings. Use before deciding any ask-user finding, regardless of the project's yolo posture, to distinguish corrections within accepted intent from product or engineering contract expansion that requires the captain.
- bootstrap-diagnostics - Agent-only handling playbook for session-start bootstrap diagnostics. Use whenever the session-start digest's bootstrap section prints an actionable diagnostic line - MISSING, MISSING_MANUAL, BACKEND_INVALID, NEEDS_GH_AUTH, TANGLE, STARTUP_MEMORY_BUDGET, CREW_DISPATCH invalid, FLEET_SYNC, PR_CHECK_MIGRATION, SECONDMATE_SYNC, SECONDMATE_LIVENESS, NUDGE_SECONDMATES, or FMX - or when a standalone bin/fm-bootstrap.sh run prints one of those lines. A silent bootstrap section, or a BOOTSTRAP_INFO fact, means no skill load.
- decision-hold-lifecycle - Agent-only policy for completing investigations and visual reviews without losing unresolved captain decisions. Load before treating an investigation, scout report, structured review, or Lavish review as complete, before ending a visual review that exposed a decision, and when recording or routing the captain's answer.
- diagnostic-reasoning - Agent-only procedure for diagnosing reported bugs. Use before scoping a reported bug and before acting on a diagnostic report. Owns end-user-aligned reproduction, causal separation, divergent-path and history inspection, counterfactual testing, and disconfirming evidence.
- firstmate-codexapp - Agent-only playbook for coordinating visible Codex Desktop threads alongside Firstmate without pretending they are a selectable shell backend. Use before creating, reading, steering, archiving, debugging, or reviewing a Codex App visible thread for Firstmate work, and before responding to requests to make Codex App native to Firstmate.
- firstmate-coding-guidelines - 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 maintainer-verification evidence).
- firstmate-orca - Agent-only operator checklist for Firstmate's Orca runtime backend. Use when switching to Orca, spawning or supervising Orca-backed work, smoke-testing Orca backend behavior, debugging Orca task state, or reconciling Orca-backed task metadata.
- fmx-respond - Agent-only playbook for handling X mode mentions and follow-ups. Use on an "x-mention <request_id>" check wake to read the stashed mention, classify it, act autonomously on eligible requests, reply or dismiss, and link spawned work. Also use on an "x-mode-error ..." check wake to report the X-mode configuration blocker instead of answering a mention. Also use on milestone and terminal wakes for an X-mode-linked task before posting completion follow-ups, ending terminal outcomes with --final. Loaded only when X mode is enabled.
- harness-adapters - Agent-only reference for firstmate harness operations. Use before spawning or recovering a crewmate or secondmate, handling a trust dialog, sending a harness-specific skill invocation, interrupting or exiting an agent, resuming an exited agent, or verifying a new harness adapter. Contains verified facts for claude, codex, opencode, pi, pi-signed, grok, and kimi.
- project-management - Agent-only procedure for Firstmate project management. Use before adding, creating, removing, or initializing a project. Cloning or registering a project is add intake and uses the same trigger. Owns project add, create, clone, remove, initialization, registry, delivery-mode, autonomy, and outward-consent decisions.
- quota-array-dispatch - Agent-only decision procedure for resolving a matched crew-dispatch profile array from current quota-axi output, including quota-window pace signals. Load when a dispatch rule or default resolves to more than one profile candidate.
- secondmate-provisioning - Agent-only reference for persistent secondmate setup and retirement. Use when creating, seeding, validating, launching, recovering, handing backlog to, pushing inherited local material into, or retiring a secondmate home, or when editing data/secondmates.md. Covers home leases, transactional seeding, project clone restrictions, secondmate harness pins, inherited local-material push, idle charter, handoff helper, and teardown safety.
- stuck-crewmate-recovery - Agent-only playbook for stuck or missing ordinary Firstmate direct reports. Use when the session-start digest reports an ordinary direct report's endpoint dead or its metadata has no window, or after a stale wake, looping pane, repeated confusion, an answered-by-brief question, an unresponsive crewmate, or a failed steer. Reconciles recorded work before escalating from targeted inspection through safe relaunch or failure.

================================================================================
CONTEXT
================================================================================

data/projects.md
--------------------------------------------------------------------------------
...

### Same digest under a claude primary (injects skill descriptions) - index absent:
0
occurrences of 'AGENT-ONLY SKILL TRIGGERS' above: 0
Evidence: Always-loaded set queried from inventory (exactly AGENTS.md + CLAUDE.md)

injection=always surfaces: ['AGENTS.md', 'CLAUDE.md']

$ python3 - <<'PY'  # query the always-loaded set from the inventory
injection=always surfaces: ['AGENTS.md', 'CLAUDE.md']
Evidence: Byte measurements vs base and 13-for-13 roster parity

AGENTS.md byte measurements (base f0d7cbe vs target e5e4161): whole file: 55237 -> 45071 (delta -10166; intent claims -10,166) section 2 (layout tree removed): 10777 -> 2758 (delta -8019; intent claims -8,019 for B1+B4) section 13 (roster replaced by generated index): 2913 -> 605 (delta -2308) Roster parity: old hand-maintained section 13 names vs generated index names: IDENTICAL - 13 skills in both (13-for-13)

AGENTS.md byte measurements (base f0d7cbe vs target e5e4161):
  whole file: 55237 -> 45071 (delta -10166; intent claims -10,166)
  section 2 (layout tree removed): 10777 -> 2758 (delta -8019; intent claims -8,019 for B1+B4)
  section 13 (roster replaced by generated index): 2913 -> 605 (delta -2308)

Roster parity: old hand-maintained section 13 names vs generated index names:
  IDENTICAL - 13 skills in both (13-for-13)
    ask-user-authority
    bootstrap-diagnostics
    decision-hold-lifecycle
    diagnostic-reasoning
    firstmate-codexapp
    firstmate-coding-guidelines
    firstmate-orca
    fmx-respond
    harness-adapters
    project-management
    quota-array-dispatch
    secondmate-provisioning
    stuck-crewmate-recovery
- Outcome: ⚠️ 1 info across 1 run (3m52s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 2 infos
  • ℹ️ .agents/skills/fmx-respond/SKILL.md:193 - The updated cross-reference says "AGENTS.md §14 declares the load trigger for X-mode-linked milestone or terminal wakes", but §14 only explicitly declares the mention/error check-wake load and the terminal-outcome load; the milestone-wake trigger now lives solely in fmx-respond's own frontmatter description (surfaced via harness injection or fm-skill-index.sh). No trigger is functionally lost, but the sentence slightly overstates what §14 declares.
  • ℹ️ bin/fm-session-start.sh:347 - fm-session-start.sh invokes fm-skill-index.sh with stderr discarded and treats empty output as "suppress". If the index ever renders empty on a non-injecting harness due to a runtime failure (e.g. awk error), the digest silently omits every agent-only skill trigger - the exact silent-suppression failure the script's own header identifies as the dangerous direction. A diagnostic line distinguishing "suppressed by design" from "rendered empty despite agent-only skills existing" would make that failure visible; the independent roster test does mitigate this in CI.
⚠️ **Test** - 1 info
  • ℹ️ tests/fm-session-start.test.sh - tests/fm-session-start.test.sh has one failing case ('MISSING diagnostic did not appear at all') that is confirmed pre-existing: the identical test file extracted from base commit f0d7cbe fails the same way in this environment, matching the author's stated known failure. Because the runner halts at the first failure, the later cases in that file were not exercised on either commit; the change's own digest-composition behavior is instead covered by tests/fm-skill-index.test.sh case 6 and a manual end-to-end run, both green.
  • bash tests/fm-skill-index.test.sh - all 6 cases pass (suppression, emission incl. unknown harness, roster derivation, frontmatter folding, --force, digest composition)
  • bash tests/fm-documentation-audiences.test.sh - all 6 cases pass, including the 2 new required-field cases and the bounded always-loaded-set assertion
  • Manual: bin/fm-skill-index.sh --harness {opencode,claude,grok,some-future-harness} - emitted for opencode and unknown harness, silent (exit 0) for claude and grok
  • Manual: bin/fm-doc-audience-check.sh green on real inventory (57 surfaces); refuses a copy with one surface's injection field removed and a copy with a two-sentence responsibility
  • Manual end-to-end: bin/fm-session-start.sh under a fake-ps opencode primary renders the AGENT-ONLY SKILLS digest section; under CLAUDECODE=1 the index is absent
  • Manual: queried docs/documentation-audiences.json for injection=always - exactly AGENTS.md and CLAUDE.md
  • Manual: diffed old hand-maintained AGENTS.md section 13 roster names against generated index names - identical, 13 for 13
  • Manual: byte measurements vs base f0d7cbe - AGENTS.md 55,237 -> 45,071 (-10,166, matching claim), section 2 10,777 -> 2,758 (-8,019, matching claim), section 13 2,913 -> 605
  • Manual: grepped new AGENTS.md for the five claimed surviving no-other-owner facts (status-line wake event, never-touch state/ internals, check.sh trust boundary, scout report survives teardown, lazy secondmates.md) - all present; no stale 'section 13' cross-references remain in skills or README
  • bash tests/fm-session-start.test.sh on both target and base-commit copies - identical single pre-existing failure ('MISSING diagnostic'), confirming it is not introduced by this change
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

kunchenguid and others added 26 commits July 27, 2026 12:28
* feat: add verified pi-signed adapter

* no-mistakes(review): Correct pi-signed maintainer verification date

* no-mistakes(review): Correct remaining pi-signed verification dates

* no-mistakes(review): Preserve authoritative pi-signed runtime identity

* no-mistakes(document): Document pi-signed shared adapter semantics

* no-mistakes: apply CI fixes
* fix(pi): rearm watcher across same-process session transitions

Pi emits session_shutdown for ordinary /new, /resume, and /fork replacement
as well as terminal quit. The primary watcher extension latched a module-level
stopping flag on every shutdown, so a replacement session in the same process
could not arm monitoring until Pi restarted.

Own arm authority per session generation so only the active live generation
may start, stop, or rearm the child. Replacement sessions can arm again without
restarting Pi, stale prior-generation callbacks cannot mutate the active cycle,
and real quit still blocks late rearm.

* no-mistakes(review): Preserve Pi generation isolation and exit cleanup

* no-mistakes(document): Correct Pi watcher transition documentation
* Consume quota-axi pace signals in dispatch profile array selection.

Add quota-array-dispatch as the single owner of the pace-aware candidate
choice, keep AGENTS.md to the intake boundary and load trigger, and cover
the acceptance cases with sanitized schemaVersion 3 fixtures.

* no-mistakes(review): Stop and report genuine quota dispatch ties

* no-mistakes(document): Document quota pace freshness and uncertainty
…nguid#1171)

* fix(grok): adapt Stop continuation to runtime capability

* no-mistakes(review): Reject ambiguous Grok Stop payloads

* no-mistakes(review): Reject duplicate Grok fields and accept spaced tmux sessions

* no-mistakes(review): Enforce exact tmux cleanup selectors

* no-mistakes(test): Fix historical tmux fixture and validate Grok Stop

* no-mistakes: apply CI fixes
* fix(brief): make DOD scaffolding parse-safe on stock macOS Bash 3.2

fm-brief.sh built each Definition-of-done block and the not-enabled
Herdr declaration with `VAR=$(cat <<EOF ... EOF)`. On Bash 3.2 (macOS
/bin/bash) the lexer scans for the command substitution's closing `)`
textually and tracks quote state through the heredoc body, so a single
apostrophe, unbalanced quote, or unbalanced paren in that prose breaks
parsing of the whole script. Every ship-brief scaffold (no-mistakes,
direct-PR, local-only) failed with `unexpected EOF while looking for
matching )`. Bash 4+ parses it fine, so the breakage stayed invisible
everywhere except stock macOS.

Replace all four command-substitution heredocs with
`IFS= read -r -d '' VAR <<EOF || true`. That removes the `$(...)`
wrapper and the entire defect class regardless of future prose, and
preserves the variable expansion the direct-PR and local-only bodies
need. `read` keeps the heredoc's trailing newline that `$(...)` used to
strip, so trim one newline to keep every generated brief byte-identical
to prior output.

Guard the structure, not one historical phrase: a new test rejects any
heredoc nested in a command substitution anywhere in fm-brief.sh, where
the old assertion pinned a single apostrophe phrase and so missed the
reintroduction. Extend the stock-macOS Bash CI job from parsing one
script to the whole maintained shell surface (bin/*.sh,
bin/backends/*.sh, tests/*.sh), matching bin/fm-lint.sh's canonical file
set so parse scope and lint scope cannot drift apart.

* no-mistakes(review): Captain: harden Bash structure and inventory guards

* no-mistakes(document): Align stock macOS Bash contributor checks

* no-mistakes(lint): Suppress deliberate SC2016 literal fixture warnings
* fix(test): pin teardown tmux baseline to historical kill selectors

merge-base HEAD main collapses to HEAD after the exact-selector change
lands on the default branch, so the old teardown fixture was accidentally
exercising current exact targets. Resolve a content-historical permissive
tmux adapter from first-parent history and force that post-squash topology
inside the conformance case so main and feature branches keep the same
old-vs-new contract.

* no-mistakes(lint): Suppress intentional literal-pattern ShellCheck warnings
…id#1197)

Cut the runtime skill to the compact pace-aware selection procedure plus
minimum owner pointers. Keep every distinct decision rule and move expanded
acceptance scenarios to deterministic fixture ownership assertions.

Size: 170/1374/10187 -> 63/544/4068 (about 63%/60%/60% reduction).
…1219)

* Inherit config/backend into secondmate homes with deliberate-override preservation

Add backend to the shared inheritable config allowlist so launch, locked
bootstrap, and config-push converge a primary pin into secondmate homes as each
home local future-spawn default. Track last-inherited bytes in a private state
provenance marker so deliberate per-home overrides survive present and absent
primary convergence, keep --backend and FM_BACKEND stronger, and extend the
existing inheritance tests plus docs and skill claims.

* no-mistakes(review): Preserve equal unprovenanced backend overrides

* no-mistakes(review): Preserve symlink overrides and verify spawn precedence

* no-mistakes(review): Snapshot backend inheritance for consistent provenance

* no-mistakes(review): Simplify backend inheritance to primary-authoritative convergence

* no-mistakes(document): Document inherited backend override preservation

* fix: restore primary-authoritative backend inheritance after document regression

The document step reintroduced provenance and deliberate per-home override
semantics after review had simplified config/backend to plain primary-authoritative
allowlist membership. Restore the primary-always-wins path: present overwrites,
absent removes, no provenance marker, and docs/tests match that contract.

* no-mistakes(review): Add divergent backend precedence regression fixtures

* no-mistakes(document): Document backend inheritance contract
* fix(pi): remove Calm's exclusive Pi upper-version ceiling

tests/fm-calm-pi-extension.test.sh gated on a closed PI_COMPAT_VERSIONS
allowlist ("0.81.1 0.82.0") that refused any other installed Pi, and docs
described that range as "supported" rather than verified evidence. The
Calm CHANGELOG shows no API introduced at either version, so there is no
evidence for a real minimum; the presentation adapters already probe the
exact method they patch rather than checking a version.

Replace the allowlist with dated version evidence that never rejects a
newer Pi, and make each presentation adapter degrade independently with
a diagnostic if a future Pi removes its API, instead of the whole Calm
extension failing to load. Rewrite the feasibility doc's "Pi 0.81.1
through 0.82.0" phrasing to state it as verified evidence, not a
ceiling.

* no-mistakes(review): Probe missing Calm adapter exports safely

* no-mistakes(document): Document Calm's unbounded Pi compatibility
…enguid#1204)

* fix(guard): allow session-local todo tools in the primary

The delegation-shape guard denied TaskCreate and TaskUpdate because their
normalized names contain the `task` stem. Those tools write only the harness's
session-local todo list, which has no executor: it spawns no agent, allocates
no worktree, registers no schedule, and starts nothing that outlives the
session. That is not the unaccounted work the guard exists to stop, so the stem
match was a false positive, and the deny text told the primary to run
bin/fm-brief.sh and bin/fm-spawn.sh to create a todo entry.

Add a separately-reasoned PLAN_ONLY_TOOLS exact-name exclusion rather than
widening OBSERVE_ONLY_TOOLS, whose documented contract is tools that only
observe or stop existing work. Both lists stay exact-name so neither can widen
by substring.

Tests cover the two allowed names and six near-miss names that a substring or
shortened-stem widening would release; both mutations were watched red.

* no-mistakes(review): drop session-local todo tools from recommended deny list

* no-mistakes: apply CI fixes
…claude pid (kunchenguid#1206)

* fix(session-lock): resolve Claude bg-spare ancestry to the outermost claude pid

fm_harness_ancestry_pid() previously returned the first ancestor process
whose command matched a verified harness name. Claude Code's Stop hook
fires as a bg-spare worker several levels below the session's actual
lock-owning claude process (hook shell -> claude bg-spare ->
claude bg-pty-host -> claude -> claude(lock)), so the first match was
the bg-spare worker, not the lock owner. fm_session_lock_owned_by_self()
then never matched state/.lock, and the Claude Stop auto-arm silently
treated its own primary session as an unrelated live owner and never
armed the watcher.

The walk now keeps going past a claude-named match, looking for a still
more ancestral claude-named match, and stops the instant a non-match
follows an already-found match (bounding it to a contiguous run rather
than the literal ancestry top, so an unrelated claude-named process
further up the real process tree is never mistaken for part of this
session's own nested chain). Every other harness keeps the original
first-match-wins behavior, since e.g. Pi's shared signed-wrapper
ancestry actually holds the session at the inner engine pid, not an
outer wrapper pid. Hop limit raised from 8 to 16 to cover the deeper
bg-spare chain.

* no-mistakes(review): Add nested-claude-ancestry regression test; fix nudge doc depth claim

* no-mistakes: apply CI fixes
* fix: confirm watcher startup on MSYS

* no-mistakes(review): gate MSYS arm ready timeout, cache uname, harden locale test

* no-mistakes(review): validate OpenCode ready timeout, make uname cache internal
…d#1195)

* fix(spawn): forward firstmate's CLAUDE_CONFIG_DIR to claude crewmates

Crewmate panes are created by a long-lived tmux/herdr daemon that does not
inherit firstmate's current environment. When firstmate runs under a non-default
CLAUDE_CONFIG_DIR (for example a work-vs-personal subscription split), a bare
`claude` in the crewmate pane fell back to the default ~/.claude store and
launched unauthenticated, blocking the crewmate before it could do any work.

fm-spawn now prefixes the claude launch with firstmate's own resolved
CLAUDE_CONFIG_DIR when set, so the crewmate uses the same credential/config
store firstmate is authenticated with. An unset value is the single-store
default and adds no prefix; non-claude harnesses are unaffected.

Adds three tests in fm-spawn-dispatch-profile.test.sh (forwarded-when-set,
omitted-when-unset, non-claude-ignored) and pins CLAUDE_CONFIG_DIR in the test
helper so launch assertions no longer depend on the developer's environment.

* no-mistakes: apply CI fixes
…guid#1233)

* fix: preserve dispatch harness identity

* no-mistakes(review): Fix Grok counterfactual tuple validation

* no-mistakes(document): Scope dispatch authentication to selected tuple

* fix: restore dispatch instruction budget

* no-mistakes(review): Scope dispatch authentication after candidate selection
* fix(bin): handle dash-leading harness process names (#2)

* fix: handle dash-leading harness process names

* no-mistakes(review): Make dash-leading harness regression hermetic

* fix: preserve secondmate reply routes across relative homes

Resolve relative home, data, and state inputs before durable charter generation, and fail when caller-relative directories cannot be resolved.

Use absolute paths at the related spawn, AFK daemon, and X-mode cross-process handoffs so later processes cannot reinterpret them from another working directory.

* no-mistakes(review): Preserve absolute overrides and normalize relative durable paths

* no-mistakes(review): Normalize relative home before deriving durable paths

* no-mistakes(document): Document relative durable-path normalization

* no-mistakes(review): Captain: Ignore inherited CDPATH during relative path normalization

* no-mistakes(lint): Fix empty CDPATH assignments for ShellCheck
* Add internal status skill

* no-mistakes(document): register /status skill in documentation-audiences inventory

* no-mistakes(lint): replace grep|wc -l with grep -c in status skill test

* test: silence literal status skill patterns

* Refactor bearings default to chat-only

---------

Co-authored-by: Kun Chen <3233006+kunchenguid@users.noreply.github.com>
* docs: add captain-approved project operation exception to hard rule 1

Firstmate stays read-only over projects by default, but when the captain
clearly approves a concrete project operation and scope in the moment,
firstmate may perform exactly that approved operation with its own tools.
The approval is never inferred, broadened, or standing, and it does not
relax the existing force, discard, unlanded-work, or merge-authority
boundaries.

* no-mistakes(review): Clarify captain-approved project operation boundaries

* no-mistakes(document): Clarify captain-approved project operation scope

* docs: cover directories and preserve the operation-or-scope alternative

Widen the captain-approved project operation exception in AGENTS.md to
files or directories, and restore the explicit operation-or-scope
alternative that a prior pipeline auto-fix had collapsed into "and".

Rework project-management SKILL.md's Remove section, which previously
told firstmate to refuse project removal until a guarded helper existed;
that helper was never built, so the text directly contradicted the new
instruction-only exception. It now points at the exception plus the
existing removal preflight it still requires unchanged.

Update the one instruction-owners test assertion that hard-coded the
sentence removed above, so the suite tracks current, not obsolete, text.

* docs: add captain-approved project operation exception to hard rule 1

Firstmate stays read-only over projects by default, but when the captain
clearly approves a concrete project operation and scope in the moment,
firstmate may perform exactly that approved operation with its own tools.
The approval is never inferred, broadened, or standing, and it does not
relax the existing force, discard, unlanded-work, or merge-authority
boundaries.

* no-mistakes(review): Clarify captain-approved project operation boundaries

* no-mistakes(document): Clarify captain-approved project operation scope

* docs: cover directories and preserve the operation-or-scope alternative

Widen the captain-approved project operation exception in AGENTS.md to
files or directories, and restore the explicit operation-or-scope
alternative that a prior pipeline auto-fix had collapsed into "and".

Rework project-management SKILL.md's Remove section, which previously
told firstmate to refuse project removal until a guarded helper existed;
that helper was never built, so the text directly contradicted the new
instruction-only exception. It now points at the exception plus the
existing removal preflight it still requires unchanged.

Update the one instruction-owners test assertion that hard-coded the
sentence removed above, so the suite tracks current, not obsolete, text.

* no-mistakes(review): Align project removal preflight with approved exception

* no-mistakes(document): Align project removal documentation with approved exception

* fix: restore removal test byte-for-byte and preserve the default sentence

tests/fm-instruction-owners.test.sh had been changed to assert different
text; restore it byte-for-byte to origin/main. project-management SKILL.md's
Remove section now keeps the exact default "Never issue a raw removal
command from Firstmate." sentence that test still asserts, immediately
followed by the already-approved captain-operation-or-scope exception, so
the default and the exception both stay explicit and consistent.

* no-mistakes(document): Align project-write boundary documentation
…henguid#1275)

* Route project intake through secondmate scopes

* no-mistakes(test): Guard all main-home project registry mutations

* no-mistakes(document): Consolidate secondmate routing documentation

* no-mistakes: apply CI fixes

* Restore new-project routing scope

* no-mistakes(document): Clarify secondmate routing for new-project intake

* no-mistakes: apply CI fixes
)

* fix: scope validation corrections by accepted behavior

* no-mistakes(review): Classify stale delivery evidence as an autonomous correction
…#1282)

* test: remove source-content assertions

* no-mistakes(review): Replace source assertions with runtime behavior coverage

* no-mistakes(review): Isolate Kimi task temp runtime coverage

* no-mistakes(document): Refresh test cleanup documentation

* no-mistakes: apply CI fixes
…#1286)

* fix(watch): bound how long a busy pane may run with no completed turn

A busy pane (backend busy state or the harness's rendered footer) was
unconditional, unbounded proof of liveness in every escalation path, so a
hung foreground tool call behind a busy signature could run for hours
undetected (2026-07 hibit-agent-focus-nonsteal-r1 incident: a catastrophic-
backtracking regex hung one bash call for 25h behind an unchanging
"Working..." footer).

FM_BUSY_TURN_MAX_SECS (default 3600s) now bounds how long a busy pane may
run with no completed turn (state/<id>.turn-ended, or its spawn record
before any turn has completed). Past the bound, busy_turn_over_age routes
the pane through the existing wedge_timer_check, reusing the identical
stale reason, escalation counter, and demand-deep-inspection marker for
human inspection only - never an automatic interrupt, signal, or restart
of the worker or its tool process. A completed turn resets the age.

Reproduced end-to-end against the real installed Pi TUI: a foreground
`sleep 999999` bash call with no timeout renders the actual busy footer,
and two captures ~15s apart show the elapsed counter changing the pane
hash while the same turn stays unfinished. Running the pre-fix watcher
against the real captures showed it never starts a wedge timer no matter
how long the pane stays busy; the fixed watcher starts and escalates the
timer through the same mechanism, while the real hung process remained
untouched and alive throughout.

* no-mistakes(review): fix: parse enriched AFK stale reasons

* no-mistakes(review): fix: preserve enriched wedges during AFK supervision

* no-mistakes(review): fix: route all enriched AFK wedges

* no-mistakes(document): Clarify busy-turn age supervision documentation
…unchenguid#1261)

A name-by-name list of config/ entries silently stops ignoring any new or
home-local file placed there, which makes the working tree read as dirty and
blocks guarded sync paths that refuse to touch a dirty home. AGENTS.md
already documents config/ as captain-private and gitignored as a category;
this makes .gitignore match that contract.
…al coverage (kunchenguid#1304)

The second assertion in fm-gitignore-config.test.sh (added by kunchenguid#1261) greps
.gitignore for a specific spelling of the config/ ignore pattern. It fails
on a semantically equivalent pattern like config/** and does not prove Git
actually ignores anything, per the completed source-content-test audit.

Replace it with a real git check-ignore control test on a generated
unrelated path, and strengthen the existing directory-coverage test with
generated unpredictable direct and nested config/ paths.
)

* Add bounded startup memory curation

* no-mistakes(review): Record reproducible stow verification evidence

* no-mistakes(review): Validate inherited secondmate stow evidence

* no-mistakes(document): Document editable startup-memory budget propagation
* fix(herdr): place workers in the launching agent's exact workspace

Herdr enforces no workspace-label uniqueness, and spawn resolved its
container by taking the FIRST workspace whose label matched the home
label. With two workspaces both labeled "firstmate", a worker launched
from the second one was created in the first, so it appeared in a
different space than the Firstmate the captain was watching.

Reproduced end to end on Herdr 0.7.5 protocol 17 by running the real
bin/fm-spawn.sh inside a launcher pane in the second "firstmate"
workspace: the worker landed in w1 while its launcher was in w2, with an
unrelated third workspace focused throughout, which also rules out any
dependence on the focused workspace.

Placement now binds to the launching process's own Herdr identity. Herdr
injects HERDR_PANE_ID, HERDR_SESSION, and HERDR_SOCKET_PATH into every
process it manages a pane for, and fm_backend_herdr_launcher_identity
resolves that pane's current owning tab and workspace live from Herdr,
cross-checking the pane against its tab and confirming the workspace
exists exactly once in the session. The injected HERDR_TAB_ID and
HERDR_WORKSPACE_ID are creation-time snapshots and are deliberately not
read as current identity. Labels are no longer placement authority.

A claimed parent identity that is unreadable, contradictory, stale, or
from another named session or Herdr server stops the spawn before any
worker endpoint exists, rather than degrading to a label search. A
launcher with no Herdr ancestry has no workspace to inherit and keeps
the per-home labeled container, which must now resolve to exactly one
workspace; two same-labeled candidates refuse instead of adopting
either. A --secondmate launch keeps standing up that home's own
workspace by design.

With presentation spaces enabled, the projected child is created and
bound under that same exact parent and anchors its ordering on it, so a
duplicated home label no longer makes the layout ambiguous. Projection,
focus restoration, restart binding, and quarantine rules are unchanged,
and children are never collapsed into the parent. tmux, Zellij, cmux,
Orca, and the away-mode daemon terminal were each inspected and are not
affected: none resolves a container by searching mutable labels.

tests/fm-backend-herdr-launcher-workspace-e2e.test.sh drives the real
spawn and teardown against an isolated Herdr lab, with its headline case
running fm-spawn.sh inside a real Herdr pane so the identity comes from
Herdr's own injection. The refusal matrix and the ordering anchor are
covered deterministically in tests/fm-backend-herdr.test.sh.

Eight existing real-Herdr suites inherited the developer terminal's own
Herdr pane into their isolated lab sessions, which the new cross-session
check correctly refuses. tests/herdr-test-safety.sh now owns
herdr_forget_inherited_pane and those suites call it, so what they assert
no longer depends on where they were launched from.

Two unrelated fixes found along the way. tests/fm-secondmate-harness.test.sh
had the same class of environment leak through CLAUDECODE, which outranks
PI_CODING_AGENT in bin/fm-harness.sh and made its pi-signed ancestry case
resolve "claude" whenever the suite ran inside Claude Code. And
fm-spawn.sh's usage() printed a fixed line range that had already been
truncating its own help mid-sentence.

* no-mistakes(review): Enforce exact Herdr launcher and projection identity

* no-mistakes(document): Document exact Herdr launcher workspace placement
* feat(calm): replace Pi's working row with an animated ship while Calm is on

While Calm is active and one logical agent run is under way, Calm now hides
Pi's built-in working row and renders a small two-row SSHHIP-derived boat in
its place. When Calm is off, Pi's stock working row is left untouched.

The presentation uses only public Pi extension API: setWorkingVisible(false)
plus a temporary setWidget() component whose render(width) owns the responsive
geometry and whose timer requests a TUI render. Visibility follows agent_start
through agent_settled, so the boat does not flicker between tool calls,
automatic continuations, retries, or compaction inside the same run, and
settle, abort, and failure all reach the same cleanup.

fm-calm.ts stays the sole owner of the presentation choice and the only caller
of setWorkingVisible(); the new lib owns the sprite geometry and widget.

* no-mistakes(review): Guarded Calm-off lifecycle visibility writes; focused tests pass

* no-mistakes(test): Fixed Calm E2E wait to include tmux scrollback

* no-mistakes(document): Document Calm working boat behavior

* no-mistakes: apply CI fixes

* feat(calm): slow the Calm boat, animate blue water, and make the sail directional

The boat now moves one column every 880ms while a bounded fixed-cell water phase
advances every 220ms, so the water ripples several times between boat steps and
the presentation reads as calm. One scheduler drives both clocks and disposing
the widget stops them together; ticks rather than wall-clock timestamps drive
every state change, so tests seek animation time exactly.

Colors are standard ANSI foreground codes instead of theme lookups: blue for
every water cell and yellow for the complete boat, each run closed with a
default-foreground reset so nothing bleeds into padding or later frames. ANSI
bytes never enter geometry, so visible width stays exact.

The mainsail is directional and trails aft of the mast: <| travelling right and
|> travelling left. Direction reverses the moment the boat lands on an endpoint,
so the endpoint frame already shows the new heading and no frame at or after a
bounce shows the previous sail.

* test(calm): wait for the Ctrl+O expansion redraw this block asserts

* docs(calm): record the revised working-presentation verification evidence

* no-mistakes(document): Fix Calm feasibility document EOF whitespace
…henguid#1349)

* fix(dispatch): scope candidate authentication to its own surface

A locally expired timestamp in one credential store was reported to the
captain as a sign-out, including for dispatch candidates that never read
that store. A `harness=pi, model=xai/grok-*` candidate authenticates
through Pi's own xAI credential, but the only Grok quota reading
available was gated on the standalone Grok CLI's separate token, whose
expiry clock drifts independently. The always-loaded intake rule then
turned that unreadable quota into a mandatory captain escalation.

Add `bin/fm-auth-preflight.sh` as the deterministic owner of the parts
that must not depend on agent memory: it resolves a tuple's
authentication surface from quota-axi's own emitted auth sources rather
than from a harness or model name, so another harness's CLI can never
gate a candidate that does not use it. A vendor CLI is launched only
when the tuple's own harness owns the credential store under test and a
non-destructive discovery command is registered for it, which today is
`grok models` alone. That probe runs at most once with stdin closed and
a hard timeout, reads its verdict from the first stdout line because the
command exits 0 either way, treats unrecognized output as indeterminate,
and never invokes login, logout, or the interactive TUI. Quota is read
at most twice, and unknown headroom never makes a candidate ineligible
on its own.

Update the dispatch procedure to match: usable authentication with
unmeasurable headroom stays eligible at lower preference with the
unknown disclosed, and stop-and-report is reserved for unresolved
authentication, an unresolved relationship, or malformed configuration.
Record that Grok's `credits.remaining` is a prepaid balance rather than
window headroom.

Gate quota-axi at 0.1.16 in bootstrap, the first build reporting
per-credential auth sources. A stale install previously passed the
presence check silently, which is why a fix published two days earlier
was still not in effect.

Replace the orphaned quota-array-dispatch fixtures, which encoded a
`provider: "xai"` shape the tool never emits and had no consumer, with
fixtures shaped like real 0.1.16 output that the new suite drives the
script against. The suite asserts the verdict and, separately, which
vendor CLIs were launched, so a Pi/xAI candidate reaching the Grok CLI
fails. Map `tests/fixtures/<dir>` to its consuming suite so a fixture
change selects the right tests instead of refusing.

* refactor(bootstrap): give the quota-axi floor one owner

The floor was stated twice - once in bootstrap's gate and once inline in
the auth preflight - so bumping it needed two edits that could drift.
Move it to bin/fm-quota-axi-lib.sh alongside its rationale, matching the
existing tasks-axi library, and derive the comparison from the constant
so the number appears exactly once. Bootstrap turns a failing check into
the operator diagnostic; the preflight refuses to emit an unscoped
verdict. Map the new library to both consuming suites so a bump re-runs
them, and record that any usable source means the surface authenticates.

* no-mistakes(review): Captain: bound quota checks and removed Python dependency

* no-mistakes(review): Captain: enforce conservative headroom and exact preflight retry

* no-mistakes(review): Captain: preserve OpenCode eligibility without auth-surface guessing

* no-mistakes(review): Captain: reject malformed OpenCode model relationships

* no-mistakes(review): Captain: exempt verified unmodeled tuples from intake escalation

* no-mistakes(document): Updated dispatch authentication documentation

* no-mistakes: apply CI fixes
…nchenguid#1350)

* feat(x-mode): reconcile promised public replies deterministically

A promised final reply in an X or Discord thread was only kept while the
primary remembered it. Compaction or restart erased that memory, so a typed
public-followup obligation could sit at pending-work after its PR merged and
the original thread never got its reply.

Make the promise durable state instead:

- bin/fm-public-followup-emit.sh reports a typed terminal work result (source
  home, work id, generation, outcome, safe deliverables, bounded public-safe
  text) into the owning home's private inbox. The event id is derived from
  that identity tuple, so duplicate reports and restart replay converge with
  no coordination, and nothing ever parses a free-form done: sentence.
- bin/fm-public-followup.sh registers a commitment, reconciles events through
  tasks-axi public-followup, and runs the idempotent delivery sequence
  (begin-delivery with the payload hash, post, record the posted receipt or a
  typed error) against the stored platform and opaque thread binding. A
  delivery interrupted between post and receipt refuses rather than risk a
  second public reply.
- Session start surfaces unresolved commitments from disk, the existing relay
  poll surfaces a new terminal-result set once, and teardown refuses while
  this home still owes a public reply for that exact work.

tasks-axi public-followup remains the only owner of the obligation state
machine, state/x-context/ the only owner of the private request context, and
fm-x-reply.sh the only thing that posts. Its new optional --receipt-file is
the one addition there, so a caller can record how many messages were sent.

A home that never opted into the myfirstmate relay gates out on a single
[ -f "$FM_HOME/.env" ] test: no tasks-axi call, no backlog or context scan,
no output, and no artifact. Evidence in docs/verification/public-followup.md.

* no-mistakes(review): Hardened public-followup reconciliation and ownership guards

* no-mistakes(review): Hardened typed terminal cleanup and receipt reconciliation

* no-mistakes(review): Automated typed-delivery cleanup and strict backlog validation

* no-mistakes(review): Fail-closed parent resolution and registration-safe delivery

* no-mistakes(review): Harden relay gating and validate secondmate bindings

* no-mistakes(review): Use owner-aware single-gate teardown protection

* no-mistakes(document): Correct public-followup documentation drift

* no-mistakes(lint): Quote done literals to fix ShellCheck warnings

* no-mistakes: apply CI fixes
…c ownership

Lane B of the documentation single-source-of-truth commission: reduce the
always-loaded contract to what only it can own, and convert the review's
ownership table from prose into a mechanically enforced artifact.

B1/B4 - AGENTS.md section 2 becomes a pointer plus safety lines.
The 9,407-byte fenced home tree restated docs/configuration.md, which already
declares itself the layout owner and explicitly pushes exact child fields to
each producing script's header. Every artifact the tree named was verified to
have such an owner before removal. What survives is what has no other owner:
the wake-event-not-truth rule, the never-touch watcher/auto-arm/sub-supervisor
classes, the check.sh execution-trust boundary, the scout report's survival of
teardown, and the corrected secondmates.md wording (created lazily by
fm-home-seed.sh, so absence means no secondmate is registered).

B2 - section 13 becomes a generated trigger index.
bin/fm-skill-index.sh renders the roster from each skill's own frontmatter,
selecting on user-invocable:false. It stays silent on harnesses that already
inject skill descriptions (claude, grok - both verified) and emits everywhere
else, including unknown harnesses: suppression requires positive evidence,
because a wrongly suppressed index silently removes every load trigger. A new
agent-only skill is now registered once, in its own frontmatter.

B3 - documentation-audiences.json gains injection and responsibility per
surface, and fm-doc-audience-check.sh requires both. The one-sentence limit on
responsibility is the enforcement: a surface needing two sentences owns too
much. The always-loaded set is now a queryable list rather than a claim.

Measured byte deltas (always-loaded plane):
  AGENTS.md   55,237 -> 45,071  (-10,166)
    section 2  10,777 ->  2,758  (-8,019; plan target -6,907)
    section 13  2,913 ->    605  (-2,308; plan target -2,927)
  Generated index costs 5,329 bytes only on non-injecting harnesses, so the
  net is -10,166 on claude/grok and -4,837 elsewhere.
  documentation-audiences.json grows 8,344 -> 17,081, never injected.

Certification: session-start smoke read under both a claude and an opencode
primary confirms no operator action lost its instruction; new
tests/fm-skill-index.test.sh (6 cases) covers suppression, emission, roster
derivation, folded-description rendering, and digest composition;
tests/fm-documentation-audiences.test.sh gains 2 cases for the required
fields; fm-lint.sh and fm-doc-audience-check.sh green.
@sbracewell64
sbracewell64 force-pushed the fm/doc-truth-fleet-lane branch from 2039ca5 to 81fb495 Compare July 31, 2026 02:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants