fix(secondmate): account for every registered secondmate at session start - #2526
Open
IanQiu979 wants to merge 3 commits into
Open
fix(secondmate): account for every registered secondmate at session start#2526IanQiu979 wants to merge 3 commits into
IanQiu979 wants to merge 3 commits into
Conversation
…tart AGENTS.md promises the session-start liveness sweep "deterministically accounts for every registered secondmate", but the sweep only iterated state/*.meta records carrying kind=secondmate and never opened data/secondmates.md. A registered secondmate whose runtime record was lost - a crash, a partial teardown, a home restored from backup - was therefore invisible to the sweep rather than skipped with a reason, and no SECONDMATE_LIVENESS: line was printed to say so. The sweep now enumerates the registry as well and names every registered id the metadata scan did not cover: SECONDMATE_LIVENESS: secondmate <id>: skipped: no runtime record Relaunch needs a recorded endpoint to act on, so the registry pass reports rather than guessing at one; every existing guarantee is unchanged. Recovery still runs only from the recovery-grade dead or missing states, ambiguous, unreadable and unreachable remote targets are still preserved, and both passes stay a primary-only no-op inside a secondmate home, which holds neither a kind=secondmate meta nor a registry of its own. Two registry-parsing defects made that guarantee unreachable in practice and are fixed alongside it: - The record regex anchors the generated (home: ...; added ...) suffix to end-of-line, so any character after the closing parenthesis fails the parse - but secondmate-provisioning did not say the suffix must come last, and following it as written produced an unparseable record. The skill now states that extra prose goes before the suffix. - secondmate_registry_validate_bindings aborted on the first malformed line, so one annotated entry disabled validation for every other secondmate in the home. It now collects and reports all of them, and fm-home-seed.sh validate prefixes each reported line. Regression coverage drives the real bin/fm-home-seed.sh validate command and the real sweep through bin/fm-bootstrap.sh.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes two high-severity defects the 2026-08-16 drift audit found in firstmate's own always-loaded contract (findings D1 and D2). Both are cases where the documentation and the code disagreed; the point of this change is that they agree when it lands.
D2 - the sweep now keeps the promise AGENTS.md makes
AGENTS.md:159tells every firstmate session that the session-start secondmate liveness sweep "deterministically accounts for every registered secondmate". It did not.secondmate_liveness_sweeponly iteratedstate/*.metarecords carryingkind=secondmateand never openeddata/secondmates.md.Live evidence, not a hypothetical. The captain's home was in exactly the failing state: one registered secondmate (
bubble-bobble-sm, a real seeded home with its own charter and an active backlog) and zero secondmate metadata records. That secondmate was therefore invisible to the sweep rather than skipped with a reason, and noSECONDMATE_LIVENESS:line was ever printed to say the guarantee had not been met. BecauseAGENTS.mdstates the guarantee, no session had cause to go looking.The consequence generalizes: a registered secondmate that loses its runtime metadata - a crash, a partial teardown, a home restored from backup - is silently never relaunched and never reported.
The sweep now enumerates the registry as well and names every registered id the metadata scan did not cover:
Narrowing the doc to "every secondmate with a runtime record" was considered and rejected: it is honest, but it leaves the recovery hole open.
Design constraints held throughout:
deadormissingstates, and ambiguous, unreadable, and unreachable remote targets are still preserved.kind=secondmatemeta nor adata/secondmates.mdof its own. This is the same reasoning already recorded atbin/fm-bootstrap.sh:585-586.<unknown>id so every emitted line still matches the one documented shape; a real registry id is a plain[A-Za-z0-9._-]+slug and cannot collide with it.AGENTS.md:159itself is deliberately not edited - the code now satisfies it as written. Per.agents/skills/firstmate-coding-guidelinesthe always-loaded contract is kept lean, so the new skip reasons were routed to their owner,.agents/skills/bootstrap-diagnostics, instead of being added inline.D1 -
fm-home-seed.sh validaterefused the entire live registryTwo separate defects, both fixed:
The contract produced records its own parser rejects.
bin/fm-secondmate-registry-lib.shanchors the generated(home: ...; added ...)suffix to end-of-line, so any character after the closing)fails the parse - butsecondmate-provisioning/SKILL.mdnever said the suffix must come last. The prose that broke the live registry was written by firstmate itself on 2026-08-08 while repairing a lost entry, i.e. following the skill as written produced an unparseable record. The skill now states that the generated suffix must be the last thing on the line and any extra prose goes before it.Validation aborted on the first malformed line, so one annotated entry disabled validation for every other secondmate in the home, and
secondmate_registry_fieldreturned 1 for every field lookup on that id. Validation now collects and reports all malformed records, implemented as a separate parse pass so the binding checks still run only on a registry known to parse end to end. Each reported line carries its own prefix.The captain's live
data/secondmates.mdwas repaired separately by moving the bracketed note ahead of the suffix with its wording unchanged; that file is captain-private, gitignored, and not part of this diff.Tests
Five new regressions, all confirmed failing against the pre-change code:
<unknown>and never kill or respawn anything.Every one drives a real executable -
bin/fm-home-seed.sh validateandbin/fm-bootstrap.sh- rather than re-describing the behaviour, per the "exercise behavior through an executable interface" rule infirstmate-coding-guidelines.Validation
Shipped through this repo's own no-mistakes pipeline: intent, rebase, review, test, document, lint all green (
outcome: passed). The review round surfaced and fixed four issues the original change missed, most importantly that the new registry read could go silent on a present-but-unreadable registry - which would have re-opened the exact blindness this change exists to close.bin/fm-lint.shandbin/fm-doc-audience-check.share clean;tests/fm-secondmate-liveness.test.sh,tests/fm-secondmate-safety.test.sh,tests/fm-secondmate-sync.test.sh,tests/fm-secondmate-harness.test.sh, andtests/fm-bootstrap.test.shall pass.