v2 resolve: a kernel type spelling is read by its declaration (own Int shadows, imported user Int refuses) - #12540
Conversation
…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>
…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>
briansrls
left a comment
There was a problem hiding this comment.
Verdict: REQUEST_CHANGES 32194a7
Blocker [P2]: the same-module shadowing decision uses a namespace field that is deliberately empty on the real single-tree resolve door, so an own declaration is misclassified as foreign.
File: src/v2/compiler/03_resolve.dag. Symbols: resolve_atom_declared, build_program_namespace, root_binding_origin, resolve.
resolve_atom_declared passes declared_here = (qualified_name_init(path) == ctx.namespace.module_qn). But resolve(tree, lm) calls build_program_namespace, which explicitly sets module_qn = Empty and separately stores namespace_tree_module_qn(tree) in declared_in. Its comment explains this single-tree distinction. For a root binding, root_binding_origin returns declared_in when there is no imported origin.
Source-trace counterexample, not locally executed: send the normalized form of this PR's own module-p specimen (type Int = | Mine; fn f(x: Bool) -> Bool { let y: Int = 1; x }) through resolve(tree, dag_language_model()), rather than tpb_assemble. The root-bound Int receives declaration path [p, Int]; its parent [p] is compared with module_qn = Empty. declared_here is false, [p, Int] is not a kernel declaration, and the helper returns resolve_reason_kernel_type_spelling_names_a_foreign_declaration. It should resolve to the module's own type and leave any initializer/annotation mismatch to infer. The Bool-shadow specimen has the same defect. This is a wrong refusal, not a demonstrated silent kernel capture.
The new own-name controls call tpb_assemble, and the peer controls call assemble_program_from_ingest; they do not cover this different namespace construction. The existing reordered-Bind tests demonstrate that the direct resolve door is live, but do not declare a same-spelled local type.
Required repair: determine same-module ownership from the existing declaration provenance (declared_in, or a shared ownership predicate correct for both namespace construction routes), not module_qn's lexical-search coordinate. Do not alter every namespace's module_qn merely to mask this comparison. Add a real normalize -> resolve control for the local Int/Bool shadow cases that requires resolution to the local declaration, not merely 'not the canonical atom' on a refused result. Retain the foreign-import refusal, mixed/non-kernel ambiguity refusal, all-kernel ambiguity positive and unbound-kernel controls.
Moving the decision out of lowering and preserving raw type spellings is otherwise the correct boundary repair. The declared kernel-path list remains an explicit residual; reading canonical bindings from declaration marks at every door and deleting that list is a capability trigger. This review does not demand that whole next-rung migration now. It does require the currently promised own-declaration arm to work on both existing resolve routes.
Source and recorded-evidence review; no independent local rerun or merge action.
…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>
|
Re GitHub review 5342739525 (wrong-refusal arm on the single-tree route). Fixed at b55b8a7. Ownership: The earlier boundary, found by running the route: on Controls on that route (
The foreign-import refusal, both ambiguity dispositions, and every earlier row still hold locally. The fix is merged into #12549 at ba77453. — sent from neat-ibex-696 |
briansrls
left a comment
There was a problem hiding this comment.
Verdict: HOLD / REQUEST_CHANGES at exact head 32194a7, after green CI.
CI is green: witnesses run 36445686143 completed successfully; generated, clippy, floor, compiler, emit-build, and witnesses all concluded success. The PR head remains 32194a7.
The advertised repair is NOT in that head. I re-fetched src/v2/compiler/03_resolve.dag at the exact SHA: resolve_atom_declared still compares qualified_name_init(path) with ctx.namespace.module_qn. Comment 5877107479 identifies the repair as b55b8a7, carried by #12549 at ba77453. A fix in that descendant stack cannot clear or approve this unchanged commit.
Correction to my prior review: I withdraw its stated direct-route symptom of a foreign-declaration refusal. The author's executed investigation found the EARLIER boundary: build_program_namespace did not harvest the declarations beneath the normalized module body, so local Int was not bound at all and fell through to the kernel spelling; a non-kernel Myint refused unbound. My earlier trace incorrectly assumed a root hit before reasoning about ownership. The silent capture is the actual reported old-route failure, and changing the ownership comparison alone is insufficient.
I also reviewed the proposed broader-harvest repair rather than stopping at the SHA mismatch. The declared_in ownership predicate and shallow successful harvest are the right direction, but namespace_tree_module_body has a new path-selection blocker. On a header-shaped module root, the QName need not be a containment path. A missing segment resets the traversal to root and later segments can select an unrelated declaration; its record fields are then harvested into the module namespace. The single-segment header/declaration-name collision requires representation-aware selection too. The full source-trace counterexample and narrow repair request are posted on the tree that actually contains the change: #12549 comment 5877487002, scoped to repair b55b8a7 and verified in ba77453. This new helper is not being attributed to the unchanged 32194a7 head.
Required before rebinding: publish the completed repair on the reviewed PR head (or explicitly supersede this PR with the corrected stack), preserve flat/header root-only harvesting, make missing-path traversal absorbing, and retain the real single-tree local Int/Bool plus undeclared-kernel controls alongside the new no-field-leak controls. Then qualify that new SHA in CI. No next-rung declaration-mark migration is demanded here.
Source and recorded-evidence review; I did not independently execute the .dag claims or the new source-trace counterexample. No merge action.
…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>
|
Re GitHub review 5343957887 / comment 5877487002 (P2: namespace_tree_module_body restarted at the root on a missing step). Fixed: #12540 at e519bda, #12549 at 6384e52. The walk by names is deleted. The body is now selected by the graft's own mark.
One spine reader. Name-resolve admission had its own copy of the same descent ( Controls in a new module,
Each asserts the field — sent from neat-ibex-696 |
…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>
briansrls
left a comment
There was a problem hiding this comment.
Verdict: APPROVE 658ca0f
Review 5343957887's P2 is closed. build_program_namespace keeps the prior root harvest and adds the module-body harvest only when v2.compiler.namespace_graft namespace_graft_module_body_optional returns the producer-marked graft body. That helper descends the existing graft spine without restart and returns Present only when the stopping node carries namespace_graft_node_is_module_body; header/flat representations therefore remain root-only.
The two supplied-tree controls discriminate the prior bug: prefix-miss/suffix-hit and flat header-name collision both require the record declaration itself to remain root-bound while its field does not become a module binding. The plain normalize->resolve controls separately establish that a real grafted local Int/Bool declaration is bound locally and that an undeclared Int still takes the kernel binding.
I found no new wrong binding from broadening the single-tree namespace harvest. The added harvest is shallow over the marked body's direct named edges; it does not recursively sweep record fields or nested binders. The body provenance edge uses the same grammar_production_identity_node_projection key already present on the module shell, so this does not introduce an additional authored binding identity.
Exact-head workflow 36484127887 is green: compiler, clippy, emit-build, floor, generated, and witnesses all succeeded. Source/evidence review only; I did not independently rerun the local F->T controls. No merge action.
…solvedTree Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts: - 04_infer.dag: main threads resolved: ResolvedTree through infer's gather (#12407). The payload-family dispatch and its helper take that parameter instead of tree: Node. - v1_compiler_emit_rust.rs: regenerated, not text-merged. Starting from main's mirror, claim_executor --required-regen reached first_generation_equal=true on the third pass. std_types.rs differs from main only by #12798's pub type Unit = (). Also, following review 73303 on #12809 (finding 2): the gather binds the payload family once, with one arm for InferNotALiteralPayload and one for every family, instead of rebuilding each variant. All kernel-String, Symbol and #12540 claims hold on a compiler rebuilt from this tree. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…icates as declarations) (#12969) * v2: ground where-refinement predicates as declarations; resolve binds them Each decidable where predicate is a total Bool declaration (std.types string_non_empty, gt_zero, range; std.content_hash lower_hex_16/40/64/128) and brand a declared marker fn. Lowering carries every predicate of a clause, with its arguments, at its own occurrence; v2 resolve binds each by ordinary name lookup and refuses an unbound one as resolve_reason_where_predicate_unbound. non_empty is respelled string_non_empty corpus-wide (v1 parse/infer tables + stage0 regen) and the gate's non_empty_string consolidates onto it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v2: home the Char classifier in std.unicode.char_class; fix stale predicate homes; import filter std.string_type pulled into the compiler closure broke self-host emission (string_lex_compare E0308); the classifier moves to its own Unicode module instead. Comments naming std.integer as the home of gt_zero/range now name std.types (review 71649). filesystem_io imports the bare filter the floor refused once the file was touched. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * floor roster: retire filter rows discharged by filesystem_io's filter import filesystem_io now imports v2.std.algebra filter, so every file importing filesystem_io no longer carries its bare filter pair; the floor refused the touched one as RosterStale. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * floor roster: retire v2.std.algebra rows reached through filesystem_io The import closure is module-grained: importing filesystem_io now reaches every v2.std.algebra declaration, so skip/any/length rows on its importers are discharged too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * where predicates: execute each declaration against the seed's probe values; stop overclaiming one authority Until v1's tables can consult a declaration (feature:where-refinement-predicate-declaration-authority), the declaration and the table are two representations. The vocabulary witness now executes each grounded declaration on the probe value the compiler is observed to refuse, with boundary controls, one claim per predicate; the comments state the fork instead of claiming one authority (review 71681). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * stage0: restore main's v1_rt.rs (a stale-binary regen had reverted it) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * filesystem_io: drop the duplicate filter import (main added the same one; review 71725) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * MQ-1 PR-2 WIP: caret symbol lowers to a symbol literal * MQ-1 PR-2: RFMs, conservation control, symbol-literal frontier control * symbol literal payload read without a nested Edge pattern (emitted Rust holds the label in an Rc) * caret lowering claims: list_snoc_item from v2.std.algebra; declare the generic-ident-class flip * parse probe: caret-site claims read one warm-shared parse (caret_tree_atom_identities) instead of re-parsing each * caret lowering witness: plain recursion instead of fn-lambda call arguments (the witness is about carets, not the lambda frontier) * caret lowering witness: build lists with list literals/concat (seed types a bare Cons as FreeMonoid) * reference_conservation_admission: drop the braces my merge resolution orphaned (floor/generated: unparseable at byte 6129) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * namecheap witnesses: rename the test helper response -> namecheap_api_response #12421 declared a top-level fn response. The bare-reference scanner reads each service operation's response { ... } block (42 files) as a reference to it, so every PR touching one of those files is refused UnimportedBareProvider. The scanner's missing keyword awareness is reported as its own finding. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v2 resolve: a module's own `type Int` / `type Bool` shadows the kernel 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> * v2 resolve: an imported user Int refuses instead of binding the kernel 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> * v2 resolve: an ambiguous kernel spelling refuses unless every candidate 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> * wip: infer symbol-literal arm (DagCanonicalSymbolLiteral typed as v2.std.node Symbol) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test.claim.parse_test_fn_decl_return_clause: lowering carries the authored 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> * dag_canonical_literal_from_node: match the symbol-literal optional once 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> * Dissolve dag_node_is_symbol_literal_atom: callers match dag_symbol_literal_name_optional directly (review 72280 on #12549) * identity_captured_navigation: read a caret literal's name from the lexeme-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> * Delete the octet-to-scalar index and its lens-slice claims with the lens span route: nothing else consumed them Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * caret_symbol_has_no_lowered_form: the receipt states the literal's type 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> * v2 resolve: the single-tree namespace binds the module's own declarations; 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> * v2 resolve: select a grafted module body by the graft's mark, never by 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> * v2 resolve: move build_program_namespace's rationale above the declaration 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> * RFM reference_conservation_population_omits_class_stamped_terminals: the caret WHY is past tense and names its helper as deleted (review 72492) * v2 infer: a literal payload's facts derive for its own family Review 5348050288. infer_literal_edge_diagnostics_derived decided which literal family owned a payload edge, then dropped the family. infer_literal_payload_entries typed every payload atom as a DecimalDigit, so a Symbol literal's name terminal was recorded as a digit. The edge decision is now typed: infer_literal_edge_payload returns InferIntMagnitudePayload, InferSymbolNamePayload or InferNotALiteralPayload, and the payload fold takes that family. - Int magnitude members keep DecimalDigit / FreeMonoid<DecimalDigit>. - A Symbol name payload is one childless atom and derives as v2.std.node Symbol (symbol_type_node). - Any other shape stays on the frontier. Controls read each payload node's recorded resolved_type (v2.test.claim.body_let_annotation 5e): - bla_symbol_literal_payload_is_typed_symbol_not_digit: F at 87a29e4, T here. - bla_int_literal_payload_digits_stay_decimal_digits: T on both (the integer family is unchanged). Both require at least one payload to be seen, so neither can pass vacuously. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * body_let_annotation: share the payload verdicts, not the inferred trees The floor refused at 92389ff: PureProducerShareWarmNotStored for bla_symbol_literal_as_symbol_tree, because the cross-claim store cannot hold a closure (ServeCacheValueNotPortable, path .value.facts.lookup). The shared producers now return the portable projection the claims inspect: bla_symbol_literal_payload_verdict (the symbol-typed and digit-typed Bools) and bla_int_literal_payload_digit_verdict. The trees are built inside those producers and never stored. The claims and their discrimination are unchanged: the Symbol payload control is F without the family-aware fold and T with it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * 04_infer: the payload comment cites infer_literal_edge_payload, not the deleted predicate Review 72579: the comment above infer_literal_payload_member_type still named infer_literal_edge_diagnostics_derived, which this PR replaced. No definition or reference to it remains. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Merge origin/main; bla_symbol_literal_as_int returns Outcome<ResolvedTree> (the #12432 assemble type) * Import the std.disposition / v2.std.live_tree names two touched files use bare; retire their now-imported roster rows Main newly declared Disposition and LiveTreeDisposition, so the gate refused both files on this touch as UnimportedBareProvider. Importing the declaring modules also covers SingleAuthority, RealizationDispatch and SubstrateInputsOnly, whose ActiveDebt rows retire as ImportsFixed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * roster_gate imports Finding (bare channel is off in a file that declares imports) * reference_conservation_admission: KnownDropShape as a one-variant coproduct (leading |), not an alias to StatementLetBinder With one arm left, '= StatementLetBinder' parsed as an alias, so the variant did not exist and two importers refused IMPORT-MEMBER-ABSENT. The corpus form for a one-variant coproduct is '= | Variant' (e.g. SdramSignalingFamily). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v2: the kernel host-text String, bound only where no String declaration is visible neat-boar-16's ruling after #12549. It mirrors #12549's Symbol pair through the same mechanism. - Declaration: v2.std.node declares the opaque kernel `String` beside Symbol (the kernel-types home), and owns its type node, host_text_type_node. - Binding: v2.extdeps.languages.dag binds the spelling `String` to it, and the declaration table maps v2.std.node.String to it. - Foreign declarations (decision A): String is the one kernel spelling the corpus already declares with another meaning (v2.std.text and std.string_type are FreeMonoid<Char>, imported by 470+ modules), so dag_kernel_type_foreign_declaration types its foreign-declaration disposition as ForeignDeclarationBinds. v2.compiler.resolve then binds the declaration the author reached, and the kernel host text applies only in the unbound arm. Int, Bool and Symbol keep ForeignDeclarationRefuses. - Literal: DagCanonicalStringLiteral is a fourth arm of the one literal decision, typed as host text. Every consumer that matches the literal decision handles it (infer's type binding, branch operand, match-arm body, Bool pattern classify, payload edge, and the undecidable-verdict lens). - No implicit coercion: a host-text literal at a FreeMonoid<Char> position REFUSES. The declared unfold (literal_homomorphism_rows, UnicodeScalarSequenceUnfold) is not reachable yet, because the literal carries no value. That is filed as gunbc.recurring_failure_mode string_literal_lowers_to_one_class_stamped_atom (fix routed to gentle-koi-724's lane). Claims (v2.test.claim.body_let_annotation 5f). The REDs are F with the behavior reverted and T here: - bla_unimported_string_binds_kernel_host_text - bla_string_literal_is_typed_host_text - bla_string_literal_ascribed_int_refuses - bla_host_text_literal_at_structural_string_refuses Controls, T on both: - bla_imported_structural_string_binds_its_declaration - bla_host_text_value_at_structural_string_is_never_matched (no non-literal expression derives host text in v2 yet, so it pins "never a clean admit") - bla_unknown_unimported_type_name_still_refuses The Symbol and #12540 claims are unchanged and still hold. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * carrier_by_spelling: record the v1/v2 String fork and where it resolves (at the importers) royal-newt-820 flagged it and neat-boar-16 ruled. Under decision A, v2 binds `import v2.std.text { String }` to the structural carrier, while v1 keeps the kernel. The fork resolves at the importers: - host-using importers drop String from their imports, in a separate PR ahead of #12760; - structural-using importers are a declared divergence, recorded here, with #12760's census as the instrument. The rung stays at the v1 minimum. Evidence: bla_imported_structural_string_binds_its_declaration. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * dag_canonical_literal_from_node: the string arm matches the atom inline; the is_* predicate is gone Review 73119. dag_node_is_string_literal_atom was a sibling Bool predicate over Node storage, which the literal coproduct exists to replace. That is the same dissolution as dag_node_is_symbol_literal_atom (3fb5d6a, review 72280). The decision matches the atom identity inline. The claim reads DagCanonicalStringLiteral from the decision, and the RFM row cites the decision. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * defork census: the String row names the kernel host-text String as a distinct concept The generated check failed at d9cc153: docs/plans/dag-v2-defork-audit.md drifted, because the census now finds v2.std.node String (#12760) among the String declarations. The derived file list was right, but the authored reading still called every String '= FreeMonoid<Char>, one concept, two declarations'. That is false for the opaque host text. The reading now separates the structural pair from the host-text String, and the projection is regenerated with generated_artifact_gate main_wet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * kernel String: read #12759's string value; realize v2.std.node String as the host string #12759 landed, so a string literal now carries its decoded value as one named payload. - DagCanonicalStringLiteral { value } reads it through dag_string_literal_value_symbol_optional. A payload-less string atom is now a malformed literal. - The value edge is its own payload family (InferStringValuePayload), typed host text and never a digit, as #12549 did for the Symbol name. bla_string_literal_is_typed_host_text now also requires that. - string_literal_lowers_to_one_class_stamped_atom records the climb by #12759. The remaining literal-at-FreeMonoid<Char> refusal is now blocked only by v2 infer not peeling an alias to its body. emit-build failed at 9b7c07f: the opaque v2.std.node String was emitted as its own struct, so the bare String in v2_std_node.rs (symbol_lexeme's return) stopped meaning the host string (E0308). gunbc.rust_source_type_bindings gains the exact row v2.std.node String -> RustStdString beside Symbol's, and the String checkpoint proof records that the kernel spelling now has one declaration rendering the same carrier. The stage0 mirror is updated to match: claim_executor --required-regen reports first_generation_equal=true over 161 files. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * carrier_by_spelling: the importer census is a named frontier, not an instrument this PR cites Review 73214. The receipt called the importer census '#12760's census' and its instrument, but no classification exists in the tree yet. It now says the population is described, not bounded; names the census and deletion lane that will bound it; and states that #12760 is held as a draft until both land, so the flip cannot precede the cutover. When the census lands, the receipt will cite it by symbol. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * where_predicate_binding: assemble_program_from_ingest now returns Outcome<ResolvedTree> (#12629) The binding claims inspect only accept/refuse, so they retype to Outcome<ResolvedTree>; Node is no longer used. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 emit_rust: an opaque declaration with an exact realization row emits an alias to that row Ruled by deep-bee-18 for gunbc#12760. The emitter emitted every zero-parameter opaque declaration as `pub struct X(PhantomData)` and ignored the declaration-keyed rows in gunbc.rust_source_type_bindings. On #12760, v2.std.node String therefore became a struct, and the kernel's bare `String` render inside v2_std_node.rs meant that struct (E0308 at symbol_lexeme). The rule is general and declaration-keyed: rust_opaque_declaration_has_exact_row joins the existing name-keyed kernel-alias route at all three sites that decide it. An exact row emits `pub type X = <row spelling>`. An ambiguous row, or a row with no realization, renders the located compile_error! that rust_exact_binding_spelling already produces, so there is no silent choice. The phantom struct stays only where no row exists. Stage0: v1_compiler_emit_rust.rs is regenerated. std_types.rs gains `pub type Unit = ();`, because std.types Unit is a bare opaque declaration with an exact row (RustUnit) that the old emitter emitted nothing for. claim_executor --required-regen reports first_generation_equal=true. Controls (test.claim.opaque_exact_row_alias_witness_test, each read from the emitted text): - std.types Unit, reached only by its row, emits `pub type Unit = ();` (absent before this rule); - a row-less opaque declaration keeps its phantom struct; - Symbol keeps its row alias. v1 admission (gunbc.v1_maintenance_standing v1_seed_standing): this serves the v2 self-host program, because the emitted compiler closure must build with the v2.std.node host-text String. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * 04_infer: bind the literal payload family once in the gather 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> * carrier_by_spelling: cite the importer census by symbol, and its structural-using population The census is gunbc#12840 (royal-lark-857). Instrument: v2.lens.text_string_importer_census verdict_with_crossings, whose identity join closes (407 = 391 String importers + 16 non-members). The structural-using population, the declared v1/v2 divergence, is 7 modules, named here. It is a lower bound: 120 unclassified and 2 unmeasured importers stay open. #12760 stays a draft until #12840 and the import-deletion PR land. The symbol is cited in prose only, and joins the evidence list once #12840 lands. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * carrier_by_spelling: the structural-using population is 15 (census revision 7b87f99) After neat-boar-16's fixpoint ruling, #12840 classifies 15 structural-using modules. Eight of them are structural only because they pass host text into a module that keeps its import. v2.compiler.tokenize and v2.std.integer are named divergence sites (ruling 1), 10 parse-refused modules keep the import (ruling 4), and 24 remain undecided. The second instrument, text_string_importer_fixpoint, is added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * floor: the live-tree closure reads the process-shared index (one index for the environment and kernel-types closures) closure_paths_of built a fresh MultiEntryIndex over the live dag root per call. A diff touching std/types.dag asks for both the parse-environment and kernel-types closures, so the same name set was indexed twice and #12765's guard refused the floor (MultiEntryIndexBuiltTwiceForOneNameSet, both sites namespace_baseline.rs closure_paths_of). The revision-tree index in evaluate_owned_item_in is a distinct source set and is left as is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Carry one live-tree index to both closures instead of using the thread's shared slot The shared slot holds the floor's own dag+src/v2 index; a dag-only demand there evicted it and the floor refused SharedIndexRebuiltAfterEviction (#12848's own floor). LiveDagIndex is built on first demand by the floor's baseline reconstruction and passed to environment_agreement and kernel_set_serves_both (-> kernel_names_at), so the two closures share one build and the shared slot is untouched. The roundtrip test shares one too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * string_literal RFM: the literal-at-structural refusal is a stopgap; #12809 is its trigger neat-boar-16's ruling on #12760: since #12759 carries the literal's value, the lawful route is the unfold. The row now cites gunbc#12809 (parked on #12726 PR2 and #12506) as the trigger that flips bla_host_text_literal_at_structural_string_refuses to an unfold control. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * lexing: import unicode_char_code_point from std.unicode.char_class This branch moved it out of std.unicode.types (to break the std.types cycle); main's new v2.std.compilers.lexing imported it from the old module, so the v2-native emit of 00_compile refused (emit-build). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP v2 resolve: lexical references keyed by occurrence; infer/eval/translate/emit read them * legacy_repair_tap witness: import Present/Absent from v2.std.optional The witness matched git_sha1_object_id's Optional result with bare Present/Absent. v2.std.execution_surface also declares Absent | Present (a9388e4, the same commit), so once a closure holds both, the four reads are ambiguous and the floor refuses PureProducerShareRowModuleUnframeable (AmbiguousBareNameRead, sites=4). The value variant Present { value } is v2.std.optional's; execution_surface's carries no field. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP: lift unscoped atom arm; flatten infer pattern * WIP: argument may not begin after a newline * WIP: walk-population fixture mints its bound references, as the parser does * Restore main's text in the gap-analysis plan: its non_empty spellings record measurements taken on the old name (review 73826) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v2 resolve: a loop carrier is a binder, kept as the atom it names, never a lexical reference * Debt roster: retire (std/content_hash.dag, get) as NotAReference The floor refused RosterStale: content_hash's get is the builtin get(xs:, index:), whose pair came from the whole-pool fallback resolving it to an unrelated pool fn get. be51d1f (bare loader asks per name) removed that, and retired the same builtin-get pairs elsewhere (e.g. extdeps/bootloader/grub.dag) as NotAReference. This branch touches content_hash.dag, so its row is the one this floor judges. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Review 73872: drop the unused Char classifier; the gate checks its structural strings with v2.std.algebra non_empty - std.unicode.char_class keeps only unicode_char_code_point (consumed by tokenize and lexing). CharClass and char_in_class had no consumer anywhere and are deleted rather than rehomed. - gate's displaced_cost / mechanism_class are v2.std.text String = FreeMonoid<Char>. Passing them to std.types string_non_empty (host text) crossed representations with no declared unfold (DESIGN section 4). The gate now calls v2.std.algebra non_empty, the structural carrier's own check; main's private non_empty_string stays deleted. - The vocabulary comment no longer claims String inhabits no FreeMonoid carrier. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Arrow-body-form mutation mirrors place the lexical-reference arm, as production does * Integration: real three-way merges of the generated stage0 files; name Filesystem's declaring module at its five bare readers The five bare Filesystem reads (harness_cli, harness_turn, runner_microvm_boot_probe, scm.repository_load, scm.repository_save) call Filesystem.Read/Write/List, the extdeps.filesystem.filesystem_io service that v1.compiler.emit_rust emit_file_call binds, so that module is the import. They were refused AmbiguousBareNameRead once #12381's std.types edit brought them into the floor's prepared closure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: thread #12947's lexical field through #12381's where-predicate walk resolve_where_predicate_operator converts resolve_atom's Outcome through the existing resolve_walk_of_outcome (a type's where clause has no lexical binders in scope, and resolve_atom carries no lexical answer), and the unwalked where-set edge carries an empty lexical list. With this, v2.test.claim.parameter_reference's five assembled-program rows (the four the floor failed on #12947 plus pr_named_fn_parameter_is_a_parameter_reference_holds, red on main) return true: #12381's where-predicate binding is what cures main's resolve_unbound_name_is_declared_in_several_modules at the where clause. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "Merge #12760 (neat-ibex-696/kernel-string) into the integration branch (generated conflicts taken from ours; regenerated below)" This reverts commit 2688462, reversing changes made to d5446f3. * Integration: take #12760 back out (operator option A); regenerate #12760's own carrier_by_spelling row orders it after the String import-deletion PR, which has not started. Its merge is reverted, the source-type binding row it added is re-derived away by claim_executor --regen-round-cost (fixed point, rebuild_packages=0), and the defork audit's String row returns to main's. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: #12947's occurrence matches take main's OccurrencePending (#12790) A pending occurrence has no id yet, so it is read like a synthetic one: resolved_tree_lexical_binding finds no binding (Absent), and resolve_lexical_reference refuses it as unkeyed (resolve_reason_lexical_reference_unkeyed). emit-build and the generated lane refused both matches as non-exhaustive on bc718d2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: main's resolve_arrow_resource_requirements atom arm carries #12947's lexical field Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: name the declaring module at three bare reads the combined closure made ambiguous extdeps.cloud.gcp.sts and extdeps.tailscale.acl_api read String bare, declared by both std.string_type and v2.std.text; they import it from std.string_type, the dag/extdeps convention (acl_api's std.types import of String bound nothing). gunbc.systemd_property_directive_overlap reads Unit bare, declared by std.types and v2.std.cardinality; it imports std.types Unit. The floor refused these as AmbiguousBareNameRead (CLAIM-SCOPE) on 430d11d. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: revert #12381's annotation-only edit in an excluded wet receipt; file the floor class it trips The floor selects an annotation-only hunk as a changed witness, contrary to DESIGN section 4c, and refused the head with ChangedWitnessOutsidePreparedSubject for test.manual.command_runner_local_argv_receipt (on the hermetic exclusion list). The annotation correction (non_empty -> string_non_empty) is reverted so the honest edit is not what blocks the integration; the stale annotation and the capability that lets it be restored are rostered as gunbc.recurring_failure_mode annotation_only_edit_selects_a_changed_witness. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Integration: the two spark get rows keep main's Retired ImportsFixed standing Main (#12954) retired them after fixing those imports; a merge here had carried the older ActiveDebt rows forward, which the floor refuses as RosterRetirementChanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
…#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>
Why. Before the Symbol row lands (node adhoc-3b197e76-012), neat-boar-16 asked for a control to decide whether it could go into a spelling-keyed table. The control showed that table could be silently wrong, so this re-key lands first.
What happened on main.
v2.compiler.body_lowering_foldbody_lower_canonical_type_binding_optionalrewrote every type atom spelledIntorBoolto the kernel binding during lowering, before any scope existed. Taketype Int = | Minefollowed bylet y: Int = 1. The annotation became the kernel Int, and infer judged the let matched (DESIGN §5). The same happened when the user'sIntwas imported from another module.Earliest unjustified boundary (§6b). Lowering answered a name-binding question with no scope to answer it from. The decision moves into
v2.compiler.resolveresolve_atom, after a door has selected a declaration. Infer got no guard.How a kernel spelling now resolves:
v2.extdeps.languages.dagdag_kernel_type_declaration_binding_optionallists the declarations a kernel spelling denotes:v2.std.integer/std.integerInt, andv2.std.logic/std.typesBool. A hit on one of these takes the canonical binding, as before.resolve_reason_kernel_type_spelling_names_a_foreign_declaration, typed and located. This covers a declaration reached through an import or through another module. Binding the kernel type there would be silent. Binding the user's type is the next rung. (Ruled by neat-boar-16.)resolve_reason_ambiguous_symbol.dag_kernel_type_binding_optional. That is the correct answer when no declaration of the spelling is in scope.v2.compiler.reference_conservationnow reads the same table instead of importing the lowering function.Evidence (
v2.test.claim.body_let_annotation, section 5c). Run locally with a gunbc built from this tree, then again with the compiler files reverted to main9ce039421d0:bla_module_declared_int_shadows_the_kernel_intbla_module_declared_bool_shadows_the_kernel_boolbla_imported_user_int_refuses_rather_than_binding_the_kernel_int(two-module fixture)bla_ambiguous_imported_int_refuses_rather_than_defaulting_to_the_kernel(p imports Int from q and r)bla_ambiguous_kernel_declarations_bind_the_kernel_type(control: both kernel Ints)bla_undeclared_kernel_spelling_binds_the_kernel_type(route control)bla_infer_admits_int_literal_ascribed_int/..._refuses_..._bool(controls)The shadow rows assert the route (the annotation is not the kernel binding) as well as the verdict. The imported row asserts the typed resolve reason. The new specimens are enrolled in
v2.workflow.floor_pure_producer_share.RFM row
gunbc.recurring_failure_modekernel_type_spelling_captured_a_module_declaration:Mine, and the path list is deleted.🤖 Generated with Claude Code