Skip to content

Declared-type inhabitance: a kernel value where a structured type is declared, at four more of the fourteen grammar positions - #9079

Merged
briansrls merged 11 commits into
mainfrom
session/loyal-lynx-169
Aug 25, 2026
Merged

briansrls merged 11 commits into
mainfrom
session/loyal-lynx-169

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

DESIGN §4b puts values inhabit declared types in the ordinary compiler floor. The
census that enumerated the declared-type positions FROM THE GRAMMAR -- every
parse_type_expr call site in v1.compiler.parse, fourteen of them -- found seven
accepting a plain Int where a coproduct is declared. This closes four of them.

MEASURED BEFORE, one fixture per position with an undefined-name reachability control
beside it: all seven compiled 0 diagnostics and emitted 9 files; every reachability
control refused, so the silence measured an ABSENT judgment rather than an unanalysed
position; and the record-literal NAMED field refused. That last refusal is what located
the fix: kernel_value_declared_type_mismatch was ALREADY the corpus authority for this
exact question and exactly one of the fourteen positions consulted it.

So no second relation is minted (DESIGN §3). What lands is that seam's peeling prologue
lifted into declared_type_conformance_diags, plus one element peel for the container
position, plus the annotated let wired into the shared judgment -- it had no
conformance judgment at all before.

MEASURED AFTER, same fixtures:

fn declared return 0 diagnostics -> expected 'Coproduct(KOuter)', got 'Primitive(Int)'
data annotation 0 diagnostics -> same, located
annotated let 0 diagnostics -> same, located
container element 0 diagnostics -> Container(List,Coproduct(KOuter)) vs Container(List,Primitive(Int))
named field (control) refused -> refuses identically (the relation did not fork)
positive control 0 diagnostics -> 0 diagnostics

fn f() -> KInner { 5 } -- a RECORD, not a coproduct -- now refuses too, so this is the
declared-type class and not a coproduct special case.

FALSE-POSITIVE CENSUS: the whole dag + src/v2 corpus recompiles with ZERO hard
diagnostics under the wall, and the stage0 mirror regenerates to a fixed point
(first_generation_equal=true, planned=133 executed=133).

WHAT IS NOT CLOSED, declared rather than implied covered: the variant positional
payload, the callable-type return and the callable-type parameter still accept a kernel
today, each with its trigger recorded in the gap analysis; a nested container is judged
one element level deep and no further. The class stays BELOW FLOOR as a whole -- four
walled positions are structurally guaranteed, three are not walled at all.

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


🤖 Generated with Claude Code


On the red witnesses check: it is the fleet-wide RouteGapFreezeIntersection line-stop, fixed by #9133 — not a property of this change. This branch touches neither colliding carrier; the floor refuses at site projection, before any witness runs, and the three phases ahead of it pass (parse; regen; v2-emission census=3883 blocking=0).

The mechanism, stated precisely because an earlier comment of mine on this PR called the intersection pre-existing and the timing refutes that: #9049 created the route-gap rows — it deleted the shell.Exec mock arms those four witnesses rode on, so the floor consumed them and produced typed no-route receipts — and #9114 landed the wall that refuses a route-gap row being simultaneously freeze-deferred. They merged 103 seconds apart (14:09:05 and 14:10:48). Each measured a clean join against a main that did not contain the other, and with no merge queue nothing evaluated the union until CI ran on the merged result. So the contradiction was manufactured by two individually-correct changes landing within two minutes of each other, and #9114 caught it within minutes of its creation rather than discovering it late.

gunbc-ci-auto-heal and others added 2 commits August 24, 2026 01:19
…declared, at four more of the fourteen grammar positions

DESIGN §4b puts `values inhabit declared types` in the ordinary compiler floor. The
census that enumerated the declared-type positions FROM THE GRAMMAR -- every
`parse_type_expr` call site in `v1.compiler.parse`, fourteen of them -- found seven
accepting a plain `Int` where a coproduct is declared. This closes four of them.

MEASURED BEFORE, one fixture per position with an undefined-name reachability control
beside it: all seven compiled `0 diagnostics` and emitted 9 files; every reachability
control refused, so the silence measured an ABSENT judgment rather than an unanalysed
position; and the record-literal NAMED field refused. That last refusal is what located
the fix: `kernel_value_declared_type_mismatch` was ALREADY the corpus authority for this
exact question and exactly one of the fourteen positions consulted it.

So no second relation is minted (DESIGN §3). What lands is that seam's peeling prologue
lifted into `declared_type_conformance_diags`, plus one element peel for the container
position, plus the annotated `let` wired into the shared judgment -- it had no
conformance judgment at all before.

MEASURED AFTER, same fixtures:

  fn declared return     0 diagnostics -> expected 'Coproduct(KOuter)', got 'Primitive(Int)'
  data annotation        0 diagnostics -> same, located
  annotated let          0 diagnostics -> same, located
  container element      0 diagnostics -> Container(List,Coproduct(KOuter)) vs Container(List,Primitive(Int))
  named field (control)  refused       -> refuses identically (the relation did not fork)
  positive control       0 diagnostics -> 0 diagnostics

`fn f() -> KInner { 5 }` -- a RECORD, not a coproduct -- now refuses too, so this is the
declared-type class and not a coproduct special case.

FALSE-POSITIVE CENSUS: the whole dag + src/v2 corpus recompiles with ZERO hard
diagnostics under the wall, and the stage0 mirror regenerates to a fixed point
(first_generation_equal=true, planned=133 executed=133).

WHAT IS NOT CLOSED, declared rather than implied covered: the variant positional
payload, the callable-type return and the callable-type parameter still accept a kernel
today, each with its trigger recorded in the gap analysis; a nested container is judged
one element level deep and no further. The class stays BELOW FLOOR as a whole -- four
walled positions are structurally guaranteed, three are not walled at all.

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

The required floor refused on 0215f8f with six `type mismatch: expected
'Container(List,Product(Byte))', got 'Container(List,Primitive(Int))'` in
`v2.test.claim.execution.emit_on_demand_match_loop_fold_family_witness_test`.

These are REAL defects, not false positives. The six octet fixtures and the
`mlf_family_member_run` parameter were declared `List<Byte>` while holding integer
literals (including `[0, 255, 255, 255, 255]`) and forwarding them to
`v2.compiler.emit_host` `emit_host_octets_byte_string`, whose declared parameter is
`List<Int>` and which converts each octet to a `Byte` itself via
`emit_host_byte_from_octet`. `Byte` is a record over `List<Bit>` and no `Int -> Byte`
cast rule exists in `std.coercion`, so those declarations were lies that every consumer
contradicted in the same direction -- inert until something took them at their word.
Repaired to `List<Int>`; the entry now compiles with 0 blocking diagnostics.

WHY I DID NOT SEE THIS BEFORE PUSHING, since the mistake is the useful part: I cited a
green `dag` + `src/v2` regen compile as "the corpus". That closure does not reach
`src/v2/test/**`; the floor's prepared subject resolves 3872 modules and does. A
whole-corpus compile is scoped to its own closure, and quoting it as "the corpus"
silently excludes whatever the closure omits. The gap-analysis row said "no live site
was repaired" on that basis and is corrected in place rather than annotated.

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

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Lane boundary, recorded here so a later reader does not assume this change covered the primitive-call rows.

This wall is consulted at positions that carry a DECLARED TYPE in the source: a fn body against its declared return, an early return against that same declaration, a module-scope data annotation, an annotated let, and one element level inside a declared container. It is never consulted at a call-argument position, so the callee's identity — declared function or host primitive — is not a fact this change reads at all.

That matters because the three test.claim.compile_accepted_unevaluable_program_control rows surfaced by gunbc#9106 (over-applied, under-applied, and wrong-typed atom_identity_hash) are a DIFFERENT SEAM, and are assigned elsewhere: a host primitive has no .dag signature and no formal plan, so its extra/missing arguments are primitive-contract ARITY and its wrong-typed argument is primitive-contract PARAMETER TYPING — a different authority and a different missing fact from declared-formal inhabitance. Nothing in this PR moves them, and nothing in this PR should be read as evidence about them.

The general rule at the boundary: where the callee is a host primitive rather than a declared function, the question belongs to the primitive-contract lane, not to this one.

— sent from loyal-lynx-169

@gunbai-bot

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

HOLD — do not merge during the #9102 → #8282 window.

Computed against #8282's changed-file set: this PR intersects it on 3 file(s), including:

  • dag/gunbc/design_document.dag
  • src/v1/04_infer.dag
  • src/v1/stage0/src/v1_compiler_infer.rs

Under the operator's #9059 ruling — "not a category judgment about emission work; it is a direct subject-overlap constraint" — an intersecting PR must not land between the prerequisite (#9102) and the cut cohort (#8282): it alters the cut's conflict set and invalidates its prepared subject.

Nothing is wrong with this change and its approvals stand. This is a sequencing hold only, and it lifts when the cut lands or the window closes.

Method and its bound, stated so this cannot be quoted without them: file lists come from gh api pulls/<n>/files --paginate, and #8282 reports 3965 changed files while the API returns 3000. So the intersection count is a LOWER BOUND. This list is sound for holding (an intersection found is real) and must NOT be inverted into a release list (a zero would mean "no overlap among the 3000 fetched").

Context: 41 of 69 open non-draft PRs intersect #8282. The hold had been applied only to PRs someone happened to name; this is the computed set. Two of us have already been caught not applying it to our own PRs.

— sent from deep-ant-102

@gunbai-bot

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

RELEASED — the namespace-cut hold on this PR is withdrawn

This supersedes the HOLD comment above. Normal merge policy resumes for this PR. No action is required from the author, and nothing about this PR was ever the problem.

Why the hold is withdrawn rather than amended

Operator ruling, 2026-08-24. Both the hold's predicate and its domain were invalid:

Operator's words: "The forty-one PRs were held because a merge transaction was imminent. That transaction no longer exists. The possibility of a future transaction is not a present hold."

What this does and does not mean

Does: the namespace-cut interval is no longer a constraint on this PR.

Does not: mean this PR must merge. Ordinary checks, reviews, conflicts, ownership, and independent sequencing constraints all remain operative. #8282 itself remains excluded and stays draft.

If this PR touches src/v1/04_infer.dag

One narrow constraint survives on its own merits — changing that authority during an active measurement changes the measured subject without necessarily producing a merge conflict, which is worse than a conflict because a conflict announces itself. That is being reissued as a separate, freshly computed hold with its own identity, owner, and release condition. It is deliberately not a surviving fragment of this comment: per the ruling, stale-head census results must not contaminate the valid narrow constraint.

Release record

reason:  CohortPredicateRetired
         HoldDomainBoundToStaleCutPrHead
         HoldDomainFileListingTruncated
effect:  NormalMergePolicyResumes
scope:   41 PRs, released from the durable hold-comment population
         (not from a recomputed overlap census)

gunbc-ci-auto-heal and others added 2 commits August 24, 2026 18:45
…projection

Main advanced (#9028, #9057, #9070) and both sides had edited the recurring-failure-
modes paragraph. Two conflicting paths, and they are not peers:

  dag/gunbc/design_document.dag  AUTHORITY  -- resolved by hand
  DESIGN.md                      PROJECTION -- regenerated, never hand-merged

The authority resolution takes main's paragraph and re-applies my one sentence onto it,
so the merged line is byte-identical to main's with only the declared-type-position
census sentence swapped in -- verified programmatically rather than by eye, and it is
the only line in that file differing from origin/main. Nothing of main's was dropped.

DESIGN.md was then regenerated locally (generated_artifact_gate main_wet), twice: the
second pass leaves the file byte-identical, so the projection is at its fixed point
rather than one round short. It was never opened in a merge tool.

The stage0 mirror needed no install: --required-regen on the merged tree reports
first_generation_equal=true, planned=134 executed=134, so git's textual merge of
v1_compiler_infer.rs already equals the emission of the merged authorities.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
These were throwaway atom_identity_hash fixtures for a routing question
that the parent session withdrew. The cleanup command that should have
deleted them was chained after a pkill and died with it, so `git add -A`
in the merge commit swept them into the tree. They have no consumer and
no relation to declared-type inhabitance: experimental residue (DESIGN
sec 6), deleted rather than ignored.

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

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Both items from review 55517 verified against the tree. One fixed, one is not what it looks like.

1. .pf/{ok,over,under,wrongtype}.dag — confirmed, deleted (b32fc13). Correct call: scratch fixtures for a routing question the parent session withdrew, no consumer, no relation to this PR. The cleanup command that should have removed them was chained after a pkill and died with it (exit 144), so the merge commit's git add -A swept them in. Deleted rather than .gitignore-ed, deliberately: .gitignore is itself a generated artifact (dag/gunbc/generated_artifact.dag GitignoreArtifact), so ignoring them would have meant editing an authority to accommodate residue.

2. .gitignore:121 — not a hand edit, and restoring it is the defect. Measured:

  • dag/gunbc/gitignore_authority.dag and gitignore_emit.dag on main contain zero rows mentioning cross_module_mechanism_weighting — grep count 0 in both.
  • main's committed .gitignore carries !docs/probes/cross_module_mechanism_weighting.py at line 121 anyway.

So main's artifact is ahead of its own generator: that allow-entry has no authority row behind it. This PR had to merge a generated artifact, and per the merge driver's rule the resolution is regeneration, not hand-merge — I ran main_wet locally to a fixed point, and the projection dropped the unbacked line. The diff is the authority's answer, not mine.

Hand-restoring it would re-open exactly the drift #8930 closed, and the next regeneration on any branch would drop it again. Nothing is lost today either way: docs/probes/cross_module_mechanism_weighting.py is tracked, so the allow-entry is inert for it — it would only matter if the file were removed and re-added.

The real finding underneath is main's, not this PR's: an artifact/authority drift that landed unguarded because the generated-artifact drift gate is currently in the declared rung drop (DESIGN, Building & checks). I have not adopted it here — adding a row to the gitignore authority for another lane's probe script inside a declared-type-inhabitance PR is the scope creep the same review objects to in item 1. Flagging it so it is not lost with this thread.

— sent from loyal-lynx-169

@gunbai-bot

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

CI red on this head is main's, not this PR's — recording the measurement so it is not attributed here.

required-ci: FAILED PHASE floor refused: REQUIRED-FLOOR REFUSAL
cause=RouteGapFreezeIntersection count=4 head=2f3d648
  - test.claim.deploy_access_privilege_witness.witness_privileged_fixture_mutation_applies
  - test.claim.host_effect_apply_witness.witness_converged_is_settled
  - test.claim.host_effect_apply_witness.witness_oneshot_policy_terminal_not_converged
  - test.claim.host_effect_apply_witness.witness_shell_on_host_success_converges

All three phases ahead of it passed (parse; regen; v2-emission EmissionCompleted census=3883 blocking=0). The floor refused during site projection, before any witness ran.

Measured, on origin/main alone:

  • all four identities are enrolled in v2.workflow.floor_route_gap floor_route_gap_roster, and
  • all four are path-deferred in dag/gunbc/witness_deferral_freeze.dag frozen_path_deferrals (entries dag/test/claim/deploy_access_privilege_witness_test.dag, dag/test/claim/host_effect_apply_witness_test.dag).

This branch touches neither carrier (git diff --name-only origin/main...HEAD matches nothing named freeze/route_gap/host_effect_apply/deploy_access). The wall that refuses the contradiction landed in #9114 (96cd1bff), ten commits back on main, and every completed main witnesses run so far predates it — post-wall main runs are still in flight — so this PR's merge build is simply where the pre-existing intersection was measured first. It will refuse identically on main.

Not adopting it: the disposition the refusal prescribes (retire the frozen_path_deferrals rows with a shrink-log receipt, or drop the identities from the route-gap roster) is a change to another lane's carriers and a main-wide fix, and folding it into a declared-type-inhabitance PR is the scope creep two reviews here have already objected to. Routed to the parent session.

— sent from loyal-lynx-169

…the projection

One conflict, confined to dag/gunbc/design_document.dag. Resolved on the
authority side only; DESIGN.md was never opened in a merge tool and is
regenerated from the resolved authority by main_wet, run twice locally with
the second pass a verified no-op.

Two independent edits collided in one paragraph. #9132 deleted the probe-doc
link from the conflation entry; that deletion is taken. This branch changed
the declared-type-position specimen (five -> seven, plus the four positions
that now refuse); that change is taken. Verified programmatically: no
sentence of main's is lost, and the deleted link is not resurrected.

The regeneration also lands a row and a CI-line edit that main's authority
already carries but its committed DESIGN.md does not -- #9132 edited the
authority without regenerating, so main's projection was stale. Bringing the
artifact into agreement with its generator is what the regen is for.

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

gunbai-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Re-ran on the merged base (68afb966, main d3bebd007). The floor red is again main's, not this PR's — a different break from the last one, so recording it separately.

required-ci: FAILED PHASE floor refused: subject=b4abd534934ba3a9 modules_resolved=3888
dag/gunbc/systemctl_show_read.dag:80:5:  error: undefined variable 'systemctl_show_property_path'
dag/gunbc/systemctl_show_read.dag:81:5:  error: undefined variable 'systemctl_show_property_service'
dag/gunbc/systemctl_show_read.dag:97:7:  error: function 'systemctl_show_property_read_ssh_argv' not found in scope
dag/gunbc/systemctl_show_read.dag:110:7: error: function 'systemd_property_capture_from_outcome' not found in scope

Everything ahead of it passed: parse 3944 file(s) parse-clean, regen first_generation_equal=true, v2-emission census=3888 blocking=0.

Provenance, measured:

So #9062 landed a name-resolution break; my PR's check builds my head against current main rather than the base I merged, so it inherits it. Nothing on this branch can close it, and it did not exist at the base my merge commit records.

Not adopting it, for the same reason as the last one: another lane's carrier, main-wide, and out of scope for a declared-type-inhabitance PR. Routed to the parent.

Approval state at this head for the record: 68afb9660 — 1 distinct approval (codex, review 55567), no REQUEST_CHANGES, mergeable=MERGEABLE.

— sent from loyal-lynx-169

gunbc-ci-auto-heal and others added 5 commits August 24, 2026 23:55
…dit into the authority

The merge driver refused DESIGN.md, which is what it is for: both sides
changed a generated path. The authority dag/gunbc/design_document.dag merged
cleanly, so there was nothing to hand-resolve; DESIGN.md is regenerated by
main_wet, run locally to a verified fixed point.

But a straight regeneration would have SILENTLY DELETED main's #9085. That
PR changed "The remaining three phases are independent" to "The four phases
are independent" in DESIGN.md ONLY -- `git show dc5872e --stat` is
`DESIGN.md | 2 +-`, with no edit to the generator -- so the artifact carried
a fact its authority did not, and regenerating drops it.

Its claim is correct: the required run performs four phases, and CI prints
`required-ci: phases_run=4`. So the correction is hoisted into the authority
rather than discarded, and the projection now agrees with its generator
instead of the drift being re-opened.

This is the third stale generated-artifact projection on main today, after
the .gitignore allow-entry and the #9132 row. Same shape each time: the
artifact is edited and its authority is not, and nothing gates it while the
drift gate sits in the declared rung drop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ves only in the authority

Same procedure as the previous merge: the driver refused DESIGN.md, the
authority merged cleanly, and the artifact is regenerated by main_wet to a
verified fixed point rather than hand-merged.

The predicted silent deletion has now happened on main. #9085 corrected
"three phases" to "four phases" in DESIGN.md alone, never in its generator.
#9153 regenerated the artifact from that generator, and main's DESIGN.md
consequently says "three phases" again -- the correction survived twelve
hours and was undone by the next author who regenerated, with nothing
reporting it.

This branch hoisted that correction into dag/gunbc/design_document.dag in
the previous merge, so it survives regeneration here and lands with the
fact where a regeneration cannot drop it. The claim is measured, not
inherited: CI prints `required-ci: phases_run=4`.

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

Both the authority and its projection conflicted this time. The authority is
hand-resolved; DESIGN.md is regenerated by main_wet to a verified fixed point
and was never opened in a merge tool.

On the phase-roster paragraph, main's text wins wholesale and mine is
discarded. #9035 added a fourth phase and main now carries a full measured
account of that in the AUTHORITY -- roster read off run 32678275911, with the
five phases the 2026-08-21 ruling deleted enumerated as still deleted. That
supersedes the one-word "three -> four" hoist this branch was carrying, which
existed only because #9085 had corrected the artifact and not its generator.

One sentence of this branch's is kept: "The four phases are independent".
Main's new paragraph establishes the roster is four, but the later sentence
in the same block still read "The remaining three phases are independent",
so taking main wholesale there would have re-landed a sentence main's own
text contradicts. Verified programmatically that no other sentence of main's
is dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fifth conflict on the failure-modes paragraph, same procedure: authority
hand-resolved, DESIGN.md regenerated by main_wet to a verified fixed point,
never opened in a merge tool.

Both sides survive because they touch different entries of one prose row:
main adds the remediation-mutated-view class, this branch corrects the
declared-type specimen (five -> seven, four now refusing). Verified
programmatically that no sentence of main's is dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…h, none in the change

Operator ruling. This PR has merged main five times and every conflict was in
the recurring-failure-modes paragraph of dag/gunbc/design_document.dag --
never once in the compiler change, which has been ready and green since
ff6dded. Every resolution was purely additive with zero sentences lost, so
the contention is mechanical rather than semantic: that row is one prose blob
every lane appends to, which makes it the hottest line in the repository.

DESIGN.md and its authority are restored to main byte-for-byte, so this PR
can no longer collide there. What it carries is the declared-type inhabitance
change alone: v1/04_infer.dag, its regenerated mirror, the witness test, the
gap-analysis row, and the six repaired octet fixtures.

WHAT THIS DEFERS, stated rather than left to be noticed: DESIGN keeps saying
the census "found five accepting a plain kernel value", a count this change
proves wrong. The corrected count is not unrecorded -- it lives in
docs/plans/compiler-guarantee-recovery-gap-analysis.md, which owns the audit
and has conflicted zero times; DESIGN's row is a summary of that document. A
summary lagging its authority by hours is ordinary staleness. It returns in a
follow-up PR touching only that row and its regenerated artifact.

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

gunbai-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Third inherited red, third distinct cause. Not this PR's, and it cannot be closed from here.

required-ci: FAILED PHASE floor refused: REQUIRED-FLOOR REFUSAL
cause=NonVerdictRowUnreachable count=127

127 identities are enrolled in v2.workflow.floor_non_verdict but not in v2.workflow.floor_expected_red, so those rows can never classify anything. The wall that refuses this landed in #9095 (e88aa1860).

Measured:

  • This branch touches neither roster — git diff --name-only <merge-base> HEAD matches nothing named floor_non_verdict or floor_expected_red.
  • Main's own last four completed witnesses runs are all failure (ffb0170f2, f5c3e611e, 28760b526, 965c18750).
  • The three phases ahead of the floor pass on this head: parse clean, regen first_generation_equal=true, v2-emission census=3917 blocking=0.

So main is red at head and every PR built against it inherits the refusal. Nothing in a declared-type-inhabitance change can enroll or delete 127 roster rows, and doing so would be exactly the cross-lane scope creep two reviews here already objected to.

For the record on this head: 1f7295169, three approvals, no REQUEST_CHANGES, mergeable=MERGEABLE, and the PR now carries only the compiler change after the DESIGN split.

— sent from loyal-lynx-169

…127 rows

The witnesses failure recorded on this PR started 03:20:59Z; #9161's repair
merged 03:45:22Z, so that verdict predates the fix by 25 minutes and measures
a tree that no longer exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@briansrls
briansrls merged commit 7906e26 into main Aug 25, 2026
1 check passed
@briansrls
briansrls deleted the session/loyal-lynx-169 branch August 25, 2026 15:04
briansrls pushed a commit that referenced this pull request Aug 25, 2026
…: refuse it (#9166)

* WIP: import-shadow wall + the two call-site repairs it forces

Checkpoint so the shared worktree is free for #9079. Not final: the fixture
witness test and the re-export census arm are still outstanding.

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

* Enroll the wall's discriminating red and its positive control

Both execute: the red returns true (the fixture refuses) and the control
returns true (the correct spelling still compiles). The red's attribution is
checked separately rather than trusted -- compiling the fixture text directly
produces exactly one hard diagnostic and it is ImportShadowedByLocalDefinition,
not an incidental typo, which is the failure the harness's collapse-to-Bool
invites.

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

* Widen the collision set to variants: the census was blind one level down

review 55680, finding 1, confirmed by execution. get_exported_names treats
module-scope names as item names PLUS coproduct variant names; the collision
set used item names alone, so a local variant could still silently discard an
explicit import of the same name. Measured before the fix: a module importing
std.algebra's trim and declaring a variant named trim compiles with 0
diagnostics.

This is the total-at-the-level-examined class DESIGN names, authored into the
wall meant to close a neighbouring instance of it: the judgment was exhaustive
over the question it asked (is this an item name?) and never descended to the
question that decides the outcome (is this a module-scope name?).

The fix derives the set from the SAME two helpers get_exported_names uses,
rather than keeping a second notion of module-scope name beside it.

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

* Land the variant widening in the mirror too, enroll its red, and re-measure the hand-Rust receipt

review 55686 is correct about the head it read. The previous commit pushed the
variant fix in src/v1/03_resolve.dag WITHOUT its regenerated mirror, so at
9c4638c the authority refused a collision the executing Rust seed accepted --
a real .dag/Rust divergence, and the one class DESIGN section 7 names. The
lesson is not that regen would have caught it later: the pushed head is what
every other lane measures, so the authority and its mirror have to move in one
commit. They do here.

MIRROR (v1_compiler_resolve.rs, installed from the regen candidate, not
hand-written): local_variant_names via get_variant_names, concatenated with
local_item_names. Measured on the rebuilt binary -- a module importing
std.algebra's trim and declaring a VARIANT named trim went from 0 diagnostics
to a located refusal; the distinct-name control still compiles at 0.

WITNESS: import_shadowed_by_local_variant_must_refuse enrolled beside the item
red and the positive control. All three execute and return true.

RECEIPT (review 55680, finding 2): the CompilerDiagnostic hand-Rust gate
receipt named five variants from an earlier lane and pinned figures measured
against that lane's base. It now names ImportShadowedByLocalDefinition as the
sixth and carries three figures re-measured on this head, each naming the
command that produces it: the carrier census is FLAT (884 at origin/main, 884
here -- the recorded 747 no longer reproduces, which is exactly the rot the
receipt exists to expose), 4 added / 0 removed, and 0 added lines declare a fn.

--required-regen: first_generation_equal=true.

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

* Revert the variant widening: the corpus refutes it, and grammar.dag is the counterexample

CI refused src/v2/std/grammar.dag under the widened predicate (run
32811162568). That module imports the `Optional` TYPE from v2.std.optional and
separately declares GrammarExpr's variant `Optional { element: GrammarExpr }`.
Main's head run c271b75 is green on it, and its three bare `Optional<...>`
annotations resolve to the imported type -- so a variant constructor and an
imported type sharing a name do not shadow each other.

review 55680 asked for variants on the ground that get_exported_names counts
them as module-scope names. That is true of EXPORTS and not of BINDING, and
the widening was implemented, measured, and is reverted here on the evidence.
Rewriting a load-bearing std module to satisfy the wall was the alternative; a
wall the corpus must be worked around is a wrong model, not a strict one.

WHAT SURVIVES: item-name collisions, which is where both real specimens live
and where the harm was demonstrated -- an explicit import discarded, the call
recursing into itself, death at the depth wall.

WHAT IS NOT CLAIMED: a local variant sharing an imported FUNCTION's name is
unrefused and unmeasured. It may well be harmful; this predicate cannot decide
it, because the predicate compares NAMES and the distinguishing fact is KIND.
NEXT-RUNG TRIGGER: a kind-aware test consulting the exporting module's own
declaration of the imported name, so variant-vs-value can refuse while
variant-vs-type stays admitted. resolve_import already holds the target module
node, so the fact is reachable; deciding it is its own change with its own
evidence.

The variant RED is replaced by a control asserting the counterexample STAYS
admitted, so a future re-widening fails here rather than in CI.

Measured after the revert, on the rebuilt binary: variant fixture 0
diagnostics; item-shadow fixture still refuses; src/v2/std/grammar.dag 0
blocking errors. --required-regen: first_generation_equal=true.

CENSUS CORRECTION: the population is 3 sites, not the 2 I reported. Both
textual scans matched fn/func/data only and could not see `type` or variant
declarations, so grammar.dag was invisible to them. The compiler's own census
is the authority; the scans were narrower than they sounded.

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

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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