From 662d5ec37de6ffb3c7dc78f0b3f6b588988d5864 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Thu, 24 Sep 2026 22:01:23 +0000 Subject: [PATCH 1/4] reference_conservation after #12221: the if-arm argument is a conserved control; the multiset control re-pinned off the two-statement body - the_if_arm_call_argument_is_reported_dropped_holds -> the_if_arm_call_argument_is_conserved_holds (DESIGN 4b(4): the pinned drop flipped when #12221 lowered if-arm arguments; the fixture passes the argument positionally so the rostered named-label drop cannot red it). - a_repeated_spelling_with_one_copy_dropped_is_exactly_one_row_holds keeps its subject (one pool copy, one drop) on a fixture whose dropped copy is a named-argument label, since #12221 now refuses the old '{ rc_rep \n rc_rep }' body. - compiler_frontend_program_status: IfArmCallArgumentReferenceVisibility is delivered by #12221, owned by the conserved control; the partition witness moves to 7 delivered / 6 outstanding. Both old rows were false on origin/main 53828ae4b2 (fierce-gull-556). Co-Authored-By: Claude Opus 5.5 (1M context) --- .../compiler_frontend_program_status.dag | 7 ++-- ...r_frontend_program_status_witness_test.dag | 9 ++-- .../reference_conservation_admission.dag | 5 ++- .../reference_conservation_test.dag | 41 +++++++++++++------ 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/dag/gunbc/compiler_frontend_program_status.dag b/dag/gunbc/compiler_frontend_program_status.dag index e4855d44b23..a0370d67bfe 100644 --- a/dag/gunbc/compiler_frontend_program_status.dag +++ b/dag/gunbc/compiler_frontend_program_status.dag @@ -271,9 +271,10 @@ fn xl2_prerequisite_standing(p: Xl2Prerequisite) -> Xl2PrerequisiteStanding { evidence: Xl2PrerequisiteEvidence { pr: 12108, merge_sha: "b0d307c31b" as NonEmptyStr, measured_at: "b8e0cc4eb9" as NonEmptyStr }, qualification: "CORRECTION: the earlier premise that call arguments were represented after lowering was FALSE. At b8e0cc4eb9 v2.compiler.body_lowering_fold body_lower_call_args_from_capture read the argument capture with the parameter-list spine reader, so every argument of a plain call, named or positional, lowered to a call with ZERO arguments -- the fact was absent from the normalized tree, not lost between the tree and the denominator. #12108 replaced it with a structural, fail-closed argument reader; an undeclared name used only as an argument now refuses at resolve located at the argument (v2.test.claim.namespace_xl0.call_argument_resolve_refusal). Bounded to PLAIN calls: arguments inside an if-arm are IfArmCallArgumentReferenceVisibility." as NonEmptyStr, } - IfArmCallArgumentReferenceVisibility => PrerequisiteOutstanding { - tracked_by: decl_ref(module_path: "v2.test.claim.namespace_xl0.reference_conservation", decl_name: "the_if_arm_call_argument_is_reported_dropped_holds"), - why: "a call argument inside an if-arm reaches no reference site: v2.compiler.body_lowering_fold body_lower_if_arm_operand_optional does not read it, and the conservation check reports it dropped (the tracking claim pins that drop). No fix has merged." as NonEmptyStr, + IfArmCallArgumentReferenceVisibility => PrerequisiteDelivered { + owner: decl_ref(module_path: "v2.test.claim.namespace_xl0.reference_conservation", decl_name: "the_if_arm_call_argument_is_conserved_holds"), + evidence: Xl2PrerequisiteEvidence { pr: 12221, merge_sha: "e74e345a93" as NonEmptyStr, measured_at: "53828ae4b2" as NonEmptyStr }, + qualification: "gunbc#12221 lowers if-arms through the statement authority, so a call argument inside an if-arm keeps its occurrence and reaches resolve. Measured on origin/main 53828ae4b2 (fierce-gull-556, seed-interpreted): the former pinned-drop claim the_if_arm_call_argument_is_reported_dropped_holds returned false because the argument was no longer dropped. That claim is restated as the conserved control that owns this row (DESIGN section 4b(4)). Its fixture passes the argument POSITIONALLY, because a named argument's label is a separately rostered drop (NamedArgumentLabel)." } BareFieldTypeVisibility => PrerequisiteDelivered { owner: decl_ref(module_path: "v2.test.claim.declaring_identity_spelling.production_ingest", decl_name: "a_bare_parameter_type_reaches_and_a_bare_field_type_does_too"), diff --git a/dag/test/claim/compiler_frontend_program_status_witness_test.dag b/dag/test/claim/compiler_frontend_program_status_witness_test.dag index 3ea5f0924b6..04484bdebc2 100644 --- a/dag/test/claim/compiler_frontend_program_status_witness_test.dag +++ b/dag/test/claim/compiler_frontend_program_status_witness_test.dag @@ -691,7 +691,7 @@ fn xl2_label_is(p: Xl2Prerequisite, want: Xl2Prerequisite) -> Bool { xl2_prerequisite_label(p: p) == xl2_prerequisite_label(p: want) } -test fn xl2_prerequisites_partition_into_six_delivered_and_seven_outstanding() -> Bool { +test fn xl2_prerequisites_partition_into_seven_delivered_and_six_outstanding() -> Bool { count(xl2_prerequisites) == 13 && xl2_delivered_by(p: PlainCallArgumentReferenceVisibility, pr: 12108, merge_sha: "b0d307c31b") && xl2_delivered_by(p: BareFieldTypeVisibility, pr: 11574, merge_sha: "b705d17c45") @@ -699,17 +699,16 @@ test fn xl2_prerequisites_partition_into_six_delivered_and_seven_outstanding() - && xl2_delivered_by(p: ResolveOccurrenceCompleteness, pr: 12116, merge_sha: "d759da1c50") && xl2_delivered_by(p: OperatorExpressionLoweredWhole, pr: 12145, merge_sha: "ada85b9452") && xl2_delivered_by(p: StrippedTreeRehearsalComposition, pr: 12097, merge_sha: "1d4fa51a3d") - && xl2_outstanding_tracked_by(p: IfArmCallArgumentReferenceVisibility, decl_name: "the_if_arm_call_argument_is_reported_dropped_holds") + && xl2_delivered_by(p: IfArmCallArgumentReferenceVisibility, pr: 12221, merge_sha: "e74e345a93") && xl2_outstanding_tracked_by(p: OptionalAccessorLocatedRefusal, decl_name: "lowering_accessor_collapses_a_sequence_operand") && xl2_outstanding_tracked_by(p: BlockStatementReferenceVisibility, decl_name: "unbound_statement_prefix_refuses_holds") && xl2_outstanding_tracked_by(p: LoweringOccurrenceProjection, decl_name: "lowering_rebuilds_an_authored_atom_without_its_occurrence") && xl2_outstanding_tracked_by(p: ListLiteralElementVisibility, decl_name: "list_literal_elements_dropped_at_v2_body_lowering") && xl2_outstanding_tracked_by(p: MatchOnCallScrutineeNavigation, decl_name: "match_on_a_call_scrutinee_refused_as_arm_navigation") && xl2_outstanding_tracked_by(p: CompoundCallArgumentValueLowering, decl_name: "compound_call_argument_value_refused_as_unread") - && count(xl2_prerequisites_outstanding()) == 7 + && count(xl2_prerequisites_outstanding()) == 6 && all(xl2_prerequisites_outstanding(), - p => xl2_label_is(p: p, want: IfArmCallArgumentReferenceVisibility) - || xl2_label_is(p: p, want: OptionalAccessorLocatedRefusal) + p => xl2_label_is(p: p, want: OptionalAccessorLocatedRefusal) || xl2_label_is(p: p, want: BlockStatementReferenceVisibility) || xl2_label_is(p: p, want: LoweringOccurrenceProjection) || xl2_label_is(p: p, want: ListLiteralElementVisibility) diff --git a/src/v2/compiler/reference_conservation_admission.dag b/src/v2/compiler/reference_conservation_admission.dag index a88ed8245f8..592961a1ab5 100644 --- a/src/v2/compiler/reference_conservation_admission.dag +++ b/src/v2/compiler/reference_conservation_admission.dag @@ -68,8 +68,9 @@ import extdeps.communication.medium { Lossless, Medium } // The shapes lowering is known to lose THAT A FIXTURE NEEDS TO EXCUSE, each pinned by its own // discriminating claim in v2.test.claim.namespace_xl0.reference_conservation. Closed on purpose: a // new shape is a new pinned claim first, then a row here, and a row enters only with the fixture -// that consumes it (the block-later-statement and if-arm-argument drops are pinned there too, and -// no admitted fixture's source contains them yet). +// that consumes it (the block-later-statement drop is pinned there too, and no admitted fixture's +// source contains it yet; the if-arm-argument drop was repaired by gunbc#12221 and is now a +// conserved control there). type KnownDropShape = NamedArgumentLabel | WhereRefinementPredicate diff --git a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag index 424eb9266c8..3419e8e554d 100644 --- a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag +++ b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag @@ -136,11 +136,18 @@ test fn the_block_second_statement_is_reported_dropped_holds() -> Bool { report_drop_count(report: block_second_statement_report(), wanted: ^dag_token_int_literal) == 1 } -// ---- drop 2: a call argument inside an if-arm -------------------------------------------------- - -// The argument's spelling is used NOWHERE else in its declaration, so the declaration-scoped pool -// cannot account for it and the red names exactly it. -data if_arm_call_argument_source: String = "module v2.test.reference_conservation_if_arm\n\nimport v2.std.logic { Bool }\n\nfn rc_callee(probe: Bool) -> Bool { probe }\n\ndata rc_arm_arg: Bool = true\n\nfn rc_if_arm(c: Bool) -> Bool { if c { rc_callee(probe: rc_arm_arg) } else { c } }\n" +// ---- former drop 2: a call argument inside an if-arm (repaired by #12221) --------------------- + +// MEASURED BOTH WAYS. Before gunbc#12221 the if-arm's call argument `rc_arm_arg` reached no reference +// site and this check reported it as exactly one DroppedReference. After #12221 (if-arms lower +// through the statement authority) the argument keeps its occurrence, and the pinned-drop claim went +// red on origin/main 53828ae4b2 (fierce-gull-556, seed-interpreted). Restated, not deleted (DESIGN +// section 4b(4)): it is now the permanent regression control that the if-arm argument is conserved. +// The argument is POSITIONAL on purpose: a named argument's label is its own, separately rostered +// drop (a_named_argument_label_is_reported_dropped_holds below), which would red this control for a +// reason that is not the if-arm. The argument's spelling is used NOWHERE else in its declaration, so +// the declaration-scoped pool cannot account for it: a regression drops it and names exactly it. +data if_arm_call_argument_source: String = "module v2.test.reference_conservation_if_arm\n\nimport v2.std.logic { Bool }\n\nfn rc_callee(probe: Bool) -> Bool { probe }\n\ndata rc_arm_arg: Bool = true\n\nfn rc_if_arm(c: Bool) -> Bool { if c { rc_callee(rc_arm_arg) } else { c } }\n" fn if_arm_call_argument_subject() -> ReferenceConservationSubject { conservation_subject(id_tail: "if_arm_call_argument", source: if_arm_call_argument_source) @@ -150,8 +157,9 @@ fn if_arm_call_argument_report() -> ReferenceConservationReport { conservation_report_of(subject: if_arm_call_argument_subject()) } -test fn the_if_arm_call_argument_is_reported_dropped_holds() -> Bool { - report_drop_count(report: if_arm_call_argument_report(), wanted: ^rc_arm_arg) == 1 +test fn the_if_arm_call_argument_is_conserved_holds() -> Bool { + let r = if_arm_call_argument_report() + reference_conservation_holds(report: r) && report_drop_count(report: r, wanted: ^rc_arm_arg) == 0 } // ---- former drop 3: a later operand of an operator chain (repaired by #12145) ------------------ @@ -235,12 +243,19 @@ test fn a_list_literal_call_argument_refuses_its_whole_module_holds() -> Bool { // ---- the multiset control: a repeated spelling, one copy dropped ------------------------------- -// `rc_rep` is spelled three times in one declaration: as the parameter binder (rebuilt into an -// edge label, so LocusErased against the pool's one label), as the first block statement (its -// occurrence survives), and as the second block statement (dropped). The pool holds one copy and -// the binder consumes it, so exactly ONE DroppedReference remains -- neither zero (a pool that -// failed to consume) nor two (a pool that was never read). -data repeated_spelling_source: String = "module v2.test.reference_conservation_repeat\n\nimport v2.std.logic { Bool }\n\nfn rc_repeat(rc_rep: Bool) -> Bool { rc_rep \n rc_rep }\n" +// `rc_rep` is spelled three times in the declaration `rc_repeat`: as its parameter binder (rebuilt +// into an edge label, so LocusErased against the pool's one label), as the named argument's LABEL at +// the call (dropped: a call lowers its arguments positionally -- the rostered NamedArgumentLabel +// shape), and as the argument's VALUE (its occurrence survives). The pool is declaration-scoped and +// holds one copy, which the binder consumes, so exactly ONE DroppedReference remains -- neither zero +// (a pool that failed to consume) nor two (a pool that was never read). `rc_callee`'s own `rc_rep` +// binder and body use sit in a different declaration and cannot feed this pool. +// RE-PINNED after gunbc#12221: the previous fixture dropped its repeated copy as the second of two +// block statements (`{ rc_rep \n rc_rep }`), and #12221 made a statement followed by another refuse +// located, so it no longer dropped one copy (red on origin/main 53828ae4b2). The multiset property is +// the subject, not the statement shape, so the fixture now drops through the one shape still +// rostered as a known drop. +data repeated_spelling_source: String = "module v2.test.reference_conservation_repeat\n\nimport v2.std.logic { Bool }\n\nfn rc_callee(rc_rep: Bool) -> Bool { rc_rep }\n\nfn rc_repeat(rc_rep: Bool) -> Bool { rc_callee(rc_rep: rc_rep) }\n" fn repeated_spelling_subject() -> ReferenceConservationSubject { conservation_subject(id_tail: "repeated_spelling", source: repeated_spelling_source) From 6c27c9d0cbdadecca834f32b45986eec0c14d0f6 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Thu, 24 Sep 2026 22:31:07 +0000 Subject: [PATCH 2/4] program status: the IfArm qualification carries its NonEmptyStr refinement like every other row (review 71069) Co-Authored-By: Claude Opus 5.5 (1M context) --- dag/gunbc/compiler_frontend_program_status.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dag/gunbc/compiler_frontend_program_status.dag b/dag/gunbc/compiler_frontend_program_status.dag index a0370d67bfe..b9a84303ad2 100644 --- a/dag/gunbc/compiler_frontend_program_status.dag +++ b/dag/gunbc/compiler_frontend_program_status.dag @@ -274,7 +274,7 @@ fn xl2_prerequisite_standing(p: Xl2Prerequisite) -> Xl2PrerequisiteStanding { IfArmCallArgumentReferenceVisibility => PrerequisiteDelivered { owner: decl_ref(module_path: "v2.test.claim.namespace_xl0.reference_conservation", decl_name: "the_if_arm_call_argument_is_conserved_holds"), evidence: Xl2PrerequisiteEvidence { pr: 12221, merge_sha: "e74e345a93" as NonEmptyStr, measured_at: "53828ae4b2" as NonEmptyStr }, - qualification: "gunbc#12221 lowers if-arms through the statement authority, so a call argument inside an if-arm keeps its occurrence and reaches resolve. Measured on origin/main 53828ae4b2 (fierce-gull-556, seed-interpreted): the former pinned-drop claim the_if_arm_call_argument_is_reported_dropped_holds returned false because the argument was no longer dropped. That claim is restated as the conserved control that owns this row (DESIGN section 4b(4)). Its fixture passes the argument POSITIONALLY, because a named argument's label is a separately rostered drop (NamedArgumentLabel)." + qualification: "gunbc#12221 lowers if-arms through the statement authority, so a call argument inside an if-arm keeps its occurrence and reaches resolve. Measured on origin/main 53828ae4b2 (fierce-gull-556, seed-interpreted): the former pinned-drop claim the_if_arm_call_argument_is_reported_dropped_holds returned false because the argument was no longer dropped. That claim is restated as the conserved control that owns this row (DESIGN section 4b(4)). Its fixture passes the argument POSITIONALLY, because a named argument's label is a separately rostered drop (NamedArgumentLabel)." as NonEmptyStr } BareFieldTypeVisibility => PrerequisiteDelivered { owner: decl_ref(module_path: "v2.test.claim.declaring_identity_spelling.production_ingest", decl_name: "a_bare_parameter_type_reaches_and_a_bare_field_type_does_too"), From 1204ef39225d11b614553ed757a8a8b51ccdb253 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sat, 26 Sep 2026 16:49:23 +0000 Subject: [PATCH 3/4] reference_conservation: acceptance is its own predicate; every lowered-and-conserved or lowered-and-dropped control asks it (side-chat REQUEST_CHANGES on #12258) reference_conservation_holds admits refused atoms, so a module normalization REFUSED could pass a 'conserved' control -- the refusal standing in for restored acceptance. Adds reference_conservation_accepted (refused == 0 and a nonzero conserved population) and reference_conservation_admitted (holds and accepted) beside holds in v2.compiler.reference_conservation. The five conserved controls (clean, if-arm, infix operand, list literal, anonymous slots) read admitted; the six pinned-drop controls (block second statement, named label, multiset, where predicate, third match arm, let binder) read accepted, since a refusal's rows could also satisfy 'exactly one drop'. Mutation control: a caret-symbol fixture that refuses at normalize is neither accepted nor admitted. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v2/compiler/reference_conservation.dag | 15 ++++++ .../reference_conservation_test.dag | 50 ++++++++++++++----- src/v2/workflow/floor_pure_producer_share.dag | 1 + 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/v2/compiler/reference_conservation.dag b/src/v2/compiler/reference_conservation.dag index ef8b6c822f8..c96c063833d 100644 --- a/src/v2/compiler/reference_conservation.dag +++ b/src/v2/compiler/reference_conservation.dag @@ -120,6 +120,21 @@ fn reference_conservation_holds(report: ReferenceConservationReport) -> Bool { length(xs: report.dropped) == 0 && length(xs: report.unmeasured) == 0 } +// ACCEPTED IS A SEPARATE FACT FROM CONSERVED, AND A CONTROL THAT MEANS "THIS MODULE LOWERS" MUST ASK +// BOTH. reference_conservation_holds admits refused atoms (a located refusal accounts for what it +// covers), so on its own it cannot tell a module that lowered and kept every reference from one that +// normalization REFUSED -- the refusal stands in for restored acceptance. A module is accepted when +// nothing in it was refused and it conserved a nonzero population (a report that measured nothing +// has not been accepted, only not rejected). Every control whose subject is "lowered, and ..." reads +// these, not their parts, so no claim re-spells what acceptance is. +fn reference_conservation_accepted(report: ReferenceConservationReport) -> Bool { + (report.refused == 0) && (report.conserved > 0) +} + +fn reference_conservation_admitted(report: ReferenceConservationReport) -> Bool { + reference_conservation_holds(report: report) && reference_conservation_accepted(report: report) +} + // ---- the parse-side population ----------------------------------------------------------------- // `items` counts the top-level items entered so far; `item_names` records each item's declaring diff --git a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag index a3aa3ca5e48..35600513b42 100644 --- a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag +++ b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag @@ -5,6 +5,8 @@ import v2.compiler.reference_conservation { ReferenceConservationReport, ReferenceConservationSubject, dag_declared_token_classes, + reference_conservation_accepted, + reference_conservation_admitted, reference_conservation_holds, reference_conservation_of_subject, reference_conservation_subject_of_read @@ -99,7 +101,7 @@ fn clean_control_report() -> ReferenceConservationReport { } test fn the_clean_control_conserves_every_authored_atom_holds() -> Bool { - reference_conservation_holds(report: clean_control_report()) + reference_conservation_admitted(report: clean_control_report()) } // The three numbers are separate and together account for the whole population: a check that @@ -132,7 +134,8 @@ fn block_second_statement_report() -> ReferenceConservationReport { } test fn the_block_second_statement_is_reported_dropped_holds() -> Bool { - report_drop_count(report: block_second_statement_report(), wanted: ^dag_token_int_literal) == 1 + let r = block_second_statement_report() + reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^dag_token_int_literal) == 1 } // ---- former drop 2: a call argument inside an if-arm (repaired by #12221) --------------------- @@ -158,7 +161,7 @@ fn if_arm_call_argument_report() -> ReferenceConservationReport { test fn the_if_arm_call_argument_is_conserved_holds() -> Bool { let r = if_arm_call_argument_report() - reference_conservation_holds(report: r) && report_drop_count(report: r, wanted: ^rc_arm_arg) == 0 + reference_conservation_admitted(report: r) && report_drop_count(report: r, wanted: ^rc_arm_arg) == 0 } // ---- former drop 3: a later operand of an operator chain (repaired by #12145) ------------------ @@ -179,7 +182,7 @@ fn infix_right_operand_report() -> ReferenceConservationReport { test fn the_infix_right_operand_is_conserved_holds() -> Bool { let r = infix_right_operand_report() - reference_conservation_holds(report: r) && report_drop_count(report: r, wanted: ^rc_rhs) == 0 + reference_conservation_admitted(report: r) && report_drop_count(report: r, wanted: ^rc_rhs) == 0 } // ---- a measured drop outside the brief: the named-argument label ------------------------------ @@ -200,7 +203,7 @@ fn named_argument_label_report() -> ReferenceConservationReport { test fn a_named_argument_label_is_reported_dropped_holds() -> Bool { let r = named_argument_label_report() - report_drop_count(report: r, wanted: ^rc_label) == 1 && length(xs: r.dropped) == 1 + reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^rc_label) == 1 && length(xs: r.dropped) == 1 } // ---- a list-literal call argument: conserved (was a module-wide refusal) --------------------- @@ -226,8 +229,7 @@ fn list_literal_argument_report() -> ReferenceConservationReport { test fn a_list_literal_call_argument_conserves_every_element_holds() -> Bool { let r = list_literal_argument_report() - reference_conservation_holds(report: r) - && r.refused == 0 + reference_conservation_admitted(report: r) && report_drop_count(report: r, wanted: ^rc_elsewhere) == 0 && report_drop_count(report: r, wanted: ^rc_list_second) == 0 && report_drop_count(report: r, wanted: ^rc_list_callee) == 0 @@ -259,7 +261,7 @@ fn repeated_spelling_report() -> ReferenceConservationReport { test fn a_repeated_spelling_with_one_copy_dropped_is_exactly_one_row_holds() -> Bool { let r = repeated_spelling_report() - report_drop_count(report: r, wanted: ^rc_rep) == 1 && length(xs: r.dropped) == 1 + reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^rc_rep) == 1 && length(xs: r.dropped) == 1 } // ---- a measured drop found by admission: the where-refinement predicate ----------------------- @@ -277,7 +279,7 @@ fn where_refinement_predicate_subject() -> ReferenceConservationSubject { test fn the_where_refinement_predicate_is_reported_dropped_holds() -> Bool { let r = conservation_report_of(subject: where_refinement_predicate_subject()) - report_drop_count(report: r, wanted: ^rc_pred) == 1 && length(xs: r.dropped) == 1 + reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^rc_pred) == 1 && length(xs: r.dropped) == 1 } // ---- measured drops found by admission: a later match arm, a statement-let binder ------------- @@ -289,7 +291,8 @@ test fn the_where_refinement_predicate_is_reported_dropped_holds() -> Bool { data match_later_arm_source: String = "module v2.test.reference_conservation_match\n\ntype RcT = RcA | RcB | RcC\n\ndata rc_first: Int = 1\n\ndata rc_second: Int = 2\n\ndata rc_third: Int = 3\n\nfn rc_match(t: RcT) -> Int {\n match t {\n RcA => rc_first\n RcB => rc_second\n RcC => rc_third\n }\n}\n" test fn the_third_match_arm_is_reported_dropped_holds() -> Bool { - report_drops_identity(report: conservation_report_of(subject: match_later_arm_subject()), wanted: ^rc_third) + let r = conservation_report_of(subject: match_later_arm_subject()) + reference_conservation_accepted(report: r) && report_drops_identity(report: r, wanted: ^rc_third) } // Found the same way through v2.test.claim.body_lowering.statement_let_bind: a statement-form let's @@ -299,7 +302,7 @@ data statement_let_binder_source: String = "module v2.test.reference_conservatio test fn a_statement_let_binder_is_reported_dropped_holds() -> Bool { let r = conservation_report_of(subject: statement_let_binder_subject()) - report_drop_count(report: r, wanted: ^rc_bound) == 1 && length(xs: r.dropped) == 1 + reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^rc_bound) == 1 && length(xs: r.dropped) == 1 } fn match_later_arm_subject() -> ReferenceConservationSubject { @@ -324,7 +327,30 @@ fn anonymous_slots_subject() -> ReferenceConservationSubject { test fn two_anonymous_parameter_slots_are_conserved_by_minted_identity_holds() -> Bool { let r = conservation_report_of(subject: anonymous_slots_subject()) - reference_conservation_holds(report: r) + reference_conservation_admitted(report: r) && report_drop_count(report: r, wanted: symbol_intern_lexeme(lexeme: "_")) == 0 && r.authored > 0 } + +// ---- the refusing fixture: acceptance is not the absence of drops ------------------------------- + +// A MODULE NORMALIZATION REFUSES MUST NOT PASS AS CONSERVED. A caret-symbol operand has no lowered +// form yet (gunbc.recurring_failure_mode caret_symbol_has_no_lowered_form), so this module refuses +// at normalize, located at the operand. reference_conservation_holds does not see that: a located +// refusal accounts for the atoms it covers, so the report can have no drops and no unmeasured rows. +// Every "lowered, and ..." control above therefore reads reference_conservation_accepted / +// reference_conservation_admitted, and this is their shared mutation: on a refusing report the +// shared predicate is false, so each of those controls would be red. When caret symbols lower, this +// fixture stops refusing and this claim reds -- restate it on whatever still refuses then. +data refusing_fixture_source: String = "module v2.test.reference_conservation_refusing\n\nimport v2.std.logic { Bool }\nimport v2.std.node { Symbol }\n\nfn rc_refusing(rc_sym_arg: Symbol) -> Bool { rc_sym_arg == ^rc_caret }\n" + +fn refusing_fixture_subject() -> ReferenceConservationSubject { + conservation_subject(id_tail: "refusing_fixture", source: refusing_fixture_source) +} + +test fn a_refusing_module_is_neither_accepted_nor_admitted_holds() -> Bool { + let r = conservation_report_of(subject: refusing_fixture_subject()) + (r.refused > 0) + && !reference_conservation_accepted(report: r) + && !reference_conservation_admitted(report: r) +} diff --git a/src/v2/workflow/floor_pure_producer_share.dag b/src/v2/workflow/floor_pure_producer_share.dag index 2c30cbde261..0bb7a02097b 100644 --- a/src/v2/workflow/floor_pure_producer_share.dag +++ b/src/v2/workflow/floor_pure_producer_share.dag @@ -848,6 +848,7 @@ data floor_cross_claim_pure_producers_warm: List = [ "v2.compiler.reference_conservation.dag_declared_token_classes", "v2.test.claim.namespace_xl0.reference_conservation.clean_control_subject", "v2.test.claim.namespace_xl0.reference_conservation.block_second_statement_subject", + "v2.test.claim.namespace_xl0.reference_conservation.refusing_fixture_subject", "v2.test.claim.namespace_xl0.reference_conservation.if_arm_call_argument_subject", "v2.test.claim.namespace_xl0.reference_conservation.infix_right_operand_subject", "v2.test.claim.namespace_xl0.reference_conservation.repeated_spelling_subject", From 907b08c0a5b1e371a373ad81bc18100404b77347 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sat, 26 Sep 2026 17:39:10 +0000 Subject: [PATCH 4/4] reference_conservation: the block-second-statement fixture is restated as refused-not-accepted, and is the shared refusing control (the caret fixture no longer refuses) Seed run at 1204ef3922 (fierce-gull-556): the_block_second_statement_is_reported_dropped_holds went red once it asked reference_conservation_accepted -- since #12221 a statement followed by another refuses located, so the old 'one drop' verdict had been the refusal standing in for a drop (the masking this predicate exists to expose). a_refusing_module_is_neither_accepted_nor_admitted_holds was red because a caret operand no longer refuses. The block fixture is now a_block_with_a_second_statement_is_refused_not_accepted_holds (refused > 0, not accepted, not admitted), the shared mutation for every lowered-and-... control; the caret fixture is removed. block_second_statement_numbers prints the report's counts. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../reference_conservation_admission.dag | 6 +-- .../reference_conservation_test.dag | 51 +++++++++---------- src/v2/workflow/floor_pure_producer_share.dag | 1 - 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/v2/compiler/reference_conservation_admission.dag b/src/v2/compiler/reference_conservation_admission.dag index e573f101888..8124244e0eb 100644 --- a/src/v2/compiler/reference_conservation_admission.dag +++ b/src/v2/compiler/reference_conservation_admission.dag @@ -68,9 +68,9 @@ import extdeps.communication.medium { Lossless, Medium } // The shapes lowering is known to lose THAT A FIXTURE NEEDS TO EXCUSE, each pinned by its own // discriminating claim in v2.test.claim.namespace_xl0.reference_conservation. Closed on purpose: a // new shape is a new pinned claim first, then a row here, and a row enters only with the fixture -// that consumes it (the block-later-statement drop is pinned there too, and no admitted fixture's -// source contains it yet; the if-arm-argument drop was repaired by gunbc#12221 and is now a -// conserved control there). +// that consumes it (gunbc#12221 changed both shapes that were pinned there without a row here: the +// if-arm argument is now conserved, and a block's later statement now REFUSES located, so both are +// restated in that module -- as a conserved control and as a refused-not-accepted control). type KnownDropShape = NamedArgumentLabel | WhereRefinementPredicate diff --git a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag index 35600513b42..ae199550982 100644 --- a/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag +++ b/src/v2/test/claim/namespace_xl0/reference_conservation_test.dag @@ -22,8 +22,9 @@ import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } import v2.std.logic { Bool } import v2.std.node { Symbol } import v2.std.text { String } -import v2.std.integer { Int } +import v2.std.integer { Int, integer_int_to_decimal_string } import extdeps.communication.medium { Lossless, Medium } +import std.process { ProcessExit, exit_failure } data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly @@ -121,8 +122,18 @@ test fn the_clean_control_routes_the_test_marker_to_its_channel_holds() -> Bool clean_control_report().test_marker_channel == 1 } -// ---- drop 1: the second statement of a block --------------------------------------------------- +// ---- former drop 1: the second statement of a block (now a located refusal, gunbc#12221) ------- +// MEASURED BOTH WAYS, AND THE SECOND WAY WAS HIDDEN. Before gunbc#12221 this body lowered and its +// second statement reached no reference site: one DroppedReference. #12221 made a statement followed +// by another REFUSE, located, so this module is no longer accepted. The old claim +// (the_block_second_statement_is_reported_dropped_holds) kept passing because +// reference_conservation_holds admits refused atoms: the refusal stood in for the drop. With +// reference_conservation_accepted asked, it went red (seed-interpreted at 1204ef3922, fierce-gull-556). +// Restated as what is true now: the module is refused, and neither accepted nor admitted. This is also +// the shared mutation for every "lowered, and ..." control in this file: on a refusing report the +// predicates they all ask are false, so each of them would be red. When a block's later statements +// lower, this reds and is restated as a conserved control. data block_second_statement_source: String = "module v2.test.reference_conservation_block\n\nfn rc_block() -> Int { 1 \n 2 }\n" fn block_second_statement_subject() -> ReferenceConservationSubject { @@ -133,9 +144,18 @@ fn block_second_statement_report() -> ReferenceConservationReport { conservation_report_of(subject: block_second_statement_subject()) } -test fn the_block_second_statement_is_reported_dropped_holds() -> Bool { +test fn a_block_with_a_second_statement_is_refused_not_accepted_holds() -> Bool { let r = block_second_statement_report() - reference_conservation_accepted(report: r) && report_drop_count(report: r, wanted: ^dag_token_int_literal) == 1 + (r.refused > 0) + && !reference_conservation_accepted(report: r) + && !reference_conservation_admitted(report: r) +} + +// A REPORT, NOT A CLAIM: the block fixture's four numbers through the process exit, so a run shows +// how the report counts a refused body. +fn block_second_statement_numbers() -> ProcessExit { + let r = block_second_statement_report() + exit_failure(reason: "authored=" + integer_int_to_decimal_string(value: r.authored) + " conserved=" + integer_int_to_decimal_string(value: r.conserved) + " locus_erased=" + integer_int_to_decimal_string(value: r.locus_erased) + " refused=" + integer_int_to_decimal_string(value: r.refused) + " dropped=" + integer_int_to_decimal_string(value: length(xs: r.dropped))) } // ---- former drop 2: a call argument inside an if-arm (repaired by #12221) --------------------- @@ -331,26 +351,3 @@ test fn two_anonymous_parameter_slots_are_conserved_by_minted_identity_holds() - && report_drop_count(report: r, wanted: symbol_intern_lexeme(lexeme: "_")) == 0 && r.authored > 0 } - -// ---- the refusing fixture: acceptance is not the absence of drops ------------------------------- - -// A MODULE NORMALIZATION REFUSES MUST NOT PASS AS CONSERVED. A caret-symbol operand has no lowered -// form yet (gunbc.recurring_failure_mode caret_symbol_has_no_lowered_form), so this module refuses -// at normalize, located at the operand. reference_conservation_holds does not see that: a located -// refusal accounts for the atoms it covers, so the report can have no drops and no unmeasured rows. -// Every "lowered, and ..." control above therefore reads reference_conservation_accepted / -// reference_conservation_admitted, and this is their shared mutation: on a refusing report the -// shared predicate is false, so each of those controls would be red. When caret symbols lower, this -// fixture stops refusing and this claim reds -- restate it on whatever still refuses then. -data refusing_fixture_source: String = "module v2.test.reference_conservation_refusing\n\nimport v2.std.logic { Bool }\nimport v2.std.node { Symbol }\n\nfn rc_refusing(rc_sym_arg: Symbol) -> Bool { rc_sym_arg == ^rc_caret }\n" - -fn refusing_fixture_subject() -> ReferenceConservationSubject { - conservation_subject(id_tail: "refusing_fixture", source: refusing_fixture_source) -} - -test fn a_refusing_module_is_neither_accepted_nor_admitted_holds() -> Bool { - let r = conservation_report_of(subject: refusing_fixture_subject()) - (r.refused > 0) - && !reference_conservation_accepted(report: r) - && !reference_conservation_admitted(report: r) -} diff --git a/src/v2/workflow/floor_pure_producer_share.dag b/src/v2/workflow/floor_pure_producer_share.dag index 0bb7a02097b..2c30cbde261 100644 --- a/src/v2/workflow/floor_pure_producer_share.dag +++ b/src/v2/workflow/floor_pure_producer_share.dag @@ -848,7 +848,6 @@ data floor_cross_claim_pure_producers_warm: List = [ "v2.compiler.reference_conservation.dag_declared_token_classes", "v2.test.claim.namespace_xl0.reference_conservation.clean_control_subject", "v2.test.claim.namespace_xl0.reference_conservation.block_second_statement_subject", - "v2.test.claim.namespace_xl0.reference_conservation.refusing_fixture_subject", "v2.test.claim.namespace_xl0.reference_conservation.if_arm_call_argument_subject", "v2.test.claim.namespace_xl0.reference_conservation.infix_right_operand_subject", "v2.test.claim.namespace_xl0.reference_conservation.repeated_spelling_subject",