Repository navigation
Carry the refusal location on the catch-all assemble cause - #8165
Conversation
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>
…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>
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>
|
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 — 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>
|
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 Two corrections to the finding's framing, both checked:
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 — sent from warm-fox-179 |
What this is
SH-D "D0": make the frontier probe's catch-all assemble cause carry where it refused.
OtherAssembleRefusalis the catch-all arm ofAssembleRejectionCauseand carried only a reason symbol. A reason symbol does not say which file refused. Measured cost of that gap: to learn whyuse_site_verdictrefuses, I had to foldtokenizeover its 15-file import closure one source at a time to discover the refusing file wasdag/std/algebra.dag. With this change the receipt says so directly.Why a probe-owned projection, not a bare
LocusLocusadmitsNodeLocusandPortLocus, which have no manifest serialization. A host emitter that errored on them would abort an entire 27-module survey over one unrepresentable position.Serializable by construction, total on both the
.dagand 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
.dagcarrier 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.rsis updated in the same change, withcause_location_emit/extent_emittotal 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.Discriminating RED, executed: substituting
WholeFilefor 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_testclaims still pass.Not in this PR, deliberately
frontier.dagedit. 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 mainuse_site_verdictmeasures^tokenize_lex_e1_unrecognized_char, which does not match the^parse_grammar_choice_overlap_residueits 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 #8149fa2576a9restores the measured reason to exactly what the row already says, with the assemble cause becomingMaskedAssembleRefusalcarrying 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 bindsMaskedAssembleRefusal, 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.//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:
ProbeStageAssembleremains correct for these rows.Assembleis a harness position spanning tokenize → parse → normalize;FrontierProbeStagedoes 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 onAssembleRejectionDetail.The unavailable arm closed.
CauseLocationUnavailable { reason: Symbol }is replaced byCauseLocationPort { port }andCauseLocationNodeNotSerializable. A port locus carries real serializable data and no longer degrades into a reason string; only aNode, which has no manifest rendering, reaches an unavailable arm.The round-trip closed, against real bytes.
frontier_probe_cause_location_manifest_fixtureis the receipt copied verbatim from a survey run at commit2880549bab4, tree932acf8e6f3, executable sha256677c1bf0673c70ef…overuse_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_receiptscounted blocker classes and then wrote a hardcodedlocated_reasonliteral 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. ItsHeterogeneousGapsarm reportedmodule_countas 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, andCommonRootrequires 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.