Skip to content

fix(#1087): parse the ledger duplicate-key-strict — a +622-line waiver was recorded with a +10-line justification - #1088

Merged
avrabe merged 1 commit into
mainfrom
fix/claims-duplicate-key-1087
Aug 27, 2026
Merged

fix(#1087): parse the ledger duplicate-key-strict — a +622-line waiver was recorded with a +10-line justification#1088
avrabe merged 1 commit into
mainfrom
fix/claims-duplicate-key-1087

Conversation

@avrabe

@avrabe avrabe commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Closes #1087.

claims.yaml on main carries a duplicate reason: key inside one waiver mapping of the selector_lines_code ratchet. YAML keeps the last value silently, so the surviving justification for RQ-60-VFPPRESSURE increment 1's +622 line growth of the instruction selector is RQ-59-I64SHIFT's reason for +10 lines.

16b135ba  RQ-59-SUBTRACT          18278
2785ffe9  RQ-59-I64SHIFT          18288   +10   <- the surviving reason
e6a3b27a  RQ-60-VFPPRESSURE inc1  18910  +622   <- the actual growth
0ec9dc7a  RQ-60-VFPPRESSURE inc2  19199  +289

The lane did its job — its commit message and the discarded reason both state the +622 honestly. The file edit turned to: 18288 into to: 18910 and appended a second reason: instead of adding a second waiver entry.

Why the gate could not see it

check_ratchet asks only "is there a waiver with to == value, and is its reason non-empty?" Both true. Neither question distinguishes the right reason from someone else's — and the waiver's documented purpose is "permission is per-growth, never standing." A duplicate key makes it standing and deletes the record of what it was granted for, with the gate green.

Red-first, on the real artifact

Same claims.yaml from main, two checkers:

shipped:  51/51 claims hold.                                          EXIT=0
fixed:    claim_check: duplicate key 'reason': declared at line 1311
          and AGAIN at line 1330 — YAML keeps the LAST one silently,
          so the first value is discarded with no diagnostic.          EXIT=1

Mutation-verified: neutering the detection (needle count asserted == 1 before mutating) fails 2 tests and lets the real defective ledger pass again. Control green, 50 tests OK.

The class

#1059's duplicate-key defect in a different file. status_evidence_check.py already parses duplicate-key-strict — but only artifacts/release-*.yaml. The strict loader was never pointed at claims.yaml, the one file every other claim in the repo is checked against. Swept: claims.yaml had exactly 1 duplicate key (this one), artifacts/**/*.yaml and rivet.yaml have 0.

Changes

  • claims.yaml — the mapping is split; both reasons are attached to the values they justify. The record is the deliverable; the numbers were always right.
  • scripts/claim_check.py — both YAML load sites parse duplicate-key-strict, with a diagnostic naming the discarded value's line (the failure mode is silence, not error).
  • scripts/test_claim_check.py — the exact shipped shape refused; the fixed two-waiver split accepted (a gate that only ever fails is as useless as one that only ever passes); safe_load pinned as the counterfactual that keeps the wrong reason; and the repo's own ledger asserted clean — non-vacuity against the real artifact, not only fixtures.

Found while auditing v0.60's ratchet numbers for the release notes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

…aiver was recorded with a +10-line justification

`claims.yaml` on main carried TWO `reason:` keys inside one waiver mapping
of the `selector_lines_code` ratchet. YAML keeps the LAST value on a
duplicate key, silently — so the surviving justification for RQ-60-
VFPPRESSURE increment 1's **+622 line** growth of the instruction selector
was RQ-59-I64SHIFT's reason for **+10 lines**: a different lane, a
different release, a different change.

From the ledger's own history (`git log -L` on the `value:` line):

    16b135b  RQ-59-SUBTRACT          18278
    2785ffe  RQ-59-I64SHIFT          18288   +10   <- the surviving reason
    e6a3b27  RQ-60-VFPPRESSURE inc1  18910  +622   <- the actual growth
    0ec9dc7  RQ-60-VFPPRESSURE inc2  19199  +289

The lane did its job: its commit message and the discarded reason both
state the +622 honestly. The file edit turned `to: 18288` into `to: 18910`
and appended a second `reason:` instead of adding a second waiver entry,
and nothing in the toolchain could see it.

WHY EVERY GATE PASSED. `check_ratchet` asks (1) does a waiver exist with
`to == value` — yes; (2) is its reason non-empty — yes, it is a perfectly
good string. Neither question can distinguish the right reason from
someone else's. The waiver's stated purpose is "permission is per-growth,
never standing"; a duplicate key converts it into a standing permission
AND deletes the record of the growth it was granted for, leaving the gate
green.

THE CLASS. This is #1059's duplicate-key defect in a different file.
`status_evidence_check.py` already parses duplicate-key-strict — but only
`artifacts/release-*.yaml`. The strict loader was never pointed at
`claims.yaml`, the one file every other claim in the repo is checked
against. Swept: claims.yaml had exactly 1 duplicate key (this one),
`artifacts/**/*.yaml` and `rivet.yaml` have 0.

WHAT THIS CHANGES
  * claims.yaml: the mapping is split. RQ-60-VFPPRESSURE increment 1's
    reason is restored on `to: 18910`; RQ-59-I64SHIFT's gets its own
    `to: 18288` back. The record is the deliverable — the numbers were
    always right.
  * claim_check.py: both YAML load sites parse duplicate-key-strict, with
    a diagnostic naming the DISCARDED value's line, because the failure
    mode is silence rather than error.
  * test_claim_check.py: the exact shipped shape refused, the fixed
    two-waiver split accepted (a gate that only ever fails is as useless
    as one that only ever passes), safe_load pinned as the counterfactual
    that keeps the WRONG reason, and the repo's own ledger asserted clean
    — non-vacuity against the real artifact, not only fixtures.

RED-FIRST, against the real artifact rather than a fixture — the same
claims.yaml from main, under the shipped checker and under this one:

    shipped:  51/51 claims hold.                                  EXIT=0
    fixed:    duplicate key 'reason': declared at line 1311 and
              AGAIN at line 1330 — YAML keeps the LAST one
              silently ...                                        EXIT=1

MUTATION-VERIFIED: neutering the duplicate detection (needle count
asserted == 1 before mutating) fails 2 tests AND lets the real defective
ledger pass again; control green, 50 tests OK.

Refs #1087, refs #1059, refs #242.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

claims.yaml has a duplicate reason: key: a +622-line waiver is recorded with a +10-line justification, and claim_check passes

1 participant