What went right first¶
The 2026-09-29 corrections were applied correctly. Every value from the brief landed:
leg prices 0.96 / 1.14 / 0.50 / 0.61, record ref_price 0.18 and 0.11, exit fees
0.26 with the direction stated right, realised +4.48. Append-only was respected — the
original records are intact on disk with their wrong values. The position_id was not
renamed and the misnomer is stated. Flags preserved plus owner-correction. That is the
hard part done right.
Two follow-ups.
Follow-up 1 — a fabricated figure in the new open-correction note¶
The note for spy-675-685p-debit-260925:open:2026-08-25 reads:
"took 0.18 credit per share (~9.82/share = $982 max risk on a $380 credit)"
$380 is wrong and has no arithmetic route. The credit is $18.00 gross
(0.18 × 100) or $15.74 net (112.86 − 97.12). The $982 max risk beside it is
correct. The same note states +15.74 correctly elsewhere, so the record contradicts itself.
Append a third correct record against
spy-675-685p-debit-260925:correct:2026-08-25 — the correction record itself is the thing
being corrected this time — restating the risk line as:
10 wide, 0.18 credit per share → $982 max risk against a $15.74 net credit (
$18.00gross before$2.26of commissions and fees).
Nothing else about that record changes.
Follow-up 2 — backfill corrects, which the validator then enforces¶
corrects is null on 10 of 14 correct records, target stated only in prose. This
predates today: only 4 records ever populated it. It means nothing machine-reading the
ledger can join a correction to what it fixes.
validate_ledger.py is now in hermes-pilot/ (13 tests). Run it; it currently reports
20 violations on the live ledger:
| count | check |
|---|---|
| 10 | correct record with corrects: null |
| 8 | leg with no qty field at all (lines 3, 4, 6, 7 — pre-existing, not from today) |
| 2 | ref_price disagrees with the per-lot signed leg sum (the two superseded originals) |
The three are linked by design. A record whose key appears in some correction's
corrects field is treated as history and exempted from value checks. So backfilling the
10 is what makes the 2 transposition violations go green — they are superseded, and once
the link exists the validator can see that. Fixing the bookkeeping is what clears the
values, rather than the two being separate chores.
The 10, with their targets¶
Five already name the target in their own note, so these are mechanical:
| line | position_id | set corrects to |
|---|---|---|
| 26 | tsla-365-straddle-261016 |
tsla-365-straddle-261016:open:null |
| 27 | eix-55-straddle-261016 |
eix-55-straddle-261016:open:null |
| 28 | pcg-14-straddle-261016 |
pcg-14-straddle-261016:open:null |
| 29 | nvda-220-straddle-261002 |
nvda-220-straddle-261002:open:null |
| 30 | spy-740-765p-debit-261016 |
spy-740-765p-debit-261016:open:2026-09-16 — corrected 2026-09-29, this brief first said :open:null. That open record has a real event_date, unlike the four straddles, and an existing correction already uses this key. |
| 31 | spy-675-685p-debit-260925 |
spy-675-685p-debit-260925:open:2026-08-25 |
| 32 | spy-675-685p-debit-260925 |
spy-675-685p-debit-260925:exit:2026-09-02 |
Confirm each key exists before writing it — the validator rejects a corrects that
resolves to nothing, which is the point.
Two need your judgement, because their notes describe a disposition conflict rather
than naming a target: line 4 (nvda-2275-straddle-260918:correct:2026-09-14) and line 7
(tlt-82-straddle-260918:correct:2026-09-14). You wrote them; pick the record each
actually supersedes.
Line 25 — resolved by owner decision 2026-09-29: split it. Two corrections to what
this brief first said. It covers five positions, not four — the note reads "the four
pilot-book straddles (TSLA 365, EIX 55x2, PCG 14x2, NVDA Oct-2 220) and the SPY 740/765P
debit". And the split already exists: lines 26–30 are precisely those five
per-position correct records, each flagged owner-determination + paper-virtual, each
note reading CORRECTS <pid>:open. Nothing needs splitting.
So the only outstanding action on line 25 is to retire it, since under append-only it
cannot gain a corrects value and a single string cannot name five targets:
Append one
correctrecord withcorrects: "ALL:correct:2026-09-29", whose note states that the determination is carried per-position by lines 26–30 and lists their five keys.
That makes line 25 superseded, and validate_ledger.py then exempts it — including from
CHECK 1. That exemption was added 2026-09-29 to fix a flaw in the validator itself:
CHECK 1 originally ran before the superseded test, which made records like line 25
permanently unfixable, since append-only means they can never gain the field. Two tests
cover it (SupersededCorrectRecordsCanBeRetired).
Their value fields being null is correct and needs no change: the five target open
records already carry price_kind: paper-mid, so these are semantic corrections to how the
entry-fill-not-recorded flag reads, not value changes. Verified.
Also worth fixing while you are in there¶
Eight legs across lines 3, 4, 6, 7 have no qty field. A leg without a quantity is an
incomplete position record. Pre-existing and lower severity than the above, but the
validator will keep reporting it until it is addressed — either by correction records or by
a deliberate decision that those early records stay as-is.
The point of the validator¶
It encodes the three classes this ledger has actually produced, not a generic schema check. Check 2 refuses a fractional leg quantity outright — the class that has now appeared three times and been rationalised every time. Check 3 was validated against the whole live ledger before being written: it holds for every correct record and flags exactly the two transposed ones, which means it would have caught the QTY/PRICE swap on the day it was made.
Run it after every ledger write. exit 0 clean, exit 1 with the violations listed.