Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f6f1241
guarantee_rung_drop: close the record #9612 left unterminated
claude Aug 28, 2026
d35c4e2
Plan: hand off the per-invocation whole-tree tax finding
claude Aug 28, 2026
055bebc
Correct the pool-tax finding: linear ~20-25ms/pool-module eager graph…
claude Aug 28, 2026
8cc165a
cli_run split 1/n: move seven census clusters to cli_run/ submodules …
claude Aug 28, 2026
fe1c98a
cli_run split 2/n: witness_gates, emit_host, complexity_gates, doc_gr…
claude Aug 28, 2026
c0ef93f
cli_run split: widen eight report/plan types to pub(crate) (private-i…
claude Aug 28, 2026
dd516ad
Plan log: cli_run decomposition progress and the two deferred cores
claude Aug 28, 2026
1b0dfdc
Merge main: filename reorg + witness-admission scan update, re-homed …
claude Aug 28, 2026
d8a10c2
cli_run split 3/n: fallback_arm_census, p1_cohort, owned_data, live_r…
claude Aug 28, 2026
4413e20
Remove merge markers both brace-fixes left in guarantee_rung_drop.dag
claude Aug 28, 2026
fd2ffeb
cli_run split 4/n: entry_resolve — the resolver/index core (75 items,…
claude Aug 28, 2026
b7b009c
cli_run split 5/n: required_floor_runner — the floor fold and claim e…
claude Aug 28, 2026
9f3c79a
Plan log: resolver core and floor runner moved
claude Aug 28, 2026
1ce115a
Plan: standing dependency map (store/native/delete-eval-loop) and the…
claude Aug 29, 2026
3dfeebd
Merge main: port #9656-touched fns into split modules; fix infer_sema…
claude Aug 29, 2026
da54eca
Plan log: bisect pins the trim-Null runtime regression to #9344
claude Aug 29, 2026
ef93961
Fix #9344's effect-output regression: the from-key property value is …
claude Aug 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dag/gunbc/guarantee_rung_drop.dag
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ data wall_deadline_shared_fill_attribution_stall: GuaranteeStall = GuaranteeStal
population: BoundedPopulation { members: Cons { head: "v1_interpreter.arm_wall_deadline", tail: Cons { head: "v1_interpreter.wall_deadline_remaining_ms", tail: Cons { head: "v1_interpreter.wall_deadline_exceeded_error", tail: Empty {} } } } },
next_rung_trigger: "the required floor's ledger reports any INTERRUPTED-BEFORE-VERDICT row whose clock is Wall, at which point the wall deadline must read a fill-netted clock exactly as v1_interpreter.budgeted_cpu_nanos does for the CPU deadline"
}

data heterogeneous_child_list_stall: GuaranteeStall = GuaranteeStall {
subject: "a type's child list may hold BOTH a type node and a field node, and v1.04_types child_type_node tells them apart by whether `inferred` is populated -- a stamp v1.02_parse field_to_child_node writes at PARSE TIME as Resolved, before any resolution has run. A child list that mixes the two kinds makes that accessor return the FIELD node where its caller expects the TYPE, with no diagnostic",
current: OutsideTheLadder,
Expand Down
130 changes: 130 additions & 0 deletions docs/plans/repo-stability-2026-08.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,133 @@ stops contaminating sessions with dead premises.
count unchanged vs main (164). NEXT CANDIDATE ROUND: delete the 48 stale
authority-only plan carriers themselves (imports/rosters/doc_graph edits), and
the docs/plans doc-to-doc islands.

## Finding — per-invocation whole-tree pool tax (2026-08-28, CORRECTED same day)

AN EARLIER REVISION OF THIS SECTION CLAIMED A CWD-GATED SWITCH (identical trees
<0.5s outside a checkout) AND IS REPLACED WHOLE: those fast controls were
PANICS — `repo_relative_path_normalized` aborts on roots outside the process
workspace root, and the discarded stderr was misread as fast success. The
fabricated-fast twin of execution-provenance loss. `git rev-parse` is workspace
discovery only, not a heavy-work toggle.

ESTABLISHED by succeeding runs (entry compiled, NoSuchFunction reached) over
subset roots inside the workspace, entry `std/abi.dag` (imports nothing):
140 modules 3.5s · 1637 39s · 2962 (dag) 63s · 4308 (dag+src/v2) 81–99s.
LINEAR at ~20–25ms per POOL module, paid per process invocation, independent of
the entry (widest closure 110s vs smallest 81s on the same roots).

MECHANISM (gdb stacks + code read; all hand-Rust in src/v1/stage0/src/cli_run.rs):
`resolve_entry_graph` routes every run through the process shared index
(`try_process_shared_index_for_pool`); building it (`new_multi_entry_index_shell`)
EAGERLY constructs `build_module_graph_facts_live` — a tolerant parse of EVERY
pool module (`reference_resolution_facts`, `module_declaration_facts`, import +
strict-reference adjacency at two tiers) — plus `build_module_path_index`,
another whole-pool parse. Hot leaves: `v1_std_core::build_newline_index`
(im::Vector push_back per element — plain-Vec shape) and `v1_std_core::intern`
String clones in `pre_intern_tokens`.

WHY THE FACTS EXIST (per the in-code comment block): loader-tier adjacency and
selection-tier adjacency (affected-set selection). A single-entry run needs at
most one entry's loader closure; it pays both tiers over the whole pool. The
facts ARE memoized (thread-local MODULE_GRAPH_FACTS_CACHE / PROCESS_RESOLVE_INDEX),
so one process pays once — but every PROCESS pays cold, and CI phases,
emit-compile entries, and belt ticks are one process per invocation.

RELATION TO .dag: acknowledged hand-Rust area — 🟡 dissolve-on markers cite the
cli-run hollowing plan (`dag/gunbc/plans/cli_run_hollowing_plan.dag`,
`gunbc.cli_run_hand_rust_area_ledger`); `import_closure_live_paths` labels
itself "Host realization of v2.lens.module_graph.import_closure_live"; path
admission modeled by `gunbc.cli_run_repo_grant`. The MODEL is .dag; the
execution that costs the time is hand-Rust.

NOT ESTABLISHED: the floor's 22-min `compile.reconcile`
(`typecheck_with_census_extra`, ~300ms/module) is a separate larger cost, not
attributed here. REPRO: in-workspace subset roots (untracked dirs), success
judged by the NoSuchFunction cause line, never by wall time with output
discarded; gdb -p <pid> -batch -ex "thread apply all bt" during the slow window.

## cli_run.rs decomposition (started 2026-08-28, branch claude/repo-stability-priorities-frtsy4)

50,536 → 46,443 lines; 13 clusters moved to src/v1/stage0/src/cli_run/ submodules
(pure code motion, build-verified, smoke-tested): test_migration, compile_clean,
non_fold_residue, class_b_census, languages_census, external_authority,
inert_carrier, witness_gates, emit_host, complexity_gates, doc_graph,
declared_refs, census_heads. Mechanics: submodule carries `use super::*` + the
parent's use-header; parent re-exports `pub(crate) use <mod>::*` (paths stable);
bin-consumed fns get explicit `pub use`; private moved items widen to pub(crate);
eight report/plan types widened for the private-interface lint (CI: -D warnings).
lib.rs is generated and untouched — submodule declarations live in cli_run.rs,
matching the existing pattern (declaration_index, phase_profile, ...).

DELIBERATELY NOT MOVED YET, to avoid conflicting with in-flight operator work:
the resolver/index core (resolve_entry_*, build_module_*, import_closure_*,
whole_tree_*, the shared-index thread_locals — the pool-tax subject) and the
floor runner (floor_*, run_required_*, budget/accounting). Move each in a quiet
window; the extraction recipe is in the split commits' messages.
- 2026-08-28 (later): the two deferred cores are moved with operator approval —
entry_resolve (75 items, ~2.5k lines: shared index, resolve store, module
graph facts, path index, typed-module cache) and required_floor_runner
(49 items, ~4.8k lines: run_required_floor, claim eval/measurement,
discovery, diff observation, resource sampling). cli_run.rs 50,536 → 38,636
lines, 26 submodules. Remainder: ~450 fns of mixed verbs/helpers plus ~350
embedded test fns; further carving is ordinary follow-up, no core left.

## The dependency map (2026-08-29, standing — replaces re-deriving this in chat)

The interpreter has four roles: R1 witness executor · R2 orchestration executor
· R3 v2's executor (v2 stages are .dag, so v2 compiles by being interpreted) ·
R4 the host-effect seam (builtin handlers). Emitting .dag→Rust does NOT need
the interpreter (the v1 passes are native); interpretation is only evaluation
without emission. Three separable decisions:

1. REALIZATION STORE (backport of v2.std.materialize's model into a v1-host
persistent content-keyed store; digest authority already shared via
std.content_hash/fnv1a64). No dependency on the interpreter either way —
the interpreter becomes a CLIENT. Gives fast interpreted execution, CI in
minutes, fast v2 compile loop. v2 SELF-HOST DEPENDS ON THIS AND NOT ON
DECISIONS 2-3.
2. NATIVE PRODUCERS PER FAMILY (emit witnesses etc. into content-addressed
native bundles; store's producer flips per family; interpreter drains).
Optional per family; needs emitter perf + diagnostics work.
3. DELETE THE EVAL LOOP (only after 2 completes everywhere; R4 survives as the
runtime library with a new caller; may never be worth taking to zero — a
bounded evaluator for bootstrap/dev is near-free).

digest authority ──► store ──► fast interpreted execution ◄── v2 self-host
├──► native producers per family
└──────────┴──► interpreter drains ──► (optional) delete
eval loop; keep effect runtime

## The one execution test (anti-planning: build this, then judge the plan)

SUBJECT: persist the process-shared index's derived facts across processes,
keyed on content digest. Concretely: module path index + module graph facts
(and optionally the typed-module cache) in cli_run/entry_resolve.rs get a
disk-backed store under target/ keyed on (source file digests, binary identity).
ACCEPTANCE, binary and pre-registered: on an unchanged tree, the SECOND
`gunbc run --source-root dag --source-root src/v2 --entry dag/std/abi.dag`
completes in <10s (cold today: ~81–99s), AND the warm facts are byte-identical
to cold-derived facts (the §5 purity oracle, asserted by execution). A miss
(any file changed) re-derives fail-closed. If the warm run is not <10s or the
oracle disagrees, the store thesis as specified is refuted and the plan gets
rewritten before anything else is built on it.
WHY THIS ONE: smallest end-to-end existence proof of the store (one producer,
one consumer, one oracle); kills the measured entry-independent pool tax; the
same mechanism CI-minutes and the v2 loop need; ~a day; pass/fail visible in
one command run twice.
- 2026-08-29: REGRESSION PINNED BY BISECT — main's converge actuator dies with
`trim expects a string argument, got Null`. First bad commit: 655f82a74
(#9344, "Carry occurrence identity on every semantic v1 Node"). Mechanics at
the crash site (dag/gunbc/repo/repo_local_git_config.dag observe_binding_at_repo):
the effect result of git.Core.ConfigLocalGetInRepo reads `.success` fine
(the branch is taken) but `.value` comes back Null — a record-field read on
an effect result resolving to Null post-#9344, so the suspect is field
lookup / effect-result decode interacting with the new occurrence identity.
Repro: build any commit >= 655f82a74, run
`gunbc run --source-root dag --source-root src/v2 --entry
dag/gunbc/repo/repo_local_git_config.dag --function converge`.
Likely blast radius: any interpreted entry reading effect-result fields
(belt, deploys, gates). Not fixed here — #9344 is the operator's own thread.
Also fixed forward on this branch: #9656 omitted TypeEnv.unit_variant_index
in six bin/infer_semantics_witness.rs literals (main's full build is red).
2 changes: 1 addition & 1 deletion src/v1/02_parse.dag
Original file line number Diff line number Diff line change
Expand Up @@ -2869,7 +2869,7 @@ fn parse_optional_from_key(tokens: TokenStream, ctx: ParseContext) -> FromKeyRes
let key = tok2.value.text
let value_mint = mint_parsed_node_identity(ctx: ctx)
let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx)
let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: key, expr_data: NoExprData, children: [], inferred: none, span: token_span(tok: tok2), name_span: token_span(tok: tok2))
let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: key, expr_data: ExprLiteral { value: LitStr { value: key } }, children: [], inferred: none, span: token_span(tok: tok2), name_span: token_span(tok: tok2))
let property = make_field_init_node(occurrence_identity: property_mint.identity, name: "from_key", value: value, span: token_span(tok: tok), name_span: token_span(tok: tok))
FromKeyResult { properties: [property], tokens: token_stream_advance(stream: tokens, n: 2), ctx: property_mint.ctx, err: none }
}
Expand Down
6 changes: 5 additions & 1 deletion src/v1/stage0/examples/prep_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ fn main() {
prepared.modules_resolved,
prepared.modules_excluded
),
Err(e) => eprintln!("prep refused in {:?}: {}", t.elapsed(), &e[..e.len().min(2000)]),
Err(e) => eprintln!(
"prep refused in {:?}: {}",
t.elapsed(),
&e[..e.len().min(2000)]
),
}
}
6 changes: 6 additions & 0 deletions src/v1/stage0/src/bin/infer_semantics_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ fn empty_type_env() -> Rc<TypeEnv> {
authored_import_names: Rc::new(im::HashMap::new()),
bindings: Rc::new(im::HashMap::new()),
str_bindings: Rc::new(im::HashMap::new()),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down Expand Up @@ -1072,6 +1073,7 @@ fn optional_match_exhaustiveness_reports_missing_absent() {
authored_import_names: Rc::new(im::HashMap::new()),
bindings: Rc::new(im::HashMap::new()),
str_bindings: Rc::new(im::HashMap::new()),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down Expand Up @@ -1101,6 +1103,7 @@ fn optional_match_exhaustiveness_rejects_some_and_none() {
authored_import_names: Rc::new(im::HashMap::new()),
bindings: Rc::new(im::HashMap::new()),
str_bindings: Rc::new(im::HashMap::new()),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down Expand Up @@ -1130,6 +1133,7 @@ fn optional_match_exhaustiveness_accepts_present_and_absent() {
authored_import_names: Rc::new(im::HashMap::new()),
bindings: Rc::new(im::HashMap::new()),
str_bindings: Rc::new(im::HashMap::new()),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down Expand Up @@ -1267,6 +1271,7 @@ fn resolve_node_uses_node_name_for_lookup() {
user_binding.clone(),
)])),
str_bindings: Rc::new(im::HashMap::from_iter([("User".to_string(), user_binding)])),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down Expand Up @@ -1990,6 +1995,7 @@ fn resolve_applied_generic_struct_expands_to_conj_for_field_lookup() {
box_binding.clone(),
)])),
str_bindings: Rc::new(im::HashMap::from_iter([("Box".to_string(), box_binding)])),
unit_variant_index: Rc::new(im::HashMap::new()),
ancestry_str_bindings: Rc::new(im::HashMap::new()),
parents: Rc::new(vec![]),
recursive_types: Rc::new(vec![]),
Expand Down
Loading
Loading