From 14df8f1c330489c19378d830c4ed9f5b534647ca Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 18:25:44 +0000 Subject: [PATCH 1/4] test(v3-compiler): ratchet gate #89 SectionRef substrate shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add integration harness mirroring timing_lens_substrate_carrier_test: resolve SectionRef from lens_application.dag in full bootstrap and assert DeclarationScope / NodeScope variants, field labels, and DeclarationId / NodeId wiring per design doc §1.2. Co-authored-by: Cursor --- src/v3/compiler/tests/integration.rs | 2 + ...lens_application_substrate_carrier_test.rs | 130 ++++++++++++++++++ .../tests/integration/sg0_census_test.rs | 2 + 3 files changed, 134 insertions(+) create mode 100644 src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs diff --git a/src/v3/compiler/tests/integration.rs b/src/v3/compiler/tests/integration.rs index f071a1a442a..c3ffefec696 100644 --- a/src/v3/compiler/tests/integration.rs +++ b/src/v3/compiler/tests/integration.rs @@ -99,6 +99,8 @@ mod lane2_stage_2d_symbolic_cost_test; mod lane2_stage_2e_parallelism_test; #[path = "integration/lane3_stage_3b_db1_test.rs"] mod lane3_stage_3b_db1_test; +#[path = "integration/lens_application_substrate_carrier_test.rs"] +mod lens_application_substrate_carrier_test; #[path = "integration/lens_behavioral_parity_demonstration_test.rs"] mod lens_behavioral_parity_demonstration_test; #[path = "integration/lens_cost_target_realization_test.rs"] diff --git a/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs b/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs new file mode 100644 index 00000000000..476b8afa3ea --- /dev/null +++ b/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs @@ -0,0 +1,130 @@ +//! **Layer:** integration +//! +//! Structural acceptance for R3 §1.8 gate **`section_ref_substrate_landed`** (T-Lens-Application-Surface): +//! `SectionRef = DeclarationScope { declaration } | NodeScope { declaration, node }` in +//! [`src/v3/std/lens_application.dag`](../../../std/lens_application.dag), per +//! [`docs/design-lens-application-surface.md`](../../../../docs/design-lens-application-surface.md) §1.2–§2. + +use v3_compiler::dag::{Dag, DeclarationId, TypeConnective}; +use v3_compiler::generated_full_bootstrap_dag; + +fn peel_declaration_alias_head(dag: &Dag, mut id: DeclarationId) -> DeclarationId { + const MAX: usize = 64; + for _ in 0..MAX { + match &dag.declaration(id).connective { + TypeConnective::Instantiation { + template, + arguments, + } if arguments.is_empty() => { + id = *template; + } + TypeConnective::Atom(ap) => { + let Some(next) = ap.resolved_id() else { + break; + }; + id = next; + } + _ => break, + } + } + id +} + +fn section_ref_decl(dag: &Dag) -> DeclarationId { + dag.declarations() + .iter() + .find(|d| { + d.name.as_deref() == Some("SectionRef") && d.span.file.ends_with("lens_application.dag") + }) + .unwrap_or_else(|| { + panic!( + "bootstrap must declare `SectionRef` in src/v3/std/lens_application.dag \ + (gate #89 section_ref_substrate_landed)" + ) + }) + .id +} + +fn disj_variant_conj(dag: &Dag, disj: DeclarationId, label: &str) -> DeclarationId { + let TypeConnective::Disj { variants } = &dag.declaration(disj).connective else { + panic!("`SectionRef` must be a disjoint sum"); + }; + let v = variants + .iter() + .find(|x| x.label == label) + .unwrap_or_else(|| panic!("SectionRef missing `{label}` variant")); + v.ty +} + +fn conj_field_entry(dag: &Dag, conj: DeclarationId, field: &str) -> DeclarationId { + let TypeConnective::Conj { children } = &dag.declaration(conj).connective else { + panic!("expected Conj payload for SectionRef variant"); + }; + children + .iter() + .find(|f| f.label == field) + .unwrap_or_else(|| panic!("conj missing `{field}` field")) + .ty +} + +#[test] +fn gate_89_section_ref_is_disjoint_sum_from_lens_application_authority() { + let dag = generated_full_bootstrap_dag(); + let section_ref = section_ref_decl(&dag); + + let TypeConnective::Disj { variants } = &dag.declaration(section_ref).connective else { + panic!("SectionRef must lower to a Disj"); + }; + let labels: Vec<&str> = variants.iter().map(|v| v.label.as_str()).collect(); + assert_eq!( + labels, + vec!["DeclarationScope", "NodeScope"], + "SectionRef variant labels + order must match design doc §1.2 (`DeclarationScope` then `NodeScope`)" + ); + + let decl_id = dag + .declaration_by_name("DeclarationId") + .expect("DeclarationId missing from bootstrap") + .id; + let node_id = dag + .declaration_by_name("NodeId") + .expect("NodeId missing from bootstrap") + .id; + + let ds_conj = disj_variant_conj(&dag, section_ref, "DeclarationScope"); + let ds_labels: Vec = match &dag.declaration(ds_conj).connective { + TypeConnective::Conj { children } => children.iter().map(|f| f.label.clone()).collect(), + other => panic!("DeclarationScope payload must be Conj: {other:?}"), + }; + assert_eq!( + ds_labels, + vec!["declaration".to_string()], + "DeclarationScope payload fields drifted" + ); + assert_eq!( + peel_declaration_alias_head(&dag, conj_field_entry(&dag, ds_conj, "declaration")), + peel_declaration_alias_head(&dag, decl_id), + "`DeclarationScope.declaration` must be substrate `DeclarationId`" + ); + + let ns_conj = disj_variant_conj(&dag, section_ref, "NodeScope"); + let ns_labels: Vec = match &dag.declaration(ns_conj).connective { + TypeConnective::Conj { children } => children.iter().map(|f| f.label.clone()).collect(), + other => panic!("NodeScope payload must be Conj: {other:?}"), + }; + assert_eq!( + ns_labels, + vec!["declaration".to_string(), "node".to_string()], + "NodeScope payload fields drifted" + ); + assert_eq!( + peel_declaration_alias_head(&dag, conj_field_entry(&dag, ns_conj, "declaration")), + peel_declaration_alias_head(&dag, decl_id), + "`NodeScope.declaration` must be substrate `DeclarationId`" + ); + assert_eq!( + peel_declaration_alias_head(&dag, conj_field_entry(&dag, ns_conj, "node")), + peel_declaration_alias_head(&dag, node_id), + "`NodeScope.node` must be substrate `NodeId`" + ); +} diff --git a/src/v3/compiler/tests/integration/sg0_census_test.rs b/src/v3/compiler/tests/integration/sg0_census_test.rs index 3f809ce445f..3a0f58e1c92 100644 --- a/src/v3/compiler/tests/integration/sg0_census_test.rs +++ b/src/v3/compiler/tests/integration/sg0_census_test.rs @@ -495,6 +495,8 @@ const EXPECTED_HAND_AUTHORED_TEST: &[&str] = &[ "src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs", "src/v3/compiler/tests/integration/lane2_stage_2e_parallelism_test.rs", "src/v3/compiler/tests/integration/lane3_stage_3b_db1_test.rs", + // R3 §1.8 gate #89 (`section_ref_substrate_landed`): `SectionRef` disjoint-sum substrate receipt. + "src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs", // R3 gate #73 (`lens_behavioral_parity_demonstration`): temporary host // receipt for the four-lens parity snapshot while LensOutputEquals / // frozen-oracle claims migrate to `.dag` TestClaim data. Dissolution is From 7392be913c0dbcfacefc04c8fbf209810510fbd1 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 14:36:48 -0400 Subject: [PATCH 2/4] WIP: R3 gate #89: section_ref_substrate_landed (T-Lens-Application-Surface) --- INVARIANTS.md | 1 + src/v3/compiler/tests/integration/sg0_census_test.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/INVARIANTS.md b/INVARIANTS.md index 78f7e5ebf08..2454101ff4a 100644 --- a/INVARIANTS.md +++ b/INVARIANTS.md @@ -342,6 +342,7 @@ Per **Dispatch-Discipline Mechanisms (b)** above, each **new** path added to `EX | `src/v3/compiler/tests/integration/ctrl_pr_digests_dag_smoke_test.rs` | **Project plan:** `docs/r4-ctrl-dag-migration-project-plan.md` §3 — catalog **#8** `dsl/ctrl/pr_digests.dag` (Wave-1 ctrl → `.dag` subsystem modeling). **PR receipt (P5 Mechanism (b)):** this INVARIANTS row + the matching `EXPECTED_HAND_AUTHORED_TEST` line in `sg0_census_test.rs` land in the same PR as the smoke test. **Dissolution:** remove when `compile_to_dag` (or a single generated harness) validates `module … service …` ctrl carrier files end-to-end without a parallel Rust string/lexer ratchet, or when the contract migrates to `.dag` `TestClaim` coverage. **Interim ratchet:** `ctrl_pr_digests_dag_tokenizes_and_matches_expected_surface` requires clean tokenization plus presence of `module ctrl.pr_digests`, `import extdeps.github.pulls { PullRequest, PullReview, ReviewComment }`, `std.errors` / `std.types` imports, the four Practice-4 sum/record carriers (with `🟡 STAGED` / `🟢 TERMINAL` markers per `dsl/ctrl/README.md`), `ReviewCommentBody` + `review_line_comments` wiring, and `service ctrl.PrDigests` / the four `operation` blocks / `readonly`. | | `src/v3/compiler/tests/integration/extdeps_sql_transport_test.rs` | **ROADMAP:** `ROADMAP.md` § **Nine lanes** row `T-PB-B` / `pb_rust_tests_outside_residual_zero`; this Rust integration receipt keeps HTTP/SQL/audit extdeps compiled by the existing v3 parser before downstream emission-target consumers rely on them. **Dissolution:** remove when extdeps transport and Phase 3 emission-target files are covered by a `.dag`-native parse/authority suite or generated test harness rather than per-file Rust `compile_to_dag` probes. **Interim ratchet:** `rest_transport_dag_compiles_cleanly` and `sql_transport_dag_compiles_cleanly` pin `dsl/extdeps/transports/rest.dag` and `dsl/extdeps/transports/sql.dag`; `http_server_extdep_dag_compiles_cleanly`, `sql_migration_extdep_dag_compiles_cleanly`, and `audit_event_extdep_dag_compiles_cleanly` pin `dsl/extdeps/http/server.dag`, `dsl/extdeps/sql/migration.dag`, and `dsl/extdeps/audit/event.dag` as parseable staged emission-target substrate. The field-sensitive companions (`http_server_target_fields_are_authoritative_substrate_edges`, `sql_migration_target_fields_bound_raw_sql_scaffold`, `audit_event_target_fields_preserve_cloudevents_core_names`) consume the new target-contract fields directly so they fail on raw `String`/`Int` regressions, missing SQL scaffold bounds, or CloudEvents alias drift while the first real projection consumer is still staged; the audit ratchet also locks CloudEvents core fields to branded carriers and `std.types.Timestamp` rather than raw strings. | | `src/v3/compiler/tests/integration/file_attachment_substrate_carrier_test.rs` | **R3 program plan:** `docs/r3-program-plan.md` §1.8 gate **#62** `substrate_gap_file_ingestion_closed` (T-Workflow-As-Data substrate-gap class; worker brief `docs/briefs/r3-substrate-gate-62-file-attachment-carrier-worker.md`). **Dissolution:** remove when a `.dag` `TestClaim` / PB-B-1 runner receipt can assert `FileAttachment` field names + cross-module nominal wiring against `generated_full_bootstrap_dag()` without this hand-Rust structural ratchet (same dissolution posture as `timing_lens_substrate_carrier_test.rs` for gate #55). **Interim ratchet:** `file_attachment_shape_locked` + `file_attachment_field_types_locked` + `file_attachment_field_count_is_five` pin the ratified Refined-B-1 five-field subset of `WorkflowObservationAnchor` (`NodeId`, `ContentHash`, `WorkflowProducerId`, `WorkflowRunId`, `Nanoseconds`) exactly as declared in `src/v3/std/timing_lens.dag`; existence proof carrier construction stays in-module as `gate_62_file_attachment_demo_record`. | +| `src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs` | **R3 program plan:** `docs/r3-program-plan.md` §1.8 gate **#89** `section_ref_substrate_landed` (T-Lens-Application-Surface — `SectionRef` disjoint sum over `DeclarationScope` and `NodeScope` in `src/v3/std/lens_application.dag`; design authority `docs/design-lens-application-surface.md` §1.2–§2). **PR receipt (P5 Mechanism (b)):** this INVARIANTS row + matching `EXPECTED_HAND_AUTHORED_TEST` line in `sg0_census_test.rs` land in the same PR as the harness. **Dissolution:** remove when a `.dag` `TestClaim` / PB-B-1 runner receipt can assert `SectionRef` variant labels, field names, and `DeclarationId` / `NodeId` nominal wiring against `generated_full_bootstrap_dag()` without this hand-Rust structural ratchet (same dissolution posture as gate **#62** `file_attachment_substrate_carrier_test.rs`). **Interim ratchet:** `gate_89_section_ref_is_disjoint_sum_from_lens_application_authority` pins variant order (`DeclarationScope` then `NodeScope`) and payload fields to `lens_application.dag`. | | `src/v3/compiler/tests/integration/workflow_substrate_carriers_test.rs` | **R3 program plan:** `docs/r3-program-plan.md` §1.8 gate **#53** `workflow_substrate_carriers_landed` (T-Workflow-As-Data Slice 1; worker brief `docs/briefs/r3-substrate-t-workflow-as-data-slice-1-worker.md`). **Dissolution:** remove when a `.dag` `TestClaim` / PB-B-1 runner receipt can assert `WorkflowSecret`, `SecretScope`, `CronSchedule`, and `CronField` structural shape against `generated_full_bootstrap_dag()` without this hand-Rust ratchet. **Interim ratchet:** `workflow_secret_shape_locked` + `secret_scope_variants_locked` + `cron_schedule_shape_locked` + `cron_field_variants_locked` pin the Slice 1 β-ratified carriers (STOP+PING discipline on `CronSchedule` field-count drift >5 per brief). | | `src/v3/compiler/tests/integration/m2_substrate_inhabitance_test.rs` | **ROADMAP:** `ROADMAP.md` — **Tier-3 perf-budget Phase-1 hand-Rust mirror benches** / T-Tier3-Dissolution paired-dispatch (`docs/briefs/r3-pb-t-tier3-consumer-slice-worker.md`). **Plan:** `docs/r3-program-plan.md` §1.8 gate **#2** `tier3_computation_mirror_dissolved` (state-check; **CONSUMER_LANDED** = §1.7 executable-consumer sense, not INVARIANTS §P2 generated-consumer — see plan §1.7 “State-check …” paragraph). **Dissolution:** retire remaining Tier3 host mirrors per `docs/r3-structure.md` §Acceptance as Evaluator-backed std bodies land. **Interim ratchet (P5 Mechanism (b)):** `tier3_computation_mirror_trivial_constructors_dissolved` (PR #2789 narrow slice) + `tier3_computation_mirror_kernel_algebra_profile_substrate_authority` with brace-bounded `dag.rs` scan asserting `type_iteration_dimension` delegates through `BOOTSTRAPPED_DAG.kernel_algebra_profile` (forbid parallel hand-maintained type→profile tables); sibling Tier3 rows in this file carry the same lane receipts. | | `src/v3/compiler/tests/integration/no_coercion_cost_dimension_ratchet_test.rs` | **ROADMAP:** `ROADMAP.md` → `### Nine lanes` → **T-PB-B** / `pb_rust_tests_outside_residual_zero` (SG-0 `EXPECTED_HAND_AUTHORED_TEST` hand-authored integration census; same “Hand-Rust census” partition narrative as `ROADMAP.md` §Nine lanes / T-PB-B row in the lanes table). **R3 program plan:** `docs/r3-program-plan.md` §1.8 gate **#39** `no_coercion_cost_dimension` (T-CostLens-Composition — host walk over `src/v3/{std,lenses,spec}/**/*.dag` forbidding standalone `CoercionCost` outside `//` comments). **PR receipt (P5 Mechanism (b)):** this INVARIANTS row + matching `EXPECTED_HAND_AUTHORED_TEST` literal land in the same PR as the ratchet. **Dissolution:** remove when the same structural claim is carried by `.dag` `TestClaim` / generated harness without this host file walk. **Interim ratchet:** `no_coercion_cost_dimension_substrate_dag_has_no_coercion_cost_carrier_token` + `standalone_needle_tests` pin identifier-boundary matching. | diff --git a/src/v3/compiler/tests/integration/sg0_census_test.rs b/src/v3/compiler/tests/integration/sg0_census_test.rs index 3a0f58e1c92..94e242795d3 100644 --- a/src/v3/compiler/tests/integration/sg0_census_test.rs +++ b/src/v3/compiler/tests/integration/sg0_census_test.rs @@ -538,9 +538,6 @@ const EXPECTED_HAND_AUTHORED_TEST: &[&str] = &[ // #issuecomment-4404395097 ratifies this bridge for the Slice 1a.1 / gate // #70 window. "src/v3/compiler/tests/integration/lens_cost_target_realization_test.rs", - // R3 §1.8 gate #39 (`no_coercion_cost_dimension`, T-CostLens-Composition): - // `.dag` substrate ratchet — no parallel `CoercionCost` token outside comments. - "src/v3/compiler/tests/integration/no_coercion_cost_dimension_ratchet_test.rs", "src/v3/compiler/tests/integration/lens_register_correspondence_test.rs", // T-Substrate-Lens-Primitive (R2 Substrate, first slice): Director- // approved hand-Rust acceptance for `Lens` substrate carrier and @@ -603,6 +600,9 @@ const EXPECTED_HAND_AUTHORED_TEST: &[&str] = &[ "src/v3/compiler/tests/integration/method_template_contract_test.rs", // Gunbc #1982 / §1.8 gate #97 — emit-shim retirement coherence (v2 tree vs Gap-4 producer). "src/v3/compiler/tests/integration/method_template_projection_emit_shim_coherence_test.rs", + // R3 §1.8 gate #39 (`no_coercion_cost_dimension`, T-CostLens-Composition): + // `.dag` substrate ratchet — no parallel `CoercionCost` token outside comments. + "src/v3/compiler/tests/integration/no_coercion_cost_dimension_ratchet_test.rs", "src/v3/compiler/tests/integration/pb1_bootstrap_full_snapshot_test.rs", // R3 row 85 / PB #1560 Gap 4: focused acceptance for the // `pb_method_template_projection` consumer hook. Stays hand-Rust From 0cd18b1b1833359bcb8c74d8b036e4f7f46e1a1f Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 18:39:38 +0000 Subject: [PATCH 3/4] fix(ci): add SG-0 PR-body append for PR #3128 Prepends SG-0 hand-path delta (+1) and pairing class (c) so check-pr-sg0-net-shrink-discipline.sh passes on edits to sg0_census_test.rs. Deferral cites existing T-LAS execution-split worker brief. Co-authored-by: Cursor --- scripts/ci-merge/sg0-pr-body-append.3128.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 scripts/ci-merge/sg0-pr-body-append.3128.txt diff --git a/scripts/ci-merge/sg0-pr-body-append.3128.txt b/scripts/ci-merge/sg0-pr-body-append.3128.txt new file mode 100644 index 00000000000..70e2849962a --- /dev/null +++ b/scripts/ci-merge/sg0-pr-body-append.3128.txt @@ -0,0 +1,3 @@ +SG-0 hand-path delta: +1 + +SG-0 pairing: (c) deferral dispatch under docs/briefs/r3-v-t-lens-application-surface-execution-split-worker.md Slice A substrate receipts (§1.8 gate #89 section_ref_substrate_landed); net SG-0 integration harness add dissolves when the same bootstrap structural asserts are carried by `.dag` `TestClaim`/runner receipts per T-Tests-As-Data posture (parity with adjacent timing/file-attachment substrate carrier tests). From d876296dc84c72de794480f377c4303f9afa67e3 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 19:34:45 +0000 Subject: [PATCH 4/4] test(v3-compiler): pick SectionRef by Disj substrate, not dag path suffix Gate #89 receipt: codex flagged span.file.ends_with(...) as an extra path-based identity bridge. Import stubs share the SectionRef name; the authoritative entry lowers as the disjoint sum itself. Select that declaration structurally. Co-authored-by: Cursor --- ...lens_application_substrate_carrier_test.rs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs b/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs index 476b8afa3ea..7a6514e15dd 100644 --- a/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs +++ b/src/v3/compiler/tests/integration/lens_application_substrate_carrier_test.rs @@ -31,18 +31,26 @@ fn peel_declaration_alias_head(dag: &Dag, mut id: DeclarationId) -> DeclarationI } fn section_ref_decl(dag: &Dag) -> DeclarationId { - dag.declarations() + // Name matches import stubs elsewhere (e.g. `lenses.cost`); the substrate + // authority for this receipt is the declaration that lowers as the + // disjoint sum itself—not `ResolvedByName` forwarding atoms. + let mut substrates: Vec = dag + .declarations() .iter() - .find(|d| { - d.name.as_deref() == Some("SectionRef") && d.span.file.ends_with("lens_application.dag") - }) - .unwrap_or_else(|| { - panic!( - "bootstrap must declare `SectionRef` in src/v3/std/lens_application.dag \ - (gate #89 section_ref_substrate_landed)" - ) - }) - .id + .filter(|d| d.name.as_deref() == Some("SectionRef")) + .filter(|d| matches!(&d.connective, TypeConnective::Disj { .. })) + .map(|d| d.id) + .collect(); + substrates.sort_by_key(|id| id.raw()); + match substrates.as_slice() { + [only] => *only, + [] => panic!( + "bootstrap must define `SectionRef` as a disjoint sum (gate #89 section_ref_substrate_landed)" + ), + ambiguous => panic!( + "multiple `SectionRef` disjoint-sum authorities in bootstrap ({ambiguous:?}); expected exactly one substrate definition" + ), + } } fn disj_variant_conj(dag: &Dag, disj: DeclarationId, label: &str) -> DeclarationId {