Skip to content

charon v0.1: the ferry log — re-targeted to main after #60 merged into its own base - #65

Merged
fathomlab merged 10 commits into
mainfrom
feat/charon-v01
Sep 5, 2026
Merged

charon v0.1: the ferry log — re-targeted to main after #60 merged into its own base#65
fathomlab merged 10 commits into
mainfrom
feat/charon-v01

Conversation

@fathomlab

Copy link
Copy Markdown
Contributor

Charon v0.1 — the ferry log — re-targeted to main.

Why this PR exists. #60 was merged while its base was still feat/sworn-v02-next-level, and #59 had already landed on main, so charon went into a branch that was no longer on its way anywhere. Its ten commits are unchanged; this is the same content, aimed at main. #60 is the review of record.

The index_check.json fixup at the head (48 → 49 arc directories, left stale when the charon INDEX row landed) rides along.

🤖 Generated with Claude Code

darkflobi and others added 10 commits September 2, 2026 14:02
…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>
@fathomlab
fathomlab merged commit 55752e4 into main Sep 5, 2026
14 checks passed
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.

1 participant