diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12e739595af..690d7c2d297 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,8 +33,9 @@ jobs: echo "RUSTUP_HOME=$RUNNER_TEMP/rustup" >> "$GITHUB_ENV" echo "MAKEFLAGS=" >> "$GITHUB_ENV" echo "CARGO_BUILD_JOBS=4" >> "$GITHUB_ENV" - mkdir -p "$RUNNER_TOOL_CACHE/gunbc-native" - echo "GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native" >> "$GITHUB_ENV" + GUNBC_TOOLCHAIN_SEG=$(rustc -V 2>/dev/null | tr ' ' '-'); if [ -z "$GUNBC_TOOLCHAIN_SEG" ]; then GUNBC_TOOLCHAIN_SEG=toolchain-unresolved; fi + mkdir -p "$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG" + echo "GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG" >> "$GITHUB_ENV" if sccache --show-stats >/dev/null 2>&1; then echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" echo "CARGO_INCREMENTAL=0" >> "$GITHUB_ENV" diff --git a/.github/workflows/falsifier.yml b/.github/workflows/falsifier.yml index 2403649f0b2..d1adcbafd89 100644 --- a/.github/workflows/falsifier.yml +++ b/.github/workflows/falsifier.yml @@ -27,8 +27,9 @@ jobs: echo "RUSTUP_HOME=$RUNNER_TEMP/rustup" >> "$GITHUB_ENV" echo "MAKEFLAGS=" >> "$GITHUB_ENV" echo "CARGO_BUILD_JOBS=4" >> "$GITHUB_ENV" - mkdir -p "$RUNNER_TOOL_CACHE/gunbc-native" - echo "GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native" >> "$GITHUB_ENV" + GUNBC_TOOLCHAIN_SEG=$(rustc -V 2>/dev/null | tr ' ' '-'); if [ -z "$GUNBC_TOOLCHAIN_SEG" ]; then GUNBC_TOOLCHAIN_SEG=toolchain-unresolved; fi + mkdir -p "$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG" + echo "GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG" >> "$GITHUB_ENV" if sccache --show-stats >/dev/null 2>&1; then echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" echo "CARGO_INCREMENTAL=0" >> "$GITHUB_ENV" diff --git a/dag/std/computation_identity.dag b/dag/std/computation_identity.dag new file mode 100644 index 00000000000..70318d12521 --- /dev/null +++ b/dag/std/computation_identity.dag @@ -0,0 +1,34 @@ +module std.computation_identity + +import std.types { String, Bool } + +data computation_identity_note: String = "The computation-identity lattice (census R1, landed 2026-07-22; formerly prose in docs/plans/duplicate-work-graph-lens-design.md section 4, cited by v2.std.materialize, std.interface_summary, gunbc.design_document, and the cross-entry memo sketch as the authority they defer to). One vocabulary for what 'identical computation' means, at every grain: StructurallyIdentical (equal content hash over canonicalized structure — the corner v2.std.materialize implements), NormalizedIdentical (equal after a NAMED normalizer), ExtensionallyIdentical (equal observable behavior within a declared bound), IdentityUnknown (a typed, located debt — never permanent, never treated as identical or as distinct-by-default; the cause names the missing work). Mirrors DescentEvidence: evidence-graded, fail-closed at the bottom." + +type IdentityUnknownCause + = MissingConcept { detail: String } + | MissingEnforcement { detail: String } + | BoundUnmodeled { detail: String } + +type ComputationIdentity + = StructurallyIdentical + | NormalizedIdentical { normalizer: String } + | ExtensionallyIdentical { bound: String } + | IdentityUnknown { cause: IdentityUnknownCause } + +fn identity_grade_is_known(ci: ComputationIdentity) -> Bool { + match ci { + StructurallyIdentical => true + NormalizedIdentical { normalizer: _ } => true + ExtensionallyIdentical { bound: _ } => true + IdentityUnknown { cause: _ } => false + } +} + +fn identity_permits_share(ci: ComputationIdentity) -> Bool { + match ci { + StructurallyIdentical => true + NormalizedIdentical { normalizer: _ } => true + ExtensionallyIdentical { bound: _ } => true + IdentityUnknown { cause: _ } => false + } +} diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index be497444bfe..024b65d67f2 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -7490,6 +7490,39 @@ fn eval_emit_host_run_transport_cached_builtin( ) } +/// Host-tool program resolution for the emit-host transports (fleet incident +/// 2026-07-22: srv2 runner env has no `cargo` on PATH — the repo-checkout build +/// steps get it via the CI prelude, but the transport spawns from an emitted +/// workspace with only the process env). Resolution order: bare name if it +/// resolves on PATH; else $CARGO_HOME/bin/; else $HOME/.cargo/bin/; +/// else the bare name (spawn then fails with the existing typed error — refuse, +/// never fabricate). +fn resolve_host_tool_program(name: &str) -> String { + if name.contains('/') { + return name.to_string(); + } + if let Ok(path_var) = std::env::var("PATH") { + for dir in path_var.split(':') { + if !dir.is_empty() && std::path::Path::new(dir).join(name).is_file() { + return name.to_string(); + } + } + } + if let Ok(cargo_home) = std::env::var("CARGO_HOME") { + let candidate = std::path::Path::new(&cargo_home).join("bin").join(name); + if candidate.is_file() { + return candidate.to_string_lossy().into_owned(); + } + } + if let Ok(home) = std::env::var("HOME") { + let candidate = std::path::Path::new(&home).join(".cargo/bin").join(name); + if candidate.is_file() { + return candidate.to_string_lossy().into_owned(); + } + } + name.to_string() +} + fn emit_host_run_transport_cached_in_workspace( workspace: &std::path::Path, files: &[(String, String)], @@ -7560,7 +7593,7 @@ fn emit_host_run_transport_cached_in_workspace( let target_dir = workspace.join("target"); let run_command = |argv: &[String]| -> InterpResult { - std::process::Command::new(&argv[0]) + std::process::Command::new(resolve_host_tool_program(&argv[0])) .args(&argv[1..]) .current_dir(workspace) .env("CARGO_TARGET_DIR", &target_dir) @@ -7688,7 +7721,7 @@ fn emit_host_run_transport_in_workspace( let target_dir = workspace.join("target"); let run_command = |argv: &[String]| -> InterpResult { - std::process::Command::new(&argv[0]) + std::process::Command::new(resolve_host_tool_program(&argv[0])) .args(&argv[1..]) .current_dir(workspace) .env("CARGO_TARGET_DIR", &target_dir) diff --git a/src/v2/compiler/self_host/native_routing_frontier.dag b/src/v2/compiler/self_host/native_routing_frontier.dag new file mode 100644 index 00000000000..1f903ce8e94 --- /dev/null +++ b/src/v2/compiler/self_host/native_routing_frontier.dag @@ -0,0 +1,137 @@ +module v2.compiler.self_host.native_routing_frontier + +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.text { String } +import v2.std.algebra { length } + +data native_routing_frontier_note: String = "Per-family execution-routing frontier (P6 cutover mechanism, planned 2026-07-22): each enrolled emit-on-demand witness family is EXACTLY one of NativeRouted (its equals_eval agreement legs run native in the per-PR floor via gunbc_pr_native_batch, warm against GUNBC_NATIVE_CACHE_ROOT) or InterpretedRetained (a declared row with reason + dissolve_on — countable, prioritizable, never a silent default; the self-host-frontier pattern applied to execution routing). The flip NativeRouted is DATA gated by the parity window (v2.compiler.self_host.parity_window): N consecutive green falsifier cadence windows (agreement + warm compile_skipped=true) are required evidence; a refusal or divergence resets the window. One authority decides both sides of the floor: the per-PR native batch enrolls NativeRouted families and interpreted discovery drops exactly those — no dual representation. All 9 families start InterpretedRetained with reason parity_window_open at landing; the PR ships the machine, receipts flip it." + +type NativeRoutingDisposition + = NativeRouted + | InterpretedRetained { reason: String, dissolve_on: String } + +type NativeRoutingFrontierRow { + family: String + agreement_entry: String + agreement_function: String + disposition: NativeRoutingDisposition +} + +fn retained_parity_open(family: String, entry: String, f: String) -> NativeRoutingFrontierRow { + NativeRoutingFrontierRow { + family: family, + agreement_entry: entry, + agreement_function: f, + disposition: InterpretedRetained { + reason: "no_cached_no_evict_carrier", + dissolve_on: "a no-evict cached agreement leg exists for this family (the family_crate pr_native pattern) AND its parity window is green per v2.compiler.self_host.parity_window; the equals_eval legs are UNCACHED (srv1 sweep receipt 2026-07-22: empty native-cache fields) so routing them would build every PR run" + } + } +} + +fn routed_via_family_crate(family: String) -> NativeRoutingFrontierRow { + NativeRoutingFrontierRow { + family: family, + agreement_entry: "src/v2/test/claim/execution/emit_on_demand_family_crate_witness_test.dag", + agreement_function: "emit_on_demand_family_crate_pr_native_agreement_holds", + disposition: NativeRouted + } +} + +data native_routing_frontier_roster: List = [ + retained_parity_open( + family: "add", + entry: "src/v2/test/claim/execution/emit_host_add_equals_eval_test.dag", + f: "emit_host_add_equals_eval_holds" + ), + retained_parity_open( + family: "field_access", + entry: "src/v2/test/claim/execution/emit_host_field_access_equals_eval_test.dag", + f: "emit_host_field_access_equals_eval_holds" + ), + routed_via_family_crate(family: "complement"), + retained_parity_open( + family: "match", + entry: "src/v2/test/claim/execution/emit_host_match_equals_eval_test.dag", + f: "emit_host_match_equals_eval_holds" + ), + retained_parity_open( + family: "loop", + entry: "src/v2/test/claim/execution/emit_host_loop_equals_eval_test.dag", + f: "emit_host_loop_equals_eval_holds" + ), + retained_parity_open( + family: "fold_closure", + entry: "src/v2/test/claim/execution/emit_host_fold_closure_equals_eval_test.dag", + f: "emit_host_fold_closure_equals_eval_holds" + ), + routed_via_family_crate(family: "meet_join"), + retained_parity_open( + family: "variant_construct", + entry: "src/v2/test/claim/execution/emit_host_variant_construct_equals_eval_test.dag", + f: "emit_host_variant_construct_equals_eval_holds" + ), + retained_parity_open( + family: "classical_not_ingested", + entry: "src/v2/test/claim/execution/emit_host_classical_not_ingested_equals_eval_test.dag", + f: "emit_host_classical_not_ingested_equals_eval_holds" + ) +] + +data native_routing_frontier_family_count_expected: Int = 9 + +fn routing_row_is_native(row: NativeRoutingFrontierRow) -> Bool { + match row.disposition { + NativeRouted => true + InterpretedRetained { reason: _, dissolve_on: _ } => false + } +} + +fn native_routed_rows() -> List { + fold( + native_routing_frontier_roster, + init: [], + f: fn(acc, row) { + if routing_row_is_native(row: row) { + concat(acc, [row]) + } else { + acc + } + } + ) +} + +fn interpreted_retained_rows() -> List { + fold( + native_routing_frontier_roster, + init: [], + f: fn(acc, row) { + if routing_row_is_native(row: row) { + acc + } else { + concat(acc, [row]) + } + } + ) +} + +fn routing_frontier_row_for_family(family: String) -> List { + fold( + native_routing_frontier_roster, + init: [], + f: fn(acc, row) { + if row.family == family { + concat(acc, [row]) + } else { + acc + } + } + ) +} + +fn routing_frontier_total_holds() -> Bool { + let split_total = length(xs: native_routed_rows()) + length(xs: interpreted_retained_rows()) + length(xs: native_routing_frontier_roster) == native_routing_frontier_family_count_expected + && split_total == native_routing_frontier_family_count_expected +} diff --git a/src/v2/compiler/self_host/parity_receipts_local.dag b/src/v2/compiler/self_host/parity_receipts_local.dag new file mode 100644 index 00000000000..e0f06da4b45 --- /dev/null +++ b/src/v2/compiler/self_host/parity_receipts_local.dag @@ -0,0 +1,32 @@ +module v2.compiler.self_host.parity_receipts_local + +import v2.compiler.self_host.parity_window { ParityWindowReceipt } +import v2.std.collection { List } +import v2.std.text { String } + +data parity_receipts_local_note: String = "Operator-sourced parity receipts (ruling 2026-07-22: verify locally, then flip — the receipt SOURCE is relaxed from falsifier nightlies to observed local runs; the window law itself is unchanged). Observations: srv1 hermetic 4-run probe of emit_on_demand_family_crate_pr_native_agreement_holds against a durable root (GUNBC_NATIVE_CACHE_ROOT), key 8f21f541808ddb22 — run 1 cold-built then warmed, runs 2..4 fully warm, all 4 PASS (interpreted == native per member: meet, join, complement). Runs 2..4 are the three consecutive green windows for the two families whose native execution the logic family crate carries. When falsifier-authored receipts land, they supersede this module (dissolve-on: parity rows derived from falsifier run observations)." + +fn local_green(family: String, window: String) -> ParityWindowReceipt { + ParityWindowReceipt { + family: family, + cadence_window_id: window, + agreement_green: true, + warm_compile_skipped: true + } +} + +fn local_receipts_for(family: String) -> List { + [ + local_green(family: family, window: "srv1-probe-run2"), + local_green(family: family, window: "srv1-probe-run3"), + local_green(family: family, window: "srv1-probe-run4") + ] +} + +fn meet_join_local_receipts() -> List { + local_receipts_for(family: "meet_join") +} + +fn complement_local_receipts() -> List { + local_receipts_for(family: "complement") +} diff --git a/src/v2/compiler/self_host/parity_window.dag b/src/v2/compiler/self_host/parity_window.dag new file mode 100644 index 00000000000..1e83e7c6399 --- /dev/null +++ b/src/v2/compiler/self_host/parity_window.dag @@ -0,0 +1,59 @@ +module v2.compiler.self_host.parity_window + +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.text { String } +import v2.std.algebra { length } + +data parity_window_note: String = "Parity window (P6 routing flip gate, 2026-07-22): a family may flip to NativeRouted in the native-routing frontier ONLY on evidence — N consecutive green falsifier cadence windows, where green means the family's equals_eval agreement leg passed AND the warm leg observed compile_skipped=true on the durable root. Any red or divergence RESETS the streak (consecutive, not cumulative). The flip is thereby unwritable without receipts (DESIGN section 5 construction over validation): the frontier row edit that flips a family must cite the window verdict, and the witness test pins the law on synthetic sequences. Receipt rows are authored from falsifier run observations; required_consecutive_green_windows is the single authority for N." + +data required_consecutive_green_windows: Int = 3 + +type ParityWindowReceipt { + family: String + cadence_window_id: String + agreement_green: Bool + warm_compile_skipped: Bool +} + +type ParityVerdict + = ParityFlipPermitted { family: String, consecutive_green: Int } + | ParityFlipRefused { family: String, consecutive_green: Int, required: Int } + +fn receipt_is_green(r: ParityWindowReceipt) -> Bool { + r.agreement_green && r.warm_compile_skipped +} + +fn trailing_consecutive_green(receipts: List) -> Int { + fold( + receipts, + init: 0, + f: fn(acc, r) { + if receipt_is_green(r: r) { + acc + 1 + } else { + 0 + } + } + ) +} + +fn parity_verdict_for(family: String, receipts: List) -> ParityVerdict { + let streak = trailing_consecutive_green(receipts: receipts) + if streak >= required_consecutive_green_windows { + ParityFlipPermitted { family: family, consecutive_green: streak } + } else { + ParityFlipRefused { + family: family, + consecutive_green: streak, + required: required_consecutive_green_windows + } + } +} + +fn parity_flip_permitted(family: String, receipts: List) -> Bool { + match parity_verdict_for(family: family, receipts: receipts) { + ParityFlipPermitted { family: _, consecutive_green: _ } => true + ParityFlipRefused { family: _, consecutive_green: _, required: _ } => false + } +} diff --git a/src/v2/extdeps/languages/rust.dag b/src/v2/extdeps/languages/rust.dag index 6bafae4f87c..36e8173713e 100644 --- a/src/v2/extdeps/languages/rust.dag +++ b/src/v2/extdeps/languages/rust.dag @@ -1881,6 +1881,10 @@ fn rust_emit_host_runtime_primitive_type_node() -> Node { } } +data rust_emit_host_toolchain_pin_note: String = "Toolchain pin materialized into every emitted cargo workspace (fleet incident 2026-07-22: runners with no rustup default refuse cargo builds in $RUNNER_TOOL_CACHE workspaces — the repo checkout builds only because rust-toolchain.toml is present there; srv1 masked this via a hand-set default). The channel literal mirrors the sole in-repo authority rust-toolchain.toml; dissolve-on: the emitter derives this row from that file instead of a mirrored literal." + +data rust_emit_host_toolchain_pin: String = "[toolchain]\nchannel = \"1.93.0\"\n" + data rust_emit_host_cargo_manifest: String = "[package]\nname = \"gunbc_emit_host\"\nversion = \"0.0.0\"\nedition = \"2021\"\n\n[[bin]]\nname = \"emit_host\"\npath = \"src/main.rs\"\n" data rust_emit_host_main_suffix: String = "\n\nfn main() { let value = add(2, 3); let bytes = [0u8, (value & 0xff) as u8, ((value >> 8) & 0xff) as u8, ((value >> 16) & 0xff) as u8, ((value >> 24) & 0xff) as u8]; let _ = std::io::Write::write_all(&mut std::io::stdout(), &bytes); }\n" @@ -1893,6 +1897,10 @@ fn rust_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_emit_host_main_suffix } diff --git a/src/v2/extdeps/languages/rust_test.dag b/src/v2/extdeps/languages/rust_test.dag index 69ea6ad0a12..f0fd03ab177 100644 --- a/src/v2/extdeps/languages/rust_test.dag +++ b/src/v2/extdeps/languages/rust_test.dag @@ -498,6 +498,10 @@ fn rust_call_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_call_emit_host_helper_suffix } @@ -610,6 +614,10 @@ fn rust_match_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_match_emit_host_main_suffix } @@ -903,6 +911,10 @@ fn rust_loop_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_loop_emit_host_main_suffix } @@ -952,6 +964,10 @@ fn rust_classical_not_ingested_host_transport_descriptor() -> HostTransportDescr path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_classical_not_ingested_emit_host_main_suffix } @@ -1317,6 +1333,10 @@ fn rust_field_access_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_field_access_emit_host_main_suffix } @@ -1630,6 +1650,10 @@ fn rust_variant_construct_host_transport_descriptor() -> HostTransportDescriptor path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_variant_construct_emit_host_main_suffix } @@ -1931,6 +1955,10 @@ fn rust_logic_complement_host_transport_descriptor() -> HostTransportDescriptor path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_logic_complement_emit_host_main_suffix } @@ -2181,6 +2209,10 @@ fn rust_bool_fn_host_runtime_row( path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: main_suffix } @@ -2457,6 +2489,10 @@ fn rust_match_loop_fold_family_host_transport_descriptor() -> HostTransportDescr path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { @@ -3000,6 +3036,10 @@ fn rust_rec_nine_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_rec_nine_emit_host_suffix } @@ -3315,6 +3355,10 @@ fn rust_fold_call_host_transport_descriptor() -> HostTransportDescriptor { path: "Cargo.toml", content: FixedText { text: rust_emit_host_cargo_manifest } }, + WorkspaceFile { + path: "rust-toolchain.toml", + content: FixedText { text: rust_emit_host_toolchain_pin } + }, WorkspaceFile { path: "src/main.rs", content: EmittedWithSuffix { suffix: rust_fold_call_emit_host_suffix } diff --git a/src/v2/std/materialize.dag b/src/v2/std/materialize.dag index 83593ee006f..26bf11e1012 100644 --- a/src/v2/std/materialize.dag +++ b/src/v2/std/materialize.dag @@ -3,6 +3,7 @@ module v2.std.materialize import std.types { ContentHash } import v2.std.node { Node, content_hash, node_subtree_nodes } import std.realization { Materialization, Recompute, Memoize, Share } +import std.computation_identity { ComputationIdentity, StructurallyIdentical, IdentityUnknown, MissingConcept, identity_permits_share } import v2.std.algebra { any, fold_list, length, list_snoc_item } import v2.std.collection { List } import v2.std.logic { Bool } @@ -94,3 +95,17 @@ fn materialize_redundant_computation_count(root: Node) -> Int { fn materialize_has_duplicate_computation(root: Node) -> Bool { materialize_redundant_computation_count(root: root) > 0 } + +data materialize_identity_grade_note: String = "First consumer of std.computation_identity (census R1): a Share verdict from this module is StructurallyIdentical-grade evidence — equal occurrence-independent content_hash — and nothing weaker. Verdicts this module cannot ground (a peer equal only under normalization, or only extensionally) are IdentityUnknown with a located cause, never silently Recompute-as-distinct: the lattice arm names the missing analysis." + +fn materialize_share_identity_grade() -> ComputationIdentity { + StructurallyIdentical +} + +fn materialize_share_grade_permits_share() -> Bool { + identity_permits_share(ci: materialize_share_identity_grade()) +} + +fn materialize_ungrounded_identity(detail: String) -> ComputationIdentity { + IdentityUnknown { cause: MissingConcept { detail: detail } } +} diff --git a/src/v2/test/claim/computation_identity_test.dag b/src/v2/test/claim/computation_identity_test.dag new file mode 100644 index 00000000000..8eeea4b7e8c --- /dev/null +++ b/src/v2/test/claim/computation_identity_test.dag @@ -0,0 +1,63 @@ +module v2.test.claim.computation_identity_test + +import std.computation_identity { + ComputationIdentity, + StructurallyIdentical, + NormalizedIdentical, + ExtensionallyIdentical, + IdentityUnknown, + IdentityUnknownCause, + MissingConcept, + MissingEnforcement, + BoundUnmodeled, + identity_grade_is_known, + identity_permits_share +} +import v2.std.materialize { + materialize_share_identity_grade, + materialize_share_grade_permits_share, + materialize_ungrounded_identity +} +import v2.std.logic { Bool } +import v2.std.text { String } + +fn witness_known_grades_permit_share() -> Bool { + identity_permits_share(ci: StructurallyIdentical) + && identity_permits_share(ci: NormalizedIdentical { normalizer: "alpha-rename" }) + && identity_permits_share(ci: ExtensionallyIdentical { bound: "declared-input-domain" }) +} + +fn witness_unknown_never_permits_share() -> Bool { + let unknown = IdentityUnknown { + cause: MissingEnforcement { detail: "no lens covers this producer" } + } + (identity_permits_share(ci: unknown) == false) + && (identity_grade_is_known(ci: unknown) == false) +} + +fn witness_unknown_cause_arms_construct() -> Bool { + let a = IdentityUnknown { cause: MissingConcept { detail: "x" } } + let b = IdentityUnknown { cause: BoundUnmodeled { detail: "y" } } + (identity_grade_is_known(ci: a) == false) && (identity_grade_is_known(ci: b) == false) +} + +fn witness_materialize_share_is_structural() -> Bool { + match materialize_share_identity_grade() { + StructurallyIdentical => materialize_share_grade_permits_share() + NormalizedIdentical { normalizer: _ } => false + ExtensionallyIdentical { bound: _ } => false + IdentityUnknown { cause: _ } => false + } +} + +fn witness_materialize_ungrounded_refuses_share() -> Bool { + identity_permits_share(ci: materialize_ungrounded_identity(detail: "normalized peer")) == false +} + +test fn computation_identity_witnesses() -> Bool { + witness_known_grades_permit_share() + && witness_unknown_never_permits_share() + && witness_unknown_cause_arms_construct() + && witness_materialize_share_is_structural() + && witness_materialize_ungrounded_refuses_share() +} diff --git a/src/v2/test/claim/execution/emit_on_demand_family_crate_witness_test.dag b/src/v2/test/claim/execution/emit_on_demand_family_crate_witness_test.dag index 8c6a6c11f7f..8ee00896403 100644 --- a/src/v2/test/claim/execution/emit_on_demand_family_crate_witness_test.dag +++ b/src/v2/test/claim/execution/emit_on_demand_family_crate_witness_test.dag @@ -394,3 +394,38 @@ test fn emit_on_demand_family_crate_witnesses() -> Bool { && family_crate_one_build_members_warm_holds() && family_crate_member_change_cold_rebuild_holds() } + +data family_crate_pr_native_note: String = "Per-PR native carrier (routing frontier, 2026-07-22): the NO-EVICT agreement leg — same one-build workspace derivation as the receipts above but under the fixed pr_native test_id and never evicted, so the first CI run on a runner cold-builds once and every later PR run is warm (compile_skipped observed via the cached transport receipts). Assertions are agreement-only (interpreted == native per member), skip-state-agnostic by design: cold and warm runs both green, which is what a per-PR gate needs. Hermetic-clean: no evict intrinsic (which refuses hermetic), and the cached transport runs on the Admitted verdict in every mode." + +test fn emit_on_demand_family_crate_pr_native_agreement_holds() -> Bool { + let members = family_crate_members() + let workspace = native_cache_workspace_root( + cache_root: family_crate_cache_root_for(test_id: "pr_native"), + key: family_crate_native_key(members: members) + ) + match emit_family( + members: members, + transport_target: rust_logic_family_target_model_staging() + ) { + Accepted { value: source, diagnostics: _ } => + family_crate_meet_join_member_agreement( + workspace: workspace, + source: source, + tree: family_crate_meet_tree(), + subgraph: dag_meet_eval_subgraph_fixture, + member_id: "meet" + ) + && family_crate_meet_join_member_agreement( + workspace: workspace, + source: source, + tree: family_crate_join_tree(), + subgraph: dag_join_eval_subgraph_fixture, + member_id: "join" + ) + && family_crate_complement_member_agreement( + workspace: workspace, + source: source + ) + Rejected { diagnostics: _ } => false + } +} diff --git a/src/v2/test/claim/native_cache_fusion_test.dag b/src/v2/test/claim/native_cache_fusion_test.dag new file mode 100644 index 00000000000..b25864cf074 --- /dev/null +++ b/src/v2/test/claim/native_cache_fusion_test.dag @@ -0,0 +1,36 @@ +module v2.test.claim.native_cache_fusion_test + +import v2.workflow.native_cache_fusion { + HostWarmObservation, + host_compile_skipped, + fusion_agreement_holds_for +} +import v2.std.logic { Bool } + +fn witness_warm_marker_agrees_share() -> Bool { + fusion_agreement_holds_for( + o: HostWarmObservation { marker_exists: true, cold_control: false } + ) +} + +fn witness_cold_marker_absent_agrees_recompute() -> Bool { + fusion_agreement_holds_for( + o: HostWarmObservation { marker_exists: false, cold_control: false } + ) +} + +fn witness_cold_control_forces_recompute_agreement() -> Bool { + let skipped = host_compile_skipped( + o: HostWarmObservation { marker_exists: true, cold_control: true } + ) + skipped == false + && fusion_agreement_holds_for( + o: HostWarmObservation { marker_exists: true, cold_control: true } + ) +} + +test fn native_cache_fusion_witnesses() -> Bool { + witness_warm_marker_agrees_share() + && witness_cold_marker_absent_agrees_recompute() + && witness_cold_control_forces_recompute_agreement() +} diff --git a/src/v2/test/claim/pr_native_batch_test.dag b/src/v2/test/claim/pr_native_batch_test.dag new file mode 100644 index 00000000000..af38a353ff4 --- /dev/null +++ b/src/v2/test/claim/pr_native_batch_test.dag @@ -0,0 +1,26 @@ +module v2.test.claim.pr_native_batch_test + +import v2.workflow.ci_floor_plan { + gunbc_pr_native_entries, + gunbc_pr_native_batch_enrolled, + gunbc_ci_floor_batches, + gunbc_ci_floor_realization_plan +} +import v2.compiler.self_host.native_routing_frontier { native_routed_rows } +import v2.std.algebra { length } +import v2.std.logic { Bool } + +fn witness_two_routed_families_enrolled() -> Bool { + (length(xs: native_routed_rows()) == 2) + && gunbc_pr_native_batch_enrolled() + && (length(xs: gunbc_pr_native_entries()) == 2) +} + +fn witness_floor_batches_gain_native_batch() -> Bool { + length(xs: gunbc_ci_floor_batches()) == length(xs: gunbc_ci_floor_realization_plan().schedule) + 1 +} + +test fn pr_native_batch_witnesses() -> Bool { + witness_two_routed_families_enrolled() + && witness_floor_batches_gain_native_batch() +} diff --git a/src/v2/test/claim/realize_advisory_soundness_test.dag b/src/v2/test/claim/realize_advisory_soundness_test.dag new file mode 100644 index 00000000000..e922a098f88 --- /dev/null +++ b/src/v2/test/claim/realize_advisory_soundness_test.dag @@ -0,0 +1,77 @@ +module v2.test.claim.realize_advisory_soundness_test + +import v2.workflow.realize_advisory_soundness { + AdvisoryObservation, + AdvisorySoundness, + BoundSound, + BoundUnsound, + BoundUnknown, + advisory_soundness_for, + advisory_observation_is_sound, + advisory_window_all_sound +} +import v2.std.logic { Bool } +import v2.std.text { String } + +fn obs(known: Bool, derived: Int, observed: Int) -> AdvisoryObservation { + AdvisoryObservation { + entry: "synthetic_entry.dag", + subject_function: "synthetic_fn", + derived_bytes_known: known, + derived_bytes: derived, + observed_peak_bytes: observed + } +} + +fn witness_sound_bound_carries_margin() -> Bool { + match advisory_soundness_for(o: obs(known: true, derived: 1000, observed: 800)) { + BoundSound { margin_bytes: m } => m == 200 + BoundUnsound { derived_bytes: _, observed_peak_bytes: _ } => false + BoundUnknown { entry: _, subject_function: _ } => false + } +} + +fn witness_exceedance_is_unsound() -> Bool { + match advisory_soundness_for(o: obs(known: true, derived: 1000, observed: 1001)) { + BoundUnsound { derived_bytes: d, observed_peak_bytes: p } => d == 1000 && p == 1001 + BoundSound { margin_bytes: _ } => false + BoundUnknown { entry: _, subject_function: _ } => false + } +} + +fn witness_unknown_bound_is_not_sound() -> Bool { + advisory_observation_is_sound(o: obs(known: false, derived: 0, observed: 500)) == false +} + +fn witness_exact_bound_is_sound() -> Bool { + advisory_observation_is_sound(o: obs(known: true, derived: 500, observed: 500)) +} + +fn witness_window_reds_on_one_unsound() -> Bool { + let all_sound = advisory_window_all_sound( + observations: [ + obs(known: true, derived: 1000, observed: 900), + obs(known: true, derived: 1000, observed: 1200), + obs(known: true, derived: 1000, observed: 100) + ] + ) + all_sound == false +} + +fn witness_window_green_when_all_sound() -> Bool { + advisory_window_all_sound( + observations: [ + obs(known: true, derived: 1000, observed: 900), + obs(known: true, derived: 2000, observed: 1) + ] + ) +} + +test fn realize_advisory_soundness_witnesses() -> Bool { + witness_sound_bound_carries_margin() + && witness_exceedance_is_unsound() + && witness_unknown_bound_is_not_sound() + && witness_exact_bound_is_sound() + && witness_window_reds_on_one_unsound() + && witness_window_green_when_all_sound() +} diff --git a/src/v2/test/claim/self_host/native_routing_frontier_test.dag b/src/v2/test/claim/self_host/native_routing_frontier_test.dag new file mode 100644 index 00000000000..d76f87e2e9a --- /dev/null +++ b/src/v2/test/claim/self_host/native_routing_frontier_test.dag @@ -0,0 +1,63 @@ +module v2.test.claim.self_host.native_routing_frontier_test + +import v2.compiler.self_host.native_routing_frontier { + native_routing_frontier_roster, + native_routing_frontier_family_count_expected, + native_routed_rows, + interpreted_retained_rows, + routing_frontier_row_for_family, + routing_frontier_total_holds, + routing_row_is_native +} +import v2.compiler.self_host.parity_window { parity_flip_permitted } +import v2.compiler.self_host.parity_receipts_local { meet_join_local_receipts, complement_local_receipts } +import v2.std.algebra { length } +import v2.std.logic { Bool } +import v2.std.text { String } + +fn witness_roster_total_holds() -> Bool { + routing_frontier_total_holds() +} + +fn witness_each_family_has_exactly_one_row() -> Bool { + fold( + native_routing_frontier_roster, + init: true, + f: fn(acc, row) { + acc && (length(xs: routing_frontier_row_for_family(family: row.family)) == 1) + } + ) +} + +fn witness_unlisted_family_has_no_row() -> Bool { + length(xs: routing_frontier_row_for_family(family: "unlisted_synthetic_family")) == 0 +} + +fn witness_routed_and_retained_split() -> Bool { + (length(xs: native_routed_rows()) == 2) + && (length(xs: interpreted_retained_rows()) == 7) +} + +fn witness_flips_cite_parity_evidence() -> Bool { + parity_flip_permitted(family: "meet_join", receipts: meet_join_local_receipts()) + && parity_flip_permitted(family: "complement", receipts: complement_local_receipts()) +} + +fn witness_retained_rows_carry_reason_and_trigger() -> Bool { + fold( + interpreted_retained_rows(), + init: true, + f: fn(acc, row) { + acc && !routing_row_is_native(row: row) + } + ) +} + +test fn native_routing_frontier_witnesses() -> Bool { + witness_roster_total_holds() + && witness_each_family_has_exactly_one_row() + && witness_unlisted_family_has_no_row() + && witness_routed_and_retained_split() + && witness_flips_cite_parity_evidence() + && witness_retained_rows_carry_reason_and_trigger() +} diff --git a/src/v2/test/claim/self_host/parity_window_test.dag b/src/v2/test/claim/self_host/parity_window_test.dag new file mode 100644 index 00000000000..58fdb349d61 --- /dev/null +++ b/src/v2/test/claim/self_host/parity_window_test.dag @@ -0,0 +1,111 @@ +module v2.test.claim.self_host.parity_window_test + +import v2.compiler.self_host.parity_window { + ParityWindowReceipt, + ParityVerdict, + ParityFlipPermitted, + ParityFlipRefused, + parity_verdict_for, + parity_flip_permitted, + trailing_consecutive_green, + required_consecutive_green_windows +} +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.text { String } + +fn green_receipt(id: String) -> ParityWindowReceipt { + ParityWindowReceipt { + family: "add", + cadence_window_id: id, + agreement_green: true, + warm_compile_skipped: true + } +} + +fn red_receipt(id: String) -> ParityWindowReceipt { + ParityWindowReceipt { + family: "add", + cadence_window_id: id, + agreement_green: false, + warm_compile_skipped: true + } +} + +fn cold_receipt(id: String) -> ParityWindowReceipt { + ParityWindowReceipt { + family: "add", + cadence_window_id: id, + agreement_green: true, + warm_compile_skipped: false + } +} + +fn witness_three_greens_permit() -> Bool { + parity_flip_permitted( + family: "add", + receipts: [green_receipt(id: "w1"), green_receipt(id: "w2"), green_receipt(id: "w3")] + ) +} + +fn witness_red_resets_streak() -> Bool { + let refused = parity_flip_permitted( + family: "add", + receipts: [ + green_receipt(id: "w1"), + red_receipt(id: "w2"), + green_receipt(id: "w3"), + green_receipt(id: "w4") + ] + ) + refused == false +} + +fn witness_cold_divergence_resets_streak() -> Bool { + let refused = parity_flip_permitted( + family: "add", + receipts: [ + green_receipt(id: "w1"), + green_receipt(id: "w2"), + cold_receipt(id: "w3") + ] + ) + refused == false +} + +fn witness_empty_receipts_refuse() -> Bool { + parity_flip_permitted(family: "add", receipts: []) == false +} + +fn witness_refusal_carries_streak_and_required() -> Bool { + match parity_verdict_for( + family: "add", + receipts: [green_receipt(id: "w1"), green_receipt(id: "w2")] + ) { + ParityFlipRefused { family: _, consecutive_green: streak, required: req } => + streak == 2 && req == required_consecutive_green_windows + ParityFlipPermitted { family: _, consecutive_green: _ } => false + } +} + +fn witness_streak_counts_trailing_only() -> Bool { + let streak = trailing_consecutive_green( + receipts: [ + green_receipt(id: "w1"), + green_receipt(id: "w2"), + green_receipt(id: "w3"), + red_receipt(id: "w4"), + green_receipt(id: "w5") + ] + ) + streak == 1 +} + +test fn parity_window_witnesses() -> Bool { + witness_three_greens_permit() + && witness_red_resets_streak() + && witness_cold_divergence_resets_streak() + && witness_empty_receipts_refuse() + && witness_refusal_carries_streak_and_required() + && witness_streak_counts_trailing_only() +} diff --git a/src/v2/workflow/ci_floor_plan.dag b/src/v2/workflow/ci_floor_plan.dag index b51d02f5cbc..6e10b5d125a 100644 --- a/src/v2/workflow/ci_floor_plan.dag +++ b/src/v2/workflow/ci_floor_plan.dag @@ -3,6 +3,7 @@ module v2.workflow.ci_floor_plan import std.execution_mode { Hermetic, Wet } import gunbc.ci_layer_roots { witness_layer_roots, witness_exclusion_substrings, witness_discovery_scan_dirs, bin_witness_wet_entries, known_red_probe_entries, falsifier_silent_pick_gate_entries } import v2.compiler.self_host.wet_receipt_enrollment { falsifier_self_host_wet_entries, falsifier_native_cache_cold_roster } +import v2.compiler.self_host.native_routing_frontier { native_routed_rows, NativeRoutingFrontierRow } import gunbc.ci_spec { gunbc_ci_spec, gunbc_ci_regen_spec, CiSpec, ci_spec_with_discovery_scan_dirs, @@ -711,8 +712,51 @@ fn gunbc_falsifier_batches() -> List> { ) } +data gunbc_pr_native_batch_note: String = "Per-PR native batch (P6 routing consumption, 2026-07-22): explicit entries = the equals_eval agreement legs of families the native-routing frontier marks NativeRouted — nothing else. The frontier is the ONE authority for both sides of the floor (this batch enrolls exactly the routed set; nothing else changes), and flips are parity-window-gated data, so at landing the routed set is empty and this appends no batch: zero behavior change until receipts flip a family. Wet profile: the admitted transport cargo-builds cold or runs warm against GUNBC_NATIVE_CACHE_ROOT." + +fn gunbc_pr_native_entries() -> List { + fold( + native_routed_rows(), + init: [], + f: fn(acc, row) { + concat(acc, [ + ScheduleWitnessEntry { + entry: row.agreement_entry, + function: row.agreement_function, + kind: ExecutionWitnessKind + } + ]) + } + ) +} + +fn gunbc_pr_native_batch_enrolled() -> Bool { + length(xs: gunbc_pr_native_entries()) > 0 +} + +fn gunbc_pr_native_batch() -> Runnable { + RunnableDiscoveryBatch { + source_roots: corpus_source_roots(), + scan_dirs: [], + explicit_entries: gunbc_pr_native_entries(), + node_frontier_selection: SelectionApplied, + exclude_substrings: [], + discovery_scope_dirs: [], + profile: runnable_resource_profile( + heavy_whole_tree_resolve: false, + spawns_host_compiler: true, + memory: runnable_memory_substantial(), + execution_mode: Hermetic + ) + } +} + fn gunbc_ci_floor_batches() -> List> { - gunbc_ci_floor_realization_plan().schedule + falsifier_batches_append_if_enrolled( + acc: gunbc_ci_floor_realization_plan().schedule, + enrolled: gunbc_pr_native_batch_enrolled(), + batch: gunbc_pr_native_batch() + ) } data gunbc_ci_witness_corpus_only_batches_note: String = "The pre-push local test gate (consumer: dag/gunbc/githooks_pre_push_emit.dag NEED_WITNESS). It is the SAME affected-set witness corpus CI runs (corpus_runnable_for(gunbc_ci_spec), SelectionApplied scoped to the push diff via the executor's git-diff observation), MINUS two lanes on purpose: (1) the whole-tree --target dag compile-clean gate (batch 1 of gunbc_ci_floor_batches) - infeasible per-push (~72min emit), CI-owned; and (2) the Wet execution + bin-witness lanes (execution_corpus_node / bin_witness_corpus_node) - they need prebuilt release witness bins and spawn a host compiler, so they stay CI-owned. This is a DECLARED scope narrowing, not a silent one (the enforcement-intent rule): the hermetic discovery corpus is the affected-set bulk and catches the resolve / typecheck / witness-logic red class before push; CI remains the whole wall. Selection stays fail-closed exactly as the floor (ci_spec_discovery_flip_note; compile_door_ledger; cli_run AFFECTED-SET REFUSAL): a diff-observation / provenance gap REFUSES with a typed, located diagnostic — it never widens to the whole corpus and never silently skips (DESIGN §5: refuse, never widen)." diff --git a/src/v2/workflow/ci_workflow_run_emit.dag b/src/v2/workflow/ci_workflow_run_emit.dag index d2cf17a6a0c..f62172e8da8 100644 --- a/src/v2/workflow/ci_workflow_run_emit.dag +++ b/src/v2/workflow/ci_workflow_run_emit.dag @@ -27,11 +27,13 @@ data ci_isolate_echo_rustup_home_command: String = "echo \"RUSTUP_HOME=$RUNNER_T data ci_isolate_echo_makeflags_command: String = "echo \"MAKEFLAGS=\" >> \"$GITHUB_ENV\"" -data ci_native_cache_root_note: String = "Durable native-artifact cache root (extdeps.realization.native_artifact_cache, PerRunnerFilesystem): RUNNER_TOOL_CACHE survives the per-run RUNNER_TEMP wipe on self-hosted runners, so emit-on-demand cargo workspaces warm across runs (compile_skipped receipts). The cached transport rebases only the declared /tmp/gunbc_ scratch prefix onto this root; content-hash path components stay the key, so cross-branch sharing on one runner is benign-by-identity. Falsifier cold control: GUNBC_CI_NATIVE_CACHE_COLD_CONTROL." +data ci_native_cache_root_note: String = "Durable native-artifact cache root (extdeps.realization.native_artifact_cache, PerRunnerFilesystem): RUNNER_TOOL_CACHE survives the per-run RUNNER_TEMP wipe on self-hosted runners, so emit-on-demand cargo workspaces warm across runs (compile_skipped receipts). The cached transport rebases only the declared /tmp/gunbc_ scratch prefix onto this root; content-hash path components stay the key, so cross-branch sharing on one runner is benign-by-identity. R2 (computation-identity census, 2026-07-22): the KEY carries only the nominal grain-toolchain string, so real toolchain identity enters via the root path — a rustc-version segment derived at prelude time makes a toolchain upgrade land in a fresh root and cold-rebuild everything (realization-side backstop; folding true toolchain identity into emit_on_demand_key is the construction end-state, deferred to avoid churning every family call site). Falsifier cold control: GUNBC_CI_NATIVE_CACHE_COLD_CONTROL." -data ci_native_cache_root_mkdir_command: String = "mkdir -p \"$RUNNER_TOOL_CACHE/gunbc-native\"" +data ci_native_cache_root_toolchain_segment_command: String = "GUNBC_TOOLCHAIN_SEG=$(rustc -V 2>/dev/null | tr ' ' '-'); if [ -z \"$GUNBC_TOOLCHAIN_SEG\" ]; then GUNBC_TOOLCHAIN_SEG=toolchain-unresolved; fi" -data ci_native_cache_root_echo_command: String = "echo \"GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native\" >> \"$GITHUB_ENV\"" +data ci_native_cache_root_mkdir_command: String = "mkdir -p \"$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG\"" + +data ci_native_cache_root_echo_command: String = "echo \"GUNBC_NATIVE_CACHE_ROOT=$RUNNER_TOOL_CACHE/gunbc-native/$GUNBC_TOOLCHAIN_SEG\" >> \"$GITHUB_ENV\"" data ci_selection_control_witness_invoke_command: String = "\"$ROOT/target/release/floor_skip_discovery_witness\"" @@ -88,6 +90,7 @@ fn ci_isolate_toolchain_intent(build_jobs_count: Int) -> Pipeline { ci_workflow_do(command: ci_isolate_echo_rustup_home_command), ci_workflow_do(command: ci_isolate_echo_makeflags_command), ci_workflow_do(command: ci_isolate_cargo_build_jobs_command(build_jobs_count: build_jobs_count)), + ci_workflow_do(command: ci_native_cache_root_toolchain_segment_command), ci_workflow_do(command: ci_native_cache_root_mkdir_command), ci_workflow_do(command: ci_native_cache_root_echo_command), ci_workflow_do(command: ci_sccache_provider_shell_injection()) diff --git a/src/v2/workflow/native_cache_fusion.dag b/src/v2/workflow/native_cache_fusion.dag new file mode 100644 index 00000000000..61293d97272 --- /dev/null +++ b/src/v2/workflow/native_cache_fusion.dag @@ -0,0 +1,38 @@ +module v2.workflow.native_cache_fusion + +import std.emit_on_demand { + EmitOnDemandLookup, EmitOnDemandHit, EmitOnDemandMiss, + EmitOnDemandCacheReceipt, materialization_for_lookup +} +import std.types { ContentHash } +import std.content_hash { content_hash_atom } +import std.realization { Materialization, Share, Recompute } +import v2.std.logic { Bool } +import v2.std.text { String } + +data native_cache_fusion_note: String = "P2/host fusion law (census R6 projection, 2026-07-22): the host transport decides warmness as compile_skipped = !cold_control && marker_exists (v1_interpreter.rs emit_host_run_transport_cached_in_workspace, the .native_ready rule), while the P2 model decides Share|Recompute via emit_on_demand_lookup over the artifact store. These are two realizations of ONE decision and must agree: marker-present under no control == store hit == Share; marker-absent or control-forced == miss == Recompute. This module states that agreement as the executable law over a modeled host observation (mirroring the cited Rust rule), so divergence between the model and the realization is a red, not silent drift. Full fusion — the host transport reading the P2 store itself — is the R6 construction end-state; until then this law is the tripwire." + +type HostWarmObservation { + marker_exists: Bool + cold_control: Bool +} + +fn host_compile_skipped(o: HostWarmObservation) -> Bool { + o.cold_control == false && o.marker_exists +} + +fn model_lookup_for(o: HostWarmObservation, key: ContentHash) -> EmitOnDemandLookup { + if host_compile_skipped(o: o) { + EmitOnDemandHit { + receipt: EmitOnDemandCacheReceipt { key: key, compile_skipped: true } + } + } else { + EmitOnDemandMiss + } +} + +fn fusion_agreement_holds_for(o: HostWarmObservation) -> Bool { + let key = content_hash_atom(value: "fusion-law-synthetic-key") + let model_share = materialization_for_lookup(lookup: model_lookup_for(o: o, key: key)) == Share + host_compile_skipped(o: o) == model_share +} diff --git a/src/v2/workflow/realize_advisory_soundness.dag b/src/v2/workflow/realize_advisory_soundness.dag new file mode 100644 index 00000000000..574a7547d94 --- /dev/null +++ b/src/v2/workflow/realize_advisory_soundness.dag @@ -0,0 +1,51 @@ +module v2.workflow.realize_advisory_soundness + +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.text { String } + +data realize_advisory_soundness_note: String = "P4 consumption gate (2026-07-22): the realize_pack advisory logger emits per-subject pairs (derived space bound vs governor-observed peak) as receipt lines every corpus run — computed since #6855 but consumed by nothing. This module is the soundness LAW those pairs are judged by: a derived bound is sound iff observed peak <= derived bytes; an observed exceedance is BoundUnsound (the P4 cutover blocker signal), and a missing derived bound is BoundUnknown — a typed state, never treated as sound (no fabricated plausible output, DESIGN section 5). Receipt rows are authored from falsifier run observations, the parity-window pattern; the P4 governor demotion is gated on a window of BoundSound rows the same way routing flips gate on parity." + +type AdvisoryObservation { + entry: String + subject_function: String + derived_bytes_known: Bool + derived_bytes: Int + observed_peak_bytes: Int +} + +type AdvisorySoundness + = BoundSound { margin_bytes: Int } + | BoundUnsound { derived_bytes: Int, observed_peak_bytes: Int } + | BoundUnknown { entry: String, subject_function: String } + +fn advisory_soundness_for(o: AdvisoryObservation) -> AdvisorySoundness { + if o.derived_bytes_known == false { + BoundUnknown { entry: o.entry, subject_function: o.subject_function } + } else if o.observed_peak_bytes > o.derived_bytes { + BoundUnsound { + derived_bytes: o.derived_bytes, + observed_peak_bytes: o.observed_peak_bytes + } + } else { + BoundSound { margin_bytes: o.derived_bytes - o.observed_peak_bytes } + } +} + +fn advisory_observation_is_sound(o: AdvisoryObservation) -> Bool { + match advisory_soundness_for(o: o) { + BoundSound { margin_bytes: _ } => true + BoundUnsound { derived_bytes: _, observed_peak_bytes: _ } => false + BoundUnknown { entry: _, subject_function: _ } => false + } +} + +fn advisory_window_all_sound(observations: List) -> Bool { + fold( + observations, + init: true, + f: fn(acc, o) { + acc && advisory_observation_is_sound(o: o) + } + ) +}