Skip to content
Merged
49 changes: 12 additions & 37 deletions docs/plans/seed-shrink-census.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,43 +190,18 @@ The 88 v1 integration-test modules (~30k LOC, **939 `#[test]` fns**, `pipeline.r
| **cache / fixture** | 916 | ~15 | `cache_purity_verdict_test.dag`, `cache_key_completeness_test.dag` |
| **cross-cutting** | 917 | ~15 | `generated_conformance_floor_test.dag` (cross_rep), `generic_alias_coproduct_instantiation_test.dag` |

### 5B. T2 coverage debt — no floor equivalent (collapse cannot proceed past)

These v1 modules have **no identified `*_test.dag` witness** (by stem or topic scan). Each needs a floor witness authored **before** the v1 test deletes:

| LOC | v1 module | v1 tests | Required floor witness (to author) |
| ---: | --- | ---: | --- |
| 1,530 | `infer_semantics` | 51 | Infer semantics oracle suite → `src/v2/test/claim/infer_semantics_*_test.dag` |
| 1,300 | `interp_recorded_fixture_test` | 24 | Recorded-fixture replay witnesses |
| 1,238 | `source_audit` | 41 | Source-audit / dep-graph witnesses |
| 733 | `effects` | 36 | Effect-shape / idempotency witnesses |
| 458 | `resolve_cross_process_cache_test` | 10 | Resolve-cache cross-process witnesses |
| 364 | `extdeps_shape_transport_policy_lens_test` | 7 | Lens already in `.dag`; needs floor `*_test.dag` consumer |
| 330 | `floor_skip_discovery_host_test` | 9 | Floor-skip discovery witnesses |
| 274 | `auth_declared_but_unwired_witness_test` | 7 | Auth wiring witnesses |
| 242 | `measure_field_access_test` | 9 | Measure emit/access witnesses |
| 234 | `coverage_completeness_lens_test` | 6 | Coverage-completeness lens floor witness |
| 221 | `list_free_monoid_chokepoint_test` | 8 | FreeMonoid generic-inference witnesses |
| 208 | `consumed_input_closure_drift_test` | 2 | Wiring-liveness witnesses |
| 206 | `ir_fixture_seam_soundness_test` | 3 | IR-fixture seam witnesses |
| 187 | `sub_value_lattice_factor_test` | 8 | Sub-value lattice witnesses |
| 186 | `pd3_adversarial` | 8 | Adversarial parse witnesses |
| 181 | `route_a_final_six_test` | 6 | Route-A emit regression witnesses |
| 179 | `variant_owner_disambiguation_test` | 3 | Variant-owner resolve witnesses |
| 96 | `fn_as_value_test` | 2 | Fn-as-value infer witnesses — shrunk from 296/10 by #6140, residual only |
| 79 | `type_alias_phantom_param_test` | 2 | PhantomData type-alias emit witnesses |
| 81 | `languages_consumer_census_lens_test` | 1 | Lens has `.dag`; floor witness missing |
| 85 | `fact_cardinality_lens_test` | 1 | Lens has `.dag`; floor witness missing |
| 65 | `coproduct_reflection_conformance_test` | 1 | Pinned-harness residual after #6142 |
| 146 | `witness_option_bridge_test` | 3 | Optional/`Value::Null` bridge witnesses — shrunk from 223/6 by #6153, residual only |
| 92 | `map_lookup_dual_dispatch_test` | 2 | Map-lookup dispatch witnesses — shrunk from 175/6 by #6150, residual only |
| … | *(≈43 more modules < 200 LOC each)* | … | Per-module `*_test.dag` or fold into concern-suite above |

**Migrated off this table (2026-07-02, confirmed gone from `src/v1/tests/src/lib.rs`):** `render_repeat` (#6147), `cron_tag` (#6145), `money_carrier_cost_witness` (#6143) — fully deleted, no residual.

**Debt total:** ~66 modules / ~12.5k LOC / ~380+ `#[test]` fns without floor equivalent (revised down from the stale 71/13k/400+ count above — six rows corrected 2026-07-02 against current `main`).

**Migration rule:** for each v1 test module, the floor `*_test.dag` witness must be **green-by-execution** in `claim_executor` before the v1 `#[test]` module deletes. Bulk-delete of `src/v1/tests` is forbidden.
### 5B. T2 coverage debt — derived live, not hand-maintained

**This is no longer a hand-authored table** (that was a parallel ledger — DESIGN §6 forbids it; the old static snapshot drifted from the tree the moment either side changed). The debt roster is now **computed from the live tree** by `v2.lens.test_migration_debt` (`src/v2/lens/test_migration_debt.dag`), which diffs `src/v1/tests/src/*.rs` modules containing a line-anchored `#[test]` against the floor `*_test.dag` witness roster (the same `witness_layer_roots` corpus the CI floor discovers from) by **exact stem equality** — a module is debt iff no floor witness has the identical stem. (A fuzzy substring match was tried and rejected in review: it let the single largest debt module, `pipeline` — 418 test fns — silently match the unrelated floor stem `typescript_import_pipeline`, hiding rather than counting debt. Exact equality can only ever *overstate* debt by missing a topically-covered-but-differently-named witness, never understate it.)

- **Live counts:** `test_migration_debt_module_count()` / `test_migration_debt_total_loc()` / `test_migration_debt_total_test_fns()` (builtins in `cli_run.rs`, dispatched via `v1_interpreter.rs`).
- **Live roster:** `test_migration_debt_module_names()` returns the current debt module list — run this instead of reading a table to see which v1 modules still need a floor witness.
- **Floor gate:** `src/v2/test/claim/manual/test_migration_debt_test.dag` enrolls three shrink-only ratchet witnesses (module count / total LOC / total test-fn count each `<=` their baseline) — floor-discovered and green-by-execution like every other witness. Debt may shrink freely; it must never silently grow.
- **Baselines** (set at this table's dissolution, re-verify by running the lens): 77 modules / 28,546 LOC / 912 `#[test]` fns.

**Migration rule (unchanged):** for each v1 test module, the floor `*_test.dag` witness must be **green-by-execution** in `claim_executor` before the v1 `#[test]` module deletes. Bulk-delete of `src/v1/tests` is forbidden. When `test_migration_debt_module_count()` reaches 0, §5 test-migration is done — no table to keep in sync.

Modules migrated off `src/v1/tests/src/lib.rs` since the baseline was set (2026-07-02 onward) shrink these live counts automatically on next lens run — no table edit needed.

---

Expand Down
146 changes: 146 additions & 0 deletions src/v1/stage0/src/cli_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8306,6 +8306,152 @@ pub fn doc_graph_doc_count() -> i64 {
doc_graph_report().doc_count as i64
}

// Live derivation of docs/plans/seed-shrink-census.md §5B ("T2 coverage debt"): that table was a
// hand-maintained snapshot of v1 test modules with no floor `*_test.dag` equivalent. This walks
// `src/v1/tests/src/*.rs` (modules containing `#[test]`) and `corpus_dag_files()` (the same
// witness-layer-roots roster the floor uses) and diffs them by stem, so the debt roster tracks
// the live tree instead of drifting the moment either side changes.
struct TestMigrationDebtEntry {
module: String,
loc: i64,
test_fn_count: i64,
}

struct TestMigrationDebtReport {
entries: Vec<TestMigrationDebtEntry>,
}

fn test_migration_debt_v1_test_dir() -> PathBuf {
workspace_root().join("src/v1/tests/src")
}

fn test_migration_debt_stem(name: &str) -> String {
let stem = name
.strip_suffix(".rs")
.or_else(|| name.strip_suffix(".dag"))
.unwrap_or(name);
stem.strip_suffix("_test").unwrap_or(stem).to_string()
}

fn test_migration_debt_floor_stems() -> Vec<String> {
let mut stems: Vec<String> = corpus_dag_files()
.into_iter()
.map(|(path, _)| path)
.filter(|p| is_test_dag(p))
.map(|p| {
let file_name = std::path::Path::new(&p)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(&p)
.to_string();
test_migration_debt_stem(&file_name)
})
.collect();
stems.sort();
stems.dedup();
stems
}

// Exact-stem equality only. A substring match (either direction) was tried and reviewed
// unsound: e.g. v1 stem "pipeline" (the single largest debt module, 418 `#[test]` fns) is a
// substring of the floor stem "typescript_import_pipeline", so a fuzzy match falsely marked
// the whole module covered — hiding debt rather than counting it. Exact equality is decidable
// and cannot understate debt; it may list a module the operator judges topically covered by a
// differently-named floor witness, which is a correct false-debt (never a false-coverage) bias.
fn test_migration_debt_stem_covered(v1_stem: &str, floor_stems: &[String]) -> bool {
floor_stems.iter().any(|floor_stem| floor_stem == v1_stem)
}

fn build_test_migration_debt_report() -> TestMigrationDebtReport {
let dir = test_migration_debt_v1_test_dir();
let floor_stems = test_migration_debt_floor_stems();
let mut entries = Vec::new();
let read_dir = match std::fs::read_dir(&dir) {
Ok(rd) => rd,
Err(_) => return TestMigrationDebtReport { entries },
};
let mut paths: Vec<std::path::PathBuf> = read_dir
.filter_map(|e| e.ok())
.map(|e| e.path())
.filter(|p| p.extension().map(|e| e == "rs").unwrap_or(false))
.collect();
paths.sort();
for path in paths {
let content = match std::fs::read_to_string(&path) {
Ok(c) => c,
Err(_) => continue,
};
// Line-anchored so `#[test]` mentioned in a comment/string/doc example doesn't inflate
// the count (a `content.matches` substring scan would).
let test_fn_count = content
.lines()
.filter(|line| line.trim() == "#[test]")
.count() as i64;
if test_fn_count == 0 {
continue;
}
let file_name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or_default()
.to_string();
let stem = test_migration_debt_stem(&file_name);
if test_migration_debt_stem_covered(&stem, &floor_stems) {
continue;
}
entries.push(TestMigrationDebtEntry {
module: file_name,
loc: content.lines().count() as i64,
test_fn_count,
});
}
TestMigrationDebtReport { entries }
}

fn test_migration_debt_report() -> &'static TestMigrationDebtReport {
static REPORT: OnceLock<TestMigrationDebtReport> = OnceLock::new();
REPORT.get_or_init(build_test_migration_debt_report)
}

pub fn test_migration_debt_module_count() -> i64 {
test_migration_debt_report().entries.len() as i64
}

pub fn test_migration_debt_total_loc() -> i64 {
test_migration_debt_report()
.entries
.iter()
.map(|e| e.loc)
.sum()
}

pub fn test_migration_debt_total_test_fns() -> i64 {
test_migration_debt_report()
.entries
.iter()
.map(|e| e.test_fn_count)
.sum()
}

pub fn test_migration_debt_module_names() -> Vec<String> {
test_migration_debt_report()
.entries
.iter()
.map(|e| e.module.clone())
.collect()
}

// Discriminating red witness for the stem matcher: `witness_option_bridge_test.rs` has a live
// floor counterpart (`witness_option_bridge_test.dag`) and must NOT appear in the debt roster.
// This goes red if the matcher regresses to comparing an un-stripped `.dag` suffix against a
// stripped `.rs` stem (as it did before this function existed), since every module would then
// spuriously report as debt.
pub fn test_migration_debt_known_covered_module_is_not_debt() -> bool {
!test_migration_debt_module_names()
.iter()
.any(|m| m == "witness_option_bridge_test.rs")
}

// Host-fed fact extraction for `v2.lens.host_language_transport_script` — the lens `.dag` table
// owns verdict logic; this bridge only projects `shell.Exec.Run` script-arg shapes from parsed
// modules. DISSOLUTION: node-tree reader at gunbc#5364; until then one shared host seam (Chunk D).
Expand Down
25 changes: 25 additions & 0 deletions src/v1/stage0/src/v1_compiler_infer_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,31 @@ pub fn builtin_function_registry() -> Rc<HashMap<String, Rc<Node>>> {
int_type(),
);
let m = v1_rt::rc_map_insert(m.clone(), "doc_graph_doc_count".to_string(), int_type());
let m = v1_rt::rc_map_insert(
m.clone(),
"test_migration_debt_module_count".to_string(),
int_type(),
);
let m = v1_rt::rc_map_insert(
m.clone(),
"test_migration_debt_total_loc".to_string(),
int_type(),
);
let m = v1_rt::rc_map_insert(
m.clone(),
"test_migration_debt_total_test_fns".to_string(),
int_type(),
);
let m = v1_rt::rc_map_insert(
m.clone(),
"test_migration_debt_module_names".to_string(),
list_of_type_variable("test_migration_debt_module_name_elem".to_string()),
);
let m = v1_rt::rc_map_insert(
m.clone(),
"test_migration_debt_known_covered_module_is_not_debt".to_string(),
bool_type(),
);
let m = v1_rt::rc_map_insert(
m.clone(),
"inert_carrier_names_live".to_string(),
Expand Down
18 changes: 18 additions & 0 deletions src/v1/stage0/src/v1_interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5871,6 +5871,24 @@ fn eval_builtin(
))),
"doc_graph_doc_count" => Ok(Some(Value::Int(crate::cli_run::doc_graph_doc_count()))),

"test_migration_debt_module_count" => Ok(Some(Value::Int(
crate::cli_run::test_migration_debt_module_count(),
))),
"test_migration_debt_total_loc" => Ok(Some(Value::Int(
crate::cli_run::test_migration_debt_total_loc(),
))),
"test_migration_debt_total_test_fns" => Ok(Some(Value::Int(
crate::cli_run::test_migration_debt_total_test_fns(),
))),
"test_migration_debt_module_names" => {
let names = crate::cli_run::test_migration_debt_module_names();
let items: Vec<Value> = names.into_iter().map(Value::Str).collect();
Ok(Some(list_value(items)))
}
"test_migration_debt_known_covered_module_is_not_debt" => Ok(Some(Value::Bool(
crate::cli_run::test_migration_debt_known_covered_module_is_not_debt(),
))),

"inert_carrier_names_live" => {
let names = crate::cli_run::inert_carrier_names_live();
let items: Vec<Value> = names.into_iter().map(Value::Str).collect();
Expand Down
60 changes: 60 additions & 0 deletions src/v2/lens/test_migration_debt.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module v2.lens.test_migration_debt
import v2.lens.common.construction_justification { ConstructionJustification, WallAfterGrounding }
import std.disposition { SingleAuthority }

import v2.std.collection { List }
import v2.std.logic { Bool }
import v2.std.text { String }

data test_migration_debt_module_count_baseline: Int = 77
data test_migration_debt_total_loc_baseline: Int = 28546
data test_migration_debt_total_test_fns_baseline: Int = 912

fn test_migration_debt_ratchet_holds(live_count: Int, baseline: Int) -> Bool {
live_count <= baseline
}

fn test_migration_debt_live_module_count() -> Int {
test_migration_debt_module_count()
}

fn test_migration_debt_live_total_loc() -> Int {
test_migration_debt_total_loc()
}

fn test_migration_debt_live_total_test_fns() -> Int {
test_migration_debt_total_test_fns()
}

fn test_migration_debt_live_module_names() -> List<String> {
test_migration_debt_module_names()
}

fn test_migration_debt_known_covered_module_is_recognized_as_covered() -> Bool {
test_migration_debt_known_covered_module_is_not_debt()
}

fn test_migration_debt_module_count_ratchet_holds() -> Bool {
test_migration_debt_ratchet_holds(
live_count: test_migration_debt_live_module_count(),
baseline: test_migration_debt_module_count_baseline
)
}

fn test_migration_debt_total_loc_ratchet_holds() -> Bool {
test_migration_debt_ratchet_holds(
live_count: test_migration_debt_live_total_loc(),
baseline: test_migration_debt_total_loc_baseline
)
}

fn test_migration_debt_total_test_fns_ratchet_holds() -> Bool {
test_migration_debt_ratchet_holds(
live_count: test_migration_debt_live_total_test_fns(),
baseline: test_migration_debt_total_test_fns_baseline
)
}

data construction_justification: ConstructionJustification = ConstructionJustification {
class: WallAfterGrounding { dissolves_to: SingleAuthority }
}
25 changes: 25 additions & 0 deletions src/v2/test/claim/manual/test_migration_debt_test.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module v2.test.lens_test_migration_debt.test_migration_debt_test

import v2.lens.test_migration_debt {
test_migration_debt_module_count_ratchet_holds,
test_migration_debt_total_loc_ratchet_holds,
test_migration_debt_total_test_fns_ratchet_holds,
test_migration_debt_known_covered_module_is_recognized_as_covered
}
import v2.std.logic { Bool }

test fn test_migration_debt_module_count_does_not_grow() -> Bool {
return test_migration_debt_module_count_ratchet_holds()
}

test fn test_migration_debt_total_loc_does_not_grow() -> Bool {
return test_migration_debt_total_loc_ratchet_holds()
}

test fn test_migration_debt_total_test_fns_does_not_grow() -> Bool {
return test_migration_debt_total_test_fns_ratchet_holds()
}

test fn test_migration_debt_known_covered_module_is_not_debt() -> Bool {
return test_migration_debt_known_covered_module_is_recognized_as_covered()
}
Loading