feat: add a family conformance gate that executes documented exit contracts - #82
Merged
Merged
Conversation
…tracts
Every check-family member's SKILL.md passed the clause-7 acceptance test
("a fresh-context agent, given only this file, can produce a well-formed
invocation"). All four still misstate their own exit-code contract. That
test checked invocability; nothing checked truth.
scripts/family_conformance.py runs a member's CLI with read-only probes and
diffs observed behaviour against what its SKILL.md claims:
UNDOCUMENTED_EXIT_CODE the CLI returns a code SKILL.md never documents
HONEST_LANE_OVERLOAD SKILL.md reserves a code for cannot-adjudicate with
do-not-retry guidance, but a usage error returns it too
STREAM_MISMATCH SKILL.md names one stream for failures, the tool uses
the other
MISSING_PIPE clause 7 codifies --pipe by name; the CLI rejects it
SCHEMA_NOT_FLAG clause 7 codifies --schema as a flag, not a subcommand
It obeys the contract it enforces: exit 0 conformant / 1 findings / 2 cannot
adjudicate, plus --pipe, --schema, and an action field on the honest lane.
Pointed at a repo with no SKILL.md it exits 2 rather than guessing.
Current results: srdcheck PASS; charactercheck, dmcheck, table-kit FAIL.
Stdlib only, and 3.10-safe (tomllib is 3.11+, so [project.scripts] falls back
to a regex parse verified to match tomllib on all four members).
Refs #81
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 19, 2026
chaoz23
added a commit
that referenced
this pull request
Aug 21, 2026
Closes the remaining half of #81. The gate landed in #82 but nothing ran it, so it could only catch defects for whoever remembered to invoke it by hand. Blocking rather than advisory. An advisory job that is permanently red is noise people learn to scroll past, and the gate currently reports real findings in three of four members. So known findings are waived in family-conformance-baseline.json and the job fails only on a NEW divergence. Two rules make the waiver list a ratchet instead of a place defects go to die: - every waiver must name the issue tracking it. A waiver without a ticket is just a hidden defect with extra steps. - a waiver that no longer fires FAILS the gate. Fixing a defect and leaving its waiver behind would silently pre-accept the next regression, so fixes have to shrink the file. Verified in all three directions, because a gate that cannot fail is worthless: known findings waived -> exit 0 a waived finding un-waived -> exit 1, reported as not in the baseline a waiver that no longer fires -> exit 1, reported as STALE BASELINE srdcheck itself passes with no waivers. The baseline's sibling entries are consulted only when those repos are audited, so this job reports nothing for them; the sibling CI jobs come next and will read the same canonical file rather than copying it, per FAMILY.md's pin-by-link rule. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 21, 2026
chaoz23
added a commit
that referenced
this pull request
Aug 25, 2026
* feat: FAMILY.md v2.2 harmonises exit 3; gate can see codes above 3 Two halves of one problem, surfaced by chaoz23/charactercheck#18. CONTRACT. v2.1 said "srdcheck's exit 3 is the family precedent", which was too weak to settle what a member should do when 3 is already spent. v2.2 states the pattern outright: 0/1/2 are the universal verdict contract, >= 3 is the no-verdict taxonomy, and 3 is usage error in EVERY member. A malformed call is the one non-verdict outcome every tool has, so harmonising it means an agent that mis-invokes any member gets the same answer. Further outcomes take 4+. charactercheck therefore moves could-not-retrieve from 3 to 4 rather than taking a different usage code. Decided deliberately over the cheaper option of letting it keep 3 and putting usage on 4: that would have left the family with two spellings for the concept an agent hits most often. GATE. parse_skill capped recorded codes at 0..3, so a documented exit 4 was silently dropped -- and the CLI returning 4 then surfaced as a bogus UNDOCUMENTED_EXIT_CODE against a tool that had documented itself correctly. The gate would have rejected the very refactor the contract now requires. That is the third time this parser has been the defect rather than the tools it checks (line-vs-paragraph in #82, stream-word matching in #84). The shape repeats: the checker silently cannot perceive the thing it is checking. Verified both directions: a synthetic 0/1/2/3/4 SKILL.md now parses all five with honest-lane=2 and usage=4, and all four real SKILL.md files parse unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: drop charactercheck's HONEST_LANE_OVERLOAD waiver charactercheck is harmonising onto exit 3 for usage errors (chaoz23/charactercheck#18). The waiver comes out before the fix lands, as the ratchet requires; the SHA pin keeps charactercheck's CI green in the meantime. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
Closes the gap found by the 2026-08-17 family-wide conformance audit. Implements the gate proposed in #81.
The problem
Every member's
SKILL.mdpassed the clause-7 acceptance test — "a fresh-context agent, given only this file, can produce a well-formed invocation" — when the front doors landed in #71. All four still misstate their own exit-code contract.That test checked invocability. Nothing checked truth.
--schema,tool.json, and the MCP surface are all generated or tested;SKILL.mdis hand-maintained prose that nothing executes.What this adds
scripts/family_conformance.py— stdlib only, no new dependencies. It runs a member's CLI with read-only probes and diffs observed behaviour against itsSKILL.md:UNDOCUMENTED_EXIT_CODESKILL.mdnever documentsHONEST_LANE_OVERLOADSTREAM_MISMATCHSKILL.mdnames one stream for failures, the tool uses the otherMISSING_PIPE--pipeby name; the CLI rejects itSCHEMA_NOT_FLAG--schemaas a flag, not a subcommandIt obeys the contract it enforces — exit
0conformant /1findings /2cannot-adjudicate, plus--pipe,--schema, and anactionfield on the honest lane. Pointed at a repo with noSKILL.mdit exits 2 rather than guessing.Current results
--pipe, honest-lane overload, stream mismatch--pipe,--schemanot a flag, honest-lane overloadReproduces 4 of the 8 independently-confirmed audit findings plus part of a fifth, with zero per-repo configuration. The highest-impact one is dmcheck's
STREAM_MISMATCH: itsSKILL.mdpromises failures print to stderr, and every envelope goes to stdout (stderr is 0 bytes) — so an agent following the docs sees no payload at all. Filed as chaoz23/dmcheck#13.Scope and safety
All probes are read-only:
--help,--schema, a nonexistent flag, and one verb pointed at a path that does not exist. Nothing is written, installed, or mutated.Python 3.10-safe:
tomllibis 3.11+, so[project.scripts]parsing falls back to a regex, verified to produce identical output totomllibon all four members' manifests.Known blind spots, stated up front
SKILL.mdexamples that don't reproduceOne caveat worth recording
The first version of this gate passed dmcheck clean. The stream claim wraps across two source lines —
"Failures print JSON on"/"stderr, never a traceback."— and a line-based matcher saw neither half. A checker that reports PASS because it structurally cannot perceive the defect is the exact failure class this gate exists to catch.Fixed by matching at paragraph level, and it is why the gate was validated against known-bad repos rather than trusted on a green result. A gate's first test is whether it can fail.
Adoption
It currently fails 3 of 4 repos, so land it non-blocking first, fix the members, then flip to blocking.
HONEST_LANE_OVERLOADis deliberatelymedium, nothigh— it fires on 3 of 4 members, and a rule that flags most of the family at high severity trains readers to ignore it.Refs #81. Related contract decision: #80.
🤖 Generated with Claude Code