โ€บNavigation
Dashboard โ€บ Three-Axis Probes โ€บ Candidate Registry Robustness โ€บ Iter 08

2026-06-16-candidate-registry-robustness-sota ยท iteration 08 ยท 2026-06-16

Iteration 08 โ€” Tamper-evident, hash-chained history (P2/D6) DONE

Every change to a candidate is now a hash-chained event โ€” editing any past entry out-of-band breaks the chain and the registry detects it. Backfilled onto all 44 rows and verified.

โœ… What has been grounded

History is now tamper-evident. Each history event carries a fingerprint (entry_hash) computed from the previous event's fingerprint โ€” like Git history or a mini-blockchain (Certificate-Transparency style). A row also stores its head_hash (the tip). Quietly editing a past note, stage, or date no longer matches the recomputed chain.
Tampering is provably detected. On a throwaway copy: changing a single past note made --verify-chain report history chain broken at seq 0 (exit 1). A normal stage change extends the chain cleanly and stays intact. --verify-chain is wired into --validate and /registry:doctor, and is its own /registry:verify-chain command.
Backfilled onto all 44 rows. --migrate now chains every row (44/44), idempotently. On the real ledger: validate PASS, tamper-evidence intact, all ids/stages/history preserved โ€” purely additive (each event gains seq + prev_hash + entry_hash; each row gains head_hash).
Caught and fixed a real bug mid-iteration (honest visibility). The first cut silently did nothing because hashlib wasn't imported in the ledger tool โ€” the throwaway test exposed it (0/44 chained). Fixed the import, re-ran: 44/44 chained, tampering detected. This is exactly why every change is tested on a copy before the real ledger is touched.

โžก๏ธ What I am doing next

1
Implement P2/D5 fully: pin each axis verdict to an input_lock (data snapshot + code SHA + params hash + harness version) + a subject_digest, so a verdict can't be reused on a different data window; tighten โ†’ promoting to also require a complete lock.
2
Implement D4: stable opaque spec-hash ids (id minted from the content hash; num demoted to a display ordinal).
3
Add stdlib structural validation (jsonschema is absent in the env) for unknown/typo'd fields.
4
Optional: enable the semantic Tier-3 (offline embedding) for abbreviation synonyms.

๐ŸŽฏ How this moves us toward the end goal

The audit trail is now trustworthy: nobody can quietly rewrite a candidate's history without it being detected. Together with the novelty gate, fleet-safe writes, lifecycle guards, and the promotion gate, the registry is now a robust, self-checking, tamper-evident system for stage-by-stage tracking โ€” which is exactly the 'high-quality candidate tracking' the campaign set out to build. (Honest limit: the chain detects out-of-band edits; a fully adversarial actor who also recomputes the chain would need to defeat a signed head โ€” that signed-head step is future hardening.)

How the chain works

event[0]  prev_hash = 000โ€ฆ0 (genesis)   entry_hash = H(0x01 โ€– prev โ€– H(0x00 โ€– content))
event[1]  prev_hash = event[0].entry_hash    entry_hash = H(โ€ฆ โ€– prev โ€– โ€ฆ)
event[2]  prev_hash = event[1].entry_hash    โ€ฆ
row.head_hash = last entry_hash   โ† edit any past content โ‡’ recomputed hashes diverge โ‡’ DETECTED
Check it: python3 findings/evolution/shared_data/candidate_ledger.py --verify-chain ยท or /registry:verify-chain ยท also folded into /registry:doctor and /registry:validate.