From 32d7d2a1dd5b60c248c0cfa8e11d7ef7af6efcb2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 14:35:56 +0000 Subject: [PATCH 01/13] WIP: Production selector cutover into the native execution kind (post-#7599 s --- dag/std/realization_schedule.dag | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dag/std/realization_schedule.dag b/dag/std/realization_schedule.dag index 495766f23fa..0b9029e366a 100644 --- a/dag/std/realization_schedule.dag +++ b/dag/std/realization_schedule.dag @@ -50,6 +50,7 @@ type RealizationObjective { type WitnessKind = CorpusWitnessKind | ExecutionWitnessKind + | NativeBundleWitnessKind type WitnessSeam { producer: String @@ -62,8 +63,21 @@ type WitnessSpan fn witness_kind_eq(a: WitnessKind, b: WitnessKind) -> Bool { match a { - CorpusWitnessKind => match b { CorpusWitnessKind => true ExecutionWitnessKind => false } - ExecutionWitnessKind => match b { ExecutionWitnessKind => true CorpusWitnessKind => false } + CorpusWitnessKind => match b { + CorpusWitnessKind => true + ExecutionWitnessKind => false + NativeBundleWitnessKind => false + } + ExecutionWitnessKind => match b { + ExecutionWitnessKind => true + CorpusWitnessKind => false + NativeBundleWitnessKind => false + } + NativeBundleWitnessKind => match b { + NativeBundleWitnessKind => true + CorpusWitnessKind => false + ExecutionWitnessKind => false + } } } From f60b8064689a598ee31765d17b995f0883749fd2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 15:24:19 +0000 Subject: [PATCH 02/13] WIP: Production selector cutover into the native execution kind (post-#7599 s --- dag/gunbc/merge_admission.dag | 3 +- dag/std/selected_witness_bundle.dag | 36 ++ src/v1/stage0/src/bin/claim_executor.rs | 483 +++++++++++++++++- src/v1/stage0/src/std_realization_schedule.rs | 10 + src/v1/stage0/src/v1_interpreter.rs | 98 +++- .../native_selected_bundle_process.dag | 22 + ...ive_selected_witness_bundle_production.dag | 125 +++++ .../native_selected_witness_bundle_test.dag | 12 +- src/v2/test/claim/pr_native_batch_test.dag | 15 +- src/v2/workflow/ci_floor_plan.dag | 26 +- 10 files changed, 781 insertions(+), 49 deletions(-) create mode 100644 src/v2/compiler/native_selected_bundle_process.dag create mode 100644 src/v2/test/claim/execution/native_selected_witness_bundle_production.dag diff --git a/dag/gunbc/merge_admission.dag b/dag/gunbc/merge_admission.dag index 1d351481a0d..ddc8dd2c617 100644 --- a/dag/gunbc/merge_admission.dag +++ b/dag/gunbc/merge_admission.dag @@ -31,7 +31,7 @@ import gunbc.commit_workflow { CommitSpecGate, CommitWitnessClaim, CommitCargoFmtCheck, } import std.realization_schedule { - WitnessKind, CorpusWitnessKind, ExecutionWitnessKind, + WitnessKind, CorpusWitnessKind, ExecutionWitnessKind, NativeBundleWitnessKind, WitnessSeam, WitnessSpan, SpanUndeclared, SpanSeams, } import gunbc.ci_gate { @@ -127,6 +127,7 @@ fn witness_kind_content_hash_structural(kind: WitnessKind) -> Fnv1a64Structural match kind { CorpusWitnessKind => content_hash_atom(value: "CorpusWitnessKind") ExecutionWitnessKind => content_hash_atom(value: "ExecutionWitnessKind") + NativeBundleWitnessKind => content_hash_atom(value: "NativeBundleWitnessKind") } } diff --git a/dag/std/selected_witness_bundle.dag b/dag/std/selected_witness_bundle.dag index 268ac81aec2..269762da8d8 100644 --- a/dag/std/selected_witness_bundle.dag +++ b/dag/std/selected_witness_bundle.dag @@ -313,6 +313,42 @@ type NativeWitnessBundleExecutionReceipt { interpreter_frontier_count: Int } +type NativeProductionTransitionVerdict + = NativeProductionTransitionAccepted + | NativeProductionTransitionFallback { cause: NativeUnavailableCause } + | NativeProductionTransitionRefused { reason: NonEmptyStr } + +type NativeWitnessProductionTransitionReceipt { + selected_count: Int + native_count: Int + interpreted_count: Int + unavailable_count: Int + bundle_count: Int + shard_count: Int + cold_compile_wall_nanos: NanosecondDuration + warm_artifact_hit_wall_nanos: NanosecondDuration + native_execution_wall_nanos: NanosecondDuration + interpreter_oracle_wall_nanos: NanosecondDuration + fallback_count: Int + rss_peak_bytes: Int + cgroup_peak_bytes: Int + verdict: NativeProductionTransitionVerdict + planted_red_equivalent: Bool +} + +fn native_production_transition_population_holds( + receipt: NativeWitnessProductionTransitionReceipt +) -> Bool { + receipt.selected_count > 0 + && receipt.bundle_count == 1 + && receipt.shard_count == 1 + && receipt.native_count + receipt.interpreted_count == receipt.selected_count + && receipt.unavailable_count == receipt.fallback_count + && receipt.fallback_count <= receipt.interpreted_count + && receipt.rss_peak_bytes >= 0 + && receipt.cgroup_peak_bytes >= 0 +} + type NativeBundleFamilyCutoverEvidence { planted_plan: SelectedWitnessPlan execution: NativeWitnessBundleExecutionReceipt diff --git a/src/v1/stage0/src/bin/claim_executor.rs b/src/v1/stage0/src/bin/claim_executor.rs index 21395094e8b..e6f676f956a 100644 --- a/src/v1/stage0/src/bin/claim_executor.rs +++ b/src/v1/stage0/src/bin/claim_executor.rs @@ -25,7 +25,8 @@ use v1_compiler::memory_governor::{ AdmittedSlot, MemoryGovernor, }; use v1_compiler::v1_interpreter::{ - color_enabled, paint, run_in_context_with_args, sgr, ExecutionMode, InterpContext, Value, + color_enabled, paint, run_in_context, run_in_context_with_args, sgr, ExecutionMode, + InterpContext, Value, }; /// Per-LANE budgets for the falsifier's rostered batches, each keyed by the lane's own @@ -567,6 +568,7 @@ enum Runnable { source_roots: Vec, scan_dirs: Vec, explicit_entries: Vec<(String, String)>, + native_bundle_entries: Vec<(String, String)>, node_frontier_selection: NodeFrontierSelectionMode, exclude_substrings: Vec, discovery_scope_dirs: Vec, @@ -838,9 +840,12 @@ fn runnable_from_value(value: &Value, ctx: &InterpContext) -> Result str_list_from_value(v, ctx)?, None => return Err("RunnableDiscoveryBatch missing field `scan_dirs`".to_string()), }; - let explicit_entries = match ctx.field(fields, "explicit_entries") { + let (explicit_entries, native_bundle_entries) = match ctx + .field(fields, "explicit_entries") + { Some(v) => { let mut out = Vec::new(); + let mut native = Vec::new(); for elem in free_monoid_elems(v, ctx)? { let efields = match elem { Value::Record { fields, .. } => fields, @@ -852,14 +857,48 @@ fn runnable_from_value(value: &Value, ctx: &InterpContext) -> Result + { + out.push((entry, function)); + } + Some(Value::Variant { variant_name, .. }) + if ctx.sym_eq(*variant_name, "NativeBundleWitnessKind") => + { + native.push((entry, function)); + } + Some(Value::Variant { variant_name, .. }) => { + return Err(format!( + "RunnableDiscoveryBatch explicit entry {entry}::{function}: \ + unhandled WitnessKind `{}` (kind_dispatch_refusal_count=1); \ + refusing instead of interpreting", + ctx.resolve(*variant_name) + )); + } + Some(other) => { + return Err(format!( + "RunnableDiscoveryBatch explicit entry {entry}::{function}: \ + WitnessKind is {}, not a variant \ + (kind_dispatch_refusal_count=1)", + other.type_label_public() + )); + } + None => { + return Err(format!( + "RunnableDiscoveryBatch explicit entry {entry}::{function}: \ + WitnessKind is absent (kind_dispatch_refusal_count=1); \ + refusing instead of interpreting" + )); + } + } } - out + (out, native) } - None => Vec::new(), + None => (Vec::new(), Vec::new()), }; let node_frontier_selection = match ctx.field(fields, "node_frontier_selection") { Some(Value::Variant { variant_name, .. }) => { @@ -915,6 +954,7 @@ fn runnable_from_value(value: &Value, ctx: &InterpContext) -> Result, scan_dirs: Vec, @@ -1196,19 +1241,31 @@ fn group_batch_units(batch: &[Runnable]) -> Vec { source_roots, scan_dirs, explicit_entries, + native_bundle_entries, node_frontier_selection, exclude_substrings, discovery_scope_dirs, execution_mode, - } => units.push(BatchUnit::Discovery { - source_roots: source_roots.clone(), - scan_dirs: scan_dirs.clone(), - explicit_entries: explicit_entries.clone(), - node_frontier_selection: *node_frontier_selection, - exclude_substrings: exclude_substrings.clone(), - discovery_scope_dirs: discovery_scope_dirs.clone(), - execution_mode: *execution_mode, - }), + } => { + if !scan_dirs.is_empty() || !explicit_entries.is_empty() { + units.push(BatchUnit::Discovery { + source_roots: source_roots.clone(), + scan_dirs: scan_dirs.clone(), + explicit_entries: explicit_entries.clone(), + node_frontier_selection: *node_frontier_selection, + exclude_substrings: exclude_substrings.clone(), + discovery_scope_dirs: discovery_scope_dirs.clone(), + execution_mode: *execution_mode, + }); + } + for (entry, selector_function) in native_bundle_entries { + units.push(BatchUnit::NativeBundle { + entry: entry.clone(), + selector_function: selector_function.clone(), + execution_mode: *execution_mode, + }); + } + } } } units @@ -1350,6 +1407,355 @@ fn claim_result_for_outcome( } } +#[derive(Clone)] +struct NativeBundleProcessSpec { + workspace_dir: String, + bundle_identity: String, + selected_count: u64, + bundle_count: u64, + shard_count: u64, + files: Vec<(String, String)>, + build: Vec>, + run: Vec, + expected_stdout: Vec, +} + +struct NativeTransportObservation { + success: bool, + compile_skipped: bool, + stdout: Vec, + artifact_lookup_nanos: u128, + cold_compile_nanos: u128, + native_execution_nanos: u128, +} + +fn native_bundle_u64_field( + fields: &[(v1_compiler::v1_interpreter::Symbol, Value)], + name: &str, + ctx: &InterpContext, +) -> Result { + match ctx.field(fields, name) { + Some(Value::Int(n)) if *n >= 0 => Ok(*n as u64), + Some(other) => Err(format!( + "native bundle spec field `{name}` must be a non-negative Int, got {}", + other.type_label_public() + )), + None => Err(format!("native bundle spec missing field `{name}`")), + } +} + +fn native_bundle_string_list(value: &Value, ctx: &InterpContext) -> Result, String> { + free_monoid_elems(value, ctx)? + .into_iter() + .map(|item| match item { + Value::Str(s) => Ok(s.clone()), + other => Err(format!( + "native bundle argv element must be String, got {}", + other.type_label_public() + )), + }) + .collect() +} + +fn native_bundle_spec_from_value( + value: &Value, + ctx: &InterpContext, +) -> Result { + let outcome_fields = match value { + Value::Variant { + variant_name, + fields, + .. + } if ctx.sym_eq(*variant_name, "Accepted") => fields, + Value::Variant { variant_name, .. } if ctx.sym_eq(*variant_name, "Rejected") => { + return Err("native bundle selector returned typed Rejected".to_string()) + } + other => { + return Err(format!( + "native bundle selector must return Outcome, got {}", + other.type_label_public() + )) + } + }; + let spec = ctx + .field(outcome_fields, "value") + .ok_or_else(|| "native bundle Accepted outcome missing `value`".to_string())?; + let fields = match spec { + Value::Record { fields, .. } | Value::Variant { fields, .. } => fields, + other => { + return Err(format!( + "native bundle selector value must be a record, got {}", + other.type_label_public() + )) + } + }; + let workspace_dir = str_field(fields, "workspace_dir", "native bundle spec", ctx)?; + let bundle_identity = str_field(fields, "bundle_identity", "native bundle spec", ctx)?; + if bundle_identity.is_empty() || !workspace_dir.contains(&bundle_identity) { + return Err( + "native bundle artifact identity is absent from its workspace path".to_string(), + ); + } + let files_value = ctx + .field(fields, "files") + .ok_or_else(|| "native bundle spec missing `files`".to_string())?; + let mut files = Vec::new(); + for file in free_monoid_elems(files_value, ctx)? { + let ff = match file { + Value::Record { fields, .. } | Value::Variant { fields, .. } => fields, + other => { + return Err(format!( + "native bundle file must be a record, got {}", + other.type_label_public() + )) + } + }; + files.push(( + str_field(ff, "path", "native bundle file", ctx)?, + str_field(ff, "text", "native bundle file", ctx)?, + )); + } + let build_value = ctx + .field(fields, "build") + .ok_or_else(|| "native bundle spec missing `build`".to_string())?; + let build = free_monoid_elems(build_value, ctx)? + .into_iter() + .map(|argv| native_bundle_string_list(argv, ctx)) + .collect::, _>>()?; + let run = native_bundle_string_list( + ctx.field(fields, "run") + .ok_or_else(|| "native bundle spec missing `run`".to_string())?, + ctx, + )?; + let expected_stdout = free_monoid_elems( + ctx.field(fields, "expected_stdout_octets") + .ok_or_else(|| "native bundle spec missing `expected_stdout_octets`".to_string())?, + ctx, + )? + .into_iter() + .map(|octet| match octet { + Value::Int(n) if (0..=255).contains(n) => Ok(*n as u8), + _ => Err("native bundle expected stdout contains a non-octet".to_string()), + }) + .collect::, _>>()?; + let spec = NativeBundleProcessSpec { + workspace_dir, + bundle_identity, + selected_count: native_bundle_u64_field(fields, "selected_count", ctx)?, + bundle_count: native_bundle_u64_field(fields, "bundle_count", ctx)?, + shard_count: native_bundle_u64_field(fields, "shard_count", ctx)?, + files, + build, + run, + expected_stdout, + }; + if spec.selected_count != 3 || spec.bundle_count != 1 || spec.shard_count != 1 { + return Err(format!( + "native bundle bounded-population refusal: selected={} bundle={} shard={} (required 3/1/1)", + spec.selected_count, spec.bundle_count, spec.shard_count + )); + } + if spec.files.is_empty() || spec.build.is_empty() || spec.run.is_empty() { + return Err("native bundle process spec has empty files/build/run".to_string()); + } + Ok(spec) +} + +fn native_transport_observation( + value: &Value, + ctx: &InterpContext, +) -> Result { + let fields = match value { + Value::Record { fields, .. } | Value::Variant { fields, .. } => fields, + other => { + return Err(format!( + "native transport result must be a record, got {}", + other.type_label_public() + )) + } + }; + let boolean = |name: &str| match ctx.field(fields, name) { + Some(Value::Bool(v)) => Ok(*v), + _ => Err(format!("native transport result missing Bool `{name}`")), + }; + let nanos = |name: &str| native_bundle_u64_field(fields, name, ctx).map(u128::from); + let stdout = free_monoid_elems( + ctx.field(fields, "stdout_octets") + .ok_or_else(|| "native transport result missing stdout".to_string())?, + ctx, + )? + .into_iter() + .map(|v| match v { + Value::Int(n) if (0..=255).contains(n) => Ok(*n as u8), + _ => Err("native transport stdout contains a non-octet".to_string()), + }) + .collect::, _>>()?; + Ok(NativeTransportObservation { + success: boolean("success")?, + compile_skipped: boolean("compile_skipped")?, + stdout, + artifact_lookup_nanos: nanos("artifact_lookup_nanos")?, + cold_compile_nanos: nanos("cold_compile_nanos")?, + native_execution_nanos: nanos("native_execution_nanos")?, + }) +} + +fn run_native_transport( + spec: &NativeBundleProcessSpec, + ctx: &InterpContext, +) -> Result { + let value = v1_compiler::v1_interpreter::run_native_bundle_process_cached( + ctx, + spec.workspace_dir.clone(), + &spec.files, + &spec.build, + &spec.run, + ) + .map_err(|e| e.to_string())?; + native_transport_observation(&value, ctx) +} + +fn write_native_transition_receipt(body: &str) -> Result<(), String> { + let path = Path::new("target/native-selected-witness-transition-receipt.tsv"); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent).map_err(|e| format!("native transition receipt mkdir: {e}"))?; + } + fs::write(path, body).map_err(|e| format!("native transition receipt write: {e}")) +} + +fn run_native_bundle_unit( + source_roots: &[String], + entry: String, + selector_function: String, + execution_mode: ExecutionMode, +) -> ClaimResult { + let started = Instant::now(); + let fail = |detail: String| ClaimResult { + function: selector_function.clone(), + entry: entry.clone(), + ok: false, + detail, + wall_nanos: started.elapsed().as_nanos(), + resolve_nanos: 0, + corpus_resolve_nanos: 0, + corpus_eval_nanos: 0, + corpus_witnesses: 3, + witness_row_costs: Vec::new(), + budget_refusal: None, + }; + if execution_mode != ExecutionMode::Wet { + return fail( + "NativeBundle handler requires Wet execution_mode (typed envelope refusal)".to_string(), + ); + } + let resolve_started = Instant::now(); + let (graph, indices) = match resolve_entry_graph(source_roots, &entry) { + Ok(v) => v, + Err(e) => return fail(format!("native bundle selector resolve refusal: {e}")), + }; + let resolve_nanos = resolve_started.elapsed().as_nanos(); + let ctx = make_eval_context(&graph, indices, ExecutionMode::Wet); + let primary = match run_in_context(&ctx, &selector_function, false) + .map_err(|e| e.to_string()) + .and_then(|v| native_bundle_spec_from_value(&v, &ctx)) + { + Ok(spec) => spec, + Err(e) => return fail(format!("native bundle selector refusal: {e}")), + }; + let planted = run_in_context(&ctx, "native_selected_logic_planted_red_spec", false) + .map_err(|e| e.to_string()) + .and_then(|v| native_bundle_spec_from_value(&v, &ctx)); + + let cold = run_native_transport(&primary, &ctx); + let warm = match &cold { + Ok(obs) if obs.success => run_native_transport(&primary, &ctx), + _ => Err("primary cold artifact unavailable".to_string()), + }; + let planted_native = planted + .as_ref() + .map_err(Clone::clone) + .and_then(|spec| run_native_transport(spec, &ctx)); + + let oracle_started = Instant::now(); + let oracle_green = matches!( + run_claim(&ctx, "native_selected_logic_interpreter_oracle_holds"), + ClaimOutcome::Pass + ); + let planted_oracle = matches!( + run_claim(&ctx, "native_selected_logic_planted_red_oracle_holds"), + ClaimOutcome::Pass + ); + let interpreter_oracle_wall_nanos = oracle_started.elapsed().as_nanos(); + + let native_ok = matches!((&cold, &warm), (Ok(c), Ok(w)) + if c.success && w.success && w.compile_skipped + && c.stdout == primary.expected_stdout && w.stdout == primary.expected_stdout); + let planted_red_equivalent = planted + .as_ref() + .ok() + .zip(planted_native.as_ref().ok()) + .map(|(spec, obs)| obs.success && obs.stdout == spec.expected_stdout && planted_oracle) + .unwrap_or(false); + let accepted = native_ok && oracle_green && planted_red_equivalent; + let fallback = !native_ok && oracle_green; + let selected = primary.selected_count; + let native_count = if native_ok { selected } else { 0 }; + let interpreted_count = if native_ok { 0 } else { selected }; + let unavailable_count = if native_ok { 0 } else { selected }; + let fallback_count = unavailable_count; + let cold_compile_wall = cold + .as_ref() + .ok() + .map(|o| o.cold_compile_nanos) + .unwrap_or(0); + let warm_artifact_hit_wall = warm + .as_ref() + .ok() + .map(|o| o.artifact_lookup_nanos) + .unwrap_or(0); + let native_execution_wall = warm + .as_ref() + .ok() + .map(|o| o.native_execution_nanos) + .unwrap_or(0); + let rss_peak = peak_rss_bytes().unwrap_or(0); + let cgroup_peak = cgroup_job_measurement().map(|m| m.leaf_peak).unwrap_or(0); + let verdict = if accepted { + "accepted" + } else if fallback { + "fallback:native_realization_refused" + } else { + "refused:equivalence_or_planted_red" + }; + let receipt = format!( + "selected_witness_count\t{selected}\nnative_count\t{native_count}\ninterpreted_count\t{interpreted_count}\nunavailable_count\t{unavailable_count}\nbundle_count\t{}\nshard_count\t{}\ncold_compile_wall_nanos\t{cold_compile_wall}\nwarm_artifact_hit_wall_nanos\t{warm_artifact_hit_wall}\nnative_execution_wall_nanos\t{native_execution_wall}\ninterpreter_oracle_wall_nanos\t{interpreter_oracle_wall_nanos}\nfallback_count\t{fallback_count}\nrss_peak_bytes\t{rss_peak}\ncgroup_peak_bytes\t{cgroup_peak}\nverdict\t{verdict}\nplanted_red_equivalent\t{planted_red_equivalent}\nbundle_identity\t{}\n", + primary.bundle_count, primary.shard_count, primary.bundle_identity + ); + if let Err(e) = write_native_transition_receipt(&receipt) { + return fail(e); + } + eprintln!("[native-selected-bundle] {}", receipt.replace('\n', " ")); + ClaimResult { + function: selector_function, + entry, + ok: accepted || fallback, + detail: if accepted { + receipt + } else if fallback { + format!("counted native fallback; {receipt}") + } else { + format!("native transition refused; {receipt}") + }, + wall_nanos: started.elapsed().as_nanos(), + resolve_nanos, + corpus_resolve_nanos: 0, + corpus_eval_nanos: interpreter_oracle_wall_nanos, + corpus_witnesses: selected as usize, + witness_row_costs: Vec::new(), + budget_refusal: None, + } +} + fn run_batch_unit( source_roots: Vec, unit: BatchUnit, @@ -1374,6 +1780,18 @@ fn run_batch_unit( witness_row_costs: Vec::new(), budget_refusal: None, }], + BatchUnit::NativeBundle { + entry, + selector_function, + execution_mode, + } => { + let mut slot = + AdmittedSlot::acquire_blocking(&governor, &format!("native-bundle {entry}")); + let result = + run_native_bundle_unit(&source_roots, entry, selector_function, execution_mode); + slot.note_unit_complete(); + vec![result] + } BatchUnit::Discovery { source_roots: roots, scan_dirs, @@ -5065,6 +5483,7 @@ fn run_perturb_check( source_roots: roots, scan_dirs, explicit_entries, + native_bundle_entries, node_frontier_selection, exclude_substrings, discovery_scope_dirs, @@ -5073,6 +5492,7 @@ fn run_perturb_check( source_roots: roots.iter().map(|r| remap_root(r)).collect(), scan_dirs: scan_dirs.iter().map(|d| remap_root(d)).collect(), explicit_entries: explicit_entries.clone(), + native_bundle_entries: native_bundle_entries.clone(), node_frontier_selection: *node_frontier_selection, exclude_substrings: exclude_substrings.clone(), discovery_scope_dirs: discovery_scope_dirs.clone(), @@ -7339,6 +7759,7 @@ mod tests { source_roots: vec!["src/v2".to_string()], scan_dirs: vec![], explicit_entries: vec![], + native_bundle_entries: vec![], node_frontier_selection: NodeFrontierSelectionMode::Applied, exclude_substrings: vec![], discovery_scope_dirs: vec![], @@ -7365,6 +7786,7 @@ mod tests { out.push((String::new(), function.clone())); } BatchUnit::Discovery { .. } => {} + BatchUnit::NativeBundle { .. } => {} } } out @@ -7396,6 +7818,33 @@ mod tests { } } + #[test] + fn native_bundle_kind_becomes_only_a_native_unit() { + let batch = vec![Runnable::DiscoveryBatch { + source_roots: vec!["src/v2".to_string(), "dag".to_string()], + scan_dirs: vec![], + explicit_entries: vec![], + native_bundle_entries: vec![("bundle.dag".to_string(), "bundle_spec".to_string())], + node_frontier_selection: NodeFrontierSelectionMode::Applied, + exclude_substrings: vec![], + discovery_scope_dirs: vec![], + execution_mode: ExecutionMode::Wet, + }]; + let units = group_batch_units(&batch); + assert_eq!( + units.len(), + 1, + "native kind must not create an interpreter discovery unit" + ); + assert!(matches!( + &units[0], + BatchUnit::NativeBundle { entry, selector_function, execution_mode } + if entry == "bundle.dag" + && selector_function == "bundle_spec" + && *execution_mode == ExecutionMode::Wet + )); + } + #[test] fn grouping_preserves_every_claim_exactly_once() { // Verdict preservation: no claim dropped, duplicated, or invented — grouping only reorders diff --git a/src/v1/stage0/src/std_realization_schedule.rs b/src/v1/stage0/src/std_realization_schedule.rs index 82333fb6ad6..ecb7a0ba805 100644 --- a/src/v1/stage0/src/std_realization_schedule.rs +++ b/src/v1/stage0/src/std_realization_schedule.rs @@ -83,6 +83,7 @@ pub struct RealizationObjective { pub enum WitnessKind { CorpusWitnessKind, ExecutionWitnessKind, + NativeBundleWitnessKind, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -111,10 +112,17 @@ pub fn witness_kind_eq(a: WitnessKind, b: WitnessKind) -> bool { WitnessKind::CorpusWitnessKind => match b.clone() { WitnessKind::CorpusWitnessKind => true, WitnessKind::ExecutionWitnessKind => false, + WitnessKind::NativeBundleWitnessKind => false, }, WitnessKind::ExecutionWitnessKind => match b.clone() { WitnessKind::ExecutionWitnessKind => true, WitnessKind::CorpusWitnessKind => false, + WitnessKind::NativeBundleWitnessKind => false, + }, + WitnessKind::NativeBundleWitnessKind => match b.clone() { + WitnessKind::NativeBundleWitnessKind => true, + WitnessKind::CorpusWitnessKind => false, + WitnessKind::ExecutionWitnessKind => false, }, } } @@ -661,6 +669,8 @@ pub struct CorpusWitnessKind; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct ExecutionWitnessKind; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct NativeBundleWitnessKind; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct RunnableMemoryNegligible; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct RunnableMemorySubstantial; diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index a2fd8aa5324..6e768c3f8dc 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -9427,6 +9427,54 @@ fn eval_emit_host_run_transport_cached_builtin( }); } + run_cached_process_spec( + ctx, + workspace_dir, + &workspace_files, + &build_argvs, + &run_argv, + false, + ) +} + +/// Native-bundle execution seam used by the production selector. The `.dag` selector owns +/// the exact files and argv values; this seed helper only realizes that typed process spec +/// through the same cache/toolchain identity path as `emit_host_run_transport_cached`. +pub fn run_native_bundle_process_cached( + ctx: &InterpContext, + workspace_dir: String, + workspace_files: &[(String, String)], + build_argvs: &[Vec], + run_argv: &[String], +) -> InterpResult { + if !ctx.execution_mode.is_wet_dispatch() { + return Err(InterpError::TypeError { + msg: "native bundle process refuses outside Wet/Record execution mode".to_string(), + }); + } + if build_argvs.iter().any(|argv| argv.is_empty()) || run_argv.is_empty() { + return Err(InterpError::TypeError { + msg: "native bundle process refuses an empty build/run argv".to_string(), + }); + } + run_cached_process_spec( + ctx, + workspace_dir, + workspace_files, + build_argvs, + run_argv, + true, + ) +} + +fn run_cached_process_spec( + ctx: &InterpContext, + workspace_dir: String, + workspace_files: &[(String, String)], + build_argvs: &[Vec], + run_argv: &[String], + require_transition_timing: bool, +) -> InterpResult { let workspace_dir = native_cache_rebase_workspace_dir(workspace_dir); let realization_workspace = std::path::PathBuf::from(&workspace_dir); std::fs::create_dir_all(&realization_workspace).map_err(|e| InterpError::TypeError { @@ -9451,6 +9499,7 @@ fn eval_emit_host_run_transport_cached_builtin( &run_argv, &build_environment, ctx, + require_transition_timing, ) } @@ -9847,15 +9896,27 @@ fn emit_host_run_transport_cached_in_workspace( run_argv: &[String], build_environment: &EmitHostBuildEnvironment, ctx: &InterpContext, + require_transition_timing: bool, ) -> InterpResult { let ready_marker = workspace.join(".native_ready"); + let cold_compile_receipt = workspace.join(".native_cold_compile_nanos"); + let artifact_lookup_started = std::time::Instant::now(); // Cold control (falsifier cadence): widen-only — ignoring the ready marker can // only force a FULL cold rebuild, never skip work (the compile-clean cold-control // pattern). Not an escape hatch: no value of the env makes the run do less. let cold_control = std::env::var("GUNBC_CI_NATIVE_CACHE_COLD_CONTROL") .map(|v| v == "1") .unwrap_or(false); - let compile_skipped = !cold_control && ready_marker.exists(); + let recorded_cold_compile_nanos = std::fs::read_to_string(&cold_compile_receipt) + .ok() + .and_then(|s| s.trim().parse::().ok()) + .filter(|n| *n > 0); + // The timing receipt is part of readiness for the production transition: an old marker + // without its measured cold wall is a warm miss and widens to a rebuild, never a zero. + let compile_skipped = !cold_control + && ready_marker.exists() + && (!require_transition_timing || recorded_cold_compile_nanos.is_some()); + let artifact_lookup_nanos = artifact_lookup_started.elapsed().as_nanos(); eprintln!( "[native-cache] key={} compile_skipped={} cold_control={}", workspace @@ -9872,7 +9933,9 @@ fn emit_host_run_transport_cached_in_workspace( stdout: &[u8], stderr: &[u8], build_log: Vec, - compile_skipped: bool| + compile_skipped: bool, + cold_compile_nanos: u128, + native_execution_nanos: u128| -> Value { Value::Record { type_name: ctx.sym("EmitHostTransportResult"), @@ -9884,6 +9947,18 @@ fn emit_host_run_transport_cached_in_workspace( (ctx.sym("success"), Value::Bool(success)), (ctx.sym("exit_code"), Value::Int(exit_code)), (ctx.sym("compile_skipped"), Value::Bool(compile_skipped)), + ( + ctx.sym("artifact_lookup_nanos"), + Value::Int(artifact_lookup_nanos.min(i64::MAX as u128) as i64), + ), + ( + ctx.sym("cold_compile_nanos"), + Value::Int(cold_compile_nanos.min(i64::MAX as u128) as i64), + ), + ( + ctx.sym("native_execution_nanos"), + Value::Int(native_execution_nanos.min(i64::MAX as u128) as i64), + ), ( ctx.sym("stdout_octets"), list_value( @@ -9925,6 +10000,7 @@ fn emit_host_run_transport_cached_in_workspace( emit_host_materialize_workspace_files(workspace, files)?; let mut build_log: Vec = Vec::new(); + let compile_started = std::time::Instant::now(); for argv in build_argvs { let out = run_command(argv)?; let code = out.status.code().map(i64::from).unwrap_or(-1); @@ -9939,17 +10015,29 @@ fn emit_host_run_transport_cached_in_workspace( &out.stderr, build_log, false, + compile_started.elapsed().as_nanos(), + 0, )); } } + let cold_compile_nanos = compile_started.elapsed().as_nanos(); + let native_started = std::time::Instant::now(); let out = run_command(run_argv)?; + let native_execution_nanos = native_started.elapsed().as_nanos(); let code = out.status.code().map(i64::from).unwrap_or(-1); build_log.push(Value::Str(format!("{} -> exit {code}", run_argv.join(" ")))); if out.status.success() { std::fs::write(&ready_marker, b"1").map_err(|e| InterpError::TypeError { msg: format!("emit_host_run_transport_cached: ready marker write failed: {e}"), })?; + std::fs::write(&cold_compile_receipt, cold_compile_nanos.to_string()).map_err(|e| { + InterpError::TypeError { + msg: format!( + "emit_host_run_transport_cached: cold compile receipt write failed: {e}" + ), + } + })?; } return Ok(transport_result( "run", @@ -9959,10 +10047,14 @@ fn emit_host_run_transport_cached_in_workspace( &out.stderr, build_log, false, + cold_compile_nanos, + native_execution_nanos, )); } + let native_started = std::time::Instant::now(); let out = run_command(run_argv)?; + let native_execution_nanos = native_started.elapsed().as_nanos(); let code = out.status.code().map(i64::from).unwrap_or(-1); let mut build_log: Vec = Vec::new(); build_log.push(Value::Str(format!("{} -> exit {code}", run_argv.join(" ")))); @@ -9974,6 +10066,8 @@ fn emit_host_run_transport_cached_in_workspace( &out.stderr, build_log, true, + recorded_cold_compile_nanos.unwrap_or(0), + native_execution_nanos, )) } diff --git a/src/v2/compiler/native_selected_bundle_process.dag b/src/v2/compiler/native_selected_bundle_process.dag new file mode 100644 index 00000000000..582f40fcbde --- /dev/null +++ b/src/v2/compiler/native_selected_bundle_process.dag @@ -0,0 +1,22 @@ +module v2.compiler.native_selected_bundle_process + +import v2.std.collection { List } +import v2.std.host_transport { MaterializedWorkspaceFile } +import v2.std.integer { Int } +import v2.std.text { String } + +data native_selected_bundle_process_note: String = "Pure selector-to-executor carrier for a content-addressed selected-witness bundle. The .dag selector owns the complete materialized file set, build/run argv, artifact identity, bounded population counts, and expected direct-call stdout. The seed executor may realize exactly this value; it must not infer a missing field or reinterpret an unknown execution kind." + +data native_selected_bundle_process_seed_deferral: String = "§7 seed-retained execution plumbing: claim_executor parses this carrier, dispatches NativeBundleWitnessKind, launches the declared process, and projects the transition receipt in hand Rust. Lane: v1 exit / ROADMAP 'Get hand-written Rust in this repository down to zero'. This is not a new semantic authority: files, argv, identities, population, and expected output are fields above, while the shared emit-host transport remains the effect boundary. Dissolve-on: the executor walk and host-process receipt projection are emitted .dag realizations; then the NativeBundle BatchUnit/parser and run_native_bundle_process_cached seed bridge delete together." + +type NativeSelectedBundleProcessSpec { + workspace_dir: String + bundle_identity: String + selected_count: Int + bundle_count: Int + shard_count: Int + files: List + build: List> + run: List + expected_stdout_octets: List +} diff --git a/src/v2/test/claim/execution/native_selected_witness_bundle_production.dag b/src/v2/test/claim/execution/native_selected_witness_bundle_production.dag new file mode 100644 index 00000000000..d428d63ea6f --- /dev/null +++ b/src/v2/test/claim/execution/native_selected_witness_bundle_production.dag @@ -0,0 +1,125 @@ +module v2.test.execution.native_selected_witness_bundle_production + +import std.content_hash { as_content_hash_structural, serialize_content_hash } +import std.selected_witness_bundle { SelectedWitnessPlan, native_witness_bundle_from_plan } +import std.types { Bool, String } +import extdeps.realization.emit_on_demand_host { + native_cache_workspace_root, + native_cache_realization_workspace_root, +} +import v2.compiler.emit_host { + build_invocation_argvs, + invocation_argv, + emit_host_input_realization_digest, + emit_host_materialized_workspace_files, +} +import v2.compiler.emit_module { EmitFamilyMember, emit_family } +import v2.compiler.native_selected_bundle_process { NativeSelectedBundleProcessSpec } +import v2.extdeps.languages.rust_test { rust_logic_selected_bundle_target_model_staging } +import v2.std.collection { List } +import v2.std.compilers.target_model { runtime_row_from_target } +import v2.std.diagnostic { Accepted, None, Outcome, Rejected } +import v2.test.execution.emit_on_demand_family_crate_witness { + family_crate_alt_members, + family_crate_members, +} +import v2.test.execution.native_selected_witness_bundle { + native_selected_witness_bundle_interpreter_complement_green_holds, + native_selected_witness_bundle_interpreter_complement_wrong_body_oracle_holds, + native_selected_witness_bundle_interpreter_join_green_holds, + native_selected_witness_bundle_interpreter_join_wrong_body_oracle_holds, + native_selected_witness_bundle_interpreter_meet_green_holds, + native_selected_witness_bundle_interpreter_meet_wrong_body_oracle_holds, + selected_logic_alt_plan, + selected_logic_bundle_cache_root, + selected_logic_expected_stdout_octets, + selected_logic_primary_plan, +} + +data native_selected_witness_bundle_production_note: String = "The production selector surface for the bounded three-member logic bundle. It is intentionally outside *_test.dag: CI calls these four entrypoints as production selection/oracle operations, while the selected plans and discriminating fixtures remain owned by native_selected_witness_bundle_test." + +fn selected_logic_process_spec_for( + plan: SelectedWitnessPlan, + members: List, + primary: Bool +) -> Outcome { + let target = rust_logic_selected_bundle_target_model_staging() + match emit_family(members: members, transport_target: target) { + Accepted { value: source, diagnostics: _ } => match runtime_row_from_target(target: target) { + Accepted { value: row, diagnostics: _ } => match build_invocation_argvs( + builds: row.transport.build + ) { + Accepted { value: builds, diagnostics: _ } => match invocation_argv( + inv: row.transport.run + ) { + Accepted { value: run, diagnostics: _ } => { + let files = emit_host_materialized_workspace_files( + workspace: row.transport.workspace, + emitted: source.carried + ) + let bundle = native_witness_bundle_from_plan(plan: plan) + let bundle_key = as_content_hash_structural( + structural: bundle.identity.structural_fingerprint + ) + let workspace_root = native_cache_workspace_root( + cache_root: selected_logic_bundle_cache_root, + key: bundle_key + ) + Accepted { + value: NativeSelectedBundleProcessSpec { + workspace_dir: native_cache_realization_workspace_root( + workspace_root: workspace_root, + realization_digest: emit_host_input_realization_digest( + files: files, + builds: builds + ) + ) + bundle_identity: serialize_content_hash(hash: bundle_key) as String + selected_count: plan.members.count() + bundle_count: 1 + shard_count: 1 + files: files + build: builds + run: run + expected_stdout_octets: selected_logic_expected_stdout_octets(primary: primary) + }, + diagnostics: None + } + } + Rejected { diagnostics: diagnostics } => Rejected { diagnostics: diagnostics } + } + Rejected { diagnostics: diagnostics } => Rejected { diagnostics: diagnostics } + } + Rejected { diagnostics: diagnostics } => Rejected { diagnostics: diagnostics } + } + Rejected { diagnostics: diagnostics } => Rejected { diagnostics: diagnostics } + } +} + +fn native_selected_logic_production_spec() -> Outcome { + selected_logic_process_spec_for( + plan: selected_logic_primary_plan(), + members: family_crate_members(), + primary: true + ) +} + +fn native_selected_logic_planted_red_spec() -> Outcome { + selected_logic_process_spec_for( + plan: selected_logic_alt_plan(), + members: family_crate_alt_members(), + primary: false + ) +} + +fn native_selected_logic_interpreter_oracle_holds() -> Bool { + native_selected_witness_bundle_interpreter_meet_green_holds() + && native_selected_witness_bundle_interpreter_join_green_holds() + && native_selected_witness_bundle_interpreter_complement_green_holds() +} + +fn native_selected_logic_planted_red_oracle_holds() -> Bool { + native_selected_witness_bundle_interpreter_meet_wrong_body_oracle_holds() + && native_selected_witness_bundle_interpreter_join_wrong_body_oracle_holds() + && native_selected_witness_bundle_interpreter_complement_wrong_body_oracle_holds() +} diff --git a/src/v2/test/claim/execution/native_selected_witness_bundle_test.dag b/src/v2/test/claim/execution/native_selected_witness_bundle_test.dag index fa8f59b3b31..82f41788bef 100644 --- a/src/v2/test/claim/execution/native_selected_witness_bundle_test.dag +++ b/src/v2/test/claim/execution/native_selected_witness_bundle_test.dag @@ -460,18 +460,22 @@ fn selected_logic_stdout(receipt: EmitHostRunReceipt) -> Optional { } fn selected_logic_expected_stdout(primary: Bool) -> ByteString { + emit_host_octets_byte_string(octets: selected_logic_expected_stdout_octets(primary: primary)) +} + +fn selected_logic_expected_stdout_octets(primary: Bool) -> List { if primary { - emit_host_octets_byte_string(octets: [ + [ 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 - ]) + ] } else { - emit_host_octets_byte_string(octets: [ + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 - ]) + ] } } diff --git a/src/v2/test/claim/pr_native_batch_test.dag b/src/v2/test/claim/pr_native_batch_test.dag index 59a95a13f7e..4d4188e5c89 100644 --- a/src/v2/test/claim/pr_native_batch_test.dag +++ b/src/v2/test/claim/pr_native_batch_test.dag @@ -6,17 +6,16 @@ import v2.workflow.ci_floor_plan { gunbc_ci_floor_ordinary_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 } +import std.realization_schedule { NativeBundleWitnessKind } -test fn witness_zero_routed_families_enrolled() -> Bool { - (length(xs: native_routed_rows()) == 0) - && !gunbc_pr_native_batch_enrolled() - && (length(xs: gunbc_pr_native_entries()) == 0) +test fn witness_selected_native_bundle_enrolled() -> Bool { + gunbc_pr_native_batch_enrolled() + && (length(xs: gunbc_pr_native_entries()) == 1) + && gunbc_pr_native_entries().first().kind == NativeBundleWitnessKind } -test fn witness_floor_batches_unchanged_when_unenrolled() -> Bool { - length(xs: gunbc_ci_floor_ordinary_batches()) == length(xs: gunbc_ci_floor_realization_plan().schedule) +test fn witness_floor_appends_one_selected_native_batch() -> Bool { + length(xs: gunbc_ci_floor_ordinary_batches()) == length(xs: gunbc_ci_floor_realization_plan().schedule) + 1 } - diff --git a/src/v2/workflow/ci_floor_plan.dag b/src/v2/workflow/ci_floor_plan.dag index b08eadaaf53..c19c4063b9c 100644 --- a/src/v2/workflow/ci_floor_plan.dag +++ b/src/v2/workflow/ci_floor_plan.dag @@ -10,7 +10,6 @@ import v2.compiler.self_host.wet_receipt_enrollment { falsifier_self_host_wet_known_red_batch_enrolled, falsifier_self_host_wet_known_red_roster } -import v2.compiler.self_host.native_routing_frontier { native_routed_rows, NativeRoutingFrontierRow } import gunbc.ci_materialization { ci_floor_declared_resolve_count } import gunbc.ci_spec { gunbc_ci_spec, gunbc_ci_regen_spec, CiSpec, @@ -58,7 +57,7 @@ import std.realization_schedule { RunnableSingleClaim, RunnableDiscoveryBatch, ScheduleWitnessEntry, - WitnessKind, CorpusWitnessKind, ExecutionWitnessKind, + WitnessKind, CorpusWitnessKind, ExecutionWitnessKind, NativeBundleWitnessKind, RunnableResourceProfile, runnable_resource_profile, runnable_resource_profile_negligible, @@ -175,6 +174,7 @@ fn entry_kind_is_execution(w: ScheduleWitnessEntry) -> Bool { match w.kind { ExecutionWitnessKind => true CorpusWitnessKind => false + NativeBundleWitnessKind => true } } @@ -1127,22 +1127,14 @@ fn gunbc_falsifier_cadence_witness_batch() -> Runnable { } } -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." +data gunbc_pr_native_batch_note: String = "Production selected-entry native bundle, slice 1 (2026-08-02): the complete bounded population is meet, join, and complement from std.selected_witness_bundle's SelectedWitnessPlan. One NativeBundleWitnessKind row names the pure .dag process-spec selector; claim_executor preserves that kind and launches one content-addressed Rust bundle whose main directly calls all three members. The interpreter remains an explicitly timed equivalence oracle, and a separately content-addressed all-wrong bundle is the live planted RED. Artifact refusal falls only through the handler's counted typed fallback receipt, never through kind parsing. Scale to the next stable shard when either generated closure exceeds 32 members or measured cold compile / peak cgroup memory exceeds twice this slice's recorded baseline; those are observable code-generation and closure-scaling triggers, not a universal-bundle promise." 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 - } - ]) - } - ) + [ScheduleWitnessEntry { + entry: "src/v2/test/claim/execution/native_selected_witness_bundle_production.dag" + function: "native_selected_logic_production_spec" + kind: NativeBundleWitnessKind + }] } fn gunbc_pr_native_batch_enrolled() -> Bool { @@ -1161,7 +1153,7 @@ fn gunbc_pr_native_batch() -> Runnable { heavy_whole_tree_resolve: false, spawns_host_compiler: true, memory: runnable_memory_substantial(), - execution_mode: Hermetic + execution_mode: Wet ) } } From b47cd5d51c2adaa261737cb764245a098be46be7 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 15:44:52 +0000 Subject: [PATCH 03/13] Model transition receipt memory as ByteSize --- dag/std/selected_witness_bundle.dag | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dag/std/selected_witness_bundle.dag b/dag/std/selected_witness_bundle.dag index 269762da8d8..7eb62369c65 100644 --- a/dag/std/selected_witness_bundle.dag +++ b/dag/std/selected_witness_bundle.dag @@ -2,6 +2,7 @@ module std.selected_witness_bundle import std.types { NonEmptyStr, List, Int, Bool } import std.verification { NanosecondDuration } +import std.measure { ByteSize } import std.content_hash { Fnv1a64Structural, content_hash_atom, @@ -330,8 +331,8 @@ type NativeWitnessProductionTransitionReceipt { native_execution_wall_nanos: NanosecondDuration interpreter_oracle_wall_nanos: NanosecondDuration fallback_count: Int - rss_peak_bytes: Int - cgroup_peak_bytes: Int + rss_peak_bytes: ByteSize + cgroup_peak_bytes: ByteSize verdict: NativeProductionTransitionVerdict planted_red_equivalent: Bool } @@ -345,8 +346,6 @@ fn native_production_transition_population_holds( && receipt.native_count + receipt.interpreted_count == receipt.selected_count && receipt.unavailable_count == receipt.fallback_count && receipt.fallback_count <= receipt.interpreted_count - && receipt.rss_peak_bytes >= 0 - && receipt.cgroup_peak_bytes >= 0 } type NativeBundleFamilyCutoverEvidence { From 526fc2867d848d59a1271ca49f1475e94358a3c0 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 16:09:13 +0000 Subject: [PATCH 04/13] Refuse fallback without planted red equivalence --- src/v1/stage0/src/bin/claim_executor.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/v1/stage0/src/bin/claim_executor.rs b/src/v1/stage0/src/bin/claim_executor.rs index e6f676f956a..6c45b3853fe 100644 --- a/src/v1/stage0/src/bin/claim_executor.rs +++ b/src/v1/stage0/src/bin/claim_executor.rs @@ -1623,6 +1623,16 @@ fn write_native_transition_receipt(body: &str) -> Result<(), String> { fs::write(path, body).map_err(|e| format!("native transition receipt write: {e}")) } +fn native_transition_decision( + native_ok: bool, + oracle_green: bool, + planted_red_equivalent: bool, +) -> (bool, bool) { + let accepted = native_ok && oracle_green && planted_red_equivalent; + let fallback = !native_ok && oracle_green && planted_red_equivalent; + (accepted, fallback) +} + fn run_native_bundle_unit( source_roots: &[String], entry: String, @@ -1696,8 +1706,8 @@ fn run_native_bundle_unit( .zip(planted_native.as_ref().ok()) .map(|(spec, obs)| obs.success && obs.stdout == spec.expected_stdout && planted_oracle) .unwrap_or(false); - let accepted = native_ok && oracle_green && planted_red_equivalent; - let fallback = !native_ok && oracle_green; + let (accepted, fallback) = + native_transition_decision(native_ok, oracle_green, planted_red_equivalent); let selected = primary.selected_count; let native_count = if native_ok { selected } else { 0 }; let interpreted_count = if native_ok { 0 } else { selected }; @@ -7845,6 +7855,15 @@ mod tests { )); } + #[test] + fn native_bundle_fallback_requires_planted_red_equivalence() { + assert_eq!( + native_transition_decision(false, true, false), + (false, false) + ); + assert_eq!(native_transition_decision(false, true, true), (false, true)); + } + #[test] fn grouping_preserves_every_claim_exactly_once() { // Verdict preservation: no claim dropped, duplicated, or invented — grouping only reorders From d3d74a2bb26e28475ad932d4f6c9573f5cbd9ff2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 16:17:26 +0000 Subject: [PATCH 05/13] WIP: Production selector cutover into the native execution kind (post-#7599 s --- dag/gunbc/ci_spec.dag | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dag/gunbc/ci_spec.dag b/dag/gunbc/ci_spec.dag index 35e9c2e0130..419ad2eb2ca 100644 --- a/dag/gunbc/ci_spec.dag +++ b/dag/gunbc/ci_spec.dag @@ -204,12 +204,15 @@ type FloorBatchClamp { data gunbc_ci_floor_batch_clamp_note: String = "DERIVED per-batch wall clamp (Piece 3, ci-two-tier-placement-redesign.md §9.8, operator 2026-07-24). Supersedes the hand-set gunbc_ci_floor_batch_wall_budget_seconds list (deleted; its two operator-signed raises 1320->1440->1680 are the static-era history kept in gunbc_ci_floor_batch_wall_budget_note): a scalar wall budget conflated workload size (affected-set selection is diff-proportional BY DESIGN, ~5x swing), host speed (±20% fleet envelope), and the quantity actually worth bounding (per-unit cost creep). The clamp re-denominates — per batch, clamp_ms = overhead_seconds*1000 + runtime_unit_count * per_unit_ms — computed by claim_executor from THIS authority plus the affected-set-selected unit count it alone knows (the schedule holds one opaque discovery runnable; the witness count is runtime, not schedule data). Rows are index-aligned to gunbc_ci_floor_batches (the length-match witness pins the alignment, mirroring the deleted list's discipline). The load-bearing row is the discovery witness batch (index 2): overhead 300s + 1000ms/witness, so a full corpus of ~2316 witnesses clamps at ~44min (under the 55-min step cap, ~1.6x the ~25-min healthy wall) while every legitimate observed full-corpus wall (1344-1629s) passes, and a runaway reds proportionally instead of at the fixed 1680s that the two hand-raises had to keep chasing. Fixed-count gate batches carry per_unit_ms 0 (their count does not vary, so overhead IS the clamp) at their measured basis. Index 3 (wet corpora) stays a fixed overhead pending a wet-per-witness rate from the D2 probe — a declared calibration gap, not a hidden default. SIGNED CONSTANTS (operator, 2026-07-24): the witness aggregate coefficient 1000ms and the discovery overhead 300s; the per-WITNESS hard max is NOT redefined here — it stays the single fast-lane authority gunbc_ci_fast_lane_eval_budget_ms (5s). BASIS OF THE 1000ms COEFFICIENT (operator, 2026-07-24): the aggregate coefficient is denominated against the observed 0.58-0.70 s/witness (the 1344-1629s full-corpus fleet envelope over ~2316 witnesses) on the srv fleet host class (arm64 self-hosted, capped runners) at the adaptive governor's realized worker width. Naming host-class-x-worker-width as the basis makes a future width or fleet change a DELIBERATE re-sign of this constant (s/witness re-denominates when the fleet or width moves), never a rediscovered fleet-wide red; the ~1.4-1.7x headroom the 1000ms average carries over the observed top rate IS the >=~1.6x runaway the clamp is sized to catch, and sub-threshold creep below that ratio is owned by the gauntlet's per-cadence s/unit receipt (not this clamp). RAISE DISCIPLINE (carried from gunbc_ci_floor_batch_wall_budget_note): raising any overhead or rate requires an appended dated operator-signed line naming the run id and the enrollment that grew the batch; tightening may land by ordinary receipt note; unit counts need no signature (the schedule computes them). The clamp is interim mechanics — the structural wall is the complexity lens (§8, cost <= a + b*n asserted at compile time), and the clamp demotes to host-pathology backstop when that lens goes Blocking. The 55-min step cap stays the absolute backstop for the total floor wall; GUNBC_FLOOR_BATCH_BUDGET_TIGHTEN_MS lowers the COMPUTED clamp (min), never raises — the RED-control hook, never an escape hatch.OPERATOR-SIGNED RAISE (briansrls, 2026-07-25): batch 4 (row index [3]) 420 -> 540 seconds, +28.6 percent. THE MARGIN RULING THIS INSTANTIATES, signed once for the budget FAMILY rather than re-litigated per incident: a clamp was doing double duty as merge-refusal threshold ('this must not merge') and growth detector ('something got slower - look'). Tight margins serve the second job and demonstrably worked - the perturb row's 53 -> 141s growth was caught precisely because the clamp was tight - but they make the FIRST job fire on host roulette, and a breach that means 'you landed on srv2-02' trains the on-call to rerun, which is the crying-wolf failure mode wearing budget clothes. POLICY: clamps are sized to cover MEASURED fleet spread, so a breach means content grew, never which host answered. The growth-detector job moves to per-row trend receipts on the falsifier cadence (row grew >2x against its dated basis = a counted drift receipt), which is what makes a larger clamp margin safe - sensitivity is preserved at row grain while merge-refusal stops firing on variance. BASIS OF 540: post-re-home projection 377s (the worst of the two observed walls, 613864ms on srv2-02, minus the ~237s of eval the six re-homed rows carried) x 1.2 worst observed fleet spread = ~452s, + ~20 percent policy margin = 540 (whole-minute grain, 9min). RUN IDS: 30148859947 @ 619bba5 wall_ms=613864 units=74 host srv2-02; 30163496549 @ 9f87967 wall_ms=571556 units=74 host srv3-01 - identical content, 7.5 percent apart, which IS the spread this raise funds. THE ENROLLMENT THAT GREW THE BATCH: none - and as with the batch-3 raises, that mismatch with this discipline's template IS the receipt. Batch 4 SHRANK this cycle (six rows re-homed to FalsifierCadenceJob, units 74 -> 68); the raise buys spread coverage on a batch that got smaller, not headroom for growth. WHY THIS IS NOT THE FORBIDDEN WIDEN: batch 4's per_unit_ms is 0, which this note ALREADY declares 'a fixed overhead pending a wet-per-witness rate from the D2 probe - a declared calibration gap, not a hidden default'; 540 funds that gap with an honest, dated, dissolving interim instead of leaving the flat rate to fire on host variance. It refuses exactly as before - only the threshold moved, and it moved on a stated measurement, not to make a red go away. HOST SPREAD IS NOT WEATHER and has a named owner: srv1/srv2 still run the pre-#7213 sccache units and are typed expected-latent-defective until re-provisioned (the A1/reach gap), so part of the 7.5-20 percent collapses when the fleet lane re-converges them; this margin covers the genuine hardware-heterogeneity residue, eventually the machine-shape lane's. DISSOLVE-ON: the dag_compile_clean_perturb_receipts_holds diagnosis lands (141s, 38 percent of the remaining batch; if the growth is the cold-spawn / per-entry-reconcile class the wasted_ms=166525 reading supports, returning it toward its 53s basis puts worst case near 350s - under even the retired 420) AND the per-unit rate replaces the flat clamp from the D2 probe; then this row recalibrates by ordinary receipt note under the tightening rule. SAME DISEASE, NOT YET DOSED: gunbc_falsifier_self_host_wet_receipt_wall_budget (600s, the 707s falsifier red) rests on a ten-day-stale basis with zero spread allowance. The margin POLICY above governs it too, but the NUMBER is deliberately not moved here - it is gated on its own sccache-vs-growth attribution, so that dosing lands with that measurement rather than by analogy. WORKER COUNTER-SIGNATURE (claude, 2026-07-25, per this discipline's dated-line requirement): I ran the dissolve-on diagnosis and it REFUTES the mechanism this note hypothesised. The growth is NOT the cold-spawn / per-entry-reconcile class the wasted_ms=166525 reading suggested. Measured by execution on the perturb spawn shape (trivial 1-module compile, 4 source roots) there are TWO independent corpus-denominated costs, in different places. (A) THE CENSUS, inside reconcile: main.rs:491-514 reads every indexed module outside the closure off disk into census_only_sources, and v1_compiler_compile.rs:2580 parse_census_fill_sources parses all ~2543 of them BETWEEN compile.normalize.done and compile.reconcile.done - so it books to the reconcile bin and reads as 'reconcile is slow' when it is a whole-tree parse wearing reconcile's label. ~23s local, ~12-13s on fleet. (B) THE POLICY TAIL, after the compile: cli_run.rs:2105 compile_clean_unlisted_import_use_blocks_from_policy calls default_source_roots() (WHOLE TREE) + resolve_entry_graph_shared to evaluate ONE nullary Bool fn. ~34-42s, once per process, and INDEPENDENT of what was compiled - proven by running the same module with only its own source root: zero pool, all phases 0ms, still 42.4s wall. THE ASYMMETRY that closes the arithmetic: main.rs:566/598 exit(1) on hard diagnostics, so a RED compile never reaches the gate (measured 27.4s total, ~2s tail) while a GREEN compile pays it in full (57.8s total, ~34s tail). The perturb row makes 4 spawns, 2 red and 2 green: ~2x14.5s + ~2x60s = ~149s against the measured 148495.7ms. Pre-#7179 that same row is 4 spawns x census-only = ~52s, which IS the 53s basis. So cost B is the ENTIRE 53->148s regression (~94s of the 148s) and cost A was always present. CONSEQUENCE FOR THIS ROW: the note's projected 'near 350s' still holds directionally but by a different mechanism - fixing B alone returns the row to ~55s, so worst case lands well under even the retired 420 and the 540 becomes pure spread coverage, which is what this note already says it is for. NO BISECT WAS RUN AND NONE IS NEEDED: the three-run measurement attributes the split directly, so the bisect across #7178/#7179 named in the probe plan is superseded work (DESIGN 2 - redundant work is not free just because it would confirm). DISSOLVE-ON, unchanged in shape but now half-discharged: the diagnosis half is DONE (this line); recalibration still waits on the cost-B fix landing (scope the policy resolve to the policy module's own import closure) plus the D2 wet-per-witness rate replacing per_unit_ms 0 on this row.ROW REMOVAL (claude, 2026-07-26, D3b gate flips): two rows DELETED from the tail, 7 -> 5, because their batches no longer exist — SourceRootIngestGate and SelfHostReadsRealBytesGate moved to the falsifier cadence (gunbc.commit_workflow gate_gauntlet_flip_basis_note), and each occupied a batch of its own. This is not a budget change: no surviving row's numbers moved, so no re-signature is owed under the raise discipline above. WHICH TWO, and why the obvious answer was wrong: the removed rows are the LAST two (600s and 420s), NOT the 120s/600s pair a reading of the schedule order suggests. Verified by execution rather than inferred — emit_host_gate_passes sits at batch index 4 BOTH before and after the flip, which is only possible if the two vanished batches were at indices 5 and 6, after it. The 120s row at index 4 is emit_host's and survives. RECORDED BECAUSE THE ALIGNMENT IS POSITIONAL AND HAND-MAINTAINED: an index-aligned list carries no evidence of which row belongs to which batch, so a plausible-but-wrong deletion here is silent — it mis-clamps a surviving batch and reads as a passing length check. The length witness (witness_floor_batch_clamp_params_cover_schedule) proves the COUNT and cannot prove the MAPPING; that gap is the standing argument for deriving these rows from the schedule rather than pairing them by position." +data gunbc_ci_native_bundle_batch_clamp_basis_note: String = "NATIVE BUNDLE ROW (index 5, operator ruling via Dispatch A->C, 2026-08-02): the production selector enrollment adds one isolated fixed-count batch, so the positional clamp table must add exactly one companion row; co-locating it with an unrelated batch is rejected because that would obscure co-residency and the transition memory receipt. Measured acceptance basis: batch wall 77.020s for three selected members; cold compile 367209379ns, warm artifact lookup 8040ns, native execution 39332338ns, and interpreter oracle 17407839ns. The fixed 125s overhead is the observed whole-batch wall times the family's 1.6x fleet-spread factor, rounded up to a whole five seconds (1.62x measured), and per_unit_ms stays 0 because slice 1 has a fixed three-member population with an explicit next-tranche scaling trigger. Memory basis: RSS peak 4801241088 bytes and cgroup peak 11940978688 bytes. The Runnable remains Substantial and isolated, preserving the measured 7.14GB gap between process RSS and cgroup peak rather than disguising that footprint through co-residence. The clamp bounds wall admission; the memory governor remains the fail-closed capacity authority." + data gunbc_ci_floor_batch_clamp_params: List = [ FloorBatchClamp { overhead_seconds: 240, per_unit_ms: 0 }, FloorBatchClamp { overhead_seconds: 60, per_unit_ms: 0 }, FloorBatchClamp { overhead_seconds: 300, per_unit_ms: 1000 }, FloorBatchClamp { overhead_seconds: 540, per_unit_ms: 0 }, - FloorBatchClamp { overhead_seconds: 120, per_unit_ms: 0 } + FloorBatchClamp { overhead_seconds: 120, per_unit_ms: 0 }, + FloorBatchClamp { overhead_seconds: 125, per_unit_ms: 0 } ] data gunbc_ci_compile_clean_clamp_note: String = "COMPILE-CLEAN LEG CLAMP (prelude coverage, first slice): discharges the compile-clean portion of gunbc_ci_floor_batch_clamp_note FOLLOW-UP ROW (a) — the eager compile-clean install ran OUTSIDE every batch budget and could only red at the step cap, which is how a 15m32s green gate grew past 49 minutes across #7398/#7438 with nothing naming the growth (typecheck-perf investigation, PR #7490). Same shape as the batch clamps: clamp_ms = overhead_seconds*1000 + closure_units * per_unit_ms, where closure_units is the compiled closure's MODULE COUNT — a runtime fact of the scope disposition (whole-tree ~2725 today, affected-set proportional to the diff), so the clamp re-denominates with scope exactly as batch clamps re-denominate with the affected set. Over-clamp is FLOOR-COMPILE-CLEAN-OVER-BUDGET: a typed, located walk refusal (admission grain — the compile receipt's ok is untouched, per the signed admission/verdict split in gunbc_ci_floor_batch_wall_budget_note); never a rerun, never a widen. RED-control hook GUNBC_FLOOR_COMPILE_CLEAN_BUDGET_TIGHTEN_MS lowers the computed clamp (min), never raises. GROWTH DETECTION at row grain is NOT this clamp's job (the family margin ruling, 2026-07-25): per-row 2x drift against dated basis rows rides gunbc.witness_row_cost's comparator over dag/gunbc/compile_clean_cost_basis.tsv — [compile-clean-cost] pass + module_typecheck rows, basis rows citing arm64 fleet run ids only, BasisAbsent counted until seeded from a cited run's own receipt lines (the #7475 seeding pattern; an empty basis must count loudly, never read as no-drift). BASIS OF THE CONSTANTS (worker-sized, 2026-07-31, from run 30602520347 @ 0ecb898, host srv1-01 arm64, post-#7490 fixes): whole-tree pass 258s over the ~1648-unit whole-tree entry closure (units = the leg's compiled closure module count, receipted by the first [compile-clean-cost] execution — NOT the ~2725-file module index, which overcounts by pool files outside every entry closure) = ~157ms/unit observed; per_unit_ms 320 is ~2x that rate, funding a full 2x fleet-spread host on top of the observed wall (the family margin ruling: a breach means content grew, never which host answered; pre-fix completing runs spread ~1.8x across hosts) — the batch family's 1000ms coefficient carries 1.4-1.7x the same way; overhead 60s covers the closure-size-independent tail (census fill parse ~13s fleet + governor arm). Whole-tree clamp = 60s + 1648*320ms = ~587s (~2.3x the observed 258s fleet wall). MECHANISM RECEIPTS (local x86, logic-not-cost host): green e2e via gunbc_ci_plan_artifact_plan — pass 310127ms/1648 units, WithinBudget, 1204 module rows, drift basis_absent=1205 counted, exit 0 (run at the pre-resize 200ms sizing; the arm proof is arithmetic-independent and the formula is witness-pinned at the final constants); RED control via GUNBC_FLOOR_COMPILE_CLEAN_BUDGET_TIGHTEN_MS=1 receipted beside it. DISPATCH: operator direction this session ('can we add the budget gating ... i suggest we share that model' — briansrls, 2026-07-31). OPERATOR SIGNATURE (briansrls, 2026-07-31): the worker-sized constants are affirmed as proposed — overhead_seconds 60, per_unit_ms 320 ('the clamp constants you chose are fine, please proceed') — so the refusal arm is signed-live per the family raise discipline; TIGHTENING may still land by ordinary receipt note, and the first fleet observations should tighten per_unit_ms toward the measured rate." From b75a6db4aea494f3f84f751d79d759e4af93218c Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sun, 2 Aug 2026 16:40:33 +0000 Subject: [PATCH 06/13] Keep native transition counts verdict-honest --- dag/std/selected_witness_bundle.dag | 22 +++++++++++++--- src/v1/stage0/src/bin/claim_executor.rs | 35 ++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/dag/std/selected_witness_bundle.dag b/dag/std/selected_witness_bundle.dag index 7eb62369c65..8c6733c290e 100644 --- a/dag/std/selected_witness_bundle.dag +++ b/dag/std/selected_witness_bundle.dag @@ -343,9 +343,25 @@ fn native_production_transition_population_holds( receipt.selected_count > 0 && receipt.bundle_count == 1 && receipt.shard_count == 1 - && receipt.native_count + receipt.interpreted_count == receipt.selected_count - && receipt.unavailable_count == receipt.fallback_count - && receipt.fallback_count <= receipt.interpreted_count + && receipt.native_count >= 0 + && receipt.interpreted_count >= 0 + && receipt.unavailable_count >= 0 + && receipt.fallback_count >= 0 + && match receipt.verdict { + NativeProductionTransitionAccepted => + receipt.native_count == receipt.selected_count + && receipt.interpreted_count == 0 + && receipt.unavailable_count == 0 + && receipt.fallback_count == 0 + NativeProductionTransitionFallback { cause: _ } => + receipt.native_count + receipt.interpreted_count == receipt.selected_count + && receipt.unavailable_count == receipt.fallback_count + && receipt.fallback_count <= receipt.interpreted_count + NativeProductionTransitionRefused { reason: _ } => + receipt.native_count + receipt.interpreted_count <= receipt.selected_count + && receipt.unavailable_count <= receipt.selected_count + && receipt.fallback_count <= receipt.interpreted_count + } } type NativeBundleFamilyCutoverEvidence { diff --git a/src/v1/stage0/src/bin/claim_executor.rs b/src/v1/stage0/src/bin/claim_executor.rs index 6c45b3853fe..f7ac4cb032e 100644 --- a/src/v1/stage0/src/bin/claim_executor.rs +++ b/src/v1/stage0/src/bin/claim_executor.rs @@ -1633,6 +1633,23 @@ fn native_transition_decision( (accepted, fallback) } +fn native_transition_population_counts( + selected: u64, + native_ok: bool, + fallback: bool, +) -> (u64, u64, u64, u64) { + let native_count = if native_ok { selected } else { 0 }; + let interpreted_count = if fallback { selected } else { 0 }; + let unavailable_count = if native_ok { 0 } else { selected }; + let fallback_count = if fallback { selected } else { 0 }; + ( + native_count, + interpreted_count, + unavailable_count, + fallback_count, + ) +} + fn run_native_bundle_unit( source_roots: &[String], entry: String, @@ -1709,10 +1726,8 @@ fn run_native_bundle_unit( let (accepted, fallback) = native_transition_decision(native_ok, oracle_green, planted_red_equivalent); let selected = primary.selected_count; - let native_count = if native_ok { selected } else { 0 }; - let interpreted_count = if native_ok { 0 } else { selected }; - let unavailable_count = if native_ok { 0 } else { selected }; - let fallback_count = unavailable_count; + let (native_count, interpreted_count, unavailable_count, fallback_count) = + native_transition_population_counts(selected, native_ok, fallback); let cold_compile_wall = cold .as_ref() .ok() @@ -7862,6 +7877,18 @@ mod tests { (false, false) ); assert_eq!(native_transition_decision(false, true, true), (false, true)); + assert_eq!( + native_transition_population_counts(3, true, false), + (3, 0, 0, 0) + ); + assert_eq!( + native_transition_population_counts(3, false, true), + (0, 3, 3, 3) + ); + assert_eq!( + native_transition_population_counts(3, false, false), + (0, 0, 3, 0) + ); } #[test] From dec4a666e69814ca0fb859d90e291d563edd3907 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 17:10:52 +0000 Subject: [PATCH 07/13] Merge main into the cutover slice: adopt RunnableBatchClamp typed-unit rows (+ index-5 native row), compose ScopedWitnessBatch beside NativeBundle Three conflicts, all compositions of independent additions: - ci_spec.dag: main (#7569) re-modeled the clamp table as RunnableBatchClamp with typed second/millisecond units; the native batch's companion row (125s, operator-ruled basis note kept) is re-expressed in that shape. - claim_executor.rs runnable fold: keep the guarded Discovery + NativeBundle partition, add main's ScopedWitnessBatch -> ScopedDiscovery arm beside it. - claim_executor.rs function census arm: Discovery | ScopedDiscovery | NativeBundle all non-function units in one arm. Co-Authored-By: Claude Fable 5 --- src/v1/stage0/src/bin/claim_executor.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/v1/stage0/src/bin/claim_executor.rs b/src/v1/stage0/src/bin/claim_executor.rs index 803bb5ce6ea..3aa4493c456 100644 --- a/src/v1/stage0/src/bin/claim_executor.rs +++ b/src/v1/stage0/src/bin/claim_executor.rs @@ -1712,7 +1712,6 @@ fn claim_result_for_outcome( } } -<<<<<<< HEAD #[derive(Clone)] struct NativeBundleProcessSpec { workspace_dir: String, @@ -2084,14 +2083,15 @@ fn run_native_bundle_unit( corpus_witnesses: selected as usize, witness_row_costs: Vec::new(), budget_refusal: None, -======= + } +} + fn scoped_execution_authority_source_roots( authority: ScopedWitnessExecutionAuthority, walk_source_roots: &[String], ) -> Vec { match authority { ScopedWitnessExecutionAuthority::InheritedWalkSourceRoots => walk_source_roots.to_vec(), ->>>>>>> origin/main } } @@ -9203,12 +9203,9 @@ mod tests { BatchUnit::UnrunnableSentinel { function } => { out.push((String::new(), function.clone())); } -<<<<<<< HEAD - BatchUnit::Discovery { .. } => {} - BatchUnit::NativeBundle { .. } => {} -======= - BatchUnit::Discovery { .. } | BatchUnit::ScopedDiscovery { .. } => {} ->>>>>>> origin/main + BatchUnit::Discovery { .. } + | BatchUnit::ScopedDiscovery { .. } + | BatchUnit::NativeBundle { .. } => {} } } out From 90c8aae0fff414dd9002357357170b08e573fb6c Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 17:42:17 +0000 Subject: [PATCH 08/13] Integrate main into the cutover slice: native-bundle wire-codec arms, re-pin the floor-append witness on the base plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Main's #7569 landed a WitnessKind wire codec (scoped_witness_kind_label/_from_label) whose exhaustive matches would not compile against the new NativeBundleWitnessKind variant — the closed-coproduct wall working as designed. Fixed in the dag authority (native-bundle arms in both directions) and regenerated stage0 (divergence 0). witness_floor_appends_one_selected_native_batch red on the merged tree for two reasons: gunbc_ci_floor_realization_plan().schedule is now defined AS gunbc_ci_floor_ordinary_batches() (x == x + 1 unsatisfiable), and ordinary batches additionally append one batch per scoped_witness_batches row. Re-pinned against the base plan gunbc_ci_floor_realization_plan_for(spec: gunbc_ci_spec) plus the scoped count, keeping +1-native the discriminated quantity. Both enrollment witnesses green by execution. Co-Authored-By: Claude Fable 5 --- Cargo.lock | 19 +++++++++++ Cargo.toml | 1 + dag/std/realization_schedule.dag | 3 ++ src/v1/stage0/src/std_realization_schedule.rs | 7 +++- src/v1/stage0_emit_core/Cargo.toml | 1 + src/v1/stage0_extdeps_base/Cargo.toml | 15 +++++++++ src/v1/stage0_extdeps_base/src/lib.rs | 33 +++++++++++++++++++ src/v1/stage0_extdeps_languages/Cargo.toml | 1 + src/v1/stage0_extdeps_languages/src/lib.rs | 1 + src/v1/stage0_std_core/src/lib.rs | 21 ------------ src/v1/stage0_std_surface/src/lib.rs | 3 -- src/v1/stage0_v1_artifact/Cargo.toml | 1 + src/v1/stage0_v1_artifact/src/lib.rs | 1 + src/v1/stage0_v1_infer/Cargo.toml | 1 + src/v1/stage0_v1_infer/src/lib.rs | 4 +-- src/v2/test/claim/pr_native_batch_test.dag | 6 ++-- 16 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 src/v1/stage0_extdeps_base/Cargo.toml create mode 100644 src/v1/stage0_extdeps_base/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f0bd2ca5e81..82b6da508b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,6 +873,7 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", + "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", @@ -881,6 +882,21 @@ dependencies = [ "v1-stage0-v1-infer", ] +[[package]] +name = "v1-stage0-extdeps-base" +version = "0.1.0" +dependencies = [ + "im", + "serde", + "serde_json", + "stacker", + "unicode-ident", + "unicode-properties", + "v1-stage0-runtime", + "v1-stage0-std-core", + "v1-stage0-std-surface", +] + [[package]] name = "v1-stage0-extdeps-languages" version = "0.1.0" @@ -891,6 +907,7 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", + "v1-stage0-extdeps-base", "v1-stage0-runtime", "v1-stage0-std-core", "v1-stage0-std-surface", @@ -945,6 +962,7 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", + "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", @@ -962,6 +980,7 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", + "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", diff --git a/Cargo.toml b/Cargo.toml index 26c137814f0..1c025b41e56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "src/v1/stage0_runtime", "src/v1/stage0_std_core", "src/v1/stage0_std_surface", + "src/v1/stage0_extdeps_base", "src/v1/stage0_extdeps_languages", "src/v1/stage0_v1_infer", "src/v1/stage0_v1_artifact", diff --git a/dag/std/realization_schedule.dag b/dag/std/realization_schedule.dag index 223a41b6f34..6f57b2e595e 100644 --- a/dag/std/realization_schedule.dag +++ b/dag/std/realization_schedule.dag @@ -301,6 +301,7 @@ fn scoped_witness_kind_label(kind: WitnessKind) -> String { match kind { CorpusWitnessKind => "corpus" ExecutionWitnessKind => "execution" + NativeBundleWitnessKind => "native-bundle" } } @@ -309,6 +310,8 @@ fn scoped_witness_kind_from_label(label: String) -> WitnessKind? { Present { value: CorpusWitnessKind } } else if label == "execution" { Present { value: ExecutionWitnessKind } + } else if label == "native-bundle" { + Present { value: NativeBundleWitnessKind } } else { none } diff --git a/src/v1/stage0/src/std_realization_schedule.rs b/src/v1/stage0/src/std_realization_schedule.rs index fc2bbe70810..c74aaa3257d 100644 --- a/src/v1/stage0/src/std_realization_schedule.rs +++ b/src/v1/stage0/src/std_realization_schedule.rs @@ -611,6 +611,7 @@ pub fn scoped_witness_kind_label(kind: WitnessKind) -> String { match kind.clone() { WitnessKind::CorpusWitnessKind => "corpus".to_string(), WitnessKind::ExecutionWitnessKind => "execution".to_string(), + WitnessKind::NativeBundleWitnessKind => "native-bundle".to_string(), } } @@ -621,7 +622,11 @@ pub fn scoped_witness_kind_from_label(label: String) -> Option { if (label.clone() == "execution".to_string()) { Some(WitnessKind::ExecutionWitnessKind) } else { - None + if (label.clone() == "native-bundle".to_string()) { + Some(WitnessKind::NativeBundleWitnessKind) + } else { + None + } } } } diff --git a/src/v1/stage0_emit_core/Cargo.toml b/src/v1/stage0_emit_core/Cargo.toml index e1d52a050ca..a75ed8ddfe0 100644 --- a/src/v1/stage0_emit_core/Cargo.toml +++ b/src/v1/stage0_emit_core/Cargo.toml @@ -13,6 +13,7 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } +v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } v1-stage0-v1-infer = { path = "../stage0_v1_infer" } v1-stage0-v1-artifact = { path = "../stage0_v1_artifact" } diff --git a/src/v1/stage0_extdeps_base/Cargo.toml b/src/v1/stage0_extdeps_base/Cargo.toml new file mode 100644 index 00000000000..283638642d3 --- /dev/null +++ b/src/v1/stage0_extdeps_base/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "v1-stage0-extdeps-base" +version = "0.1.0" +edition = "2021" + +[dependencies] +stacker = "0.1" +im = { version = "15.1", features = ["serde"] } +serde = { version = "1", features = ["derive", "rc"] } +serde_json = "1" +unicode-ident = "1" +unicode-properties = { version = "0.1", features = ["emoji"] } +v1-stage0-runtime = { path = "../stage0_runtime" } +v1-stage0-std-core = { path = "../stage0_std_core" } +v1-stage0-std-surface = { path = "../stage0_std_surface" } diff --git a/src/v1/stage0_extdeps_base/src/lib.rs b/src/v1/stage0_extdeps_base/src/lib.rs new file mode 100644 index 00000000000..6e76c2be71a --- /dev/null +++ b/src/v1/stage0_extdeps_base/src/lib.rs @@ -0,0 +1,33 @@ +//! Generated by regen_stage0 -- do not edit. +//! +//! Layered core crate in the derived stage0 partition. +//! +//! Owns its module bodies via path includes and re-exports lower partition +//! crates so `crate::` references in generated modules keep resolving. + +#![allow( + unused_imports, + unused_variables, + unused_mut, + unused_parens, + dead_code, + non_shorthand_field_patterns, + suspicious_double_ref_op, + clippy::all +)] +#![deny(unreachable_patterns)] +#![recursion_limit = "256"] + +pub use v1_stage0_runtime::*; +pub use v1_stage0_std_core::*; +pub use v1_stage0_std_surface::*; + +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_container_oci_digest.rs"] +pub mod extdeps_container_oci_digest; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_external_authority.rs"] +pub mod extdeps_external_authority; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_uri.rs"] +pub mod extdeps_uri; diff --git a/src/v1/stage0_extdeps_languages/Cargo.toml b/src/v1/stage0_extdeps_languages/Cargo.toml index 4326d899d31..aebd0d35b42 100644 --- a/src/v1/stage0_extdeps_languages/Cargo.toml +++ b/src/v1/stage0_extdeps_languages/Cargo.toml @@ -13,3 +13,4 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } +v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } diff --git a/src/v1/stage0_extdeps_languages/src/lib.rs b/src/v1/stage0_extdeps_languages/src/lib.rs index 6affc3bd7c3..87ed4023547 100644 --- a/src/v1/stage0_extdeps_languages/src/lib.rs +++ b/src/v1/stage0_extdeps_languages/src/lib.rs @@ -18,6 +18,7 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] +pub use v1_stage0_extdeps_base::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; pub use v1_stage0_std_surface::*; diff --git a/src/v1/stage0_std_core/src/lib.rs b/src/v1/stage0_std_core/src/lib.rs index a346b8c1a90..243fa83828c 100644 --- a/src/v1/stage0_std_core/src/lib.rs +++ b/src/v1/stage0_std_core/src/lib.rs @@ -87,26 +87,5 @@ pub mod std_iteration; #[path = "../../stage0/src/std_graph.rs"] pub mod std_graph; #[rustfmt::skip] -#[path = "../../stage0/src/extdeps_uri.rs"] -pub mod extdeps_uri; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_external_authority.rs"] -pub mod extdeps_external_authority; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_container_oci_digest.rs"] -pub mod extdeps_container_oci_digest; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_units_dimensionless.rs"] -pub mod extdeps_units_dimensionless; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_units_iec_80000_13.rs"] -pub mod extdeps_units_iec_80000_13; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_units_iso8601.rs"] -pub mod extdeps_units_iso8601; -#[rustfmt::skip] -#[path = "../../stage0/src/std_occurrence_identity.rs"] -pub mod std_occurrence_identity; -#[rustfmt::skip] #[path = "../../stage0/src/v1_std_core.rs"] pub mod v1_std_core; diff --git a/src/v1/stage0_std_surface/src/lib.rs b/src/v1/stage0_std_surface/src/lib.rs index 2bb14eca190..a8c445e2994 100644 --- a/src/v1/stage0_std_surface/src/lib.rs +++ b/src/v1/stage0_std_surface/src/lib.rs @@ -36,6 +36,3 @@ pub mod std_pareto; #[rustfmt::skip] #[path = "../../stage0/src/std_realization_schedule.rs"] pub mod std_realization_schedule; -#[rustfmt::skip] -#[path = "../../stage0/src/std_trait_derive_shape.rs"] -pub mod std_trait_derive_shape; diff --git a/src/v1/stage0_v1_artifact/Cargo.toml b/src/v1/stage0_v1_artifact/Cargo.toml index 071afe4e901..8260fda60f2 100644 --- a/src/v1/stage0_v1_artifact/Cargo.toml +++ b/src/v1/stage0_v1_artifact/Cargo.toml @@ -13,5 +13,6 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } +v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } v1-stage0-v1-infer = { path = "../stage0_v1_infer" } diff --git a/src/v1/stage0_v1_artifact/src/lib.rs b/src/v1/stage0_v1_artifact/src/lib.rs index 9e631f31e19..e48b08ffbd9 100644 --- a/src/v1/stage0_v1_artifact/src/lib.rs +++ b/src/v1/stage0_v1_artifact/src/lib.rs @@ -18,6 +18,7 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] +pub use v1_stage0_extdeps_base::*; pub use v1_stage0_extdeps_languages::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; diff --git a/src/v1/stage0_v1_infer/Cargo.toml b/src/v1/stage0_v1_infer/Cargo.toml index e6771854fd0..ceece26e924 100644 --- a/src/v1/stage0_v1_infer/Cargo.toml +++ b/src/v1/stage0_v1_infer/Cargo.toml @@ -13,4 +13,5 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } +v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } diff --git a/src/v1/stage0_v1_infer/src/lib.rs b/src/v1/stage0_v1_infer/src/lib.rs index f9286473a97..ff69009ab09 100644 --- a/src/v1/stage0_v1_infer/src/lib.rs +++ b/src/v1/stage0_v1_infer/src/lib.rs @@ -18,6 +18,7 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] +pub use v1_stage0_extdeps_base::*; pub use v1_stage0_extdeps_languages::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; @@ -33,9 +34,6 @@ pub mod v1_compiler_infer_env; #[path = "../../stage0/src/v1_compiler_infer_items.rs"] pub mod v1_compiler_infer_items; #[rustfmt::skip] -#[path = "../../stage0/src/v1_compiler_infer_occurrence_binding.rs"] -pub mod v1_compiler_infer_occurrence_binding; -#[rustfmt::skip] #[path = "../../stage0/src/v1_compiler_infer_service.rs"] pub mod v1_compiler_infer_service; #[rustfmt::skip] diff --git a/src/v2/test/claim/pr_native_batch_test.dag b/src/v2/test/claim/pr_native_batch_test.dag index 4d4188e5c89..49907fbb1b6 100644 --- a/src/v2/test/claim/pr_native_batch_test.dag +++ b/src/v2/test/claim/pr_native_batch_test.dag @@ -4,8 +4,10 @@ import v2.workflow.ci_floor_plan { gunbc_pr_native_entries, gunbc_pr_native_batch_enrolled, gunbc_ci_floor_ordinary_batches, - gunbc_ci_floor_realization_plan + gunbc_ci_floor_realization_plan_for } +import gunbc.ci_layer_roots { scoped_witness_batches } +import gunbc.ci_spec { gunbc_ci_spec } import v2.std.algebra { length } import v2.std.logic { Bool } import std.realization_schedule { NativeBundleWitnessKind } @@ -17,5 +19,5 @@ test fn witness_selected_native_bundle_enrolled() -> Bool { } test fn witness_floor_appends_one_selected_native_batch() -> Bool { - length(xs: gunbc_ci_floor_ordinary_batches()) == length(xs: gunbc_ci_floor_realization_plan().schedule) + 1 + length(xs: gunbc_ci_floor_ordinary_batches()) == length(xs: gunbc_ci_floor_realization_plan_for(spec: gunbc_ci_spec).schedule) + length(xs: scoped_witness_batches) + 1 } From e49235d75add9e19ee16efd9f6a4c8685af42c0b Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 18:15:52 +0000 Subject: [PATCH 09/13] Repair the stale stage0 crate partition: regenerate with a freshly built seed (review 47484) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous head's regen ran with a stale regen_stage0 binary and committed a half-completed partition — a new v1-stage0-extdeps-base crate holding three modules while extdeps_units_*/std_occurrence_identity/std_trait_derive_shape/ v1_compiler_infer_occurrence_binding were dropped from their crates without relocation, breaking the partition workspace members (cursor review 47484) and redding CI's regen self-host gate ('Stage0 split crate boundary files are stale'). Regenerated in the correct order (build seed from committed tree -> regen -> rebuild -> --verify divergence 0): the partition reverts to the derived state, stage0_extdeps_base leaves the workspace and is deleted. cargo check --workspace green; fmt clean. Also softens the native_selected_bundle_process carrier note per review 47480: the planted-red twin and oracle names are seed convention today, not carrier fields — declared honestly with the existing dissolve-on. Co-Authored-By: Claude Fable 5 --- Cargo.lock | 19 ----------- Cargo.toml | 1 - src/v1/stage0_emit_core/Cargo.toml | 1 - src/v1/stage0_extdeps_base/Cargo.toml | 15 --------- src/v1/stage0_extdeps_base/src/lib.rs | 33 ------------------- src/v1/stage0_extdeps_languages/Cargo.toml | 1 - src/v1/stage0_extdeps_languages/src/lib.rs | 1 - src/v1/stage0_std_core/src/lib.rs | 21 ++++++++++++ src/v1/stage0_std_surface/src/lib.rs | 3 ++ src/v1/stage0_v1_artifact/Cargo.toml | 1 - src/v1/stage0_v1_artifact/src/lib.rs | 1 - src/v1/stage0_v1_infer/Cargo.toml | 1 - src/v1/stage0_v1_infer/src/lib.rs | 4 ++- .../native_selected_bundle_process.dag | 2 +- 14 files changed, 28 insertions(+), 76 deletions(-) delete mode 100644 src/v1/stage0_extdeps_base/Cargo.toml delete mode 100644 src/v1/stage0_extdeps_base/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 82b6da508b2..f0bd2ca5e81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,7 +873,6 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", - "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", @@ -882,21 +881,6 @@ dependencies = [ "v1-stage0-v1-infer", ] -[[package]] -name = "v1-stage0-extdeps-base" -version = "0.1.0" -dependencies = [ - "im", - "serde", - "serde_json", - "stacker", - "unicode-ident", - "unicode-properties", - "v1-stage0-runtime", - "v1-stage0-std-core", - "v1-stage0-std-surface", -] - [[package]] name = "v1-stage0-extdeps-languages" version = "0.1.0" @@ -907,7 +891,6 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", - "v1-stage0-extdeps-base", "v1-stage0-runtime", "v1-stage0-std-core", "v1-stage0-std-surface", @@ -962,7 +945,6 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", - "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", @@ -980,7 +962,6 @@ dependencies = [ "stacker", "unicode-ident", "unicode-properties", - "v1-stage0-extdeps-base", "v1-stage0-extdeps-languages", "v1-stage0-runtime", "v1-stage0-std-core", diff --git a/Cargo.toml b/Cargo.toml index 1c025b41e56..26c137814f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ members = [ "src/v1/stage0_runtime", "src/v1/stage0_std_core", "src/v1/stage0_std_surface", - "src/v1/stage0_extdeps_base", "src/v1/stage0_extdeps_languages", "src/v1/stage0_v1_infer", "src/v1/stage0_v1_artifact", diff --git a/src/v1/stage0_emit_core/Cargo.toml b/src/v1/stage0_emit_core/Cargo.toml index a75ed8ddfe0..e1d52a050ca 100644 --- a/src/v1/stage0_emit_core/Cargo.toml +++ b/src/v1/stage0_emit_core/Cargo.toml @@ -13,7 +13,6 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } -v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } v1-stage0-v1-infer = { path = "../stage0_v1_infer" } v1-stage0-v1-artifact = { path = "../stage0_v1_artifact" } diff --git a/src/v1/stage0_extdeps_base/Cargo.toml b/src/v1/stage0_extdeps_base/Cargo.toml deleted file mode 100644 index 283638642d3..00000000000 --- a/src/v1/stage0_extdeps_base/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "v1-stage0-extdeps-base" -version = "0.1.0" -edition = "2021" - -[dependencies] -stacker = "0.1" -im = { version = "15.1", features = ["serde"] } -serde = { version = "1", features = ["derive", "rc"] } -serde_json = "1" -unicode-ident = "1" -unicode-properties = { version = "0.1", features = ["emoji"] } -v1-stage0-runtime = { path = "../stage0_runtime" } -v1-stage0-std-core = { path = "../stage0_std_core" } -v1-stage0-std-surface = { path = "../stage0_std_surface" } diff --git a/src/v1/stage0_extdeps_base/src/lib.rs b/src/v1/stage0_extdeps_base/src/lib.rs deleted file mode 100644 index 6e76c2be71a..00000000000 --- a/src/v1/stage0_extdeps_base/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Generated by regen_stage0 -- do not edit. -//! -//! Layered core crate in the derived stage0 partition. -//! -//! Owns its module bodies via path includes and re-exports lower partition -//! crates so `crate::` references in generated modules keep resolving. - -#![allow( - unused_imports, - unused_variables, - unused_mut, - unused_parens, - dead_code, - non_shorthand_field_patterns, - suspicious_double_ref_op, - clippy::all -)] -#![deny(unreachable_patterns)] -#![recursion_limit = "256"] - -pub use v1_stage0_runtime::*; -pub use v1_stage0_std_core::*; -pub use v1_stage0_std_surface::*; - -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_container_oci_digest.rs"] -pub mod extdeps_container_oci_digest; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_external_authority.rs"] -pub mod extdeps_external_authority; -#[rustfmt::skip] -#[path = "../../stage0/src/extdeps_uri.rs"] -pub mod extdeps_uri; diff --git a/src/v1/stage0_extdeps_languages/Cargo.toml b/src/v1/stage0_extdeps_languages/Cargo.toml index aebd0d35b42..4326d899d31 100644 --- a/src/v1/stage0_extdeps_languages/Cargo.toml +++ b/src/v1/stage0_extdeps_languages/Cargo.toml @@ -13,4 +13,3 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } -v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } diff --git a/src/v1/stage0_extdeps_languages/src/lib.rs b/src/v1/stage0_extdeps_languages/src/lib.rs index 87ed4023547..6affc3bd7c3 100644 --- a/src/v1/stage0_extdeps_languages/src/lib.rs +++ b/src/v1/stage0_extdeps_languages/src/lib.rs @@ -18,7 +18,6 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] -pub use v1_stage0_extdeps_base::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; pub use v1_stage0_std_surface::*; diff --git a/src/v1/stage0_std_core/src/lib.rs b/src/v1/stage0_std_core/src/lib.rs index 243fa83828c..a346b8c1a90 100644 --- a/src/v1/stage0_std_core/src/lib.rs +++ b/src/v1/stage0_std_core/src/lib.rs @@ -87,5 +87,26 @@ pub mod std_iteration; #[path = "../../stage0/src/std_graph.rs"] pub mod std_graph; #[rustfmt::skip] +#[path = "../../stage0/src/extdeps_uri.rs"] +pub mod extdeps_uri; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_external_authority.rs"] +pub mod extdeps_external_authority; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_container_oci_digest.rs"] +pub mod extdeps_container_oci_digest; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_units_dimensionless.rs"] +pub mod extdeps_units_dimensionless; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_units_iec_80000_13.rs"] +pub mod extdeps_units_iec_80000_13; +#[rustfmt::skip] +#[path = "../../stage0/src/extdeps_units_iso8601.rs"] +pub mod extdeps_units_iso8601; +#[rustfmt::skip] +#[path = "../../stage0/src/std_occurrence_identity.rs"] +pub mod std_occurrence_identity; +#[rustfmt::skip] #[path = "../../stage0/src/v1_std_core.rs"] pub mod v1_std_core; diff --git a/src/v1/stage0_std_surface/src/lib.rs b/src/v1/stage0_std_surface/src/lib.rs index a8c445e2994..2bb14eca190 100644 --- a/src/v1/stage0_std_surface/src/lib.rs +++ b/src/v1/stage0_std_surface/src/lib.rs @@ -36,3 +36,6 @@ pub mod std_pareto; #[rustfmt::skip] #[path = "../../stage0/src/std_realization_schedule.rs"] pub mod std_realization_schedule; +#[rustfmt::skip] +#[path = "../../stage0/src/std_trait_derive_shape.rs"] +pub mod std_trait_derive_shape; diff --git a/src/v1/stage0_v1_artifact/Cargo.toml b/src/v1/stage0_v1_artifact/Cargo.toml index 8260fda60f2..071afe4e901 100644 --- a/src/v1/stage0_v1_artifact/Cargo.toml +++ b/src/v1/stage0_v1_artifact/Cargo.toml @@ -13,6 +13,5 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } -v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } v1-stage0-v1-infer = { path = "../stage0_v1_infer" } diff --git a/src/v1/stage0_v1_artifact/src/lib.rs b/src/v1/stage0_v1_artifact/src/lib.rs index e48b08ffbd9..9e631f31e19 100644 --- a/src/v1/stage0_v1_artifact/src/lib.rs +++ b/src/v1/stage0_v1_artifact/src/lib.rs @@ -18,7 +18,6 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] -pub use v1_stage0_extdeps_base::*; pub use v1_stage0_extdeps_languages::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; diff --git a/src/v1/stage0_v1_infer/Cargo.toml b/src/v1/stage0_v1_infer/Cargo.toml index ceece26e924..e6771854fd0 100644 --- a/src/v1/stage0_v1_infer/Cargo.toml +++ b/src/v1/stage0_v1_infer/Cargo.toml @@ -13,5 +13,4 @@ unicode-properties = { version = "0.1", features = ["emoji"] } v1-stage0-runtime = { path = "../stage0_runtime" } v1-stage0-std-core = { path = "../stage0_std_core" } v1-stage0-std-surface = { path = "../stage0_std_surface" } -v1-stage0-extdeps-base = { path = "../stage0_extdeps_base" } v1-stage0-extdeps-languages = { path = "../stage0_extdeps_languages" } diff --git a/src/v1/stage0_v1_infer/src/lib.rs b/src/v1/stage0_v1_infer/src/lib.rs index ff69009ab09..f9286473a97 100644 --- a/src/v1/stage0_v1_infer/src/lib.rs +++ b/src/v1/stage0_v1_infer/src/lib.rs @@ -18,7 +18,6 @@ #![deny(unreachable_patterns)] #![recursion_limit = "256"] -pub use v1_stage0_extdeps_base::*; pub use v1_stage0_extdeps_languages::*; pub use v1_stage0_runtime::*; pub use v1_stage0_std_core::*; @@ -34,6 +33,9 @@ pub mod v1_compiler_infer_env; #[path = "../../stage0/src/v1_compiler_infer_items.rs"] pub mod v1_compiler_infer_items; #[rustfmt::skip] +#[path = "../../stage0/src/v1_compiler_infer_occurrence_binding.rs"] +pub mod v1_compiler_infer_occurrence_binding; +#[rustfmt::skip] #[path = "../../stage0/src/v1_compiler_infer_service.rs"] pub mod v1_compiler_infer_service; #[rustfmt::skip] diff --git a/src/v2/compiler/native_selected_bundle_process.dag b/src/v2/compiler/native_selected_bundle_process.dag index 582f40fcbde..0bc9b52c2de 100644 --- a/src/v2/compiler/native_selected_bundle_process.dag +++ b/src/v2/compiler/native_selected_bundle_process.dag @@ -5,7 +5,7 @@ import v2.std.host_transport { MaterializedWorkspaceFile } import v2.std.integer { Int } import v2.std.text { String } -data native_selected_bundle_process_note: String = "Pure selector-to-executor carrier for a content-addressed selected-witness bundle. The .dag selector owns the complete materialized file set, build/run argv, artifact identity, bounded population counts, and expected direct-call stdout. The seed executor may realize exactly this value; it must not infer a missing field or reinterpret an unknown execution kind." +data native_selected_bundle_process_note: String = "Pure selector-to-executor carrier for a content-addressed selected-witness bundle. The .dag selector owns the complete materialized file set, build/run argv, artifact identity, bounded population counts, and expected direct-call stdout. The seed executor may realize exactly this value; it must not infer a missing field or reinterpret an unknown execution kind. HONEST SCOPE (review 47480): today there is a single production spec, and the planted-red twin plus the two oracle fn names are bound by seed convention in run_native_bundle_unit rather than declared on this carrier — slice-1 scaffold coupling that dissolves with the seed deferral below (the executor walk emitting from .dag), or earlier by widening the carrier to declare the twin/oracle references." data native_selected_bundle_process_seed_deferral: String = "§7 seed-retained execution plumbing: claim_executor parses this carrier, dispatches NativeBundleWitnessKind, launches the declared process, and projects the transition receipt in hand Rust. Lane: v1 exit / ROADMAP 'Get hand-written Rust in this repository down to zero'. This is not a new semantic authority: files, argv, identities, population, and expected output are fields above, while the shared emit-host transport remains the effect boundary. Dissolve-on: the executor walk and host-process receipt projection are emitted .dag realizations; then the NativeBundle BatchUnit/parser and run_native_bundle_process_cached seed bridge delete together." From 2ed8a0e5c7766c512702ac329e64d4fd05f5d7f1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 18:43:26 +0000 Subject: [PATCH 10/13] WIP: Dispatch A->C --- dag/std/selected_witness_bundle.dag | 2 + src/v2/test/claim/pr_native_batch_test.dag | 44 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/dag/std/selected_witness_bundle.dag b/dag/std/selected_witness_bundle.dag index 8c6733c290e..5071b759638 100644 --- a/dag/std/selected_witness_bundle.dag +++ b/dag/std/selected_witness_bundle.dag @@ -337,6 +337,8 @@ type NativeWitnessProductionTransitionReceipt { planted_red_equivalent: Bool } +data native_production_transition_population_note: String = "🟡 The population law is a VALIDATOR over the flat-count receipt (review 47496): counts and verdict are authored separately, so an inconsistent pair is representable and this fn is what discriminates it. Executing consumers: the witness-unit controls in v2.test.claim.pr_native_batch_test — an accepted positive control plus discriminating REDs per verdict arm, enrolled in per-PR discovery. The seed's TSV transition-receipt projection does not yet route through this law; that wire belongs to native_selected_bundle_process_seed_deferral. dissolve-on: counts carried on the verdict variants so an inconsistent receipt is unwritable, or the executor walk emitting receipts from .dag — whichever lands first; then this validator and this note delete together." + fn native_production_transition_population_holds( receipt: NativeWitnessProductionTransitionReceipt ) -> Bool { diff --git a/src/v2/test/claim/pr_native_batch_test.dag b/src/v2/test/claim/pr_native_batch_test.dag index 49907fbb1b6..4dd076c980b 100644 --- a/src/v2/test/claim/pr_native_batch_test.dag +++ b/src/v2/test/claim/pr_native_batch_test.dag @@ -11,6 +11,17 @@ import gunbc.ci_spec { gunbc_ci_spec } import v2.std.algebra { length } import v2.std.logic { Bool } import std.realization_schedule { NativeBundleWitnessKind } +import std.selected_witness_bundle { + NativeWitnessProductionTransitionReceipt, + NativeProductionTransitionVerdict, + NativeProductionTransitionAccepted, + NativeProductionTransitionFallback, + NativeRealizationAbsent, + native_production_transition_population_holds +} +import std.verification { nanosecond_duration } +import std.measure { byte_size } +import std.types { Int } test fn witness_selected_native_bundle_enrolled() -> Bool { gunbc_pr_native_batch_enrolled() @@ -21,3 +32,36 @@ test fn witness_selected_native_bundle_enrolled() -> Bool { test fn witness_floor_appends_one_selected_native_batch() -> Bool { length(xs: gunbc_ci_floor_ordinary_batches()) == length(xs: gunbc_ci_floor_realization_plan_for(spec: gunbc_ci_spec).schedule) + length(xs: scoped_witness_batches) + 1 } + +fn native_transition_receipt_fixture(selected: Int, native: Int, interpreted: Int, unavailable: Int, fallback: Int, verdict: NativeProductionTransitionVerdict) -> NativeWitnessProductionTransitionReceipt { + NativeWitnessProductionTransitionReceipt { + selected_count: selected, + native_count: native, + interpreted_count: interpreted, + unavailable_count: unavailable, + bundle_count: 1, + shard_count: 1, + cold_compile_wall_nanos: nanosecond_duration(count: 367000000), + warm_artifact_hit_wall_nanos: nanosecond_duration(count: 8000), + native_execution_wall_nanos: nanosecond_duration(count: 39000000), + interpreter_oracle_wall_nanos: nanosecond_duration(count: 17000000), + fallback_count: fallback, + rss_peak_bytes: byte_size(count: 0), + cgroup_peak_bytes: byte_size(count: 0), + verdict: verdict, + planted_red_equivalent: true + } +} + +test fn witness_native_transition_population_law_accepts_green_receipt() -> Bool { + native_production_transition_population_holds(receipt: native_transition_receipt_fixture(selected: 3, native: 3, interpreted: 0, unavailable: 0, fallback: 0, verdict: NativeProductionTransitionAccepted)) +} + +test fn witness_native_transition_population_law_RED_accepted_with_shortfall() -> Bool { + !native_production_transition_population_holds(receipt: native_transition_receipt_fixture(selected: 3, native: 2, interpreted: 0, unavailable: 0, fallback: 0, verdict: NativeProductionTransitionAccepted)) +} + +test fn witness_native_transition_population_law_fallback_arm_discriminates() -> Bool { + native_production_transition_population_holds(receipt: native_transition_receipt_fixture(selected: 3, native: 2, interpreted: 1, unavailable: 1, fallback: 1, verdict: NativeProductionTransitionFallback { cause: NativeRealizationAbsent })) + && !native_production_transition_population_holds(receipt: native_transition_receipt_fixture(selected: 3, native: 2, interpreted: 0, unavailable: 1, fallback: 1, verdict: NativeProductionTransitionFallback { cause: NativeRealizationAbsent })) +} From 6362ff2ec69b57191a4a87170452a5e87caf97a1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 20:07:42 +0000 Subject: [PATCH 11/13] Count the enrolled native batch in the enrolled-set preservation witness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit witness_floor_schedule_preserves_enrolled_set redded on CI (run 30762089274): gunbc_ci_floor_ordinary_batches appends the selected native batch when the frontier enrolls it, but gunbc_ci_floor_enrolled_runnable_labels_for still projected only gates + corpus + scoped batches, so the length check failed by exactly the appended batch. The enrolled side now appends the same runnable's label under the same gunbc_pr_native_batch_enrolled() condition the schedule uses — one enrollment authority read by both sides. ci_floor_plan_witnesses, ci_corpus_discovery_flip_witnesses, and the native pair green by execution. Co-Authored-By: Claude Fable 5 --- src/v2/workflow/ci_floor_plan.dag | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/v2/workflow/ci_floor_plan.dag b/src/v2/workflow/ci_floor_plan.dag index d1bb9d9161f..fd20d1e38ef 100644 --- a/src/v2/workflow/ci_floor_plan.dag +++ b/src/v2/workflow/ci_floor_plan.dag @@ -362,7 +362,12 @@ fn gunbc_ci_floor_enrolled_runnable_labels_for(spec: CiSpec) -> List { let corpus_labels = list_map(xs: corpus_plan_nodes(spec: spec), f: fn(node) { runnable_single_claim_function(r: runnable_for_node(node: node, spec: spec)) }) - concat(concat(gate_labels, corpus_labels), map(scoped_witness_batches, batch => "__scoped_witness_batch__")) + let spec_labels = concat(concat(gate_labels, corpus_labels), map(scoped_witness_batches, batch => "__scoped_witness_batch__")) + if gunbc_pr_native_batch_enrolled() { + list_snoc_item(xs: spec_labels, item: runnable_single_claim_function(r: gunbc_pr_native_batch())) + } else { + spec_labels + } } fn gunbc_ci_floor_schedule_runnable_labels(batches: List>) -> List { From 9a80249ce30208f03dd39a3c056bcb675a75824f Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 21:24:57 +0000 Subject: [PATCH 12/13] Fallback arms on native outage, never divergence; transport causes reach the wire (CI receipt run 30764923923) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The floor redded on srv4-03 with all 3 selected members unavailable and verdict refused:equivalence_or_planted_red — review 47508's advisory made real: fallback required the planted RED's NATIVE run to succeed, which in a native-toolchain outage it cannot, so the counted-fallback arm was unreachable in exactly the outage it was modeled for (NativeProductionTransitionFallback { cause: NativeUnavailableCause }), and a toolchain outage became a hard floor red with its cause dropped on the floor. Split the folded bit: DIVERGENCE (native ran, produced undeclared output) still hard-refuses — an auto-pick would mask it, per the bundle note's 'divergence is a hard refusal, never an auto-pick'. OUTAGE (transport refused or process failed) arms the counted fallback when the interpreter oracle is green AND the planted RED's ORACLE discriminates — the discriminating-RED evidence for the thing actually consumed under fallback. Acceptance keeps the full native bar including planted-red native equivalence. New verdict string refused:native_divergence separates the classes; the cold/warm/planted transport causes now print to stderr and ride the FAIL/fallback detail (the TSV receipt shape is unchanged — it is a parsed contract). Seed tests cover outage-fallback, no-discrimination-no-fallback, divergence-never-fallback, and the acceptance bar. Co-Authored-By: Claude Fable 5 --- src/v1/stage0/src/bin/claim_executor.rs | 111 ++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 8 deletions(-) diff --git a/src/v1/stage0/src/bin/claim_executor.rs b/src/v1/stage0/src/bin/claim_executor.rs index 3aa4493c456..b50fb2a949a 100644 --- a/src/v1/stage0/src/bin/claim_executor.rs +++ b/src/v1/stage0/src/bin/claim_executor.rs @@ -1928,13 +1928,31 @@ fn write_native_transition_receipt(body: &str) -> Result<(), String> { fs::write(path, body).map_err(|e| format!("native transition receipt write: {e}")) } +/// Acceptance and fallback are gated on DIFFERENT planted-red evidence, and the +/// difference is the outage/divergence split (CI receipt run 30764923923, review 47508's +/// advisory made real: srv4-03's native toolchain refused, the planted RED's native run +/// therefore also refused, and the old gate — fallback requires planted-red NATIVE +/// equivalence — made the counted-fallback arm unreachable in exactly the outage it was +/// modeled for, turning a toolchain outage into a hard floor red). +/// +/// - ACCEPTED (native-consumed) still requires the full native bar: native ran green +/// twice, the interpreter oracle agrees, and the planted RED built and reproduced its +/// wrong output natively (planted_red_equivalent). +/// - FALLBACK (counted interpretation) arms only on an OUTAGE — the native transport +/// refused or its process failed — never on a DIVERGENCE (native ran successfully but +/// produced unexpected output: that is the hard-refusal class, an auto-pick would mask +/// it). The discriminating-RED evidence for the thing actually being consumed (the +/// interpreter oracle) is the planted RED's ORACLE discriminating; demanding the +/// planted NATIVE run in an outage would demand the outage not exist. fn native_transition_decision( native_ok: bool, + native_diverged: bool, oracle_green: bool, + planted_oracle_discriminates: bool, planted_red_equivalent: bool, ) -> (bool, bool) { let accepted = native_ok && oracle_green && planted_red_equivalent; - let fallback = !native_ok && oracle_green && planted_red_equivalent; + let fallback = !native_ok && !native_diverged && oracle_green && planted_oracle_discriminates; (accepted, fallback) } @@ -2022,14 +2040,56 @@ fn run_native_bundle_unit( let native_ok = matches!((&cold, &warm), (Ok(c), Ok(w)) if c.success && w.success && w.compile_skipped && c.stdout == primary.expected_stdout && w.stdout == primary.expected_stdout); + // Divergence = the native realization RAN (process success) and produced output the + // spec did not declare. Distinct from an outage (transport Err / process failure): + // divergence hard-refuses, outage is fallback-eligible. + let leg_diverged = |leg: &Result| matches!(leg, Ok(obs) if obs.success && obs.stdout != primary.expected_stdout); + let native_diverged = leg_diverged(&cold) || leg_diverged(&warm); let planted_red_equivalent = planted .as_ref() .ok() .zip(planted_native.as_ref().ok()) .map(|(spec, obs)| obs.success && obs.stdout == spec.expected_stdout && planted_oracle) .unwrap_or(false); - let (accepted, fallback) = - native_transition_decision(native_ok, oracle_green, planted_red_equivalent); + let (accepted, fallback) = native_transition_decision( + native_ok, + native_diverged, + oracle_green, + planted_oracle, + planted_red_equivalent, + ); + // The transport causes are the located half of any non-accepted verdict; dropping + // them made CI's outage red opaque (run 30764923923 refused with no cause on the + // wire). Rendered into the FAIL/fallback detail and stderr, never into the TSV + // receipt (its shape is a parsed contract). + let leg_cause = |name: &str, leg: &Result| match leg { + Ok(obs) if obs.success && obs.stdout == primary.expected_stdout => None, + Ok(obs) if obs.success => Some(format!( + "{name}: ran but diverged (stdout {} bytes != expected {} bytes)", + obs.stdout.len(), + primary.expected_stdout.len() + )), + Ok(_) => Some(format!("{name}: process failed")), + Err(e) => Some(format!("{name}: {e}")), + }; + let transport_causes: Vec = [ + leg_cause("cold", &cold), + leg_cause("warm", &warm), + match &planted_native { + Ok(obs) if obs.success => None, + Ok(_) => Some("planted-native: process failed".to_string()), + Err(e) => Some(format!("planted-native: {e}")), + }, + ] + .into_iter() + .flatten() + .collect(); + if !transport_causes.is_empty() { + eprintln!( + "[native-selected-bundle] transport causes: {}", + transport_causes.join(" | ") + ); + } let selected = primary.selected_count; let (native_count, interpreted_count, unavailable_count, fallback_count) = native_transition_population_counts(selected, native_ok, fallback); @@ -2054,6 +2114,8 @@ fn run_native_bundle_unit( "accepted" } else if fallback { "fallback:native_realization_refused" + } else if native_diverged { + "refused:native_divergence" } else { "refused:equivalence_or_planted_red" }; @@ -2072,9 +2134,15 @@ fn run_native_bundle_unit( detail: if accepted { receipt } else if fallback { - format!("counted native fallback; {receipt}") + format!( + "counted native fallback ({}); {receipt}", + transport_causes.join(" | ") + ) } else { - format!("native transition refused; {receipt}") + format!( + "native transition refused ({}); {receipt}", + transport_causes.join(" | ") + ) }, wall_nanos: started.elapsed().as_nanos(), resolve_nanos, @@ -9265,12 +9333,39 @@ mod tests { } #[test] - fn native_bundle_fallback_requires_planted_red_equivalence() { + fn native_bundle_fallback_arms_on_outage_never_divergence() { + // Outage (no divergence), interpreter oracle green, planted-red ORACLE + // discriminates: counted fallback — even though the planted NATIVE run also + // failed (planted_red_equivalent=false), because in an outage it must. + assert_eq!( + native_transition_decision(false, false, true, true, false), + (false, true) + ); + // Same outage but the planted-red oracle does NOT discriminate: no fallback — + // the thing we would fall back to has no proven RED. + assert_eq!( + native_transition_decision(false, false, true, false, false), + (false, false) + ); + // Divergence (native ran, wrong output): NEVER fallback, regardless of oracles. + assert_eq!( + native_transition_decision(false, true, true, true, true), + (false, false) + ); + // Oracle red: neither acceptance nor fallback. + assert_eq!( + native_transition_decision(false, false, false, true, false), + (false, false) + ); + // Full native bar: accepted requires planted-red NATIVE equivalence. + assert_eq!( + native_transition_decision(true, false, true, true, true), + (true, false) + ); assert_eq!( - native_transition_decision(false, true, false), + native_transition_decision(true, false, true, true, false), (false, false) ); - assert_eq!(native_transition_decision(false, true, true), (false, true)); assert_eq!( native_transition_population_counts(3, true, false), (3, 0, 0, 0) From a97899e0127771a04e28d4fdb4ebb1006c610dd1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 2 Aug 2026 22:31:05 +0000 Subject: [PATCH 13/13] Consciously raise ci_floor_declared_resolve_count 1 -> 2: the enrolled native batch is an escaping entry class (Receipt 9, CI run 30767841790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The floor gate worked as designed: run 30767841790's batch 6 PASSED via the counted outage fallback (transport causes located on the wire), and the sole red was FLOOR-FINALIZATION-REFUSED resolve count 2 != declared 1 — gunbc_pr_native_batch is a RunnableSingleClaim on its own entry file, paying its own cold closure resolve per the empirical law in ci_floor_resolve_receipt_note. Co-Authored-By: Claude Fable 5 --- dag/gunbc/ci_materialization.dag | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dag/gunbc/ci_materialization.dag b/dag/gunbc/ci_materialization.dag index 561db862943..c549da5d01e 100644 --- a/dag/gunbc/ci_materialization.dag +++ b/dag/gunbc/ci_materialization.dag @@ -170,7 +170,9 @@ data ci_floor_resolve_receipt_note: String = "The counted cold-resolve receipt o data ci_floor_resolve_receipt_path: String = "target/floor-resolve-receipt.txt" -data ci_floor_declared_resolve_count: Nat = 1 +data ci_floor_declared_resolve_count: Nat = 2 + +data ci_floor_native_batch_resolve_receipt_note: String = "RECEIPT 9 — CONSCIOUS RAISING 1 -> 2 (2026-08-02, native-bundle production enrollment): CI run 30767841790 refused exactly `floor resolve count 2 differs from declared 1` and wrote target/floor-resolve-receipt.txt with resolves_total=2, resolve_ms_total=79064. The cause is the empirical law above operating as designed: gunbc_pr_native_batch enrolls as a RunnableSingleClaim on its own entry file (src/v2/test/claim/pr_native_batch_test.dag), an entry class whose closure escapes the batch-1 whole-tree materialization, so it pays its own cold resolve — 1 anchor + 1 escaping entry = 2. Same run: the batch itself PASSED via the counted outage fallback (verdict fallback:native_realization_refused, transport causes located), so the resolve count is the sole finalization refusal. Ratchet direction unchanged: the persistent content-keyed store still owes the permanent pin at 1, and de-enrolling the native batch (or pooling its closure warm) lowers this row consciously in the PR that does it." data floor_finalization_note: String = "The CI floor's post-batch contract, and it lives HERE rather than in std.realization_schedule because it is a fact about THIS floor's duplicate-computation budget, not about walks in general (review 2026-07-30): the generic carrier takes it as a type parameter, so gunbc_ci_floor_plan returns WalkPlan and every other plan returns WalkPlan. WHAT THAT BUYS, narrowly: the signature DECLARES which finalization family each plan intends, and the std-level coproduct fork is gone. It is NOT a construction wall today — probed by execution, the typechecker does not check a declared return type against the body, so a plan can still return the wrong family and typecheck. Until return-position and annotated-data checking are grounded, the enrolled value witnesses and the executor's parser are the wall; the witnesses dissolve when that checking lands (std.realization_schedule walk_finalization_note carries the probe and the dissolve-on).