sworn conformance v0.1: the tests become bytes a second verifier can be held to - #63
Merged
Conversation
…verifier can be held to, frozen before any code Leg 3, item 2 of papers/PLAN_the_next_level_2026_09_02.md, under the plan's own label: the precondition for any second verifier; no claim. The spec rules ten things before any code exists: the pinned core follows the code (thirteen keys, verifier and coverage excluded, the receipt's build-bound digest never a vector's number); inputs are bytes in six modes; the clock and the git dates are pinned at generation; the coverage floor is pinned and the observer is not; nothing unvectorable is dropped silently; a moved core refuses regeneration; one digest pins every byte transitively with provenance outside it; `requires` says what a verifier needs; the layout wears no suffix another sweep claims; and the verifier stays pure, with a SnapshotTree that reproduces every GitTree reason but git_unavailable without a git binary. It widens the plan row's source list to both sworn test files and says why. It licenses nothing: the RESULT that follows the set carries every count as a sworn span. Same commit: .gitattributes gains `conformance/** -text`, because this box has core.autocrlf=true and the vectors carry CRLF, lone CR, BOM, NUL and invalid UTF-8. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tTree reason but git_unavailable without a git binary Built to papers/sworn/SPEC_sworn_conformance_vectors_v01_2026_09_05.md, C10, frozen at 1e94721. MemoryTree carries bytes and no modes, so it can never say not_a_blob, receipt_too_large or commit_absent; GitTree says them but needs a git binary. SnapshotTree sits in section 3 of styxx/sworn.py beside MemoryTree, is a dict of {path: {mode, size, sha256, bytes}} at one snapshot commit, and imports nothing and calls nothing: no git, no filesystem, no clock. Its handle commit follows MemoryTree's rule (None means no commit) and verify() overwrites it with the document's commit as for every handle; a handle commit that is not the snapshot's, or is not a full lowercase hex id, is commit_absent; a tree, symlink or gitlink entry is not_a_blob whatever bytes it carries; an entry whose bytes were not embedded is receipt_too_large; from_memory() lifts a MemoryTree to the same snapshot. Everything that reads git to build one is left to the recorder the next commit adds. tests/test_sworn.py gains TestSnapshotTree (26 cases): every MemoryTree vector TestReceipts pins replays through from_memory to the same portable core (the verdict minus verifier minus coverage); a 040000, a 120000 and a 160000 entry are not_a_blob; the four handle-commit shapes (None, another commit, not hex, uppercase, short) resolve as the spec rules; an entry over the cap with no bytes is receipt_too_large and one at the cap is served; a prereg digest is found among embedded blobs and not among unembedded ones nor under a symlink; on the git_repo fixture a snapshot built by ls-tree -r -t -l agrees with GitTree on all nine cases and with MemoryTree on the seven it can express; and the class is exported and its source names neither subprocess nor the filesystem. The three sworn test files pass with no verdict changed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… files and replayed through styxx.sworn under one digest Built to papers/sworn/SPEC_sworn_conformance_vectors_v01_2026_09_05.md, frozen at 1e94721. Three modules under conformance/sworn/. recorder.py is a pytest plugin, loaded with -p, that pins sworn._now and the git author and committer dates to the spec's clock (C3), wraps verify, to_sidecar, load_sidecar, verify_receipt and Manifest.from_dict, records each top-level call's inputs as bytes and its outcome, passes nested calls through unrecorded, and lists what it cannot carry instead of dropping it (C5); it is the only file that reads git, and the verifier never imports it. gen_vectors.py runs the two sources under the recorder, folds the records into vectors addressed by sha256 of jcs({mode, inputs}), merges identical inputs across tests, assigns each vector a family by its lowest source's test class and the v0.2 rules and battery rows its sources pin, replays every vector through styxx.sworn before writing, refuses a nondeterministic id or a moved core in the manner of papers/sworn/reissue_receipts_v1.py (C6), and writes index.json, vectors/<family>.json, blobs.json and observer.json through one LF writer (C7, C9). replay.py is the reference for what a second verifier does, entrypoint by entrypoint, and is what both the generator and the test call. README.md says how to consume and regenerate the set and what passing does not mean. The set itself is generated, never hand-edited; its counts are leaves of conformance/sworn/index.json and the RESULT that follows binds them. The fuzz family is carried in full. Three recorded calls are listed under index.unvectored.skipped rather than carried: the manifest holding a NaN, a sidecar holding a lone surrogate that no UTF-8 text can carry, and the receipt check against this repository's own history. Every reason in REASONS and every verdict in VERDICTS is produced by some vector except the three C5 names, and six refusal codes in the table are produced by no test and are listed as such. The receipt_check inputs embed the issuing build's verifier block by construction; that is recorded as ERRATA E1 on the spec in the commit that carries the RESULT. tests/test_sworn_conformance.py loads the committed set at import, so a missing set is a collection error and nothing skips: every blob hashes to its key; every family file hashes to its index entry and set_sha256 re-derives; every id re-derives from its mode and inputs; every vector replays, per family, with zero skips; every v0.2 rule has a positive and a negative vector and every battery row a vector that shows its verdict; every reason and verdict is produced or listed, and the unvectored lists are exactly C5's; every tracked file under conformance/ resolves text unset and holds no CR; no file wears a suffix another sweep claims; and gen_vectors.py --check regenerates the committed set to its own digest. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ery count a leaf of the index at b02f3fc papers/sworn/RESULT_sworn_conformance_v01_ships_2026_09_05.md with its sidecar and verdict receipt, SWORN-HELD with nothing failed, unresolved or malformed, checked VERIFIED and rendered byte-identical. Every span binds to a leaf of conformance/sworn/index.json at b02f3fc, the commit that carries the set: the label, the vector and family and blob counts, the fuzz family's size, the core and refused outcome counts, the vectors that need a tree, the receipt checks, the skipped count, the one unproduced verdict, the pinned clock and set_sha256. The document ships under the plan's own label, the precondition for any second verifier; no claim, and says so. The set is never regenerated in place after this commit. Same commit: a dated ERRATA section appended to the frozen SPEC, editing nothing above it, with five entries: receipt_check inputs name the issuing build by construction, so C7's invariance holds for every other vector; a lone-surrogate sidecar is a third input the set cannot carry; battery rows carry one shows sentence rather than a positive and a negative; refusal codes no test produces are listed under index.unvectored.refusal_codes; SnapshotTree's handle commit defaults to none, MemoryTree's rule. And the CHANGELOG [Unreleased] entry for sworn conformance v0.1 at the top of the file, in the house shape, ending in what it does not say and what is owed. No .gitattributes line is added: papers/sworn/** is already -text, and tests/test_sworn_eol.py and tests/test_sworn_dogfood.py pass over the new triple. No INDEX row: papers/sworn/ has one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…which index field CI refused this set on Linux with two digests and nothing else, which cannot be acted on. The refusal now prints every family whose file hash moved with its counts, whether blobs.json moved, and any non-family index field that differs. The check still passes here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…latforms agree CI refused this set on Linux: same 3618 vectors, same 3977 blobs, every vector replaying, and a different set_sha256. The drift report named the two things that moved — the worked_examples family and blobs.json — and that family holds the only fixture whose bytes come off the working tree. papers/closed-model-frontier/stage2_result.json is LF in git and CRLF in a Windows checkout, so the set embedded whichever copy the generating machine held. The file is untouched: three committed certificates cite it and a receipt is history. The fixture now reads it with content identity modulo newlines, which is what corpus_audit._receipt_sha_matches and charon._content_sha256 already do to every receipt in the corpus; every assertion in that class reads a JSON leaf, so no verdict moved (348 sworn tests pass unchanged). Regenerated once under the SPEC's own C6 path. The digest moved from cb5d5148… to 96dfe159…, which is the digest the Linux run had already produced — the platforms agree rather than one having been declared correct. SPEC ERRATA records the cause, the repair, and the rule it adds to C7: a vector's bytes may never come off the working tree unnormalised. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e one both platforms produce 13 spans, SWORN-HELD. The only number that moved is the set digest itself; the counts, the families and the boundary sentences are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fathomlab
pushed a commit
that referenced
this pull request
Sep 5, 2026
…ing copy's bytes, so sworn.py is pinned After the worked-examples repair the set still refused to regenerate here, and the drift report named four families — cli, gaming, receipt_v1, rules — all of them receipt_check vectors, which is the class the SPEC's ERRATA E1 already says embeds the issuing build. Decoding one named the field: verifier.sworn_sha256, which styxx.sworn computes over THIS FILE'S WORKING-COPY BYTES. This worktree had sworn.py CRLF; git holds it LF, which is what Linux checks out and what the committed set was generated against. So every sworn receipt, and every conformance vector that embeds one, depended on the line endings of the checkout that produced it. styxx/sworn.py is now `-text` pinned: the blob does not move (the staged diff is empty), and a checkout can no longer change the hash every receipt carries. The working copy here was normalised to match, and the set regenerates to 96dfe159… — the digest #63 produces and the one Linux produced before either repair. Also in this commit: conformance/sworn/replay_js_result.json is renamed replay_js_report.json, because the conformance suite forbids `result` in a file name under conformance/ (a suffix another sweep claims) and this branch had been failing that test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-vectors # Conflicts: # CHANGELOG.md
… are classified, not quoted py3.9, 3.10 and 3.11 refused a set that py3.12 accepted, and the drift report named one field: index.unvectored. Two of its three skipped entries carried a CPython exception message verbatim -- the wording of a NaN refusal and of a lone-surrogate encode error -- and that wording moves between versions. Every site that records why a call could not be vectored now classifies the exception type into a sentence this lab wrote, so the same input yields the same word on every interpreter. Same shape as the worked-examples repair, so the SPEC's ERRATA states the rule once for both: nothing a set pins may come from outside the format, neither the checkout's line endings nor the interpreter's prose. The digest moved to 85e2d3b9…; the RESULT binds it and is re-sworn next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…atforms produce Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-vectors # Conflicts: # .gitattributes # CHANGELOG.md
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.
Leg 3, item 2 of
papers/PLAN_the_next_level_2026_09_02.md: conformance vectors for sworn output, under the plan's own label — the precondition for any second verifier; no claim. Base isfeat/charon-v01(stacked on #60 → #59); independent of #61 and #62.What this is
Every call the two sworn test files (
tests/test_sworn.py,tests/test_sworn_attacks.py) make intostyxx.swornis recorded as bytes — the document, the manifest, a tree snapshot with modes, and the exact receipt core the verdict must reproduce — and addressed by one digest, so that a verifier in another language can be shown where it disagrees, byte by byte, before anyone is asked to trust it.The ladder
papers/sworn/SPEC_sworn_conformance_vectors_v01_2026_09_05.md— frozen alone before any code, withconformance/** -textin the same commit (1e94721).styxx.sworn.SnapshotTree— a tree snapshot with modes that reproduces everyGitTreereason butgit_unavailablewithout a git binary; pure, additive, besideMemoryTree; 26 tests (1bc1b31).conformance/sworn/— the recorder (a pytest plugin that pins the clock and the git dates), the generator (gen_vectors.py, with--checkand--replay), the set (3618 vectors in 20 families, 3977 blobs, 3 calls listed as unvectored with their reasons),observer.jsonoutside the digest, a README, andtests/test_sworn_conformance.py(72 tests, nothing skipped: every blob hashes to its key, every id re-derives, every vector replays throughstyxx.sworn, every rule has both shapes, every closed set is produced or listed, every file is-textand CR-free, and the committed set regenerates to its own digest) (b02f3fc).RESULT_sworn_conformance_v01_ships_2026_09_05.md, sworn, 13 spans, every count and the set digest bound to leaves ofconformance/sworn/index.jsonat the commit that carries them; a dated ERRATA on the SPEC for what it could not foresee (3d94013).The rules that matter
core_sha256 = sha256(utf8(jcs(core)))over the verifier's output minusverifierminuscoverage; the receipt's owndigestis build-bound and is never a vector's number.styxx/sworn.pyre-keys the sixteenreceipt_checkvectors by construction and moves the set digest; the generator reports them dropped and added, and a new set is a new commit with a new RESULT — never in place.Verification
tests/test_sworn.py,tests/test_sworn_attacks.py,tests/test_sworn_eol.py: 463 passed, no verdict changed.tests/test_sworn_conformance.py: 72 passed, 0 skipped.gen_vectors.py --check: stable across three runs on this box.python -m styxx.sworn checkre-derives the RESULT's receipt VERIFIED (digest match, verdict reproduces, same build).python -m ruff check styxx: clean. The wheel does not shipconformance/.What it does not say
That agreement on these vectors makes a verifier correct. That the vectors cover the format — they cover what two test files exercise, written by the builder. That the fuzz family is adversarial. That any second verifier exists. CI (Linux, 3.9–3.12) has not yet run this branch; the set's cross-platform digest stability rests on the pinned clock and git dates making fixture commit ids identical, which is the thing to watch.
Owed
A
committedfamily fromtests/test_sworn_dogfood.py; arefusalattribute on the verifier'sSystemExitif a second verifier needs codes at the source; theverdict_core()split ofverify(); the Python-versus-JavaScript semantics the vectors pin and item 5 must implement. The set is ~8.5 MB in the tree; a JS consumer should load families independently.🤖 Generated with Claude Code