charon v0.1: the ferry log — every verdict re-derived from bytes, chained, and attacked before it was announced - #60
Merged
Conversation
…s what a verdict can mean, with a total gates table and its contaminated prior cited by digest Leg 4 of PLAN_the_next_level. A design, not a preregistration: the proposed gates block parses under styxx.protocol, every one of 4096 gate combinations reaches one of 12 named verdicts, every gate carries a power basis, and the exploratory token-kind receipt is cited by blob digest as the contaminated prior. Fresh corpus disjoint from the 140 + 82 repositories already judged; two seat families gated alone; integer cells sized to 30; additivity as the test that separates a form-independent factor from an interaction; one-repository concentration as an INVALID. Sworn, 9 spans, at d35ed81. Licenses nothing until signed and renamed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every verdict this lab ever issued, re-derived from bytes, hash-chained, with the size of the receipt set printed beside every HELD; SKEW (the verifier moved) distinguished from DRIFT (the bytes moved); reproduces, never adjudicates; no signatures, no fetch, no immutable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ned, with the receipt-set size on every line styxx/charon.py, built to SPEC_charon_v01_2026_09_02.md. Three derivers wrap the three verifiers the lab already has (styxx.sworn at a named commit, styxx.capsule, styxx.corpus_audit over styxx.certify); Charon reproduces and never adjudicates. Every entry is a JCS-digested core chained to the line before it; timestamps are outside the digest. verify names SKEW (the verdict moved and the verifier's bytes moved) apart from DRIFT (the verdict moved under the same build), UNRESOLVED (bytes unavailable, never an accusation) and TAMPER (the chain broke); exit 1 only on TAMPER. The page is one static file with no script and no request. The first log: papers/charon/charon.log.jsonl — 18 sworn documents at their commits, 12 capsules, 210 tracked certificates (anc/ staging copies excluded); verify: 240 REPRODUCED, 0 of anything else; head 7eec6b2f. Two capsules record reproduced=false at ingest with the reason on the line: the UNCOVERED suffix a later verifier added to the verdict string, and the retired path-claim branch changing the gate record — the instrument moved since they were minted, and capsule.py compares verdict strings where the corpus auditor compares classes. Recorded, not repaired here. tests/test_charon.py: 13, incl. tamper by edit and by removal, SKEW vs DRIFT vs MOVED_VERIFIER under a monkeypatched verifier, UNRESOLVED on an absent commit, LF everywhere, no <script. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…roduced-at-ingest split; the page colours OATH classes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s the 49th arc Every count bound to charon_verify_result.json or to a line of the log itself: 240 lines, 240 REPRODUCED, 0 TAMPER, receipt sets up to 21 with 10 of 227 held-class lines on ten or more, 18/18 sworn documents reproduced at ingest, 6 OATH capsules and 1 diffgate capsule not (the verifier moved: the UNCOVERED suffix, the retired path branch), 3 certificates not — two known drift flags and one new: the staged arXiv copy arxiv/read_neq_write/source.md re-certifies OATH-FAILED where it recorded OATH-HELD, outside the papers/ tree the corpus audit walks. INDEX row added; charon leaves NOT_ARCS; CHANGELOG entry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…log rebuilt at schema v1 papers/charon/ATTACKS_charon_v01_battery_2026_09_02.md — three attackers, three lenses, run against the module at 6b61f12 before any announcement, as the standing rule requires. Four sentences the instrument published about itself were false and are now narrower and true: 1. the chain binds order and content TO THE HEAD, not against rebuilding. A forger who recomputes seq/prev/entry_id down the file produces a chain that checks. verify/status now take --expect-head, HEAD_MISMATCH is a status, and a report without an expected head establishes internal consistency only — which the report now says. 2. capsule verdicts were COPIED from the embedded record, not re-derived; verify_capsule computed a live verdict and returned the embedded one. Both capsule kinds now carry the live re-derivation, with the embedded string as counts.recorded_verdict; a test forges an embedded verdict and asserts it never reaches the line. 3. verify compared the verdict class and one module's bytes; a line whose receipts, subject digest and commit had all moved came back REPRODUCED. It now compares the whole core and reports fields_changed, subject_moved and receipts_moved. REPRODUCED is renamed SAME_LINE — the old word collided with the artifact-level `reproduced` flag. 4. SKEW saw one file. verifier.modules now carries the whole derivation path — Charon included — and SKEW detection is bounded by that set, which the module states. Also repaired: a chained header (an edited header is TAMPER); ingest onto a headerless log refused; a BOM, a non-JSON line or a missing key is a reported problem, never a traceback; no absolute path is ever written; a missing log is refused instead of printing a clean zero; CRLF and file digest reported; resolved receipts hashed onto OATH lines beside the cited ones; sworn `reproduced` runs styxx.sworn.verify_receipt rather than comparing one string; vacuous HELD excluded from held counts; `derive` prints the exact core a line carries and the page prints that command on every row. styxx/capsule.py: layer 2 compares verdict CLASSES, not strings. The v0.13 UNCOVERED band appends ", N uncovered" to a verdict — a coverage report in the headline, not a verdict change — and six sound capsules read as failures because of it. A class change still fails; the string difference is reported as advisory. tests/test_capsule_uncovered_suffix.py pins both, incl. a forged class. styxx/sworn.py: GitTree._index sizes with --batch-check and streams the bodies it keeps, from its own feeder thread. Reading every blob of the tree into one buffer per commit grew a re-derivation to 13 GB and died — the red team hit it and could not finish a re-verification. The log is rebuilt at schema v1 by papers/charon/build_log.py, which IS the population: git ls-files over the three suffixes, the arXiv staging certificates entering as UNRESOLVED lines rather than absences, and one exclusion — the sworn RESULT that describes the log, because a snapshot cannot contain its own description (the rule the corpus census already pays). 243 lines, head bcffbebc; SAME_LINE 243, TAMPER 0. The v0 log stays in history at a5cf9ec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nces the attackers found wrong The RESULT is rewritten against the rebuilt log and re-sworn at 16e30ef: 26 spans, SWORN-HELD. Every sentence the battery contradicted is corrected rather than softened: - the handoff capsule's divergence is its tests_pass explanation string, which grew when the evidence channel shipped — not "the retired path-claim branch", which an earlier draft asserted and the bytes do not support; - the three certificates are one whose verdict moved, one whose receipt changed (and is therefore incomplete), and one whose verdict moved — not "one incomplete" as a separate line; three more had no document at all and are UNRESOLVED lines; - arxiv/read_neq_write/source.md is the canonical submission source, not a staged copy, and it sits outside the directory REPLICATIONS.md runs the corpus audit over — a property of the invocation, not of the code; - "every verdict this lab ever issued" becomes "the record over three verdict-bearing formats"; thirty-four seal.json artifacts have no deriver and appear on no line; - receipts.n means different things by kind, and only the 8 OATH lines among the 10 held-on-ten are the shape the dogfood warned about; - 243 SAME_LINE is a determinism check, not a stability result: verify ran under the builds ingest ran under, minutes later, on the same tree. The ten OATH capsules now reproduce; six of them read as failures until the capsule verifier was taught to compare classes, and that loosening is stated as one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ree digest is content identity modulo newlines CI caught it where Windows could not: the resolved receipt digests on an OATH line disagreed between the two checkouts, because a raw hash of working-tree bytes is CRLF on Windows and LF on Linux. Under that rule a stranger re-deriving this log on Linux would have seen all 213 OATH lines move, and the promise the log makes — that a stranger re-runs it and gets the same lines — would have been false on half the world's checkouts. _content_sha256 normalises CRLF to LF before hashing, which is the doctrine corpus_audit._receipt_sha_matches already states for certificates: a hash that depends on line endings is pinning the wrong thing. Applied to an OATH certificate's document, its resolved receipts, and a capsule file. NOT applied to a sworn document — that format refuses newline normalisation by design and its bytes are pinned by .gitattributes — nor to digests from git plumbing or embedded base64, which are already stable. Disclosed as the auditor discloses it: this certifies content identity, not byte identity. A consequence on every OATH line: receipts.sha256 and receipts.cited.sha256 now differ, because every receipts_sha256 in this corpus was recorded from a Windows tree. Both sets are on the line and the certificate still reproduces, because the auditor compares content. tests/test_charon.py builds the same certificate under LF and under CRLF and asserts the two lines carry identical subject and receipt digests. SPEC errata E15. Log rebuilt: 243 lines, head 1647a26a, SAME_LINE 243. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26 spans, SWORN-HELD at dd78bc2. New head 1647a26a, new log digest, and one added sentence: a working-tree digest is content identity modulo newlines, so an OATH line reads the same on either checkout while the certificate cited what a Windows tree gave it — both sets are on the line. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… check file was left at 48 The INDEX row landed with the charon RESULT; papers/build_index.py regenerates this file and it was not re-run. No claim moves; the check reads ok either way. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 5, 2026
fathomlab
added a commit
that referenced
this pull request
Sep 5, 2026
…-derived from bytes and chained charon v0.1: the ferry log — re-targeted to main after #60 merged into its own base
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.
charon v0.1: the ferry log — the lab's record over three formats, re-derived from bytes, chained, and attacked before it was announced
Stacked on #59 (base:
feat/sworn-v02-next-level). Spec committed before the module; module; adversarial pass; repairs; log rebuilt; RESULT re-sworn against it.What Charon is
styxx/charon.py— the log of crossings. Every line is a verdict re-derived from bytes by one of the three verifiers the lab already has: a sworn document at the commit its sidecar names (styxx.sworn), a capsule (styxx.capsule), an OATH certificate with its receipts (styxx.corpus_audit→styxx.certify). Charon reproduces; it never adjudicates, accuses no one, fetches nothing, signs nothing.verifyseparates a core that moved with the instrument's bytes from one that moved under the same build, beside MOVED_VERIFIER, UNRESOLVED, HEAD_MISMATCH and TAMPER.verifier.modulescarries the whole derivation path, Charon included.bcffbebc…. SAME_LINE 243, TAMPER 0 — a determinism check, not a stability result. The population ispapers/charon/build_log.py, not a sentence.The adversarial pass — run before any announcement
papers/charon/ATTACKS_charon_v01_battery_2026_09_02.md: three attackers, three lenses. Four sentences the instrument published about itself were false, and are repaired:seq/prev/entry_idproduces a chain that checks. The chain binds order to the head →--expect-head,HEAD_MISMATCH, and a report that says so without one.verifyre-derives every line." It compared a class. It now compares the whole core and reportsfields_changed,subject_moved,receipts_moved. REPRODUCED →SAME_LINE.Also repaired: chained header; refused headerless ingest; malformed lines as TAMPER not tracebacks; no absolute paths; refused missing log; resolved-vs-cited receipts;
reproducedviastyxx.sworn.verify_receipt; vacuous HELD excluded; aderivesubcommand the page prints on every row. Unrepaired attacks are named with what the instrument prints instead.What the log found
Seven lines record an artifact that did not reproduce at ingest or had nothing to reproduce against — each with its reason on the line:
arxiv/read_neq_write/source.mdre-certifies OATH-FAILED where its certificate recorded OATH-HELD, with every byte and receipt digest matching. The verifier moved. This is the canonical arXiv/Zenodo submission source and it sits outside the directoryREPLICATIONS.mdruns the corpus audit over, which is why no audit reached it.tests_passexplanation string grew when the evidence channel shipped;Two repairs outside charon
styxx.capsule: layer 2 compares verdict classes, not strings. The v0.13 UNCOVERED band appends, N uncovered— a coverage report, not a verdict change — and six sound capsules read as failures. A class change still fails; the string difference is advisory. This also unblocksscripts/zenodo_capsule_arc.py, which refused to deposit on exactly those four capsules.styxx.sworn:GitTree._indexsizes with--batch-checkand streams. Reading every blob of a tree into one buffer per commit grew a re-derivation to 13 GB and died.Verification
tests/test_charon.py27,tests/test_capsule_uncovered_suffix.py3,ruffclean on every touched file16e30ef: 26 spans, SWORN-HELDAlso in this branch
papers/closed-model-frontier/DESIGN_provenance_law_2026_09_02.md(sworn): leg 4 of the plan — 12 gates, 4096 combinations, 12 named verdicts, every gate with a power basis, contaminated prior cited by digest. Licenses nothing until signed.What it does not say
That any verdict is true. Who wrote any line. That a rebuilt or truncated log is detectable without a head pinned outside it. That receipt shopping is prevented — it is printed. That anything is immutable or tamper-proof. Thirty-four
*.seal.jsonartifacts have no deriver and appear on no line. The attacker was the builder.🤖 Generated with Claude Code