From 39a338dbd016cc033dde4e966111a21c735ff7b1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 12:01:12 +0000 Subject: [PATCH 01/10] Enroll the function-value adapter alignment control: the adapter fires exactly where the impl Fn bound is emitted This lands the EVIDENCE for a property that holds by construction today and which nothing else would notice losing. WHAT WAS CLAIMED AND IS FALSE. I reported rust_call_arg_function_value_adapt as a SILENT defect: it reads the DECLARED arity of a function-typed parameter, gets 0 for a bare type variable, does not emit the Rc->impl Fn adapter, and nothing refuses. bright-ram carried that into a standing correction of the XL-0 push ("loud sites self-select into the typeck count, this one does not"). It is wrong, and the correction has been withdrawn. WHY. The adapter predicate and the predicate that decides whether the parameter renders WITH an impl Fn bound are the same expression on the same node -- `param_node_type_expr(n: param).params |> count` in rust_call_arg_function_value_adapt, and `n.params |> count > 0` in emit_rust_param_type reached through emit_param. The seam the adapter closes is Rc flowing into an impl Fn BOUND, and that bound exists exactly where the adapter fires. Arity is also invariant under substitution: instantiation changes an arrow's type ARGUMENTS, never its parameter count, so the site was never answering the instantiated-type question at all. MEASURED, not argued (BuildBuddy, gunbc compile then cargo check on the emitted crate): pub fn make_adder() -> Rc i64> pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64) -> i64 pub fn hold_tv(value: T) -> T apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1) A bare type variable renders as a plain generic with NO Fn bound, so there is no seam to close and adapting there would be a fabricated repair. The emitted crate compiles: 0 rustc errors. Building the refusal that was routed would have been a permanently-green decoration cited later as coverage. THE CONTROL IS THE DELIVERABLE. Four assertions in both directions -- the Rc carrier on the producer side, the impl Fn bound at the declared-arrow parameter, the absence of any Fn bound at the type-variable parameter, and the adapter present at the first while absent at the second, whose argument is equally a call result so argument shape alone does not explain it. Fork the two predicates and one of the four goes red. VALIDATION AND WHAT IS NOT DONE. v1_src_dag_parse reports 4475 files parse-clean with this edit, run with the discriminating control its own header requires: appending one unattached trailing `//` to this file produced exactly one refusal naming it at :3339, so the instrument did read the edited bytes. The stage0 mirrors are NOT regenerated here -- claim_executor --regen-round-cost refuses on a BuildBuddy runner (HostBudgetUnreadable: no cgroup memory.high or memory.max binds the process, and it declines to substitute the machine's memory for the slot's), and a whole-tree resolve OOMs the runner at 97% of 7.8 GB. The drift gate is therefore expected red until the mirrors are healed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- src/v1/compiler_tests_rust.dag | 98 ++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/v1/compiler_tests_rust.dag b/src/v1/compiler_tests_rust.dag index 3a5dd2399eb..744fd0ef497 100644 --- a/src/v1/compiler_tests_rust.dag +++ b/src/v1/compiler_tests_rust.dag @@ -3069,6 +3069,103 @@ fn ct_shell_service_output_projection_known_hole_probe_test() -> String { "\n") } +fn ct_function_value_adapter_bound_alignment_control_test() -> String { + concat( + " // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n", + " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n", + " //\n", + " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n", + " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n", + " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n", + " // the argument in a forwarding closure, and it decides on\n", + " // `param_node_type_expr(n: param).params |> count > 0`.\n", + " //\n", + " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n", + " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n", + " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n", + " // they remain one expression. This control is what notices if they are ever forked.\n", + " //\n", + " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n", + " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n", + " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n", + " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n", + " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n", + " // ARGUMENTS, never its parameter count.\n", + " #[test]\n", + " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n", + " let result = std::thread::Builder::new()\n", + " .stack_size(32 * 1024 * 1024)\n", + " .spawn(|| {\n", + " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n", + " path: \"probe.dag\".to_string(),\n", + " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n", + " });\n", + " let r = crate::v1_compiler_compile::compile_sources(\n", + " std::rc::Rc::new(im::vector![source]),\n", + " crate::v1_compiler_artifact::RenderTarget::Rust,\n", + " );\n", + " let errors: Vec<_> = r\n", + " .diagnostics\n", + " .iter()\n", + " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n", + " .collect();\n", + " assert!(\n", + " errors.is_empty(),\n", + " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n", + " defect rather than a defect in the fixture. Got: {:?}\",\n", + " errors\n", + " );\n", + " let emitted = r\n", + " .files\n", + " .iter()\n", + " .find(|f| f.path == \"src/probe.rs\")\n", + " .map(|f| f.content.clone())\n", + " .expect(\"probe module must emit src/probe.rs\");\n", + "\n", + " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n", + " assert!(\n", + " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n", + " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n", + " emitted\n", + " );\n", + " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n", + " assert!(\n", + " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n", + " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n", + " emitted\n", + " );\n", + " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n", + " assert!(\n", + " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n", + " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n", + " bound -- if this ever gains one, the adapter predicate must move with it, \\\n", + " got:\\n{}\",\n", + " emitted\n", + " );\n", + " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n", + " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n", + " // whose argument is equally a call result, so shape alone does not explain it.\n", + " assert!(\n", + " emitted.contains(\n", + " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n", + " ),\n", + " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n", + " emitted\n", + " );\n", + " assert!(\n", + " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n", + " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n", + " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n", + " emitted\n", + " );\n", + " })\n", + " .expect(\"failed to spawn thread\")\n", + " .join();\n", + " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n", + " }\n", + "\n") +} + fn compiler_tests_source() -> String { concat( ct_module_header(), @@ -3086,6 +3183,7 @@ fn compiler_tests_source() -> String { ct_function_value_named_application_controls_witness_test(), ct_function_value_field_method_known_hole_probe_test(), ct_shell_service_output_projection_known_hole_probe_test(), + ct_function_value_adapter_bound_alignment_control_test(), ct_method_existence_wall_witness_test(), ct_declared_type_conformance_witness_test(), ct_sole_constructor_test(), From d428e98850f9e6fa40ef0e7ed828184b8a6a28ad Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 12:29:54 +0000 Subject: [PATCH 02/10] File one_refusal_two_destinations: a single refusal naming two different expected types, and the remedy row is the wrong one bright-ram asked for this class after two of us measured it independently. The row is authored in the .dag authority; DESIGN.md and docs/design-ledgers.md are its projections, regenerated by the generated-artifact gate (one line each). THE CLASS. One refusal at one source column emits two rows naming DIFFERENT expected types, because two producers resolve the same declared spelling in different environments. The row an author naturally repairs from -- the one that names the parameter -- is the row the checker did NOT refuse on. SPECIMEN, measured on two binaries and two phases (gunbc compile emit-stage and gunbc run entry-resolve), by calm-boar-314 and bold-carp-449 independently: type mismatch: expected 'Primitive(String)', got 'Primitive(Int)' value does not inhabit its declared type at the direct call argument for parameter 's': declared 'Node(String)', produced 'Primitive(Int)' THE PRODUCERS ARE NAMED FROM SOURCE, NOT FROM MESSAGE SHAPE, and the first attribution was wrong: I named declared_type_conformance_diags off the message text, and it is not that -- that function emits TypeMismatch and serves return conformance. Reading the source, the compat row is v1.compiler.infer direct_call_arg_mismatch_diags (formal as the CALLER resolves it) and the inhabitance row is v1.compiler.infer declared_type_obligation_diags (obligation.declared, via declared_type_inhabitance). Both render through v1.compiler.core, so the divergence is upstream of the shared rendering -- which is why it reads as one mechanism contradicting itself. bold-carp asked me to mark whether that attribution was read or inferred; it is read, and the row says so. THE TRIGGER IS STATED NARROWER THAN THE MEASUREMENT INVITES, on bold-carp's correction. "The import creates the disagreement" is an inference across two cells that agree for OPPOSITE reasons: un-imported foreign agrees at Primitive(String) because only the kernel binding exists, in-module agrees at Node(String) because only the local declaration does. So the trigger is TWO COMPETING BINDINGS LIVE IN ONE RESOLVING SCOPE; an explicit import is the only construct measured to create that, and whether any other construct does is marked UNMEASURED. Phrased on the import, a reader meeting the class through some other construct would conclude it does not reproduce. CROSSED ARM, pre-registered before its log was opened: removing the import moves ONLY the inhabitance row (Node(String) -> Primitive(String)) while the compat row is Primitive(String) under both. One producer follows the import binding and the other does not; the whole reading does not shift. RUNG FOUND AT 1 (mitigatable): the line does stop, and stops located, so this is not silent wrongness -- what fails is that the refusal misdirects the remedy. CEILING 3. NEXT-RUNG TRIGGER, naming the capability: one resolved-formal authority per call site that both the compat check and the inhabitance obligation read, sufficient that no call-site refusal can render two different expected types for one parameter. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- dag/gunbc/recurring_failure_mode.dag | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dag/gunbc/recurring_failure_mode.dag b/dag/gunbc/recurring_failure_mode.dag index cdd2e72ba5a..8d8f548e163 100644 --- a/dag/gunbc/recurring_failure_mode.dag +++ b/dag/gunbc/recurring_failure_mode.dag @@ -141,6 +141,12 @@ data mistyped_body_radiates_nonlocal_diagnostics: RecurringFailureMode = Recurri data mitigation_injected_where_judgment_declined: RecurringFailureMode = RecurringFailureMode { identity: "mitigation_injected_where_judgment_declined" as NonEmptyStr, authored: "**mitigation injected where the judgment declined** (a downstream stage injects a RUNTIME mitigation at exactly the seam where an upstream judgment returned Undecidable, so a 4b rung-1 fallback comes to occupy the place the wall belongs and the declined seam stops looking empty. **THE LOAD-BEARING HALF IS WHAT THE COINCIDENCE PROVES ABOUT THE DECLINE**: an Undecidable verdict is normally read as benign conservatism — the facts did not settle it, nothing is claimed, no harm asserted — and a mitigation landing on the SAME LINE is the first evidence that a real defect was sitting under that silence. The decline is therefore load-bearing AT THIS SITE, which refutes reading an Undecidable verdict as evidence of ABSENCE. **IT DOES NOT MAKE THE DECLINE CENSUS PREDICTIVE, and this row carries that limit because the author first wrote the stronger claim and then measured it FALSE** on the same board that produced the specimen: 259 of 272 declines sit in modules with ZERO blocking errors, only 6 of 28 decline-bearing modules carry any error at all, and the module holding 42 of the 63 errors carries ZERO declines and 105 ACCEPTS. Declines and defects are ANTI-CORRELATED at module grain, so this specimen is ONE co-location out of 272 and a walk of the decline census would be walking sites that are ~95% empty. The class is about a mitigation landing on a declined seam; it is NOT a claim that declines predict defects. Distinct from `absorbing_fallback`, whose arm WIDENS to a superset and destroys the precise mechanism s signal; here the arm NARROWS to a panic and destroys nothing except the evidence that a judgment was owed. Distinct from `reflection_evidence_structural_proof`, which mistakes an observation for a proof; here nothing is proven or observed — a decision was declined and then papered. Specimen with a receipt, measured 2026-09-01 on gunbc 0e8c49d and unrepaired at authoring: `v2.std.diagnostic outcome_accepted` is `fn outcome_accepted(value: T) -> Outcome` with T FREE; `v2.compiler.07_target_carriers target_fidelity_quotient_optional` declares `-> Outcome>` and calls `outcome_accepted(Present \{ value: child \})`, so T instantiates to `Optional` and THE SOURCE IS CORRECT. The Rust emitter nonetheless rendered `Some(child).expect(\"fail-closed: an optional value flowed into non-optional parameter 0 of outcome_accepted (empty Optional at runtime)\")`. FOUR DEFECTS IN ONE LINE: it fires on a GENERIC formal where `Optional` is a legitimate instantiation rather than a cardinality escape, so the check does not know T is free; it substitutes a runtime panic for a compile-time judgment; the emitted code does NOT typecheck anyway (rustc E0308 expected `Option>` found `Rc`), so the mitigation buys nothing while standing where the wall belongs; and its own panic string calls itself `fail-closed`, which is 4b rung inflation inside a string literal — a diagnostic naming the discipline it violates is worse than a silent one because it will be cited as evidence the discipline holds. The coincidence that makes this a class and not a bug: `v1.compiler.infer declared_type_inhabitance` returned InhabitanceUndecidable\{UndecidableOptionalCarrier\} at that module s ONLY optional-carrier decline, 07_target_carriers.dag:128:24 parameter `value` — the same line the emitter mitigated. RUNG FOUND AT: 1 (mitigatable) on a seam whose CEILING is 3 (structurally guaranteed), since generic-formal instantiation is decidable from modeled structure. CONSEQUENCE WITH ITS OWN TRIGGER, deliberately NOT folded into this row: wiring the optional-carrier judgment is argued by this specimen but is a separate change, and its trigger is a producer at that seam that can distinguish a FREE type variable from a declared non-optional formal — until that exists the judgment would decline for the same reason it declines today.)" as NonEmptyStr, evidence: [] } +data one_refusal_two_destinations: RecurringFailureMode = RecurringFailureMode { + identity: "one_refusal_two_destinations" as NonEmptyStr, + authored: "**one refusal, two destinations, remedy misdirected** (a single refusal at a single source column emits two rows naming DIFFERENT expected types, because two producers resolve the same declared spelling in different environments. The reader repairs from the row that names the parameter -- and that is the row the checker did NOT refuse on. **THE SYMPTOM IS THE RECOGNITION RULE, NOT THE CAUSE**: what a debugging author encounters is one column, two rows, two expected types; the instruction that saves them is DO NOT REPAIR FROM THE INHABITANCE ROW -- the compat row is what refused. Specimen, measured 2026-09-01 on gunbc c0a378c07be by calm-boar-314 and bold-carp-449 independently, on two binaries and two phases (`gunbc compile` emit-stage refusal and `gunbc run` entry-resolve), unrepaired at authoring. A module declaring `type String = FreeMonoid` and `fn takes_bare(s: String) -> Int`, called from a foreign module that IMPORTS the function, with a deliberately wrong `Int` actual so the diagnostic must name its destination, refuses with: `type mismatch: expected 'Primitive(String)', got 'Primitive(Int)'` AND `value does not inhabit its declared type at the direct call argument for parameter 's': declared 'Node(String)', produced 'Primitive(Int)'`. THE TWO PRODUCERS, read from source rather than inferred from message shape: `v1.compiler.infer direct_call_arg_mismatch_diags` renders the compat row from the formal as the CALLER environment resolves it, and `v1.compiler.infer declared_type_obligation_diags` renders the inhabitance row from `obligation.declared` through `declared_type_inhabitance`. Both reach `type_mismatch_error` and `DeclaredTypeNotInhabited` in `v1.compiler.core`, so the rendering is shared and the DIVERGENCE IS UPSTREAM OF IT -- which is why the two rows look like one mechanism disagreeing with itself. **THE TRIGGER IS TWO COMPETING BINDINGS LIVE IN ONE RESOLVING SCOPE, NOT THE IMPORT AS SUCH**, and this row states the narrower claim deliberately: the with/without-import pair is measured, but the two AGREEING cells agree for OPPOSITE reasons -- an un-imported foreign caller agrees at `Primitive(String)` because only the kernel binding is available, and an in-module caller agrees at `Node(String)` because only the local declaration is. Phrasing the trigger as the import would make a reader conclude the class does not reproduce when some other construct puts a second binding in scope. An explicit `import \{ \}` is the ONLY construct measured to create the competition; whether any other does is UNMEASURED. Crossed arm, pre-registered before its log was read: removing the import moves ONLY the inhabitance row, from `Node(String)` to `Primitive(String)`, while the compat row is `Primitive(String)` under both -- so one producer follows the import binding and the other does not, rather than the whole reading shifting. RUNG FOUND AT: 1 (mitigatable) -- the line DOES stop, and stops located, so this is not silent wrongness; what fails is that the refusal MISDIRECTS the remedy, which is DESIGN section 5's requirement that a refusal be typed AND located read one layer deeper: located at the right column while naming the wrong destination. CEILING: 3 (structurally guaranteed) -- one resolution of a callee's declared type per call site, consumed by both producers, makes two destinations unconstructible. NEXT-RUNG TRIGGER, naming the capability rather than an artifact: a single resolved-formal authority at the call site that both the compat check and the inhabitance obligation READ, sufficient that no call-site refusal can render two different expected types for one parameter. Distinct from `meaning_fork`, which is one NAME carrying two meanings across scopes -- that is the underlying condition here and is separately rostered; this row is about two PRODUCERS disagreeing inside a single refusal, which is what makes the remedy wrong rather than merely the meaning ambiguous. Distinct from `diagnostic_name_mechanism_silent`: there the diagnostic names a mechanism that never ran; here both mechanisms ran and both reported faithfully about different environments. WHAT IS NOT CLAIMED, by either measurer: which producer is correct, and why they read the binding differently. No arm on either rig touches it, and the source reading above identifies the producers without settling which environment a call-argument formal SHOULD be resolved in.)" as NonEmptyStr, + evidence: [], +} + data instrument_output_read_as_subject_content: RecurringFailureMode = RecurringFailureMode { identity: "instrument_output_read_as_subject_content" as NonEmptyStr, authored: "**instrument output read as subject content** (a consumer derives a SET from a report whose completeness is a property of the REPORTING TOOL rather than of the subject. **The boundary against `execution_provenance_loss` is the whole justification for a separate row, because the two look identical at the call site and have opposite repairs**: there a value is consumed as though an observation produced it while nothing proves the observation path RAN, and the fix is to bind an execution receipt; here the observation ran and reported FAITHFULLY — the instrument answered its own question correctly — and what is wrong is that its output was complete for the REPORTER s purpose and was read as complete for the CONSUMER s. Provenance is intact; the SUBJECT is substituted, so no receipt binding can detect it and the repair is instead to derive the set from the subject itself. Distinct from `total_at_the_level_examined_blind`, which is a judgment shape (a match total over the type it examines, blind inside an arm), and from `reachability_read_as_occupancy`, which asks whether a quiet guard should exist; this is neither a match nor a guard. Specimen with a receipt, repaired on main by gunbc#9829: the required floor asked `extdeps.git` `git.Core.DiffUnified0` (`git diff -U0 `) which lines a change touched, and `floor_diff_edits_from_line_ranges` attributed those lines to enclosing declarations to decide which witness identities the change established. Git prints only the hunks that DIFFER, so on a rename it prints the module line and whatever else moved — while every identity at the destination is a newly qualified `module.function` that has never executed under that spelling, because the authored module name moved with the file. **THE REASON IT SURVIVED IS THAT THE TWO ANSWERS COINCIDE BY ACCIDENT IN THE COMMON CASE**: for a wholly-added file every line is a `+` line, so line attribution reaches every declaration and the defect is invisible; it appears only when the instrument gets TERSE, which rename detection is. Measured over the window reachable in a shallow session clone — a floor on the population, not the population, since older renames are unmeasured — 8 of 8 rename-destination `.dag` files carrying test decls were under-enrolled and at least 87 of their 103 identities were never selected; a PURE MOVE with no content edit enrolled NOTHING. It was not merely a reporting gap: changed-witness membership is what OVERRIDES the cost-debt withhold and the outside-gate suppression, so the same miss on a rostered identity is a silent decline of a witness whose author is present, which is the state `v2.workflow.floor_changed_witness` `changed_witness_execution_standing` exists to red. The repair derives the set from the subject: a path `parse_unified_diff_added_paths` already rules new-at-path contributes the declarations THE FILE ITSELF PARSES TO, bounded to that file s own decl list and never the corpus, so it is the precise answer rather than an absorbing widen. Its discriminating red is `rename_destination_enrolls_every_test_decl_not_only_the_diff_touched_one`, which feeds the specimen s verbatim diff and FAILS when the rule is disabled, paired with `in_place_modify_enrolls_only_the_touched_test_decl`, which passes under both states so the first cannot be satisfied by widening. **Recognition rule, and it predicts well beyond git**: whenever a set is read out of a tool s output, ask whether that tool promised completeness over YOUR question or over its own — `--stat`, any de-duplicating or truncating reporter, and any porcelain that elides for human brevity all report faithfully and none of them promise the consumer s set. **Its near twin is `executed_conjunct_discriminates_nothing`, approached from the other side**: there the satisfied signal is EXECUTION -- the conjunct genuinely runs and is genuinely gated on -- while here it is COMPLETENESS RELATIVE TO THE REPORTER, which is why this class is not a reachability problem and looking for an unexecuted path finds everything healthy. In both, the axis the diligent reader checks already reads green, and checking it harder returns the same green.)", evidence: [] } data executed_conjunct_discriminates_nothing: RecurringFailureMode = RecurringFailureMode { identity: "executed_conjunct_discriminates_nothing" as NonEmptyStr, authored: "**a conjunct that executes, is reached, is gated on, and still discriminates nothing** (a predicate wired into a live check runs on every call, sits inside a gate that really blocks, and yet deletes cleanly: remove it and every witness stays green, because no fixture ever constructs the population that would make it false. **It is invisible precisely BECAUSE reachability is satisfied.** The usual signature of an unenforced mechanism -- nothing calls it -- is absent, so every reachability-based tell reports health, and review reads the conjunct as a wall because it genuinely is evaluated. Executed and enforcing are different properties, and no amount of coverage over the calling path distinguishes them. **It is bounded against three neighbours and none of their recognition rules will find it.** `reachability_read_as_occupancy` asks whether to DELETE a guard that is quiet, and warns that mechanism-yes / join-yes / occupancy-zero is a healthy guard; this class is not about deletion and not about occupancy -- the conjunct here should stay, and the defect is that it was believed to be doing work it was not. Section 6's inert-lens tell is machinery that nothing GATES on; this is gated on. Section 4b's decoration case is a check whose RED cannot be authored ANYWHERE; this RED can be authored -- it simply never was, which is the whole difference, and it is the difference between a permanent ceiling and one missing fixture. **THE REMEDY HAS TWO HALVES AND THE SECOND IS WHAT MAKES THE FIRST SOUND.** First: for each wall, run the DELETE arm and confirm EXACTLY ONE witness reddens -- not that a witness reddens. Second: the subject that isolates the conjunct must be chosen with care, because a red for the wrong reason is how this class survives its own test. **SPECIMEN, with both halves executed** (gunbc#9838, `gunbc.self_host_compile_phase_frontier`): `census_population_is_duplicate_free` was added as a conjunct of `receipt_population_coherent`, evaluated on every coherence check and reachable from the live path; deleting it left the whole witness module green. The fixture that isolates it is a receipt whose `refused_files` REPEATS A PATH -- enrolled as `a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence` in `test.claim.self_host_compile_phase_frontier_witness`, with `the_same_receipt_without_the_repeat_is_coherent` as its positive control. The subject that looks equally good and is not: a repeated ERROR DIAGNOSTIC IDENTITY also reddens the module, but it breaks a count invariant one line over rather than this conjunct, so it would have scored the DEAD conjunct as LIVE and closed the investigation with the wall still inert. **RUNG: mechanically preventable, and the honest ceiling is the same rung rather than higher.** The unenforcing conjunct stays writable; what exists is an executed falsifier per wall, not a construction that forbids authoring one. The next-rung trigger is a CAPABILITY and not an artifact: a mechanism that derives, from the check itself, the population its removal would change -- so that a conjunct with an empty such population fails to compile rather than waiting for an author to think of the delete arm. Enumerating delete arms by hand does not retire it; it only executes this row's recognition rule once per wall. **Its near twin is `instrument_output_read_as_subject_content`, and they meet from opposite sides**: there a report is complete for the REPORTER and read as complete for the SUBJECT; here a conjunct is genuinely executed and read as genuinely discriminating. Both are the shape where the health signal the reader actually checks -- completeness there, execution here -- is fully satisfied while the property they believe it establishes does not hold. **Neither is found by checking harder along the axis that already reads green.**)", evidence: [] } @@ -181,4 +187,5 @@ data recurring_failure_mode_roster: List = [ unbacked_execution_claim, mitigation_injected_where_judgment_declined, merge_region_excludes_shared_tail, + one_refusal_two_destinations, ] From 8d2b2e65356d25c396dfad91ce9f1d25e0bab418 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 13:02:09 +0000 Subject: [PATCH 03/10] Regenerate the ledger projections on the rebased tree Route A (generated_artifact_gate main_wet_one) with a binary rebuilt AFTER the rebase, not before -- a pre-rebase binary re-emits the older rendering and re-drifts the file it is converging while exiting green (vivid-deer-102's receipt, #9898). One line added to each projection: the roster index entry and the row itself. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- DESIGN.md | 1 + docs/design-ledgers.md | 1 + 2 files changed, 2 insertions(+) diff --git a/DESIGN.md b/DESIGN.md index f0d7cc54c5a..f00a1249428 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -215,6 +215,7 @@ One row per class, each carrying its recognition rule and its receipts, in [docs - `unbacked_execution_claim` - `mitigation_injected_where_judgment_declined` - `merge_region_excludes_shared_tail` +- `one_refusal_two_destinations` ## Building & checks diff --git a/docs/design-ledgers.md b/docs/design-ledgers.md index edc02cf8587..adc26d21514 100644 --- a/docs/design-ledgers.md +++ b/docs/design-ledgers.md @@ -43,6 +43,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **unbacked execution claim** (prose asserts a live executing relation — this runs on X, X reads these fields, Y already resolves Z — that no authority backs, and a reader forms the premise and plans against it. §4b's CI rung drop names the harm PREMISE CONTAMINATION in its own words; this row is that harm as a general class, since the drop is about one paragraph in the canonical authority and the class is about every carrier. **THE ORIGINS ARE A FIELD OF THIS ONE ROW RATHER THAN SEPARATE ROWS, because the recognition rule is identical across them** — resolve the claim against the authority that owns the relation — **but the REMEDY BRANCHES ON THE ORIGIN, and a remedy applied without reading the origin manufactures new false statements.** Three origins are ATTESTED here and a fourth is conceivable but was NOT found. ORIGIN 1, EXECUTOR DELETED: the claim was true and its executor was removed. Specimen: `gunbc.floor_component_receipt_document` recited that an alert downloads an artifact named `floor-component-receipt` from a run id it is given and reads four named fields; that alert was `falsifier-alert.yml`, deleted 2026-08-15, and a lane read the module, believed the transport live, planned against it, and was corrected by its reviewing authority — the cost is measured, not hypothetical. Second specimen, same origin: `gunbc.ci_failure_class` stated its dissolution trigger as calling `classify_failure_reason` *the way claim_executor already resolves* `gunbc.floor_component_receipt`; `write_floor_component_receipt_at` did exactly that from 2026-07-30 (gunbc#7467) until gunbc#9228 deleted it on 2026-08-25. ORIGIN 2, THE CITED SYMBOL DIED WHILE ITS CONTENT SURVIVED AS AN ANNOTATION, and this one has a corpus-wide producer: `v1_compiler.cli_run` twice cited `floor_component_resource_checkpoint_note` and `floor_component_phase_journal_scaffold_note`, which were real `data …: String` declarations in `gunbc.floor_component_receipt` until the 2026-08-30 prose-bankruptcy sweep (gunbc#9752) converted module-scope commentary rows into §4c annotations corpus-wide. §4c makes an annotation uncitable by construction — `v1_compiler.cli_run` `annotation_erased_scan_text` feeds the semantic passes, so annotation text is not present in the tree the citation harvester walks. **THE CONSEQUENCE IS THE OPPOSITE OF THE ONE THIS ROW FIRST DREW, AND THE CORRECTION IS THE INSTRUCTIVE PART.** The first revision reasoned that the sweep therefore broke every citation of a converted row, making the population the sweep's own diff. Measured by a separate lane (gunbc XL-0-CITE, 2026-09-01) against `v1_compiler.declaration_index`, whose only citation producers are `citation_from_record_literal` and `citation_from_constructor_call`: the typed-citation breakage is **ZERO**, computed both today and as of the sweep commit, on a control that discriminates in both directions. A plain name in annotation prose was never a citation, so the sweep could not break one. What that leaves is a REAL class with an honest ceiling rather than a defect population: these citations bind READERS and no mechanism, so they sit in §4b's *outside the modeled guarantee* column — observed and repaired by reading, never gated — and calling them a dangling-citation population would have been rung inflation about a check that by construction cannot see them. The two `cli_run` sites are genuine instances of the harm and there is no mechanical census that would have found them. ORIGIN 3, WRONG AUTHORITY FOR SOMETHING THAT STILL EXECUTES: `dag/test/claim/instrument_sandbox_witness_test` says its live half `runs on the falsifier lane`; that half sits on `FalsifierSubstrateLongLane`, which `std.witness_admission` `witness_cadence_has_scheduled_route` reports routeless — but it also carries a local recipe, and `OfflineLocalRecipe` HAS a route, so the relation is live and only the named authority is wrong. THE FOURTH, NEVER BACKED AT ALL, IS NOT ATTESTED IN THIS CORPUS and is recorded as unmeasured rather than as a population. **THIS ROW IS NOT THE AUTHORITY ON ANY POPULATION, and saying so is the point:** `gunbc.deleted_cadence_reference_census` already owns the falsifier-cadence instance of origin 1 — twelve sites, a `DeletedCadenceReferenceStanding` vocabulary whose `PremiseInvalidated` arm is exactly this class, and one `GuaranteeRungDrop` filed once for the shared executor rather than per site. A pattern row that restated its population would be a second authority for a fact that already has one, which is the §3 violation this row's own remedy is meant to prevent; so the census is cited here and nothing about its contents is copied. What belongs HERE is only the recognition rule and the remedy arms, which generalize past the falsifier. **THE MECHANICAL TEST for finding one is sharper than asking whether the verb is runs or is enrolled: resolve the claim against the authority that owns the relation, and ask whether the prose implies a live route for something that authority says has none.** The naive runs/enrolled discriminator loses one arm and it is the common one — `Enrolled on falsifier_rehomed_bin_wet_entries (nightly batch 5)` is nominally an enrollment claim, which is TRUE, but `nightly` asserts a cadence that executes and `FalsifierRehomedBinWet` is routeless, so the reader forms the false premise anyway. Three outcomes per line: asserts execution (contaminating), asserts enrollment only (true, leave it), asserts enrollment while implying a live cadence (contaminating). **THE REMEDY HAS THREE ARMS, KEYED TO WHAT THE AUTHORITY SAYS NOW, and picking the wrong one is itself an instance of this class.** Origin 1 → PAST TENSE WITH THE DATE, keeping the reasoning, because the reasoning usually outlives its executor and a reader who finds a dangling claim silently deleted learns nothing. Origin 2 → name the module and the FACT rather than the dead symbol, since §4c left no symbol to cite; past-tensing here would wrongly report the content as gone when only its citability is. Origin 3 → CORRECT IT to the authority that does back it, NOT past tense: past-tensing a live relation records it as dead and is a new contamination in the opposite direction, produced by the remedy itself. Origin 4 → say it was never backed, or delete the assertion while keeping any surviving reasoning; NEVER past tense, because there is no past to record, and `X USED TO resolve Y` asserts an execution that also never happened. **The default against deletion is a default and not an absolute: a sentence whose entire content is a false execution claim has no reasoning to preserve.** **THE SELF-RECEIPT, and it is the most useful thing in this row (2026-09-01):** the first revision of this entry asserted the `ci_failure_class` clause and the two `cli_run` notes as never-true, on the strength of a grep showing they resolve nowhere TODAY. **Both were true when written**, and the row about unbacked claims therefore contained two of them. It was caught by a reviewing authority asking for verification rather than inheritance, not by any check. **RECOGNITION RULE EARNED: `resolves nowhere now` is not `never resolved`, the distinction is decided by history and not by the working tree, and the instrument is `git log --all -S` over the DECLARATION FORM** — which also separates origin 1 from origin 2 by showing WHAT deleted the referent. The neighbouring rule is `positional_citation`'s: a citation left naming a deleted symbol fakes a grep hit, so every arm above records the change rather than quietly removing the name.) - **mitigation injected where the judgment declined** (a downstream stage injects a RUNTIME mitigation at exactly the seam where an upstream judgment returned Undecidable, so a 4b rung-1 fallback comes to occupy the place the wall belongs and the declined seam stops looking empty. **THE LOAD-BEARING HALF IS WHAT THE COINCIDENCE PROVES ABOUT THE DECLINE**: an Undecidable verdict is normally read as benign conservatism — the facts did not settle it, nothing is claimed, no harm asserted — and a mitigation landing on the SAME LINE is the first evidence that a real defect was sitting under that silence. The decline is therefore load-bearing AT THIS SITE, which refutes reading an Undecidable verdict as evidence of ABSENCE. **IT DOES NOT MAKE THE DECLINE CENSUS PREDICTIVE, and this row carries that limit because the author first wrote the stronger claim and then measured it FALSE** on the same board that produced the specimen: 259 of 272 declines sit in modules with ZERO blocking errors, only 6 of 28 decline-bearing modules carry any error at all, and the module holding 42 of the 63 errors carries ZERO declines and 105 ACCEPTS. Declines and defects are ANTI-CORRELATED at module grain, so this specimen is ONE co-location out of 272 and a walk of the decline census would be walking sites that are ~95% empty. The class is about a mitigation landing on a declined seam; it is NOT a claim that declines predict defects. Distinct from `absorbing_fallback`, whose arm WIDENS to a superset and destroys the precise mechanism s signal; here the arm NARROWS to a panic and destroys nothing except the evidence that a judgment was owed. Distinct from `reflection_evidence_structural_proof`, which mistakes an observation for a proof; here nothing is proven or observed — a decision was declined and then papered. Specimen with a receipt, measured 2026-09-01 on gunbc 0e8c49d and unrepaired at authoring: `v2.std.diagnostic outcome_accepted` is `fn outcome_accepted(value: T) -> Outcome` with T FREE; `v2.compiler.07_target_carriers target_fidelity_quotient_optional` declares `-> Outcome>` and calls `outcome_accepted(Present { value: child })`, so T instantiates to `Optional` and THE SOURCE IS CORRECT. The Rust emitter nonetheless rendered `Some(child).expect("fail-closed: an optional value flowed into non-optional parameter 0 of outcome_accepted (empty Optional at runtime)")`. FOUR DEFECTS IN ONE LINE: it fires on a GENERIC formal where `Optional` is a legitimate instantiation rather than a cardinality escape, so the check does not know T is free; it substitutes a runtime panic for a compile-time judgment; the emitted code does NOT typecheck anyway (rustc E0308 expected `Option>` found `Rc`), so the mitigation buys nothing while standing where the wall belongs; and its own panic string calls itself `fail-closed`, which is 4b rung inflation inside a string literal — a diagnostic naming the discipline it violates is worse than a silent one because it will be cited as evidence the discipline holds. The coincidence that makes this a class and not a bug: `v1.compiler.infer declared_type_inhabitance` returned InhabitanceUndecidable{UndecidableOptionalCarrier} at that module s ONLY optional-carrier decline, 07_target_carriers.dag:128:24 parameter `value` — the same line the emitter mitigated. RUNG FOUND AT: 1 (mitigatable) on a seam whose CEILING is 3 (structurally guaranteed), since generic-formal instantiation is decidable from modeled structure. CONSEQUENCE WITH ITS OWN TRIGGER, deliberately NOT folded into this row: wiring the optional-carrier judgment is argued by this specimen but is a separate change, and its trigger is a producer at that seam that can distinguish a FREE type variable from a declared non-optional formal — until that exists the judgment would decline for the same reason it declines today.) - **merge region excludes the shared tail** (a roster carrier whose rows are multi-line blocks ending in an identical suffix makes every two-lane append resolve WRONG BY DEFAULT. The three-way merge factors the shared suffix out of the conflict region, so the region holds two half-blocks above the markers and one tail below them, and the purely additive resolution -- delete the markers, keep both sides, which is the CORRECT resolution when the two appended rows are independent -- leaves the first row's closing lines belonging to the second. Specimen: this carrier, which conflicted on every integration of main across four merge bases in one session (2026-09-01) with a shared tail of `evidence: [],` and `}`; `gunbc.rung_drop` had the same shape with `}` alone. **THE CLASS IS LOUD, AND THAT IS THE HALF A REPORT OF IT WILL GET WRONG.** The first reading was that the severed row survives as a structurally broken declaration under which the natural check -- declared names against rostered names -- still passes, because both lists stay complete. Measured against a gunbc built at d0009ca531 on the resolved shape: it is a PARSE REFUSAL at the module index, `expected expression, found Eq`, because a `data` keyword cannot stand in record-field position. Nothing reaches the checks that reading worried about, so the cost is toil and not silent wrongness -- a load-bearing authority whose every integration lands a conflict whose natural resolution does not compile, hand-repaired each time. **RECOGNITION RULE: for a carrier two lanes append to, ask what suffix the appended units SHARE, because a conflict region never contains it -- whatever semantics live in that suffix are exactly what a resolution can drop.** THE REPAIR IS THE UNIT AND NOT A CHECK: make the appended unit one line, and the shared suffix is a blank separator carrying nothing. A brace-balance or name-join check written here would be the DESIGN section 4b decoration -- permanently green, because the compiler already refuses the only corpus it could fire on.) +- **one refusal, two destinations, remedy misdirected** (a single refusal at a single source column emits two rows naming DIFFERENT expected types, because two producers resolve the same declared spelling in different environments. The reader repairs from the row that names the parameter -- and that is the row the checker did NOT refuse on. **THE SYMPTOM IS THE RECOGNITION RULE, NOT THE CAUSE**: what a debugging author encounters is one column, two rows, two expected types; the instruction that saves them is DO NOT REPAIR FROM THE INHABITANCE ROW -- the compat row is what refused. Specimen, measured 2026-09-01 on gunbc c0a378c07be by calm-boar-314 and bold-carp-449 independently, on two binaries and two phases (`gunbc compile` emit-stage refusal and `gunbc run` entry-resolve), unrepaired at authoring. A module declaring `type String = FreeMonoid` and `fn takes_bare(s: String) -> Int`, called from a foreign module that IMPORTS the function, with a deliberately wrong `Int` actual so the diagnostic must name its destination, refuses with: `type mismatch: expected 'Primitive(String)', got 'Primitive(Int)'` AND `value does not inhabit its declared type at the direct call argument for parameter 's': declared 'Node(String)', produced 'Primitive(Int)'`. THE TWO PRODUCERS, read from source rather than inferred from message shape: `v1.compiler.infer direct_call_arg_mismatch_diags` renders the compat row from the formal as the CALLER environment resolves it, and `v1.compiler.infer declared_type_obligation_diags` renders the inhabitance row from `obligation.declared` through `declared_type_inhabitance`. Both reach `type_mismatch_error` and `DeclaredTypeNotInhabited` in `v1.compiler.core`, so the rendering is shared and the DIVERGENCE IS UPSTREAM OF IT -- which is why the two rows look like one mechanism disagreeing with itself. **THE TRIGGER IS TWO COMPETING BINDINGS LIVE IN ONE RESOLVING SCOPE, NOT THE IMPORT AS SUCH**, and this row states the narrower claim deliberately: the with/without-import pair is measured, but the two AGREEING cells agree for OPPOSITE reasons -- an un-imported foreign caller agrees at `Primitive(String)` because only the kernel binding is available, and an in-module caller agrees at `Node(String)` because only the local declaration is. Phrasing the trigger as the import would make a reader conclude the class does not reproduce when some other construct puts a second binding in scope. An explicit `import { }` is the ONLY construct measured to create the competition; whether any other does is UNMEASURED. Crossed arm, pre-registered before its log was read: removing the import moves ONLY the inhabitance row, from `Node(String)` to `Primitive(String)`, while the compat row is `Primitive(String)` under both -- so one producer follows the import binding and the other does not, rather than the whole reading shifting. RUNG FOUND AT: 1 (mitigatable) -- the line DOES stop, and stops located, so this is not silent wrongness; what fails is that the refusal MISDIRECTS the remedy, which is DESIGN section 5's requirement that a refusal be typed AND located read one layer deeper: located at the right column while naming the wrong destination. CEILING: 3 (structurally guaranteed) -- one resolution of a callee's declared type per call site, consumed by both producers, makes two destinations unconstructible. NEXT-RUNG TRIGGER, naming the capability rather than an artifact: a single resolved-formal authority at the call site that both the compat check and the inhabitance obligation READ, sufficient that no call-site refusal can render two different expected types for one parameter. Distinct from `meaning_fork`, which is one NAME carrying two meanings across scopes -- that is the underlying condition here and is separately rostered; this row is about two PRODUCERS disagreeing inside a single refusal, which is what makes the remedy wrong rather than merely the meaning ambiguous. Distinct from `diagnostic_name_mechanism_silent`: there the diagnostic names a mechanism that never ran; here both mechanisms ran and both reported faithfully about different environments. WHAT IS NOT CLAIMED, by either measurer: which producer is correct, and why they read the binding differently. No arm on either rig touches it, and the source reading above identifies the producers without settling which environment a call-argument formal SHOULD be resolved in.) ## Declared rung drops (§4b(3)) From f5443adb8ac273030a677d2cbe117ce90cb8a838 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 13:34:11 +0000 Subject: [PATCH 04/10] Install the two stage0 mirrors the enrolled control drifts, to the regen fixed point Route B (claim_executor --required-regen), locally, three rounds -- the third is the receipt and the first two are not: round 1 FAIL generated surface drift: v1_compiler_compiler_tests_rust.rs round 2 FAIL generated surface drift: compiler_tests.rs round 3 first_generation_equal=true, no drift, rc=0 Two rounds are structural, not a retry: installing the mirror of the generator module changes what the seed emits, so the generator's own output can only be measured against a seed rebuilt from the installed mirror. Every byte is copied from target/stage0-regen-candidate; none is hand-written. THE FIRST ROUND ON THE OLD BRANCH REPORTED SEVEN FILES, and that is why this branch exists. Six of them -- v1_compiler_compile.rs, v1_compiler_emit.rs, v1_compiler_emit_rust.rs, v1_compiler_infer_resolve.rs, v1_compiler_parse.rs, v1_std_core.rs -- were the mirrors of a superseded WIP shell repair (dede56fa91f, "kept for reference only, not for landing") that was still on session/calm-boar-314 and had silently become part of PR #9929. It duplicates sharp-dove-805's open #9886. Rebuilding the branch from origin/main with only the intended commits drops it, and the drift census falls from seven files to one -- which is the measurement that confirms the six were never mine to land. Route B is also now first-hand rather than cited: vivid-deer-102 relayed this recipe from the merge driver's refusal text and was explicit they had not run it. It works locally. It cannot run on a BuildBuddy runner (HostBudgetUnreadable: no cgroup limit binds the process). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- src/v1/stage0/src/compiler_tests.rs | 95 +++++++++++++++++++ .../src/v1_compiler_compiler_tests_rust.rs | 6 +- 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 32a964a88be..63ca25ac36d 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -984,6 +984,101 @@ mod compiler_tests { .expect("shell_service_output_projection_fabricates_stdout_known_hole_probe panicked"); } + // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing + // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled. + // + // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an + // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first + // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping + // the argument in a forwarding closure, and it decides on + // `param_node_type_expr(n: param).params |> count > 0`. + // + // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to + // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the + // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while + // they remain one expression. This control is what notices if they are ever forked. + // + // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a + // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing + // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn + // bound, so there is no seam to close, and adapting there would be a fabricated repair. + // Arity is invariant under substitution anyway: instantiation changes an arrow's type + // ARGUMENTS, never its parameter count. + #[test] + fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() { + let result = std::thread::Builder::new() + .stack_size(32 * 1024 * 1024) + .spawn(|| { + let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile { + path: "probe.dag".to_string(), + content: "module probe\nfn add_one(x: Int) -> Int { x + 1 }\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\nfn hold_tv(value: T) -> T { value }\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\n".to_string(), + }); + let r = crate::v1_compiler_compile::compile_sources( + std::rc::Rc::new(im::vector![source]), + crate::v1_compiler_artifact::RenderTarget::Rust, + ); + let errors: Vec<_> = r + .diagnostics + .iter() + .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone())) + .collect(); + assert!( + errors.is_empty(), + "the fixture is ordinary admissible source; a refusal here is a compiler \ + defect rather than a defect in the fixture. Got: {:?}", + errors + ); + let emitted = r + .files + .iter() + .find(|f| f.path == "src/probe.rs") + .map(|f| f.content.clone()) + .expect("probe module must emit src/probe.rs"); + + // (1) the producer side of the seam: a function VALUE is the Rc carrier. + assert!( + emitted.contains("pub fn make_adder() -> Rc i64>"), + "a function-valued return must realize as the Rc carrier, got:\n{}", + emitted + ); + // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here. + assert!( + emitted.contains("pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)"), + "a declared-arrow parameter must carry the impl Fn bound, got:\n{}", + emitted + ); + // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here. + assert!( + emitted.contains("pub fn hold_tv(value: T) -> T"), + "a bare type-variable parameter must render as a plain generic with no Fn \ + bound -- if this ever gains one, the adapter predicate must move with it, \ + got:\n{}", + emitted + ); + // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the + // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter -- + // whose argument is equally a call result, so shape alone does not explain it. + assert!( + emitted.contains( + "apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)" + ), + "the adapter must close the seam at the impl Fn parameter, got:\n{}", + emitted + ); + assert!( + !emitted.contains("hold_tv({ let __adapt_f"), + "no adapter may be injected at a parameter that carries no Fn bound -- that \ + would be a fabricated repair of a seam that does not exist, got:\n{}", + emitted + ); + }) + .expect("failed to spawn thread") + .join(); + result.expect( + "function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked", + ); + } + #[test] fn method_existence_wall_witness() { // DISCRIMINATING RED for method_existence_wall_note. Before the wall an diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 4fec99157be..b122ae7bdb4 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -380,6 +380,10 @@ pub fn ct_shell_service_output_projection_known_hole_probe_test() -> String { v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // KNOWN-HOLE PROBE (not a desired-behavior control), DESIGN section 4b(4).\n".to_string(), " //\n".to_string()), " // The shell service-emission path FABRICATES rather than refuses: every declared\n".to_string()), " // output field is bound to `stdout`, whatever source the declaration named, and the\n".to_string()), " // error arm returns a bare String against a declared Box.\n".to_string()), " // Both produce Rust that does not compile, with ZERO diagnostics -- section 5's\n".to_string()), " // fabricated-plausible-output arm, in the emitter.\n".to_string()), " //\n".to_string()), " // The three-output fixture is load-bearing. The two-field case this was first seen\n".to_string()), " // on (an operation declaring `success: Bool from \"exit_success\"` beside\n".to_string()), " // `stdout: String from \"stdout\"`) cannot distinguish \"wrong tuple index\" from \"the\n".to_string()), " // declared source never arrived\": with two fields, \"always the first output\" and\n".to_string()), " // \"always stdout\" produce the same bytes. Three fields separate them, and the\n".to_string()), " // ABSENCE of the `let stderr = ...` prelude line is the positive evidence -- that\n".to_string()), " // line is emitted only when some field claims the stderr channel, so its absence\n".to_string()), " // proves the `from \"stderr\"` field was invisible to the renderer rather than\n".to_string()), " // mis-ordered. child_from_key returns Absent for all three.\n".to_string()), " //\n".to_string()), " // WHEN THE WALL LANDS THIS PROBE MUST FLIP and become a permanent regression\n".to_string()), " // control: the emitted body must bind each field to its named source, box the error\n".to_string()), " // arm, and REFUSE -- typed and located, naming the field and the unresolvable\n".to_string()), " // source -- for any source it cannot realize.\n".to_string()), " #[test]\n".to_string()), " fn shell_service_output_projection_fabricates_stdout_known_hole_probe() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nservice Probe {\\n operation Version {\\n input {}\\n output {\\n success: Bool from \\\"exit_success\\\"\\n out: String from \\\"stdout\\\"\\n err: String from \\\"stderr\\\"\\n }\\n transport shell { argv: [\\\"git\\\", \\\"--version\\\"] }\\n }\\n}\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"KNOWN HOLE today: the emitter does not refuse; it fabricates silently. \\\n".to_string()), " When the wall lands this becomes the refusal assertion. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"service module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // The signature reads the declaration correctly...\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"-> Result<(bool, String, String), Box>\"\n".to_string()), " ),\n".to_string()), " \"signature must project the three declared output types, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // ...and the body then ignores every declared source.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"Ok((stdout.clone(), stdout.clone(), stdout.clone()))\"),\n".to_string()), " \"KNOWN HOLE: every output field is bound to stdout regardless of its \\\n".to_string()), " declared source. If this assertion fails the wall may have landed -- \\\n".to_string()), " flip this probe to assert the correct per-channel binding. Got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // The stderr prelude is the absence that proves the source was never read.\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"String::from_utf8_lossy(&output.stderr)\"),\n".to_string()), " \"KNOWN HOLE: the `from \\\"stderr\\\"` field is invisible to the renderer, \\\n".to_string()), " so no stderr prelude line is emitted. Got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result\n".to_string()), " .expect(\"shell_service_output_projection_fabricates_stdout_known_hole_probe panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) } +pub fn ct_function_value_adapter_bound_alignment_control_test() -> String { + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n".to_string(), " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n".to_string()), " //\n".to_string()), " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n".to_string()), " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n".to_string()), " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n".to_string()), " // the argument in a forwarding closure, and it decides on\n".to_string()), " // `param_node_type_expr(n: param).params |> count > 0`.\n".to_string()), " //\n".to_string()), " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n".to_string()), " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n".to_string()), " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n".to_string()), " // they remain one expression. This control is what notices if they are ever forked.\n".to_string()), " //\n".to_string()), " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n".to_string()), " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n".to_string()), " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n".to_string()), " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n".to_string()), " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n".to_string()), " // ARGUMENTS, never its parameter count.\n".to_string()), " #[test]\n".to_string()), " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n".to_string()), " defect rather than a defect in the fixture. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"probe module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n".to_string()), " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n".to_string()), " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n".to_string()), " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n".to_string()), " bound -- if this ever gains one, the adapter predicate must move with it, \\\n".to_string()), " got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n".to_string()), " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n".to_string()), " // whose argument is equally a call result, so shape alone does not explain it.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n".to_string()), " ),\n".to_string()), " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n".to_string()), " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n".to_string()), " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) +} + pub fn compiler_tests_source() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_pipeline_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_known_hole_probe_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_pipeline_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_known_hole_probe_test()), ct_function_value_adapter_bound_alignment_control_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) } From 8a1c8479eda1b83e071e6865555af8e5cec550e5 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 13:44:59 +0000 Subject: [PATCH 05/10] Regenerate the projections after merging main Binary rebuilt from the MERGED tree before regenerating. One line added to each file: the roster index entry and the row. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- DESIGN.md | 1 + docs/design-ledgers.md | 1 + 2 files changed, 2 insertions(+) diff --git a/DESIGN.md b/DESIGN.md index 9b11abeb4a3..0d8a44794e2 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -217,6 +217,7 @@ One row per class, each carrying its recognition rule and its receipts, in [docs - `merge_region_excludes_shared_tail` - `sealing_property_erases_structure` - `restoration_promise_names_a_route_that_does_not_exist` +- `one_refusal_two_destinations` ## Building & checks diff --git a/docs/design-ledgers.md b/docs/design-ledgers.md index c82eea5b30f..1c49df7a32e 100644 --- a/docs/design-ledgers.md +++ b/docs/design-ledgers.md @@ -45,6 +45,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **merge region excludes the shared tail** (a roster carrier whose rows are multi-line blocks ending in an identical suffix makes every two-lane append resolve WRONG BY DEFAULT. The three-way merge factors the shared suffix out of the conflict region, so the region holds two half-blocks above the markers and one tail below them, and the purely additive resolution -- delete the markers, keep both sides, which is the CORRECT resolution when the two appended rows are independent -- leaves the first row's closing lines belonging to the second. Specimen: this carrier, which conflicted on every integration of main across four merge bases in one session (2026-09-01) with a shared tail of `evidence: [],` and `}`; `gunbc.rung_drop` had the same shape with `}` alone. **THE CLASS IS LOUD, AND THAT IS THE HALF A REPORT OF IT WILL GET WRONG.** The first reading was that the severed row survives as a structurally broken declaration under which the natural check -- declared names against rostered names -- still passes, because both lists stay complete. Measured against a gunbc built at d0009ca531 on the resolved shape: it is a PARSE REFUSAL at the module index, `expected expression, found Eq`, because a `data` keyword cannot stand in record-field position. Nothing reaches the checks that reading worried about, so the cost is toil and not silent wrongness -- a load-bearing authority whose every integration lands a conflict whose natural resolution does not compile, hand-repaired each time. **RECOGNITION RULE: for a carrier two lanes append to, ask what suffix the appended units SHARE, because a conflict region never contains it -- whatever semantics live in that suffix are exactly what a resolution can drop.** THE REPAIR IS THE UNIT AND NOT A CHECK: make the appended unit one line, and the shared suffix is a blank separator carrying nothing. A brace-balance or name-join check written here would be the DESIGN section 4b decoration -- permanently green, because the compiler already refuses the only corpus it could fire on.) - **a construction-restricting property read as a structure-erasing one** (a declaration is annotated to RESTRICT how its inhabitants may be built, and a consumer that asks about the declaration's SHAPE treats the annotation as a reason to stop looking -- so the deliberate climb on the construction axis silently drops a rung on every axis decided by shape, with no declaration, because the two axes are read by different consumers. **THE INVERSION IS THE CLASS**: the annotation exists to make the carrier MORE distinct from its payload, and the consumer's response is to make it INDISTINGUISHABLE from everything. Recognition rule, keyed on the SHAPE and not on any one keyword: whenever a declaration-level marker is stored in a general side-channel -- a properties list, an attribute bag, a modifier set -- find every consumer that BRANCHES ON THAT CHANNEL BEING NON-EMPTY rather than on the specific marker, and ask what each of them would have answered had the marker been absent; a consumer that answers 'opaque', 'unknown', or 'skip' for the whole channel has conflated 'this declaration carries a marker I do not model' with 'this declaration has no structure', and every future marker inherits the same silence on arrival. **SPECIMEN, with the discriminating pair** (gunbc XL-0-FLOOR, 2026-09-01): `v2.compiler.normalized_tree` `NormalizedTree` was sealed by BL-1 from an alias for `Node` into a `sole_constructor` record so that a wrapper-retention drop would be unwritable. `sole_constructor` is carried as a PROPERTY on the declaration node (`v1.compiler.parse` `parsed_sole_constructor_properties`), and `v1.compiler.infer` `exposure_view_for_node` answered `OpaqueTypeHead` for any node whose properties list was non-empty -- so `nominal_product_head_name` answered the empty string for every sealed carrier, `nominal_product_inhabitance_refusal` short-circuited on the empty head, and `declared_type_inhabitance` fell through to `Inhabits`. `v2.compiler.source_authority` `normalized_source_ast_equal_witness` then bound a `NormalizedTree` at a formal declared `Node` and the compiler ACCEPTED it: the ordinary-floor violation DESIGN section 4b names as exact application bijection, below baseline. The discriminating pair is two record declarations identical to the token except for the word `sole_constructor` -- the sealed one compiled with zero diagnostics where the plain one refused. **WHY A CENSUS MISSED IT, which is the part that generalizes**: gunbc#8886 measured 285 sites behind the `v2.*` direct-call argument-type exemption, of which 148 were `Node` against `ResolvedTree`/`ParseTree` and siblings -- every one a transparent-ALIAS false positive. This shape never appears in that roster and could not have, because it is a TRUE positive the comparison relation cannot reach: the census enumerates what the relation REFUSES, so a defect the relation is blind to is invisible to the census by construction, and a large census reads as thorough coverage of exactly the region it cannot see. **THE MISDIAGNOSIS THIS CLASS INVITES, recorded because this lane was dispatched with it**: the silence sat inside a module the exemption covers, so the exemption was the obvious cause; refuting it took running the identical program in an ordinary module and on a tree with the exemption deleted, both of which stayed silent, while the same run showed the exemption's effect on a kernel red so the arms were provably live. A plausible nearby mechanism that is genuinely broken is the most expensive wrong answer available, because repairing it changes nothing and the repair reads as coverage. **Rung: mechanically preventable, and the ceiling for this class as a class is the same rung.** The repair makes one marker structure-preserving by positive establishment -- the parser builds the identical declaration node and only the properties list differs -- and every OTHER marker in that channel stays opaque and unmeasured, which is a named residue rather than a covered class. The next-rung trigger is a CAPABILITY: markers carried in the declaration's own type rather than in an untyped side-channel, so that a consumer branching on the channel cannot compile.) - **a restoration promise names a route that does not exist** (a mechanism withholds, defers or dormant-marks a population and tells the reader it becomes observable again under some named condition — and that condition names a RUN, LANE, CADENCE OR SWEEP the tree does not contain. Nothing refuses, because the promise is a string in a diagnostic rather than a citation anything resolves; the population is not silently dropped, which is what makes the class survive review — it is dropped WITH A RECEIPT, and the receipt is what stops anyone looking. **THE BOUNDARY AGAINST `unbacked_execution_claim` IS THE TENSE AND IT DECIDES THE REMEDY.** That class is prose asserting a relation that RUNS NOW; this is prose asserting a relation that WILL run — a future condition, so `git log --all -S` over the declaration form finds nothing to past-tense and the origin arms there do not apply. It is also not `absorbing_fallback`: nothing widens, the withhold is precise and correctly counted. It is 4b(3)'s trigger trap with the polarity inverted — there a trigger names LESS than the capability it restores and gets satisfied while the capability stays dead; here the trigger names a capability whose PRECONDITION IS ALREADY FALSE, so it can never be satisfied at all and the row waits forever in a state that reads as temporary. **SPECIMEN WITH A RECEIPT, measured 2026-09-01 on head 4c6c509e and unrepaired at authoring.** `v1_compiler.cli_run.required_floor_runner` `suppress_withheld` removes enrolled expected-red identities whose module sits outside the required gate, printing that their enrolment `becomes observable again when the gate roster admits the module or in the whole-corpus receipts run`. THAT RUN DOES NOT EXIST: the phrase occurs exactly once in the tree, inside the message that promises it, and the repository carries three workflows of which none is it. 39 identities across 23 modules sit under that promise. Each is enrolled on `v2.workflow.floor_expected_red`, whose own header states what an enrolment asserts — that the identity REACHES ITS SUBJECT AND ANSWERS, and that a row belongs there only while someone is fixing it — so every one of the 39 asserts `runs, fails, someone is fixing it` about a row no run reaches. The only surviving route by which one executes is the changed-witness override, i.e. somebody editing it. **THE POPULATION IS DERIVABLE AND IS DELIBERATELY NOT TRANSCRIBED HERE**: it is `v2.workflow.floor_expected_red` `floor_expected_red_roster` minus the identities whose module matches `v2.workflow.required_floor` `required_gate_prefixes` — two authorities and a set difference, so it re-derives instead of rotting. **THE SAME ROSTER'S HEADER ALREADY RECORDS THE ANCESTOR OF THIS MISTAKE**, which is why it is a class: 101 rows were held there as agreement while never reaching their subject, and were reclassified into `v2.workflow.floor_route_gap` on 2026-08-20 once `ExpectedRedArm` was taught to refuse `HostEffectRefused`, `HostToolUnresolved` and an interrupted budget. That repair closed the arm where a NON-VERDICT was read as agreement; this class is the same harm one step earlier, where a row never reaches an arm at all and a sentence promises it will. **RECOGNITION RULE: whenever a diagnostic says a withheld thing becomes observable again `in`/`under`/`by` some named run, grep the tree for that name and require an executing consumer — a workflow job, a scheduled entry point, an actuator argv. If the only occurrence is the promise itself, the population is dormant forever and the honest states are two: admit the row cannot be observed on any cadence, or delete the enrolment. **RUNG: 1 (mitigatable) — the withhold is counted and located, which is the whole of what holds. CEILING: 3, since `whether a named route exists` is decidable from the workflow and entry-point authorities the tree already carries. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact: restoration conditions expressed as a resolvable citation to an executing consumer rather than as prose, so a promise naming no route fails to compile — writing this particular sentence better retires nothing.) +- **one refusal, two destinations, remedy misdirected** (a single refusal at a single source column emits two rows naming DIFFERENT expected types, because two producers resolve the same declared spelling in different environments. The reader repairs from the row that names the parameter -- and that is the row the checker did NOT refuse on. **THE SYMPTOM IS THE RECOGNITION RULE, NOT THE CAUSE**: what a debugging author encounters is one column, two rows, two expected types; the instruction that saves them is DO NOT REPAIR FROM THE INHABITANCE ROW -- the compat row is what refused. Specimen, measured 2026-09-01 on gunbc c0a378c07be by calm-boar-314 and bold-carp-449 independently, on two binaries and two phases (`gunbc compile` emit-stage refusal and `gunbc run` entry-resolve), unrepaired at authoring. A module declaring `type String = FreeMonoid` and `fn takes_bare(s: String) -> Int`, called from a foreign module that IMPORTS the function, with a deliberately wrong `Int` actual so the diagnostic must name its destination, refuses with: `type mismatch: expected 'Primitive(String)', got 'Primitive(Int)'` AND `value does not inhabit its declared type at the direct call argument for parameter 's': declared 'Node(String)', produced 'Primitive(Int)'`. THE TWO PRODUCERS, read from source rather than inferred from message shape: `v1.compiler.infer direct_call_arg_mismatch_diags` renders the compat row from the formal as the CALLER environment resolves it, and `v1.compiler.infer declared_type_obligation_diags` renders the inhabitance row from `obligation.declared` through `declared_type_inhabitance`. Both reach `type_mismatch_error` and `DeclaredTypeNotInhabited` in `v1.compiler.core`, so the rendering is shared and the DIVERGENCE IS UPSTREAM OF IT -- which is why the two rows look like one mechanism disagreeing with itself. **THE TRIGGER IS TWO COMPETING BINDINGS LIVE IN ONE RESOLVING SCOPE, NOT THE IMPORT AS SUCH**, and this row states the narrower claim deliberately: the with/without-import pair is measured, but the two AGREEING cells agree for OPPOSITE reasons -- an un-imported foreign caller agrees at `Primitive(String)` because only the kernel binding is available, and an in-module caller agrees at `Node(String)` because only the local declaration is. Phrasing the trigger as the import would make a reader conclude the class does not reproduce when some other construct puts a second binding in scope. An explicit `import { }` is the ONLY construct measured to create the competition; whether any other does is UNMEASURED. Crossed arm, pre-registered before its log was read: removing the import moves ONLY the inhabitance row, from `Node(String)` to `Primitive(String)`, while the compat row is `Primitive(String)` under both -- so one producer follows the import binding and the other does not, rather than the whole reading shifting. RUNG FOUND AT: 1 (mitigatable) -- the line DOES stop, and stops located, so this is not silent wrongness; what fails is that the refusal MISDIRECTS the remedy, which is DESIGN section 5's requirement that a refusal be typed AND located read one layer deeper: located at the right column while naming the wrong destination. CEILING: 3 (structurally guaranteed) -- one resolution of a callee's declared type per call site, consumed by both producers, makes two destinations unconstructible. NEXT-RUNG TRIGGER, naming the capability rather than an artifact: a single resolved-formal authority at the call site that both the compat check and the inhabitance obligation READ, sufficient that no call-site refusal can render two different expected types for one parameter. Distinct from `meaning_fork`, which is one NAME carrying two meanings across scopes -- that is the underlying condition here and is separately rostered; this row is about two PRODUCERS disagreeing inside a single refusal, which is what makes the remedy wrong rather than merely the meaning ambiguous. Distinct from `diagnostic_name_mechanism_silent`: there the diagnostic names a mechanism that never ran; here both mechanisms ran and both reported faithfully about different environments. WHAT IS NOT CLAIMED, by either measurer: which producer is correct, and why they read the binding differently. No arm on either rig touches it, and the source reading above identifies the producers without settling which environment a call-argument formal SHOULD be resolved in.) ## Declared rung drops (§4b(3)) From 845c1d3db6990271d4ec7e12b1dbc45343365948 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 14:03:41 +0000 Subject: [PATCH 06/10] Supersede the one-artifact memory ceiling: 8.37 GiB, measured the same way as the figure it replaces vivid-deer-102 asked me to file this and was right that it matters more than a number being slightly off: a documented ceiling that UNDERSTATES the measured peak gets cited as the reason a thing is safe to try. At 7.54 GiB against a 7.86 GB VM the margin reads as thin-but-conceivable, which invites the "maybe with a tighter budget setting" attempt whose only outcome is an rc=137 twenty minutes in. At 8.37 GiB against 7.32 GiB the requirement is a full gigabyte outside the whole VM. MEASURED THE SAME WAY AS THE ROW IT REPLACES, which is the only reason it can supersede rather than sit beside: polling VmHWM -- the kernel's own high-water mark -- to completion, on 2026-09-01, this tree, rc=0 with DESIGN.md written. 8,776,996 KiB. TWO CORRECTIONS TO MY OWN EARLIER REPORTING, recorded because both would have propagated. I first reported 8.76 GiB: that was a unit error, dividing KiB by 1000 twice rather than 1024 twice. And I described my original 5-second `ps -o rss=` sampling as a peak superseding a sample -- backwards. VmHWM cannot underreport; sampled RSS can only ever be a LOWER BOUND. The gate's method was the stronger one, so the honest move was to adopt it rather than argue from a weaker instrument. THE DATED PAIR IS DELIBERATE. 7.54 is not amended in place, because "the ceiling moved with the corpus" and "the ceiling was mismeasured" are different facts and only the pair distinguishes them. Same instrument, same method, 0.83 GiB higher in one day: it grew. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- .../instruments/generated_artifact_gate.dag | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/dag/gunbc/instruments/generated_artifact_gate.dag b/dag/gunbc/instruments/generated_artifact_gate.dag index a8bb0963979..87c49be80d2 100644 --- a/dag/gunbc/instruments/generated_artifact_gate.dag +++ b/dag/gunbc/instruments/generated_artifact_gate.dag @@ -113,11 +113,33 @@ func generated_artifact_drift_failure_receipt() -> String { // would fit. The first half is true; THE SECOND IS FALSE AND WAS MEASURED FALSE BEFORE THIS // LANDED, which is why the corrected version is recorded rather than the tidy one. // -// THE CEILING, stated at the grain that is actually true (measured 2026-08-31, this tree, by -// polling VmHWM to completion): -// main_wet -- all 35 artifacts -- peak RSS 7.55 GiB -// main_wet_one -- exactly one -- peak RSS 7.54 GiB -// ctrl-build --remote runner VM -- 7.86 GB TOTAL +// THE CEILING, stated at the grain that is actually true (by polling VmHWM to completion): +// main_wet -- all 35 artifacts -- peak RSS 7.55 GiB (2026-08-31) +// main_wet_one -- exactly one -- peak RSS 8.37 GiB (2026-09-01, SUPERSEDES 7.54) +// ctrl-build --remote runner VM -- 7.86 GB TOTAL (= 7.32 GiB) +// +// THE ONE-ARTIFACT FIGURE ROSE 0.83 GiB IN ONE DAY AND THE OLD ONE IS NOT AMENDED IN PLACE, +// because a ceiling that moves with the corpus is a different fact from a ceiling that was +// mismeasured, and only the dated pair shows which this is. 8.37 GiB was measured on +// 2026-09-01 by the same method as the row above it -- polling VmHWM, the kernel's own +// high-water mark, to completion -- so the two are comparable and the growth is real rather +// than an artifact of instrumentation. Re-derive it rather than trusting it: the poller is +// two lines of shell over /proc//status, and the figure belongs to the tree it was +// measured on. +// +// WHY THE SUPERSESSION MATTERS MORE THAN THE 0.83: at 7.54 against a 7.86 GB VM the margin +// reads as thin-but-conceivable, which invites the "maybe with a tighter budget setting" +// attempt whose only outcome is an rc=137 twenty minutes in. At 8.37 GiB against 7.32 GiB +// the requirement is a full gigabyte OUTSIDE the whole VM and the question stops being +// tempting. A documented ceiling that UNDERSTATES the measured peak is worse than an +// unmeasured one, because it gets cited as the reason a thing is safe to try -- the §4b +// decoration shape pointed at a resource limit rather than at a check. +// +// gunbc.memory_stall_refusal bounds the same runner class from the other two sides: a +// TRUTHFUL budget declaration thrashes without completing, an OVERSTATED one is SIGKILLed at +// rc=137. With this figure the honest range there is not merely narrow, it is EMPTY, and the +// remedy is a runner exposing a real cgroup limit rather than any value of the budget +// variable. // Regenerating one artifact costs what regenerating thirty-five costs. The generation fold is NOT // where the memory goes: the shared WHOLE-TREE RESOLUTION is, and every path reaching the // generation stage pays it in full, so ROSTER SIZE IS NOT THE VARIABLE. main_wet is SIGKILLed on From 65da87d34ae39f5c13d9510067df1b1c5f18296c Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 17:21:35 +0000 Subject: [PATCH 07/10] Weaken the adapter control's claim to what its bytes can decide (review 58256) The control asserted, in its annotation, that the adapter CLOSES the E0277 seam. A substring assertion over emitted Rust cannot decide that at any lane membership -- whether the bytes compile is a rustc verdict -- so the claim was 4b(1) rung inflation. Codex review 58256 named it; the remedy is a sentence, not a mechanism. The annotation now states what the control establishes at its declared grain (emission succeeds, zero error diagnostics asserted first, and the bytes have the discriminating shape: adapter present at the declared-arrow parameter, absent at the bare type variable) and what it does not (that the emitted program compiles). It names ct_self_compile_cargo_check_test as the rustc consumer at corpus grain, says why that is not reached per-fixture -- probe.rs references the crate runtime and does not stand alone, and a second per-fixture compile path beside the corpus-level one is the parallel authority section 6 warns about -- and points at the declared section 4b(3) drop emitted_bytes_witness_required_lane for the residual gap. Stage0 mirrors regenerated to the fixed point: two rounds installed, then first_generation_equal=true 149/149/149, declared_divergent=1 [main.rs]. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- src/v1/compiler_tests_rust.dag | 15 +++++++++++++++ src/v1/stage0/src/compiler_tests.rs | 15 +++++++++++++++ .../stage0/src/v1_compiler_compiler_tests_rust.rs | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/v1/compiler_tests_rust.dag b/src/v1/compiler_tests_rust.dag index 744fd0ef497..97e76677ad0 100644 --- a/src/v1/compiler_tests_rust.dag +++ b/src/v1/compiler_tests_rust.dag @@ -3085,6 +3085,21 @@ fn ct_function_value_adapter_bound_alignment_control_test() -> String { " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n", " // they remain one expression. This control is what notices if they are ever forked.\n", " //\n", + " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that\n", + " // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal\n", + " // fails here rather than being matched past -- and that the emitted bytes have this SHAPE:\n", + " // the adapter appears at the declared-arrow parameter and is absent at the bare type\n", + " // variable. That is a structural fact about the emitter, and substring matching can decide it.\n", + " //\n", + " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a\n", + " // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring\n", + " // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust\n", + " // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here\n", + " // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types)\n", + " // and does not stand alone, and a second per-fixture compile path beside the corpus-level one\n", + " // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop\n", + " // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else.\n", + " //\n", " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n", " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n", " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n", diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 63ca25ac36d..009864f5a37 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -998,6 +998,21 @@ mod compiler_tests { // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while // they remain one expression. This control is what notices if they are ever forked. // + // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that + // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal + // fails here rather than being matched past -- and that the emitted bytes have this SHAPE: + // the adapter appears at the declared-arrow parameter and is absent at the bare type + // variable. That is a structural fact about the emitter, and substring matching can decide it. + // + // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a + // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring + // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust + // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here + // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types) + // and does not stand alone, and a second per-fixture compile path beside the corpus-level one + // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop + // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else. + // // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index b122ae7bdb4..4df2682bc87 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -381,7 +381,7 @@ pub fn ct_shell_service_output_projection_known_hole_probe_test() -> String { } pub fn ct_function_value_adapter_bound_alignment_control_test() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n".to_string(), " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n".to_string()), " //\n".to_string()), " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n".to_string()), " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n".to_string()), " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n".to_string()), " // the argument in a forwarding closure, and it decides on\n".to_string()), " // `param_node_type_expr(n: param).params |> count > 0`.\n".to_string()), " //\n".to_string()), " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n".to_string()), " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n".to_string()), " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n".to_string()), " // they remain one expression. This control is what notices if they are ever forked.\n".to_string()), " //\n".to_string()), " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n".to_string()), " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n".to_string()), " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n".to_string()), " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n".to_string()), " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n".to_string()), " // ARGUMENTS, never its parameter count.\n".to_string()), " #[test]\n".to_string()), " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n".to_string()), " defect rather than a defect in the fixture. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"probe module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n".to_string()), " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n".to_string()), " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n".to_string()), " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n".to_string()), " bound -- if this ever gains one, the adapter predicate must move with it, \\\n".to_string()), " got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n".to_string()), " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n".to_string()), " // whose argument is equally a call result, so shape alone does not explain it.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n".to_string()), " ),\n".to_string()), " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n".to_string()), " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n".to_string()), " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n".to_string(), " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n".to_string()), " //\n".to_string()), " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n".to_string()), " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n".to_string()), " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n".to_string()), " // the argument in a forwarding closure, and it decides on\n".to_string()), " // `param_node_type_expr(n: param).params |> count > 0`.\n".to_string()), " //\n".to_string()), " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n".to_string()), " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n".to_string()), " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n".to_string()), " // they remain one expression. This control is what notices if they are ever forked.\n".to_string()), " //\n".to_string()), " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that\n".to_string()), " // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal\n".to_string()), " // fails here rather than being matched past -- and that the emitted bytes have this SHAPE:\n".to_string()), " // the adapter appears at the declared-arrow parameter and is absent at the bare type\n".to_string()), " // variable. That is a structural fact about the emitter, and substring matching can decide it.\n".to_string()), " //\n".to_string()), " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a\n".to_string()), " // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring\n".to_string()), " // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust\n".to_string()), " // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here\n".to_string()), " // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types)\n".to_string()), " // and does not stand alone, and a second per-fixture compile path beside the corpus-level one\n".to_string()), " // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop\n".to_string()), " // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else.\n".to_string()), " //\n".to_string()), " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n".to_string()), " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n".to_string()), " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n".to_string()), " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n".to_string()), " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n".to_string()), " // ARGUMENTS, never its parameter count.\n".to_string()), " #[test]\n".to_string()), " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n".to_string()), " defect rather than a defect in the fixture. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"probe module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n".to_string()), " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n".to_string()), " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n".to_string()), " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n".to_string()), " bound -- if this ever gains one, the adapter predicate must move with it, \\\n".to_string()), " got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n".to_string()), " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n".to_string()), " // whose argument is equally a call result, so shape alone does not explain it.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n".to_string()), " ),\n".to_string()), " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n".to_string()), " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n".to_string()), " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) } pub fn compiler_tests_source() -> String { From a1336b1264a27ec0413e1efd1db5cf4d5f0c2069 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 18:36:46 +0000 Subject: [PATCH 08/10] Drop the named non-candidate and the inflated assert string (review 58256, follow-through) Three further corrections, each verified before applying: - The annotation no longer NAMES any candidate rustc consumer, even negatively. A named non-candidate is still a pointer, and a pointer is what a later reader turns into coverage. It now states a fact about the tree instead: no enrolled fail-closed rustc consumer covers this synthetic fixture. Checked rather than assumed -- the committed workflow invokes cargo test --release -p v1-compiler --lib with no --ignored, so what is established is that no committed scheduled route exists, not that none could. - The assertion MESSAGE said the adapter must close the seam. That is a claim at a rung the test does not reach, and it is what a reader sees at the moment it goes red. It now says the forwarding adapter must be EMITTED at the impl Fn parameter. - No rung-drop citation remains in the annotation: the drop it named is a drop of lane membership and does not answer a discrimination objection. Mirrors driven to the fixed point over three rounds -- the emitter of the test text, then the test text, then the verify -- first_generation_equal=true, 149/149/149, declared_divergent=1 [main.rs]. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- src/v1/compiler_tests_rust.dag | 40 ++++++++++++------- src/v1/stage0/src/compiler_tests.rs | 40 ++++++++++++------- .../src/v1_compiler_compiler_tests_rust.rs | 2 +- 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/v1/compiler_tests_rust.dag b/src/v1/compiler_tests_rust.dag index 97e76677ad0..6a08b471d4c 100644 --- a/src/v1/compiler_tests_rust.dag +++ b/src/v1/compiler_tests_rust.dag @@ -3085,20 +3085,32 @@ fn ct_function_value_adapter_bound_alignment_control_test() -> String { " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n", " // they remain one expression. This control is what notices if they are ever forked.\n", " //\n", - " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that\n", - " // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal\n", - " // fails here rather than being matched past -- and that the emitted bytes have this SHAPE:\n", - " // the adapter appears at the declared-arrow parameter and is absent at the bare type\n", - " // variable. That is a structural fact about the emitter, and substring matching can decide it.\n", + " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN. Emission SUCCEEDS on this fixture -- zero\n", + " // error diagnostics, asserted FIRST, so a refusal fails here rather than being matched past\n", + " // -- and the emitted bytes carry, for this fixture, all six of:\n", + " // the function-valued producer emitted as `Rc`;\n", + " // the declared-arrow formal emitted as `impl Fn(..) + Clone`;\n", + " // a forwarding closure emitted AT that formal;\n", + " // the bare type-variable formal carrying NO Fn bound;\n", + " // NO forwarding closure at that formal;\n", + " // and hence the two emitter decisions staying aligned on this fixture.\n", + " // Those are structural facts about the emitter, and substring matching can decide them.\n", + " // That list is the WHOLE claim.\n", " //\n", - " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a\n", - " // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring\n", - " // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust\n", - " // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here\n", - " // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types)\n", - " // and does not stand alone, and a second per-fixture compile path beside the corpus-level one\n", - " // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop\n", - " // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else.\n", + " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED, AND NOTHING EXECUTING TODAY DOES.\n", + " // Whether these bytes compile is a RUSTC verdict, and no amount of exact rendering is\n", + " // evidence about one; a substring assertion could not decide it at any lane membership.\n", + " //\n", + " // NO ENROLLED FAIL-CLOSED RUSTC CONSUMER COVERS THIS SYNTHETIC FIXTURE. That is a statement\n", + " // about the whole tree as it stands, not a pointer at some other test that would do it --\n", + " // deliberately, because naming a candidate invites the next reader to read 'not yet' as\n", + " // 'once someone schedules it', and a candidate cited that way becomes coverage in the telling.\n", + " //\n", + " // NO PER-FIXTURE RUSTC CONSUMER IS BUILT HERE EITHER. probe.rs references the crate runtime\n", + " // (im::vector, v1_std_core, the artifact types) and does not stand alone, and a second\n", + " // per-fixture compile path is the parallel authority section 6 warns about. The standing\n", + " // execution half would be a real COMMITTED occurrence of this adapter shape joined BY\n", + " // IDENTITY to a rustc consumer that runs and REFUSES. That join does not exist today.\n", " //\n", " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n", " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n", @@ -3164,7 +3176,7 @@ fn ct_function_value_adapter_bound_alignment_control_test() -> String { " emitted.contains(\n", " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n", " ),\n", - " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n", + " \"the forwarding adapter must be emitted at the impl Fn parameter, got:\\n{}\",\n", " emitted\n", " );\n", " assert!(\n", diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 009864f5a37..0253dd4a46a 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -998,20 +998,32 @@ mod compiler_tests { // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while // they remain one expression. This control is what notices if they are ever forked. // - // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that - // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal - // fails here rather than being matched past -- and that the emitted bytes have this SHAPE: - // the adapter appears at the declared-arrow parameter and is absent at the bare type - // variable. That is a structural fact about the emitter, and substring matching can decide it. + // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN. Emission SUCCEEDS on this fixture -- zero + // error diagnostics, asserted FIRST, so a refusal fails here rather than being matched past + // -- and the emitted bytes carry, for this fixture, all six of: + // the function-valued producer emitted as `Rc`; + // the declared-arrow formal emitted as `impl Fn(..) + Clone`; + // a forwarding closure emitted AT that formal; + // the bare type-variable formal carrying NO Fn bound; + // NO forwarding closure at that formal; + // and hence the two emitter decisions staying aligned on this fixture. + // Those are structural facts about the emitter, and substring matching can decide them. + // That list is the WHOLE claim. // - // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a - // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring - // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust - // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here - // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types) - // and does not stand alone, and a second per-fixture compile path beside the corpus-level one - // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop - // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else. + // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED, AND NOTHING EXECUTING TODAY DOES. + // Whether these bytes compile is a RUSTC verdict, and no amount of exact rendering is + // evidence about one; a substring assertion could not decide it at any lane membership. + // + // NO ENROLLED FAIL-CLOSED RUSTC CONSUMER COVERS THIS SYNTHETIC FIXTURE. That is a statement + // about the whole tree as it stands, not a pointer at some other test that would do it -- + // deliberately, because naming a candidate invites the next reader to read 'not yet' as + // 'once someone schedules it', and a candidate cited that way becomes coverage in the telling. + // + // NO PER-FIXTURE RUSTC CONSUMER IS BUILT HERE EITHER. probe.rs references the crate runtime + // (im::vector, v1_std_core, the artifact types) and does not stand alone, and a second + // per-fixture compile path is the parallel authority section 6 warns about. The standing + // execution half would be a real COMMITTED occurrence of this adapter shape joined BY + // IDENTITY to a rustc consumer that runs and REFUSES. That join does not exist today. // // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing @@ -1077,7 +1089,7 @@ mod compiler_tests { emitted.contains( "apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)" ), - "the adapter must close the seam at the impl Fn parameter, got:\n{}", + "the forwarding adapter must be emitted at the impl Fn parameter, got:\n{}", emitted ); assert!( diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 4df2682bc87..f2f0eee4407 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -381,7 +381,7 @@ pub fn ct_shell_service_output_projection_known_hole_probe_test() -> String { } pub fn ct_function_value_adapter_bound_alignment_control_test() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n".to_string(), " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n".to_string()), " //\n".to_string()), " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n".to_string()), " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n".to_string()), " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n".to_string()), " // the argument in a forwarding closure, and it decides on\n".to_string()), " // `param_node_type_expr(n: param).params |> count > 0`.\n".to_string()), " //\n".to_string()), " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n".to_string()), " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n".to_string()), " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n".to_string()), " // they remain one expression. This control is what notices if they are ever forked.\n".to_string()), " //\n".to_string()), " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN, AND WHAT IT DOES NOT. It establishes that\n".to_string()), " // emission SUCCEEDS on this fixture -- zero error diagnostics, asserted first, so a refusal\n".to_string()), " // fails here rather than being matched past -- and that the emitted bytes have this SHAPE:\n".to_string()), " // the adapter appears at the declared-arrow parameter and is absent at the bare type\n".to_string()), " // variable. That is a structural fact about the emitter, and substring matching can decide it.\n".to_string()), " //\n".to_string()), " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED. Whether these bytes compile is a\n".to_string()), " // RUSTC verdict, and no amount of exact rendering is evidence about one; a substring\n".to_string()), " // assertion could not decide it at any lane membership. The rustc consumer for emitted Rust\n".to_string()), " // is ct_self_compile_cargo_check_test at corpus grain. It is not reached per-fixture here\n".to_string()), " // because probe.rs references the crate runtime (im::vector, v1_std_core, the artifact types)\n".to_string()), " // and does not stand alone, and a second per-fixture compile path beside the corpus-level one\n".to_string()), " // is the parallel authority section 6 warns about. The gap is the declared section 4b(3) drop\n".to_string()), " // emitted_bytes_witness_required_lane, retired by its trigger and by nothing else.\n".to_string()), " //\n".to_string()), " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n".to_string()), " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n".to_string()), " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n".to_string()), " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n".to_string()), " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n".to_string()), " // ARGUMENTS, never its parameter count.\n".to_string()), " #[test]\n".to_string()), " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n".to_string()), " defect rather than a defect in the fixture. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"probe module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n".to_string()), " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n".to_string()), " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n".to_string()), " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n".to_string()), " bound -- if this ever gains one, the adapter predicate must move with it, \\\n".to_string()), " got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n".to_string()), " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n".to_string()), " // whose argument is equally a call result, so shape alone does not explain it.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n".to_string()), " ),\n".to_string()), " \"the adapter must close the seam at the impl Fn parameter, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n".to_string()), " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n".to_string()), " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" // REGRESSION CONTROL for a property that holds BY CONSTRUCTION today, and which nothing\n".to_string(), " // else would notice losing. DESIGN section 4b(4): the evidence stays enrolled.\n".to_string()), " //\n".to_string()), " // A function-VALUE realizes as `Rc`; a function-typed PARAMETER realizes as an\n".to_string()), " // `impl Fn(..) + Clone` bound, and `Rc` carries no blanket `impl Fn`, so passing the first\n".to_string()), " // into the second is an E0277 seam. rust_call_arg_function_value_adapt closes it by wrapping\n".to_string()), " // the argument in a forwarding closure, and it decides on\n".to_string()), " // `param_node_type_expr(n: param).params |> count > 0`.\n".to_string()), " //\n".to_string()), " // THAT IS THE SAME EXPRESSION ON THE SAME NODE that emit_param/emit_rust_param_type use to\n".to_string()), " // decide whether to emit the `impl Fn` bound at all. So the adapter fires exactly where the\n".to_string()), " // seam exists, and cannot fire where it does not -- the two predicates cannot disagree while\n".to_string()), " // they remain one expression. This control is what notices if they are ever forked.\n".to_string()), " //\n".to_string()), " // WHAT THIS ESTABLISHES, AT ITS DECLARED GRAIN. Emission SUCCEEDS on this fixture -- zero\n".to_string()), " // error diagnostics, asserted FIRST, so a refusal fails here rather than being matched past\n".to_string()), " // -- and the emitted bytes carry, for this fixture, all six of:\n".to_string()), " // the function-valued producer emitted as `Rc`;\n".to_string()), " // the declared-arrow formal emitted as `impl Fn(..) + Clone`;\n".to_string()), " // a forwarding closure emitted AT that formal;\n".to_string()), " // the bare type-variable formal carrying NO Fn bound;\n".to_string()), " // NO forwarding closure at that formal;\n".to_string()), " // and hence the two emitter decisions staying aligned on this fixture.\n".to_string()), " // Those are structural facts about the emitter, and substring matching can decide them.\n".to_string()), " // That list is the WHOLE claim.\n".to_string()), " //\n".to_string()), " // IT DOES NOT ESTABLISH THAT THE E0277 SEAM IS CLOSED, AND NOTHING EXECUTING TODAY DOES.\n".to_string()), " // Whether these bytes compile is a RUSTC verdict, and no amount of exact rendering is\n".to_string()), " // evidence about one; a substring assertion could not decide it at any lane membership.\n".to_string()), " //\n".to_string()), " // NO ENROLLED FAIL-CLOSED RUSTC CONSUMER COVERS THIS SYNTHETIC FIXTURE. That is a statement\n".to_string()), " // about the whole tree as it stands, not a pointer at some other test that would do it --\n".to_string()), " // deliberately, because naming a candidate invites the next reader to read 'not yet' as\n".to_string()), " // 'once someone schedules it', and a candidate cited that way becomes coverage in the telling.\n".to_string()), " //\n".to_string()), " // NO PER-FIXTURE RUSTC CONSUMER IS BUILT HERE EITHER. probe.rs references the crate runtime\n".to_string()), " // (im::vector, v1_std_core, the artifact types) and does not stand alone, and a second\n".to_string()), " // per-fixture compile path is the parallel authority section 6 warns about. The standing\n".to_string()), " // execution half would be a real COMMITTED occurrence of this adapter shape joined BY\n".to_string()), " // IDENTITY to a rustc consumer that runs and REFUSES. That join does not exist today.\n".to_string()), " //\n".to_string()), " // WHY THE BARE TYPE VARIABLE IS THE DISCRIMINATING HALF. It was reported (by me, wrongly) as a\n".to_string()), " // silent defect: a parameter declared `T` has arity 0, so no adapter is emitted, and nothing\n".to_string()), " // refuses. The bytes below are the refutation -- `T` renders as a plain generic with NO Fn\n".to_string()), " // bound, so there is no seam to close, and adapting there would be a fabricated repair.\n".to_string()), " // Arity is invariant under substitution anyway: instantiation changes an arrow's type\n".to_string()), " // ARGUMENTS, never its parameter count.\n".to_string()), " #[test]\n".to_string()), " fn function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(32 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let source = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"probe.dag\".to_string(),\n".to_string()), " content: \"module probe\\nfn add_one(x: Int) -> Int { x + 1 }\\nfn make_adder() -> fn(Int) -> Int { fn(n) { add_one(x: n) } }\\nfn hold_tv(value: T) -> T { value }\\nfn apply_arrow(f: fn(Int) -> Int, v: Int) -> Int { f(v) }\\nfn through_type_variable() -> Int { apply_arrow(f: hold_tv(value: make_adder()), v: 1) }\\nfn through_declared_arrow() -> Int { apply_arrow(f: make_adder(), v: 1) }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let r = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![source]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let errors: Vec<_> = r\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " errors.is_empty(),\n".to_string()), " \"the fixture is ordinary admissible source; a refusal here is a compiler \\\n".to_string()), " defect rather than a defect in the fixture. Got: {:?}\",\n".to_string()), " errors\n".to_string()), " );\n".to_string()), " let emitted = r\n".to_string()), " .files\n".to_string()), " .iter()\n".to_string()), " .find(|f| f.path == \"src/probe.rs\")\n".to_string()), " .map(|f| f.content.clone())\n".to_string()), " .expect(\"probe module must emit src/probe.rs\");\n".to_string()), "\n".to_string()), " // (1) the producer side of the seam: a function VALUE is the Rc carrier.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn make_adder() -> Rc i64>\"),\n".to_string()), " \"a function-valued return must realize as the Rc carrier, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (2) a DECLARED-ARROW parameter carries the impl Fn bound -- the seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64)\"),\n".to_string()), " \"a declared-arrow parameter must carry the impl Fn bound, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (3) a BARE TYPE VARIABLE parameter carries NO Fn bound -- no seam exists here.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\"pub fn hold_tv(value: T) -> T\"),\n".to_string()), " \"a bare type-variable parameter must render as a plain generic with no Fn \\\n".to_string()), " bound -- if this ever gains one, the adapter predicate must move with it, \\\n".to_string()), " got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " // (4) THE ALIGNMENT, both directions. The adapter wraps the argument at the\n".to_string()), " // impl-Fn-bound parameter, and does NOT wrap it at the type-variable parameter --\n".to_string()), " // whose argument is equally a call result, so shape alone does not explain it.\n".to_string()), " assert!(\n".to_string()), " emitted.contains(\n".to_string()), " \"apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1)\"\n".to_string()), " ),\n".to_string()), " \"the forwarding adapter must be emitted at the impl Fn parameter, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !emitted.contains(\"hold_tv({ let __adapt_f\"),\n".to_string()), " \"no adapter may be injected at a parameter that carries no Fn bound -- that \\\n".to_string()), " would be a fabricated repair of a seam that does not exist, got:\\n{}\",\n".to_string()), " emitted\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"function_value_adapter_fires_exactly_where_the_impl_fn_bound_is_emitted panicked\");\n".to_string()), " }\n".to_string()), "\n".to_string()) } pub fn compiler_tests_source() -> String { From c302557559ff1d9827e263f663116bcf9e3a62c2 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Tue, 1 Sep 2026 19:51:04 +0000 Subject: [PATCH 09/10] Roster the new hand-Rust test blob in the scaffold index (review 58290) gunbc.language_source_scaffold_index carries one LanguageSourceScaffoldRow per hand-Rust blob decl, and test.claim.language_source_scaffold_index_test counts ct_ declarations in the carrier against rows for that carrier. The new control's blob had no row, so the diff added a ct_ declaration without appending to the roster it belongs in. The row takes compiler_tests_rust_hand_assertion_scaffold_trigger -- the same Scaffold disposition every other hand-assertion blob in this carrier carries, dissolving to SingleAuthority at v1.compiler.coercion CoercionTestEntry -- rather than minting a new one, which would be a section 3 fork. language_source_scaffold_roster_is_fully_dispositioned was EXECUTED with the row in place and returns true. Separately, and not repaired here: the carrier's completeness check is already red on main -- 43 ct_ declarations against 40 rostered rows, three blobs unrostered before this branch existed. That is filed as its own work item; this commit discharges only this diff's contribution. Mirrors unchanged (first_generation_equal=true, 149/149/149) and both doc projections regenerate to identical bytes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- dag/gunbc/language_source_scaffold_index.dag | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dag/gunbc/language_source_scaffold_index.dag b/dag/gunbc/language_source_scaffold_index.dag index 2f9a1cdc83e..3904c0fc878 100644 --- a/dag/gunbc/language_source_scaffold_index.dag +++ b/dag/gunbc/language_source_scaffold_index.dag @@ -414,6 +414,12 @@ data ct_row_ct_call_deficit_red_witness_test: LanguageSourceScaffoldRow = Langua disposition: compiler_tests_rust_hand_assertion_scaffold_trigger } +data ct_row_ct_function_value_adapter_bound_alignment_control_test: LanguageSourceScaffoldRow = LanguageSourceScaffoldRow { + carrier_module: "v1.compiler.compiler_tests_rust", + blob_decl: "ct_function_value_adapter_bound_alignment_control_test", + disposition: compiler_tests_rust_hand_assertion_scaffold_trigger +} + data ct_row_ct_function_value_named_application_controls_witness_test: LanguageSourceScaffoldRow = LanguageSourceScaffoldRow { carrier_module: "v1.compiler.compiler_tests_rust", blob_decl: "ct_function_value_named_application_controls_witness_test", disposition: compiler_tests_rust_hand_assertion_scaffold_trigger @@ -488,6 +494,7 @@ data language_source_scaffold_roster: List = [ ct_row_ct_caret_parse_smoke_native_witness_tests, ct_row_ct_call_shape_wall_witness_test, ct_row_ct_call_shape_duplicate_wall_witness_test, + ct_row_ct_function_value_adapter_bound_alignment_control_test, ct_row_ct_call_deficit_red_witness_test, ct_row_ct_function_value_named_application_controls_witness_test, ct_row_ct_function_value_field_method_known_hole_probe_test, From 2a4c4af5df4397ef10e6638e4c6ba0daf482018b Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Wed, 2 Sep 2026 00:53:01 +0000 Subject: [PATCH 10/10] Record the v1 admission for the adapter alignment control, and add EvidenceEnrollment (review 58359) Review 58359 refused the new compiler_tests blob for lacking a hand-Rust receipt naming a lane and a ROADMAP row. That vocabulary names nothing: verified independently by me and by the ruling manager against origin/main, DESIGN.md carries no such gate -- the SECOND time it has been cited at a PR and the second time it was found to name nothing (the first is recorded in the RcStr row of this same carrier). The receipt also cannot land in language_source_scaffold_index, whose row type has no field a lane or ROADMAP row could occupy; bolting it in as prose would be the section 4c violation. So the obligation lands where v1 admissions actually live. The row records the ruling relayed from bright-ram-778 on 2026-09-02, including the parts that are easiest to drop in the citing: PublicSurfaceGrowth FIRES LITERALLY and is admitted anyway, because the class exists to stop the seed accumulating CAPABILITY and a test emitter accumulates none; the cheaper ruling -- that compiler_tests blobs are not admission subjects at all -- was DECLINED, because a category exemption never comes up for review again while one admission does; the ruling admits this change only and does not resolve the new-declaration-versus-any-change boundary; and the counter-argument is preserved so overturning it is easy. EvidenceEnrollment is added to MaintenanceAdmissionInstance rather than forcing this into one of the four existing shapes -- every 4b(4) climb in v1 produces it, so it is a class and not a bespoke slot. Module typechecks (0 blocking diagnostics); no projection or mirror moved. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --- dag/gunbc/v1/v1_maintenance_standing.dag | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dag/gunbc/v1/v1_maintenance_standing.dag b/dag/gunbc/v1/v1_maintenance_standing.dag index bf3cbabe67b..148775cd6e7 100644 --- a/dag/gunbc/v1/v1_maintenance_standing.dag +++ b/dag/gunbc/v1/v1_maintenance_standing.dag @@ -52,6 +52,7 @@ type MaintenanceAdmissionInstance = | BehaviorPreservingRedundancyRemoval | BoundedOperationalFix | DefectRepairDiagnosticsMayMove + | EvidenceEnrollment // The five refused classes, and they DOMINATE the admitted ones above. These are // the growth surfaces DESIGN 3 names: a freeze that still accepts rows is not a @@ -441,3 +442,9 @@ data v1_seed_standing: SeedLifecycleStanding = SemanticsFrozen { maintenance: Ma // the carrier that actually governs v1 admissions. data v1_maintenance_typecheck_progress_admission_note: String = "AN ADMISSION UNDER THE 2026-08-20 PURPOSE TEST, recorded in the same PR as the change it admits, because an admission written afterwards is indistinguishable from an author's own classification. THE RULING, verbatim and relayed through the requesting session's parent (snappy-dove-250, import/namespace manager) on 2026-08-25: 'ah yeah - we need to fix the typecheckmoduleresult issue'. There is no PR review or transcript to point at; the relay is the record and this row is the citation, stated plainly rather than dressed up as pointing at a document that does not exist -- the same shape as v1_maintenance_purpose_ruling_note above.\n\nTHE DEFECT, at the grain that makes it a defect rather than an improvement. v1.compiler.infer typecheck_module has an early return: when build_type_env yields error diagnostics it hands back a TypedModule whose items list is EMPTY and never reaches item analysis. The seed therefore renders two different facts as one value -- a module that COMPLETED item checking and legitimately has no items, and a module that was ABANDONED before item checking started. Every downstream reader of TypedModule.items receives the same empty list for both, so a consumer wanting the distinction must infer it from 'items is empty AND there are error diagnostics', and that inference is unreliable in the direction that matters: a module that completed and has item-level errors presents identically. This is the state-space conflation DESIGN names, in the seed, on a carrier read by the whole back end.\n\nWHY THE FIELD LANDS ON TypedModule AND NOT ON TypecheckModuleResult, since the ruling names the result type and the change does not edit it. realize_module destructures the result and inserts only .typed into the module index; a progress field on the result alone would be discarded one line after it was set, which is this same defect one level out. The result type is where the issue was NOTICED; the carrier that survives the destructure is where the fact has to live.\n\nTHE EXHIBITED COST, because a defect with no demonstrated victim is a preference. A demand oracle built in this lane to score resolution producers read TypedModule.items to derive per-module demand, and was found DEAD as a scoring instrument for exactly this reason: an abandoned module reports total_arm1=1, which is indistinguishable from a genuine single-ask module, so the instrument's error is ANTI-CORRELATED with the defect it was built to find -- the modules most likely to abandon are the ones whose demand it most understates. That oracle was discarded rather than repaired, which is the measured price of the conflation and is why this is not speculative hardening.\n\nWHY IT SERVES THE V2 SELF-HOST PROGRAM, which is the whole admission test. The v2 resolution work this lane exists to do reads seed-produced TypedModule values to measure and compare producers. An instrument that cannot tell 'not checked' from 'nothing to check' cannot score a producer, and the program's next steps (one closure authority, exact denotation) are measurement-gated. This repairs the seed's report of its own progress; it adds no language behavior, no compatibility obligation, no escape hatch, and completes no seed feature.\n\nTHE SCOPE LIMIT, stated because this row will be cited and its limit is the part most likely to be dropped in the citing. THE RULING ADMITS THIS CHANGE ONLY. It does NOT settle whether PublicSurfaceGrowth means a NEW EXPORTED DECLARATION or ANY CHANGE TO EXPORTED SURFACE -- this change adds a coproduct and a record field to a type the seed exports, so it sits squarely on that unresolved boundary and was ruled admissible without the boundary being drawn. Nobody may cite this row as the answer to that question. A later proposal that needs the boundary decided must route it for its own ruling; treating this admission as precedent for a general reading of PublicSurfaceGrowth would be the authority-substitution failure DESIGN names -- borrowing one authority's answer to settle a question it never addressed. The five refused classes are untouched and still dominate every admission, including this one." + +// The 2026-09-02 admission, and the second sighting of a receipt vocabulary that names nothing. +// EvidenceEnrollment is added to the instance list rather than forcing this into one of the four +// existing shapes: every section 4b(4) climb in v1 produces this same shape, so it is a class. + +data v1_maintenance_adapter_alignment_control_admission_note: String = "AN ADMISSION UNDER THE 2026-08-20 PURPOSE TEST, recorded in the same PR as the change it admits. THE RULING, relayed from bright-ram-778 (XL-N manager) on 2026-09-02, in response to a REQUEST_CHANGES (review 58359) that refused a new compiler_tests blob for lacking a hand-Rust receipt. The relay is the record and this row is the citation -- the same shape as the rows above.\n\nWHAT WAS ADMITTED. v1.compiler.compiler_tests_rust ct_function_value_adapter_bound_alignment_control_test: a regression control asserting that the function-value adapter is emitted exactly where the impl Fn bound is emitted, and NOT at a bare type-variable parameter.\n\nTHE NAMED AUTHORITY IN THE REFUSAL DOES NOT EXIST, verified independently by the author and by the ruling manager against origin/main: DESIGN.md carries no hand-Rust receipt gate, no census-shrink requirement, and no lane-plus-ROADMAP deferral rule. This is the SECOND time that vocabulary has been cited at a PR and the second time it was found to name nothing -- see the RcStr row above, which records the first. The obligation is real and lands HERE, which is why this row exists; the receipt cannot land in gunbc.language_source_scaffold_index, whose LanguageSourceScaffoldRow carries only carrier_module, blob_decl and disposition, with no field a lane or ROADMAP row could occupy. Bolting that in as prose would be the section 4c violation of authoring commentary into a typed carrier.\n\nWHY IT SERVES THE V2 SELF-HOST PROGRAM. The adapter/bound alignment is an emission property v2 must preserve, and nothing else in the tree would notice a fork in it -- the adapter's predicate and the bound's predicate are one expression on one node today, and this control is what fails if they are ever separated. Section 4b(4) is explicit that a climb dissolves the lower-rung PRODUCTION machinery while the discriminating evidence REMAINS ENROLLED, so enrolling it is an obligation the design document places on us rather than a discretionary addition.\n\nTHE FIVE REFUSED CLASSES. Four are untouched: no semantic change (not NewLanguageBehavior), no compatibility obligation, no escape hatch or admission row, and the seed is no more capable after it (not SeedFeatureCompletion). PUBLICSURFACEGROWTH FIRES LITERALLY AND IS ADMITTED ANYWAY, stated plainly rather than argued away: the declaration IS a new exported fn in a v1 module. It is admitted because the class exists to stop the seed ACCUMULATING CAPABILITY, and a test emitter accumulates none -- nothing is expressible after this change that was not expressible before, and the declaration's entire content is evidence about behavior that already exists. The ruling cites the RcStr row's statement of WHAT THE CLASS IS FOR, and explicitly NOT its outcome: this is not 'RcStr was admitted, so this is'.\n\nWHY THE CHEAPER RULING WAS DECLINED, recorded because it will be proposed again. Ruling that compiler_tests blobs are not v1 admission subjects at all would have disposed of the review in one sentence and was refused: it carves an entire CATEGORY out of the freeze on a manager's say-so, as a side effect of handling one review. A freeze that still accepts rows is not a freeze, and a freeze with a silently exempt category is worse than one that accepts a row -- one admission is auditable and comes up for review; a category exemption never does.\n\nTHE SCOPE LIMIT. THIS RULING ADMITS THIS CHANGE ONLY. It does NOT resolve whether PublicSurfaceGrowth means a NEW EXPORTED DECLARATION or ANY CHANGE TO EXPORTED SURFACE. That boundary is recorded as unresolved above and stays unresolved; nobody may cite this row as the answer to it. Citing it that way would be the authority-substitution failure DESIGN names.\n\nTHE COUNTER-ARGUMENT, preserved so whoever overturns this need not reconstruct it: a new pub fn in a v1 module is exactly what the class names; the capability-versus-evidence distinction is authored rather than derived; and nothing mechanically holds it. WHO CAN OVERTURN IT: the classification is authored, at the mitigatable rung this carrier already declares, so it is a reviewer's or the operator's to reject. It is written to be easy to overturn."