Repository navigation
Type parameters bind only inside their own declaration (rule 2 / A'; stacks on #13260) - #13265
gunbai-bot[bot] wants to merge 5 commits into
Conversation
…claration (item resolution + topo body resolution); module-scope param_bindings and is_type_variable_name filters deleted. Mirrors NOT regenerated; known regression: fn(K) -> V? loses ? in emitted std_algebra Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ble render arms wrap optional cardinality. Still open: K?/V? on a declaration's type parameter emits without Option (pre-existing on main for record fields; leak masked it for fn returns) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion<K>)
Every arm that spells a generic parameter -- the declared-generic leaf in
render_rust_decl_type and the signature renderer, the TypeVariable arms of
render_rust_type and render_rust_applied_type_arg -- wraps through
rust_carrier_optional_wrap. On main, 'get: K?' in a generic record emitted
'pub get: K' (an absent value had no representation).
gunbc.recurring_failure_mode optional_type_parameter_emitted_without_its_cardinality
filed. native-emission-controls: ControlOptionalParam<K> { get: K? } built with
Absent and Present, read back natively, each with a red.
RED (this tree, fix reverted): EmittedCompilerBuildFailed E0308 at the carrier's
'get: None' (field emitted 'pub get: K'). GREEN: 23/23 held. Mirror regenerated
(pass 2 first_generation_equal=true).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…param scoping; mirrors regenerated (pass 2 first_generation_equal=true). With #13260 underneath, A' changes only its own infer mirrors: std_algebra keeps Option<V>. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ope leak; RED/positive controls Sites (each T is the fresh parameter of the generic reading type it consumes): - extdeps.languages.json.parse json_field_value, json_field_cause - extdeps.docker.container_inspect nested_value, nested_causes - gunbc.machine_intake.mtjade1_access_observation read_cause - gunbc.machine_intake.mtcollins1_boot_diagnostic_bundle members_channel test.claim.type_parameter_declaration_scope_witness (tools.multi_module_compile_fixture): same-module RED, cross-import RED, declared <Q> positive control. New seed: same=T cross=T positive=T. Main seed: same=F cross=F positive=T. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
NO-LAND at this exact head. The declaration-local type-parameter model and the two leak REDs look right, but the whole-tree consequence is not closed: the exact-head floor failed in extdeps.dns.domain_name::parse_dns_label_list. At labels |> list_push(label), the receiver is now inferred as Product(ServeWireResponse) rather than List<DnsLabel>, so list_push is unresolved; the existing frontier row simultaneously reports that its former Primitive(ok) occurrence disappeared. This must not be repaired by merely changing the frontier identity/count—the new receiver is semantically wrong. Restore/establish the binder's List<DnsLabel> type (or land the upstream identity fix that actually does so), then lower/delete the old frontier row from measured ground and rerun the exact-head floor. Run 31519's required CI receipt records both blocking diagnostics.
|
Held behind derived-node-identity step 2 ( What the floor found on head 2d5645a.
So scoping exposes the name-keyed instantiation; it does not cause it. This PR lands only after step 2 substitutes by binder identity. That is the RED step 2 needs. Caveat: a standalone two-module reduction (generic — sent from snappy-wolf-524 |
|
Step-2 evidence from native broker lane 2L (gentle-gull-189), posted here beside 1C's at gentle-dove-36's request. Lane 2L is held and closed: instantiating a generic record literal from its field payloads is the move Everything under "Measured" was observed by emitting Rust with a seed built from main ( The std.list shape
Why name-keyed
|
| expression in the step | type printed |
|---|---|
acc.kept |
List<E> (rendered _) |
map_insert(acc.firsts, key(x), x) |
Rc<HashMap<String, E>> — the receiver's formal, not x's T |
concat([x], acc.kept) |
Rc<Vec<T>> — first argument wins |
concat(acc.kept, [x]) |
List<E> (rendered _) |
In the real duplicated_by_key, every list payload in the step's literals is read back out of acc (acc.kept_reversed, concat([first], acc.kept_reversed) with first from map_get(acc.firsts, ..)). The only genuine evidence for the function's T is the value argument x of map_insert, and that call is typed from its receiver. So a payload-to-formal unify_generics over those fields binds T := T, where the right-hand T is the record's leaked formal. It reads as the function's T only because both are spelled T; today's emitter already leans on the same coincidence (|acc: Rc<DuplicatedScan<T>>, ..|). Rename the record's param and nothing binds.
The same leak with no enclosing generic at all: Same<T> folded over List<Int> prints e: Rc<HashMap<String, T>> in a function that declares no T.
Three more specimens (all on main)
- Formal leaks out of a payload-determined literal.
let s = Scan { firsts: empty_map(), kept: [1] }thenfold(s.kept, init: 0, f: (acc, n) => acc + n)emits|acc: i64, n: E|infn() -> i64, and the siblingempty_map()is erased, althoughkept: [1]determinesE. - Valid code refused.
Pair { left: Scan { firsts: empty_map(), kept: ["x"] }, right: [Scan { firsts: empty_map(), kept: [2] }] }(type Pair<A, B> { left: A, right: List<B> }), thenfold(outer.right, .., f: (acc, inner) => acc + count(inner.kept)): blockingno field 'kept' on type 'B'. - Arithmetic falls off the typed path.
Pair { left: 1, .. }thenq.left + nemits a raw(q.left.clone() + ..)instead ofv1_rt::int_add, becauseq.leftis typedA.
What a name-keyed rule cannot decide (for the step-2 design)
- An owner formal leaked back out of an uninstantiated value vs. the enclosing declaration's parameter of the same spelling. The only discriminator available today is the declared roster by name (
scope.enclosing_declared_type_param_names). - The kernel container slot name: every
List<M>has a child spelledT, so a "does this type mention the owner's param" walk must read slots throughchild_type_node, never by the child's own name. unify_genericsdescends only single-child applications, so a formalMap<String, E>never bindsE.- An application minted for a struct literal reaches the emitter's Rc-carrier decision (
v1.compiler.emit_rustemit_rust_expr_record_lit,rc_name). Inference: a variant literal of a generic coproduct takes the expected application (native broker dns E0599) #13243 measured a qualified-name struct literal losing itsRc::new(there (v2.std.artifactgenerated_artifact_validation, E0308); neither lane traced the arm. - The fold init is inferred before the step; once the step names an application the init must be inferred again under it, or its fields stay uninstantiated while the fold's type is instantiated.
2D (#13243) and I agree a generic literal is one fact — an application of its owner, args from the expected type else from payloads — and should have one instantiation authority; #13243's coproduct-only restriction exists only because of that carrier decision.
Unexecuted 2L patch to src/v1/04_infer.dag (typechecks under an older seed; never run)
diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag
index 0482917b3e..2492c5852d 100644
--- a/src/v1/04_infer.dag
+++ b/src/v1/04_infer.dag
@@ -361,6 +361,8 @@ type FieldInferResult {
typed_field: Node
infer_result: InferResult
diagnostics: List<ErrorNode>
+ authored: Node
+ position_diagnostics: List<ErrorNode>
}
type BuildTypeEnvResult {
@@ -7409,7 +7411,7 @@ fn derive_element_provenance(coll_expr: Node, elem_type: Node, scope: InferScope
// type is unknown expects nothing, as before.
fn infer_method_args_with_fold(method_name: String?, method_args: List<Node>, fold_info: ArgInferResult?, fold_acc_type: Node, element_type: Node, elem_provenance: SubValueRelation, arg_contract: DeclaredArgContract, scope: InferScope) -> List<ArgInferResult> {
let is_fold = method_name_is(opt: method_name, expected: "fold")
- method_args |> enumerate |> map(idx_pair =>
+ let step_blind_results = method_args |> enumerate |> map(idx_pair =>
let a = idx_pair.second
let idx = idx_pair.first
let is_init_arg = arg_has_name(arg: a, name: "init", source_indices: scope.type_env.source_indices) || (arg_name_at(n: a, source_indices: scope.type_env.source_indices) == none && idx == 0)
@@ -7490,6 +7492,52 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List<Node>, fo
}
}
)
+ if is_fold && fold_info != none {
+ fold_record_init_under_step_application(results: step_blind_results, method_args: method_args, fold_acc_type: fold_acc_type, scope: scope)
+ } else { step_blind_results }
+}
+
+// A RECORD-LITERAL INIT OF A GENERIC DECLARATION IS INFERRED AGAIN ONCE THE STEP NAMES THE
+// APPLICATION. The init is inferred before the step, so `init: Scan { firsts: empty_map(), kept: [] }`
+// has no payload that binds E and types as the declaration; the step's return is where E is
+// established (record_lit_payload_application, over a body that conses an element). The fold call
+// already refines its ACCUMULATOR from that return (fold_accumulator_is_unapplied_generic) and
+// never went back to the init, so the fold's type was instantiated while the init's own fields
+// were not: its `empty_map()` reached the emitter with an erased value type (std.list
+// duplicated_by_key). The second inference is the ordinary expected-type route --
+// record_lit_instantiated_fields under the step's application -- admitted only when that
+// application's head resolves to the SAME declaration the init typed as (rc identity), so a step
+// that returns some other type leaves the init as it was. One extra inference of the init, of a
+// literal whose first inference bound nothing.
+fn fold_record_init_under_step_application(results: List<ArgInferResult>, method_args: List<Node>, fold_acc_type: Node, scope: InferScope) -> List<ArgInferResult> {
+ if fold_acc_type.connective != Conj || !fold_accumulator_is_unapplied_generic(n: fold_acc_type) { results } else {
+ match results |> filter(r => is_lambda_expr(e: arg_value(n: r.typed_arg))) |> first {
+ Absent => results
+ Present { value: step } =>
+ let step_return = resolved_type(n: arg_value(n: step.typed_arg))
+ let step_names_the_declaration = step_return.connective == NoConnective
+ && (step_return.children |> count) > 0
+ && (step_return.children |> count) == (fold_acc_type.params |> count)
+ && match lookup_type_for(env: scope.type_env, node: step_return) {
+ Present { value: head } => rc_ptr_eq(head, fold_acc_type)
+ Absent => false
+ }
+ let si = scope.type_env.source_indices
+ let authored_init = match method_args |> filter(a => arg_has_name(arg: a, name: "init", source_indices: si)) |> first {
+ Present { value: a } => Present { value: a }
+ Absent => method_args |> first
+ }
+ match authored_init {
+ Absent => results
+ Present { value: ia } =>
+ if !step_names_the_declaration || record_lit_expr_optional(expr: arg_value(n: ia)) == none { results } else {
+ let again = infer_expr(texpr: arg_value(n: ia), scope: scope, expected: Present { value: step_return })
+ let init_under_application = ArgInferResult { typed_arg: make_arg_node(occurrence_identity: ia.occurrence_identity, name: arg_name_at(n: ia, source_indices: si), value: again.typed, span: ia.span, name_span: ia.span), diagnostics: again.diagnostics }
+ results |> map(r => if r.typed_arg.span == ia.span { init_under_application } else { r })
+ }
+ }
+ }
+ }
}
fn is_lambda_expr(e: Node) -> Bool {
@@ -10335,7 +10383,9 @@ fn infer_map_literal(occurrence_identity: NodeOccurrenceIdentity, map_node: Node
name_span: node_name_span(n: fi)
),
infer_result: ar,
- diagnostics: ar.diagnostics
+ diagnostics: ar.diagnostics,
+ authored: fi,
+ position_diagnostics: []
}
)
InferResult {
@@ -10519,6 +10569,187 @@ fn present_value_expected_from_optional(type_name: String, field_name: String, v
// declares no fields, so `SingleAuthority { reason: "..." }` supplies one that does not exist. The
// ambiguity guard is shared with MissingField for the same reason it exists there -- an ambiguous
// name has not been resolved to a type, so neither half may judge its fields.
+// A GENERIC RECORD LITERAL IS AN APPLICATION OF ITS DECLARATION WHEN ITS OWN PAYLOADS SAY WHICH.
+// `Scan { firsts: empty_map(), kept: [1] }` of `type Scan<E> { firsts: Map<String, E>, kept: List<E> }`
+// typed as the DECLARATION -- the expansion still carrying `E` as a param -- so every reader of the
+// value saw the formal: `s.kept` was List<E>, a lambda over it annotated `n: E` into a function with
+// no E, and the sibling `empty_map()` was inferred against Map<String, TypeVariable E> and reached
+// the emitter with its value type erased (std.list duplicated_by_key, native broker lane 2C/2L).
+// The literal is the earliest link holding the instantiating fact: its field payloads. The call path
+// already reads them -- unify_record_lit_generics walks a literal ARGUMENT's fields to bind the
+// CALLEE's generics, a consumer compensating for a literal that did not carry its own application.
+// This is the same payload-to-formal unification (unify_generics over each declared field type and
+// its payload type), asked once at the literal for the OWNER's params.
+//
+// IT ANSWERS ONLY WHEN EVERY OWNER PARAM IS BOUND BY ADMISSIBLE, AGREEING EVIDENCE; otherwise the
+// literal keeps the declaration exactly as before. A payload type is not evidence when it is
+// unresolved, carries an error, is optional, or mentions one of the owner's own formals that the
+// enclosing declaration does not declare -- that last is the formal LEAKED back out of an
+// uninstantiated value (`acc.kept` of an accumulator typed as the declaration is List<E>), and
+// binding E to it instantiates nothing. Two payloads that bind one param to incompatible types
+// decline rather than letting the first win: a literal typed Pair<Int> over a String payload would
+// be this stage asserting a type its own evidence contradicts.
+//
+// THE ADMISSION IS NAME-KEYED, AND THAT IS THE ROSTERED FORK, NOT A NEW ONE. unify_generics binds a
+// formal by its label, and an owner param spelled like an enclosing declared type parameter
+// (`type Scan<T>` built inside `fn f<T>`) cannot be told from it here, so a leaked formal spelled T
+// is admitted as the function's T. gunbc.recurring_failure_mode generic_identity_decided_by_spelling
+// owns that class and its trigger (declaration identity carried through infer's node-copying
+// constructors); this arm reads the declared roster the way name_is_enclosing_declared_type_parameter
+// does and adds no identity scheme of its own.
+//
+// AN EXPECTED APPLICATION STILL OUTRANKS THE PAYLOADS: record_lit_instantiated_fields instantiates
+// the fields from it and this arm is not asked. The literal's own type on that route stays the
+// declaration (v1.compiler.infer variant_literal_expected_application takes the coproduct half), so
+// one instantiation authority for both halves is still owed.
+type PayloadOwnerBindings {
+ bound: Map<String, Node>
+ conflicted: Bool
+}
+
+fn record_field_declared_type(sf: Node) -> Node {
+ match sf.inferred {
+ Present { value: Resolved { node: rt } } => rt
+ _ => field_node_type_expr(n: sf)
+ }
+}
+
+fn payload_type_carries_error(n: Node, fuel: Int) -> Bool {
+ if fuel <= 0 { false } else {
+ let own = match n.inferred {
+ Present { value: inf } => is_compiler_error(inferred: inf)
+ Absent => false
+ }
+ own || (n.children |> any(ch => payload_type_carries_error(n: child_type_node(ch: ch), fuel: fuel - 1)))
+ }
+}
+
+// A kernel container names its argument SLOT after its own template parameter -- every List<M>
+// carries a child spelled T and resolved to M (make_container_type) -- so a walk that reads a child's
+// own name finds an owner param spelled T inside every list. The slot is read through to what it
+// resolves to (child_type_node); only a bare leaf or a type variable that IS the name counts.
+fn payload_type_mentions_formal(n: Node, names: List<String>, source_indices: Map<String, NewlineIndex>, fuel: Int) -> Bool {
+ if fuel <= 0 || (names |> count) == 0 { false } else {
+ let is_variable = match n.inferred {
+ Present { value: TypeVariable { id: id } } => names |> any(g => g == id)
+ _ => false
+ }
+ let t = match n.inferred {
+ Present { value: Resolved { node: _ } } => child_type_node(ch: n)
+ _ => n
+ }
+ let is_bare_leaf = (t.children |> count) == 0 && t.connective == NoConnective
+ && (names |> any(g => g == authored_name_at(source_indices: source_indices, node: t)))
+ is_variable || is_bare_leaf
+ || (t.children |> any(ch => payload_type_mentions_formal(n: ch, names: names, source_indices: source_indices, fuel: fuel - 1)))
+ }
+}
+
+fn payload_type_is_instantiating_evidence(candidate: Node, leaked_formal_names: List<String>, source_indices: Map<String, NewlineIndex>) -> Bool {
+ candidate.return_cardinality != CardOptional
+ && !payload_type_carries_error(n: candidate, fuel: 16)
+ && is_fully_resolved(n: candidate, source_indices: source_indices)
+ && !payload_type_mentions_formal(n: candidate, names: leaked_formal_names, source_indices: source_indices, fuel: 16)
+}
+
+fn record_lit_payload_owner_bindings(owner_param_names: List<String>, struct_fields: List<Node>, typed_fields: List<Node>, scope: InferScope) -> Map<String, Node>? {
+ let si = scope.type_env.source_indices
+ let leaked_formal_names = owner_param_names |> filter(g => !name_is_enclosing_declared_type_parameter(name: g, scope: scope))
+ let walked = fold(struct_fields, init: PayloadOwnerBindings { bound: empty_map(), conflicted: false }, f: (st, sf) =>
+ let field_name = authored_name_at(source_indices: si, node: sf)
+ match typed_fields |> filter(fi => field_init_node_name_at(n: fi, source_indices: si) == field_name) |> first {
+ Absent => st
+ Present { value: fi } =>
+ let field_formal = record_field_declared_type(sf: sf)
+ if sf.return_cardinality == CardOptional || field_formal.return_cardinality == CardOptional { st } else {
+ let field_evidence = unify_generics(formal: field_formal, actual: resolved_type(n: field_init_node_value(n: fi)), generic_names: owner_param_names, source_indices: si, acc: empty_map())
+ fold(owner_param_names, init: st, f: (inner, g) =>
+ match map_get(field_evidence, g) {
+ Absent => inner
+ Present { value: raw } =>
+ let candidate = child_type_node(ch: raw)
+ if !payload_type_is_instantiating_evidence(candidate: candidate, leaked_formal_names: leaked_formal_names, source_indices: si) { inner } else {
+ match map_get(inner.bound, g) {
+ Absent => PayloadOwnerBindings { bound: map_insert(inner.bound, g, candidate), conflicted: inner.conflicted }
+ Present { value: earlier } =>
+ if node_type_compatible(left: earlier, right: candidate, source_indices: si, text: TextJudgedIn { env: scope.type_env }) { inner }
+ else { PayloadOwnerBindings { bound: inner.bound, conflicted: true } }
+ }
+ }
+ }
+ )
+ }
+ }
+ )
+ if walked.conflicted || (owner_param_names |> any(g => map_get(walked.bound, g) == none)) { none } else { Present { value: walked.bound } }
+}
+
+fn record_lit_payload_application(type_name: String, name_span: SourceSpan, owner_param_names: List<String>, struct_fields: List<Node>, typed_fields: List<Node>, scope: InferScope) -> Node? {
+ match lookup_type_by_name(env: scope.type_env, name: type_name) {
+ Absent => none
+ Present { value: owner } =>
+ if owner.connective != Conj || (owner.params |> count) != (owner_param_names |> count) { none } else {
+ match record_lit_payload_owner_bindings(owner_param_names: owner_param_names, struct_fields: struct_fields, typed_fields: typed_fields, scope: scope) {
+ Absent => none
+ Present { value: bindings } =>
+ let application = Node {
+ occurrence_identity: OccurrenceSynthetic, name: type_name, span: name_span, ident_span: Present { value: name_span },
+ children: owner_param_names |> map(g => match map_get(bindings, g) {
+ Present { value: bound } => bound
+ Absent => error_type
+ }),
+ connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [],
+ body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false,
+ has_non_tail_self_call: false, match_pattern: none, module_item_kind: NotAModuleItem, declaration_marker: Unmarked, declaration: none, expr_data: NoExprData
+ }
+ match lookup_type_for(env: scope.type_env, node: application) {
+ Present { value: head } =>
+ if rc_ptr_eq(head, owner) && record_lit_instantiated_fields(type_name: Present { value: type_name }, expected: Present { value: application }, scope: scope) != none {
+ Present { value: application }
+ } else { none }
+ Absent => none
+ }
+ }
+ }
+ }
+}
+
+// THE SIBLINGS THE PAYLOADS COULD NOT TYPE ARE INFERRED AGAIN UNDER THE APPLICATION, and only those:
+// a field whose declared type mentions an owner param and whose payload came back unresolved under
+// the declaration's formals (`empty_map()` against Map<String, E>, `[]` against List<E>). The
+// instantiated field types are the ones record_lit_instantiated_fields answers for an EXPECTED
+// application, so both routes instantiate a field through one function. A field that was already
+// evidence is not inferred twice.
+fn record_lit_fields_settled_under_application(type_name: String?, application: Node, owner_param_names: List<String>, struct_fields: List<Node>, first_pass: List<FieldInferResult>, scope: InferScope) -> List<FieldInferResult> {
+ let si = scope.type_env.source_indices
+ match record_lit_instantiated_fields(type_name: type_name, expected: Present { value: application }, scope: scope) {
+ Absent => first_pass
+ Present { value: instantiated_fields } =>
+ first_pass |> map(fir =>
+ let fi_name = field_init_node_name_at(n: fir.typed_field, source_indices: si)
+ let payload_type = resolved_type(n: field_init_node_value(n: fir.typed_field))
+ let payload_is_settled = is_fully_resolved(n: payload_type, source_indices: si) && !payload_type_carries_error(n: payload_type, fuel: 16)
+ let declared_mentions_owner_param = struct_fields
+ |> filter(sf => authored_name_at(source_indices: si, node: sf) == fi_name)
+ |> any(sf => type_node_mentions_any_name(n: record_field_declared_type(sf: sf), names: owner_param_names, source_indices: si, fuel: 16))
+ if payload_is_settled || !declared_mentions_owner_param { fir } else {
+ match instantiated_fields |> filter(sf => authored_name_at(source_indices: si, node: sf) == fi_name) |> first {
+ Absent => fir
+ Present { value: instantiated } =>
+ let again = infer_expr(texpr: field_init_node_value(n: fir.authored), scope: scope, expected: Present { value: preserve_outer_optional_cardinality(outer: instantiated, inner: resolved_type(n: instantiated)) })
+ FieldInferResult {
+ typed_field: make_field_init_node(occurrence_identity: fir.authored.occurrence_identity, name: fi_name, value: again.typed, span: fir.authored.span, name_span: node_name_span(n: fir.authored)),
+ infer_result: again,
+ diagnostics: concat(again.diagnostics, fir.position_diagnostics),
+ authored: fir.authored,
+ position_diagnostics: fir.position_diagnostics
+ }
+ }
+ }
+ )
+ }
+}
+
fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type_name: String?, field_inits: List<Node>, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult {
let instantiated_struct_fields = record_lit_instantiated_fields(type_name: type_name, expected: expected, scope: scope)
let expected_struct_fields = if instantiated_struct_fields == none {
@@ -10657,7 +10888,7 @@ fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type
let unbound_owner_param_variables = fold(uninstantiated_owner_param_names, init: empty_map(), f: (acc, g) =>
map_insert(acc, g, type_variable_node(id: g))
)
- let fi_infer_results = map(field_inits, fi =>
+ let declared_formal_fi_results = map(field_inits, fi =>
let fi_name = field_init_node_name_at(n: fi, source_indices: scope.type_env.source_indices)
let unknown_field_diags = match construction_field_names {
@@ -10796,18 +11027,43 @@ fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type
}
Absent => []
}
+ let position_diags = concat(concat(field_type_diags, unknown_field_diags), bare_none_field_construction_diags(
+ fi: fi,
+ fi_name: fi_name,
+ field_declared_type: field_declared_type,
+ type_name_for_message: tn_str,
+ scope: scope
+ ))
FieldInferResult {
typed_field: make_field_init_node(occurrence_identity: fi.occurrence_identity, name: fi_name, value: ar_typed, span: fi.span, name_span: node_name_span(n: fi)),
infer_result: ar,
- diagnostics: concat(concat(concat(ar_diags, field_type_diags), unknown_field_diags), bare_none_field_construction_diags(
- fi: fi,
- fi_name: fi_name,
- field_declared_type: field_declared_type,
- type_name_for_message: tn_str,
- scope: scope
- ))
+ diagnostics: concat(ar_diags, position_diags),
+ authored: fi,
+ position_diagnostics: position_diags
}
)
+ let payload_application = if tn_str == "" || presence_variant_owner != none || expected_variant_node != none || (uninstantiated_owner_param_names |> count) == 0 { none } else {
+ record_lit_payload_application(
+ type_name: tn_str,
+ name_span: name_span,
+ owner_param_names: uninstantiated_owner_param_names,
+ struct_fields: struct_fields,
+ typed_fields: declared_formal_fi_results |> map(fir => fir.typed_field),
+ scope: scope
+ )
+ }
+ let fi_infer_results = match payload_application {
+ Absent => declared_formal_fi_results
+ Present { value: application } =>
+ record_lit_fields_settled_under_application(
+ type_name: type_name,
+ application: application,
+ owner_param_names: uninstantiated_owner_param_names,
+ struct_fields: struct_fields,
+ first_pass: declared_formal_fi_results,
+ scope: scope
+ )
+ }
let typed_fields = fi_infer_results |> map(fir => fir.typed_field)
let fi_own_diags = flat_map(fi_infer_results, fir => fir.diagnostics)
let record_effectful_fields = flat_map(typed_fields, tf =>
@@ -10938,7 +11194,9 @@ fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type
}
let expected_optional_parent = Present { value: "Optional" }
let is_present_ctor = type_name.value == "Present" && local_variant_parent == expected_optional_parent
- let resolved_node = if is_present_ctor {
+ let resolved_node = if payload_application != none {
+ payload_application.value
+ } else if is_present_ctor {
let val_field = fi_infer_results |> filter(fir => field_init_node_name_at(n: fir.typed_field, source_indices: scope.type_env.source_indices) == "value") |> first
match val_field {
Present { value: val_fir } => with_optional_cardinality(n: resolved_type(n: val_fir.infer_result.typed))
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…ision Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Closed without folding in the v1 closeout bankruptcy (#13641). REQUEST_CHANGES (review 78367): it would bind Result's ok to an unrelated fn ok (fabricated type). Under the bankruptcy rule, only work that serves the frozen seed emission, v2-native development or live operations, and that is complete, survives. The branch is kept for archaeology; no follow-up obligation is created. — sent from neat-wolf-604 |
* dispatch-actuator witness: import the lineage, alignment and ticket names #13622's specimen uses Review 78285 on #13622: the supplied-specimen claims call lineage_walk, lineage_is_rooted and alignment_chain and build TicketLine/TicketFields/NodeParent/AdmittedRoot/RoadmapNodeIdentity without importing them. They resolved only through the flat bare-name tier DESIGN schedules for removal, so they would go red when it is cut. Import each from its declaring module. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "Merge #13548 (session/sharp-deer-755-unimported-type-import-migrate) into integration/sharp-raven-357" This reverts commit 1a22abd, reversing changes made to a04255a. * native_emission_controls: repair integration union (close variant_literal_application_cases, one roster, one composition over all 17 case groups) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Exclude #13604 from integration/eager-gull-22: WIP, open REQUEST_CHANGES (review 78326) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs/design-rung-drops.md: regenerate through tools.docs_projection_gate regen after the #13569 merge Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * grammar: import int_to_decimal_string from std.integer (#13436 moved it; #13379's binding-power row still named v2.std.integer integer_int_to_decimal_string) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP: mtcollins1 runner: boot leg, runner image medium + runner-host-up termin * Realize reviewed kernel dependencies through guarded host maintenance * Rewrite the cross-module record-field pin to the refusal it named as its trigger. Infer now refuses `n: true` against `RcfFar` declared in another module; keeping the counted-Undecidable pin would be a meaning fork of the same claim name. Co-authored-by: Cursor <cursoragent@cursor.com> * Close the post-main census: drop the Map interpolation hole, concat the spatial cast. Merging main reintroduced one implicit stringify (Map Display in the canonical-order witness) and left the spatial_dimension `{o as String}` template as a v1 span mismatch. Named Int/Nat/Symbol routes stay; the Map hole is deleted rather than given a fourth renderer. Co-authored-by: Cursor <cursoragent@cursor.com> * Regenerate fleet-converge.yml via generated_artifact_gate main_wet Replaces the provisional #13359 copy taken at merge, which dropped main's printer mode, WIF provider rename and r2_cache options. Diff vs main is now only the two new custody credential options (cursor_worker_turn_api_key, codex_worker_turn_auth). Regenerated remotely (BuildBuddy invocation 3107c1bf-7c17-4bd4-92ec-53bb6b0be1fe) under a cgroup memory.max, regen exit 0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Remove scratch witness scripts committed by the close-out flush (review 78354) The wind-down flush committed untracked local files (.runwit*.sh, .probe2.sh, .wit/) as 32dcf74. They are local receipt scaffolding, not part of the boot leg. This restores the tree to 80c24b3. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * cax onboard: enumerate the closed-coproduct arms the floor's non-fold residue check refused approved_grant_policy, plan_against_policy and provider_controlled_host matched closed coproducts with a wildcard arm; each arm is now explicit, so a new variant refuses at compile rather than being absorbed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * v1 closeout: open PR accounting Every open PR, with its owning lane and its disposition in the mega branch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: add the side-chat dispositions and wave 2 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Regenerate stage0 emit_rust mirror for the integrated authorities (first_generation_equal=true, 0 installs on pass 2) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: bold-bee and qwen dispositions Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: outstanding work, closed PRs, and a re-sweep of all 162 open PRs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: #13607, swift-bat-828 branches Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * integration/silent-lark-156: regenerate generated artifacts after merging #13472 and #13610 Produced by main_wet + claim_executor --required-regen on BuildBuddy at fd4421d; second regen round installed nothing (fixed point). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: silent-lark, gentle-dove, royal-moth, neat-boar, nimble-heron, valiant-crab handoffs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Second-type OpenRouter Retry-After and quota term (review 78356) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * v1 closeout accounting: lively-ram and silent-lark handoffs, #13460 folded, #13108 and #13330 dispositions Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Regenerate docs/design-rung-drops.md and the v1_compiler_emit_rust stage0 mirror for the integrated tree Generated through docs_projection_gate regen and claim_executor --required-regen on srv1; round 2 reports first_generation_equal=true (a fixed point). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: #13488, #13574, #13475, #13634 reviews; #13648 closed; archive-flush residue Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * provisional: gentle-dove-36 mirrors for conflicted generated files (seed bootstrap; regen replaces) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Revert "Merge #13574 into integration/gentle-dove-36" This reverts commit 32720e2, reversing changes made to eee50a4. * provisional: v1_rt.rs from silent-lark-156 (carries host_budget_darwin_physical; seed bootstrap, regen replaces) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * provisional: v1_rt.rs = v1-closeout + silent-lark-156 delta (seed bootstrap; regen replaces) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * v1 closeout accounting: sharp-raven report, #13265, #13574 revert decision Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * provisional: append rt_host_budget (HostBudgetJoin*) to v1_rt.rs (seed bootstrap; regen replaces) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Exclude #13595/#13574 from integration/eager-gull-22 (operator decision msg_c695ffcc) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Exclude #13595/#13574 from integration/eager-gull-22 (operator decision msg_c695ffcc) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix stderr-capture tests so they hit real routes, not decoys. Delete the rustc program that returned Err before spawn without compiling emit_shell_stderr_policy_binding; absent policy is already refused at the emit diagnostic wall. Drive Complete limits from the live host-budget join and keep drain specimens on the emit_rust authority strings. Co-authored-by: Cursor <cursoragent@cursor.com> * fabric_quota: re-attach the window-start comment to quota_window_start (review 78371) checked_second had been inserted between the comment and the function it documents. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Required CI: withdraw the four v1-judged lanes; the gate is emit-build alone (operator ruling 2026-10-09) The operator's v1 withdrawal: v1 is no longer a validation authority, and the one use left to the seed is emitting v2. gunbc.compiler_gate_workflow drops `floor`, `generated`, `rust-unit-tests` and `seed`; the `witnesses` aggregate reads the one remaining lane, `emit-build`, through the same folded roster (one row). The GateArmSkippedOnPullRequest arm leaves with its only inhabitant. The loss is one declared drop, gunbc.rung_drop v1_required_lanes_withdrawn, stated member by member (witnesses, stage0 mirrors and every generated artifact, lint, v1 unit tests, module resolution outside the two emitted closures, the downstream consumers), with a trigger that names the capability: a binary built from an emission of v2 judging that population on the required path. rust_unit_tests_off_pull_requests is Superseded (its lane runs nowhere; trigger did not fire; the new row holds the loss). gunbc.required_ci_contract_epoch moves to 2026-10-09.1: the name `witnesses` now carries a materially different contract. Consumers repaired rather than left dangling: the lane-resolution census roster (the census now does not hold by design and is the instrument that re-derives the drop's module population), DESIGN section 3's typed required-gate reference (gunbc.documentary_refs, now emitted_subject_build_rows), the Building & checks rows, the onboarding path's run-witnesses step, five recurring_failure_mode evidence rows that cited deleted declarations, and the two gate witness files (the blocking set is asserted as exactly emit-build; a new RED asserts the four withdrawn variables reach neither gate surface). Projections regenerated by tools.generated_artifact_gate main_wet (the run peaked at 15.8 GB RSS, against the 7.55 GiB that module's own note cites for 2026-08-31): witnesses.yml, DESIGN.md, docs/design-rung-drops.md, docs/onboarding.md; every other rostered artifact came out byte-identical. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Drop process-global budget env from stderr-capture tests. review 78373: planting Complete limits through GUNBC_MEMORY_BUDGET_BYTES leaked into parallel tests and did not inhabit the emit bind. Claim the drain strings only; leave the host-budget join uncovered. Co-authored-by: Cursor <cursoragent@cursor.com> * regen round 0: stage0 mirrors from claim_executor --required-regen (supersedes provisional splices) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * provisional: re-append rt_host_budget to v1_rt.rs (round-0 regen emitted v1_rt.rs without it; seed bootstrap) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * regen round 2: stage0 mirrors (v1_rt.rs now emitted with rt_host_budget; hand-appended lines gone) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Regenerate generated artifacts for integration/eager-gull-22 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * required_ci_phase_roster: import std.optional (v2.std.optional moved by #13388; stale import from #13225) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * v1 closeout accounting: all lanes reported; remaining merge plan; closed auto-opened PRs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert #13123 (admit_callers enforcement: mega's AdmitCallersEdge is the one enforcer) * v1 closeout accounting: #13516 folded, #13212 dispositioned; every lane reported Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Drop #13545 transcribed-count red chunk (counts derive from ci_runner_sudo_binaries); retarget caller-admission real-route evidence to exact counts Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * v1 closeout accounting: eager-gull review outcomes, #13608 newer head, updated plan Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Drop the seed-growth citation of the deleted absent-policy decoy. review 78381: hand_authored_declarations still named emitted_absent_policy_refuses_before_spawn after that test was removed. Absent policy stays cited as capture_channels_without_stderr_capture_input_refuse_the_union. Co-authored-by: Cursor <cursoragent@cursor.com> * Revert #13586 (receipt-only, excluded by operator review) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Revert #13453 (base-compiler/floor protocol; excluded by operator review): seed Rust, workflow steps and the script-row refusal API go with it Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * WIP: one required job, fresh products, memory envelope, heal-publish deletion (pre-merge, projections not yet regenerated) * stage0 mirrors: restore generated mirrors to the mega branch's coherent set pending one regen round Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * floor_route_gap: give the belt exit-drain expectations their own chunk_43 Two folded PRs (#13442's seeded_filler rows and #13125's belt exit-drain rows) each added floor_route_gap_expectation_chunk_42. The second silently replaced the first and the native emitter refused (duplicate declaration). The exit-drain chunk becomes chunk_43 and joins the roster, so both expectation sets are read. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * live_deploy: reconcile #13599 with #13583's directory authority #13583 made owned directories the single directory authority (directory demands; host_directories) and removed the directory kinds from the ensured steps and the instance parameter from deployment_ensured_steps. #13599, folded alongside it, still called deployment_ensured_steps(instance:, target:) and its witness matched on the deleted step kinds. The call passes target only, and the lab-vs-production fabric-store claim now counts fabric_storage_store_directories demands in deployment_directory_demands. Same claim, read through the surviving authority. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * roadmap_task_record: JSON codec for a runtime RoadmapNode (piece 1, uncompiled draft) * roadmap_task_record witness * roadmap_task_store: chain-partition roster over the fabric state binding, with wet witness (draft) * roadmap_task_record: parent and centering required on the wire; drop nested optionals Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * managed_host: a superseded rung drop is not a standing citation drop_is_standing_citation matched RungDropStanding with Retired and Standing only. Superseded has existed since the 2026-10-06 supersession, and the closeout's seed refuses the non-exhaustive match, which reaches every closure through managed_host (generated_artifact_gate included). A superseded drop no longer stands, so it is not a citation, the same as Retired. (Found by smart-gull-336.) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP: federation retired-path row below imports; floor_demand pinned envelope rows; managed_host Superseded arm (pre-regen) * Headless Claude dispatch: print argv, systemd unit, stream-json projection. When the harness has no spark, ExecutorDefault can admit Claude if custody is present; events stay in the belt's Codex envelope. Credential converge on srv1 remains an operator decision. Co-authored-by: Cursor <cursoragent@cursor.com> * closeout: complete the #13453 revert -- gunbc.fleet_desired_admission_workflow no longer imports the deleted script-row refusal API 6ee1d21 (integration/v1-closeout) removed fleet_desired_candidate_fetch_script_row and candidate_scripts_refusal from gunbc.fleet_desired_candidate but left their consumer, so every entry whose closure reaches the generated-artifact registry refused to resolve (regen, verify, five gate witnesses). This is origin/main's shape of the file: the admission workflow emits its YAML directly again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * closeout: complete the #13453 revert -- gunbc.fleet_desired_admission_workflow no longer imports the deleted script-row refusal API 6ee1d21 (integration/v1-closeout) removed fleet_desired_candidate_fetch_script_row and candidate_scripts_refusal from gunbc.fleet_desired_candidate but left their consumer, so every entry whose closure reaches the generated-artifact registry refused to resolve (regen, verify, five gate witnesses). This is origin/main's shape of the file: the admission workflow emits its YAML directly again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 94464b1) * roadmap_task_record: balance ticket decode braces Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Address review 78387: one Claude event mapping, explicit executor, transmit effort. parse_codex_jsonl now classifies bounded Claude stream-json via claude_code_line_codex_kind; jq only bounds those lines. ExecutorDefault stays a harness refusal. Print argv carries --effort. Co-authored-by: Cursor <cursoragent@cursor.com> * v2 compiler: reconcile #13438's precedence climbing with #13582 and #12942 Two merge-born references to deleted code, found by emit-build on #13641: - 02_parse: #13438's infix stamp still wrote ParseProvenanceState.frame / FrameMinted, which #13582 deleted with the packrat memo. The write goes; the sibling stamps already carry none. - body_lowering_fold: #12942's sealed body_lower_fold_raw kept the pre-#13438 pipe-tower test (body_lower_is_pipe_tower_root / body_lower_tower_pipes_into_fold), which #13438 deleted. It now uses #13438's replacement predicate, body_lower_application_pipes_into_fold, and keeps #12942's sealed outcome. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fleet_converge_workflow: drop MtCollins1UiBundleObserve from the mode list #13503 removed the UI-bundle-observe mode (AMI-bundle-derived MegaRAC content) from FleetConvergeWorkflowMode but left it in fleet_converge_workflow_modes. Every name in the list now resolves to a declared variant. (Found by smart-gull-336.) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP: trip is a ByteSize derived from the slot envelope (review 78388 item 3); witness claim the_trip_sits_inside_the_slot_envelope * Address review 78389: emit tmux event pipe only for tmux containers. Claude and harness systemd spawn no longer derive readiness from tee/pipe emission or refuse as tmux-event-pipe-emit. Co-authored-by: Cursor <cursoragent@cursor.com> * closeout: two stale references from folded deletions - first_element_of_a_list_has_three_spellings cited v2.std.optional Optional; the module is std.optional (#13388's move). - authorization_pattern_selection_witness imported PastedOperatorToken, which #13568 removed with the pasted-token refusal; the import was unused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Regenerated projections for the one-job gate, on the merged closeout tree One main_wet of tools.generated_artifact_gate over this branch merged with integration/v1-closeout a925452 (regen 632 s, verify 693 s, both exit 0, on srv1 under capped MemorySwapMax=0 scopes), nine artifacts: - witnesses.yml: both subject steps carry GUNBC_BIND_MEMORY_CGROUP_BYTES (the derived trip, 20 GiB) and the failure notice carries the envelope lines (what 137 means, no larger runner and no retry, the MEMORY RECEIPT). - DESIGN.md, docs/design-rung-drops.md: the CI row and the drop roster. - .gitattributes: the deleted heal-publish.yml leaves the generated-artifact merge list. - fleet-converge.yml: the closeout's authority fix projected. - tools/fabric_ci_fci1_bounded_execution_context.env: the fci1 context follows the slot (22/21 GiB). - provisioning/srv{1,3,4}/gunbc-ghrunner.sudoers: a 22 GiB slot fits more slots per host than a 26 GiB one, so the derived rosters grow (srv1 gains srv1-10 and srv1-11). Desired state; applying it is the converge effect. The witness batch on the same tree: 16 files, green except the two latent reds already recorded in the PR (fci1_bounded_execution_context: a stale envelope-basis expectation; heal_publication_boundary: 23/34). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Enrol roadmap_task_store wet witness on the local-repo wet lane, as the allocation seam witness is Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Land the v2 cutover program as designed roadmap entries: 11 nodes, native_obligation_population plan, edges, RED acceptance witnesses Co-Authored-By: Claude Sonnet 5.5 <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 belt_liveness_publication_answers_unconsumed Ledger-Rows-Repaired: docs/design-rung-drops.md bmc_secure_apply_converge_new_witness_eval_step_cost Ledger-Rows-Repaired: docs/design-rung-drops.md edited_bin_witness_wet_rows_not_executed_by_ci Ledger-Rows-Repaired: docs/design-rung-drops.md fixture_closure_union_unmodeled_stderr_capture Ledger-Rows-Repaired: docs/design-rung-drops.md handoff_observer_is_sol_not_kvm_viewer Ledger-Rows-Repaired: docs/design-rung-drops.md kvm_observer_protocol_wet_witnesses_deleted_with_the_observer Ledger-Rows-Repaired: docs/design-rung-drops.md mtcollins1_boot_matrix_enrolment_dead_band_observed_only Ledger-Rows-Repaired: docs/design-rung-drops.md mtcollins1_boot_matrix_new_witness_eval_step_cost Heal-Candidate-Run: 38000315997 * closeout: regenerate stage0 mirrors and workflows from the folded tree One emission round (operator ruling 2026-10-04) on srv1 at a925452: claim_executor --required-regen, then generated_artifact_gate main_wet. Then on the regenerated tree: seed build OK, gunbc test //gunbc/instruments:v2-native-cli exit 0, //gunbc/instruments:self-host exit 0. Settles the files the folds left provisional (fleet-converge.yml, the std_* and v1_compiler_* mirrors). docs/design-rung-drops.md was already regenerated by CI auto-heal (17a309c). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * WIP: option B -- subject steps require the slot envelope; per-step trip withheld by the declared drop native_step_trip_awaits_fleet_job_cgroup; slot-grain receipt in gunbc test; seed-growth receipt (pre-regen) * Enrol roadmap_task_store wet witness in floor_route_gap and the local-repo wet terminal, as the allocation seam witness is Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Regenerate ROADMAP.md, docs/plans and .gitattributes for the cutover rows; repair updated(...) wrapping Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Describe the envelope as slot-grain (option B) in witnesses-one-required-job; regenerate projections on the merged head Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Type the cutover receipt readings (closed kinds, ByteSize) and make the peak-above-trip control compare against the slot trip Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Subject steps require the slot envelope; the per-step trip waits on a fleet fact; the envelope decision is a .dag fold the seed mirrors The first required run that passed GUNBC_BIND_MEMORY_CGROUP_BYTES (38002497388 on a4b8f78) refused in four seconds: MemoryCgroupBindRefused, the cgroup2 tree is not writable. memory_governor apply_memory_cgroup_bind creates its leaf at the cgroup ROOT (a container-root design; the bind had never been requested on the fleet) and a fleet job runs as the setpriv'd job user under a root unit, so no job process can create the bound. The operator approved the slot-grain arm (escalation 2026-10-09). gunbc.memory_envelope (new) owns the decision and the verdict as folds over supplied inputs -- the sibling of gunbc.memory_cgroup_binding -- and test.claim.memory_envelope_witness_test reaches every arm by supplied value, including the RED an inline decision could not: a slot requirement over a process no numeric memory.max binds REFUSES (MemoryEnvelopeAbsent) rather than running as bounded. The seed mirrors it arm for arm with unit tests; the shells resolve the bounding cgroup through binding_cap_cgroup_dir (never the peak locator), read memory.swap.max/.current/.peak (modeled in extdeps.linux.cgroup_v2_memory) before and after the producer, print a slot-grain MEMORY RECEIPT with event deltas and the peak labelled by whether it rose, and refuse the run on any OOM kill or swap. gunbc.emitted_subject_build_gate carries two envelope inputs and ONE decision over them, native_step_memory_inputs(ownership): every subject step REQUIRES the slot envelope (GUNBC_MEMORY_ENVELOPE_REQUIRED=slot, the projection of EnvelopeSlotRequired) and the bind input at the derived trip is withheld while gunbc.runner_slot_desired gunbc_runner_slot_job_cgroup_ownership is JobOwnsNoBoundedCgroup. That is a fleet fact, not a rung drop -- nothing on the required path ever held the trip -- so the climb is rostered as gunbc.guarantee_stall native_step_trip_awaits_fleet_job_cgroup_stall (grounding: unit delegation with DelegateSubgroup=, a per-job cgroup staged by the root JIT wrapper, the governor's already-bound arm). The workflow and the failure notice consume the fact; the witness exercises both arms by supplied value, reads the live row, and asserts the bind KEY is absent. The slot wall follows the ruling too: gunbc.runner_slot_allocation gunbc_runner_slot_allocation_wall_holds drops its three floor conjuncts (a slot sized to a tenant that no longer runs in it) and requires MemorySwapMax == 0 instead of a swap above the maximum; the floor-fit drop slot_row_pinned_below_demonstrated_demand_unrefused is Superseded with v1_required_lanes_withdrawn as its loss holder; the slot witness re-pins the row to 22/21/0 and its width alarms to the smaller slot's derivation (srv1 12, srv3/srv4 21). The slot's demand oracle from here is the first cold required run's MEMORY RECEIPT, a declared frontier. The trip stays a ByteSize derived from the slot (review 78388 item 3). The seed growth is receipted as gunbc.memory_envelope_receipt_seed_growth (review 78391). The design document's CI row and the slot row's note say the same. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * emit_rust: locate module via ModuleIndex.by_name; is_known_variant reads carried variant_to_enum (port of #13608 23f2d08, 8ff94ca; mirrors pending regen) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * decimal_digit_of_units: construct the units digit via the successor table; no D9 default for out-of-range Int * closeout: bind variant_to_enum correctly at three #13665 call sites import_variant_parent_for_name has no emit_info parameter; emit_specific_import_use_lines has no variant_to_enum binding. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Regenerate ROADMAP.md on the merged head; re-cite the envelope fact and stall Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Take sold Group B (srv9-srv12) out of everything that reaches hardware; declare fixture residue as a rung drop Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Supply sold Group B (srv9-srv12) as in-witness fixture population; production rosters stay empty Chain: the scoped cut emptied dgx_spark_reserved_identities and the router bindings, so witnesses that discriminated on the Group B population (commitment standings, admissibility, rail rows, topology membership, reach labels) read nothing. spark_host_commitment_witness now folds the production placement, claim and reservation rows over a local four-host fixture, with one inhabitance claim that the production roster is empty; the topology, reach and site-locale witnesses are re-derived to the emptied rosters. Under rung drop serving_fixtures_name_sold_group_b_hosts. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Regenerate std_integer stage0 mirror (remote required-regen candidate) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * closeout: revert #13662's fold (operator decision 2026-10-10) #13662 (headless Claude worker) stays outside the closeout. A child re-lands it into main after #13641, with its review findings resolved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Recut to five durable outcomes: cold-run envelope receipt rename, acceptance-receipt framing, derived-universe denominator, stable frontier subject; six chores moved to runtime tasks; no red witnesses Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * roadmap: split the event carrier's directory demand into a leaf module gunbc.roadmap.dashboard_instance_directories imported gunbc.roadmap.roadmap_event_carrier for one directory function, and through it the dispatch actuator. With #13625's host_standup -> host_effect import (c390a49), that closed a 13-module cycle (materialized_secret -> host_phase_status -> host_standup -> host_effect -> live_deploy.spec -> dashboard_instance_directories -> roadmap_event_carrier -> roadmap_dispatch_actuator -> cursor_harness_credential -> ...), and main_wet refused to resolve. The demand moves unchanged to gunbc.roadmap.roadmap_event_carrier_directory; the carrier, the directory list and the owned-directory witness import it from there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address review 78405: delete the never-red frontier-count decoration; eligibility and disjointness controls run over supplied members Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * closeout: five merge-born refusals that main_wet found - managed_host: HostnameAllocation no longer carries canonical_hostname; read it through allocated_canonical_hostname (hostname_allocation's name scheme, #13625). - host_control_route: handle ManagedHostFoundUnderDeclaredDrop the way managed_host's own account lookup does: the standing still decides the BMC route. - mtjade1_arrival_federation_provision: DedicatedFederation's principal_set became impersonation: FederationImpersonation; the arrival pool is a standing-pool impersonation. - fleet_workflow_steps: ci_fleet_wif_auth_step_when passed if_condition twice (a merge of #13607 and #13625). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Make fleet-converge branch-agnostic and parseable. GitHub refused the workflow on every push after the mode input description crossed ~10k characters. Shorten that description to an authority citation, pin WIF to the workflow file on any heads ref plus workflow_dispatch (not pull_request), and admit a deploy from the current branch when --candidate-branch is empty. expected_revision stays a check when supplied and otherwise is the dispatched sha. Co-authored-by: Cursor <cursoragent@cursor.com> * Name the branch-dispatch ruling; type malformed expected_revision. Comments no longer claim reviewed-main file trust. Absent vs malformed expected_revision are separate arms so admit_optional cannot parse prose. Co-authored-by: Cursor <cursoragent@cursor.com> * Declare the named-revision and deploy-branch drop. Those two refusals are a different subject from the WIF main pin; §4b(3) needs its own population and trigger. Co-authored-by: Cursor <cursoragent@cursor.com> * Recut #13660: restore privileged WIF to reviewed-main equality. A rung drop does not substitute for the trust boundary. Privileged fleet-converge federations pin workflow_ref and ref at main again; session-branch admission lives only on the development pin list, which is not bound to fleet-cloud-convergence. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop leftover census conflict markers and project the named-revision drop. The recut commit had kept rebase markers in gcp_iam_approval_enforced_in_reviewed_code; the projection now carries fleet_converge_named_revision_and_branch against closeout. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix OidcClaimPin inhabitance and the privileged-pin wording fork. branch_dispatch_claim_pins now constructs event_name via oidc_equals. Privileged jobs are described as reviewed-main equality; the development pin list is named as a frontier, not a live federation. Co-authored-by: Cursor <cursoragent@cursor.com> * Split presented OIDC claims from pins; printer session-branch is a red. Privileged printer pins equal reviewed main, so a concatenated session-branch workflow_ref must refuse. Admission now takes OidcPresentedClaim (name and value only); relation lives only on the pin. Co-authored-by: Cursor <cursoragent@cursor.com> * Regenerate fleet-converge.yml (21 inputs) and pin dashboard-deploy to main. GitHub refused the hand-edited 30-input file; emission from fleet_converge_dispatch_inputs is the repair. dashboard-deploy now requires refs/heads/main and environment srv1-production so a branch dispatch cannot wet-deploy production. Co-authored-by: Cursor <cursoragent@cursor.com> * closeout: revert #13663's fold (operator ruling: #13662 and #13663 stay outside the closeout) deep-cat-540 recuts it onto main after #13641. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Omit Spark dispatch when the administrator roster is empty. Review 78408: regeneration had folded a sold-out Spark roster into target options: [] while spark_* modes stayed selectable. Restoring srv5-srv12 would invent enrolled hosts. Emission now drops the target input and spark_* mode options, and refuses any remaining empty InputChoice. Co-authored-by: Cursor <cursoragent@cursor.com> * Treat srv1-production environment protection as the root-mutation boundary. A branch dispatch runs that branch's YAML, so a github.ref if is not a trust boundary. dashboard-deploy, approval-broker-dark-install and microvm-controller-install now name srv1-production; the required GitHub setting (main-only deployment branches, required reviewers) is modeled with an unobserved readback. Checkout is the event sha. Co-authored-by: Cursor <cursoragent@cursor.com> * closeout: stage0 mirrors and projections regenerated at a fixed point on 5c0d9d5 The composed closeout tip (the #13663 revert and #13664's fixed head folded) could not regenerate itself: claim_executor --required-regen refused with Stage0EmittedEdgesNotCovered (62 emitted edge endpoints with no stage0 crate) and the committed mirrors did not build a seed. Two generation-1 facts explain both, and both are repaired in this set rather than worked around. First, the regen's coverage check reads the host-shell roster from the TREE's src/v1/stage0/src/lib.rs (required_regen_host: closure_modules(lib.rs)), not from the seed. The integration-side regen from the d9368e8 seed, an emitter predating the crate planner (#13597), rewrote lib.rs without the three pub mod lines #13597's head 3674580 carried for gunbc_crate_partition, gunbc_emitted_crate_workspace and v1_compiler_emitted_workspace, while their mirrors and .dag sources stayed. Restoring the three declarations lets the regen run; the regenerated lib.rs then lists them canonically, which is the only change this set makes to lib.rs. Second, --required-regen renders v1_rt.rs from the SEED's compiled-in runtime rows, so a boot seed older than the tree's runtime_rust.dag emits a candidate without the host-budget join that the tree's memory_governor mirror consumes, and generation 1 does not build (the closeout history records the same provisional step at 42954d2). The committed v1_rt.rs is kept for generation 1; generation 2, whose seed carries the tip's rows, emits it identically, so v1_rt.rs is unchanged here. Recipe, on a shallow clone of 5c0d9d5 on srv1, each step under systemd-run --user --scope -p MemoryMax=80G -p MemorySwapMax=0: boot seed built from 3674580; main_wet; lib.rs roster repair; required-regen with the boot seed (first_generation_equal=false, 244-file candidate); install; v1_rt.rs restored; then the tip's own seed: build, main_wet, required-regen (generation 1: divergent, candidate installed; generation 2: first_generation_equal=true). No .dag file changes. The projections are main_wet's output over the composed tree: fleet-converge.yml regenerated from its 21-row authority (the committed 30-input file was drift), ROADMAP.md and docs/plans/native-obligation-population.md for #13664's recut, docs/design-rung-drops.md for the supersession, .gitattributes for the plan projection's merge driver. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fleet-converge: omit the Spark target input and spark_* modes while the administrator roster is empty; refuse an empty choice at emission (port of ffe8a90) The fixed-point regeneration on 5c0d9d5 faithfully emitted .github/workflows/fleet-converge.yml with `target: type: choice, options: []`, because gunbc.spark.credential_workflow spark_administrator_credential_roster has been empty since 2026-10-10 (every Spark sold) and gunbc.fleet_converge_workflow had no wall for an empty closed choice. GitHub rejects a choice input without options, so the regenerated workflow would have been undispatchable in every mode, not only the seven spark_* modes that read inputs.target; the previously committed file was drift the other way (hand-kept srv5..srv12 options for hosts no longer enrolled). Review 78408 on gunbc#13660 found this, and snappy-stag-26 fixed the authority there at ffe8a90; that PR is ruled outside the closeout at its WIF scope, so this commit ports exactly the empty-roster hunk and nothing of the WIF or environment changes. What changes in the authority: fleet_converge_spark_target_modes names the seven modes that consume the target; fleet_converge_dispatchable_modes() drops them while fleet_converge_spark_target_options is empty, and fleet_converge_mode_options is derived from it; the dispatch inputs are now fleet_converge_dispatch_input_rows filtered by fleet_converge_dispatch_inputs, which omits `target` while the roster is empty; fleet_converge_empty_choice_input_names() enumerates every InputChoice with no options over the four DispatchInputType variants, and expected_fleet_converge_yml() refuses emission with those names before the input-count check (DESIGN section 5: refuse, do not emit options: []). The witness every_dispatch_option_is_a_wire_value_of_the_vocabulary joins the options to the dispatchable modes, and empty_spark_roster_does_not_emit_an_empty_choice_or_spark_dispatch_modes pins the current roster state. The fleet_workflow_steps.dag hunk of ffe8a90 is not needed here: the closeout's ci_fleet_wif_auth_step_when already passes if_condition by name. The regenerated fleet-converge.yml is main_wet's output over this authority with the fixed-point seed; the stage0 mirrors are unchanged (the module is not in the emitted population) and required-regen stays at first_generation_equal=true. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * closeout: delete the accounting doc; the terminal ledger lives in #13641's body (review 5474794145) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * closeout: revert the #13664 fold (5c0d9d5) per the operator's review 5477471759: close #13664 without folding, branch preserved; projections regenerated next * deployment environments: model the branch policy as GitHub returns it (name + branch-or-tag rules), so the srv1-production standing can be discharged by a faithful GET (review 78420) Review 78420 on gunbc#13660 (folded here at 60c9457) found that extdeps.github.deployment_environments modeled the deployment-branch policy as SelectedRefs { refs: ["refs/heads/main"] }, while the API carries no refs: the environment object's deployment_branch_policy is null or { protected_branches, custom_branch_policies }, and the custom rules live at GET /repos/{owner}/{repo}/environments/{name}/deployment-branch-policies as branch_policies rows { name, type } with type "branch" or "tag". A reading of the real API can therefore never match the modeled refs, so gunbc.auth.github_deployment_environment's standing could never move from Unobserved to Holds (DESIGN section 3: model what the API actually returns; section 5: a check that cannot be discharged is not a boundary). The model now carries DeploymentBranchPolicyRule { name, ref_type: PolicyRefBranch | PolicyRefTag } under SelectedBranchesAndTags { rules }, the srv1-production requirement is the single branch rule named main with required reviewers, the restriction predicate requires exactly one rule that is a branch named main, and the read obligation names both GETs and the shapes they return. The witness gains a supplied-value control: a tag rule named main and a two-rule policy are not the main-branch boundary, the single branch rule is. Standing stays Unobserved until the operator applies the setting and its readback lands; that flip is the first follow-up on main. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * closeout: regenerate at the fixed point on composition A (revert of #13664, fold of #13660) Same recipe as f8c3fa4, on a shallow clone of dbdc9d2 with the previous fixed-point seed as the boot seed (srv1, logs8): main_wet exit 0; required-regen generation 0 drifted gunbc_cli_dispatch_surface.rs (gunbc.cli_dispatch_surface is touched by #13660), generation 1 drifted gunbc_cli_dispatch_generated.rs, generation 2 first_generation_equal=true planned=169 executed=169 adjudicated=169 declared_divergent=1 [main.rs]; verify (dry main) exit 0; rebuild; gunbc test //gunbc/instruments:v2-native-cli exit 0 (emit and build exit_status=0 warning_count=0 wall_s=611, discriminating red on v2_cli_compile_cli) and //gunbc/instruments:self-host exit 0 (wall_s=716, red on v2_compiler_compile). The projections resolved toward #13660's side in the merge (ROADMAP.md, fleet-converge.yml, docs/design-rung-drops.md) were byte-identical to main_wet's output, so only .gitattributes and the two cli_dispatch mirrors change here. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: gunbc-ci-auto-heal <briansrls@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> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: x <x@x> Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com>
Native broker 1C, rule 2 (ruling A' by gentle-dove-36). Stacks on #13260: its commits appear in this diff until it lands. Held behind #13164, since it is an emitter/infer-mirror PR.
Root cause (§6b)
A generic function was emitted without its type parameters because
v1.compiler.inferbuild_type_envparam_bindingsinserted every generic type declaration's parameters into the module environment:type Box<Q>made a bareQresolve anywhere in that module, and in its importers.fn f(x: Int) -> Qwas then accepted with no<Q>, and even returned anIntas aQ.is_type_variable_name, a hard-coded list ofT, K, V, MappedElement, FoldAccumulator, was the patch that stripped those names from import surfaces again.Two controls ran before any change:
Twith no generic type in the module was already refused.Qwas accepted aftertype Box<Q>.So the defect was the scope leak, not the list.
Change
v1.compiler.infer_resolvedeclaration_type_param_namesserves both item resolution andtopo_resolve_types, which now usesdeclaration_body_env. The body keeps the nominal-leaf shape it always resolved against; only the scope changed.v1.compiler.infer_envenv_with_type_parameter_bindingsis the one scoped insert, and the type-variable shape calls it too.param_bindings,is_type_variable_name, itsstd.typesimport filter (type_env_for_importcollapses away), the import-all export filter, and the record-fieldconvarm.fnsignatures in dag, src/v2, src/v1 and examples, every listed name) finds the same population. Every site gets an explicit<T>, and eachTis the fresh parameter of the reading type it consumes:extdeps.languages.json.parsejson_field_value,json_field_causeextdeps.docker.container_inspectnested_value,nested_causesgunbc.machine_intake.mtjade1_access_observationread_causegunbc.machine_intake.mtcollins1_boot_diagnostic_bundlemembers_channelEvidence
std.algebraPartialFunctionlostOption<V>: a pre-existing defect that this leak had masked.test.claim.type_parameter_declaration_scope_witnessruns ontools.multi_module_compile_fixture(the real acceptance path):QrefusesUnresolvedType;Qrefuses in the importer;<Q>compiles clean.🤖 Generated with Claude Code