Skip to content

v2 infer: a key carrying two different facts refuses; equal facts merge - #12582

Merged
gunbai-bot[bot] merged 86 commits into
mainfrom
session/eager-newt-412
Sep 30, 2026
Merged

gunbai-bot[bot] merged 86 commits into
mainfrom
session/eager-newt-412

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Step 1 of node adhoc-3e34606f-ffc: a key in v2 infer's facts table carries one fact.

The diff against main is src/v2/compiler/04_infer.dag and src/v2/test/infer_facts/facts_key_conflict_test.dag. #12549 and #12557, which this was stacked on, have landed.

Change

v2.compiler.infer inferred_facts_map_enter, the one admission point of the node-keyed facts Map (#12557), used to keep the first entry under a key and silently drop a later, different fact. It now:

  • refuses with ^infer_facts_key_conflict, located at the key through node_locus, when a key arrives with a different fact;
  • merges an equal fact, which is one subject reached twice.

facts_map_from_entries threads the refusal out. Admission stays one map_lookup per entry: review 72444's quadratic-scan finding was fixed by building on the keyed Map.

The key is the whole structural Node, occurrence included. So one node reached twice is one subject, and two structurally different nodes that share a minted id are two keys here. Whether such a pair may exist is the occurrence admission's question (#12790 / #12605), not this table's.

Evidence (gunbc run --function, remote)

claim head pre-wall (first-wins insert)
fkc_differing_facts_under_one_key_refuse true false
fkc_equal_facts_under_one_key_merge true true
fkc_supplied_facts_differ (control: the planted facts differ) true true
fkc_same_minted_node_reached_twice_is_one_subject true —
fkc_different_nodes_sharing_a_minted_id_are_two_keys true —

The first three were run with the refusal reverted to first-wins, and the refusal claim flipped. The last two ran at b27a773; this file and the refusal are unchanged since then.

Audit of claims that passed only because of the defect

The required floor was green when first-wins became a refusal: no enrolled claim was green only because a conflicting fact was dropped. That bound is the floor's selected set. One known specimen off main: #12506's synthetic_facts_key_collision claims assert the disagreement exists. Per ruling, whichever of #12582 or #12506 lands second flips them to assert this refusal, keeping the raw-entry disagreement as the control.

The facts key is within-run only: the Map is built and consumed inside one infer call, and is never persisted or compared across runs, which is compatible with #12604 PR2's allocated occurrence ids.

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 30 commits September 27, 2026 15:28
…_atom_identities) instead of re-parsing each
…uments (the witness is about carets, not the lambda frontier)
…l spelling instead of being captured

Body lowering rewrote every type atom spelled Int or Bool to the kernel binding before any scope
existed. A module that declared its own `type Int = | Mine` and wrote `let y: Int = 1` therefore
had its annotation replaced by the kernel Int, and infer judged the let matched.

The spelling table moves to its language authority (v2.extdeps.languages.dag
dag_kernel_type_binding_optional), and resolve_atom consults it only after the scope walk and the
symbol index. A hit declared in the referencing module binds that declaration. Imported, foreign,
ambiguous and unbound kernel spellings keep the kernel binding, unchanged.

Claims (v2.test.claim.body_let_annotation, 5c): the module-declared Int and Bool lets refuse at the
annotation, and the annotation is asserted not to be the kernel binding. An undeclared Int/Bool
still binds the kernel type. Both shadow rows are red on main 9ce0394 and green here.
The rfm row records the residual and its trigger.

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

Resolve now reads a kernel spelling by the declaration a door selected.
v2.extdeps.languages.dag dag_kernel_type_declaration_binding_optional lists the declarations a
kernel spelling denotes. A hit on one of them takes the canonical binding, and the module's own
declaration shadows it. Any other declaration, reached through an import or another module,
refuses with resolve_reason_kernel_type_spelling_names_a_foreign_declaration. Unbound and
ambiguous names keep the spelling fallback.

Third RED: bla_imported_user_int_refuses_rather_than_binding_the_kernel_int (a two-module
fixture, p imports q's `type Int = | Mine`). All three REDs are F on main and T here, and the
controls are T on both. The new specimens are enrolled in floor_pure_producer_share. The rfm row now
states rung = refused, with the trigger at capability grain: declaration-keyed binding across every
door.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…te is a kernel declaration

An ambiguous kernel spelling now binds the kernel type only when every candidate is a kernel
declaration of it: v2.std.integer Int beside std.integer Int is one kernel type. Otherwise it
refuses with the ordinary resolve_reason_ambiguous_symbol instead of defaulting to the kernel. An
unbound name keeps the kernel binding, which is the correct answer when no declaration is in scope.

New claims:
- RED bla_ambiguous_imported_int_refuses_rather_than_defaulting_to_the_kernel (p imports Int from
  q and r). F on main, T here.
- Control bla_ambiguous_kernel_declarations_bind_the_kernel_type. T on both.

The multi-module specimens now share one helper, bla_assemble_with_peers. The rfm residual is now
only the kernel-declaration path list. Its trigger is a mark on the kernel declarations themselves.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-ibex-696/symbol-arm

# Conflicts:
#	src/v2/test/claim/body_let_annotation_test.dag
#	src/v2/workflow/floor_pure_producer_share.dag
…std.node Symbol)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…hored return-type spelling

Three floor blockers on fa8c596. These claims read the positional return clause from body lowering
and expected the kernel binding (dag_binding_type_int, bool_node_symbol). Lowering used to produce
that binding by rewriting the spelling. That rewrite now happens in v2.compiler.resolve, after the
scope walk, so lowering carries `Int` and `Bool` as written, as the generic row already reads `T`.
Arm 1 still discriminates: the return type is Bool, not the parameter's Int.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
review 72280: the symbol arm tested dag_node_is_symbol_literal_atom and then recomputed
dag_symbol_literal_name_optional. That was the same optional twice, and the recomputation needed an
arm the predicate had already ruled out. The decision now matches the optional once. The remaining
Absent arm is a name payload with no atom identity, which is reachable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…teral_name_optional directly (review 72280 on #12549)
…-ibex-696/symbol-arm

# Conflicts:
#	src/v2/compiler/03_resolve.dag
…xeme-stamped terminal; delete the span/source-text route and its prose note row (review 72294 on #12549)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ens span route: nothing else consumed them

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pe as this PR derives it

review 72301: the receipt still said the symbol literal's type stays on the GroundingNotDerived
frontier. The arm in this PR makes that false. It now names the derivation route
(DagCanonicalSymbolLiteral, infer_literal_type_binding, v2.std.node symbol_type_node) and the two
body_let_annotation claims that execute it. Census trigger (a) stays open and the receipt says why:
it names the source checker v1.compiler.types, which still types LitSymbol as string_type.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…anned per lookup

facts_map_from_entries admitted entries into a List and answered every
lookup with lookup_inferred_facts_in_entries, a linear scan: each consumer
walking the tree paid quadratic. It now enters admitted entries into a
Map<Node, InferredFacts> once and answers lookup with map_lookup. A
repeated node keeps its FIRST admitted entry, as the scan did.

The gather fold's own scans (lookup_inferred_facts_in_entries inside
infer_gather_fold_algebra) remain: the catamorphism computes children
independently, so removing them needs a state-threading node fold, filed
as node adhoc-914690c3-870.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ions; ownership reads declared_in

GitHub review 5342739525 on #12540. The same-module test compared a declaration's path to
ctx.namespace.module_qn, but build_program_namespace (the plain normalize -> resolve route)
leaves module_qn Empty and records its owner in declared_in. namespace_owns_declaration now reads
declared_in, which is the owner on both namespace routes and the field root_binding_origin reads.

Measuring that route found the earlier boundary. build_program_namespace harvested only the root's
named edges, and a normalized module keeps its declarations under captured -> <module path>, so
none of them were bound. `type Myint` refused as unbound, and a module's own `type Int` fell
through to the kernel spelling and was silently bound to the kernel Int. The namespace now also
harvests the module body, which it finds by declared_in.

Controls on that route (v2.test.claim.body_let_annotation, enrolled share points):
- bla_single_tree_module_declared_int_and_bool_bind_the_local_declaration: F before, T now.
- bla_single_tree_undeclared_int_binds_the_kernel_type: T on both.
The foreign-import refusal and both ambiguity dispositions are unchanged and still hold.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/v2/workflow/floor_pure_producer_share.dag
…y walking names

Review 5343957887 (P2 on b55b8a7). namespace_tree_module_body walked the module path's names and
restarted at the root on a missing step. Two leaks followed:
- `module m.t` with a root-level record `t` missed `m`, restarted, found `t`, and bound the record's
  field as a module binding.
- `module t` with a record `t` selected it at once.

The body is now selected by the producer's own mark. v2.compiler.namespace_graft
namespace_graft_module_body_optional descends the containment spine
(namespace_graft_spine_segment_edge_optional) until a step is not a segment, never restarts, and
answers only when that stop is the marked body (namespace_graft_node_is_module_body).
Header and flat representations have no grafted body, so they keep root-only harvesting.

The admission reader in v2.compiler.name_resolve already descended the same spine with its own
copy (admit_named_exports_body_root and _descend_spine). It now calls the one function in
namespace_graft (namespace_graft_module_body_root), so the spine has one reader.

Controls (v2.test.claim.resolve.single_tree_module_body): supplied emit-shaped roots, because
normalize always emits a well-formed graft and source text cannot author these shapes.
- a_record_matching_the_path_suffix_is_not_a_module_body_holds: F on b55b8a7, T here.
- a_record_named_like_a_flat_module_is_not_its_body_holds: F on b55b8a7, T here.
Each asserts `leaked` is not bound and `t` still is.

The local Int/Bool and undeclared-kernel controls still hold.

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

The parse phase refused a // annotation inside the fn body (DESIGN section 4c: only module-item
grain is modeled). This is the same text, placed above the declaration.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 5 commits September 30, 2026 16:43
… threads main's resolved (as on the #12628 integration)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Review 73303 on #12809 (finding 2) flagged the pattern this PR introduced: each family arm matched a
variant only to rebuild it for infer_gather_literal_payload_step. The gather now binds the family
once, with one arm for InferNotALiteralPayload and one for every family (DESIGN section 2).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… commit took #12549's whole file)

6ff1aae resolved one hunk with 'git checkout --theirs', which replaced the entire file and
dropped inferred_facts_map_enter's refusal. This recomputes the three-way merge (ours = e056dde,
theirs = #12549 6e9850b) and takes #12549's side only in its two conflicting hunks; the file now
differs from #12549 by exactly this PR's refusal.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Sep 30, 2026
…evel; #12582's refusal kept)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 4 commits September 30, 2026 18:56
…eps #12549's symbol_type_node and main's construct_tag_marker)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/v2/extdeps/languages/dag.dag
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 30, 2026
Merged via the queue into main with commit 2145cbb Sep 30, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/eager-newt-412 branch September 30, 2026 23:37
gunbai-bot Bot pushed a commit that referenced this pull request Sep 30, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Oct 1, 2026
…ords): one Loop walk

21 commits, 15 conflicts across three files, each resolved on what the merged
declarations actually are.

#12550 REPLACED THE FOLD SEAM, and that changes what this lane's Loop work is FOR rather
than merely colliding with it. The encoding is now
Bind { acc := init, Loop [ step, domain: collection, carrier, bound, realized: head ] }:
the positional child is the WHOLE STEP, not the step's body, and the carrier is bound by
the enclosing Bind. So a step that lowers to an Arrow carries both of its binders in that
Arrow's domain, which is the representation this lane's first control already proves
resolve admits (it admits `found` AND `e`).

TWO resolve_loop_node DECLARATIONS EXISTED AFTER THE MERGE and the namespace refused the
duplicate -- which is the only reason this is one edit. They answered different questions:
main's routes a realized-declaration head, this lane's opens the carrier's frame and
carries the carrier and the bound measure UNWALKED (v2.std.node's role model says the
carrier is "a BINDER, never a value" and the bound edge is "the termination measure").
Consolidated into one walk holding both.

THE CARRIER FRAME IS KEPT even though the encoding's Bind now binds the same name, because
they are not the same scope: the Bind's frame covers the encoding's body, while a Loop
reached by any other producer carries its binder with no Bind above it. Where both bind one
name the admission answers BinderHidesVisibleValue -- a real question about the encoding,
not an artifact of this walk, and the next native run is what reports it.

OTHER CONFLICTS. 04_infer: took main's infer_judge_formal_args consolidation and its
record-construct dispatch, and kept this lane's facts-aware reads through them --
infer_application_type_params stays (node, entries) over
infer_application_callee_arrow_with_facts, because main's version calls the facts-BLIND
reader this lane deleted, which answers Absent for a named call's Conj callee. The
resolved carrier is threaded into infer_formation_facts_from_entries through main's new
infer_gather_formed_facts_row extraction. symbol_index: all ten conflicts were pure
additions from main (a renaming_aliases field threaded through every constructor) adjacent
to this lane's declared_type_params; both survive, 13 sites each.

The test control was repointed off fold_call_seam_loop, which #12550 retired. It now builds
the Loop it supplies, while still taking the carrier atom from the production constructor,
because calling fold_recurrence_encoding would drag a collection, an init and a realized
head into a row whose subject is one edge.

callable_binder_slice 10/10 on the merged tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Oct 1, 2026
… infer facts (synthetic cells collided under #12582's key-conflict refusal)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Oct 1, 2026
…ead can block

reach_head_cannot_block is derived from claim_differential_blocks over every base arm.
A passing head never blocks, and a head where the claim is no longer declared is a
removal under every base, so neither is run at base. The base arm then runs only the
claims that FAIL at head: 60 of 1481 for a one-line v2.std.node edit and 18 of 240
for #12582's change (srv1, 2026-10-01), about 25x less base work. An all-passing reach
spawns no base process.

Controls: a_head_passed_claim_is_never_run_at_base_and_never_blocks (Rust, real
model: the partition sends only the failing head to base, and a passing head blocks
under no base) and only_a_failing_head_needs_the_base_arm (.dag).

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

Copy link
Copy Markdown
Contributor

The subject your conflict check refuses on: the empty synthetic Conj

#12582 is doing its job — this is a report of what it caught, not a request to relax it. Handing it to the facts-identity owner with the producer, parent edge, and consumer named, and with one question that must be answered before any key is proposed.

Build identity for every number below

head 8ea7415dc422068061b5cde7c2902cb9e6dfdb94 (lane/reference-evidence-consumer)
claim_batch 2026-10-01 10:54:55, sha256 90bcc97a016bc876
gunbc 2026-10-01 10:54:56, sha256 80a01a1f1f45273e

An earlier instrument on this lane was stale (six seed commits after its build, including #12550's merge). Every measurement I reported from it is void; everything here is from the binaries above.

The subject, enumerated

The conflicting key is:

Node { kind: TypeNode { connective: Conj }, children: [], occurrence_id: OccurrenceSynthetic }
  • Conj, zero children, OccurrenceSynthetic — each measured separately, not inferred from shape.
  • Reachable from more than one parent edge in a single resolved tree, so one key genuinely serves several positions.
  • Facts consumer: v2.compiler.infer inferred_facts_map_enter, via facts_map_from_entries. The entries list itself is clean — infer_entries_for_tree accepts; the refusal is at map admission.
  • Producers include v2.std.algebra, where the empty Conj is the empty FreeMonoid — so every empty list in a program is literally the same node — alongside body_lowering_fold's empty_interior / empty_suffix / NoTypeParams arm and fold_lowering's empty-conj mint.
  • The two entries under the key differ, but not in derived-ness of grounding, nor descent, nor denotation as those compare — so the difference is in the grounding's recorded subject, not in a verdict.

The trigger, which is sharper than "a projection fixture"

A named call whose argument is an Int literal refuses; the same call whose argument is a parameter accepts.

fn consumer() -> Int { callee(only_arg: 3) }    // refuses: infer_facts_key_conflict
fn consumer(y: Int) -> Int { callee(only_arg: y) }  // accepts

That cost me two wrong readings before I used the fixture's own text, so it is worth stating plainly: the literal mints a further synthetic node that collides.

Current blast radius on this lane

11 rows red, all one cause: nine of ten in v2.test.claim.callexec.declaration_reference_eval (named-call execution, argument-dependence, the Bool pair separating) and two in v2.test.claim.field_projection.field_projection_stages. These were green before the merge and are not repaired by anything in this lane.

The question that precedes a key, and the two things that do not answer it

Before proposing an identity, the owner needs to decide whether the empty value is the true semantic subject, or a child incorrectly carrying its parent's contextual facts. The second reading is live: an empty list is the same value everywhere, so if two positions legitimately share it, the defect is that facts contextual to a PARENT were recorded against a child that has no context of its own — and a key would then be encoding a mistake rather than fixing one.

Happy to supply the enumeration probes, run any discriminating fixture on the pinned binaries above, or re-run the native eight once a repair lands.

🤖 Generated with Claude Code

briansrls pushed a commit that referenced this pull request Oct 1, 2026
Wall 3d. All eight of v2.test.parse.expression_bodied_fn_decl_parse refused natively at
infer with infer_reason_projection_receiver_declares_no_fields, the chain walking
"v2" then "live_tree" then "LiveTreeDisposition" -- and the file writes no projection at
all, only `data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly`.

So a reader was CLAIMING a projection, and it was this lane's. resolve_projection_base
admitted BoundAtRoot, so the head segment of a MODULE PATH became a projection base and
the remaining segments became nested field projections; infer then asked a COPRODUCT for
its fields. The arm exists so a LOCAL binder shadows an absolute path (`b.tree` where `b`
is a parameter), which is what dissolved the AmbiguousQualifiedHeadShadowsAbsolute guard
-- a name bound at the module ROOT is a declaration or a namespace segment, so a dotted
path through it is a qualified name and not a projection.

REMOVING BoundAtRoot OUTRIGHT WAS ALSO WRONG, and the controls said so in one run: the
same arm is how a plain root-bound ANNOTATION resolves, so `type Box { tree: Int }` with
`fn f(b: Box) -> Int { 7 }` -- no projection anywhere -- stopped inferring. The two shapes
look alike at the head and are distinguished by whether there are FIELDS: with none, this
resolves a name and either binding answers; with fields, it is building a projection and
the base must be a lexical binder. lookup_chain already carries that distinction, and it
is the same one the value-binder admission uses to decide what hiding means.

TWO REDS IN THIS FILE PREDATE THIS CHANGE AND ARE NOT CAUSED BY IT, qualified by running
them at 2bd1f0d before the edit: fps_the_receiver_without_a_projection_infers and
fps_the_match_form_infers_and_the_projection_stays_on_the_frontier. Their reason is
infer_facts_key_conflict -- main's #12582, which made a key carrying two different facts a
REFUSAL. That is the synthetic-key collision this lane measured and documented in
v2.test.claim.callexec.synthetic_facts_key_collision, now load-bearing instead of latent:
structurally identical nodes minted at OccurrenceSynthetic share one facts key, and this
lane's projection and spine nodes are minted there. The frozen facts-identity question is
therefore un-frozen by main, and it is the next subject rather than a side note.

callable_binder_slice 9/9; field projection 14/16 with both reds attributed above.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Oct 1, 2026
…t supported

The 3d repair says a namespace segment may not be projected through. Read carelessly that
becomes "only a lexical binder may have fields", which would be an over-prohibition
(DESIGN section 4d), so the case that distinguishes them gets a control: `cfg.tree` where
`cfg` is a module-level `data` value names a VALUE, not a namespace segment.

MEASURED: it refuses at resolve with resolve_reason_unbound_symbol, and it did so BEFORE
the gate as well -- the same reason at 2bd1f0d and at bd9d3d3, taken in a detached
worktree so the head is the only variable. The gate therefore removed no working
capability: the head segment is not bound in the scope chain at all, upstream of the arm
that decides projection bases, so it was Absent before and is Absent after.

The row is written AT THE REFUSAL rather than at the capability, so it cannot sit green
while the thing it names stays broken, and it flips when a root-bound value becomes
projectable. It asserts the REASON, not merely that something refused -- a row satisfied
by any refusal would stay green if the gate over-prohibited and broke this for a different
cause, which is the failure this control exists to catch. Next trigger: a module-level
value binding the scope chain answers for.

field projection 15/17; the two reds are the pre-existing infer_facts_key_conflict pair
(main's #12582), unchanged by this commit and attributed in the previous one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Oct 1, 2026
…y full declaring path

Two things, and the second corrects two wrong readings of mine from the same hour.

THE LOCATOR WAS A SECOND AUTHORITY FOR THE APPLICATION ENCODING. cref_callee_reference_optional
matched ComputationNode { behavior: Transform } and read positional child 0 by hand --
the same positional re-derivation DESIGN section 3 forbids, and the same defect repaired
earlier today in the arm-pattern reader. It now asks v2.compiler.infer
infer_application_callee_use, the reader the application's own formals and type parameters
come from, so a change to the encoding reaches this file as it reaches infer.

AND IT SELECTS BY THE WHOLE PATH. The old annotation claimed it keyed on "a declaration
path ending in `callee`"; the code checked NO name, taking the first node with any
declaration-reference callee -- so an annotation or an unrelated reference could have been
selected and the row would still have looked green. Each fixture declares one callee at
module `p`, every value helper now carries that name, and the locator requires EXACTLY ONE
call to the full path; two matches are Absent, so a fixture that grows a second call to
one declaration refuses rather than silently picking.

THE NINE RED cref ROWS ARE NOT EXPLAINED BY THIS, AND I SAID TWICE THAT THEY WERE. I
reported first that they were a separate cause from the two field-projection reds, then
that they were a stale locator rather than a compiler regression. Both wrong. Measured:
infer REFUSES cref_source with infer_facts_key_conflict -- main's #12582 -- which is the
SAME cause as the field-projection pair. What misled me was probing with a hand-written
fixture that passed the callee a PARAMETER while cref_source passes an Int LITERAL; the
parameter form infers and the literal form does not, because the literal mints a further
synthetic node that collides on the shared key.

So this commit is a section 3 repair that stands on its own and fixes none of the reds.
The rows stay red and the named-call claims are NOT restored: the ruling admits them only
if the fresh rows pass, and they do not.

EVERY claim_batch RESULT I REPORTED SINCE THE MAIN MERGE IS VOID. The binary was built
19:53 with six seed commits after it, including #12550's merge; gunbc was rebuilt but
claim_batch was not. Fresh binary, fresh numbers from here.

cref 1/10 (the unresolved-callee negative), all nine reds attributed above.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Oct 1, 2026
… from a fieldless receiver, and reads the closure's resolved declarations

`infer_projection_receiver` collapsed two different facts into `ReceiverNotARecord`,
and both emitted `projection_receiver_declares_no_fields`:

  the receiver's type is established and is not a declaration reference
  the receiver's type names a declaration THIS CONTEXT CANNOT RETRIEVE

The second is not a fact about the program. A lookup miss establishes that this
index does not hold the declaration, which is a statement about the evidence
available to the stage. Asserting it as "declares no fields" convicts a correct
program of a defect it does not have.

The cause was structural rather than incidental. `resolved_declarations_of` fills
the index from ONE module root, so a record an imported provider declares was
absent BY CONSTRUCTION and every cross-module field read was reported as a program
defect. `resolved_tree_of` now takes the closure's resolved roots and
`resolved_declarations_over` folds the existing single-root door over them --
`symbol_index_fill_module_declarations` already keys each declaration at its own
module's qualified name, so the fold is total and order-independent and no
index-union authority needs to exist. The subject is folded last and
unconditionally, so a caller passing an empty list gets exactly the previous
answer.

`closure_resolved_roots` assembles those roots, and the recursion is cut by
passing an EMPTY closure to the per-root resolves: each provider is resolved
exactly as it is resolved today and only the SUBJECT is resolved against the
collected roots. N + 1 resolves, not N squared. The native per-module door reaches
the same reading through `native_test_closure_resolved_roots`, which asks the
shared resolution context rather than threading an accumulator through every
caller; its arguments are invariant across a lane's modules, so the call memo
answers all but the first.

WHAT WAS REFUSED. Reading `resolved.symbol_index` instead would have made imported
field typing appear to work off AUTHORED declarations rather than resolved ones,
which is the fork this carrier exists to keep apart. A provider that fails to
resolve contributes nothing, so a receiver typed by its records refuses with the
located unavailable reason -- answering the field read anyway would have been the
absorbing arm DESIGN §5 forbids.

EVIDENCE, AND ONE PIECE OF IT IS NOT MINE.
v2.test.claim.reference_evidence.declaration_reference_evidence carried an
expecting-red probe whose header DECLARED THIS REPAIR'S TRIGGER before it was
built -- "a resolved-declaration index over every resolved module root ... minted
by resolve beside the per-module carrier". That is what landed, so the probe
greened. Under DESIGN §4b(4) it does not retire: renamed
`dre_an_imported_reference_grounds_through_the_closure_index`, same subject and
fixture, assertion inverted, enrolled as the permanent regression control. 11/0.
A control written as the wall's trigger, by an author who did not know how it
would be built, is better evidence than any claim the implementer can make.

v2.test.claim.field_projection.field_projection_stages is 22/24, the two reds
being the pre-existing `infer_facts_key_conflict` rows owned by #12582. A
same-module positive stands beside the cross-module subject so the repair is a
gained capability rather than a widened acceptance, and a scalar receiver still
refuses with `declares_no_fields` so the OTHER arm kept its meaning -- without
that row the split could be satisfied by routing every projection refusal to the
new reason, losing a diagnosis instead of gaining one.

THE NEW ARM'S RED IS AUTHORABLE, which is checked rather than assumed. Once the
closure index made the ordinary cross-module case succeed, the only remaining way
to reach `ReceiverDeclarationUnavailable` is a provider whose declarations never
enter the index, and `closure_resolved_roots` drops a root that fails to resolve.
`fps_an_unresolvable_provider_leaves_its_declaration_unavailable` produces exactly
that and asserts BOTH directions -- the unavailable reason present, declares_no_fields
absent. An earlier row asserting that the cross-module case refuses was obsoleted
BY SUCCESS, the same way the imported-grounding probe was; its subject moved to the
condition that still reaches the arm rather than being deleted, because a
permanently unreachable arm cited as coverage is the decoration §4b forbids.

v2.test.claim.projection_dispatch.receiver_disposition establishes that the two
representations are DISJOINT by executing both readers on both shapes: a
declaration reference is not read as a projection and a projection is not read as
a declaration reference. That pair is what ruled out a reader-overlap explanation
for the native refusal, and it is the control that made the remaining diagnosis
decidable.

`cross_module_reference_resolution` is 15/15, including
`a_receiver_with_no_such_child_never_accepts` -- the control whose breakage caused
the arms to be collapsed in the first place. `00_compile` compiles clean: 0
blocking errors, 221 files emitted.

NO MOVEMENT IS CLAIMED ON THE NATIVE SEVEN OR EIGHT, and no cross-module roadmap
node is closed. The native eight still refuse, and after this split their reason is
diagnostic: `declares_no_fields` fires once and the unavailable reason zero times,
anchored on `field_projection_base -> e`, `field_projection_field -> target`. Since
the two reasons are now disjoint arms, the absence of the second is positive
evidence that `e`'s type is ESTABLISHED and is NOT a declaration reference -- not
underived, not unretrievable. The split paid for itself immediately: before it
those three outcomes were one string and the question could not have been asked.
The remaining defect is one link above: `fold_lowering` writes `^loop_domain_edge`
carrying the fold's collection, that label has a producer and NO READER anywhere in
src/v2/compiler while its siblings `loop_carrier_edge` and `loop_bound_edge` are
read in `03_resolve` and `std/cardinality`, and the step's element formal carries no
authored annotation -- so nothing joins the domain's element type to it. That is a
separate charter.

RECORD PAYLOAD MARKS ARE NOT CARRIED and the limitation is inherited rather than
chosen: the fill takes a normalize-time record roster, `resolved_declarations_of`
passed Empty for it before this change, and a resolved `Node` does not carry that
roster. `symbol_index_declared_payload_at` therefore answers Absent for a RECORD in
this index, so a reader asking it would take a record for a binder. The projection
path reads through `symbol_index_lookup` and is unaffected. A reader needing the
payload KIND must be handed the roster; it must not infer it from a lookup hit.

THE CLOSURE FOLDED IS THE SELECTED CLOSURE, not the import closure, so it does more
work than the dependency relation requires. Narrowing to the exact provider set
changes WHICH roots are folded and not the inference rule, so it can land later
without disturbing this reading. This is the one-seat form of a dependency the
demand engine owns.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Oct 2, 2026
…ot the collision

All three rows in v2.test.claim.callexec.synthetic_facts_key_collision asserted
`total > 1` -- that more than one inferred-facts entry stood under a single key,
because structurally identical synthetic nodes keyed one entry and eval could refuse
at a node that was not its subject. gunbc#12582's facts-key work eliminated that, so
all three failed.

MEASURED BEFORE FLIPPING: exactly ONE entry stands under the key, for both fixtures.
That matters for how the rows are written -- `== 1` rather than `<= 1`, because a
fixture that stopped producing the node at all would answer 0, and a `<= 1` row would
sit green while testing nothing. The count is enumerated rather than inferred from a
lookup, which the original rows did for the same reason: a lookup answering something
proves only that SOME entry matched, while counting proves how many stand there.

DESIGN §4b(4) IS WHY THEY FLIPPED RATHER THAN RETIRED. A climb deletes the lower-rung
production handling and keeps the evidence, so each row keeps its fixture and its
counting method and now asserts the separation: exactly one entry under the key, that
entry grounded, and the same separation reached by a second fixture -- which is what
the original third row established in the opposite direction, that the property belongs
to the keying relation over ordinary programs rather than to one source text. They go
red the moment two entries share a key again.

4/4.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Oct 5, 2026
…#12951)

* Regenerate docs/design-rung-drops.md after merging main

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

* Reach differential: the base arm runs only the reached claims whose head can block

reach_head_cannot_block is derived from claim_differential_blocks over every base arm.
A passing head never blocks, and a head where the claim is no longer declared is a
removal under every base, so neither is run at base. The base arm then runs only the
claims that FAIL at head: 60 of 1481 for a one-line v2.std.node edit and 18 of 240
for #12582's change (srv1, 2026-10-01), about 25x less base work. An all-passing reach
spawns no base process.

Controls: a_head_passed_claim_is_never_run_at_base_and_never_blocks (Rust, real
model: the partition sends only the failing head to base, and a passing head blocks
under no base) and only_a_failing_head_needs_the_base_arm (.dag).

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

* Emitted-package join also matches canonicalized paths, so a symlinked crate dir cannot undercount (review 73526)

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

* Reach differential: the base-arm budget is born typed Milliseconds (review 73528)

ReachDifferentialStanding's DifferentialBlocking carries base_arm_wall_budget:
Milliseconds (std.types) instead of base_arm_wall_budget_ms: Int, and the host wire
reach_differential_blocking_budget returns Milliseconds, so the unit is the type's
and not the name's. The branded value reaches the host as Value::Int, which the
existing non-negative match unwraps; any other shape still refuses. The sibling
required_floor_claim_wall_safety_limit_ms stays as existing debt, not widened here.

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

* Reach differential: per-identity base verdicts; an unmeasured base blocks only when no roster declares the claim red

A non-verdict base outcome (budget, panic, host tool or effect, not attempted) is now
not_measured for that identity alone; the other reached claims keep their verdicts
(srv1 replay 4d79fc6: one BudgetInterrupted claim voided all 60). Only instrument
failures refuse the whole arm.

reach_claim_verdict takes the claim identity. An unmeasured base on the declared
main-red roster (floor_expected_red_roster, joined by identity) is a counted
base_not_measured_rostered finding that does not block. On no roster it BLOCKS as
base_not_measured_unrostered (deep-ferret-305 ruling, 2026-10-01). A base verdict
decides as before.

Control: an_unmeasured_base_blocks_only_when_no_roster_declares_the_claim_red (.dag:
rostered reports, unrostered blocks, a base verdict still decides).

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

* Reach differential: planned on the merge group only (operator ruling 2026-10-01), modeled, announced when deferred, naming what newly failed

- v2.workflow.floor_subject_seed reach_planned_for_event decides, over the event the
  runner reads through the authority that chose its diff window, whether reach
  consumers are planned: ReachOnMergeGroupOnly, compared against
  extdeps.github.actions github_event_name_merge_group. This is the phase scoping
  DESIGN puts in the binary, not the workflow YAML. An unreadable event refuses on CI
  (ReachEventUnreadable) rather than silently deferring.
- On any other event no reach consumer is planned or executed (PRs +0), and the floor
  prints phase=reach-differential state=deferred_to_merge_group with the count it
  would have reached.
- A blocking regression or failing new claim prints
  [floor-reach-finding] NewlyFailedAtHead identity=..., so a dequeued author sees
  what broke without rerunning.

Controls: only_a_merge_group_plans_the_reach_differential (.dag, both directions) and
a_pull_request_defers_the_reach_differential_and_a_merge_group_plans_it (Rust, real
rule plus the deferral line).

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

* NFR: enumerate the three qemu-host-observe readiness arms main added since (census PR1/3)

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

* Reach differential: blocking verdicts are a typed outcome field the adjudication names, not free text in failures

neat-boar-16's srv1 control (2026-10-01) showed blocking=8 but no per-identity
adjudication line for them. RequiredFloorOutcome gains reach_differential_blocking:
Vec<(identity, differential)>. required_floor_outcome_is_clean requires it empty, and
required_floor_measurement_blockers adds one blocker per identity with cause
reach_differential_<differential> (regressed, new_claim, base_not_measured_unrostered,
refused). A refused base arm records every claim it left unjudged as base_arm_refused.

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

* Reach differential: both main-red rosters; a non-verdict at head is not_measured, never failed; one shared test pool

- claim_on_declared_main_red_roster joins floor_expected_red by identity AND
  gunbc.explicit_witness_admission's known-red rows by (entry, function), through that
  roster's own explicit_witness_admission_is_known_red. On the srv1 control rerun three
  known_red_probe map_literal claims had blocked as unrostered; they now report.
- The head standing uses the base arm's classifier (base_standing_of): a wall
  interruption at head under load is not_measured, verdict head_not_measured, never
  sent to base and never read as a regression. It was matches!(Pass), which made a
  passing base plus a loaded head a false regression. The floor's own
  interrupted_before_verdict rule still refuses such a run.
- The base-only residual is named beside the rule: an unrostered claim whose base lands
  within load noise of the 8 s hang guard dequeues load-dependently (loud, named). Its
  trigger: the hang guard gets its own typed refusal and a much larger declared value
  through one plumbing for both arms.
- reach_base_standings tests share one pool (test_roots): the process-global shared
  index holds a single resident pool, and the fixture test's extra root made test order
  decide a SharedIndexSecondResidentPool panic.

Controls: an_unmeasured_head_is_not_a_regression (.dag); the roster control extended
with the explicit-admission arm; the partition test with a not_measured head. Rust 5/5,
.dag controls true, clippy clean.

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

* WIP: locate floor runtime-error rows; typed host IO refusal

* Floor runtime-error rows carry message + raising declaration; host write failures are a typed IO refusal

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

* RFM: portable value map order is process-random (RandomState HAMT iteration; Symbol hashed by address)

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

* Portable map entries in canonical content order; value_hash hashes variant names by spelling; RFM row scoped by the iteration and value_hash censuses, with the DefaultHasher residual

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

* emit-host transport read failures are HostIoFailed too (Cargo config read, tool canonicalize/read, cold receipt read, cache evict); probe spawn via host_tool_spawn_failure

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

* Review 73653: seed-growth justification for the canonical-order Rust; the row states its controls are off the merge path

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

* Canonical order: floats by IEEE 754-2019 totalOrder (f64::total_cmp), not raw bits, which invert negatives; control floats_order_by_ieee_total_order

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

* Six ungated main reds re-derived; three entries admitted by importing LiveTreeDisposition

(1)(2) live_deploy.emit sudoers claims: the needle is now the install's own node
(gunbc.ci_deploy_sudoers deploy_sudoers_elevated over the fleet visudo row) rendered by the same
serializer. Stale since #12602 (/usr/bin/sudo) and #12525 (bash builder quotes every word). The
two probe negatives are deleted: unmatchable under quoting, and since #12168 those probes are
emitted on purpose after the install.
(3) twin claim: count equality replaced by an identity join on artifact kind, host singletons
(fabric storage + #12747's approval broker front door) subtracted by the functions that decide them.
(4) CPUQuota grant: sudoers side read through sudoers_argument_word (escape since #12563).
(5) tasks verdict: bare `Absent ==` never named the ConvergeVerdict arm; typed match + a Drifted
discriminating conjunct.
(6) runner_lifecycle: fabric rows from srv3/srv4_fabric_first_slot, each controlled by the
slot below it on its own host (srv4-06 is fabric since 2026-09-18).
Admission: build_cache_endpoint_observe, ci_budget_tree_witness, host_allocation_conservation
import v2.std.live_tree (the #12540 class #12819 fixed once); variant rows retired ImportsFixed.

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

* ci_budget_tree_witness: three live-tree reds were stale premises; re-derived from the producers

witness_live_is_fail_closed asserted the Unestablished arm while srv1 now resolves ReservationBytes;
it asserts each arm's relation over session_reservation_bytes(srv1). witness_srv2_symmetric_to_srv1
assumed equal RAM (srv1 is 512 GiB since 2026-08-22; usable RAM per host since #11625); it asserts
the pools differ by exactly the RAM gap. witness_srv3_outbudgets_srv1_by_exactly_the_overhead_gap
missed the 1,392,640-byte usable-RAM difference; gap = overhead gap + RAM gap, both read from the
producers. Removed from floor_expected_red_chunk_live_tree_admission (they now pass).

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

* Floor: unimported-bare-provider standing judged over the whole pool, not the diff; census fixed

The diff-scoped standing check let #12540's new pairs in untouched files through while
claim_batch's entry route refused them. The floor now judges every pool file (13.6 s over
7,175 files on the warm index, measured). Census at this base: 172 Unrostered + 16 RosterStale.
Fixes: 167 pairs import their declared provider (138 files; no new import cycle), 5 bare
`ends_with` calls that bound to gunbc.rust_item_scan's private helper use the builtin
.ends_with(suffix:) method instead; 16 + 344 rows whose pairs the imports dissolved retire as
ImportsFixed. Re-census: zero refusals.

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

* std.algebra: TotalOrder<T> is the one compare law; OrderedRing and Field compose it (WIP)

* Interpreter: one canonical content order (ContentView over Value and PortableValue); map Display/Debug canonical; sort_by admits only emitted-agreeing keys; cmp_values deleted (WIP)

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

* Canonical render order: emitter refuses map rendering typed; to_string classified CanonicalOrder; two-process, kind-rank, totalOrder and carrier-differential controls (WIP)

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

* Rows: RFM rendering receipt and per-path rung; spelling stand-in on variant_owner_identity_stall; seed-growth row extended (WIP)

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

* Witness: emitted map rendering refused typed; to_string classified CanonicalOrder by the gate route (WIP)

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

* Gate comment names the phase line instead of transcribing its measurement; phase line carries standing_ms (review 73712)

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

* v2: production list order from map_keys -> sorted_map_keys (target_model supplemental-bound and representation-choice nodes, rust_crate_partition first-unknown module, legacy_binding_observation expected ids)

The #12890 warm-row specimen: rust_classical_not_ingested_target_model_staging varied per process because
target_derive_supplemental_generic_bound_requirement_nodes_for_contract built its child list by folding
map_keys (HostUnspecifiedOrder). Keys are Symbol/ModuleId/Int, all admitted by sorted_map_keys, whose order
is identical in both realizations.

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

* Drop determinism_transitive_reachability: population names the unjudged production corpus; receipt for the six map_keys folds found by the #12890 specimen

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

* Emitter: a single-field anonymous record literal matching 2+ structs refuses instead of emitting the bare value; VersionScheme literals name their type; revert stage0 files swept in by an interrupted regen

std.algebra TotalOrder gained the same single 'compare' field as extdeps.version VersionScheme, so
find_unique_struct_name_by_fields stopped being unique and '{ compare: f }' emitted 'f' -- a fail-open
arm (DESIGN section 5). It now refuses exactly as the multi-field arm does; the three VersionScheme
literals carry the nominal type that remedy names.

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

* Split the two cost-debt-rostered sudoers claims out of this PR

The floor's changed cost-debt edit judgment lexes the whole 125 KB emit_test.dag at base and at
head per identity in the interpreter; with these two identities changed, site projection ran past
the 90-minute cap (run 36856989404). Their fix moves to its own PR, held on that floor defect.

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

* live_deploy.emit sudoers claims: needle is the install's own node; unmatchable probe negatives deleted

Split from #12905. Stale since #12602 (/usr/bin/sudo) and #12525 (bash builder quotes every word).

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

* Emitter annotation moved to module-item grain

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

* Retire the one row main's merge made stale (ownership_movable_test#Read); re-census over 7,193 files: 0 refusals after this

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

* Regenerate stage0 (std_algebra, std_primitive_projection, v1_compiler_emit_rust); control: supplemental-bound requirement nodes emit in canonical parameter order (the #12890 specimen at its cause)

regen-round-cost converged in one stage, changed_paths=3.

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

* Floor cost-debt edit judgment: one lex per changed file, shared by every identity in it

v2.workflow.floor_cost_debt_edit judged each changed cost-debt witness in its own call, and each
call lexed the whole base and head file, so a file with k changed witnesses paid 2k lexes. With two
changed witnesses in the 125 KB emit_test.dag, site projection ran past the floor's 90-minute cap
(run 36856989404). The wet entry is now cost_debt_changed_witness_ceilings_at_base, called once
per file with every changed cost-debt function in it. It lexes base and head once, reads the base
resolution once, and selects each declaration from those streams. The host prints
`[floor-cost-debt-edit] judgments= changed_identities=` as the control.

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

* Pin PlannedAsReachConsumer as not a changed-witness selection in the sublane join

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

* clippy: redundant closure in the per-file ceiling call

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

* v2.std.integer: int_ordered_ring composes order: TotalOrder (OrderedRing no longer restates compare/lt/le/gt/ge)

Control supplemental_bound_requirement_order: requirement_nodes_are_emitted_in_canonical_parameter_order
returns true, and false with map_keys restored at the outer fold (discriminating).

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

* Regenerate docs/design-rung-drops.md (docs_projection_gate regen)

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

* rust_item_scan: a raw string literal opened in a body is tracked; an unattributed refusal names its cause

The census could not judge gunbc#12886 because the scanner tracked raw string
literals only when opened on an item header. A `let src = r#"...` fixture in a
body let its own column-zero `}` close the fn early, and its `"#;` then refused
the file (interp_recorded_fixture_witness.rs:458). The same shape put 5 of the
9 hand files on main out of reach. An item ends at its own closing brace, and a
brace inside a literal is not one: every item line is now read for an unclosed
raw literal (token-start `r`/`br`, terminator from its own hash count). Only a
header-opened literal's end may end the item.

v1_interpreter.rs was never unscanned: the scanner reads it whole (1040 items,
36 macro regions) and attributes #12814 completely. #12886's v1_interpreter
refusal is a line inside `thread_local!`, the declared macro-item ceiling, but
it was reported with the out-of-range sentence. The refusal now names which
cause fired.

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

* Regenerate docs/design-rung-drops.md after merging main

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

* RFM: anonymous_record_resolved_by_field_names_guesses_on_ambiguity (the emitter one-field fail-open TotalOrder exposed)

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

* Reach differential: DifferentialBlocking per the operator's 2026-10-01 option-B ruling

Base-arm budget 625200 ms: the largest srv1 base arm measured (312.6 s for 22
identities, loaded host) times 2 for load variance; an arm over it still refuses
with BaseArmOverBudget. PRs still defer to the merge group.

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

* rust_item_scan: an expression-bodied item ends at its own semicolon; a backslash-continued line is string text

A `static NAME: T =` header that rustfmt continues before its initializer puts
the declaration's `;` one indent deeper, so the item stayed open and swallowed
the following items until a column-0 `}`. That was a SILENT mis-attribution:
cli_run.rs `static PROVIDER_BOOTSTRAP_STORE_SKIPS` absorbed
`fn record_provider_bootstrap_store_skip`. Across 22 hand files, about 125
items were never recorded, 7 of them in v1_interpreter.rs
(record_builtin_time_inclusive, canonical_symbol_spelling, ...). An item whose
header ends at `=` now ends at the continuation-indent line that ends the
statement.

A line after a trailing backslash is string-literal text at whatever indent
its author chose, never structure. The line that ends such a literal with `;`
ends an expression-bodied item; ExprBody is read from rust_item_forms, not
listed here. No item key is lost in any hand file, and the refusal count is
unchanged.

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

* rust_item_host_observation: carry the refusal from the one attribution; RawLiteral replaces terminator+flag

Review 73783 found that change_lines_unattributed reduced each attribution to a
line number, and unattributed_line_detail recomputed it. That was the same fact
derived twice (DESIGN §2), and the recompute needed two arms that wrote a
fabricated sentence (DESIGN §5). change_lines_unattributed now matches once
into RustLineRefusal, which has only the two refusing arms
(LineInsideUnnamedMacroBlock, LineBeyondTheFile). The detail is read off that
value, so the record and its sentence cannot disagree.

Also from the review: ItemScope's raw_terminator + raw_opened_on_header could
represent "opened on the header with no terminator". They are now one variant,
RawLiteral = NoRawLiteral | OpenRawLiteral { terminator, opened_on_header }.

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

* std.algebra: the TotalOrder comment names the real (seed-retained) realization instead of a symbol that does not exist (review 73794)

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

* Emitted ordering keys fail closed: v1_rt CanonicalOrdKey (String, i64, bool only) bounds sorted_map_keys and sort_by; sort_by drops partial_cmp(..).unwrap_or(Equal); enrolled one-order claims; seed-growth trigger names the capability and first consumer

neat-boar-16 conditions for executed agreement on #12925: (1) enrolled claims
test.claim.canonical_order_enrolled_witness; (2)+(4) trigger at capability grain naming the first
real consumer; (3) the emitted frontier refuses non-admitted keys typed (on_unimplemented message).

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

* rust_item_scan: a static inside thread_local! is a named item, by upstream citation

extdeps.rust.std_thread_local records std's thread_local! as the pinned 1.93.0
docs state it: the macro "wraps any number of static declarations", and
"Publicity and attributes for each static are allowed". The scanner reads a
thread_local! block as a scope that admits exactly those lines. Each static is
an item of the enclosing module, so a change inside one is attributed to it by
name. Anything else in the body refuses, and so does a one-line
thread_local!(...), which this reader cannot split. Every other macro stays at
the declared macro-item ceiling (macro_rules! controls).

On #12886's tree the census now observes the change completely:
JSON_ENCODE_NESTING is an added static, and the only unreadable hand file left
is phase_profile.rs (extern "C").

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

* rust_item_scan: a header at the open item's own indent refuses; a trailing comment does not hold a declaration open

The swallow class becomes structural. Whatever leaves an item open past its
end -- a continued initializer, a trailing comment, an ordinary multi-line
string, or a construct not yet met -- next meets a sibling item header at the
open item's own indent, and no item body puts one there. scan_step now refuses
at that header instead of reading it as body. Under the prior reader that
refusal fires at the original swallow sites in cli_run.rs and v1_interpreter.rs.

A second instance surfaced by the same measurement is fixed. A one-line
declaration followed by `// comment` did not end in `;`, so it stayed open and
swallowed the next const (resolved_graph_cache.rs PART_DESCRIPTOR_LEN over
V3_HEADER_LEN). A `//` with an even quote count before it now starts a comment.

Files the recurring failure mode as its general class,
gunbc.recurring_failure_mode census_instrument_silently_drops_items: a census
instrument whose parser silently drops items reports a smaller population, and
a short count reads as success. Its distinguishing fact is that a swallowed
item's lines ARE attributed (to the swallower), so a line-coverage join passes.
The violated join is header coverage.

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

* Regenerate stage0 (whole-compiler rebuild: runtime CanonicalOrdKey reaches v1_compiler_stage0_crates)

--regen-round-cost refused with WholeCompilerRebuildRequired (partition generation authority
changed), so candidates were emitted with --required-regen, installed, the whole compiler rebuilt,
and --required-regen re-run: first_generation_equal=true over 161 planned.

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

* Enrolled one-order claims import empty_map/map_insert from v2.std.collection (floor UnimportedBareProvider)

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

* Name the instrument instead of transcribing the probed RAM gap (review 73848)

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

* Merge group: the floor window's base is the group's own parent (merge_group.base_sha), never origin/main

#12514's first live merge_group run (group head 529d438) compared against main
8a249e7 and charged the four PRs queued ahead (#12921 #12735 #12770 #12905) to
this landing: three order-edge claims from #12770 read as regressed.

- extdeps.github.merge_group_event: cited payload reader for merge_group.base_sha
  and the merge queue's group-composition guarantee (cited), consumed by the resolver.
- gunbc.diff_baseline: MergeGroupBase arm; merge_group resolves through
  resolve_merge_group_base, which REFUSES on an absent/empty/unreadable/malformed
  base_sha and never falls back to origin/main. Two-dot comparison.
- Witnesses: payload parsing (nested member, absent, empty, not an oid, not json)
  and resolution (own parent, no parent refuses, cause carried).

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

* WIP: derive gunbc.rung_drop.roster from its directory by declared type (shared fold with RFM)

Unverified by CI; main_wet regen of stage0 mirrors not completed.

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

* #12514: cover PlannedAsReachConsumer in main's newer disposition matches; hoist in-body annotations

Merging main brought six matches over RequiredFloorDisposition written after the
reach-consumer arm existed on this branch (E0004 in emit-build). Each new arm follows
the .dag authority: v2.workflow.floor_changed_witness and v2.workflow.required_floor
treat PlannedAsReachConsumer exactly as Planned (planned standing, gate runs, not a
cost-debt withhold, CostDebtDeclaredButNotWithheld, never suppresses a changed-witness
enrollment).

merge_group_event.dag carried '//' annotations inside a type body, which DESIGN §4c
refuses; they move to the leading block above the declaration.

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

* integration: cover variants that landed on main after the NFR enumerations were written

Composing the burn-downs with main exposed two non-exhaustive matches, the
exact class enumeration exists to surface:
- floor_unimported_bare_provider_debt_roster: three standing matches lacked
  Retired { cause: RelocatedOutOfSourceRoots } (floor refusal, CI run 36931173776).
- target_model realized-closure body classification lacked ParameterReferenceBody,
  added by #12766 (emit-build refusal); it projects like DeclarationReferenceBody.

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

* integration: regenerate stage0 mirrors to a fixed point; cover more variants that landed after enumeration

- stage0 mirrors regenerated locally (claim_executor --required-regen, whole-compiler
  rebuild between rounds) until first_generation_equal=true (161/161 adjudicated).
- DESIGN.md and docs/design-rung-drops.md from tools.docs_projection_gate regen and
  generated_artifact_gate main_wet_verified.
- More matches the NFR burn-downs enumerated before main added variants; each new arm
  keeps what main's removed wildcard returned:
  live_deploy emit identity_member_of_step and member_observe root_members_of_step
  gain ApprovalBrokerFrontDoor (none / []); mtcollins1_kvm_still kvm_pending_step,
  kvm_established_step and kvm_gap_mark gain KvmJournalNavigated/PageConsole/PageError
  (acc / []).

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

* integration: retire 31 bare-provider rows the composed tree no longer carries

The pool-wide standing check (#12908) judged the composed head and found 31 ActiveDebt
pairs whose files no longer carry them (imports added by the other merged burn-downs).
Each is retired as ImportsFixed, exactly as the refusal names (CI run 36939427278).

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

* integration: regenerate after merging main; name runner_microvm_boot_probe's Filesystem authority

- stage0 mirrors regenerated to a fixed point after the main merge (first_generation_equal=true),
  docs/design-rung-drops.md regenerated; main_wet_verified green.
- runner_microvm_boot_probe read Filesystem bare while three modules declare it
  (AmbiguousBareNameRead, floor run 36941252236); it uses Filesystem.Write, so it imports the
  service from extdeps.filesystem.filesystem_io, as its sibling runner modules do.

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

* integration: regenerate the rung-drops projection after the main merge

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

* integration: back out #12610 (typed NFR check D)

Its typed check judges every module the diff touches, and this branch's diff touches
hundreds, so the floor refused with 65 unrostered closed-coproduct wildcard sites
(NonFoldResidueRosterDiverged, run 36948688303). That is exactly the joint landing
#12610 was waiting on (census roster, old-scan deletion, srv1 typed census at 0/0),
which is not built. #12610 is reopened to carry it.

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

* integration: iterative Drop for PortableValue

value_depth_walker_tests::a_deep_value_round_trips_through_the_portable_form aborted the
test process (stack overflow, SIGABRT, rust-unit-tests run 36951304061) when the deep
portable chain was dropped: PortableValue is a plain owned tree, as deep as its value, and had
the recursive default drop. It now drops through a heap worklist exactly as impl Drop for
Value does (class recursion_over_value_depth_uncounted_by_the_call_limit). The test passes
locally, and the other deep-value tests still pass.

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

* integration: green the --lib population #12753 makes blocking

#12753 turns rust-unit-tests into a blocking lane, so this branch must carry a green --lib
population. Main's own reds, which nothing ran:
- closure_edge_demand_tests::required_phase_..._catches_a_bypass judged a second root set on
  the same thread, which #12831's SharedIndexSecondResidentPool now refuses; the twin pool's
  judgment runs on its own thread, as a separate floor run would.
- compile_clean_via_index_verdict_equivalence::regen_subject_admits_a_provider_reached_only_by_
  reference wrote a bare cross-tree reference, which #12741 refuses (CrossTreeBareReference);
  the fixture now writes it qualified, still reference-only with no import.
- nfr_roster_receipt: 13 parameter-scrutinee wildcard sites landed on main after the
  2026-10-01 census; rostered with a stated reason and the owning-fold dissolution.

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

* integration: live-pool tests start from no held pool

live_pool_thread_tests::two_claims_on_the_live_pool_thread_share_one_index failed whenever
an earlier test had left the live-pool thread holding its own fixture pool: #12831 refuses a
second resident pool on one thread (SharedIndexSecondResidentPool). Each live-pool test now
releases the live pool first (yield_live_pool_before_building_another), so its result no longer
depends on test order. The serial suite's live-pool and content-key tests pass (7/7).

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

* integration: regenerate stage0 after the main merge; roster 2 more post-census NFR sites

- v1_compiler_emit{,_rust}.rs regenerated from main's base to a fixed point
  (first_generation_equal=true); docs projection unchanged.
- dag/gunbc/action_use_admission.dag checkout_context_names_a_commit and
  checkout_ref_value_refusals landed on main after the census; rostered like the earlier 13.
- Full serial --lib suite (RUST_TEST_THREADS=1, as CI runs it): 1116 passed, with the only
  failure being these two sites, now green.

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

* integration: keep a deleted file's roster row FileDeleted; stop a test helper from providing 'github' pool-wide

- import_closure_live_test.dag#ReadsLiveTree: the file is deleted on main, so its row stays
  Retired FileDeleted (my conflict resolution had taken ImportsFixed).
- #12835's fleet_converge_checkout_pin_witness_test.dag declares a top-level helper
  'fn github(path:)'. With #12908's pool-wide standing check, that made it a candidate bare
  provider for every module that reads 'github' bare (115 Unrostered refusals, run
  36964372555). The helper is test-local, so it is renamed github_context_access; it no
  longer collides with the 'github' those modules mean.

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

* Revert "integration: merge #12912 (session/deep-deer-663-sudoers)"

This reverts commit 9502c4c, reversing
changes made to c276c43.

* Regenerate stage0 mirrors and rung-drop docs after the main merge (fixed point)

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

* github_app_registry witness: import its live-tree disposition instead of reading it bare

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

* Regenerate rung-drop docs and stage0 mirrors after the main merge (fixed point)

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

* NFR roster: rows for parse_sequence_capture and grammar_emit_sequence (landed on main after the census)

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

* Regenerate stage0 mirrors after the main merge (fixed point)

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

* Regenerate stage0 mirrors and docs after the main merge (fixed point)

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

* Cover main's new LexicalReferenceKind / LexicalReferenceBody in two enumerated matches; docs regen

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

* Bare-provider debt roster: the three body_lowering tests' rows are ImportsFixed on this branch (floor: RosterStale)

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

* NFR roster: delete the 757 rows whose wildcards this branch's burn-down PRs enumerated (floor: stale)

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

* semantic_decl_emission: the four edge-label matches name Authored and StructuralLabel (Named is gone after #12799)

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

* target_model: name StructuralLabel in the wire-child declared-type match; docs regen

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

* match_pattern_binds_erased: carry the pattern's parent_identity (main's VariantPattern field)

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

* program_partition, realization_attempt: name StructuralLabel in three edge-label matches (#12799)

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

* Regenerate stage0 mirrors after the main merge (fixed point)

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

* Regenerate DESIGN.md from the merged design_document (generated_artifact_gate main_wet)

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

* NFR roster: restore main's rows for the five wildcard bodies taken from main in the #12799 merge

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

* Regenerate after the main merge (fixed point)

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

* Regenerate after the main merge (fixed point)

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

* roadmap_belt_actuate: delete belt_spawn_tally_not_admitted, left without a caller once main's arms were taken

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

* Delete two branch helpers left without a caller once main's arms were taken in the #12787 merge

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

* Regenerate stage0 mirrors after the #12787 merge (fixed point)

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

* Bare-provider debt roster: retire three pairs the merged files no longer carry (floor: RosterStale -> ImportsFixed)

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

* unit_standing, runner_microvm_slot_unit: name RuntimeMaxSec in four directive matches taken from main

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

* Regenerate rung-drop docs

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

* Bare-provider roster unit test: ImportsFixed -> FileDeleted now admits (#12787's rule); the reverse still refuses

#12787 made FileDeleted terminal in v2.workflow.floor_unimported_bare_provider_debt without updating this Rust test, which main does not run as a blocking lane.

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

* Regenerate after the #12512 merge (fixed point)

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

* Regenerate rung-drop docs

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

* Regenerate after the main merge (fixed point)

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

* Regenerate after the main merge (fixed point)

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

* Regenerate after the main merge (fixed point)

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

* Regenerate rung-drop docs

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

* runner_unit_live_read: the enumerated converge-verdict arms name VerdictAbsent (#12721)

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

* NFR roster: drop two rows main added for d0 sites this branch enumerates (floor: stale)

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

* integration: floor fixes after the main merge; #12753 retirement text claims only what was observed

- debt roster: fabric_witness_run_test HardRequirements/Shape/current_runner_slot_profile keep
  main's Retired ResolvesInClosure (the floor refuses a changed retirement, RosterRetirementChanged).
- unit_standing_witness_test: import extdeps.systemd { systemd_duration_usec } (Unrostered on the
  floor; the file declares imports so its bare channel is off).
- rust_unit_tests_off_the_merge_path: the merge_group pass had not happened; the text now says the
  merge_group revision is proven by the queue's own required run at landing.

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

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


Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
Heal-Candidate-Run: 37180751525

* Regenerate docs projections (docs_projection_gate regen)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 1)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

* integration: follow main's #13186 (HeadGrain deleted) in the ownership join; LoadCredential arm in the microvm slot unit

- gunbc.refusal_reason_ownership_join: main keyed cause ownership by cause alone and deleted the grain
  field, so a row owns its cause; reason_is_fatal_owned is the cause match. The witness drops the
  HeadGrain control (head_row / head_grain_row_does_not_own_a_fatal_reason): the state it planted is
  no longer constructible.
- runner_microvm_slot_unit: main added SystemdServiceDirective LoadCredential; the enumerated
  directive match was non-exhaustive (floor declarations finding).

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

* integration: delete the 2 NFR rows whose sites no longer carry a wildcard (floor NonFoldResidueRosterDiverged stale=2)

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

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

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


Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md determinism_transitive_reachability
Heal-Candidate-Run: 37235281080

* Regenerate docs projections and witnesses.yml after stage0 regen

* integration: the four rust-unit-tests reds the restored lane surfaced (all stale against main, which runs no unit lane)

- nfr_observation_roster_test: gunbc#13277 enumerated ci_hold_cause_text and drained its NFR row;
  the test now asserts the row stays drained (renamed observation_hold_cause_row_stays_drained).
- process_cwd_mutation_reachability_gate: a_stale_binary_is_refused_before_any_instrument_runs
  reached test_verb's producers, several of which set the process cwd. The freshness refusal is
  split out as stale_binary_refusal and the witness calls it, so the route is asserted without
  reaching any producer; test_verb_after keeps the same behaviour.
- changed_selections_outside_discovery_mirror_tests: since gunbc#13138 the .dag decider returns
  its list as a free-monoid Cons/Empty chain (list_reverse); the test reads either realization.
- renderer_hop_decides_realization_from_declaration_identity_without_an_env: the structural-Bool
  half retires as dissolution of the Bool de-fork (gunbc#12583), mirroring the .dag witness's
  retired row; the prelude control stays.

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

* integration: list_items matches the Value by reference (E0509: Value implements Drop)

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

* integration: pin run_native_serve_program in the cwd gate's undecided set; carry the renderer-hop retirement into its .dag source

- process_cwd_mutation_reachability_gate: main's #13135 declared run_native_serve_program in two
  files, the exact shape of the pinned run_native_claim_program (producer called only from its own
  TargetProducer match; the native_lane_runner twin reached by the qualified cli_run:: spelling).
- compiler_tests.rs is generated from v1.compiler.compiler_tests_rust; the structural-Bool
  retirement is now authored there, rendering the same lines the mirror carries.

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

* integration: the compiler_tests_rust mirror carries the renderer-hop retirement its .dag source now authors

v1_compiler_compiler_tests_rust.rs is the emitted form of v1.compiler.compiler_tests_rust; its
ct_renderer_hop_identity_keying_test is re-rendered in the emitter's own concat shape (the old body
round-trips byte-identically through the same rendering), so the regen's first generation agrees.

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

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 3)

* Regenerate docs projections and witnesses.yml after stage0 regen

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 3)

* Regenerate docs projections and witnesses.yml after stage0 regen

* Reach differential: an unmeasured head and a claim declared at neither side refuse, never pass (review 76405)

reach_claim_verdict returned a non-blocking 'head_not_measured' for a head
with no verdict; it now refuses typed and located (DESIGN 5). claim_differential
mapped NotDeclared at both sides to DifferentialRemoved (never blocks); it is
now DifferentialUndeclaredAtBothSides, which blocks, so a removal runs the
base arm to prove it was one. Tests: an_unmeasured_head_is_refused_not_reported,
a_claim_declared_at_neither_side_blocks_and_a_removal_reports, and
only_a_passing_head_skips_the_base_arm.

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

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

* Reach differential: not_measured is a declared parsed arm; one constructor builds the verdict (review 76416)

ParsedClaimStanding gains StandingNotMeasured, parsed once in
claim_standing_named; reach_claim_verdict and reach_head_cannot_block match the
arm instead of each comparing the string. reach_verdict_of builds ReachVerdict's
name and blocks from ONE ClaimDifferential value, so they cannot disagree; the
two flat fields stay because they are the wire the seed floor runner reads.

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

* Regenerate stage0 mirrors (claim_executor --required-regen, round 3)

* Regenerate docs projections and witnesses.yml after stage0 regen

* floor_demand: typed arm for the cross-claim-share-derivation seam (main's #13043)

#13043 added floor_seam("cross-claim-share-derivation") to the floor runner
without a FloorSeam arm or a FloorSeamToken row; main never runs the unit
lane, so every_floor_seam_literal_has_a_typed_arm was latent-red there and the
restored rust-unit-tests lane caught it. Adds SeamCrossClaimShareDerivation,
its token row, and its arm in receipt_peak_seam.

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

* rung drop rust_unit_tests_off_the_merge_path: retired on its own trigger, runner supply, with the receipt (review 76493)

The trigger_fired text cited the population being green and the job being
re-added, which the row itself says does not retire it. It now cites the
supply receipt from this PR's required runs: the unit job starts with the
other lanes (no queueing) and finishes before floor, so the required wall
did not rise. It also cites the operator's sign-off for the roster addition.

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

* rung drop rust_unit_tests_off_the_merge_path: restore the declaration the last edit dropped (review 76497)

163ef99 replaced the trigger_fired text but cut through to the end of
the declaration's AuthoredProse, deleting the drop's record of what it
declared (and leaving the record without a required field). Restored from
its parent; only the trigger_fired string differs.

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

* Regenerate docs projections (rung-drop retirement text)

* Regenerate DESIGN.md (generated_artifact_gate main_wet_one): the unit-test lane is no longer described as off every CI path

* rung drop retirement: name the instrument for the supply receipt, not the transcribed wall times (review 76511)

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

* Regenerate docs projections and DESIGN.md (retirement receipt names its instrument)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 2)

* Regenerate stage0 mirrors (claim_executor --required-regen, round 3)

* Regenerate stage0 mirrors after the eighth main merge (round 1)

* Regenerate docs projections after the tenth main merge

* required_floor_runner test: cost_debt_clean_outcome carries reach_differential_blocking

Main's test constructor (added with the moved required_floor_outcome_is_clean)
predates this branch's field; the unit lane failed to compile (E0063).
cargo check --lib --tests is clean.

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

* Regenerate DESIGN.md and docs projections after the eleventh main merge

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com>
Co-authored-by: Brian Searls <briansrls@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant