DashboardThree-Axis ProbesCandidate Registry Robustness › Iter 05

2026-06-16-candidate-registry-robustness-sota · iteration 05 · 2026-06-16

Iteration 05 — Novelty gate wired into the ledger + fleet-safe writes (D2) DONE

Adding a candidate now AUTO-runs the novelty check and records the result, and the ledger can no longer be corrupted or lose appends when multiple sessions write at once — verified end-to-end without touching the real ledger.

✅ What has been grounded

The novelty gate is now wired INTO the registry tool. candidate_ledger.py --add automatically runs the novelty check first: covered → the add is refused (it's already in the catalog); needs_reviewblocked unless you pass --confirm-dup; unique → added, with a dedup record (status, mechanism, score, matched ids, content hash) stamped on the row. A standalone --novelty "NAME" command runs the gate on demand.
Writes are now fleet-safe (D2). Saving is atomic (write to a temp file → fsync → atomic rename → fsync the directory), so a crash can never leave a half-written ledger. And --add/--set-stage run inside an exclusive file lock and re-read the file fresh, so the parallel bigblack panes serialize and cannot clobber each other's appends — closing the failure class behind the old 29,908-duplicate incident.
Verified end-to-end on a throwaway copy (real ledger never touched). covered name → refused, row count unchanged · brand-new name → added (44→45) with dedup.status=unique · re-adding the same name in different case → refused (the gate sees the new row immediately) · --set-stage works · the file re-loads as valid JSONL. The live 44-row ledger stayed exactly 44 throughout.
Backward compatible. All 44 existing rows still pass --validate; every existing command behaves the same; the new dedup field is purely additive. candidate_ledger.py parses and runs on the env's Python 3.14 with no new dependencies.

➡️ What I am doing next

1
Add a migrate() pass to backfill dedup + content hash onto the existing 44 rows, so historical candidates carry the same provenance new ones get.
2
Implement P1: the lifecycle transition table + per-edge guards (e.g. → promoting requires all three axes PASS + leakage gates) and stable opaque spec-hash ids.
3
Implement P2: input-lock verdict pinning + hash-chained provenance history, then the /registry:doctor and /registry:check-full commands (Eon slash-command standard).
4
Optional: enable the semantic Tier-3 (offline embedding) to catch abbreviation synonyms like A-MF-DFA ≡ Asymmetric MF-DFA.

🎯 How this moves us toward the end goal

This delivers your explicit requirement — 'the system handles checking against existing entries whenever new candidates are added' — and makes it safe under the parallel-fleet workflow. The pool is now an active, self-checking registry: registering a candidate automatically proves novelty (catalogue-uniqueness) and records the evidence, and concurrent sessions can't corrupt the file or lose entries. That means the discovery loop can register and triage candidates at speed, in parallel, with no double-evaluation and no data loss — before any expensive orthogonality compute is spent.

What --add does now

--add --name "X" --family F ...
   └─ acquire exclusive lock  → re-read ledger fresh
   └─ novelty_check(X)
        covered      → REFUSE (already in catalog)
        needs_review → BLOCK unless --confirm-dup
        unique       → append row + stamp dedup{status,mechanism,score,matched_ids,spec_hash}
   └─ atomic write (temp → fsync → rename → fsync dir)  → release lock
test (on throwaway copy)result
add a covered namerefused, rows stayed 44
add a brand-new nameadded 44→45, dedup=unique
re-add same (different case)refused — gate sees the new row
set-stage on new rowok → pending
real ledger during testsuntouched (44 rows, still valid)