What
ifc-reference-reader.read-model publishes parse / tessellate / batch / complete on the progress channel (#405). None of them carries the filter receipt (selected), which appears only in the complete node output.
Why it matters
A consumer that draws segments as they arrive cannot, while drawing, tell these two runs apart:
- a bridge that honoured
storeys: [L2] and is streaming one floor, and
- a pre-1.2.0 bridge that ignored the filter entirely, exits zero, and is streaming the whole building.
read-model.md is explicit that this is the failure the receipt exists to catch, and that absence-means-cannot-answer applies to the input as well as the output. So a progressive consumer has no honest option but to refuse to draw filtered reads at all.
No count cap substitutes for it. floless's own pre-read estimate documents itself as not an upper bound (a type filter resolves with includeInherited: true while the probe's rows are exact leaf names), and the harm is correctness rather than size anyway — a legitimately large floor and a silently unfiltered building are the same number of objects. Inferring capability from capability ("segments arrived, so the bridge must be new enough to filter") reasons across two independently installed binaries, which is the move frame, selected, colorsAvailable and budget all exist to make unnecessary.
Repro (measured 2026-08-12, CLI 0.121.0, agent 1.4.0, bridge current)
2023-05-09 30 Daldy Street Model.ifc, 65.8 MB, 17,460 objects, batch-size: 100:
- 237
node-progress records — 1 parse, 1 tessellate, 235 batch. Every batch record carries seq, done and an artifact descriptor.
- No record carries
selected, at any phase, including complete (which repeats the whole artifact's descriptor only).
- The same run filtered to one storey behaves identically on the channel: nothing distinguishes it.
Suggested shape
Carry the receipt on the tessellate record — it is published once, after the filter has resolved to expressIDs and before the first segment, which is exactly the point at which a consumer must decide whether it may draw:
{ "kind": "node-progress", "node": "read",
"data": { "phase": "tessellate",
"selected": { "storeys": ["L2"], "candidates": 3767, "unmatched": [] } } }
A consumer then draws only when the receipt confirms the axes it asked for, and falls back to today's wait-for-complete otherwise. Absent selected on tessellate keeps its current meaning (this bridge cannot answer), so nothing existing changes.
Impact
floless.app ships progressive reference-model import today for unfiltered reads only, for exactly this reason — first geometry drops from ~64 s to ~6 s there. Filtered reads are the case where the wait is most often deliberate (a user narrows precisely because the building is too big), so they are the ones currently left out.
What
ifc-reference-reader.read-modelpublishesparse/tessellate/batch/completeon the progress channel (#405). None of them carries the filter receipt (selected), which appears only in the complete node output.Why it matters
A consumer that draws segments as they arrive cannot, while drawing, tell these two runs apart:
storeys: [L2]and is streaming one floor, andread-model.mdis explicit that this is the failure the receipt exists to catch, and that absence-means-cannot-answer applies to the input as well as the output. So a progressive consumer has no honest option but to refuse to draw filtered reads at all.No count cap substitutes for it. floless's own pre-read estimate documents itself as not an upper bound (a type filter resolves with
includeInherited: truewhile the probe's rows are exact leaf names), and the harm is correctness rather than size anyway — a legitimately large floor and a silently unfiltered building are the same number of objects. Inferring capability from capability ("segments arrived, so the bridge must be new enough to filter") reasons across two independently installed binaries, which is the moveframe,selected,colorsAvailableandbudgetall exist to make unnecessary.Repro (measured 2026-08-12, CLI 0.121.0, agent 1.4.0, bridge current)
2023-05-09 30 Daldy Street Model.ifc, 65.8 MB, 17,460 objects,batch-size: 100:node-progressrecords — 1parse, 1tessellate, 235batch. Everybatchrecord carriesseq,doneand anartifactdescriptor.selected, at any phase, includingcomplete(which repeats the whole artifact's descriptor only).Suggested shape
Carry the receipt on the
tessellaterecord — it is published once, after the filter has resolved to expressIDs and before the first segment, which is exactly the point at which a consumer must decide whether it may draw:{ "kind": "node-progress", "node": "read", "data": { "phase": "tessellate", "selected": { "storeys": ["L2"], "candidates": 3767, "unmatched": [] } } }A consumer then draws only when the receipt confirms the axes it asked for, and falls back to today's wait-for-complete otherwise. Absent
selectedontessellatekeeps its current meaning (this bridge cannot answer), so nothing existing changes.Impact
floless.app ships progressive reference-model import today for unfiltered reads only, for exactly this reason — first geometry drops from ~64 s to ~6 s there. Filtered reads are the case where the wait is most often deliberate (a user narrows precisely because the building is too big), so they are the ones currently left out.