Skip to content

Carry the refusal location on the catch-all assemble cause - #8165

Merged
briansrls merged 11 commits into
mainfrom
session/warm-fox-179
Aug 13, 2026
Merged

briansrls merged 11 commits into
mainfrom
session/warm-fox-179

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

What this is

SH-D "D0": make the frontier probe's catch-all assemble cause carry where it refused.

OtherAssembleRefusal is the catch-all arm of AssembleRejectionCause and carried only a reason symbol. A reason symbol does not say which file refused. Measured cost of that gap: to learn why use_site_verdict refuses, I had to fold tokenize over its 15-file import closure one source at a time to discover the refusing file was dag/std/algebra.dag. With this change the receipt says so directly.

Why a probe-owned projection, not a bare Locus

Locus admits NodeLocus and PortLocus, which have no manifest serialization. A host emitter that errored on them would abort an entire 27-module survey over one unrepresentable position.

type FrontierProbeCauseLocation
  = CauseLocationTextual { file: Symbol, extent: Extent }
  | CauseLocationUnavailable { reason: Symbol }

Serializable by construction, total on both the .dag and Rust sides, and the unavailable arm carries a typed reason so the deficit is counted rather than fabricated or fatal.

Location is deliberately kept separate from the cause key: two modules refusing for the same reason at different positions are the same detailed cause, so a clustering key must read the cause, not this field.

The survey binary is the third consumer

Changing the .dag carrier alone would have emitted a manifest that no longer typechecks against the new field — worse than dropping it, since it fails at reload rather than at the edit. frontier_probe_survey.rs is updated in the same change, with cause_location_emit / extent_emit total and no error arms.

Verified rather than assumed: the generated manifest needs no new import. The manifest import block already omits variant constructors (GrammarChoiceOverlap, OtherAssembleRefusal), so bare names resolve; I confirmed by deleting the import from a probe and re-running — identical result.

Evidence

frontier_probe_cause_location_test.dag — fixtures, not a pipeline walk, so ~0ms and per-PR affordable.

claim result
textual locus preserves the file PASS
textual locus preserves the exact byte range PASS
PortLocus keeps its port symbol rather than degrading PASS
NodeLocus reaches the not-serializable arm PASS
reason and location are drawn from the same diagnostic PASS

Discriminating RED, executed: substituting WholeFile for the real extent reds only the byte-range claim and leaves the other two green. The byte range is asserted exactly on purpose — an implementation that kept the file but dropped the position would satisfy a presence check while destroying the thing the field is for.

Regression: all five existing frontier_probe_overlap_detail_test claims still pass.

Not in this PR, deliberately

  • The measurement instruments. The probes that produced the findings above (real-closure door probe, cause probe, lex localizer, tokenize fixtures) are one-off experimental residue and are not landed.
  • Any frontier.dag edit. The roster is the program lead's file, and — stated because an earlier revision of this description got it wrong — no row correction is owed here. On current main use_site_verdict measures ^tokenize_lex_e1_unrecognized_char, which does not match the ^parse_grammar_choice_overlap_residue its row records. That is a masking wall, not a misattributed row: applying only the annotation-channel hunk from Re-cut the partial v2 std-ingestion frontier; propagate lowering refusals and wire DAG annotations #8149 fa2576a9 restores the measured reason to exactly what the row already says, with the assemble cause becoming MaskedAssembleRefusal carrying real overlap rows. Updating the row from a pre-repair measurement would therefore have replaced the recorded reason with a transient one. Stated at the grain the evidence supports: B restores the recorded reason at reason grain only. At detailed-cause grain B binds MaskedAssembleRefusal, whose meaning is that the overlap residue is ITSELF masking a further chain — so "the row is confirmed" is NOT established, and an earlier revision of this description that implied it was overclaiming. What is established is that the current-main reason is a mask and the recorded reason reappears beneath it; whether the recorded reason is the terminal cause depends on the remaining chain, which is not yet read.
  • The // annotation-channel repair, which is the production root behind that measurement. It belongs to Re-cut the partial v2 std-ingestion frontier; propagate lowering refusals and wire DAG annotations #8149 and is not duplicated here.

Stage note: ProbeStageAssemble remains correct for these rows. Assemble is a harness position spanning tokenize → parse → normalize; FrontierProbeStage does not model compiler substage.

Added after the first review pass

The location moved off the cause. It was a field of OtherAssembleRefusal, which made a position structurally part of what the refusal is — two modules refusing for the same reason at different positions would read as different detailed causes at a clustering key. It now sits beside the cause on AssembleRejectionDetail.

The unavailable arm closed. CauseLocationUnavailable { reason: Symbol } is replaced by CauseLocationPort { port } and CauseLocationNodeNotSerializable. A port locus carries real serializable data and no longer degrades into a reason string; only a Node, which has no manifest rendering, reaches an unavailable arm.

The round-trip closed, against real bytes. frontier_probe_cause_location_manifest_fixture is the receipt copied verbatim from a survey run at commit 2880549bab4, tree 932acf8e6f3, executable sha256 677c1bf0673c70ef… over use_site_verdict.dag; the reload half passes against it. It is regenerated, never hand-edited — a hand-written approximation would test the fixture author's idea of the format instead of the emitter's.

The clustering verdict now measures instead of asserting. frontier_gap_clustering_from_receipts counted blocker classes and then wrote a hardcoded located_reason literal into whichever branch fired, so it reported a reason no receipt had to carry — the one real survey measures ^tokenize_lex_e1_unrecognized_char, which no branch could ever name. Its HeterogeneousGaps arm reported module_count as the distinct-reason count. count_receipts_with_located_reason, the function that reads the measured axis, had zero callers. Both numbers are now derived from the receipts, and CommonRoot requires unanimity rather than a plurality, because a plurality bar is a threshold and a threshold is the smuggled heuristic a closed system never needs.

New controls, all executed with their REDs verified: unanimous survey reports the measured reason and counts it; mixed survey reports 2 distinct reasons over 3 receipts where the old arm reported 3; empty survey is never a common root.

OtherAssembleRefusal is the catch-all arm of AssembleRejectionCause, and it
carried only a reason symbol. A reason symbol does not say WHICH file refused,
so recovering that meant re-lexing an entire import closure by hand — measured
on use_site_verdict, whose 15-file closure had to be folded through tokenize
one source at a time to learn that dag/std/algebra.dag was the refusing file.

The location is carried as a probe-owned projection rather than a bare Locus.
Locus admits NodeLocus and PortLocus, which have no manifest serialization; a
host emitter that errored on them would abort a 27-module survey over one
unrepresentable position. FrontierProbeCauseLocation is serializable by
construction and total, and its unavailable arm carries a typed reason so the
deficit is counted rather than fabricated or fatal.

Location is kept structurally separate from the cause key: two modules refusing
for the same reason at different positions are the same detailed cause, so a
clustering key reads the cause and not this field.

The survey binary is the third consumer and is updated with it — the DAG
carrier change alone would have emitted a manifest that no longer typechecks
against the new field, which is worse than dropping it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title Semantic Pipeline Family Carry the refusal location on the catch-all assemble cause Aug 12, 2026
gunbc-ci-auto-heal and others added 5 commits August 12, 2026 03:37
…e its variants

The location was a field of OtherAssembleRefusal, which made a position
structurally part of what the refusal IS: two modules refusing for the same
reason at different positions read as different detailed causes at a
clustering key. It now sits beside the cause on AssembleRejectionDetail.

CauseLocationUnavailable { reason: Symbol } is replaced by the closed pair
CauseLocationPort { port } and CauseLocationNodeNotSerializable. A PortLocus
carries real serializable data and no longer degrades to a reason string;
only a Node, which has no manifest rendering, reaches an unavailable arm.

The survey emitter follows the field and the arms, and stays total.

Controls (all executed): each of the three Locus arms reaches its own arm;
the byte range is asserted exactly, so substituting WholeFile reds; and a
two-diagnostic control pins reason and location to the SAME diagnostic
(RED verified by asserting the tail's offset).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fixture was hand-edited to the reshaped carrier, which is exactly what
its own note forbids: a hand-written approximation tests the author's idea
of the format instead of the emitter's. These bytes are copied verbatim out
of a survey run at commit 2880549, tree 932acf8, executable sha256
677c1bf0673c70ef… over src/v2/compiler/use_site_verdict.dag, and the reload
half passes against them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eipts

frontier_gap_clustering_from_receipts counted blocker CLASSES and then wrote
a hardcoded located_reason literal into whichever branch fired, so the
verdict reported a reason no receipt had to carry: the one real survey
measures ^tokenize_lex_e1_unrecognized_char, which no branch could name. Its
HeterogeneousGaps arm reported module_count as the distinct-reason count,
which is a count of modules wearing the name of a count of reasons. And
count_receipts_with_located_reason, the function that reads the measured
axis, had zero callers.

Both numbers are now read off the receipts. CommonRoot requires unanimity
rather than a plurality, because any plurality bar is a threshold and a
threshold is the smuggled heuristic a closed system never needs. An empty
survey reports a distinct count of zero rather than becoming a common root.

Controls (executed, both REDs verified): a unanimous survey reports the
measured reason and counts the receipts carrying it; a mixed survey reports
2 distinct reasons over 3 receipts, where the old arm reported 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
These eight files are the one-off measurement instruments behind the A/B
finding — the real-closure door probe, the cause and reason readouts, the
lex localizer and three tokenize fixtures. They were never meant to land;
the PR description says so explicitly. A blanket 'git add -A src/v2' put
them in the tree anyway, which is experimental residue and a description
that no longer described the diff.

They stay local, excluded via .git/info/exclude so the next add cannot
repeat this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 12, 2026 17:56
gunbc-ci-auto-heal and others added 4 commits August 12, 2026 17:56
The tally ran unconditionally and its result was discarded on the
heterogeneous arm, which needs the distinct count alone. Cheap at survey
scale, but a copied fold whose output is thrown away is a cost-shape
defect regardless of the realized n, and 'n is small here' is not a
time-stable fact. Found by review 51421.

All four clustering claims still pass by execution.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MEASURED, not hypothesised. src/v2/compiler/03_resolve.dag needs 71 source
reads against the manifest transport's 64-row inline cap, so the manifest
emits SourceRootManifestElided with produced_row_count 0 and an Empty
ingest. Handed that, frontier_probe_emit_from_ingest answered
^resolve_module_not_found with cause MissingModuleIdentityUnavailable — a
survey row asserting the module is missing when the truth is that its
sources were never supplied. Two states, different remedies, and the one
reported was the plausible one.

frontier_probe_coverage_gate already classifies an elided manifest
correctly, but it guards only the discovery path; this entry receives the
ingest directly and never consults coverage, so the conflation was
reachable from every from_ingest caller.

An empty ingest is now a typed, located, counted population refusal naming
^frontier_probe_empty_ingest.

Residue, declared rather than closed: emptiness is decidable here, coverage
is not, because the entry is not given the SourceRootCoverage — a PARTIAL
closure still answers. Dissolve-on is on the carrier: route the coverage
receipt into this entry so the refusal becomes an arm of the existing gate.

Four claims green by execution; RED verified by disabling the wall, which
reds three of them and restores the module-not-found answer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…tern

Every other match site was updated when the field landed; this one kept the
two-field pattern. Review 51431 flagged it.

The predicted typecheck failure does not occur — the file's five claims were
green by execution before this change and are green after — so the language
admits the partial pattern. That is the reason to fix it rather than to
leave it: a pattern that silently keeps matching when the carrier grows a
field is how a match stops covering what its author thought it covered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 4634377 — thanks, review 51431 was right that this was the one stale pattern site.

One correction for the record: the predicted typecheck failure does not occur. All five claims in that file were green by execution before the change and are green after, so the language admits the partial variant pattern. That makes it a weaker finding than REQUEST_CHANGES implies, but a better reason to fix it than the one given: a pattern that silently keeps matching when its carrier grows a field is exactly how a match stops covering what its author thought it covered. Bound as at: _.

— sent from warm-fox-179

Review 51432 is right that this claim's behavior against the checked-in
stub changed. What it was before is the part worth naming: with receipts
Empty, clustering asked self_emit_ready_count == module_count, both were 0,
and it answered CommonRoot with dominant_located_reason ^probe_stage_emit_ok
— a survey with no receipts reporting that every module reached emit. The
one claim whose subject IS the clustering verdict was passing vacuously on
a fabricated verdict.

Receipt-derived clustering answers HeterogeneousGaps for an empty survey,
so the claim now reds on the stub. That is the same state its siblings were
already in and is the file's declared offline condition, not a CI failure
shape: compiler_frontier_per_module_probe_survey_holds compares the receipt
count against the 27-row roster, and 0 is not 27.

The length check makes THIS claim's red say 'no receipts' explicitly rather
than leaving it to read as a clustering disagreement. Verified by execution
that the conjunction is false on an empty survey rather than erroring.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 2bc11e0. Review 51432 correctly identified that this claim's behavior against the checked-in stub changed, and it was worth chasing.

What it was doing before is the part worth naming. With receipts: Empty, clustering asked self_emit_ready_count == module_count, both were 0, and it answered CommonRoot { dominant_located_reason: ^probe_stage_emit_ok } — a survey with no receipts reporting that every module reached emit. So the one claim whose subject is the clustering verdict was passing on a fabricated verdict. That is the vacuous green this PR's clustering rework exists to remove, and it deserves to red rather than be restored.

Two corrections to the finding's framing, both checked:

  • The file was already red on the stub, before this PR and independently of it. compiler_frontier_per_module_probe_survey_holds compares the receipt count against the 27-row roster, and 0 is not 27. So this PR does not take an otherwise-green enrolled witness red; it adds one more red function to a file whose declared offline condition is red-on-stub (its own note: "Local recipe RED on stub manifest (receipts Empty) is offline-only until the authoritative survey runs — not a CI failure shape").
  • "reads green in CI only because the long lane is offline" is not the situation — it does not read green anywhere. It reds locally, and CI never executes it.

The change made: the claim now requires a nonempty survey before reading the verdict, so its red says no receipts explicitly rather than reading as a clustering disagreement. Verified by execution that the conjunction is false on an empty survey rather than erroring. No witness rename, so the transport string at frontier_probe_survey_transport.dag is untouched.

— sent from warm-fox-179

@briansrls
briansrls merged commit 30e3c61 into main Aug 13, 2026
5 checks passed
@briansrls
briansrls deleted the session/warm-fox-179 branch August 13, 2026 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant