v0.32.0-beta — five corpora redrawn, and the collision is silent
Pre-releaseBreaking — five corpora changed bytes, and the collision is SILENT
temporal, bitemporal, conjunction, episodic and forgetting all moved corpus_sha256.
arithmetic, prospective and semantic did not — their sidecars changed; their corpora did not.
| vertical | corpus_sha256 |
hops |
|---|---|---|
temporal |
31d26e60fd21 → 9b83da0cd8ea |
2 |
conjunction |
c62ef4773597 → 9f6a0f37a506 |
3 |
bitemporal |
f5b384d7f0ff → abf2f3f43219 |
1 |
episodic |
2c6000a6912e → 542da3fa1767 |
1 |
forgetting |
ba759097b9bd → 7fe6e166dbf1 |
1 |
Read this before comparing any number to a 0.31.0-beta baseline. All five redrawn corpora keep
100% identical question_id sets with 0 byte-identical items, and corpus_id
(agenteval-typedmemeval-<vertical>-v5) and revision (v5) do not move either. corpus_sha256
is the only field that distinguishes the two corpora.
In bitemporal, 27 of 60 items keep the exact same question text with a different gold answer
(tme-bit-003: same question, gold Northolt Bay → Kelsford); only 4 kept both. A consumer keying
a cache, leaderboard row or regression baseline on question_id will silently mis-grade rather
than fail loudly. Compare on the sha, never on the corpus id, revision or question id.
temporal additionally lost its entire G=1 stratum — the 20 single-gold questions are gone,
redistributing to G=3 (5→11), G=4 (5→12), G=5 (5→12). Retrieval controls change in kind, not only in
value.
Added — two shapes that could not rank anything now can
-
temporal/occurrence-order: headroom 0.05 → 0.75, now the strongest shape in its vertical. It
asked about two adjacent chain events, so the single link between them stated the answer outright
while the question handed BM25 both rare names — a lexical lookup in the vertical whose premise is
that narration order must be followed. It now asks the two ends, so every link is necessary.
V9 19/20 → 5/20; gold 1 → 3–5 sessions; 0 of 20 questions have any single session naming both
asked events, against 20 of 20 before. V1 held at 20/20. -
bitemporal/belief-at-instant: headroom 0.11 → 0.31, and on pairs 0.167 → 0.556 against a
scaled floor of 0.254 it previously missed. Only two sessions per haystack named the asked subject;
same-subject, other-month distractors now compete (median 2 → 5, exactlyK_REF). -
conjunction/order-then-value: V9 15/15 → 7/15 — the second-largest per-shape V9 move in the
release. It was saturated under BM25 and could not discriminate retrievers at all. -
Paired-arm discrimination. Bitemporal's 30 pairs have different correct answers and disjoint
gold, so per-question scoring averages the capability away.pair_headroomships with
pair_floor_scaledandpair_separation_sd: a shape must clear both, because the floor assumes
independent arms and they measurably are not, while the standard-error separation assumes nothing
about correlation. -
A per-shape coverage band gate, which immediately found three shapes outside ADR-026's
[0.50, 0.90] that nothing had reported. -
--dry-runfor the probe runner — every case through the real code path against a stub: no API
calls, no credentials, nothing written. It found a real bug on its first execution. -
--recalibrateon all nine generators. Calibration is now an authoring step, not a build step:
a plain regeneration rebuilds at the echo the sidecar records and reproduces byte for byte.
Previously a corpus was a function of (generator, seed, search algorithm), so changing the search
silently desynchronised every committed corpus from the generator that produces it.
Fixed — previously published numbers that were wrong
Per-shape realised coverage never described the shipped corpus. calibrate_per_shape recorded
each shape's value mid-search, while later shapes' knobs were still 0, then rebuilt with all knobs
set.
| shape | published | actual |
|---|---|---|
arithmetic/delta |
0.7767 | 0.7350 |
arithmetic/duration |
0.6528 | 0.6250 |
conjunction/alias-then-count |
0.3444 | 0.3356 |
semantic/co-reference |
0.6889 | 0.7222 |
prospective/not-yet-true |
0.6667 | 1.0000 — saturated |
prospective/due-later-reminder |
0.75 | 0.50 |
prospective/due-window |
0.2222 | 0.4352 |
prospective/expiring-validity |
0.8333 | 0.6667 |
semantic's echo never moved, so this was long-standing and independent of the calibration work.
The guide asserted something false. It read "V1 − V9 is the headroom a better retriever can
capture." It is not — a real retriever returns gold plus what else it ranks highly, so its ceiling
is V8, not V1. headroom_reachable had been in the sidecar since 0.31 and the word "reachable"
appeared zero times in the docs. prospective/due-window publishes 0.94 of which 0.17 is
reachable.
The calibration search was fixed twice. Bisection assumed a monotone most shapes violate; the
sweep that replaced it was itself a regression on cliff-shaped curves, returning coverage 0.000
on arithmetic/delta where bisection returned 0.735. A sweep locates and bisection resolves;
both are needed. See ADR-028 §12.
Three sidecars had lost fields they carried at 0.31.0-beta — structure.retrieval_ceiling and
structure.scaffolding_dependence on bitemporal, episodic and forgetting. Regenerating those
corpora dropped them correctly (the values described the old bytes) and nothing re-ran the stampers.
Restored, with no sha change.
Known defects shipping in this release
-
prospective/due-window's answer key is wrong. Class parity requires filler to use gold's own
construction, and this shape asks a set-membership question whose membership criterion is that
construction — so filler reminders falling inside the window satisfy the question and are not
gold. The reference model is marked wrong for being right. A fix is written and measured
(V8 4/18 → 13/18, reachable headroom 0.17 → 0.44) but is not in this release; it cannot land
while the separability tell below is unfixed. Read its published 0.94 / 0.17 as mis-keyed, not
hard. -
prospective/not-yet-trueis saturated at coverage 1.0 — BM25 returns gold for every question.
Its headroom of 0.1667 is one question out of six. -
A measured, unfixed separability tell. Gold's first assistant turn is longer than every
distractor's in 8–10 of 50prospectivequestions against 4.1 expected by chance, and 6 of 50 in
episodic. Diagnosed intools/diagnose_padding_asymmetry.py: gold's first assistant turn starts
45 and 36 characters shorter than filler's in those two verticals, so it takes the most
whole-sentence padding steps and the last one overshoots.semantic,temporalandbitemporal
have comparable base texts and show no tell. -
61 of 75 measured real-world name collisions remain unremediated, declared in
tools/name-collision-audit.json. The guard scans onlytemporalandconjunction, and only for
the 14 remediated names. -
forgetting/never-knownis checked by nothing. Its 15 questions have no gold, so every validity
arm reports 0/0 and both discrimination assertions silentlycontinue.
Changed — defaults and CI a fork inherits
TypedMemEvalOptions.JudgeMaxOutputTokens512 → 1500, the value the shipped judge calibration
was measured at.ExternalBenchmarkOptions.JudgeMaxOutputTokensis unchanged at 256, so LongMemEval
judge budgets are untouched.llm-integration-tests.ymldefault deploymentgpt-4o-mini→gpt-5.5.- A release-blocking gate in
release.yml, betweendotnet packanddotnet nuget push, verifies
every embedded corpus against the working tree — 9 corpora × 3 frameworks. A release can now fail
after packing; that is this gate, not a packaging outage. corpus-reproducibility.ymlregenerates all nine corpora and compares bytes, triggered by changes
totools/gen_*,typedmemeval_common.pyor the corpora.- New test classes:
TypedMemEvalPackagedCorpusTests,TypedMemEvalNameCollisionTests,
TypedMemEvalCoverageBandTests,TypedMemEvalDiscriminationTests,TypedMemEvalJudgeBudgetTests.
Several read from disk, so the suite is no longer runnable outside a full repo checkout.
Sidecar schema
- Added:
coverage.echo_by_shape,coverage.per_shape_realised, and per shape
headroom_perfect_selector,headroom_reachable,limited_by,discriminates, pluspair_*
fields where a shape has arms. - Removed, and the absence is the disclosure:
probes.empty_completion_disclosure,
probes.empty_rate_scopeandprobes.no_answer_capturedare conditionally emitted. With zero empty
completions on the current corpora there is nothing to disclose. Read their absence as "none",
not as "not measured".
Added
-
Every shape now publishes what KIND of hard it is, and a gate on whether it can rank anything.
Implements ADR-028 §3a and §3e.V1 − V9is what a perfect selector buys — a retriever returning gold and nothing else. A real
retriever returns gold plus whatever else it ranks highly, so it cannot beat having everything:
its ceiling is V8, not V1. Where those diverge the published headroom is unreachable, and a
consumer reading it buys retrieval work that cannot help.shape headroom (perfect) reachable limited by prospective/due-window0.94 0.17 reasoning semantic/co-reference0.40 0.27 retrieval arithmetic/delta0.90 0.90 retrieval due-windowis the case that motivated it: 0.94 published, 0.17 actually reachable. Both figures
and the classification now ship in every sidecar.The gate asserts each shape clears a 0.15 discrimination floor. It is a ratchet, not a
wall — a gate that stays red for the life of a known-weak shape stops being read, and a regression
introduced while fixing something else then lands invisibly. Two lists, both with reasons:
saturated by design (WorkingMemory's three short ladder rungs, where the gradient is the
measurement and deleting the saturation deletes the construct) and pending redesign. Listed
shapes may improve and may not regress; anything unlisted must clear the floor outright.The pending-redesign list shipped empty. It held
temporal/occurrence-orderat 0.05 and
bitemporal/belief-at-instantat 0.11 when the gate was written; both were fixed later in this
same release, to 0.75 and 0.31, and removed. Their reasons are kept in the now-empty dictionary
rather than deleted with the entries — a list that only ever grows is a list nobody reads.Red-first verified: raising the floor to 0.25 turns three verticals red; restored, 1073/1073 green.
No corpus regenerates and no consumer control moves — the raw arm counts were already recorded,
so this is reporting and acceptance only.The 0.15 floor is a judgement, not a measurement. Nothing in the data derives it; it sits where
the distribution has a natural gap (three at 0.00, two between 0.05 and 0.11, twenty-five at 0.17+)
and should be revisited once a second reference retriever exists, because the whole scale is
BM25-relative.
Fixed
-
value-then-countasked how many times the speaker ORDERED while its sessions recorded sending
paperwork, booking collections and raising jobs. The question hard-coded "put an order in with"
for every draw whileCOUNTABLEsupplies four different actions, so 19 of 20 questions asked
about an event that never happened. V1 sat at 19/20 only because the model treated the recorded
events as orders anyway — leniency, not soundness — and part of the shape's apparent difficulty
was that incoherence rather than the join it exists to test.A disabled attempt at this fix stood in the file as
if False, deriving the verb by
predicate.split("the speaker ")[1].split(" with")[0]— which silently returns the whole phrase
for "sent paperwork to {entity}", because there is no" with"to split on. The verb is now
a third, explicit element ofCOUNTABLE: three parallel forms are longer and cannot go quietly
wrong. -
And the question asked for less than its gold required. Gold is
"{n} times, with {entity}"
and names the entity deliberately — without it a judge cannot tell a correct count attached to a
superseded value from a correct answer. But the question asked only for a count, so "4
times" was fully responsive and scored wrong (tme-cnj-006failed V1 on exactly that), and for
the nineteen that passed, naming the entity was verbosity rather than evidence the semantic half
had been performed. A conjunction shape has to ask for both halves or it cannot observe that the
join happened. It now asks for both.before after V1 49/50 50/50 — tme-cnj-006resolvedvalue-then-countV92/20 6/20 value-then-countheadroom0.85 0.70 vertical headroom 0.76 0.72 The headroom drop is the honest part. Some of the old difficulty was the question asking about
an event the corpus never recorded; a shape is not hard because it is incoherent. 0.70 is what the
join is worth once the question is answerable as written.Corpus sha
99f609c9…→9f6a0f37…; Conjunction controls reset — its third move this arc, all
inside the pre-tag window. -
Episodic ran one echo knob across three shapes whose coverage spanned 0.66, and the vertical
mean reported none of it. Single-knob calibration put the mean at a healthy 0.682 while the
shapes sat atparticipant-attribution0.933,assistant-stated0.800,list-order
0.275. Attribution was effectively saturated — V9 14/15, headroom 0.07, no two retrievers
distinguishable — and list-order was far below band. This is the mean-satisfiable-by-averaging
defect the family already fixed for Arithmetic; Episodic simply never received it.Opted into per-shape calibration, which four verticals already use. Spread 0.66 → 0.033:
shape coverage headroom participant-attribution0.933 → 0.667 0.07 → 0.20 assistant-stated0.800 → 0.700 0.20 → 0.30 list-order0.275 → 0.692 1.00 → 0.73 list-ordertraded extreme headroom for being in band — it was out of spec at 0.275 and is still
the widest shape in the vertical. Attribution's residual limit is structural: it is a k=2
question ("was that me or you?"), so a retriever that finds the gold session gets it right and
guessing covers half the rest. 0.20 is what calibration can buy.Corpus sha
2c6000a6…→542da3fa…; Episodic controls reset. -
The saturation screen reported the chance floor as if it were evidence of saturation. Added
yesterday comparing V9 pass rate against BM25 coverage, it flagged the recalibrated
participant-attributionat +0.133. That was the screen, not the shape: on a closed-choice
question a model with gold missing still picks from the named candidates and lands at1/k, so
the score to beat iscoverage + (1 − coverage) / k, not coverage.Against its actual floor of 0.833, attribution reads −0.033 — slightly below what evidence
plus guessing explains. The screen now computeskfrom the question text. Nothing in the family
exceeds its floor; the largest positive is +0.083 on a declared ladder rung.The same arithmetic has now corrected V2's reading, V3's threshold, and this screen. A floor
derived once does not transfer — each instrument needs it computed against its own budget and
its own baseline. -
The judge's default completion budget could silently void it on the deployments its own claim
was measured on, and CI was certifying a different judge. Two coupled defects, fixed together
because fixing either alone makes things worse.The budget.
TypedMemEvalOptions.JudgeMaxOutputTokensdefaulted to 512. That is ample for
a non-reasoning model and dangerous on a reasoning one, where the budget covers reasoning tokens
too: the model can spend the whole allowance thinking and return an empty completion. This
family has already paid for that once — empty completions scored as answers until the silence
accounting was built — and any consumer pointing the judge at agpt-5.xdeployment on defaults
would have hit it silently.Now 1500, which is not a guess: it is the value the calibration test floors at, and therefore
the configuration the published agreement number (0.987 over 230 cases) was actually measured
under. A default that differs from the configuration the claim came from means the out-of-box
judge is not the judge the claim describes.The deployment. The integration workflow defaulted to
gpt-4o-miniwhile the judge's validity
claim is measured ongpt-5.5. A gate exercising a different model certifies nothing about that
claim — its green is decoration, and a regression on the calibrated deployment would not turn it
red. The default is now the calibrated deployment; the cheaper models stay selectable for manual
runs where the question is "does the plumbing work" rather than "is the judge still valid".
If cost ever bites, run the calibrated judge less often rather than a different judge more
often.Behaviour-affecting, and recorded as such. Raising a cap can flip a formerly-truncated
verdict, so the effective value is now stamped per run in
BenchmarkRunProvenance.JudgeMaxOutputTokens. Two runs differing only in this number are not
comparable, and that has to be visible rather than inferred.Pinned by tests rather than left to a comment — and the first draft of that test failed,
correctly:ExternalBenchmarkOptionscarries the same setting at a default of 256 and serves
LongMemEval, whose own calibration was measured there. The guarantee is not "the base default is
1500" but that the TypedMemEval facade overrides it on the way through. A value corrected in
one of two places is the applied-once shape, caught here by its own guard. -
conjunction/order-then-valuecould not rank any two retrievers, and now it can. It measured
V9 15/15, headroom 0.00 — a perfect retriever and a plain BM25 retriever scored identically —
while its BM25 coverage was only 0.667. Those two numbers together are the diagnosis: the
retriever was fetching two thirds of gold and the model still scored perfectly, so the missing
third could not have mattered.One gold session read
"{anchor} happened while {middle} was the {attribute}."— naming the
anchor and the answer in a single sentence. It was also the only session carrying both terms the
question names, so it was simultaneously the easiest to retrieve and sufficient on its own. The
join the shape exists to test was never required.The anchor is now pinned to the switch events rather than to the value, so answering takes two
hops in different sessions: place the anchor between the two switches, then read which value that
switch moved to. Asserted at build time — no gold session contains both the anchor and the answer.shape V9 before after headroom order-then-value15/15 8/15 0.00 → 0.47 alias-then-count1/15 1/15 0.93 value-then-count2/20 2/20 0.90 → 0.85 Vertical headroom 0.64 → 0.76. Corpus sha
b756721c…→99f609c9…; Conjunction controls
reset. Folded in before the tag at the consuming project's request — their recall-fan-out router
reads this vertical by shape, and a dead cell in that instrument would have cost them two control
resets instead of one.The separability gate refused the first two builds, and both refusals were the same mistake:
filler must carry every construction gold uses. The new anchor frame was gold-only on the first
build; the"That was the week of X"clause dating each switch was gold-only on the second — 30
gold sessions, zero distractors. The rule was already written in this file for the previous
anchor frame, and I applied it to one of the two new constructions and not the other.
Known
-
value-then-countasks for less than its gold requires. The question is "How many times did
I put an order in with my {attribute}?" and gold is"{n} times, with {entity}."— so a model
answering "4 times" is responsive to the question as written and scores as wrong. One question
(tme-cnj-006) fails V1 on exactly this. The wider implication is the reason it is recorded
rather than patched: for the other nineteen, naming the entity may be verbosity rather than
evidence the join was performed. Scoped as its own change under the agreed one-shape-at-a-time
sequencing, not folded into a fix for a different shape. -
Forgetting's coverage was 30% a constant, and the echo search had been optimising it.
realised_coverageanswers1.0when a question has no gold — vacuously, all of nothing was
found. That is the right answer and the wrong thing to average. Forgetting's 15never-known
probes are G=0 by design, so the publishedmean_realisedof 0.670 was three-tenths a
constant; measured over the questions that have gold it was 0.529, against a band floor of
0.50. The vertical sat a third of the way to the floor from where it read.The correct treatment already existed in this codebase, in one place.
calibrate_per_shape's per-shape search drops these questions with the reasoning written out
beside it — "no coverage to realise … excluded rather than allowed to pin a shape at saturation
it cannot leave". It was never carried to the vertical mean in either path, and Forgetting has no
per-shape calibration, so it fell exactly in the gap between them. A correct treatment written
once and applied once is how a defect survives review: the reviewer sees the reasoning and assumes
its reach.before after mean_realised0.670 (30% constant; true 0.529) 0.629 (measured over 35 gold-bearing questions) echo 0.500 0.250 V1 32/35 34/35 V8 interference −0.0571 +0.0857 headroom 0.2857 0.3714 A negative interference cost meant the full haystack outscored gold-only, which is incoherent;
it is now positive. Which of the three changes fixed it — the echo, the new filler bank, or the
redraw — was not isolated, and isolating it would cost a regeneration that destroys the probe
record, so it is reported as resolved rather than explained.Corpus sha
ba759097…→7fe6e166…; Forgetting controls reset. No other corpus touched. -
CHOICESwas a gold-only construction, and the separability gate caught it mid-recalibration.
Regenerating Forgetting under the corrected mean changed the draw, and the gate refused to write:
"went with"appeared in 12 gold sessions and zero distractors. Every phrasing in the bank
was gold-only for the corpus's whole shipped life — it had stayed under the 20% bar by luck, not
by design.Filler now draws from the same bank, at a share sized below the re-affirmation one so the
invalidation-shaped filler V3 needs is not crowded out. Filler states a parity value, never a
gold one, so the invariant the statement session rests on is untouched: the gold value still lives
in the gold session and nowhere else.The rule was already written in this same file, one bank above: "Re-affirmation frames, drawn
from ONE bank for gold and filler alike."CHOICESsimply never received the treatment its
neighbour did — the third instance today of a correct treatment applied once and not propagated. -
V2 now ships the caveat that makes its own number readable — and the threshold was deliberately
NOT "fixed". The arm asks each question with no haystack and rejects at 2 hits in 10. On an
open question chance is ~0, so any hit is signal and the arm does exactly what it claims. On a
closed-choice question the model can pick from the candidates the question itself names, so it
reaches gold at1/kwithout evidence — and the reject line of 0.20 sits below that floor
(0.50 at k=2, 0.33 at k=3). 71 questions are in that position: temporal 35, prospective 21,
episodic 15.Measured across 7,540 cached V2 answers, 97.9% are explicit declines — "I have no way of
knowing" — under a prompt that ends "If you have no way of knowing, say so plainly." So a pass
records that the model did not volunteer an answer, which is real and useful, and is not the
guessability question.The obvious repair was tested and rejected on evidence. Raising the bar to the statistically
correct value — 9-of-10 at k=2, 7-of-10 at k=3 — keepstme-tem-013(10/10) and misses
tme-tem-046(5/10), a question we know was leaking: the model was reasoning from real-world
knowledge about Yarrow Shipbuilders and landing right about half the time. Its 5 hits are
statistically indistinguishable from guessing (p=0.213) and were not guessing. Calibrating the
bar would trade a real detection for a tidier statistic — the naive threshold is more
sensitive precisely because the model declines, so against a decliner any hit means it
volunteered.So the number stays and the claim narrows. Every sidecar now carries a
closed_choiceblock
with the per-question candidate count and how many passes are not evidence of
non-inferability. Compare with V3, where the identical arithmetic produced the opposite
disposition: there the budget was 3 samples, no threshold could clear the floor, and not
decidable was the honest verdict. Same rule, different budgets, different answers — which is why
it had to be derived per arm rather than applied as a policy.No corpus sha moves, no verdict changes, zero model calls — the hit counts were already
recorded, because V2 never short-circuited. -
V3's leak threshold is now read against the chance floor, and 24 of its passes were never
earned. The arm draws 3 ablation samples and condemned a question on a single hit. On a
closed-choice question that is not a measurement: the question hands the model its candidates, so
with every gold session removed it still reaches gold at1/k. Against a pure guesser the
false-failure rate is1 − (1 − 1/k)³— 0.875 at k=2, 0.704 at k=3.The threshold is now the smallest
hwhose tailP(X ≥ h | 1/k)falls under 0.05, and a question
is not decidable when nohwithin the sample budget reaches it. At 3 samples that gives
k=2 → undecidable(even 3-of-3 leaves p=0.125),k=3 → 3-of-3, open → 1 hit as before. The loop
no longer short-circuits on the first hit, because with a threshold above one the count is the
evidence and a question that stopped at sample 0 can never be compared against a 3-of-3 bar.This retires a hand-curated list.
_V3_GUESSABLE_SHAPESnamedoccurrence-order, and this
session addedrecencyafter four of its questions "failed" a clean regeneration. Both are
consequences of the arithmetic above rather than facts about those shapes — and the list had
silently missed Episodic'sparticipant-attribution("Was that me or you?", k=2) for its entire
shipped life. A curated exemption list is a chance-floor bug that somebody patched once.vertical V3 before after what moved prospective 44/44 29/29 15 unearned passes removed episodic 44/50 35/35 9 unearned passes and 6 false failures removed temporal 15/15 30/30 recencyrestored to measurement — and all 15 pass at 3-of-3Temporal is the evidence the rule is right: measured against a threshold it can actually fail,
everyrecencyquestion passes. They never leaked; the single-hit rule was condemning coin flips.24 unearned passes removed, 6 false failures corrected, and no corpus sha moves — this is a
probe-record change only, so no consumer control resets. No other arm changed: V1, V2, V6, V8 and
V9 are identical across all nine verticals. The full family was re-probed under the new rule for
16 new calls, everything else served from cache.Silence handling followed the threshold rather than staying at one: a silent draw now disqualifies
only where hits-seen plus silent-draws could have reached the bar, which is the rule V2 already
used. Records carryv3_hits,v3_required_hitsandv3_candidatesso the verdict can be
re-derived instead of trusted. -
The corpora were built from real place-names, and a model was answering from world knowledge.
V2 asked "Which came first, the Fenn commissioning or the Yarrow move?" with no haystack at
all and the reference model replied "Yarrow moved its shipbuilding operations to Scotstoun,
Glasgow in the early 1900s, while the Fenn commissioning was during World War II." Real facts
about Yarrow Shipbuilders. The generator's comment said this could not happen — "Invented
milestone names. Arbitrary by construction (V2): nothing about a name makes it likelier to be
first" — and had never been measured.A sweep of every entity bank in the family (
tools/audit_name_collisions.py, 163 names, 0
unparsed) found 75 are real-world referents: Harrow and Kessel are places, Bellamy and Vance
and Ruskin are people, Calder is a river, Esker is a company.V2 sees only half of this defect. It scores a leak only when the leak agrees with gold. Five
temporal questions show world-knowledge reasoning; V2 flagged two.tme-tem-013hit 10/10
purely because the corpus happened to order those events the way history did — ordered the other
way, the model would have been confidently wrong ten times out of ten and the question would have
passed. The arm that caught this cannot certify its repair, which is why the guard is a
deterministic test rather than another probe.Fixed where the harm is, declared where it is not. A real referent is only exploitable when
its real-world facts answer the question asked: "Meridian Tools" being a real brand does not tell
a model which vendor the user chose, but "Yarrow" moving in 1906 does tell it which milestone
came first. So the three ordering banks were remediated —temporal:MILESTONES(9 of 12
colliding),temporal:FILLER_MILESTONES(5 of 6),conjunction:MILESTONES(4 of 6) — and the
other 61 collisions are declared, not rewritten, intools/name-collision-audit.jsonwith the
reasoning. Rewriting them would move all nine corpus shas and reset every control the consuming
project holds, for no measured leak.Replacement names were verified by the instrument that condemned the originals, not chosen by
taste. Re-probed under the V2 condition, the new names produce bare declines ("I have no way of
knowing.") with no world-knowledge reasoning.before after temporal V2 48/50 50/50 — both leaks gone temporal V9 / headroom 30/50 / 0.40 33/50 / 0.34 conjunction V1 49/50 50/50 conjunction V9 / headroom 18/50 / 0.62 18/50 / 0.64 Corpus shas move: temporal
31d26e60…→124458d0…, conjunctionc62ef477…→b756721c….
Both verticals' controls reset. No other corpus is touched. -
V3 was false-failing
recencyseven times in ten. A clean regeneration took temporal's V3 from
30/30 to 26/30 and every one of the four "failures" was arecencyquestion. Nothing had leaked.
V3 draws 3 ablation samples and condemns a question on a single hit, so against a model
guessing among the k candidates the question itself names, the false-failure rate is
1 − (1 − 1/k)³:shape k false-failure rate strictest threshold occurrence-order2 0.875 3-of-3 still leaves p=0.125 — undecidable recency3 0.704 3-of-3 would give p=0.037 occurrence-orderwas already exempt for exactly this reason;recencyhands the model three
candidates and had never been added. It is now, and the arithmetic is written down beside the set
instead of left as a curated list. The previous run's 30/30 was luck, not evidence — the model
usually declines rather than guessing, so the arm's verdict on these shapes swings on whether it
happened to guess.The proper fix is a chance-aware threshold that derives the exempt set rather than curating it,
and would keeprecencymeasured at 3-of-3 instead of dropping it. That changes V3 semantics for
every closed-choice shape in the family, so it is queued as its own change rather than
smuggled in beside a name fix.
Added
tools/audit_name_collisions.py— asks the reference model whether it can state a concrete
fact about each name in every entity bank, and refuses to count an unparseable reply as
"invented". Its measured result is committed totools/name-collision-audit.jsonso the finding
and the harm assessment travel with the repository rather than living in a chat log.TypedMemEvalNameCollisionTests— a deterministic guard, red-first verified against the old
corpus, asserting that no remediated name reaches a question or answer in the two verticals whose
questions turn on order. It also asserts the audit record still covers all three ordering banks,
so a shrunken record cannot make the guard vacuous.