ID |
|
|---|---|
Status |
Backlog |
Bucket |
architecture |
Priority |
5 |
Theme |
classification-model |
Created |
2026-08-17 |
Updated |
2026-08-17 |
Pre-index reads of ErrorIndex.EMPTY return a plausible wrong answer
BuildContext.errors is initialised to ErrorIndex.EMPTY, and its siblings (nodes,
tables, scalarVerdicts) follow the same pattern: before TypeBuilder.buildClassificationIndices()
runs, a reader gets a populated-looking index that answers every membership question with
"no". The empty value conflates two different facts, "this schema declares no @error
types" and "the index has not been built yet", and a pre-index reader cannot tell them
apart, so it computes a plausible wrong answer instead of refusing. This has now bitten
twice through BuildContext.detectErrorsFieldShape: the routine-carrier grounding
(fixed by moving groundRoutineCarriers() after the index build) and the DML-carrier
grounding (R687, which applies the same fix); in both cases the write target
silently failed to ground and the payload surfaced a misleading classify-time rejection.
The only enforcement today is prose comments on the call sites in
TypeBuilder.prepareForWalk, which is review-only and did not propagate the last time.
The fix shape to evaluate at Spec: give the not-yet-built state its own arm (a sealed
NotBuilt / Built(map) on the index types, or hand the built index to passes as a
parameter instead of letting them read it off the context), so a pre-index read is a typed
refusal or a compile failure rather than a silent empty. The fact-model principle applies
directly: an empty relation is a fact about the population, and "nothing captured yet" is a
different fact that deserves its own representation.