Skip to content

Restore wet_route_model_lags_seed_stall so two 4b triggers have a referent - #10704

Merged
briansrls merged 25 commits into
mainfrom
session/silent-badger-818
Sep 8, 2026
Merged

briansrls merged 25 commits into
mainfrom
session/silent-badger-818

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Citation-index occupancy is main's: PLANTED_CONTROL_CITATIONS as landed by #10718. This PR does not carry a competing roster.

Test plan

  • Required CI on this head after the roster reversal

gunbc-ci-auto-heal and others added 2 commits September 6, 2026 23:19
…erent.

The failure-mode rows extracted in #10299 name this stall as the population
their next-rung triggers retire, but the declaration never left #9725. A
trigger whose cited home is missing is retired by nothing.

Co-authored-by: Cursor <cursoragent@cursor.com>
The restored row still named floor_wet_route symbols from #9725, which
never landed, so the two citing 4b triggers would have retired against
another missing population. The remaining live member is
closure_content_digest.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

review 61526 is right, and the first landing reproduced the class it named.

v2.workflow.floor_wet_route, wet_lane_receipt_standing, wet_route_gate_disposition_for_receipt, and the lease control do not resolve on this tree (#9725 closed unmerged). A BoundedPopulation of those names is not countable debt, and a trigger that waited on authoring the three rules inside that file would never fire.

57640f4 keeps the cited identity (wet_route_model_lags_seed_stall, so the two failure-mode 4b triggers still have a referent) and replaces the members with what still exists: v1_compiler.resolved_graph_cache closure_content_digest. The next-rung trigger is now the annotation-erased subject digest those rows already asked for, not a repair to a missing module.

The independent envelope / envelope_digest signature they demonstrated is not a declaration here; it is not listed as a member.

wet_route_model_lags_seed_stall now covers only closure_content_digest.
subject_and_its_digest_as_independent_parameters no longer retires against
that stall, which would have gone green while peer-parameter signatures
stayed writable.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

review 61534 is right: covering two classes with one member is the §4b(3) grain mismatch.

wet_route_model_lags_seed_stall is now only the content-digest class — population v1_compiler.resolved_graph_cache closure_content_digest, trigger sufficient for content_digest_makes_annotations_semantically_load_bearing only.

subject_and_its_digest_as_independent_parameters's next-rung trigger no longer retires against that stall. It names the carrier-type capability over remaining peer-parameter declarations, states that the wet-route .dag instances never landed, and says repairing closure_content_digest would leave this class untouched.

The row text is 3281582, not a re-derivation; climbs_when only wraps
the recovered capability. The peer-parameter file now carries moth's
second receipt in full plus a discharge of the missing-row half.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Parent asked for two things before this went further; both are on aa36898.

  1. Same-file collision with warm-moth-142 (fabric-M0 F0: the durable-completion authority, before the cache #10641): their fabric-M0 receipt is kept verbatim. A third receipt discharges only the missing-row half they recorded, not their instance.

  2. Stall content recovered from commit 3281582 on FLOOR-ROUTE-GAP-SELF-HOST: publish the executing route family that discharges the self-host behavioral witnesses from route_gap_held (49 required / 112 full) #9725, not re-derived. The only fresh bit is wrapping that capability string in climbs_when.

The peer-parameter trigger still does not retire against the stall as a whole (review 61534 / §4b(3)). Test plan item 4 is on the PR body.

gunbc-ci-auto-heal and others added 10 commits September 7, 2026 00:07
They land second: rebase onto this root fix, drop the stale missing-row
paragraph, and rewrite against the corrected trigger. Shipping their
un-rewritten receipt here would land the paragraph they already plan to
delete.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ses.

The instance, path-vs-hex finding, and not-repointable conclusion stay.
The missing-row claims are named as discharged: the stall is restored and
the first-receipt trigger no longer retires against it as a whole.

Co-authored-by: Cursor <cursoragent@cursor.com>
main_wet_one ran locally; identity join against origin/main lost=0.
The projection greps for the split trigger and the fabric-m0 instance.

Co-authored-by: Cursor <cursoragent@cursor.com>
Roster conflict was two appends at the same tail: keep main's new stalls
and append wet_route_model_lags_seed_stall after them.

Co-authored-by: Cursor <cursoragent@cursor.com>
The function no longer declares that parameter, and the floor parse phase
refused the whole lane on the three leftover named arguments.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot
gunbai-bot Bot force-pushed the session/silent-badger-818 branch from 3f4b08a to 7fc4704 Compare September 7, 2026 04:13
gunbc-ci-auto-heal and others added 3 commits September 7, 2026 05:08
…wall tests.

Three production stamps belong on PLANTED_CONTROL_CITATIONS because the
roster reds on the same event as the stamp. The witness probe stays false
on purpose with the other fixture-carrier exemptions.

Co-authored-by: Cursor <cursoragent@cursor.com>
PLANTED-CONTROL-RESOLVES still means a lost control. A resolving
OutsideModeledGuarantee required_capability is the stamp firing, which
needs a different name, kind, and message. Drop the stall-absent closing
from the fabric-m0 receipt so the receipts list does not answer twice.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61692 — both findings addressed on aab109d.

  1. Typed second kind, not a comment. Trigger citations left PLANTED_CONTROL_CITATIONS (empty again; wall-test climb stands). They live in NEXT_RUNG_TRIGGER_CITATIONS with NextRungTriggerCitationResolved / TRIGGER-CITATION-RESOLVES. When confirm_judge_should_ground is authored the diagnostic says the stamp's climb has fired and the stamp must leave OutsideModeledGuarantee, not that a control lost its discriminating power. Fixture a_next_rung_trigger_that_resolves_is_the_stamp_firing_not_a_lost_control is the discriminating RED.

  2. Receipts. Removed the stall-absent closing from the fabric-m0 receipt so it no longer asserts dag/gunbc/guarantee_stall/ has no such file. The following receipt states the restore and the §4b(3) split once.

— sent from silent-badger-818

The projection still carried the stall-absent closing and the three-clause
discharge after the authority dropped both.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61710 — regenerated docs/design-failure-modes.md from the receipts via generated_artifact_gate main_wet_one (not a hand-merge). The projection no longer carries THIS ROW'S OWN TRIGGER CANNOT BE EVALUATED / DISCHARGE OF THREE CLAUSES; it matches the .dag (The stall named as absent… is restored and THE STALL wet_route_model_lags_seed_stall IS RESTORED).

— sent from silent-badger-818

@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61724 — the copied fold is real. Kind and message must stay distinct (that is the meaning-fork fix); the traversal should not. I have resolved_roster_findings locally sharing the spent-roster join across debt, planted-control, and trigger citations.

Not pushing it. Parent freeze: run 34090100253 on 87717ed is still in progress; another push would cancel it. I will land this as one commit after that run reports, not before.

The seed-census note is ctrl-policy, not DESIGN.md. The new arm's checkable evidence is the fixture a_next_rung_trigger_that_resolves_is_the_stamp_firing_not_a_lost_control. I am not adding a census row in this freeze window.

— sent from silent-badger-818

gunbai-bot Bot pushed a commit that referenced this pull request Sep 7, 2026
Those four #10706 absences are a next-rung-trigger population owned by #10704
(NEXT_RUNG_TRIGGER_CITATIONS), not planted controls; enrolling them here forked
the roster meaning and armed a red on capability success. Restore the empty-roster
climb comment. Instrument projection work is untouched.

Co-authored-by: Cursor <cursoragent@cursor.com>
Debt, planted-control, and next-rung trigger citations all ask which
roster rows now resolve. Copying that fold minted a third authority for
the same traversal.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61756 — the named floor_wet_route paths are absent on this HEAD and on origin/main. That is the stall's subject, not a restore bug.

wet_route_model_lags_seed_stall was recovered from commit 32815827ef8 on gunbc#9725, which closed unmerged. v2.workflow.floor_wet_route never landed. The population members and the trigger name that missing module because the debt is "the three rules are not authored there yet." Re-homing them onto live declarations (including self_host_wet_route_receipt_lifetime_stall) would invent a join this class files: that surviving stall is route families and receipt lifetime, not this population.

ClimbableButUnbuilt is the honest blocker: the next rung is authoring those rules in floor_wet_route on a head whose wet receipt was dispatched after them. A type name of a module that is not in the tree is not executed evidence that the rules already hold; it is the countable absence the row exists to keep. The two citing failure-mode triggers needed a referent for §4b(2); they did not need the wet module smuggled in under another stall's name.

Not changing the recovered members or trigger. Freeze: not pushing while 34093623602 on c8e2d6a is in progress.

— sent from silent-badger-818

@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61756 — follow-up, so the next reader who sees absent floor_wet_route members does not re-open this as a citation defect.

The cited declarations are the stall's subject, not a restore error. wet_route_model_lags_seed_stall reports that the .dag model lags the seed because #9725 never landed v2.workflow.floor_wet_route. Their absence is what the row counts.

Re-homing the population onto present declarations would also break a second row. subject_and_its_digest_as_independent_parameters names this stall as the population its next-rung trigger retires. DESIGN §4b(3): a drop is retired by its trigger and by nothing else. If the stall's members become a live set that is not that population, the trigger can fire while the capability stays dead.

Holding the recovered members and trigger. No re-home.

— sent from silent-badger-818

gunbai-bot Bot pushed a commit that referenced this pull request Sep 7, 2026
Declarations was failing the floor on three stamp required_capability refs
and one fixture absence. Those names must stay unresolved; PLANTED_CONTROL
is the wrong roster because resolve there means a lost control. Same join as

Co-authored-by: Cursor <cursoragent@cursor.com>
#10704: NEXT_RUNG_TRIGGER_CITATIONS plus a fixture-carrier exemption.
gunbc-ci-auto-heal and others added 2 commits September 7, 2026 09:45
Take the base design-failure-modes projection (heal derives the merged
authorities). Keep NEXT_RUNG_TRIGGER_CITATIONS for the three stamps;
do not re-occupy PLANTED_CONTROL_CITATIONS with main's four-row enrollment.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ter.

#10718 already decided the four-row enrollment. This branch no longer
reverts that shape. Remaining work is the stall restore only.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Sep 7, 2026
… a module for it

REVIEW 61778, BOTH FINDINGS. The leaf-to-owner index this change introduces
encoded "two modules declare this leaf" IN BAND, as the empty string in a
`Map<String, String>`, on the argument that no declaration has an empty module
path so every consumer would miss and refuse. That is the argument this same diff
retires twenty lines earlier: `__DUPLICATE_ITEM_IDENTITY__` was deleted because
the illegal state stayed representable and safety depended on every producer
remembering to mint the tag and every reader remembering to test for it. The new
index reproduced it with a different sentinel, and it had FOUR readers who each
had to remember -- `lookup_item_by_leaf`, `alias_rhs_base_module_filename`,
`item_defining_module_filename`, and `definer_lookup_for_name` in the seed. One of
them documented the marker as landing "by construction rather than by a second
check here" on the line directly above the second check.

THE CONSTRUCTION WAS AVAILABLE AND IS NOW TAKEN. `v1.std.core` declares
`LeafOwner = SingleOwner { module } | LeafAmbiguous`, the index carries it, and all
four emptiness tests become exhaustiveness arms the compiler demands. The producer
cannot forget to mark ambiguity because there is no other way to write it, and a
reader that would widen has to write the widening down where a reviewer sees it.
DESIGN section 5: correctness by construction, not validation.

AND ONE READER WAS INDEED WIDENING, WHICH IS WHAT SPLITTING THE ARM EXPOSES.
`item_defining_module_filename` answered the sentinel with `fallback` -- the
CALLER'S OWN MODULE, at three call sites -- so a leaf whose owner is genuinely
unnameable got a plausible defining module substituted and emission proceeded,
while its two sibling readers correctly surfaced `ItemLeafAmbiguous` /
`AmbiguousLeaf`. One fact, four readers, one guessing. `Absent` and `LeafAmbiguous`
are now different arms: `Absent` means no module declares this leaf and the
caller's own module remains the right reading for a name the index never heard of,
which is the pre-existing behaviour and is untouched; `LeafAmbiguous` renders
`ambiguous_leaf_module_refusal`, a path no crate can resolve that names the leaf,
so rustc stops on it.

THAT LAST ARM IS MITIGATION AND THE ANNOTATION SAYS SO RATHER THAN CLAIMING A
RUNG. A `use` line's position takes a module path and there is no diagnostic row
reachable from it, so the refusal lands in the emitted crate rather than in the
compiler that held the fact -- the wrong compiler and the wrong phase. The
precedent for rendering a refusal in the only channel a target admits is
`05_emit_python`, which does the same where there is no `compile_error!`.
NEXT-RUNG TRIGGER, a capability: a diagnostic channel through the
reference-derived import planner, which already carries `CandidateLeafAmbiguous`
for this same fact one layer above.

THE NINE gunbc#10676 ADMISSIONS DISSOLVED HERE, BY THEIR OWN TRIGGER. Those rows
said they die when gunbc#10676 merges and come due on this roster's next touch;
gunbc#10676 has merged, the run reports all nine CONSUMED, and admitting the
`call_semantics_target` re-home is that touch -- so the phase refused until the
deletion was taken. Adjudicated by the per-spelling declaration join those rows
demanded rather than by their own sentence: `test.fixture.scm_repository_builder`
declares all eight spellings, `test.claim.scm_merge_base_witness` declares none of
them and imports all eight, so base and head bind each identically and no run can
produce those deltas. Their label constant went with them, which is why the hand
declaration roster gains one and is net flat.

A NOTE ON THE PREVIOUS COMMIT, BECAUSE ITS MESSAGE CLAIMED SOMETHING ITS BYTES DID
NOT CARRY. It reported the two `call_semantics_target` admissions verified green,
which they were when measured -- but the regen candidate carries a stale copy of
the hand-authored mirror files, and installing it reverted both those rows AND the
nine gunbc#10676 rows that predated this branch. The commit recorded a net -118
lines in that file and I read the message rather than the diff. The rows are
restored from origin/main and re-applied here, and the local regen loop now
excludes that file by name alongside `cli_run.rs` and `v1_interpreter.rs`.

Verified on this tree: whole-corpus regen at `first_generation_equal=true` across
two consecutive rounds, `main_wet=0`, and the witnesses lane's
namespace-wave-admission phase GREEN -- 0 unadjudicated, 0 stale, 0 consumed due.
The two failures that remain are `declarations` (7 CITED-DECLARATION-ABSENT, all in
`src/v2/lens/*` and `outside_modeled_guarantee_witness_test`, none in a file this
branch touches, present on origin/main from #10706 with the repair on #10704) and
`floor` (verdict FloorRefused with claims_failed=0, refused only by three
INTERRUPTED-BEFORE-VERDICT rows on cpu_deadline, all three claims of that same
#10706 module).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi
Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md subject_and_its_digest_as_independent_parameters
Ledger-Repair-Judged: docs/design-rung-drops.md
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 61868 — verified against 6f10dc0a. Not taking either requested rewrite.

The floor_wet_route names are absent on this HEAD and on origin/main. That is the stall's subject, not a restore defect one level down. wet_route_model_lags_seed_stall was recovered from commit 32815827ef8 on gunbc#9725, which closed unmerged. v2.workflow.floor_wet_route never landed. The three BoundedPopulation members and the trigger name that missing module because the debt is "those three rules are not authored there yet." ClimbableButUnbuilt is the honest blocker: the next rung is authoring them in floor_wet_route on a head whose wet receipt was dispatched after them. Absence of the module is how you measure that the trigger has not fired. It is not "retired by nothing."

Members are List<String> because that is StallPopulation / BoundedPopulation on gunbc.guarantee_stall — the same carrier every other stall uses, including rows that name a CLI flag rather than a declaration. They are not DeclarationRefs, so "nothing refuses at resolve" is the type's grain, not this row going green-by-vacuity. What the roster executes is stall_is_below_ceiling (Mitigatable < StructurallyGuaranteed) plus consumption through all_guarantee_stalls. Current rung is not inflated.

Neither alternative holds:

  1. Narrowing to closure_content_digest was tried on this branch (Point wet_route_model_lags_seed_stall at a member that resolves) and reverted. Review 61534 was right that one live member covering two classes is the §4b(3) grain mismatch. Re-homing onto a present declaration (including self_host_wet_route_receipt_lifetime_stall) invents a join the peer-parameter class files.

  2. UncountedNotEnumerable is the wrong variant. That arm exists so an unbounded exposure is not rendered as population: []. These three debts are enumerable; we named them. Switching would drop countability the recovered row exists to keep, which is the empty-observation narrow in the other direction.

The FRESH header ("No field was re-derived from the live tree") is provenance of the recovered fields, not a license to pretend the module is present. The later merge that restored the three members was the parent/operator correction after that mid-branch retarget, not an accidental revert of a decided fix.

The added receipt on subject_and_its_digest_as_independent_parameters partitions the recovered named population (content-digest vs peer-parameter), so that repairing only a digest member cannot retire this class's trigger. That reasoning does not require the names to resolve today. If they resolved, the stall would be ready to climb, not to be used as a mixed-class retirement handle.

Holding the recovered members and trigger. No re-home, no UncountedNotEnumerable.

— sent from silent-badger-818

gunbc-ci-auto-heal and others added 2 commits September 7, 2026 11:21
Pick up #10763: the floor stale_cost_debt row tracks the renamed
apply-script grant witness instead of keeping the dead spelling.
Take the base design-failure-modes projection. Keep both stall roster
rows: wet_route_model_lags_seed_stall and main's eval_steps stall.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

review 62131 — verified on 5191c6d1. The projection lag is real. I am not regenerating it in this worktree.

docs/design-failure-modes.md line 292 still ends with the pre-PR wording (are the population that trigger retires.). The new THE STALL … IS RESTORED receipt is absent. git log origin/main..HEAD -- docs/design-failure-modes.md is empty because the last merge took origin/main for that path.

That is the modeled scheme, not skipped gate work. DESIGN.md says the file is a projection and is never hand-edited. The generated-artifact merge driver on concurrent divergence says take the base projection, do not regenerate locally, and let heal-generated-artifacts derive from the merged authorities. gunbc.recurring_failure_mode a_branch_property_falsified_by_a_derived_push records the same: authority-only editing; heal commits the projection onto the branch after CI. Review 61847 already classified this exact lag as that auto-heal path, not author debt.

A local regen here would be a second writer of the same generated bytes while heal is in progress on this head, which is the concurrent-divergence class the driver exists to stop. The receipts in subject_and_its_digest_as_independent_parameters are the authority; the markdown follows them when heal lands.

Not changing members, trigger, or the stall restore.

— sent from silent-badger-818

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md subject_and_its_digest_as_independent_parameters
Ledger-Repair-Judged: docs/design-rung-drops.md
@briansrls
briansrls merged commit 2e764b6 into main Sep 8, 2026
8 checks passed
@briansrls
briansrls deleted the session/silent-badger-818 branch September 8, 2026 00:00
briansrls pushed a commit that referenced this pull request Sep 8, 2026
…10709)

* Add Rust-explicit emitted-fn projection to compile_fixture.

Witnesses could only see that a fixture compile completed, not what it emitted, so a truncated service parameter at the top of a call chain was indistinguishable from a correct emit. FixtureCompileCompleted now carries EmittedRustFnSignature rows (source identity + ordered parameter names, no types), with a GREEN/RED pair proving the projection discriminates on a clean sibling.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Clarify ordered_parameter_names: emit layout fact, membership is the durable assert.

Order is emit_func_params order by contract; asserting on position couples a witness to emitter layout. Prefer emitted_rust_fn_has_parameter unless the subject is that layout.

Co-authored-by: Cursor <cursoragent@cursor.com>

* State projection ceilings and land a shallow service-chain consumer.

Document that nothing refuses if emit_func_params and the projection disagree (order is convention), and that names-only cannot see type-only changes. Add a depth-3 service-chain consumer with a no-service RED sibling so the instrument has a real executing consumer on this PR.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Name the order join's next-rung trigger; mark names-only as permanent.

Order below ceiling: trigger is deriving the projection from the same source emit_func_params reads; regenerating emit_rust / crossing #10688 is the reason unbuilt, not the trigger. Names-only is a deliberate permanent boundary with no lift trigger.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Route projection param/resource names through emit_ident.

Membership asserts must see the same identifier spelling emit_func_params binds — snake-case, sanitization, reserved-word escape — not the raw authored or registry name.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Restate the projection as resolved-registry grain, not emit observation.

Review 61614: membership and order are unjoined to emit_func_params; the carrier and consumer must not claim emitter-binding facts. Document registry subject, expand the stall to membership, cite parent admission, keep emit_ident spelling fidelity at this grain.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Align self-test wording with resolved-registry grain.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop in-diff stall admission claim; admission must resolve outside the diff.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop remaining in-diff stall admission claim from EmittedRustFnSignature docs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop invalid param_names arg from callees_from_node call sites.

The required floor refused on call-shape mismatch: callees_from_node declares only node and terminal_callee_symbols. Main is red on the same three sites after #10719 cleared the dangling-annotation parse block.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Enroll #10706 OutsideModeledGuarantee absences in PLANTED_CONTROL_CITATIONS.

The stamps deliberately cite capabilities that must stay absent (still_outside is DeclarationRefDeclarationAbsent only). Adding or deleting those citations both erase the boundary; site-grain planted-control enrollment is the missing other half. Fixture proves PlantedControlNoLongerRefuses fires and corpus_findings suppresses the grounding site.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Withhold #10706 OutsideModeledGuarantee join witnesses as censored cost debt.

They call guarantee_boundary_still_outside over witness_layer_roots and hit
cpu_deadline before any verdict (~33-41s vs 500ms); siblings that skip the join stay on the floor.

Co-authored-by: Cursor <cursoragent@cursor.com>

* State EmittedRustFnSignature as a §3b middle-value divergence with a technical reason.

The fork of emit_func_params remains real and named; the reason (registry-grain consumer
surface without coupling this instrument to emit_rust/#10688) admits it without an in-diff
approval claim. Document the resource-arm source drift the tip reviews measured.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop PLANTED_CONTROL enrollment and its censored cost-debt follow-on.

Those four #10706 absences are a next-rung-trigger population owned by #10704
(NEXT_RUNG_TRIGGER_CITATIONS), not planted controls; enrolling them here forked
the roster meaning and armed a red on capability success. Restore the empty-roster
climb comment. Instrument projection work is untouched.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Rename registry projection off emitted_* to ResolvedRustFn*.

The rows are filled from item_registry before emit_resolved_for_target; keeping
an emitted_* carrier name was a §3 meaning fork. Helpers and FixtureCompileCompleted
field follow. Parallel emit_func_params walk stays the named next-rung, not this rename.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Rename projection witnesses off emitted_* to match ResolvedRustFn* carrier.

Module paths and filenames were still test.claim.emitted_rust_fn_*; that
reintroduced the §3 meaning fork the carrier rename removed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update module lines and citations after resolved_rust_fn_* witness rename.

The prior commit moved the files; this aligns module paths, test names, and the
instrument's discriminating-RED citation with the ResolvedRustFn* carrier.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Refuse bare-name registry collisions in resolved_rust_functions projection.

Walk per TypedModule.item_registry instead of the bare-name-merged graph
registry, overlay expanded service names when the module still owns the row,
and require Found before asserting a parameter is absent so Absent cannot green REDs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Keep per-module resolved_rust_fn rows across bare-name reuse.

Review 61777: aborting the instrument on cross-module bare-name collision turns legal multi-module programs (and subjects that should CompileRefuse) into InstrumentRefused. Rows stay keyed by (owner_module, declaration_name); overlay the merged registry only when it still names this module.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Move witness match-arm annotations to module-item grain.

Floor parse refuses body-level //; the Absent≠lacks-parameter notes belong above the enclosing fns.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Omit colliding bare-name rows from resolved_rust_functions.

Review 61828: falling back to the un-expanded TypedModule ItemInfo on a merge loser silently drops propagated service_names while emit_func_def still binds the survivor's via bare-name lookup. Omit every Fn/Func row whose bare name appears in more than one module — lookup Absent, not InstrumentRefused, not a wrong signature.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Follow #10724 witness rename in floor_cost_debt enrollment.

CI merge hit stale_cost_debt: the apply_script_* identity was renamed on main while the roster still enrolled the old spelling.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Note #10724 rename beside the floor_cost_debt measurement comment.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
briansrls pushed a commit that referenced this pull request Sep 8, 2026
…e callee cannot be named (#10688)

* Key service effect propagation on callee identity, and refuse when the callee cannot be named

Effect propagation joined callee summaries on the AUTHORED NAME. Two modules
declaring the same name produced one edge key, so their effect summaries merged
and a caller could be told it depends on a service its actual callee never
touches. Rust emission compounded it by rebuilding a module-qualified overlay
from PRE-EXPANSION per-module registries -- the right declaration carrying stale
effects -- while Go and Python keyed off the authored call spelling. Three
consumers, three keys, one map.

The cut is at the root: one identity key space (owner module path + declaration
name), the overlay and its merge deleted, and the leaf-keyed accessor replaced by
lookup_item_by_identity. Consumers that legitimately hold only a leaf complete it
through an owner index whose ambiguity sentinel makes them refuse rather than take
whichever module folded last.

Keying on identity means a callee that cannot be NAMED can no longer be silently
joined, so the analysis is now total: ServiceEffectAnalysis is EffectsComplete or
EffectsIncomplete with typed causes, and the registry is reachable only through
the complete arm. An exhausted expansion budget is one such cause -- it used to
return an ordinary registry, indistinguishable from a fixed point, so callers
above the cut emitted without the service parameter their callees required and
the emitted Rust carried an unrealized-host-seam panic where a working call
belonged. That is the absorbing fallback DESIGN section 5 forbids.

Establishing the callee identity needed one repair upstream. main's
CallTargetOutcome partitions the direct-call decision so the producer decides once
and consumers read the constructor. But func_sig_from_global_bare admits a
borrowed census declaration only when it can also produce a RETURN TYPE, evidenced
by `params > 0 || inferred != none || type_annotation != none`, and a nullary
census node carries none of the three -- so the signature lookup went silent about
a callee the census names perfectly well, and CallableUnresolved inherited that
silence. Identity does not depend on the return type. That state now has its own
constructor:

  DeclaredCallableIdentityResolved { declared, borrowed_declaration }

built in call_target_for_direct_call at the point that would otherwise construct
CallableUnresolved. It carries the OBSERVATION, not just the answer: the typing
seam below reached global_bare_callable_node(type_env, name: func_name) -- a
second census query keyed on the spelling -- so identity and type could be
answered by two lookups that can disagree. That arm now dereferences the node the
producer already had. The superseded resolved_plain_call_target and
builtin_call_target_or_undetermined are deleted; all nine direct-call sites
consume the outcome projection.

EVIDENCE, on this exact tree:

  Mutation A/B, one variable (the producer's census arm reverts to constructing
  CallableUnresolved), same corpus, same build path:

    mutant     45 callee-identity + 1 budget + 24 pre-existing = 70 blocking
    candidate   1 callee-identity + 1 budget + 24 pre-existing = 26 blocking

  The budget and pre-existing counts are invariant, which is the control that the
  mutation moved only its own class. The surviving callee-identity refusal is
  `join` in srv3_websocat_sequence_witness, whose file already carries a
  pre-existing "function 'join' not found in scope" -- the analysis correctly
  declines to vouch for a summary over a call that does not resolve.

  Candidate versus unmodified main, diagnostic IDENTITY sets (a different grain
  from the occurrence counts above, and reported separately):

    common 24, candidate-only 2 (the A5 budget wall and the join consequence),
    base-only 1

KNOWN OPEN, not claimed by this change: the two A4 discriminators (wrong-owner
homonym, right-owner/stale-effects) have no witness yet; the A5 witness's red is
satisfied by any blocking diagnostic rather than by the budget cause specifically,
which needs the incompleteness causes to carry their own diagnostic classes; and
expand_transitive_services_once still answers a resolved callee whose registry row
is absent, and a call through a function value, with the empty list. A prototype
of that last refusal surfaced 13 real sites -- all intra-module, all
resolved-identity-with-absent-row, zero function-value -- which is a genuine
registry gap and its own change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Derive the effect-expansion bound instead of choosing one

The pass budget was the literal 5, and the first repair in this branch made an
exhausted budget REFUSE rather than return a registry indistinguishable from a
fixed point. That replaced a silent truncation with a loud one; it did not remove
the truncation. CI proved the difference: the live corpus is deeper than five, so
the refusal blocked generated_artifact_emit, floor_diff_observe and heal -- three
red lanes, one cause.

Five was a guess about how deep a call chain gets, and the loop already checks
CONVERGENCE before it checks the budget, so the budget never made this terminate.
It only decided when to stop early. Termination does not need a guess: each
non-converging pass strictly increases total_service_count, because
expand_transitive_services_once only ever adds names to an item's set, and that
total is bounded above by (item count x distinct service count) since each set
holds distinct names from a fixed alphabet. expansion_pass_bound returns that
product, which cannot be reached before the ascent has already stopped growing.
The budget becomes a termination guard over a monotone lattice ascent rather than
a cut across the answer.

ExpansionBudgetExhausted stays, and stays blocking. The argument above says it
cannot fire, but it is a proof about the registries today's producers hand in, not
a property of the type, and deleting it would make a violated invariant silent.

  main_wet                exit 0 (was: refused with the budget cause)
  corpus blocking         25 = 1 callee-identity + 0 budget + 24 pre-existing
  bootstrap               rounds 2, 3, 4 first_generation_equal=true
  fmt / clippy            0 / 0

THE WITNESS FLIPS RATHER THAN RETIRES. There is no longer a depth at which the
budget cuts, so the old red is unauthorable; per DESIGN section 4b(4) the probe
becomes a permanent regression control. That it still discriminates is executed,
not asserted -- with expansion_pass_bound mutated to return 5:

  chain_deeper_than_any_chosen_pass_count_still_converges   PASS -> FAIL
  chain_within_a_single_pass_still_emits                    PASS -> PASS

the positive control holding green in both arms, which is what rules out a
mutation that simply breaks everything.

ITS CEILING, RECORDED BECAUSE IT IS NOT OBVIOUS: neither control establishes that
the service reached the TOP of the chain. compile_fixture returns emitted file
names and diagnostic census rows, not emitted contents, and the original defect
COMPLETED -- emitting an unrealized-host-seam panic with no diagnostic -- so it
would satisfy `completed` exactly as the repair does. These controls discriminate
the refusing and truncating-at-a-chosen-depth behaviours and nothing more. The
next-rung trigger is a fixture instrument that can assert over emitted content.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Make EffectsComplete honest, and stop naming the importer as a callee's owner

THE PRIMARY RESULT WAS FOUND, NOT CONSTRUCTED. dag/std/observation.dag CALLS
fold_list without importing it, at three call sites. A bare free call resolves
against the corpus-wide declaration census, so it type-checked for however long
it has been there -- but the declaring module never entered the compiled
population, so no registry row existed, the join found nothing, and that
module's effect summary silently omitted whatever fold_list does. It was caught
by the new blocking arm on live code that nobody authored to be found.

THE OWNERSHIP REPAIR, PROVEN BY EXECUTION. func_sig_from_global_bare consulted
the module type environment and stamped THAT module as the callee's owner. An
import is precisely a name placed into the importing module's environment, so
every imported callable was identified as owned by its importer, addressing a
registry key that cannot exist. Discriminating control on the live corpus:
13 wrong-owner refusals with the defect restored, 0 repaired, naming the
mechanism rather than a count -- v1.compiler.parse.parse_expr_loop calls
v1.compiler.parse.make_file_span, which v1.std.core declares. The reading of
each outcome was written down before the run was read, including that a zero
would NOT have confirmed anything.

Claim grain: the OWNERSHIP REPAIR is proven, at identity grain. Not that the
effect analysis is correct.

EffectsComplete NO LONGER OUTRUNS WHAT THE ANALYSIS KNOWS. Two silent `[]` arms
inside the propagation fold became represented causes.
ResolvedCalleeRegistryRowAbsent BLOCKS -- it is the arm that found the
observation defect. EffectSummaryIncompleteAtFunctionValue is ADVISORY, its own
diagnostic variant rather than a blocking InternalError: measured at 45 sites,
every one correct code, because a function-typed PARAMETER's effects belong to
whoever supplies the argument. Its next-rung trigger is a capability, effect
polymorphism over function-typed parameters. What the completeness LABEL gates
today is nothing, and that is written at the type rather than only in review.

THE DEDUP-KEY DEFECT UNDERNEATH IT. FunctionValueCallee carried key "" and the
collector DROPS empty-key edges, so every higher-order call site was deleted
before any reader existed and the population read as a measured zero. Giving the
edge a key turned the same measurement into 45. PrimitiveCallee also keys empty
and there the drop is CORRECT -- an absence that is an answer and an absence
that is a gap shared one encoding, one line apart.

TWO FIXTURES DELETED RATHER THAN ENROLLED. An explicit-import version and a
bare-call version both PASSED with the defect restored. A permanently-green
witness is worse than absent because it gets cited as coverage.

THE ORDERING LESSON, A NEAR MISS. Landing the blocking arm before verifying how
the identity was DERIVED would have refused 13 CORRECT programs, and those
refusals would have been read as findings about the registry producer. A
blocking arm must not be landed over an identity whose derivation has not itself
been verified.

Rows filed: resolution_scope_conflated_with_ownership_scope and
empty_grouping_key_silently_deletes_its_population.

STATED CEILING: neither witness establishes that a propagated service reaches
the TOP of a chain in the EMITTED artifact -- compile_fixture returns file names
and diagnostic census rows, no contents, so the original defect completed with
no diagnostic at all. #10709 is the instrument; the ceiling is written into the
witness file and the discriminator follows once it lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* A local binding is not an unestablished callee, and one producer for the leaf index

THE CI RED WAS MINE AND IT WAS A FALSE REFUSAL. required-witnesses-floor went red
on two v2.test.claim.local_binding_shadow fixtures: `let shadow_sentinel =
local_sentinel` then `shadow_sentinel(1)`, reported as "no established callee
identity". That callee IS established -- the resolver produces LocallyBoundCallee
-- and `resolved_plain_call_target_for_outcome` collapsed it to
CallableTargetUndetermined one seam below. The same fork this PR is about, at the
next level up, refusing a correct program.

CallTargetIdentity now carries LocallyBoundCall, and a locally bound callee gets
its own edge and its own advisory cause. The two are not one fact: an unresolved
SPELLING names nothing and must BLOCK; a local binding names something whose
effects this pass cannot join through the registry, which is the function-value
situation and is reported the same way. It gets its own diagnostic variant rather
than sharing the function-value one, because a census keyed on diagnostic name
would otherwise group two mechanisms -- the failure this repository files as
diagnostic_name_mechanism_silent.

REVIEW FINDING 1, TWO PRODUCERS OF ONE FACT -- CONFIRMED AND CUT AT THE ROOT.
`item_leaf_owner_modules` was built by `build_item_leaf_owner_modules` from a
module list and then OVERWRITTEN twice from the registry, two sources that can
disagree, with the annotations contradicting each other. The registry-derived one
is the one the PR's reasoning defends, so it is the one that survives:
`leaf_owner_modules_from_registry` moves to v1.compiler.infer_items -- the layer
both consumers can see, since v1.compiler.infer_emit_info cannot name ItemInfo
without closing an import cycle it already documents -- `build_emit_graph_info`
takes the registry, and the module-list producer and both overwrites are gone.
One producer, including through the seed's own hand-written resolve path.

REVIEW FINDING 2, A GUESS WEARING AN ANNOTATION -- CONFIRMED AND MADE TYPED.
`definer_module_for_name` answered an ambiguous bare leaf with
`.values().find(...)` -- first row wins, silently, for exactly the question the
.dag side refuses. The reviewer's sharp point is that the annotation calling it a
guess made it visible to a READER and not to a CONSUMER. It now returns a typed
DefinerLookup with a distinct AmbiguousLeaf state, the census carries an
AmbiguousLeaf binding source (its own variant in
gunbc.compile_clean_diagnostic_policy, because "nothing declares this name" and
"several do" are different facts), and `symbol_resolves_for_name` is separate
because whether a symbol RESOLVES and whether its definer can be NAMED are two
questions an ambiguous leaf answers differently.

The test-scope call observer in declaration_index.rs gets LocallyBoundTarget for
the same reason: that observer exists to detect the undetermined-collapse, so
folding a named target into TargetUndetermined would defeat it.

Verified: whole-corpus regen at a fixed point with zero hard diagnostics and zero
blocking effect causes, the shadow fixtures no longer reporting an unestablished
callee, cargo fmt clean, and cargo clippy --all-targets -D warnings clean -- which
is what caught the test-target arm, since nothing else compiles that target.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Read the leaf index instead of rescanning it, and measure every hand-Rust file the diff touches

REVIEW 61647, FINDING 1: A SCAN WHERE A MODELLED INDEX ALREADY EXISTS. The first
repair of the ambiguous-leaf guess answered by walking `item_registry.values()`.
It was correct and it was expensive: `classify_unlisted_import_binding_source`
scanned twice per call and its callers twice more, so roughly four full registry
passes rode on every unlisted-import census row, over a census of thousands. That
is the DESIGN section 6 cost-shape defect that is always fixed regardless of the
realized n -- and worse, a section 2 re-invention, because the leaf-to-owner index
it re-derived is `leaf_owner_modules_from_registry`, which THIS SAME CHANGE makes
the single producer of. It now reads that index off
`ResolvedGraph.emit_graph_info`: one map lookup, and being the same authority the
emitted path reads, it cannot disagree with it. The empty owner is that index's
own ambiguity marker, so ambiguity falls out by construction rather than by a
second check here.

REVIEW 61647, FINDING 2: A CENSUS OVER THE WRONG POPULATION, IN THE RECEIPT WHOSE
SUBJECT IS THAT UNVERIFIABLE FIGURES ROT. The SEVENTH LANE paragraph certified
the hand-Rust carrier census as FLAT having measured only compile_clean.rs, while
the diff also grew cli_run.rs -- so it omitted the one file that moved. It now
measures all three hand-Rust files the diff touches, states that the census is NOT
flat, and explains why the added-`fn`-line count reads 3 while the census moves by
2: `definer_module_for_name` existed at base and was rewritten, so it is an added
line and not an added declaration.

FOUR STALE CITATIONS, MINE, FROM MY OWN DELETION. The declarations phase refused
`build_qualified_item_registry` and the two duplicate-marker symbols in
gunbc.bare_name_identity_consumer_census and
gunbc.emit_summary_map_consumer_partition. Those rows documented the qualified
overlay as the good CONTRAST, and this PR deleted that overlay for being a second
key space. The rows are rewritten rather than repointed, because the contrast
survives its subject: the registry is keyed on declaration identity at
construction, so the homonym cannot arise from the key, and what remains is the
reverse question answered by one owner index whose ambiguous entries refuse.

`AmbiguousLeaf` also owed an arm in the step0 calibration witness, which matches
the binding-source coproduct exhaustively.

AND ONE TEST PREDICATE TIGHTENED, FLAGGED BECAUSE IT TURNS A RED GREEN.
`local_binding_shadow_compile.compiles_clean` read `count(rows) == 0` -- every
row, advisory included. The file's own annotation states the intent: an assertion
about a program the compiler REFUSES would be no verdict. An advisory row refuses
nothing, so the predicate answered a different question from the one its consumers
ask and was sensitive to any new advisory anywhere. It now counts BLOCKING rows.
The discrimination is unchanged and that is the test of a tightening: refusal
still fails through both arms, a blocking diagnostic still fails, and the sibling
control's declaration-labeled arm has no local binding so it carries no advisory
either way. Both witnesses execute green.

Verified on this tree: witnesses lane declarations findings 0, floor claims_failed
0, whole-corpus regen at a fixed point with zero hard diagnostics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md resolution_scope_conflated_with_ownership_scope
Ledger-Rows-Repaired: docs/design-failure-modes.md empty_grouping_key_silently_deletes_its_population
Ledger-Repair-Judged: docs/design-rung-drops.md

* Ask the owning module for a leaf, at the last two emission sites that still asked the corpus

REVIEW 61748, BOTH FINDINGS, AND THEY ARE THE TWO CLASSES THIS SAME CHANGE FILES,
REINTRODUCED ON ITS OWN CHANGED LINES. When the registry moved from a leaf key to
`DeclaredCallableIdentity`, two `map_get(registry, leaf)` sites in
`v1.compiler.emit_rust` were translated into `lookup_item_by_leaf` -- the
corpus-wide index -- rather than into the identity question, and each disposed of
the resulting `ItemLeafAmbiguous` with a silent empty answer. That is
`resolution_scope_conflated_with_ownership_scope` (resolution scope widened to the
whole corpus while ownership was never asked) and
`empty_grouping_key_silently_deletes_its_population` (an absence that is an answer
and an absence that is a gap sharing one encoding), and DESIGN section 5 names the
arm directly: a failure arm must refuse, never widen.

FIRST SITE, `all_svc_names` IN `emit_module_full`. The items being folded are
`typed_module.items` -- declarations this module itself authors -- so ownership
was never in question, and the module's own authored name is already in hand one
line above where `this_mod_filename` reads it. A leaf this module declares that
any other module in the closure also declares came back ambiguous and lost that
item's `service_names`, so the `use crate::<mod>::<Service>;` line was never
emitted and the generated Rust named a service it had not imported. It now asks
`lookup_item_by_identity` with this module as the owner, which is exactly how
`05_emit_go` and `05_emit_python` ask the same question.

SECOND SITE, `emit_import_name`. `is_data` decides whether the emitted spelling is
snake_cased, so a wrong answer emits an identifier that does not exist. Every one
of its five callers already knows which module the `use` line names, and threading
that identity does more than fix the ambiguity: it collapses the two silent
`false` arms into one honest `Absent`, which now means this identity declares
nothing and therefore is not a data item. Two callers pass the provider module,
one passes `info.module_name`, and the two inside `emit_specific_import_block`
needed the PATH the line resolves to rather than its filename -- so
`graph_type_import_module_path` sits beside the existing
`graph_type_import_module_filename` and reads the same re-export resolution, which
is why the two cannot disagree about who owns the name.
`qualified_type_reference_use_lines` gives back the `emit_info` parameter it only
needed for the leaf index.

TWO NAMESPACE ADMISSIONS FOR THE `call_semantics_target` RE-HOME. Moving that
reduction from `v1.compiler.emit_rust` to `v1.std.core`, beside the `CallSemantics`
it destructures and the `CallTargetIdentity` it answers, reports `TargetChanged` at
its two emit-side binding sites. Enumerated one row per site rather than matched by
module pattern, because the roster's population is an enumeration and never a
predicate.

AND THE ROSTER'S OWN CLAIM RESTORED WHILE ADDING TO IT.
`gunbc.namespace.namespace_wave_admission` states that every declaration in that
module is enumerated in `hand_authored_declarations`, and it was already false:
`SCM_REPOSITORY_BUILDER_REHOME_LABEL` landed with gunbc#10676 and was never
listed. Enumerating only the constant this change adds would have left the claim
false and blamed it on the previous author, so both are listed and the reason
records why -- the same authored-obligation-not-derived-denominator warning that
row already quotes, firing a second time on its own file.

Verified on this tree: whole-corpus regen at `first_generation_equal=true`,
`main_wet=0` with the failure-mode projection byte-identical to the healed head,
namespace-wave-admission green with both new rows reported ADMITTED-BY.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Make the ambiguous leaf a coproduct arm, and stop one reader guessing a module for it

REVIEW 61778, BOTH FINDINGS. The leaf-to-owner index this change introduces
encoded "two modules declare this leaf" IN BAND, as the empty string in a
`Map<String, String>`, on the argument that no declaration has an empty module
path so every consumer would miss and refuse. That is the argument this same diff
retires twenty lines earlier: `__DUPLICATE_ITEM_IDENTITY__` was deleted because
the illegal state stayed representable and safety depended on every producer
remembering to mint the tag and every reader remembering to test for it. The new
index reproduced it with a different sentinel, and it had FOUR readers who each
had to remember -- `lookup_item_by_leaf`, `alias_rhs_base_module_filename`,
`item_defining_module_filename`, and `definer_lookup_for_name` in the seed. One of
them documented the marker as landing "by construction rather than by a second
check here" on the line directly above the second check.

THE CONSTRUCTION WAS AVAILABLE AND IS NOW TAKEN. `v1.std.core` declares
`LeafOwner = SingleOwner { module } | LeafAmbiguous`, the index carries it, and all
four emptiness tests become exhaustiveness arms the compiler demands. The producer
cannot forget to mark ambiguity because there is no other way to write it, and a
reader that would widen has to write the widening down where a reviewer sees it.
DESIGN section 5: correctness by construction, not validation.

AND ONE READER WAS INDEED WIDENING, WHICH IS WHAT SPLITTING THE ARM EXPOSES.
`item_defining_module_filename` answered the sentinel with `fallback` -- the
CALLER'S OWN MODULE, at three call sites -- so a leaf whose owner is genuinely
unnameable got a plausible defining module substituted and emission proceeded,
while its two sibling readers correctly surfaced `ItemLeafAmbiguous` /
`AmbiguousLeaf`. One fact, four readers, one guessing. `Absent` and `LeafAmbiguous`
are now different arms: `Absent` means no module declares this leaf and the
caller's own module remains the right reading for a name the index never heard of,
which is the pre-existing behaviour and is untouched; `LeafAmbiguous` renders
`ambiguous_leaf_module_refusal`, a path no crate can resolve that names the leaf,
so rustc stops on it.

THAT LAST ARM IS MITIGATION AND THE ANNOTATION SAYS SO RATHER THAN CLAIMING A
RUNG. A `use` line's position takes a module path and there is no diagnostic row
reachable from it, so the refusal lands in the emitted crate rather than in the
compiler that held the fact -- the wrong compiler and the wrong phase. The
precedent for rendering a refusal in the only channel a target admits is
`05_emit_python`, which does the same where there is no `compile_error!`.
NEXT-RUNG TRIGGER, a capability: a diagnostic channel through the
reference-derived import planner, which already carries `CandidateLeafAmbiguous`
for this same fact one layer above.

THE NINE gunbc#10676 ADMISSIONS DISSOLVED HERE, BY THEIR OWN TRIGGER. Those rows
said they die when gunbc#10676 merges and come due on this roster's next touch;
gunbc#10676 has merged, the run reports all nine CONSUMED, and admitting the
`call_semantics_target` re-home is that touch -- so the phase refused until the
deletion was taken. Adjudicated by the per-spelling declaration join those rows
demanded rather than by their own sentence: `test.fixture.scm_repository_builder`
declares all eight spellings, `test.claim.scm_merge_base_witness` declares none of
them and imports all eight, so base and head bind each identically and no run can
produce those deltas. Their label constant went with them, which is why the hand
declaration roster gains one and is net flat.

A NOTE ON THE PREVIOUS COMMIT, BECAUSE ITS MESSAGE CLAIMED SOMETHING ITS BYTES DID
NOT CARRY. It reported the two `call_semantics_target` admissions verified green,
which they were when measured -- but the regen candidate carries a stale copy of
the hand-authored mirror files, and installing it reverted both those rows AND the
nine gunbc#10676 rows that predated this branch. The commit recorded a net -118
lines in that file and I read the message rather than the diff. The rows are
restored from origin/main and re-applied here, and the local regen loop now
excludes that file by name alongside `cli_run.rs` and `v1_interpreter.rs`.

Verified on this tree: whole-corpus regen at `first_generation_equal=true` across
two consecutive rounds, `main_wet=0`, and the witnesses lane's
namespace-wave-admission phase GREEN -- 0 unadjudicated, 0 stale, 0 consumed due.
The two failures that remain are `declarations` (7 CITED-DECLARATION-ABSENT, all in
`src/v2/lens/*` and `outside_modeled_guarantee_witness_test`, none in a file this
branch touches, present on origin/main from #10706 with the repair on #10704) and
`floor` (verdict FloorRefused with claims_failed=0, refused only by three
INTERRUPTED-BEFORE-VERDICT rows on cpu_deadline, all three claims of that same
#10706 module).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md resolution_scope_conflated_with_ownership_scope
Ledger-Rows-Repaired: docs/design-failure-modes.md empty_grouping_key_silently_deletes_its_population
Ledger-Repair-Judged: docs/design-rung-drops.md

* Delete the sentence describing the sentinel this change removed

REVIEW 61893. The annotation on `leaf_owner_modules_from_registry` still opened
with "A leaf two modules declare gets the empty owner, which is not a legal module
path, so consumers refuse rather than taking whichever row was folded last", and
then immediately retired that encoding in the next sentence. The function no
longer produces an empty owner at all, so the annotation restated the declaration
and restated it WRONGLY -- describing the in-band sentinel whose deletion is this
change's whole argument. DESIGN section 4c: an annotation preserves why a
construction has its shape and must not restate what the declaration structurally
says.

The two sentences are now one that says the thing worth saying: what a consumer
cannot do. Regen re-run to a fixed point, which is also the check that an
annotation edit is one -- `first_generation_equal=true` with no surface drift, so
nothing semantic moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* File the class that made a green run report over bytes that had been reverted

A REGENERATION INSTALLS OVER A HAND-AUTHORED FILE AND REPORTS SUCCESS. The stage0
candidate tree carries EVERY mirror file, including the ones regeneration does not
author, so installing it wholesale reverts hand edits to those files while every
figure the run prints stays green.

RECEIPT, THIS PR. Two `NAMESPACE_TRANSITION_ADMISSIONS` rows were authored by
hand, the phase was run, and it reported both ADMITTED-BY. The install then
reverted that file to a state predating gunbc#10676 -- deleting the two new rows
AND the nine gunbc#10676 rows that had been on main for a day -- and the commit
landed asserting a green the bytes no longer carried. `git show --stat` on it read
23 insertions and 118 DELETIONS in a file the change was supposed to grow.

WHY IT SURVIVES REVIEW, and it is not inattention: the verification is real and is
taken at the wrong MOMENT. Build, run the phase, read green, install, commit --
the install sits between the evidence and the artifact, and nothing in the loop's
output names the file, because the producer never claimed to own it. The tell is
the absence of a tell.

Two recognition rules, and the second is the cheap one that does not require
knowing the mechanism: after any generate-and-install loop, read `git diff --stat`
for NEGATIVE line counts on files the change was supposed to grow.

CEILING 3, and the trigger is a capability rather than a longer exclusion list:
the generator already adjudicates its output file by file, so an install whose
population is that adjudication roster cannot touch a file the generator did not
author. What this lane actually did was add a file NAME to a local exclusion list,
which is the maintained-roster shape this repository files against elsewhere and
is wrong for the same reason -- the next hand-authored mirror file is reverted
until someone remembers. The row says so rather than claiming the class repaired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Delete a dangling declaration and three annotations describing a sentinel that no longer exists

REVIEW 61919, BOTH FINDINGS.

FIRST, PROSE ASSERTING THE OPPOSITE OF THE IMPLEMENTED REFUSAL. Three annotation
paragraphs had stacked above `item_lookup_of_optional`, and two of them described
the encoding this change DELETES -- "names the empty string when two modules claim
the leaf ... so the ambiguous case resolves to Absent and the caller refuses", and
"A leaf two modules declare maps to the empty owner, which is not a legal module
path, so it lands in Absent". Both are false on this head:
`leaf_owner_modules_from_registry` produces `LeafAmbiguous` and
`lookup_item_by_leaf` yields `ItemLeafAmbiguous`, which is the whole argument of
the PR they sit inside. The first block also duplicated the second nearly verbatim.
DESIGN section 4c: an annotation must not restate what the declaration
structurally says, and restating it WRONGLY is the strongest form of that. The
earlier commit that deleted one such sentence caught one site and missed these --
which is the same one-site repair this PR files a class about.

They are deleted rather than corrected, because the fact they reached for belongs
to `lookup_item_by_leaf` one declaration below and is already stated there. What
replaces them says the thing that is not derivable from three lines of code: that
this function is the projection and not the policy, and that an ambiguous leaf
never reaches it. The construction-wall paragraph above is kept, accurate, and now
attached rather than orphaned by the blank line the deleted function left behind.
The history note on `lookup_item_for_value_ref` also spoke of the empty-string
owner in the PRESENT tense and now speaks of it in the past, with the sentence
that it can no longer be written at all.

SECOND, A DANGLING DECLARATION. `value_ref_registry_lookup_key` was the
key-computation for the old `lookup_item_for_value_ref`, which this diff rewrote to
compute qualifier and leaf inline. It has no call site -- only the definition and
its generated mirror -- so it is DESIGN section 3c's mechanical tell exactly:
a declaration with no consumer in the closure, which costs authoring, review and
maintenance and displaces nothing. Deleted; the mirror follows on regen.

AND THE SEVEN `exit_ok` ADMISSIONS DISSOLVED, BY THEIR OWN TRIGGER ON THIS TOUCH.
CI on the previous head reported them CONSUMED and due for deletion, because this
change touches the roster. Their trigger said exactly that would happen once the
relocation reached main. Adjudicated by the join those rows demanded rather than
by their sentence: `std.process` DECLARES `fn exit_ok`, `tools.ci_gates` carries no
occurrence of the spelling at all, and the single consumer
`gunbc.instruments.floor_effect_gate_witness` imports it from `std.process` and
uses it at the seven call sites those rows named. Rows and label deleted together,
so the hand declaration roster gains one constant and loses two.

Verified on this tree: regen at `first_generation_equal=true`, `main_wet=0`, and
the witnesses lane's namespace-wave-admission phase green -- 0 unadjudicated, 0
stale, 0 consumed due. CI's floor on the previous head was `verdict=FloorClean`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Import the type this change declares, in the three modules that use it

REVIEW 61956. `LeafOwner`, `SingleOwner` and `LeafAmbiguous` are declared in
`v1.std.core` by this change, and the three modules that consume them --
`v1.compiler.emit_rust`, `v1.compiler.infer_items`, `v1.compiler.infer_emit_info`
-- each carry an explicit named-import block from `v1.std.core` that did not list
them. They resolved by corpus-wide bare-name resolution instead.

THAT IS THE DEFECT THIS SAME DIFF REPAIRS ELSEWHERE, WHICH IS WHY IT IS WORTH MORE
THAN THREE LINES OF ATTENTION. `dag/std/observation.dag` gained an import in this
PR with the annotation that a bare free call resolves against the corpus-wide
declaration census, so it type-checks while the declaring module is never pulled
into the compiled population -- and that module's effect summary silently omitted
what the callee does. The pool risk is genuinely nil here, since all three modules
already import `v1.std.core`, so what is left is the census cost: a fresh
`UnlistedImportUse` population for a type introduced by the change whose thesis is
that a name must be resolved through its declaring authority rather than through
whatever the corpus happens to expose. `UnlistedImportBindingSource`, whose doc
this diff edits, calls `DefinerResolvable` the terminal shape every row must reach.

IMPORTED WHAT EACH MODULE USES AND NOT MORE: `infer_emit_info` names only the TYPE
on its `item_leaf_owner_modules` field, so it imports only `LeafOwner`; the other
two construct and match on both arms and import all three.

Verified: regen at `first_generation_equal=true`, `main_wet=0`, witnesses lane
parse and namespace-wave-admission green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Finish the sentinel deletion by sweeping the corpus instead of the reported line

REVIEW 62005, AND IT IS THE THIRD TIME THIS BRANCH HAS BEEN TOLD THE SAME THING.
`EmitGraphInfo`'s annotation still carried a truncated fragment of the deleted
sentence -- "A leaf claimed by more than one module maps to the empty string,
which is not" -- immediately contradicted by the line below it, which is my own
earlier edit having replaced the text without deleting the line it replaced. The
empty-string owner exists nowhere: `leaf_owner_modules_from_registry` produces
only `SingleOwner` and `LeafAmbiguous`. The neighbouring "carries the OWNER MODULE
PATH rather than the ItemInfo" was imprecise for the same reason and is fixed in
the same pass -- it carries a `LeafOwner`.

WHAT I ACTUALLY CHANGED THIS TIME IS THE METHOD, BECAUSE THREE PER-SITE REPAIRS IS
THE CLASS THIS PR FILES. Reviews 61893, 61919 and now 62005 each named a stale
sentinel sentence, and I fixed each reported line. That is a repair scoped to a
detector, inheriting its blind spots. So this one was done by grepping the corpus
for the phrases the deleted encoding could be spelled with -- "empty owner",
"empty string, which is not", "maps to the empty", "owner is the empty", "the
empty string when" -- across every `.dag` and `.rs` file, not just the diff. That
sweep returns exactly one remaining site in this change's subject, the one fixed
here. `05_emit_rust` line 2601 also matches and is CORRECT: it is the history note
that says the empty owner is gone, in the past tense, which is the one place the
phrase belongs.

Regen re-run to `first_generation_equal=true`, which is also the check that an
annotation edit is one: nothing semantic moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Freeze the seed-projection receipt row, so the seventh paragraph is the last one

REVIEW 62020 IS CORRECT AND IT IS ANSWERED HERE AS FOUND, NOT ARGUED AWAY.
`compiler_diagnostic_seed_projection_note` is a bare `String` carrying a receipt
plus commentary, which DESIGN section 4c calls misplaced data, and the compliant
carrier is a typed row. That defect is real. Six lanes had already written into
this row before my seventh, and that is not a defence -- it is the measurement of
how fast the surface grows, and accepting a seventh with no other change would
hand the eighth lane the same argument I made.

SO THE SECTION 3 FROZEN-X CARVE-OUT IS TAKEN EXPLICITLY, ON THE ROW ITSELF. It
stays, because it is production-critical and its replacement cannot land in a
change about effect identity, and it takes NO NEW INVESTMENT AND NO NEW ROWS ON
ITS GROWTH SURFACES. A lane needing to record a hand-Rust receipt from here files
it in the typed carrier the migration lands, and if that carrier does not exist
yet its obligation is to say so and wait rather than append here. That sentence is
what makes this a bounded exception with an owner instead of a precedent.

WHY NEITHER REPAIR ON OFFER WAS TAKEN, both refused for stated reasons rather than
for scope. Relocating the paragraph into a `//` annotation -- what the review
proposed -- would DELETE the receipt: `gunbc.plans.compile_clean_forcecheck` names
this row as the receipt's authority precisely because annotations are erased and
no `Accepted` program can read one, so a receipt moved into an annotation is a
receipt no projection can carry. And migrating the whole row inside this PR is the
opportunistic version of a replacement migration, which section 3 requires be cut
at the ROOT with a disposition census rather than wherever a reviewer notices the
defect -- the carrier is declared here, mirrored into the seed as
`v1_std_core::compiler_diagnostic_seed_projection_note`, and cited by a plan
projection.

THE LANE IS NAMED RATHER THAN DESCRIBED, which arrived while this was being
written: silent-otter-161 owns the migration into
`gunbc.compiler_diagnostic_seed_projection`, and it DELETES this data row rather
than shrinking it. So the freeze is not a holding pattern over a surface that
survives -- it is the no-new-rows rule over a surface with a scheduled death, and
it is retired when the row is gone and the freeze has no subject. The row also
enumerates what that lane must cover, so the migration is not scoped to the
paragraph that happened to be reviewed: the typed carrier, all seven lane
receipts, the seed mirror, and the plan projection's citation, which must name the
new authority or it becomes the stale-citation class this row's own text is about.

Regen re-run to `first_generation_equal=true` and `main_wet=0`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Say the refusal is unexercised, because nothing will ever refute the sentence that said otherwise

THE ANNOTATION ON `ambiguous_leaf_module_refusal` SAID "the refusal is real".
Nothing executes it: no witness in the corpus reaches `ItemLeafAmbiguous` or the
`LeafAmbiguous` arm, and the one census witness over the dispositions above --
which this same PR touches -- passes an EMPTY leaf-owner index at every site, so
it cannot reach ambiguity by construction. The arm very likely fires on the live
corpus, since a homonym leaf across four thousand modules is likely, but likely is
not a receipt.

WHY THIS IS PUSHED BEFORE MERGE RATHER THAN CARRIED INTO THE FOLLOW-UP, and the
reason is not tidiness. This corpus rosters the class already, with a worse
receipt than mine: `subject_and_its_digest_as_independent_parameters`, whose third
face is PROSE ADJACENCY IS NOT A JOIN -- an annotation stating that two per-identity
classes were waived, three lines above a body that waived four, in the same
function, read past by four approvals. Its conclusion is the argument here. An
annotation reads as documentation and FUNCTIONS as an assertion, and by section 4c
no `Accepted` program can ever disagree with one. A wrong annotation is therefore
the single kind of claim in this repository that nothing downstream will refute
for you, which makes "fix it in the follow-up" a different bet from what it sounds
like.

THE ROW IS NOW HONEST AT BOTH GRAINS, because the two claims have different
evidence and were sharing one sentence. The CONSTRUCTION claim needs no execution
and is made without one: `LeafOwner` gives ambiguity its own arm, so the
empty-string owner is unwritable and no reader reaches an owner without writing the
arm that says there is none -- a property of the type. The BEHAVIOURAL claim, that
this rendering stops a build, is an argument about the emitted path and is now
labelled as unexercised.

AND THE TRIGGER IS NAMED AS A THING THAT CAN BE BUILT TODAY, which is what makes
this section 4b(2) rather than an untracked stall:
`tools.multi_module_compile_fixture` compiles authored sources, and
`v2.test.claim.local_binding_shadow_compile` -- this branch's own witness --
already uses it to make two modules declare one spelling. So the RED is expressible
in a fixture even though an ambiguous leaf is not authorable in the ACCEPTED
corpus, and declining to write it would be specification-without-execution by
section 4b's own test. It lands next as its own witness rather than as a change to
this wall.

The pre-existing ceiling is unchanged and restated where it belongs: this rendering
stays MITIGATION even once exercised, because the refusal lands in the emitted
crate rather than in the compiler that held the fact.

Annotation-only. Regen re-run to `first_generation_equal=true`, which is also the
check that it is annotation-only: nothing semantic moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Call the cause-to-diagnostic mapping instead of hand-copying it into the seed

REVIEW 62156, AND IT IS CORRECT. `finish_resolved_graph_assembly` in the seed
hand-copied the five-arm `EffectIncompleteness` match from
`v1.compiler.infer` `typecheck_with_census_extra` -- three of the message strings
VERBATIM -- under a comment that admitted it ("Mirrors typecheck_with_census_extra").
Two sources for one fact is DESIGN section 2's forked-logic trap and section 3's
authority fork, and the failure it buys is the silent kind: a message edited on one
side, or a sixth arm added on one side and defaulted on the other, disagrees with
nothing that would refuse.

THE CONSTRUCTION WAS AVAILABLE, WHICH IS WHAT MAKES DEFERRING IT WRONG. The
mapping is a pure fold over a coproduct with no host effect, and
`expand_transitive_services` is already consumed by the seed through its generated
projection -- so `effect_incompleteness_diagnostics` is now one `.dag` declaration
in `v1.compiler.infer`, `typecheck_with_census_extra` calls it, and the seed calls
its generated mirror. The two paths are now incapable of disagreeing, and a sixth
arm is a compile error on both rather than a default on one. What stays mirrored in
the seed is only the SHAPE of the unwrap: the registry reachable through the
complete arm alone, causes carried onto the graph's diagnostics.

AND THE RECEIPT IS RE-MEASURED, BECAUSE THIS REPAIR MOVES THE FIGURES IT CERTIFIES.
Review 62156 also noted the seventh-lane receipt certified 145/14 of `cli_run.rs`
growth while justifying only three declarations -- the copied block was the bulk of
those lines and no part of the receipt's argument. It now reads 108/15 against base
1e51ea99bb, and the row records BOTH moves rather than overwriting them: the base
moved because this branch merged main (a stable base is stable for a branch, not
across a merge -- the moving-ref defect an earlier lane repaired once already), and
the added lines fell by roughly thirty-seven because the fork was extracted.

THE READING THAT MATTERS IS THAT (a) DID NOT MOVE: the declaration census is 643 ->
645 before and after, because the copied block lived inside an existing function.
It was never added hand-Rust CAPABILITY, and (b) alone would have reported a shrink
that (a) shows was never a growth in declarations. That is the third time this
receipt's own subject -- a figure that rots when nobody re-derives it -- has fired
on the receipt itself.

This does not violate the freeze declared one commit earlier: no row is added and
no new investment is made. An existing paragraph's figures are re-derived because
this same change invalidated them, which is the freeze's whole point rather than an
exception to it.

Verified: regen at `first_generation_equal=true` across two rounds, `main_wet=0`,
witnesses lane parse and namespace-wave-admission green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* State where the freeze begins, since a rule falsified by its own diff is not a rule

REVIEW 62213 IS RIGHT ABOUT THE INCOHERENCE. The freeze text said the row "takes
NO NEW INVESTMENT AND NO NEW ROWS ON ITS GROWTH SURFACES" while the same commit
added a row to it. Read as a present-tense property that is simply false, and a
rule the diff declaring it falsifies is not a rule -- it is the shape section 6
names when it says adding a trigger after review makes a proposal eligible for a
decision rather than resolving the objection.

THE BOUNDARY IS NOW WRITTEN DOWN INSTEAD OF IMPLIED: the seventh paragraph is the
last one ADMITTED, and the freeze binds every lane after it. A freeze has to begin
somewhere, and where it begins is a fact, not something a reader should have to
infer from which commit the sentence arrived in.

AND THE ADMISSION IS ATTRIBUTED, WHICH IS THE PART SECTION 5 REQUIRES BE EXTERNAL
TO THE DIFF: an author who can write an exception can equally write a row claiming
one was granted. The seventh was admitted by merry-bear-25's ruling of 2026-09-07,
on the explicit condition that the freeze be declared in the same change so the
eighth lane cannot reuse the seventh's argument -- which is exactly what review
62213 was testing for and would otherwise have been my own say-so.

WHAT I DID NOT DO, and it is the review's proposed repair, so it is owed an answer
rather than silence: drop the paragraph and carry the receipt in the PR body. A PR
body is not in the repository. Six lanes' receipts live in this row and
`gunbc.plans.compile_clean_forcecheck` names it as the receipt's authority, so
putting the seventh somewhere the tree cannot read would not move the receipt to a
better carrier -- it would delete it from the corpus while the hand-Rust growth it
certifies stays. That is a worse outcome than a bounded, attributed, last-admitted
row, and it is also a decision above my authority: the ruling that admitted the
paragraph considered keeping it, migrating the whole row, and relocating the
paragraph, and this is a fourth option raised after it. I have put it back to the
operator rather than overriding a ruling by acting on a later review.

Annotation-only; regen at `first_generation_equal=true` and `main_wet=0`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Re-derive the mirror and the projection from the merged sources

THE MERGE LEFT THREE GENERATED FILES DESCRIBING A TREE THAT NO LONGER EXISTED, and
each needed deriving rather than resolving.

`v1_compiler_emit_rust.rs` was taken from main whole, so the seed still called
`lookup_item` -- the leaf-keyed lookup this branch deletes -- and would not compile.
The escape is that the mirror is DERIVED: the pre-merge binary still matched this
branch's `.dag`, so it regenerated the mirror before the toolchain could be
rebuilt, and the loop then iterated to `first_generation_equal=true` over four
rounds. That fixed point is the real check here: a mirror that agrees with the
merged sources under its own regeneration cannot be half of each side.

One casualty of using the pre-merge binary is recorded because it is the same
stale-candidate class this branch already filed: `std_realization_schedule.rs` came
back in an older shape, since my compiler predated main's change to it and this
branch does not touch it. Restored from main rather than from the candidate.

`docs/design-failure-modes.md` is regenerated from the merged authorities, not
hand-merged. Verified in both directions at row identity: no row on main's side is
dark, and this branch's own three rows -- `empty_grouping_key_silently_deletes_its_population`,
`resolution_scope_conflated_with_ownership_scope`,
`regen_candidate_reverts_hand_authored_mirror` -- are present again, restored by
derivation from authorities that survived the merge rather than by transcribing the
bytes the driver refused.

Verified: regen at `first_generation_equal=true`, `main_wet=0`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Restore the failure-mode row a clean auto-merge deleted, and the module behind it

I PUSHED A COMMIT THAT DELETED ANOTHER LANE'S WORK, then found it by reading a
check I had already run and mislabelled. The previous commit's message asserted
that no row on main's side went dark. The command underneath it printed
`admission_roster_read_as_the_whole_membership_rule` and the label "(empty above =
every main row survived)" printed unconditionally beside it, so a real finding was
rendered as its own refutation and I pushed without reading the output.

WHAT WAS ACTUALLY LOST, and it was landed by #10801 hours earlier: the module
`gunbc.recurring_failure_mode.admission_roster_read_as_the_whole_membership_rule`
and both of its roster references -- the import and the list entry. Neither merge
reported a conflict. `roster.dag` auto-merged CLEANLY and wrongly: this branch
appends three imports and three list entries in the same region where main appends
one, so git resolved adjacent appends by taking one side's hunk, and the projection
gate cannot see it because the projection is derived from a roster that is
internally consistent with itself.

That is the append-vs-append shape this repository already knows, arriving through
the ONE file where it is least visible -- the failure-mode roster itself -- and it
would have deleted a row whose subject is that reading a roster is not reading the
run.

RESTORED: the module file from main, and both roster references, keeping this
branch's three. Verified by set difference at row identity in both directions, with
the check written so it cannot print a pass it did not measure: no row on main's
side is dark, and this branch's three are present.

Verified: `main_wet=0` with the projection re-derived from the repaired authorities
rather than edited.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Make not-tracked an arm, and file the class where a clean merge deletes a row unseen

REVIEW 62256, SECOND FINDING, AND IT IS AN INCONSISTENCY INSIDE ONE DIFF RATHER
THAN A NEW DEFECT. `callee_edge_dedup_key` returned `""` for `PrimitiveCallee` and
the collector dropped any edge whose key was `""` -- an in-band sentinel for "not
tracked", in the same change whose `LeafOwner` annotation argues at length that an
absent state encoded as an impossible string, with every reader obliged to remember
the test, is what `__DUPLICATE_ITEM_IDENTITY__` was retired for. Spending a
coproduct to remove that shape in one place while leaving it in another is not a
defensible boundary, and I had defended it on the grounds that a primitive's
absence is an ANSWER. That distinction is real and it survives: it is now
`CalleeEdgeDedup = Tracked { key } | NotTracked`, so the answer is an ARM the
compiler forces a producer to write, and a future `CalleeEdge` arm that forgets to
decide is a non-exhaustive match instead of an edge missing from the effect graph.

THE FAILURE-MODE ROW THAT SAID THE ENCODING WAS NOT REMOVED IS CORRECTED RATHER
THAN QUIETLY EDITED. `empty_grouping_key_silently_deletes_its_population` recorded,
truthfully at the time, that the repair gave the edge a key but left the encoding
standing. That stopped being true inside the same pull request, so the row now
carries both states and says which review closed it. What it does NOT now claim is
that the class is climbed: this is one collector, the rung stays 1, and the trigger
-- a key carrier with no empty inhabitant -- is still unbuilt.

AND A NEW CLASS IS FILED, WHICH IS THE PART WITH THE WIDER SUBJECT.
`derived_artifact_gate_blind_to_its_authority_merge`: a roster of independently
authored members, appended by several lanes in one lexical region, merges CLEANLY
and wrongly, and every guard on its projection stays silent. The gate is not weak
-- it is answering a different question correctly, because the document is DERIVED
from the roster, so a roster missing a row projects a document missing that row and
the artifact does match its authority. The refusing merge driver never fires
either: the conflict is one layer above the path it guards. An entire apparatus is
silent BY CONSTRUCTION, and silence from a mechanism that never applied is not
evidence.

Its receipt is this branch deleting gunbc#10801's row with zero reported conflicts
and pushing it. Its recognition rule names the oracle precisely -- a set difference
at member identity against the MERGE BASE, not against main, because missing
relative to main mostly means the branch is behind, which is not a defect, while
present at the base and absent on the branch is a deletion and nothing else. Its
second rule is about the check rather than the subject, because this class was
nearly missed twice by the same author: the set difference ran, printed the missing
row, and an unconditional `echo` beside it claimed the result was empty. A pass
label that prints whether or not it was earned is a fabricated plausible output in
a test oracle. Ceiling 4, with the capability named: roster membership DERIVED from
the declaring modules, so there is no list to merge.

Verified on this tree: regen at `first_generation_equal=true`, `main_wet=0`, the
merge-base set difference clean under a check that branches on its result, and the
full witnesses lane green -- `phases_run=3 phases_failed=0`, `verdict=FloorClean`
over 3541 claims, including the two `generated_artifact_merge_driver_real_execution`
row-extractor witnesses that CI reported failing on the previous head.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md binding_chosen_by_pool_membership_rather_than_by_the_declared_rule
Ledger-Rows-Repaired: docs/design-failure-modes.md stale_claim_survives_its_own_correct_edit
Ledger-Rows-Repaired: docs/design-failure-modes.md lookup_miss_read_as_positive_classification
Ledger-Rows-Repaired: docs/design-failure-modes.md match_bound_element_type_mask
Ledger-Rows-Repaired: docs/design-failure-modes.md constant_verdict_gate_stops_discriminating
Ledger-Rows-Repaired: docs/design-failure-modes.md decision_surface_truncation
Ledger-Repair-Judged: docs/design-rung-drops.md

* Delete the dangling ServiceSymbolOwners and file the class it was pretending to wall

Review 62314 is right on both halves: `ServiceSymbolOwners` had no producer and no
consumer, and the annotation above it claimed in the present tense that a refusal
"lives here" when nothing in the diff refuses. That is DESIGN 3c dangling modeling and
4b(1) rung inflation in one place, and 4c is explicit that an annotation is never
evidence a machine claim holds.

The wall is not landed here because it needs its own CompilerDiagnostic variant, and
that coproduct's seed projection is the receipt row this same PR declares FROZEN --
one commit cannot declare a freeze and breach it. The class is filed instead at
gunbc.recurring_failure_mode.shared_symbol_projection_is_not_injective, recorded below
the ladder rather than at rung 1 because nothing fires at all, with its trigger named
as a capability: a typed CompilerDiagnostic receipt carrier existing.

Also reverts this morning's 04_lookup change, which review 62308 asked for and which
executed evidence refutes. Four cells, both binaries against both corpora: main's
binary passes on both trees, the changed binary refused `Unit` on both, and the
reverted binary passes on both. The review's premise does not hold -- the
owner-bearing derivation, census_declaration_identity, already answers Absent on
BorrowedCensusDeclAmbiguous, so no fabricated owner ever reached an identity or a
registry key. The owner that declaring_module_for_local_binding supplies is consumed
by func_sig_from_global_bare for signature and formal resolution, where the
referencing module is the correct answer. Routing the ambiguity into that path closed
no hole and turned correct resolution into a corpus-wide false refusal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Regenerate the stage0 mirror from the merged authority

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Delete the roster row the merge duplicated, and record the direction the check missed

The failure-mode roster carried admission_roster_read_as_the_whole_membership_rule
twice: once where this branch restored it after an earlier clean auto-merge deleted it,
and once where main landed it in #10801. Two floor witnesses whose subject is duplicate
detection refused on it -- row_extractor_reconciles_with_both_rosters and
row_extractor_refuses_a_duplicated_identity, the latter unable to discriminate a planted
duplicate from the live one. The six other witnesses in that module passed, which is what
separated this from the shell.Mktemp.Dir hermetic route gap that fails the same two
witnesses locally on main's tree with main's binary.

Main's 177 rows verified as an in-order subsequence of the resulting 182, so the
projection order the roster declares load-bearing is intact and the five additions are
the only difference.

The merge check that missed it is filed as a receipt on the existing class
check_subject_narrower_than_its_declared_claim rather than as a new row: this is that
class, not a neighbour of it. The narrowing was a DIRECTION, not a population -- the
check computed only "present in base or theirs and missing now", so it ranged over
losses while being cited for the claim that the roster survived the merge, and a
duplicate is not a loss.

Local: lane=witnesses phases_failed=0 verdict=FloorClean 3551/3551 terminal;
lane=build phases_failed=0, mirrors and regen both at fixed point.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* Finish the identity re-key cutover at three hand-authored consumers, with a control

Review 62444 found three Rust consumers still addressing item_registry by bare leaf
after this PR re-keyed it on the declaration identity (owner.decl). All three confirmed:

- cli_run/emit_host.rs: the whole-graph read missed every time, so the Some(expanded)
  arm was dead and every row silently took the unexpanded TypedModule entry, dropping
  transitive service_names at the host signature seam. Keyed by callable_identity now --
  the graph registry is the one place the leaf is genuinely ambiguous, so it needs the
  real key.
- cli_run/owned_data.rs and coproduct_reflection.rs: both read PER-MODULE registries,
  where the authored leaf is unique. They scan that module's own values rather than
  reconstructing an owner spelling, which would be a second way to spell a key the
  registry already owns.

Two more bare-leaf reads checked and left alone: cli_run.rs definer_lookup_for_name
degrades into the LeafOwner index, which is the authority for that question; and
v1_interpreter.rs reads a registry deliberately re-projected to bare leaves.

THE EXISTING WITNESSES COULD NOT SEE THIS. They are single-module, and a single module's
local row is already complete, so the seam that loses only CROSS-module expansion is
invisible to them. Added the three-module chain the existing witness file names as this
lane's to take: setsw.top -> setsw.mid -> setsw.leaf -> setsw.Probe.Ping, where the
service parameter can only arrive by expansion across two module boundaries.

Executed control, both directions:
  with the fix     -- cross-module PASS, shallow PASS, both no-service siblings PASS
  fix reverted     -- cross-module FAIL, shallow FAIL, both siblings still PASS
The siblings holding green under the reverted build is what makes the pair
discriminating rather than merely broken.

STATED CEILING: the shallow witness catches this defect and was green on this branch
throughout, because that witness module never enters the floor's executed set --
FloorClean over 3551 claims was silent about it. The new claim inherits that dormancy
(planned is still 3551), so this is a control I ran by hand, not enrolled coverage. The
class is mechanically preventable with the mechanism not executing.

Local: lane=build phases_failed=0; lane=witnesses phases_failed=0, verdict=FloorClean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* File the class where a correct witness is absent from the executed set

Per the parent's ruling: the row, not the enrollment fix. The witness and the class are
both present and correct; the only missing thing is membership in the population the
required run schedules, so every signal a reader consults says covered and none of them
is the one that decides.

Recorded at rung 2 on paper and BELOW the ladder in fact, because 4b(2) makes rung 2
conditional on the mechanism executing and staying enrolled. The cheap detector is a set
difference the runner could print with its verdict: claim modules on disk minus claim
modules any required lane schedules. The floor already prints
outside_this_runs_universe, so the shape exists -- a module in no schedule is outside
the universe of the thing that reports being outside the universe.

Carries the fourth-instance-in-one-night observation the parent supplied, since four
independent discoveries of one shape is the argument that it is a class: a check whose
FORM is right and whose POPULATION is narrower than its name implies.

Enrollment is deliberately NOT fixed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtfacHQfiYMAD9SiH6oZhi

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md non_verdict_disposition_surfaces_as_refusal
Ledger-Rows-Repaired: docs/design-failure-modes.md obligation_fields_as_…
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