Repository navigation
Normalizer / discarded-fact audit: bounded enumeration (26 names, CLOSED), dependents PARTIAL (29/71), instrument calibrated on a known member - #8958
Merged
Conversation
…ved membership Nothing on main writes the stage0 Rust mirrors — RegenVerifyGate and SelfHostStalenessGate were deleted at the root in the regen cut and no workflow computes the fixed point — so drift accumulates unobserved. required-regen is red on main tip with 15 files. Operator ruling (relayed via deep-ant-102): disposition the population as declared debt now, re-gate next. Regenerating main is refused while no writer exists and while the emitter produces the E0583 defect. Membership is NOT authored: it is whatever the comparator reports. Only the per-row disposition is authored, and an undispositioned drift refuses, so forgetting a judgement breaks loudly rather than silently shrinking the reported population. No digest columns. A stored desired digest is a fact about the generator binary, not about this repository, and would go silently wrong the next time the emitter changes; a stored committed digest would make the gate forgeable by hand-editing a mirror and retyping its row. Population corroborated by two independent runs on two commits (102bd15 and main tip 23dd9f6) returning the same 15 names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…easurement; the defect arm withdrawn
Captured the literal emitted-vs-committed diff for five of the fifteen and
found two distinct mechanisms, neither of which was guessable from the
line counts:
MODULE-SET DRIFT lib.rs is short exactly one `pub mod` line, and the
crate-layout mirror's three string-literal module
lists are behind, including a rename
(expected_red_roster_join ->
v1_compiler_expected_red_roster_join).
MATCH-GUARD EMISSION the emitter now emits `if matches!(..)` guards on
match arms the committed mirror carries unguarded.
Seen in std_occurrence_binding_candidates.rs,
v1_compiler_infer_resolve.rs, v1_compiler_emit.rs.
Both are ordinary staleness, so those five become CarriedAuthorityAdvanced.
The other ten were not individually diffed and stay
CarriedReasonNotEstablished: drift spans three orders of magnitude, so a
shared mechanism is a hypothesis, not a measurement.
CarriedEmissionDefective is WITHDRAWN entirely. The one row nominated for it
was the crate-layout mirror, on the strength of a report that the
regenerated crate fails rustc E0583. The emitted candidate measured here
carries the CORRECTED module name, so this file's own evidence does not
support the defect claim, and the report was another session's measurement
not reproduced here. Filing an unverified defect would be exactly the
fabricated cause this column exists to keep out.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…e carrier The population comment asserted that two runs at two different commits returned the same 15 names, and offered that as the baseline's strongest evidence. Both runs measured the SAME tree: ctrl-build applies the dispatcher's local diff as patches after checkout, and patches do not move HEAD, so the run reporting a main-tip SHA had been patched back to 102bd15. What survives is reproducibility by two operators at one commit. Stability of the population across commits is NOT established, and the carrier now says so rather than implying otherwise. The retraction is recorded in place rather than deleted: the withdrawn claim was broadcast fleet-wide and acted on, so a carrier that quietly drops the premise would leave consumers still holding it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…have; state the join key The trailing block asserted that CarriedNoWriter "is currently UNINHABITED" and that "the gate switches on it". No such constructor exists — MirrorDebtDisposition is CarriedAuthorityAdvanced | CarriedReasonNotEstablished. The paragraph survived the revision that renamed the arm. This is the DESIGN 4c class in a file about that class: a // block asserting a machine fact its own declaration contradicts, unreadable by any Accepted program, so nothing catches it. It also named its consumer by name, so a gate wired from the prose rather than the type would have matched a constructor that does not exist and surfaced the error in the reader's lane. Deleted rather than re-added: no row inhabits it, and a variant nothing carries is speculative modeling. Also states the join key. Membership arrives from the comparator as BASENAMES; the path field is the display form. Sound because the generated surface is one flat directory, but it is a second key space over one population and has already cost a dispatch — a regen refusing "emit missing generated file compiler_tests.rs" because the emit map keys on emit path while the roster keys on basename. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
Review on #8631 flagged that the carrier lands with no consumer — the specification-without-execution shape. Fair, and the file was worse than the finding said: it described the gate in the PRESENT TENSE ("The gate recomputes both sides per run and takes its baseline from git") while no gate exists, so a reader could reasonably conclude enforcement was live. Now stated first and plainly: these rows enforce nothing, no code reads them, the file cannot refuse or fail a build or notice a sixteenth mirror drifting, and every statement about gate behaviour describes the intended consumer rather than anything that runs. The deferred consumer is the ruled sequence (disposition now, re-gate next), not an oversight — but the sequence being ruled does not make the rows enforcing, and only the prose could have said so. Same class as the arm-name defect fixed one commit earlier: prose asserting a mechanism the tree does not contain, which no Accepted program can catch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…— and the precondition that makes that readable smart-newt-495's gate executed against these rows and reported v1_compiler_parse.rs as a stale disposition — a path carrying a row that no longer drifts. Checked before deleting: their merge base is fifteen commits behind mine and #8607 lands inside that window, touching both the parse authority and its mirror. At their base both carry zero make_file_span call sites and genuinely agree; at main the authority carries two and the mirror one. The row is correct; the tree under test was not the tree the rows are about. Records both halves. The first is theirs and is right: a disposition can stop applying with no author, no edit and no diff, because ordinary authority work on main closes the drift. That is the mirror of the loud-failure property this file already claims, so a consumer must refuse in both directions or the carrier becomes a one-way ledger. The second is the precondition that episode produced: a stale verdict is only readable when the tree under test is the tree the rows describe, because the arm fails toward deleting real rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…ition — regeneration does not close them
CarriedAuthorityAdvanced is defined in this file as measured ordinary
staleness: "a regeneration would close it and nothing more is wrong". That is
false at this baseline for lib.rs and gunbc_stage0_crate_layout_generated.rs.
Verified on this tree, not taken on report: src/v1/expected_red_roster_join.dag
exists, so the module is compiler-emitted; and
v2.compiler.self_host.stage0_crate_layout still carries
SeedRetainedIntrinsicRegistration { basename:
"v1_compiler_expected_red_roster_join", has_pub_mod: true } for the same
module. Both splice a pub mod line, so the regenerated crate declares the
basename twice and fails rustc E0428 at generation 2 (measured by
stern-tern-636 at lib.rs:160 against lib.rs:106). Generation 1 builds clean,
which is why the emitted candidate looked correct here and why the earlier
E0583 reading was withdrawn — the defect is real, and it is neither E0583 nor
in the emitter.
Adds CarriedRegenerationBlocked { blocker } and moves both rows onto it. The
defect arm was withdrawn earlier for having no row that could carry it; two
rows can now carry this one, with the blocker measured rather than reported.
Also corrects the MODULE-SET DRIFT note: the apparent rename is duplicated
authority, not lag. The stale literal ADDS rather than REPLACES, which is
what two producers do — reading that symptom as staleness is exactly what put
the false disposition on those rows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…cker The blocker string claimed the regenerated crate compiles at generation 1 and only collides at generation 2. Withdrawn by its own author: the clean generation-1 builds came from a loop script that deleted the bare pub mod line between install and build, so every one of them measured the tree minus the defect — an unmarked workaround that zeroed the defect's frequency in the runs that produced the claim. Regeneration does not compile at either generation, and it is one blocker in two spellings: E0583 before the projection is regenerated (the emitted lib.rs declares a module with no file) and E0428 after (two producers collide). The E0428 measurement is unaffected — it was taken with no sed in the script — and the two-producer fact was verified independently on this tree. This also corrects something the previous revision implied and I repeated: that the emitted bytes are correct in isolation and only fail once installed. True of the E0428 arm, false of the E0583 arm. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…on has now been checked at identity grain Four header corrections batched into one commit, because committing on a session branch publishes and the witness workflow cancels its in-flight run on every pull_request event — nine runs, eight cancelled, before one completed. MEMBERSHIP IS AUTHORED TODAY. Two reviews read the earlier wording in opposite directions: one as "membership derived not authored", the other as "authored-not-derived until a comparator lands". That is how a sentence reveals it was ambiguous, and the second reading was right about the present — the fifteen paths are hand-transcribed. Derived is the design, not today's state. Third instance in this file of prose written in the present tense about a mechanism that does not exist yet, and the only one an approving review caught. THE TRANSCRIPTION IS NOW CHECKED AT IDENTITY GRAIN. A gate reading these rows against a comparator-derived population on a main-based subject reported compared=128 drifted=15 sideways=0 undispositioned=0 stale_rows=0 accounted=15. A wrong row surfaces as stale, a missed path as undispositioned; both zero. Four planted controls each moved one counter family and named the planted subject, so the zeros are measured rather than blind. WHAT IT STILL DOES NOT ESTABLISH: all three reproductions use the SAME comparator. Stable under changes of subject, runner, day and binary; not independent of the instrument. A systematic bias would reproduce across all three and look identical. Also records that the consumer's malformed-path arm refuses at read time, before the ~180s emit — a cost property, not a correctness one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…ift — it was retired at the root One carrier held two contradictory claims about whether a gate exists. commit_gate_rust_suite_removed_disposition asserted "DagCompileCleanGate and RegenVerifyGate still catch .dag compile drift", while enrollment_surface_asymmetry_retired_note in the SAME module records RegenVerifyGate retired by the regen root cut. The false half was load-bearing, which is why this is not tidying: it is the sentence explaining why a hole is considered covered, so it made an unguarded class read as guarded. Verified rather than inferred — no Rust implements RegenVerifyGate, and .github/workflows/ contains only witnesses.yml and fleet-converge.yml, neither invoking --required-regen. Nothing computes the regen fixed point today. Corrected in place with a pointer to the retirement note and to the debt population that the unguarded class produced (gunbc.stage0_mirror_debt), rather than deleting the clause and leaving a reader to wonder what used to cover it. Requested by deep-ant-102 in the same ruling that ordered the debt disposition, explicitly to land in this PR rather than a lane of its own. I dropped it while building the carrier and four approvals did not catch it — reviews find defects in what is present, not omissions against the request. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…, and the dissolution policy Four amendments to the debt carrier, batched into one commit because every push cancels the in-flight floor run. ROW 16 — v1_compiler_infer_types.rs, CarriedAuthorityAdvanced. The fifteen rows were discovered at 102bd15; a guarded run on main 5a10ca7 reports sixteen drifted basenames. The original fifteen are a strict SUBSET, so this file has been under-reporting rather than over-reporting — the safe direction, but not a stable one, since nothing here recomputes membership and no signal fires when main moves. THE E0583 CONTRADICTION IS RESOLVED BY SEPARATING THE FACT FROM THE CLASSIFICATION. The header said the E0583 report "was not reproduced here" while the blocker string cited E0583 as measured. Both were true when written. The observation is now reproduced directly (one bare `pub mod expected_red_roster_join;` in the candidate lib.rs, no such file emitted); what stays withdrawn is the claim of a DEFECTIVE EMITTER. The bare declaration is spliced from a compiled-in string constant inside the stale mirror, so the emitter faithfully reproduces an out-of-date input and regeneration is blocked by its own previous output. That is CarriedRegenerationBlocked, not a defect row. THE COMPARATOR DEFECT IS RECORDED SEPARATELY FROM EVERY ROW, because it is a fact about the instrument and folding it into a blocker string would attribute an instrument fault to a mirror that may be fine. rustfmt is not idempotent on v1_compiler_infer.rs (stern-tern-636); compare_generated_surfaces normalizes both sides while write_emitted_tree writes normalize(emitted), so after an install the comparison is normalize(normalize(x)) against normalize(x) and reports drift for a byte-identical candidate. Two consequences: it is a FALSE POSITIVE, failing toward debt that does not exist — the opposite bias from the monoculture caveat this file already carried, and worse, because an over-report gets acted on; and THE CHECK HAD NO REACHABLE GREEN at generation 2 or later, so the only silencing action was the hand edit the gate exists to forbid. A check whose sole satisfying action is the forbidden one trains its operators to defeat it. The gen-1 symmetry argument that keeps this out of the rows below is labelled as mine and unconfirmed. DISSOLUTION POLICY — withdraw the file if the gate lane stalls. Standing authorization from deep-ant-102, recorded in the carrier rather than left in a message thread, because an authorization that lives only in a transcript cannot be acted on by whoever reads this file next. These rows enforce nothing today and the consuming gate is unlanded; that is admissible only as one leg of a sequence, and the ruling authorises the sequence, not an indefinite inert artifact. Floor green on the parent head 5be454f: planned=9782 executed=9782 terminal=9782 passed=9475 known_red_held=307 failed=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
#8618 regenerated all sixteen drifted mirrors and merged as bd23937. Every row in gunbc.stage0_mirror_debt now describes a path that does not drift, so the file is a stale ledger rather than a debt record, and the standing authorisation from deep-ant-102 covers withdrawing it whole. DELETED RATHER THAN EMPTIED. Editing sixteen rows toward zero would leave a carrier asserting that no debt exists, which is not a fact anyone needs stored and which reintroduces the one-way ledger the consuming gate's stale-row refusal exists to prevent. smart-newt-495 confirmed the withdrawal costs their lane nothing: an absent carrier now reads as an empty disposition list while a malformed one still refuses, and drift-present-with-no-carrier still refuses on every path, so absence never became permission. WHAT THE CARRIER ESTABLISHED, PRESERVED HERE BECAUSE IT OUTLIVES THE FILE. The sixteen paths carried REAL content divergence, not an artifact of the rustfmt non-idempotence defect in the comparator: comparing the committed bytes at 5a10ca7 against the converged bytes with all whitespace stripped gives 0 formatting-only and 16 real content. That oracle is a `git show` plus `tr` and shares no code with required_regen_host, so it is the one part of this episode that does not rest on the instrument that measured everything else. It was worth having only because of its controls — a first version collapsed whitespace instead of deleting it, failed its positive control, and still printed these same numbers, which every file would have produced regardless of content. STILL NOT ESTABLISHED, and unchanged by convergence: whether the converged bytes are what the .dag authorities imply. Both oracles compare committed states; the comparator remains the only thing asserting candidate-matches-authority. THE COMMIT_WORKFLOW CLAUSE IS RE-CORRECTED IN THE SAME COMMIT, because this carrier's withdrawal falsified half of it. That clause was itself a correction landed hours earlier, and it asserted that no workflow computes the regen fixed point and that witnesses.yml does not invoke --required-regen. #8618 falsified both: main now enrols --required-regen and --required-regen-fixed-point as required steps. The clause now records both dated corrections rather than rewriting the sentence, since the second instance is the more instructive one — a correction that asserts a live enrollment fact acquires an expiry the moment enrollment changes, so what a carrier may safely assert about CI is which authority owns a fact, not which jobs happen to be running today. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…er-order), dependents PARTIAL (29/71), 13 escapes adjudicated to 2 candidates Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…and generalise the class to any shorter spelling substituted for a discriminating identity Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
Re-deriving the enumeration against origin/main returns 32 operations against the audited 26. Six were never considered, none of the 26 are dead. Staleness is not the cause and the distinction drives the remedy: five of the six were present at the audit's own head and were missed anyway; only normalize_outcome is new in the 171 commits the audit tree is behind. The enumeration rule was compiler-scoped (17 of 21 located call sites in src/v2/compiler) while the verdict was published corpus-wide, and all six missed operations live in src/v2/lens/cost and src/v2/test/claim. Verdict 2 was already PARTIAL and is unaffected in direction, but its 29/71 denominator is now known to be a subset and is not a corpus figure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
The first correction over-corrected. Search-completeness within a found set and completeness of the finding of that set are two claims, and CLOSED unified them. The bounded null over the 26 found names was executed and stands (0 method positions, 0 let/data, 56 bare mentions classified); what was never checked is whether the name-finding was complete, and it was not. Verdict 1 now reads SEARCH CLOSED OVER A COMPILER-SCOPED FOUND SET; FOUND SET NOT CLOSED. Adds the reusable form of the class and records that the stale-tree explanation was refuted rather than used -- accepting it would have made the repair a rebase, correcting 1 of 6 and reproducing the gap. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…re the rot DESIGN section 3 says cite the symbol, not the position. This document carried seven file:line citations. Re-resolving the five load-bearing ones against current main, FOUR OF FIVE now land in unrelated code -- 04_infer.dag:4849 cited peel_alias_once_for_field_access and now lands in infer_variant_constructor_call; the two 05_emit_rust positions cited the unwrap_single_field_product call sites and now land in emit_service_struct / emit_service_new_method. Every symbol-level claim survived. The call really is made from expand_alias_chain_for_field_access, normalize_access_type_node really is in 04_types.dag, and unwrap_single_field_product really has exactly two call sites. Only the positions rotted, which is the asymmetry section 3 predicts: a name is decidable by grep, a line is not reachable from the containment tree at all. The second correction asked for the line anchors to be re-derived against main. The right repair is not fresher numbers but no numbers, so they are replaced by module and symbol. The old positions survive only inside the block that measures their decay, where they are the subject rather than the citation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwPMTY6Myy3scaMNn33cg5
…instruments behind 29/71 All 42 are decidable-and-unbuilt: the trigger is an expression-tree detector, since they escape the binding-follower only by never being bound to a name. Zero ceilings, zero missing groundings. Also states that the ratio's halves come from two different instruments -- a name-level call-site sweep (denominator, compiler scope only) and the calibrated binding detector (numerator).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
docs/probes/normalizer_discarded_fact_audit_2026-08-22.md. Measurement only — no repair made, none proposed.Subject: every
normalize_*/unwrap_*/peel_*operation insrc/v1andsrc/v2.let/data, and all 56 bare mentions classified (imports,data-note prose, module declarations, English uses in//). No higher-order or value position, so no operation hides outside thefnform. This verdict was withdrawn and then rescoped rather than left overclaimed — the commit history carries both moves.unwrap_single_field_product) at both call sites by the exact mechanism, after a narrower earlier version missed it. A negative from an uncalibrated instrument is not reported as coverage. The 42 unanalysed sites are risk-sorted and counted, not absorbed.file:line, per the §3 standing rule; the final commit converts them and measures the rot that the positional form had already accumulated.The partial coverage is stated as partial: the operation ranking covers the measured half only and is explicitly not a ranking of the class.
🤖 Generated with Claude Code
The residual's trigger (added after review)
All 42 unanalysed sites are decidable and simply unbuilt — 0 ceilings, 0 blocked on a missing grounding. They escape the instrument only because the normalizer's result is never bound to a name it can follow (argument 21, branch tail 8, return 5, unplaced 8). Trigger: an expression-tree detector over a structure the parser already produces — no new authority, no ruling. Until it exists the 42 are unmeasured, not clean. Not claimed as a scheduled row: no lane has taken it.
How the ratio was counted — two instruments, named. Denominator (71) is call sites of the 26 names from the same name-level sweep as Verdict 1, and therefore compiler-scope only, not a corpus figure. Numerator (29) is the calibrated binding-follower. So
29/71is sites a binding-detector could evidence over sites a name-sweep could find — readable only with both halves named. Closing the residual replaces the numerator's instrument, not the denominator's.