From c36d06b72a28c4bc4ad384c7627ff0ff4daffb9d Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 19 Aug 2026 04:46:52 +0000 Subject: [PATCH 1/2] Delete the required-floor manifest: the admission decision was computed twice The floor marshalled 10,498 discovered sites into the interpreter, folded them through `required_floor_manifest` to decide which are required-floor claims, and marshalled 9,008 back. The host then applied the identical prefix test itself, in Rust, to explain the difference between sites offered and claims returned. One decision, two computations, with an interpreted round trip between them whose only product was a population the host could derive from facts it already held in `prepared.witness_files`. The externally required outcome is exactly: exclude a witness whose AUTHORED module sits in the long home, exclude one that reads the live tree, claim everything else Hermetic. That is now one loop over the inventory. Three findings made this a deletion rather than an optimisation: - `WitnessDisposition` (five arms) had no consumer. Its one predicate, `disposition_is_required_floor`, was never called; the file said so itself ("stays modelled and unconsumed exactly as it was"). `disposition_for_module`, cited in `cli_run.rs` and DESIGN.md as the admission authority, does not exist. - The duplicate-enrollment invariant was already enforced downstream. `receipted: HashSet` is keyed on the same qualified name, so two claims sharing one give executed=2, receipted=1 and `ClaimIdentityCountsDisagree` refuses. `ManifestScan.enrollments` was a second mechanism for that one invariant -- and, being a growing `Value::Map` re-hashed once per fold step, was the whole of the phase's quadratic cost. - The Wet arm was dead: `wet_sites` was always passed as `empty_sites`. The authored facts stay authored. `long_home_prefixes`, the claim budget and the warn threshold are still read from `v2.workflow.required_floor`; what is deleted is the reconstruction, never the fact. The test remains on the module's AUTHORED name and never its path, which is the 2026-08-04 ruling's actual requirement. Two refusals were deleted with their producer. `SitePartitionInexact` and the unexplained-decline arm existed to catch the two computations disagreeing; with one computation they have no reachable producer, and the partition is now exact by construction. One refusal was added in their place: `LongHomePrefixesEmpty`, since an empty roster would otherwise silently admit the long home into the floor. Deliberately NOT in this change: `eval_call_memo` is untouched, and `Value::Map` is unchanged. Whether the generic eval-frame memo should survive is a separate question with its own consumers, and optimising a foundational datatype on behalf of this machinery was the wrong dependency direction while the machinery's necessity was still unestablished. Co-Authored-By: Claude Opus 5 (1M context) --- src/v1/stage0/src/cli_run.rs | 510 ++++++----------------------- src/v2/workflow/required_floor.dag | 493 +--------------------------- 2 files changed, 103 insertions(+), 900 deletions(-) diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index 29625373569..069b04a2357 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -39171,10 +39171,9 @@ fn record_value( } } -/// The module whose `required_floor_attempt` folds the manifest. Named once: the manifest is -/// evaluated in its OWN exact scope, exactly as every claim is, so the program that decides -/// which claims exist is not itself privileged with a wider namespace than the claims it -/// admits. +/// The module carrying the floor's authored thresholds and the long-home roster. Named once, +/// and evaluated in its OWN exact scope exactly as every claim is, so the module that supplies +/// the admission facts is not privileged with a wider namespace than the claims they admit. const REQUIRED_FLOOR_MANIFEST_MODULE: &str = "v2.workflow.required_floor"; /// THE REQUIRED FLOOR, AS ONE ATTEMPT. @@ -39396,6 +39395,21 @@ fn floor_value_shape(v: Option<&v1_interpreter::Value>) -> String { // subject, and the recursive spelling already in this file for dependency edges would recurse // once per element -- fine for a handful of edges, a stack overflow here. Depth belongs on the // heap when the depth is the population size. +/// One nullary `.dag` Int authority, decoded. The floor's per-claim thresholds are authored in +/// `v2.workflow.required_floor` and read here rather than re-spelled in Rust: the host owns when +/// a budget is applied, never what it is. +fn floor_required_int(ctx: &v1_interpreter::InterpContext, func: &str) -> Result { + let qualified = format!("v2.workflow.required_floor.{func}"); + match v1_interpreter::run_in_context(ctx, &qualified, false) { + Ok(v1_interpreter::Value::Int(n)) if n >= 0 => Ok(n as u64), + Ok(other) => Err(format!( + "{qualified}: expected a non-negative Int, got {}", + floor_value_shape(Some(&other)) + )), + Err(e) => Err(format!("{qualified}: {e}")), + } +} + fn floor_decode_list<'a>( ctx: &v1_interpreter::InterpContext, v: Option<&'a v1_interpreter::Value>, @@ -39842,137 +39856,41 @@ pub fn run_required_floor( floor_seam("site-projection"); let projection_started = std::time::Instant::now(); let files = &prepared.witness_files; - // THE SITE CARRIES ITS MODULE. `InventoryWitnessFile` already holds `module_path`, read from - // the same inventory entry in the same iteration, so the site is complete at construction. + // ONE DECISION, MADE ONCE, WHERE THE FACTS ALREADY ARE. // - // This replaced a second projection of the WHOLE inventory into an entry-to-module list -- - // 3,680 records marshalled into the interpreter -- which the .dag manifest then JOINED back - // onto the sites by `entry`. Both lists came from one collection keyed by one file path, so - // the join re-derived inside the fold a fact this loop held two lines earlier, and its answer - // was always "exactly one". The refusal for the other cases had no reachable producer. - // EVERY DISCOVERED SITE IS OFFERED TO THE MANIFEST, and the manifest decides which are - // required-floor claims. + // WHAT THIS REPLACED, and why it was not an optimisation. The required outcome of this whole + // region is exactly: exclude a witness whose AUTHORED module sits in the long home, exclude + // one that reads the live tree, claim everything else Hermetic. That decision used to be + // made TWICE — once by `required_floor_manifest` over 10,498 records marshalled into the + // interpreter, and again here in Rust, applying the same prefix test to explain the + // difference between sites offered and claims returned. Between the two sat an interpreted + // fold whose only product was a population this host could compute directly from facts it + // already held in `prepared.witness_files`. // - // This host previously partitioned the population itself, by testing whether a file's PATH - // contained the long home. That made a directory the admission authority — the 2026-08-04 - // ruling's exact root cause — and it decided at file grain, so one expensive witness took - // every cheap sibling in its file out of the floor with it. It was also a SECOND authority: - // `WitnessDisposition` already modelled the answer in `.dag` and nothing consulted it. - // - // The disposition now lives where it is authored — `v2.workflow.required_floor` - // `disposition_for_module`, a grant over a namespace subtree joined by the prefix relation, - // with `RequiredFloor` as the fail-closed default. Discovery's job is to report what exists; - // deciding what that means is the manifest's. - // - // The exclusion is still counted, and counted from the claim list rather than from a - // predicate this host applies: sites offered minus claims returned is what the manifest - // declined, so the number cannot drift from the decision that produced it. - let mut sites: Vec = Vec::new(); - // THE SAME POPULATION, KEPT IN HOST SHAPE, so the decline can be reported as a PARTITION - // rather than as a subtraction. `sites_offered - claims.len()` says how many rows vanished - // and nothing about why; two independent hacks decline rows here, and a single difference - // cannot distinguish them, cannot notice a row declined by neither, and cannot notice a row - // counted by both. - let mut site_facts: Vec<(String, String, bool)> = Vec::new(); - for file in files { - for function in &file.functions { - site_facts.push(( - format!("{}.{}", file.module_path, function), - file.module_path.clone(), - file.reads_live_tree, - )); - sites.push(record_value( - &hermetic, - "WitnessSite", - vec![ - ("entry", v1_interpreter::str_value(file.path.clone())), - ("function", v1_interpreter::str_value(function.clone())), - ( - "module_path", - v1_interpreter::str_value(file.module_path.clone()), - ), - ( - "reads_live_tree", - v1_interpreter::Value::Bool(file.reads_live_tree), - ), - ], - )); - } - } - let sites_offered = sites.len(); - eprintln!( - "[floor-phase] phase=site-projection state=completed wall_ms={} sites={} files={}", - projection_started.elapsed().as_millis(), - sites_offered, - files.len() - ); - let subject = record_value( - &hermetic, - "ObservedSubjectIdentity", - vec![ - ("commit", v1_interpreter::str_value(commit.to_string())), - ( - "source_digest", - v1_interpreter::str_value(prepared.subject_digest.clone()), - ), - ( - "modules_resolved", - v1_interpreter::Value::Int(prepared.modules_resolved as i64), - ), - ( - "modules_excluded", - v1_interpreter::Value::Int(prepared.modules_excluded as i64), - ), - ], - ); - let empty_sites = - v1_interpreter::Value::List(Rc::new(Vec::::new().into())); - floor_seam("manifest-evaluation"); - let manifest_eval_started = std::time::Instant::now(); - let admission = v1_interpreter::run_in_context_with_args( - &hermetic, - "required_floor_attempt", - &[ - (Some("subject".to_string()), subject), - ( - Some("hermetic_sites".to_string()), - v1_interpreter::Value::List(Rc::new(sites.into())), - ), - (Some("wet_sites".to_string()), empty_sites), - ], - false, - ) - .map_err(|e| format!("required_floor_attempt: {e}"))?; - eprintln!( - "[floor-phase] phase=manifest-evaluation state=completed wall_ms={}", - manifest_eval_started.elapsed().as_millis() - ); - floor_seam("admission-decode"); - let admission_decode_started = std::time::Instant::now(); - let mut claims = required_floor_claims_from_admission(&hermetic, &admission)?; - eprintln!( - "[floor-phase] phase=admission-decode state=completed wall_ms={} claims={}", - admission_decode_started.elapsed().as_millis(), - claims.len() - ); - // WHAT THE MANIFEST DECLINED, derived from the two populations rather than recomputed. A - // site offered and not returned as a claim carries a non-required disposition, and those - // rows are NOT covered by this floor — reported every run in those words, because the - // gunbc#7762 failure was not that rows were deferred but that the deferral was silent. - // THE DECLINE IS A PARTITION, AND IT IS PROVED HERE RATHER THAN ASSERTED. + // THE AUTHORED FACTS STAY AUTHORED. `long_home_prefixes`, the claim budget and the warn + // threshold are still read from `v2.workflow.required_floor`, so the prefix list and both + // thresholds remain .dag authorities and are not re-spelled in Rust. What is deleted is the + // reconstruction, never the fact. // - // Two hacks decline rows: the long-home prefix test and the live-tree declaration. A single - // `offered - claims` difference cannot tell them apart, cannot see a row declined by - // NEITHER (which would be a silent disappearance — the exact gunbc#7762 failure), and - // cannot see a row that both would claim. So the three populations are computed by identity - // and required to reconstruct the whole: + // THE TEST IS ON THE MODULE'S AUTHORED NAME, never its path — the 2026-08-04 ruling's actual + // requirement, and the reason the inventory carries `module_path` beside each file. A + // directory deciding admission was that ruling's root cause; reading the declaration is what + // fixes it, and that is preserved here exactly. // - // offered = executed ⊎ long-home-declined ⊎ live-tree-declined + // THE PARTITION IS NOW EXACT BY CONSTRUCTION, not by reconciliation. Every site takes exactly + // one arm below, so `claims + declined == offered` holds because the loop cannot do + // otherwise. The former `SitePartitionInexact` and unexplained-decline refusals existed to + // catch the two computations disagreeing; with one computation they have no reachable + // producer, so they are deleted rather than left standing as walls nothing can trip. // - // The prefixes are DECODED from the `.dag` authority rather than restated here, because a - // host-side copy of that list is a second authority that would drift the moment either side - // moved — and the drift would show up as this partition disagreeing, which is a confusing - // way to learn about a copy-paste. + // DUPLICATE ENROLLMENT IS UNCHANGED AND UNMOVED, and this is the one invariant the deleted + // fold genuinely carried. It is caught downstream by `receipt_identities`, a HashSet keyed on + // the same qualified name: two claims sharing a name give executed=2, receipted=1, and + // `ClaimIdentityCountsDisagree` refuses. The manifest's enrollment map was a second mechanism + // for that one invariant — and, being a growing `Value::Map` re-hashed once per fold step, + // was the whole of the phase's quadratic cost. + let claim_budget_ms = floor_required_int(&hermetic, "required_floor_claim_budget_ms")?; + let claim_warn_ms = floor_required_int(&hermetic, "required_floor_claim_warn_ms")?; let long_home_prefixes: Vec = { let value = v1_interpreter::run_in_context( &hermetic, @@ -39981,83 +39899,67 @@ pub fn run_required_floor( ) .map_err(|e| format!("long_home_prefixes: {e}"))?; let items = floor_decode_list(&hermetic, Some(&value)) - .map_err(|e| format!("long_home_prefixes: {e}"))?; + .map_err(|why| format!("long_home_prefixes decode: {why}"))?; let mut out = Vec::new(); for item in items { match item { v1_interpreter::Value::Str(s) => out.push(s.to_string()), other => { return Err(format!( - "long_home_prefixes: expected a module-path prefix, got {}", + "long_home_prefixes: expected String rows, got {}", floor_value_shape(Some(other)) - )); + )) } } } + if out.is_empty() { + return Err( + "REQUIRED-FLOOR REFUSAL cause=LongHomePrefixesEmpty — the long-home roster \ + decoded to zero prefixes, which would silently admit the long home into the \ + required floor" + .to_string(), + ); + } out }; - { - let executed: HashSet<&str> = claims.iter().map(|c| c.qualified.as_str()).collect(); - let mut long_declined = 0usize; - let mut live_declined = 0usize; - let mut both = 0usize; - let mut unexplained: Vec<&str> = Vec::new(); - for (qualified, module_path, reads_live_tree) in &site_facts { - if executed.contains(qualified.as_str()) { + let mut claims: Vec = Vec::new(); + let mut long_declined = 0usize; + let mut live_declined = 0usize; + let mut sites_offered = 0usize; + for file in files { + let long_home = long_home_prefixes + .iter() + .any(|prefix| file.module_path.starts_with(prefix.as_str())); + for function in &file.functions { + sites_offered += 1; + if long_home { + long_declined += 1; continue; } - let long_home = long_home_prefixes - .iter() - .any(|p| module_path.starts_with(p)); - // ASSIGNED IN A FIXED ORDER SO THE ARMS STAY DISJOINT, with the overlap counted - // separately rather than hidden by whichever test ran first. A row that is both - // long-home and live-tree is a real thing and it is worth knowing how many there - // are, but it must be attributed once. - match (long_home, *reads_live_tree) { - (true, true) => { - long_declined += 1; - both += 1; - } - (true, false) => long_declined += 1, - (false, true) => live_declined += 1, - // DECLINED BY NEITHER HACK. This is the arm that must stay empty: the manifest - // dropped a row for a reason this host cannot name, which is precisely a silent - // narrowing of the roster. - (false, false) => unexplained.push(qualified.as_str()), + if file.reads_live_tree { + live_declined += 1; + continue; } - } - let declined = long_declined + live_declined + unexplained.len(); - if declined > 0 { - eprintln!( - "[floor-disposition] {declined} of {sites_offered} discovered site(s) are NOT \ - required-floor and NOT RUN HERE: {long_declined} long-home-declined \ - ({both} of them also declare ReadsLiveTree), {live_declined} live-tree-declined \ - — each needs an executing consumer on another cadence, and none exists yet on \ - this branch" - ); - } - if !unexplained.is_empty() { - unexplained.sort_unstable(); - let shown: Vec<&str> = unexplained.iter().copied().take(20).collect(); - return Err(format!( - "REQUIRED-FLOOR REFUSAL cause=SiteDeclinedWithoutDisposition count={} — a \ - discovered site was neither executed nor declined by a named disposition, so \ - the roster narrowed for a reason nothing can report; first {}: {}", - unexplained.len(), - shown.len(), - shown.join(", ") - )); - } - if claims.len() + declined != sites_offered { - return Err(format!( - "REQUIRED-FLOOR REFUSAL cause=SitePartitionInexact offered={} executed={} \ - declined={} — the three populations must reconstruct the offered set exactly", - sites_offered, - claims.len(), - declined - )); + claims.push(RequiredFloorClaim { + qualified: format!("{}.{}", file.module_path, function), + module_path: file.module_path.clone(), + function: function.clone(), + execution_mode: v1_interpreter::ExecutionMode::Hermetic, + budget_ms: claim_budget_ms, + warn_ms: claim_warn_ms, + }); } } + eprintln!( + "[floor-phase] phase=site-projection state=completed wall_ms={} sites={} files={} \ + claims={} declined_long={} declined_live={}", + projection_started.elapsed().as_millis(), + sites_offered, + files.len(), + claims.len(), + long_declined, + live_declined + ); // THE EXPECTED-RED ROSTER, read from its .dag authority in the manifest's own frame — it // must be decoded BEFORE that frame is dropped below, and it is a separate evaluation from @@ -40220,7 +40122,6 @@ pub fn run_required_floor( // the next run says, and if the step survives then the cost is elsewhere and this was still // correct — an unread value held across the longest phase of the program has no defence. drop(hermetic); - drop(admission); drop(manifest_scope); // ── 4. fold the manifest ────────────────────────────────────────────────────────────── @@ -40901,233 +40802,6 @@ fn witness_eval_verdict_from_claim_outcome( } } -/// Read the `.dag` admission. A refusal is reported with every offending row rather than the -/// first, because a manifest with three conflicting declarations should take one round-trip to - -fn required_floor_claims_from_admission( - ctx: &v1_interpreter::InterpContext, - admission: &v1_interpreter::Value, -) -> Result, String> { - // EVERY STEP MARKED, BECAUSE THE ONE UNMARKED REGION IS WHERE THE TIME WAS. - // - // Run 31942605651 completed manifest-evaluation at 11:14:12 and was cancelled at 13:48:13 - // having printed neither arm's entry marker -- so 2h34m elapsed inside this function before - // reaching either. That region was left unmarked on my reasoning that it is a sym_eq and two - // binary searches and "cannot cost hours on its face". That was an assumption about cost - // stated as a bound, and it was wrong. Each step now emits, so no step can absorb time - // silently. - let entered = std::time::Instant::now(); - eprintln!("[floor-phase] phase=admission-decode state=started"); - let v1_interpreter::Value::Variant { - variant_name, - fields, - .. - } = admission - else { - return Err( - "required_floor_attempt did not answer a RequiredFloorAdmission variant".to_string(), - ); - }; - eprintln!( - "[floor-phase-progress] phase=admission-decode step=destructured wall_ms={} {}", - entered.elapsed().as_millis(), - floor_resource_sample() - ); - let refused = ctx.sym_eq(*variant_name, "RequiredFloorRefused"); - eprintln!( - "[floor-phase-progress] phase=admission-decode step=arm-resolved refused={} wall_ms={} {}", - refused, - entered.elapsed().as_millis(), - floor_resource_sample() - ); - if refused { - // T5a — THE REFUSAL RENDER IS ITS OWN TERM because it is the arm that can cost more - // than the decode it reports on. `{r:?}` walks an interpreter `Value` structurally, and - // a refusal carries records that share substructure: Debug re-renders each occurrence - // rather than the shared node, so a cheap-looking format over a few thousand rows is not - // bounded by the row count. A run that refuses would otherwise spend that time inside a - // function whose seam says "decode", attributing a diagnostic's cost to the decode loop. - // THE SEAM MOVES WITH EXECUTION, or the heartbeat lies about where the run is. - // `floor_seam` was last set to "admission-decode" by the caller, and the heartbeat prints - // whatever it holds — so a run stalled inside THIS arm reported `phase=admission-decode` - // for its entire life, which is indistinguishable in the log from a run stalled BEFORE the - // arm was entered. A reader then cannot tell "never reached the render" from "spent three - // hours inside it", and the natural conclusion is that no progress instrument exists. - floor_seam("refusal-render"); - let refusal_render_started = std::time::Instant::now(); - let refusal_count = match ctx.field(fields, "refusals") { - Some(v1_interpreter::Value::List(items)) => items.len(), - _ => 0, - }; - eprintln!("[floor-phase] phase=refusal-render state=started total={refusal_count}"); - // The SAME progress obligation as the decode loop, and it was missing here first. A - // censored run keeps only what was already printed, so an arm with an entry marker and a - // completion timer and nothing between teaches nothing when it is the arm that stalls -- - // and a rate plus a denominator is a completion estimate obtainable WITHOUT completing. - // Every 16 rather than every 256 because a refusal render is few rows of possibly enormous - // output, so the interesting variance is per-row, not across thousands. - let rendered = match ctx.field(fields, "refusals") { - Some(v1_interpreter::Value::List(items)) => items - .iter() - .enumerate() - .map(|(i, r)| { - if i % 16 == 0 { - eprintln!( - "[floor-phase-progress] phase=refusal-render rendered={i} total={} wall_ms={} {}", - items.len(), - refusal_render_started.elapsed().as_millis(), - floor_resource_sample() - ); - } - format!("{r:?}") - }) - .collect::>() - .join("\n "), - _ => "".to_string(), - }; - eprintln!( - "[floor-phase] phase=refusal-render state=completed wall_ms={} total={} rendered_bytes={}", - refusal_render_started.elapsed().as_millis(), - refusal_count, - rendered.len() - ); - return Err(format!( - "REQUIRED-FLOOR REFUSAL cause=ManifestInadmissible — the claim manifest carries \ - refusals, so the floor does not run its clean subset and report on the rest:\n \ - {rendered}" - )); - } - if !ctx.sym_eq(*variant_name, "RequiredFloorRunnable") { - return Err("required_floor_attempt answered an unknown admission arm".to_string()); - } - let Some(v1_interpreter::Value::Record { fields: af, .. }) = ({ - let r = ctx.field(fields, "attempt"); - eprintln!( - "[floor-phase-progress] phase=admission-decode step=attempt-field wall_ms={} {}", - entered.elapsed().as_millis(), - floor_resource_sample() - ); - r - }) else { - return Err("RequiredFloorRunnable carries no attempt record".to_string()); - }; - // THE REFUSAL NAMES THE SHAPE IT OBSERVED, not merely that the shape was wrong. - // - // "the attempt carries no claim list" is true of an absent field, of a record, of a variant - // and of a scalar alike, so it identifies the seam and nothing else. Reaching this arm costs - // a full preparation plus manifest evaluation — measured at 28 minutes on the first run that - // ever got here — and spending that to learn only that the field was not a list makes the - // next attempt cost the same again. What discriminates the causes is the constructor. - let claims_field = ctx.field(af, "claims"); - let claims_shape = floor_value_shape(claims_field); - eprintln!( - "[floor-phase-progress] phase=admission-decode step=claims-field wall_ms={} observed={} {}", - entered.elapsed().as_millis(), - claims_shape, - floor_resource_sample() - ); - let rows = floor_decode_list(ctx, claims_field).map_err(|why| { - format!("the attempt's `claims` field is not a list — {why} (field shape {claims_shape})") - })?; - // T5b — the ordinary decode loop, reported separately from the refusal arm above so that - // "the decode is slow" and "the refusal diagnostic is slow" are never one number. - // Same obligation as the refusal arm: carry the seam into the loop so the heartbeat names - // the loop rather than the phase that called it. Without this the decode's own ticks and the - // heartbeat disagree about the phase name, and a reader filtering the log on - // "admission-decode" — the name the heartbeat kept printing — silently excludes every - // `phase=claim-decode` progress line and concludes the loop has no counter at all. - floor_seam("claim-decode"); - let decode_loop_started = std::time::Instant::now(); - eprintln!( - "[floor-phase] phase=claim-decode state=started total={}", - rows.len() - ); - let mut out = Vec::with_capacity(rows.len()); - // PROGRESS, NOT JUST COMPLETION. A timer printed after a loop reports the loop's cost only if - // the loop terminates; a run killed inside it leaves "entered" and "finished" equally silent, - // so decoded-0 and decoded-9000 present identically. The tick is what separates them. - for (decoded, row) in rows.iter().enumerate() { - if decoded % 256 == 0 { - eprintln!( - "[floor-phase-progress] phase=claim-decode decoded={decoded} total={} wall_ms={} {}", - rows.len(), - decode_loop_started.elapsed().as_millis(), - floor_resource_sample() - ); - } - let v1_interpreter::Value::Record { fields: cf, .. } = row else { - return Err("a manifest claim is not a record".to_string()); - }; - let Some(v1_interpreter::Value::Record { fields: df, .. }) = ctx.field(cf, "declaration") - else { - return Err("a manifest claim carries no declaration identity".to_string()); - }; - let module_path = match ctx.field(df, "module_path") { - Some(v1_interpreter::Value::Str(s)) => s.to_string(), - _ => return Err("a claim identity carries no module path".to_string()), - }; - let function = match ctx.field(df, "function") { - Some(v1_interpreter::Value::Str(s)) => s.to_string(), - _ => return Err("a claim identity carries no function name".to_string()), - }; - let budget_ms = match ctx.field(cf, "budget_ms") { - Some(v1_interpreter::Value::Int(n)) if *n > 0 => *n as u64, - // A non-positive budget is refused rather than defaulted: a zero deadline that - // reads as "no limit" is the absorbing fallback, and one that reads as "refuse - // instantly" fails every claim for a reason unrelated to the claim. - other => { - return Err(format!( - "claim {module_path}.{function} carries a non-positive budget ({other:?})" - )) - } - }; - let warn_ms = match ctx.field(cf, "warn_ms") { - Some(v1_interpreter::Value::Int(n)) if *n > 0 => *n as u64, - other => { - return Err(format!( - "claim {module_path}.{function} carries a non-positive warn threshold ({other:?})" - )) - } - }; - let execution_mode = match ctx.field(cf, "execution_mode") { - Some(v1_interpreter::Value::Variant { - variant_name: m, .. - }) => { - if ctx.sym_eq(*m, "Hermetic") { - v1_interpreter::ExecutionMode::Hermetic - } else if ctx.sym_eq(*m, "Wet") { - v1_interpreter::ExecutionMode::Wet - } else if ctx.sym_eq(*m, "Record") { - v1_interpreter::ExecutionMode::Record - } else { - return Err(format!( - "claim {module_path}.{function} names an unknown execution mode" - )); - } - } - _ => { - return Err(format!( - "claim {module_path}.{function} carries no execution mode" - )) - } - }; - out.push(RequiredFloorClaim { - qualified: format!("{module_path}.{function}"), - module_path, - function, - execution_mode, - budget_ms, - warn_ms, - }); - } - eprintln!( - "[floor-phase] phase=claim-decode state=completed wall_ms={} claims={}", - decode_loop_started.elapsed().as_millis(), - out.len() - ); - Ok(out) -} - pub fn run_required_regen( candidate_dir_rel: &str, receipt_rel: &str, diff --git a/src/v2/workflow/required_floor.dag b/src/v2/workflow/required_floor.dag index 4070170358d..f89d7eeb337 100644 --- a/src/v2/workflow/required_floor.dag +++ b/src/v2/workflow/required_floor.dag @@ -1,8 +1,10 @@ module v2.workflow.required_floor -import v2.std.algebra { Cons, Empty, TailAbsent, TailFound, fold_list, length, list_append, list_map, list_reverse, list_snoc_item } -import v2.std.collection { List, Map, empty_map, map_insert, map_lookup } +import v2.std.algebra { Cons, Empty } +import v2.std.collection { List } import std.dissolution { DissolutionCondition, unbound_dissolution } +import v2.std.text { String } + // THE ROSTER IS IMPORTED HERE SO IT IS REACHABLE, NOT SO IT IS RE-EXPORTED. // // The host evaluates the expected-red roster in the SAME frame it evaluates this manifest in, @@ -15,14 +17,6 @@ import std.dissolution { DissolutionCondition, unbound_dissolution } // thin accessor here would be a second name for one authority, and this module would then own // a fact it does not produce. import v2.workflow.floor_expected_red { floor_expected_red_roster } -import v2.std.logic { Bool } -import v2.std.text { CharAbsent, CharFound, String, string_head, string_is_empty, string_tail } -import std.execution_mode { ExecutionMode, Hermetic, Record, Wet, execution_mode_eq } -import v2.workflow.floor2_prepared_subject { - WitnessIdentity, - WitnessSite, - witness_identity_qualified_name -} // BARE-NAME AMBIGUITY IS COMPUTED AND DISCARDED, one rung below where the machinery already // stands. This is an ACKNOWLEDGEMENT of debt the floor cut discovered on its base, not debt the @@ -57,90 +51,6 @@ import v2.workflow.floor2_prepared_subject { // component, because the qualified key is collision-free by construction. data floor_bare_name_ambiguity_next_rung_trigger: DissolutionCondition = unbound_dissolution(description: "dissolve-on: bare-name binding stops being decided by insertion order. Reached when ambiguous references carry their qualified module path (v2.compiler.emit.emit rather than emit), which routes through the collision-free qualified key in the interpreter's index and needs no change to the frozen component. Owned by the namespace cut, gunbc#8282; the nine production emit call sites were handed over and taken 2026-08-17. Until then [floor-bare-name-ambiguity] counts the population every run and the three emit renames on integration/floor-cut are interim debt reverting on that landing. Rung today: mitigatable — the ambiguous set is computed and countable, and the wrong binding is loud at the caller as a contract mismatch rather than silent. Ceiling: structural impossibility — a qualified reference has exactly one declarer, so no ambiguous binding is writable.") -// THE REQUIRED FLOOR IS ONE ATTEMPT: read the sources once, prepare one subject, fold one -// exact claim manifest, reduce one receipt. This module is that program. -// -// It deliberately does NOT reach the generic schedule vocabulary. There is no Runnable -// here, no WalkPlan, no batch, no batch position, no positional clamp, no worker and no -// coordinator — not because those happen to be unused on this path but because the required -// floor is not a walk of runnables. A batch is a grouping of separately-prepared work, and -// once there is one preparation the grouping has no subject. Preserving the word would -// preserve the architecture: a batch identity implies batch receipts, batch clamps and batch -// ordering, each of which then needs a consumer, and the outer floor reassembles itself -// around the new evaluator. That is exactly what happened when the inner entry-major loop -// was replaced while the outer grammar was left standing. -// -// WHAT THE HOST STILL OWNS IS EXACTLY TWO OPERATIONS, and neither is expressible here -// because a .dag function cannot construct the interpreter that runs it: build an evaluable -// context from a declared source set, and evaluate one qualified declaration inside it. -// Which claims exist, what identity each has, what refuses, which evaluation frame each -// needs and what the run's verdict is are facts of this module. - -// THE SUBJECT AS THE RUN OBSERVED IT, which is deliberately NOT `v2.workflow.ci_attempt` -// `CiAttemptRequest`. -// -// That carrier is the right one and this is not a nickname for it: it declares a subject in -// interned identities — `TreeIdentity { commit: Symbol }`, `SourceManifestIdentity { digest: -// Hash }` — which is the correct shape for an authored row and the wrong shape for a host -// observation, because a digest computed while preparing has no declaration to intern. The -// two meet at admission, where the exact-subject lane judges an observation against a request. -// This carries what one preparation measured, and nothing it did not. -// -// The counts are here rather than derived from the inventory because they answer a question -// the claim list cannot: how many modules the subject dropped. A run reporting claims without -// reporting exclusions cannot distinguish a clean small roster from a subject that silently -// lost half the tree. -type ObservedSubjectIdentity { - commit: String - source_digest: String - modules_resolved: Int - modules_excluded: Int -} - -type RequiredFloorAttempt { - subject: ObservedSubjectIdentity - claims: List -} - -// EXECUTION MODE IS DECLARED ON THE CLAIM, and it is deliberately NOT derived from -// `reads_live_tree`. Those answer different questions — reads_live_tree says what substrate -// a declaration may observe, execution_mode says what evaluator frame must run it — and -// their populations coinciding today does not make one the definition of the other. Deriving -// it is the cheapest-looking shortcut available at this seam and it silently re-couples two -// independent axes the first time they disagree. -// -// There is no enrollment-origin field. It was drafted and removed: it named which of the -// three former batches a claim came from, which is the batch concept surviving as a column. -// A row that remembers its batch invites a consumer to group by it, and the grouping is the -// thing being deleted. -// -// The budget is milliseconds because that is the currency the host's evaluate primitive -// reads (`EvaluatePreparedClaimRequest.budget_ms`); carrying seconds here and converting at -// the seam would put a unit change between the authority and the mechanism that enforces it. -type RequiredFloorClaim { - declaration: WitnessIdentity - execution_mode: ExecutionMode - budget_ms: Int - warn_ms: Int -} - -// THE DISPOSITION OF EVERY DECLARED WITNESS, total by construction. -// -// There is no `Deferred` arm, and its absence is the point. A deferral is not a disposition: -// it says a row was not run without saying who runs it, so the population accumulates -// silently and reads as coverage. The measured specimen this closes: 1,083 rows reported as -// "deferred-discovery" on a run whose receipt otherwise claimed to have executed the floor. -// -// `ReadsLiveTree` is NOT one of these arms either, and could not be — it determines an -// evaluation frame, not whether anything executes the row. -type WitnessDisposition - = RequiredFloor - | ScheduledWet - | ScheduledLong - | KnownRedQuarantine - | DeletedNotAWitness - -// LONG-HOME EXCLUSION, and it is a hack rather than a model (operator, 2026-08-17). // // THREE PREFIXES, NOT ONE, and the count is what found that. A single `test.claim.long.` test // excluded 42 rows of an expected ~310, because the long home is not one namespace: 64 modules @@ -163,9 +73,13 @@ type WitnessDisposition // authored all along and the host was reading a shadow of it. // // That is the whole change. No grant table, no disposition lattice, no second mechanism: one -// prefix test, in the manifest, where admission is decided. `WitnessDisposition` stays modelled -// and unconsumed exactly as it was — wiring it is a real modelling question about wet lanes and -// cadences, and this is not that question. +// prefix test over the roster below, applied once by the host that already holds every witness's +// authored module name. +// +// `WitnessDisposition` — a five-arm coproduct with no consumer, whose one predicate +// `disposition_is_required_floor` was never called — was deleted with the manifest fold rather +// than left standing as a model of a decision nothing made. Wiring wet lanes and cadences is a +// real modelling question, and when it is asked it will be asked against a live consumer. // // These rows are NOT COVERED by anything. The host reports the count every run. fn long_home_prefixes() -> List { @@ -181,73 +95,6 @@ fn long_home_prefixes() -> List { } } -fn string_starts_with(s: String, prefix: String) -> Bool { - match string_head(s: prefix) { - CharAbsent => true - CharFound { value: p } => - match string_head(s: s) { - CharAbsent => false - CharFound { value: c } => - match c == p { - false => false - true => - match string_tail(s: s) { - TailAbsent => string_is_empty(s: prefix) - TailFound { tail: s_rest } => - match string_tail(s: prefix) { - TailAbsent => true - TailFound { tail: p_rest } => - string_starts_with(s: s_rest, prefix: p_rest) - } - } - } - } - } -} - -fn module_is_long_home(module_path: String) -> Bool { - fold_list( - xs: long_home_prefixes(), - empty: false, - cons: fn(acc, prefix) { - match acc { - true => true - false => string_starts_with(s: module_path, prefix: prefix) - } - } - ) -} - -fn disposition_is_required_floor(d: WitnessDisposition) -> Bool { - match d { - RequiredFloor => true - ScheduledWet => false - ScheduledLong => false - KnownRedQuarantine => false - DeletedNotAWitness => false - } -} - -// The manifest refuses rather than deduplicating. Silently merging populations is how a -// declaration enrolled twice under conflicting modes becomes one arbitrary winner — and the -// losing mode is precisely the fact worth having. Each arm names the exact qualified -// declaration, so the refusal is located rather than counted. -type ManifestRefusal - = DeclarationEnrolledTwice { qualified: String } - | DeclarationEnrolledWithConflictingModes { qualified: String } - -// ADMISSION IS ALL-OR-NOTHING. A manifest carrying any refusal does not run its clean subset -// and report on the rest: a narrowed roster presented as a roster is the silent narrowing -// every other wall on this path exists to prevent. -type RequiredFloorAdmission - = RequiredFloorRunnable { attempt: RequiredFloorAttempt } - | RequiredFloorRefused { refusals: List } - -data no_required_floor_claims: List = [] - -data no_manifest_refusals: List = [] - -data no_seen_qualified_names: List = [] // THE EVALUATION DEADLINE FOR ONE CLAIM IS WALL TIME, AND IT HAS TWO TIERS. // @@ -302,321 +149,3 @@ fn required_floor_claim_budget_ms() -> Int { fn required_floor_claim_warn_ms() -> Int { 100 } - -fn required_floor_claim_qualified(claim: RequiredFloorClaim) -> String { - witness_identity_qualified_name(identity: claim.declaration) -} - -// A resolved witness becomes a claim, or contributes its refusal. Both halves are produced in -// one pass so the refusal population and the claim population cannot disagree about which -// rows they came from. -type ClaimScan { - claims: List - refusals: List -} - -// THE SCAN ACCUMULATES BY PREPENDING AND REVERSES ONCE AT THE END. -// -// It appended with `list_snoc_item`, and that is quadratic in ALLOCATION, not merely in time. -// `list_snoc_item(xs, item)` is `list_append(left: xs, right: [item])`, and `list_append` folds -// over its LEFT argument rebuilding every cell — so appending one row to a list of length k -// allocates k+1 cells and abandons the k that were there. Appending n rows one at a time -// allocates about n squared over two. -// -// On the measured subject that is 10,444 claims, so roughly 54.6 MILLION cons cells for the -// claim list alone, each a variant carrying a boxed field vector. Manifest evaluation was -// observed peaking around 38 GB — about 29 GB above the prepared graph it starts from — to -// produce 10,444 records holding a module path, a function name, a mode and an integer. Nothing -// about the RESULT is large; all of it was the intermediates. -// -// WHY THIS SURVIVED UNTIL THE CUT, because it is the more useful half of the finding: the -// deleted floor packed workers to a memory envelope and prepared a separate small subject per -// worker, so no execution ever accumulated one 10,444-element list this way. The quadratic was -// always here; the governor kept it under the size where it is visible. Folding the whole roster -// once is what turned a latent cost shape into a measured peak, which is the deletion surfacing -// what the old structure was hiding rather than a regression the cut introduced. -// -// Prepending is O(1) per row and `list_reverse` is one linear prepend fold, so the population is -// built in time and allocation linear in its own size. Both populations are REVERSED-ORDER while -// the scan runs and are restored exactly once, in `required_floor_manifest`. The field names say -// so, because a list whose order is a lie is worse than a slow one: the obligation is discharged -// in a single named place rather than assumed by each reader. -type ClaimScanReversed { - claims_reversed: List - refusals_reversed: List -} - -data claim_scan_reversed_empty: ClaimScanReversed = ClaimScanReversed { - claims_reversed: no_required_floor_claims, - refusals_reversed: no_manifest_refusals - } - -// A SITE BECOMES A CLAIM DIRECTLY. There is no identity step between them any more, because the -// site arrives carrying the module the host read it from, so identification cannot fail. -// -// The refusal arm this replaced matched `WitnessIdentityRefused` and produced -// `DeclarationIdentityAmbiguous`. It had no reachable producer: sites and the entry-to-module -// list were projected from ONE inventory keyed by the same file path, so the join always found -// exactly one module. Keeping an arm for it would be validation of a state with no constructor. -// -// `refusals_reversed` survives because duplicate enrollment is a real refusal, discovered after -// the scan rather than during it. -// THE MANIFEST DECIDES ADMISSION, not the discovery that fed it. A long-home site produces no -// claim row, so the exclusion happens where the module's own name can be read rather than in a -// host-side test on its file path. -// -// A LIVE-TREE SITE IS EXCLUDED FOR A DIFFERENT REASON, and the difference matters. The long -// home is a hack. This one is a fact about the witness: a module declaring -// `LiveTreeDisposition = ReadsLiveTree` reads state outside its resolved closure, so it CANNOT -// execute in the hermetic frame this floor runs — it does not fail because it is broken, it -// fails because it was handed the wrong evaluator. Forcing it hermetic produced 172 refusals -// against missing mocks, and every one of them was the floor asking a live-tree witness to -// answer without the tree. -// -// Excluding them is parity with what the old floor already did: main defers 1,073 rows from -// per-PR discovery, 613 of them declaring exactly this. These rows were never covered per-PR -// before this cut and are not covered now — what changes is that the reason is an authored -// declaration read from the module's own source rather than a deferral nobody could see. -// -// This is NOT a disposition in the modelled sense and must not be mistaken for one: it names no -// executing consumer, so the coverage owed is real and outstanding. It dissolves when a wet -// lane exists to run them. -fn scan_site( - acc: ClaimScanReversed, - site: WitnessSite, - mode: ExecutionMode -) -> ClaimScanReversed { - match module_is_long_home(module_path: site.module_path) || site.reads_live_tree { - true => acc - false => - ClaimScanReversed { - claims_reversed: Cons { - head: RequiredFloorClaim { - declaration: WitnessIdentity { - module_path: site.module_path, - function: site.function - }, - execution_mode: mode, - budget_ms: required_floor_claim_budget_ms(), - warn_ms: required_floor_claim_warn_ms() - }, - tail: acc.claims_reversed - }, - refusals_reversed: acc.refusals_reversed - } - } -} - -fn scan_site_list( - acc: ClaimScanReversed, - sites: List, - mode: ExecutionMode -) -> ClaimScanReversed { - fold_list(xs: sites, empty: acc, cons: fn(inner, s) { - scan_site(acc: inner, site: s, mode: mode) - }) -} - -// COMPLETENESS IS AN IDENTITY JOIN, NEVER A COUNT. Two populations of equal size can name -// different declarations, and a count comparison reports that as clean. So the duplicate check -// asks about a qualified declaration's ENROLLMENTS, never about how many rows exist. -// -// ENROLLMENT IS A STATE PER NAME, not a group to be re-collected. The former shape asked, for -// each first-seen name, `claims_named(claims, qualified)` — a fold over the WHOLE claim list — -// while also testing membership with `contains` over a linearly growing `seen` list that was -// itself built by quadratic append. On 10,444 claims with mostly distinct names that is three -// separate quadratic populations layered on one pass, and none of them retains anything the -// verdict needs: the group was collected only to take its length and compare its modes. -// -// `QualifiedEnrollment` carries exactly what those questions consume, and it is a state machine -// over occurrences rather than a collection of them. Absence from the map is the zero case. -// The reference mode is the FIRST occurrence's, which is what the group form compared against, -// and once conflicting it stays conflicting — so a declaration enrolled Hermetic, Hermetic, Wet -// reports the conflict rather than reporting agreement from a prefix. -type QualifiedEnrollment - = FirstEnrollment { mode: ExecutionMode } - | RepeatedSameMode { mode: ExecutionMode } - | RepeatedConflictingModes - -fn enrollment_after(prior: QualifiedEnrollment, mode: ExecutionMode) -> QualifiedEnrollment { - match prior { - FirstEnrollment { mode: first } => - if execution_mode_eq(left: first, right: mode) { - RepeatedSameMode { mode: first } - } else { - RepeatedConflictingModes - } - RepeatedSameMode { mode: first } => - if execution_mode_eq(left: first, right: mode) { - RepeatedSameMode { mode: first } - } else { - RepeatedConflictingModes - } - RepeatedConflictingModes => RepeatedConflictingModes - } -} - -// The two duplicate arms are kept APART on purpose. The same declaration twice under one mode -// is a roster defect: it would run twice and the receipt would carry two rows for one -// subject. The same declaration under two modes is a contradiction about how it must execute, -// and the tempting repair — pick one — discards the fact worth knowing. Both refuse; only the -// second is unrecoverable without a decision. A name enrolled exactly once refuses nothing. -// Prepends onto the accumulator rather than returning a fragment to be appended: a zero-or-one -// fragment joined with `list_append` would rebuild the accumulator once per name, which is the -// same quadratic being removed above, merely over a smaller population. "n is small here" is not -// a fact that stays true — this list is one row per DUPLICATED declaration today because the -// roster is mostly clean, and the shape must not depend on the roster staying that way. -fn enrollment_refusal_prepend( - acc: List, - qualified: String, - enrollment: QualifiedEnrollment -) -> List { - match enrollment { - FirstEnrollment { mode: _ } => acc - RepeatedSameMode { mode: _ } => - Cons { head: DeclarationEnrolledTwice { qualified: qualified }, tail: acc } - RepeatedConflictingModes => - Cons { - head: DeclarationEnrolledWithConflictingModes { qualified: qualified }, - tail: acc - } - } -} - -type ManifestScan { - enrollments: Map - first_seen_reversed: List -} - -data manifest_scan_empty: ManifestScan = ManifestScan { - enrollments: empty_map(), - first_seen_reversed: no_seen_qualified_names - } - -// ONE refusal per distinct duplicated declaration, ordered by FIRST occurrence — the same -// contract the group form had, reached without collecting the group. `first_seen_reversed` -// records a name only when it is new, so it is both the dedup and the order, and a declaration -// enrolled three times still reports one refusal about itself rather than three. -// `first_seen_reversed` is walked in reverse — last-seen first — and the prepending fold flips -// it back, so the emitted refusals come out in FIRST-OCCURRENCE order with one reversal rather -// than two. -fn duplicate_refusals(claims: List) -> List { - let scan = fold_list(xs: claims, empty: manifest_scan_empty, cons: fn(acc, c) { - let qualified = required_floor_claim_qualified(claim: c) - match map_lookup(m: acc.enrollments, key: qualified) { - Absent => ManifestScan { - enrollments: map_insert( - m: acc.enrollments, - key: qualified, - value: FirstEnrollment { mode: c.execution_mode } - ), - first_seen_reversed: Cons { head: qualified, tail: acc.first_seen_reversed } - } - Present { value: prior } => ManifestScan { - enrollments: map_insert( - m: acc.enrollments, - key: qualified, - value: enrollment_after(prior: prior, mode: c.execution_mode) - ), - first_seen_reversed: acc.first_seen_reversed - } - } - }) - fold_list( - xs: scan.first_seen_reversed, - empty: no_manifest_refusals, - cons: fn(acc, qualified) { - match map_lookup(m: scan.enrollments, key: qualified) { - Present { value: e } => - enrollment_refusal_prepend(acc: acc, qualified: qualified, enrollment: e) - Absent => acc - } - } - ) -} - -// THE MANIFEST. One fold over the observed populations, producing one claim list and the -// refusals that make it inadmissible. -// -// `hermetic_sites` are the discovered witnesses; `wet_sites` are the rows whose subject IS a -// live effect and which therefore need a dispatching frame. They arrive as separate lists -// rather than one list with a flag because the flag would have to be derived from something, -// and the only available something is `reads_live_tree` — the derivation this module refuses -// to make. -// THIS IS THE ONE PLACE REVERSED ORDER IS DISCHARGED. Both scan populations were prepended and -// are restored here, once each, before anything reads them. Hermetic claims precede wet ones and -// each class keeps its site order, exactly as the appending form produced them. -fn required_floor_manifest( - hermetic_sites: List, - wet_sites: List -) -> ClaimScan { - let after_hermetic = scan_site_list( - acc: claim_scan_reversed_empty, - sites: hermetic_sites, - mode: Hermetic - ) - let after_wet = scan_site_list( - acc: after_hermetic, - sites: wet_sites, - mode: Wet - ) - let claims = list_reverse(xs: after_wet.claims_reversed) - ClaimScan { - claims: claims, - refusals: list_append( - left: list_reverse(xs: after_wet.refusals_reversed), - right: duplicate_refusals(claims: claims) - ) - } -} - -fn required_floor_attempt( - subject: ObservedSubjectIdentity, - hermetic_sites: List, - wet_sites: List -) -> RequiredFloorAdmission { - let scan = required_floor_manifest( - hermetic_sites: hermetic_sites, - wet_sites: wet_sites - ) - if length(xs: scan.refusals) == 0 { - RequiredFloorRunnable { - attempt: RequiredFloorAttempt { subject: subject, claims: scan.claims } - } - } else { - RequiredFloorRefused { refusals: scan.refusals } - } -} - -// ONE PREPARATION PER ATTEMPT, and it holds by SHAPE rather than by counting. An attempt -// names exactly one subject, and a claim carries only an identity — no source root, no -// index, no resolver, no entry path — so nothing a consumer of this model holds can name a -// second compiler world. An entry-private preparation is unrepresentable here, not merely -// absent, and that is why there is no cache to look in and no memo to hide repeated demands. -fn required_floor_preparation_count(attempt: RequiredFloorAttempt) -> Int { - 1 -} - -fn required_floor_claim_count(attempt: RequiredFloorAttempt) -> Int { - length(xs: attempt.claims) -} - -// The attempt's effect envelope, derived from its claims rather than declared beside them. A -// separately declared envelope drifts: a manifest gains a Wet row while a hand-written -// Hermetic declaration keeps saying the run reaches no live effects. It widens rather than -// narrows, which is the fail-closed direction — an envelope narrower than some claim would -// let a consumer treat a live-effect run as inert. Record is widest because it dispatches AND -// captures. -fn required_floor_effect_envelope(attempt: RequiredFloorAttempt) -> ExecutionMode { - fold_list(xs: attempt.claims, empty: Hermetic, cons: fn(acc, c) { - match acc { - Record => Record - Wet => match c.execution_mode { - Record => Record - Wet => Wet - Hermetic => Wet - } - Hermetic => c.execution_mode - } - }) -} From 0141f6262b8c9aff3a8425ffcb1ff7d002a06d25 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 19 Aug 2026 04:59:20 +0000 Subject: [PATCH 2/2] Delete record_value with the fold that used it Review 53686: its only call sites were the WitnessSite / ObservedSubjectIdentity marshalling into the interpreter, both deleted with the manifest path. A helper whose only purpose was to construct values for a deleted consumer is residue, not a utility. Co-Authored-By: Claude Opus 5 (1M context) --- src/v1/stage0/src/cli_run.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index 069b04a2357..c3cdf9a5997 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -39155,22 +39155,6 @@ fn str_list(items: impl IntoIterator) -> v1_interpreter::Value { )) } -fn record_value( - ctx: &v1_interpreter::InterpContext, - type_name: &str, - fields: Vec<(&str, v1_interpreter::Value)>, -) -> v1_interpreter::Value { - v1_interpreter::Value::Record { - type_name: ctx.sym(type_name), - fields: Rc::new( - fields - .into_iter() - .map(|(n, v)| (ctx.sym(n), v)) - .collect::>(), - ), - } -} - /// The module carrying the floor's authored thresholds and the long-home roster. Named once, /// and evaluated in its OWN exact scope exactly as every claim is, so the module that supplies /// the admission facts is not privileged with a wider namespace than the claims they admit.