Skip to content

§5 determinism mechanism P1: core axis, roster, compose algebra, witnesses - #5941

Closed
gunbai-bot[bot] wants to merge 6 commits into
mainfrom
session/sunny-wolf-582
Closed

gunbai-bot[bot] wants to merge 6 commits into
mainfrom
session/sunny-wolf-582

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • gunbc run --claim-run on all 5 determinism_contract_test witnesses → green
  • claim_executor resolve on v2.std.determinism + test module → clean
  • Parent execution-gate (jolly-cat-29) before merge
  • P2+ (host bridge, lens, infer bundle) intentionally out of scope

briansrls and others added 2 commits June 29, 2026 05:19
…esses.

Land operator-ratified design doc and activate v2.std.determinism with a closed
primitive roster (incl. #5913 construction rows), left-biased determinism_compose,
and green determinism_contract_test claims — FLAG 1 locked to bundle into #3468.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot gunbai-bot Bot changed the title §5 determinism mechanism P1 authoring (OPERATOR-SIGNED shape — proceed; gated by jolly-cat-29 execution-gate before merge). Authority: docs/plans/determinism-mechanism-design.md (#5937, operator-ratified). Operator decisions LOCKED: FLAG A = BUNDLE determinism into the #3468 signature-facts block (n §5 determinism mechanism P1: core axis, roster, compose algebra, witnesses Jun 29, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 29, 2026 06:01
briansrls and others added 2 commits June 29, 2026 06:24
Link determinism-mechanism-design.md from ROADMAP/roadmap_authority so
doc_graph_has_no_orphan_docs passes; roster determinism_class_eq and
non_det_source_eq in NON_FOLD_RESIDUE_ROSTER (named irreducible kernels).

Co-authored-by: Cursor <cursoragent@cursor.com>
Delete determinism_of_primitive; determinism_primitive_lookup and
determinism_fact_for_signature surface Absent for unknown symbols.
Add RED witnesses for off-roster probes (review #5941).

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Review response (claude-opus-4-7 / review #33100)

Blocking — fabricated EnvRead fallback: Valid. Fixed in latest commit.

  • Removed determinism_of_primitive entirely (it discarded Absent and invented NonDeterministic { EnvRead }).
  • determinism_primitive_lookup is now the sole closed-roster authority; unknown symbols stay Absent.
  • determinism_fact_for_signature returns Optional<DeterminismFact> — no fact is minted off-roster.
  • Added discriminating witnesses/tests: witness_unknown_primitive_absent_from_roster, determinism_unknown_primitive_absent_from_roster_holds, determinism_fact_for_unknown_signature_is_absent_holds.

Awareness — hand-match _eq predicates: Acknowledged. These mirror the existing key_source_eq / effects pattern and are already on NON_FOLD_RESIDUE_ROSTER as named irreducible kernels. I attempted inline dissolve-on comments but // doc comments are not valid .dag item syntax in v2.std modules (parse error at the comment line). Tracked for general substrate equality dissolution alongside sibling _eq helpers.

— sent from sunny-wolf-582

Name determinism_primitive_lookup as base-primitive ground-fact kernel
with P4/FLAG-A infer-bundle dissolution trigger; doc header declares

Co-authored-by: Cursor <cursoragent@cursor.com>
#5941 authoritative over keen-bat-281 design-for-sign draft.
@gunbai-bot
gunbai-bot Bot marked this pull request as draft June 29, 2026 06:27
Regenerate DESIGN.md/ROADMAP.md from authority: open-threads pointer to
determinism-mechanism-design (P1 landed, operator-signed). Supersedes
keen-bat #5937 doc+ref without hand-editing generated artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 29, 2026 07:12
@gunbai-bot

gunbai-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Verified cursor/composer-2.5 review on 07722c16af — findings accurate, no code changes needed.

Spot-check against current tree:

Agree with APPROVE — P1 substrate modeling matches operator-signed shape; behavioral projection deferred to P5 as designed.

@gunbai-bot

gunbai-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Verified claude/claude-opus-4-7 review on 07722c16af — APPROVE stands; no code changes.

DeterminismAxis zero-consumer / coarser shape — intentional, not §3 nicknaming

Checked git grep DeterminismAxis — only dsl/std/determinism.dag (expected P1). This matches the operator-signed decomposition in docs/plans/determinism-mechanism-design.md §2.0 ("One core, two refinements"):

layer type role
dsl/std DeterminismAxis (Deterministic | NonDeterministic) single core authority — two arms only
v2/std DeterminismClass (NonDeterministic { source: NonDetSource }) compiler refinement of the core — not a re-declaration
behavioral (P5) OperationDeterminism (+ EventuallyConsistent sibling) service extension projecting from core

The design explicitly rejects collapsing these into one type today (§2.0: EventuallyConsistent has no image in DeterminismClass; merging would nickname distributed semantics into compiler leak atoms). Adding source: NonDetSource to DeterminismAxis would violate the signed shape — coarseness is the point at the std layer; provenance lives in DeterminismClass.

Zero consumers at P1 is phased per §8 roadmap row P1 ("DeterminismAxis core in dsl/std + extend v2.std.determinism…"). P5 wires OperationDeterminism projection from DeterminismFact; until then the inert core is shape-sign, same pattern cursor noted for P1 phasing.

Not a parallel-authority fork — it's Vendor<Hardware>-style core + domain refinement (design §2.0 analog). The consolidation trigger is P5 behavioral projection + P4 #3468 infer bundle, documented in the signed design doc (operator-ratified authority for this PR).

non_det_source_eq / determinism_class_eq — acknowledged

Agree these are predicate/walker mechanical triggers, explicitly rostered in NON_FOLD_RESIDUE_ROSTER (non_fold_residue_project.rs:124-125) with kernel marker naming P4/#3468 dissolution — checked, not missed.

@briansrls briansrls closed this Jun 29, 2026
@gunbai-bot

gunbai-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

briansrls added a commit that referenced this pull request Jun 29, 2026
PR #5941 only added determinism eq sites; the three commit_workflow
exceptions must stay on the roster until gunbc#5364 dissolves them.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls added a commit that referenced this pull request Jun 29, 2026
…esses.

Re-harvest closed #5941 onto fresh main (post-#5937 design merge):
- v2.std.determinism primitive roster + determinism_compose algebra + witness data
- dsl/std/determinism.dag DeterminismAxis authority
- determinism_contract_test.dag (7 fail-closed witnesses)
- design doc reconciled as MODIFY on #5937; DESIGN.md + ROADMAP.md regen'd
- non_fold_residue roster: determinism_class_eq + non_det_source_eq

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls added a commit that referenced this pull request Jun 29, 2026
…esses. (#5944)

Re-harvest closed #5941 onto fresh main (post-#5937 design merge):
- v2.std.determinism primitive roster + determinism_compose algebra + witness data
- dsl/std/determinism.dag DeterminismAxis authority
- determinism_contract_test.dag (7 fail-closed witnesses)
- design doc reconciled as MODIFY on #5937; DESIGN.md + ROADMAP.md regen'd
- non_fold_residue roster: determinism_class_eq + non_det_source_eq

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls added a commit that referenced this pull request Jun 29, 2026
The three gates use different (source_roots, binary) tuples (verified):
- DslCompileCleanGate: gunbc compile dsl+src/v2
- EmitDeterminismGate: gunbc compile dsl only (x2 oracle pair)
- RegenVerifyGate: regen_stage0 --verify (different binary)

No artifact sharing is possible across gates in the current set.
M2's value is forward-proofing (future gates declaring the same tuple
reuse the RunnableCompile node; duplicates caught by lens), not
present-day savings. Displacement table corrected: M1 saves ~35s
(resolve memo), M2 saves up to 1x compile when oracle pair collapses
after #5941 closes the non-determinism gap.

Also: M1 dissolution trigger corrected (M1 is orthogonal to M2, not
subsumed by it).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jun 30, 2026
* Design sketch: floor shared-computation memoization (no implementation)

Documents the root (double-paid full-tree compile: 4× subprocess + 2×
in-process resolve_entry_graph), two fix axes (M1 within-walk resolve
memo + M2 RunnableCompile artifact node), and the four operator decisions
needed before any implementation lands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix stale §1 framing of EmitDeterminismGate (oracle, not redundant)

The original text said the x2 diff was redundant if compile is
content-addressed. Corrected: the gate is a load-bearing oracle for
known-live non-determinism; content-addressing assumes determinism not
proves it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix M2: each gate uses distinct compile tuple; no artifact sharing today

The three gates use different (source_roots, binary) tuples (verified):
- DslCompileCleanGate: gunbc compile dsl+src/v2
- EmitDeterminismGate: gunbc compile dsl only (x2 oracle pair)
- RegenVerifyGate: regen_stage0 --verify (different binary)

No artifact sharing is possible across gates in the current set.
M2's value is forward-proofing (future gates declaring the same tuple
reuse the RunnableCompile node; duplicates caught by lens), not
present-day savings. Displacement table corrected: M1 saves ~35s
(resolve memo), M2 saves up to 1x compile when oracle pair collapses
after #5941 closes the non-determinism gap.

Also: M1 dissolution trigger corrected (M1 is orthogonal to M2, not
subsumed by it).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix §6 displacement table and §7 collapse claim

Table row said '×2' (oracle pair survives) but the text below
correctly said 4→3 (three distinct tuples remain after oracle pair
2→1). Fix to '×3' throughout.

§7 'collapse to 1× total compile' was impossible: even after oracle
pair collapses, DslCompileClean + EmitDeterminism×1 + RegenVerify are
three distinct-tuple operations and all remain necessary. Corrected to
'4→3×'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix §6 displacement table: baseline 4× resolves (not 2×), M1 saves ~105s (not ~35s)

Round 4 reviewer finding: Axis B actually has 4 resolve_entry_graph calls per run
(Batch 1 DslCompileClean, Batch 2 SharedClaims group, serialized RegenVerify batch,
serialized EmitDeterminism batch) — not 2×. M1 eliminates 3 redundant calls → ~105s
saved, not ~35s.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix stale ~37s in §6 Total row — M1 saves ~105s not ~35s

cursor review finding: Total compile cost row had ~37s in both M1 columns,
inconsistent with the corrected ~105s in the M1 granular table row and prose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add link to floor-shared-compute-memoization sketch in DESIGN.md open threads

Fixes doc_graph_has_no_orphan_docs CI failure: the new docs/plans file was
not reachable from DESIGN.md. Added li to open_threads_blocks() and
regenerated DESIGN.md via main_wet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jun 30, 2026
)

* Design sketch: floor shared-computation memoization (no implementation)

Documents the root (double-paid full-tree compile: 4× subprocess + 2×
in-process resolve_entry_graph), two fix axes (M1 within-walk resolve
memo + M2 RunnableCompile artifact node), and the four operator decisions
needed before any implementation lands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix stale §1 framing of EmitDeterminismGate (oracle, not redundant)

The original text said the x2 diff was redundant if compile is
content-addressed. Corrected: the gate is a load-bearing oracle for
known-live non-determinism; content-addressing assumes determinism not
proves it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix M2: each gate uses distinct compile tuple; no artifact sharing today

The three gates use different (source_roots, binary) tuples (verified):
- DslCompileCleanGate: gunbc compile dsl+src/v2
- EmitDeterminismGate: gunbc compile dsl only (x2 oracle pair)
- RegenVerifyGate: regen_stage0 --verify (different binary)

No artifact sharing is possible across gates in the current set.
M2's value is forward-proofing (future gates declaring the same tuple
reuse the RunnableCompile node; duplicates caught by lens), not
present-day savings. Displacement table corrected: M1 saves ~35s
(resolve memo), M2 saves up to 1x compile when oracle pair collapses
after #5941 closes the non-determinism gap.

Also: M1 dissolution trigger corrected (M1 is orthogonal to M2, not
subsumed by it).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix §6 displacement table and §7 collapse claim

Table row said '×2' (oracle pair survives) but the text below
correctly said 4→3 (three distinct tuples remain after oracle pair
2→1). Fix to '×3' throughout.

§7 'collapse to 1× total compile' was impossible: even after oracle
pair collapses, DslCompileClean + EmitDeterminism×1 + RegenVerify are
three distinct-tuple operations and all remain necessary. Corrected to
'4→3×'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* Fix §6 displacement table: baseline 4× resolves (not 2×), M1 saves ~105s (not ~35s)

Round 4 reviewer finding: Axis B actually has 4 resolve_entry_graph calls per run
(Batch 1 DslCompileClean, Batch 2 SharedClaims group, serialized RegenVerify batch,
serialized EmitDeterminism batch) — not 2×. M1 eliminates 3 redundant calls → ~105s
saved, not ~35s.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix stale ~37s in §6 Total row — M1 saves ~105s not ~35s

cursor review finding: Total compile cost row had ~37s in both M1 columns,
inconsistent with the corrected ~105s in the M1 granular table row and prose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add link to floor-shared-compute-memoization sketch in DESIGN.md open threads

Fixes doc_graph_has_no_orphan_docs CI failure: the new docs/plans file was
not reachable from DESIGN.md. Added li to open_threads_blocks() and
regenerated DESIGN.md via main_wet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* M1 within-walk resolve memo: fix Runnable pattern exhaustiveness

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* M1 resolve scope: add discriminating witnesses to ci_floor_plan

GREEN: all heavy runnables in the plan declare ResolveScopeShared.
RED: a heavy profile with ResolveScopeIsolated fails the lens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* fix: OR use_walk_memo on SharedClaims merge; document source_roots invariant

When group_batch_units merges a ResolveScopeShared SingleClaim into an
existing SharedClaims unit that was created from an Isolated claim first,
the group would silently drop the Shared flag and run via
run_shared_entry_claims instead of the cross-batch memo path. Fix by
ORing use_walk_memo on merge so the memo path wins whenever any member
of the group declares ResolveScopeShared.

Also document the memo-key invariant: source_roots is constant per
run_walk call, so keying the memo by entry alone is safe today; notes
what to change if that assumption ever widens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: gate workspace_root import under #[cfg(test)] to clear unused-import clippy error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: replace vec! with array literal in warm==cold test to silence clippy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* §5 construction: drop resolve_scope — derive memo from heavy_whole_tree_resolve

heavy_whole_tree_resolve is the single authority (§3). The memo decision
follows by law: a whole-tree resolve is deterministic per source_roots, so
heavy⟹memoize is always true. Two independent axes with one combination
forbidden was validation-where-construction-was-available (DESIGN §5).

Removes: type ResolveScope, resolve_scope field on RunnableResourceProfile,
resolve_scope_eq, runnable_profile_resolve_scope_valid, and the three
schedule walkers (runnable_resolve_scope_valid, batch_all_resolve_scope_valid,
schedule_list_all_resolve_scope_valid, schedule_all_runnables_valid_resolve_scope).
These dissolve — HeavyIsolated is now unwritable by construction, so the
validator and witnesses testing it are unnecessary.

claim_executor.rs derives use_walk_memo from profile.heavy_whole_tree_resolve
directly (single read site, no gate list).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* reword stale ResolveScope vocab in two comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* WIP: DESIGN SKETCH ONLY (no code; returns to stern-moth-225 + operator before

* fix: promote memo-eligible thread_units on entry cache hit; sync regen

Two changes:
1. executor: at partition time, also move SharedClaims to memo_units if
   their entry is already in walk_memo (populated by a prior batch's heavy
   resolve). This eliminates cold re-resolves of the same entry in later
   batches even when the gate's own profile is non-heavy — achieving the
   documented 4×→1× resolve count per walk.

2. std_realization_schedule.rs: sync regen'd output (field shorthand
   vs explicit form in runnable_resource_profile constructor).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* add resolve-count oracle: memo fires resolve_entry_graph once per entry per walk

memo_deduplicates_resolve_count: first call assert resolve_nanos > 0 (fresh
resolve fires), second call for same entry asserts resolve_nanos == 0 (cache
hit, resolve_entry_graph does NOT fire). Goes RED if the memo is bypassed.
Discriminating witness for the 4x->1x dedup claim (DESIGN §2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Jul 4, 2026
…rator session 2026-07-04)

Names the target architecture for the resolve problem measured during the CI
dig-out: request-major private universes -> cheap edge graph + reverse-reachable
minimal set + forward once-per-node evaluation (construction, not cache lookup),
windowed-frontier memory (interface vs body artifacts), isolation-as-purity, and
the full v1/v2 change surface. Staged S1 (union resolve, in-process, ships in
the current PR line) / S2a (module nodes + Merkle keys) / S2b (persistence,
gated on determinism #5941) / S3 (shared store) so it is not a 10-PR arc.
Cross-linked from the M1/M2 memoization doc it supersedes (that doc's own M1
dissolution trigger anticipated exactly this design).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf
briansrls added a commit that referenced this pull request Jul 4, 2026
* CI witness opt-in inversion: zero witnesses by default, enrollment by declared roster row

Operator decision 2026-07-04: the tree-wide glob roster (543 files / ~1,551
test fns, growing quadratically - a witness is definable between any two
pipeline segments) pushed both CI jobs to the 90-min timeout: maximum cost,
zero delivered signal, every merge effectively fail-open. Existence no longer
enrolls a witness in CI.

- CiSpec.witness_entries: the opt-in roster, projected from CommitWitnessClaim
  rows on the GithubActionsCiJob surface of commit_gate_roster (the existing
  enrollment authority - no new mechanism). Empty today.
- ci_floor_plan: an empty roster puts NO witness-corpus node in the plan
  (structural omission, not an empty glob - the executor's empty-corpus
  fail-closed diagnostic stays meaningful); a non-empty roster becomes
  explicit-entries discovery batches (scan_dirs/discovery_scope_dirs empty, so
  the glob path is unreachable from CI), partitioned corpus vs execution by
  path prefix, still compile-gated and heavy-serialized. The dedicated
  grounding whole-tree node dissolved into the roster.
- claim_executor: when a plan carries no DiscoveryBatch, run the naming-
  hygiene tree walk (test fn outside *_test.dag, __ basenames) once,
  fail-closed - a witness must stay nameable even when not enrolled.
- Witness tests inverted: live plan asserts discovery tracks the roster
  (zero today); the enrollment machinery is proven on synthetic rosters
  (presence, partition, gating after compile, heavy serialization, exclusion
  edges) with red discrimination.
- Rust lane, same inversion: the two whole-tree tests (func_env whole-tree
  ptr-count, whole-corpus semantic oracle) are now #[ignore] with written
  reasons per the #5427 discipline; run via -- --ignored.
- Found and fixed two files the v1 interpreter grammar could not parse
  (top-level // comments): affected_set_floor_runner.dag - which made
  resolve_floor_runner_context fail and silently disabled the affected-set
  skip, falling back to full corpus on every floor run - and
  phase_profile_proof_plan.dag. Comments converted to data-string markers.
- Local tree-wide discovery unchanged (claim_batch --roster-from-discovery).
- Dissolve-on: affected-set selection + floor memoization make per-PR
  selection-by-affectedness affordable; enrollment returns to discovery
  shrunk by the affected set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Enroll the first opt-in CI witness: variant_owner_expected_type (single pure-fn canary)

Per operator intent: exactly one witness in CI for now, to observe the floor's
behavior around a known-tiny payload. The canary is
dag/test/claim/variant_owner_expected_type_test.dag ::
expected_type_picks_variant_owner_not_alpha_order - a single test fn over
self-contained pure functions (no host intrinsics, one std.logic import;
measured locally: 3ms resolve / 2-module closure, ~0ms eval), so whatever time
the CI witness lane now costs is the floor's fixed overhead, not the witness.

Also: run the witness naming-hygiene walk unconditionally in claim_executor's
plan path, BEFORE plan evaluation - explicit-entries discovery batches skip
the glob scan that used to carry the placement checks, and pre-plan ordering
makes a naming violation the cheapest possible failure. Verified by execution:
red probe (planted test fn in a non-_test.dag file) fails closed with the
placement diagnostic in seconds; green probe on the live tree passes the walk
and proceeds to plan eval; the enrolled canary runs green via claim_batch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fix clippy absurd_extreme_comparisons on the emitted-Rust error ratchet (pre-existing on main; surfaces on any .rs-touching PR)

The ratchet constant deliberately sits at its minimum (0); scoped allow with
justification keeps raising the ceiling a one-constant edit instead of
hardcoding == 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Eliminate every degradation arm in floor selection: declared machinery fails immediately

Operator decision: 'fail closed' here means DON'T PROCEED, never 'silently run
more'. skip_unaffected_node_frontier: true is a declared capability, so every
input it needs is required - a failure is a loud typed error:

- git diff observation failed -> error (was: run full corpus). The
  FloorGitDiffOutcome degradation enum is deleted; an absent diff is no longer
  a representable input state to selection. To run without selection, declare
  skip_unaffected_node_frontier: false - an explicit bit, not a silent state.
- diff->declaration attribution failed -> error (was: run full corpus)
- affected-set runner unresolvable -> error naming the declared entry
  (was: run full corpus - the arm that hid the broken runner for weeks)
- same per shard -> error through the shard join (was: run all rows in shard)
- precompute_would_skip / per-witness would_skip / frontier-touch fns
  erroring -> error naming the witness (was: run anyway)
- roster row file unreadable -> error (was: silently reclassify as
  host-scaffold)

Rationale: the 'safe' superset fallback conflated broken artifacts with
missing observations, hid the defect permanently (no consumer of the eprintln),
and at corpus scale 'run more' inverted into fail-open-by-timeout. The runner
provisioning, fetch step, and observers are all declared by this repo's own
spec, so there is no 'environment' excuse category: a missing input is a bug
in a declared step and stops the floor.

cargo build green, clippy -D warnings green, fmt clean; floor-scoped lib unit
tests and a live red/green probe through a discovery batch are running and any
regression they surface lands as a follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Floor prelude: resolve the plan entry once, stamp every phase with wall-clock marks

The 'gunbc ci' step went silent for 35+ minutes after the release build on the
self-hosted runner - all of it pre-witness prelude: naming walk, output-policy
install, plan-entry resolve, interpreted scheduler eval (gunbc_ci_floor_batches),
then a SECOND resolve of the same plan entry for spawn-width, then another
interpreted eval. Nothing printed until all of it finished, so a 30-minute
prelude was indistinguishable from a hang.

- resolve_entry_graph(plan_entry) now runs once; the hermetic plan eval and the
  wet spawn-width eval share the resolved graph (the double-paid-compute trap
  from the floor memoization thread, paid at minutes per resolve).
- claim_executor stamps [t+Xs] phase marks: hygiene walk, policy install, plan
  resolved, plan evaluated, width evaluated / walk starting. The floor log now
  itemizes its own prelude.

eval_plan stays as a resolve+eval wrapper for the --perturb-check path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* CI job timeout: 90 -> 10 minutes (operator inversion of the timeout ratchet)

The prior ratchet went 30 -> 50 -> 90, each raise buying headroom for the
unfixed resolve cost; at 90 the queue backed up and runs still died at the
cap having delivered zero signal. The budget is now a forcing function: the
floor must fit it, and the [t+Xs] phase marks itemize exactly which phase
does not. Jobs stay red-by-timeout until resolve memoization lands - an
honest red, unlike a 90-minute lane that never completed.

ci.yml hand-synced with the ci_workflow.dag authority (3 job sites); the
generated-artifact drift gate byte-verifies the pairing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver graph-major design doc: once-per-node module evaluation (operator session 2026-07-04)

Names the target architecture for the resolve problem measured during the CI
dig-out: request-major private universes -> cheap edge graph + reverse-reachable
minimal set + forward once-per-node evaluation (construction, not cache lookup),
windowed-frontier memory (interface vs body artifacts), isolation-as-purity, and
the full v1/v2 change surface. Staged S1 (union resolve, in-process, ships in
the current PR line) / S2a (module nodes + Merkle keys) / S2b (persistence,
gated on determinism #5941) / S3 (shared store) so it is not a 10-PR arc.
Cross-linked from the M1/M2 memoization doc it supersedes (that doc's own M1
dissolution trigger anticipated exactly this design).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Hand-sync generated docs to their edited authorities (DESIGN.md CI bullet, ci-selection-vs-scheduling section 7)

The interpreted main_wet regeneration was killed twice by container restarts
(~2 CPU-hours each attempt, itself a receipt for the resolver-graph-major
design). The generated outputs are hand-applied to byte-match what the
emitters produce from the already-committed authorities
(dag/gunbc/design_document.dag, dag/gunbc/plans/ci_selection_vs_scheduling.dag);
the GeneratedArtifactDriftGate adjudicates exactness once the floor fits its
10-minute budget.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* claim_batch: honor GUNBC_FLOOR_PHASE_PROFILE (same install as claim_executor)

Without it, claim_batch diagnostics cannot attribute time to
resolve/typecheck/eval phases - a 20-minute silent resolve is
uninterpretable, and the resolver investigation needs per-phase receipts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: phase verdict (typecheck-dominant) + one-scheduler-no-special-cases section; per-module typecheck attribution

Instrumented, isolated measurement: the 11-module closure finishes
parse+resolve+normalize in ~1.1s then sits in typecheck 13+ minutes -
inference is ~99.9% of cold resolve cost. Reprioritizes the plan: pathology
lane first (per-module [typecheck-attribution] lines now name any module
over 2s), unification (module obligations under the existing executor)
second, union-of-global-passes demoted to a ~1s-class cut.

Adds the operator's formulation as design section 1b: resolution is the
system's one special case - the Bazel-shaped executor schedules eleven
coarse gates while the dominant work hides in one opaque recursive host
call; module resolution IS dependency execution over the same substrate.
Maps the external witness-frontier-cursor vocabulary onto existing
authorities (Runnable/RunnableCompile, Realization content-hash key +
EffectShape, executor batches, receipts) per the section-3 anti-nickname
discipline, and adopts the four-terminal-state invariant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* S1a: process-level resolve store - fixed-entry machinery resolves once per process

First implementation increment of the resolver graph-major design (and of
the stratification rule: resolution is declared shared work, not ambient
per-consumer control flow). A thread-local store keyed by (source_roots,
entry) now serves the floor runner context, the diff observer, the output
policy, the group syntax, the wet-hermetic roster prefix, and the
executor's plan entry - each was previously a private resolve, re-paid per
consumer and per discovery batch within one process. Failure semantics
unchanged: a miss resolves exactly as before, including the typed error
path; the store never converts an error into a fallback.

Receipt: process_resolve_store_dedupes_repeat_resolve - Rc identity on the
second resolve proves zero recompute (0.00s, fixture tree under target/).
Thread-local by design: resolved graphs are Rc-based (not Send); shard
threads keep their own store rather than smuggling Rc across threads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* typecheck attribution: start markers (profile-gated) name the pathological module

Verdict from the instrumented run: all std modules in the closure -
including std.algebra and std.realization_schedule themselves - typecheck
in under 2s each; the call that runs 17+ minutes is typecheck_module on
the 80-line CONSUMER module (test.claim.realization_schedule_witness).
The inference pathology is at generic use sites, not definition sites.
Next lane: the existing type-env lookup profiler (text_lookup_work_counter
feature, reset_type_env_lookup_profile) pointed at that one module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Phase heartbeat: live type-env amplification counters; pathology named

Heartbeats now carry env_flatten/env_builds/env_merges/env_rewires from the
existing v1_compiler_infer_env atomics. First live capture on the
pathological entry: env_flatten grows ~80k/sec unbounded (9.7M by t=120s)
while builds=11, merges=37, rewires=0 stay flat.

Root site: record_lit_variant_fields_from_visible_env
(v1_compiler_infer.rs, generated from v1.compiler.infer) - every VARIANT
LITERAL flattens the entire visible environment (recursive parent fold; the
counter) and then scans every visible binding with
expand_type_for_field_access per candidate to find the variant's owner.
Cost = variant literals x |visible env| x expansion - definitions cheap,
consumers explode. 04_env.dag:35 carries an invariant expecting
flatten_visible_parent_recurses==0 on import chains; live count says 9.7M
in 2 minutes. Fix shape (next block, dag source + regen): a variant-name ->
owner index built once per env, and expected-type short-circuit before any
global scan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: operator ruling - constructor ambiguity is an ERROR; resolution follows the binding edge

The ambiguity support (bare constructor names legal across coproducts,
expected-type tie-break, whole-env owner scan as fallback) is itself the
bug - accidental semantics, never intended. The DAG already provides the
namespace: imports bind arm names to arm nodes; the parent edge names the
owner; resolution is following the edge already held. Rules: bound-name
resolution via parent edge; unbound constructor literal = typed error
(today a silent undeclared-dependency fail-open via the scan); double
binding = collision error at env build; patterns resolve via scrutinee
type; expected-type owner-picking deleted. The pathological scan is
removed, not memoized.

Census: 5,526 arm names, 221 global collisions (uniqueness must be scoped
to co-visibility); <=4,572 unbound arm-name uses upper bound, dominated by
legal pattern positions. Control run killed at 60+ min still inside one
typecheck_module call on the 80-line module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: operator sequencing - union resolve first as interim with explicit contract; flat name visibility refinement

Union resolve leads the resolve lane with a recorded contract: minimum
upper bound (resolve cost <= 1x union closure, receipt-enforced), successor
must be maximally parallel (topo-antichain module typecheck, budget-tree
width) and frontier-window efficient; it dissolves into S2a and must not
grow features that delay that. Namespacing ruling refined per operator:
visibility is FLAT - locals + direct imports only, never transitive -
making collision detection per-file with zero graph traversal; types
propagate by graph identity underneath.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

---------

Co-authored-by: Claude <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Jul 4, 2026
…erface

Reframe the post-S1 step per operator direction: the "edges carry no payload"
pre-req is not a module-specific blocker to clear before S2a — it is an
interface generalization of the executor itself, added once and adopted by both
riders.

- §1b: the missing primitive is the artifact-bearing job (RunnableCompile
  shape) carrying produce/consume keys into the content-hash store; the CI floor
  rides it with a degenerate unit artifact, module resolution with
  ModuleInterface. One executor, N payloads. Scheduling reused unchanged.
- §5: v2.workflow.executor is generalized to a dataflow executor, not reused
  as-is; migration receipt is a byte-identical 11-gate plan.
- §7 S2a: two ordered moves — (1) generalize the executor + migrate the CI floor
  (behavior-preserving, unit payload), (2) put module resolution on the same
  executor (ModuleInterface payload). Not gated on determinism (#5941). Three
  open decisions flagged: keyed store vs inline edge payload, CI gates stay
  ordering-only for the migration, and who computes the 5.5k-node schedule
  (.dag authority vs host-computed + .dag-witnessed).

Work lands after S1 merges; this is the plan only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G6J28X52KhGXVArk6gcPgd
briansrls added a commit that referenced this pull request Jul 4, 2026
… shards) (#6234)

* Union resolve S1: one shared index per process (prelude + discovery + shards)

The request-major resolver gave every entry a private universe: the executor
prelude did 3+ cold resolves (plan entry, output policy, group syntax), the
discovery corpus resolved the floor runner in a separate index from its rows,
and each shard rebuilt both. The shared std/spec prefix re-typechecked once per
consumer — the top time-waster (docs/plans/resolver-graph-major-design.md §0).

S1 (host-layer only, no seed regen, no corpus migration) routes every consumer
through ONE shared MultiEntryIndex so the union closure typechecks once per node:

- resolve_entry_graph_shared now resolves against a thread-local shared index
  (process_shared_index) instead of a fresh per-call module index, so the
  prelude's fixed entries union.
- run_discovery_corpus_with_options builds one index threaded through frontier
  attribution, the floor runner (now resolve_entry_with_index, not a private
  resolve), and every row. Each shard shares one index for its floor runner +
  rows; cross-shard sharing is the S2b/Arc frontier (Rc<ResolvedGraph> is !Send).

The switch to the index path is proven behaviorally identical to the cold
resolve_entry_graph by the existing resolve_typed_cache_equivalence_test
(cached == cold in every resolve order).

Receipts (all execute, each with a red control):
- once-per-node counter: union computes < sum of private closures, and
  re-resolving an already-resolved entry computes ZERO new typechecks
  (union_resolve_typechecks_each_node_once). Enforces the minimum-upper-bound
  contract — resolve cost <= 1x union closure, not Nx.
- byte-identity oracle: union-view outcome == private resolve, every order
  (union_view_result_equals_private_resolve_in_every_order).
- collision honesty: the shared typed cache fails loud on a module name mapping
  to two declaring files (check_module_source_identity), never silent-serve
  (source_identity_flags_coresidence_collision_but_allows_reexport). Same wall
  build_module_index already raises tree-wide, now at the cache seam.

Interim: dissolves into S2a's parallel module-obligation architecture; no
feature growth (design doc §7/§8).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G6J28X52KhGXVArk6gcPgd

* Plan: S2a as general-executor consolidation, pre-req dissolved as interface

Reframe the post-S1 step per operator direction: the "edges carry no payload"
pre-req is not a module-specific blocker to clear before S2a — it is an
interface generalization of the executor itself, added once and adopted by both
riders.

- §1b: the missing primitive is the artifact-bearing job (RunnableCompile
  shape) carrying produce/consume keys into the content-hash store; the CI floor
  rides it with a degenerate unit artifact, module resolution with
  ModuleInterface. One executor, N payloads. Scheduling reused unchanged.
- §5: v2.workflow.executor is generalized to a dataflow executor, not reused
  as-is; migration receipt is a byte-identical 11-gate plan.
- §7 S2a: two ordered moves — (1) generalize the executor + migrate the CI floor
  (behavior-preserving, unit payload), (2) put module resolution on the same
  executor (ModuleInterface payload). Not gated on determinism (#5941). Three
  open decisions flagged: keyed store vs inline edge payload, CI gates stay
  ordering-only for the migration, and who computes the 5.5k-node schedule
  (.dag authority vs host-computed + .dag-witnessed).

Work lands after S1 merges; this is the plan only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G6J28X52KhGXVArk6gcPgd

---------

Co-authored-by: Claude <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 4, 2026
…ll, scan deleted — the engine PR (#6235)

* CI witness opt-in inversion: zero witnesses by default, enrollment by declared roster row

Operator decision 2026-07-04: the tree-wide glob roster (543 files / ~1,551
test fns, growing quadratically - a witness is definable between any two
pipeline segments) pushed both CI jobs to the 90-min timeout: maximum cost,
zero delivered signal, every merge effectively fail-open. Existence no longer
enrolls a witness in CI.

- CiSpec.witness_entries: the opt-in roster, projected from CommitWitnessClaim
  rows on the GithubActionsCiJob surface of commit_gate_roster (the existing
  enrollment authority - no new mechanism). Empty today.
- ci_floor_plan: an empty roster puts NO witness-corpus node in the plan
  (structural omission, not an empty glob - the executor's empty-corpus
  fail-closed diagnostic stays meaningful); a non-empty roster becomes
  explicit-entries discovery batches (scan_dirs/discovery_scope_dirs empty, so
  the glob path is unreachable from CI), partitioned corpus vs execution by
  path prefix, still compile-gated and heavy-serialized. The dedicated
  grounding whole-tree node dissolved into the roster.
- claim_executor: when a plan carries no DiscoveryBatch, run the naming-
  hygiene tree walk (test fn outside *_test.dag, __ basenames) once,
  fail-closed - a witness must stay nameable even when not enrolled.
- Witness tests inverted: live plan asserts discovery tracks the roster
  (zero today); the enrollment machinery is proven on synthetic rosters
  (presence, partition, gating after compile, heavy serialization, exclusion
  edges) with red discrimination.
- Rust lane, same inversion: the two whole-tree tests (func_env whole-tree
  ptr-count, whole-corpus semantic oracle) are now #[ignore] with written
  reasons per the #5427 discipline; run via -- --ignored.
- Found and fixed two files the v1 interpreter grammar could not parse
  (top-level // comments): affected_set_floor_runner.dag - which made
  resolve_floor_runner_context fail and silently disabled the affected-set
  skip, falling back to full corpus on every floor run - and
  phase_profile_proof_plan.dag. Comments converted to data-string markers.
- Local tree-wide discovery unchanged (claim_batch --roster-from-discovery).
- Dissolve-on: affected-set selection + floor memoization make per-PR
  selection-by-affectedness affordable; enrollment returns to discovery
  shrunk by the affected set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Enroll the first opt-in CI witness: variant_owner_expected_type (single pure-fn canary)

Per operator intent: exactly one witness in CI for now, to observe the floor's
behavior around a known-tiny payload. The canary is
dag/test/claim/variant_owner_expected_type_test.dag ::
expected_type_picks_variant_owner_not_alpha_order - a single test fn over
self-contained pure functions (no host intrinsics, one std.logic import;
measured locally: 3ms resolve / 2-module closure, ~0ms eval), so whatever time
the CI witness lane now costs is the floor's fixed overhead, not the witness.

Also: run the witness naming-hygiene walk unconditionally in claim_executor's
plan path, BEFORE plan evaluation - explicit-entries discovery batches skip
the glob scan that used to carry the placement checks, and pre-plan ordering
makes a naming violation the cheapest possible failure. Verified by execution:
red probe (planted test fn in a non-_test.dag file) fails closed with the
placement diagnostic in seconds; green probe on the live tree passes the walk
and proceeds to plan eval; the enrolled canary runs green via claim_batch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fix clippy absurd_extreme_comparisons on the emitted-Rust error ratchet (pre-existing on main; surfaces on any .rs-touching PR)

The ratchet constant deliberately sits at its minimum (0); scoped allow with
justification keeps raising the ceiling a one-constant edit instead of
hardcoding == 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Eliminate every degradation arm in floor selection: declared machinery fails immediately

Operator decision: 'fail closed' here means DON'T PROCEED, never 'silently run
more'. skip_unaffected_node_frontier: true is a declared capability, so every
input it needs is required - a failure is a loud typed error:

- git diff observation failed -> error (was: run full corpus). The
  FloorGitDiffOutcome degradation enum is deleted; an absent diff is no longer
  a representable input state to selection. To run without selection, declare
  skip_unaffected_node_frontier: false - an explicit bit, not a silent state.
- diff->declaration attribution failed -> error (was: run full corpus)
- affected-set runner unresolvable -> error naming the declared entry
  (was: run full corpus - the arm that hid the broken runner for weeks)
- same per shard -> error through the shard join (was: run all rows in shard)
- precompute_would_skip / per-witness would_skip / frontier-touch fns
  erroring -> error naming the witness (was: run anyway)
- roster row file unreadable -> error (was: silently reclassify as
  host-scaffold)

Rationale: the 'safe' superset fallback conflated broken artifacts with
missing observations, hid the defect permanently (no consumer of the eprintln),
and at corpus scale 'run more' inverted into fail-open-by-timeout. The runner
provisioning, fetch step, and observers are all declared by this repo's own
spec, so there is no 'environment' excuse category: a missing input is a bug
in a declared step and stops the floor.

cargo build green, clippy -D warnings green, fmt clean; floor-scoped lib unit
tests and a live red/green probe through a discovery batch are running and any
regression they surface lands as a follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Floor prelude: resolve the plan entry once, stamp every phase with wall-clock marks

The 'gunbc ci' step went silent for 35+ minutes after the release build on the
self-hosted runner - all of it pre-witness prelude: naming walk, output-policy
install, plan-entry resolve, interpreted scheduler eval (gunbc_ci_floor_batches),
then a SECOND resolve of the same plan entry for spawn-width, then another
interpreted eval. Nothing printed until all of it finished, so a 30-minute
prelude was indistinguishable from a hang.

- resolve_entry_graph(plan_entry) now runs once; the hermetic plan eval and the
  wet spawn-width eval share the resolved graph (the double-paid-compute trap
  from the floor memoization thread, paid at minutes per resolve).
- claim_executor stamps [t+Xs] phase marks: hygiene walk, policy install, plan
  resolved, plan evaluated, width evaluated / walk starting. The floor log now
  itemizes its own prelude.

eval_plan stays as a resolve+eval wrapper for the --perturb-check path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* CI job timeout: 90 -> 10 minutes (operator inversion of the timeout ratchet)

The prior ratchet went 30 -> 50 -> 90, each raise buying headroom for the
unfixed resolve cost; at 90 the queue backed up and runs still died at the
cap having delivered zero signal. The budget is now a forcing function: the
floor must fit it, and the [t+Xs] phase marks itemize exactly which phase
does not. Jobs stay red-by-timeout until resolve memoization lands - an
honest red, unlike a 90-minute lane that never completed.

ci.yml hand-synced with the ci_workflow.dag authority (3 job sites); the
generated-artifact drift gate byte-verifies the pairing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver graph-major design doc: once-per-node module evaluation (operator session 2026-07-04)

Names the target architecture for the resolve problem measured during the CI
dig-out: request-major private universes -> cheap edge graph + reverse-reachable
minimal set + forward once-per-node evaluation (construction, not cache lookup),
windowed-frontier memory (interface vs body artifacts), isolation-as-purity, and
the full v1/v2 change surface. Staged S1 (union resolve, in-process, ships in
the current PR line) / S2a (module nodes + Merkle keys) / S2b (persistence,
gated on determinism #5941) / S3 (shared store) so it is not a 10-PR arc.
Cross-linked from the M1/M2 memoization doc it supersedes (that doc's own M1
dissolution trigger anticipated exactly this design).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Hand-sync generated docs to their edited authorities (DESIGN.md CI bullet, ci-selection-vs-scheduling section 7)

The interpreted main_wet regeneration was killed twice by container restarts
(~2 CPU-hours each attempt, itself a receipt for the resolver-graph-major
design). The generated outputs are hand-applied to byte-match what the
emitters produce from the already-committed authorities
(dag/gunbc/design_document.dag, dag/gunbc/plans/ci_selection_vs_scheduling.dag);
the GeneratedArtifactDriftGate adjudicates exactness once the floor fits its
10-minute budget.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* claim_batch: honor GUNBC_FLOOR_PHASE_PROFILE (same install as claim_executor)

Without it, claim_batch diagnostics cannot attribute time to
resolve/typecheck/eval phases - a 20-minute silent resolve is
uninterpretable, and the resolver investigation needs per-phase receipts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: phase verdict (typecheck-dominant) + one-scheduler-no-special-cases section; per-module typecheck attribution

Instrumented, isolated measurement: the 11-module closure finishes
parse+resolve+normalize in ~1.1s then sits in typecheck 13+ minutes -
inference is ~99.9% of cold resolve cost. Reprioritizes the plan: pathology
lane first (per-module [typecheck-attribution] lines now name any module
over 2s), unification (module obligations under the existing executor)
second, union-of-global-passes demoted to a ~1s-class cut.

Adds the operator's formulation as design section 1b: resolution is the
system's one special case - the Bazel-shaped executor schedules eleven
coarse gates while the dominant work hides in one opaque recursive host
call; module resolution IS dependency execution over the same substrate.
Maps the external witness-frontier-cursor vocabulary onto existing
authorities (Runnable/RunnableCompile, Realization content-hash key +
EffectShape, executor batches, receipts) per the section-3 anti-nickname
discipline, and adopts the four-terminal-state invariant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* S1a: process-level resolve store - fixed-entry machinery resolves once per process

First implementation increment of the resolver graph-major design (and of
the stratification rule: resolution is declared shared work, not ambient
per-consumer control flow). A thread-local store keyed by (source_roots,
entry) now serves the floor runner context, the diff observer, the output
policy, the group syntax, the wet-hermetic roster prefix, and the
executor's plan entry - each was previously a private resolve, re-paid per
consumer and per discovery batch within one process. Failure semantics
unchanged: a miss resolves exactly as before, including the typed error
path; the store never converts an error into a fallback.

Receipt: process_resolve_store_dedupes_repeat_resolve - Rc identity on the
second resolve proves zero recompute (0.00s, fixture tree under target/).
Thread-local by design: resolved graphs are Rc-based (not Send); shard
threads keep their own store rather than smuggling Rc across threads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* typecheck attribution: start markers (profile-gated) name the pathological module

Verdict from the instrumented run: all std modules in the closure -
including std.algebra and std.realization_schedule themselves - typecheck
in under 2s each; the call that runs 17+ minutes is typecheck_module on
the 80-line CONSUMER module (test.claim.realization_schedule_witness).
The inference pathology is at generic use sites, not definition sites.
Next lane: the existing type-env lookup profiler (text_lookup_work_counter
feature, reset_type_env_lookup_profile) pointed at that one module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Phase heartbeat: live type-env amplification counters; pathology named

Heartbeats now carry env_flatten/env_builds/env_merges/env_rewires from the
existing v1_compiler_infer_env atomics. First live capture on the
pathological entry: env_flatten grows ~80k/sec unbounded (9.7M by t=120s)
while builds=11, merges=37, rewires=0 stay flat.

Root site: record_lit_variant_fields_from_visible_env
(v1_compiler_infer.rs, generated from v1.compiler.infer) - every VARIANT
LITERAL flattens the entire visible environment (recursive parent fold; the
counter) and then scans every visible binding with
expand_type_for_field_access per candidate to find the variant's owner.
Cost = variant literals x |visible env| x expansion - definitions cheap,
consumers explode. 04_env.dag:35 carries an invariant expecting
flatten_visible_parent_recurses==0 on import chains; live count says 9.7M
in 2 minutes. Fix shape (next block, dag source + regen): a variant-name ->
owner index built once per env, and expected-type short-circuit before any
global scan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: operator ruling - constructor ambiguity is an ERROR; resolution follows the binding edge

The ambiguity support (bare constructor names legal across coproducts,
expected-type tie-break, whole-env owner scan as fallback) is itself the
bug - accidental semantics, never intended. The DAG already provides the
namespace: imports bind arm names to arm nodes; the parent edge names the
owner; resolution is following the edge already held. Rules: bound-name
resolution via parent edge; unbound constructor literal = typed error
(today a silent undeclared-dependency fail-open via the scan); double
binding = collision error at env build; patterns resolve via scrutinee
type; expected-type owner-picking deleted. The pathological scan is
removed, not memoized.

Census: 5,526 arm names, 221 global collisions (uniqueness must be scoped
to co-visibility); <=4,572 unbound arm-name uses upper bound, dominated by
legal pattern positions. Control run killed at 60+ min still inside one
typecheck_module call on the 80-line module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: operator sequencing - union resolve first as interim with explicit contract; flat name visibility refinement

Union resolve leads the resolve lane with a recorded contract: minimum
upper bound (resolve cost <= 1x union closure, receipt-enforced), successor
must be maximally parallel (topo-antichain module typecheck, budget-tree
width) and frontier-window efficient; it dissolves into S2a and must not
grow features that delay that. Namespacing ruling refined per operator:
visibility is FLAT - locals + direct imports only, never transitive -
making collision detection per-file with zero graph traversal; types
propagate by graph identity underneath.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Union-resolve follow-up: main-thread discovery rides the thread's shared index

run_discovery_corpus_with_options now takes process_shared_index(source_roots)
instead of building a private MultiEntryIndex, so when the executor prelude
already resolved on this thread, discovery reuses its parse/typed caches
(one union per thread, not per consumer). Shards keep their own index
(Rc !Send, per-shard contract in resolver-graph-major-design §7 S1).

Also: resolve_typed_cache_equivalence_test fixtures move from
std::env::temp_dir() to the workspace target/ dir — build_module_path_index
fails closed on out-of-workspace paths, so the /tmp fixture could never
resolve in a workspace-guarded environment (union_resolve_receipts_test
precedent).

Gates run: cargo build -p v1-compiler; cargo test -p v1-compiler-tests
resolve_typed_cache + union_resolve (green); source_identity guard (green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: three-layer executor framing (scheduler / runner+store / content keys) + realization tower

Supersedes the 'artifact-bearing executor' framing (operator, 2026-07-04:
artifacting is a separate concern, opaque to scheduling). §1b/§5/§7 now
state the split: the scheduler is payload-agnostic and unchanged; dataflow
lives in a runner + node-keyed store (typed_module_cache is its embryo);
S2b only swaps the store's key function to content hashes. The S2a open
decisions are settled by the split (results in the store, jobs reference
by node identity; gates stay unit-result; .dag-authority schedule).

New §5b: the realization tower — Rust is the bootstrap row, not the floor;
the intrinsic kernel is the declared HAND_MAINTAINED surface + registered
builtins; realization-scoped decisions (Rc !Send) carry dissolve-ons.

Post-fix timing receipts are placeholders by design, filled at the
receipts commit of this PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Constructor-owner ruling (§1c): binding-edge resolution, per-file collision wall, scans deleted — dag sources

Implements the operator ruling in the .dag authority (v1.compiler.infer /
infer_resolve). This commit is step 1 of the seed two-step: the checked-in
generated Rust still realizes the OLD semantics; the next commit hand-patches
the seed functionally, and the regen commit replaces the hand-patch with this
source's true emission (RegenVerifyGate byte-identity + bootstrap fixed point).

- infer_record_lit: the unconditional whole-env scan-first rung is DELETED
  (record_lit_variant_fields_from_visible_env and both call sites). The
  ladder is now instantiate -> expected -> declaration/binding-edge only.
- variant_owner_node: O(1) owner lookup — scope.locals binds arm name to its
  owning coproduct NODE; no name round-trip, owner need not be name-visible.
- build_module_context: constructor namespace is FLAT — local coproduct arms
  + direct imports' contributions (is_all covered; specific enum or arm
  names covered; owner node carried on the binding). The transitive
  ancestry fold and the unique-owner-or-nothing import map are deleted.
- Collision wall: one arm name -> two different owners in one file appends
  VariantCollision at env construction (insert_variant_owner_checked); the
  same declaration via two import paths is one owner, not a collision.
  Kernel coproduct arms keep low-priority prelude merge.
- expected_type_override_enum (expected-type-as-owner-picker) DELETED;
  ExprVar variant bindings resolve by binding edge alone.
- field_in_any_variant_named re-scoped to the resolved owner's arms.
- Unbound constructor literal now reports UnresolvedType (was a generic
  InternalError message); no new diagnostic variants minted — VariantCollision
  and UnresolvedType already existed in 00_core.
- collect_unit_variant_phantom_matches (04_resolve): flat one-level search
  (own + direct parents' str_bindings), no recursive ancestry flatten.
- Dead code deleted: unique_imported_variant_owner,
  enum_parents_for_variant_in_items, is_imported_variant_owned_by,
  union_parent_variant_locals, fold_local_coproduct_variant_locals
  (kernel path inlined), variant_locals_from_items.

Note: v2.std.determinism roster rows ^unique_imported_variant_owner /
^alpha_sorted_variant_fold are quoted symbols and still compile, but now
name superseded fns — flagged for operator re-signing (#5941 roster).

Baseline receipt (pre-fix, this base): realization_schedule_witness_test
(81 lines, 2 imports) killed at 900s still inside typecheck_module,
env_flatten 69.7M and linear (~78k/s) — target/baseline/single_module_pre_fix.log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Constructor-owner ruling: hand-patched seed (two-step step 2) + diagnostic tests + payoff receipt

Functional hand-patch of generated v1_compiler_infer.rs ONLY (201 insertions,
one generated file — budget was ~200 across <=3): (a) build_module_context
realizes the new flat, collision-walled construction (local arms + direct
imports; owner node on the binding; VariantCollision on two owners for one
name; kernel arms low-priority); (b) variant_owner_node helper; (c)
record_lit_expected_fields owner via the binding node, scan fallback deleted;
(d) infer_record_lit scan-first rung deleted; (e) ExprVar expected-type
owner-picker deleted; (f) unbound constructor literal -> UnresolvedType.
Deferred to regen (semantic gap re-censused with the true seed):
field_in_any_variant_named re-scope, phantom-path flat re-scope, dead-fn
deletions. This hand-patch is replaced wholesale by regen output in the
convergence commit (precedent 3d89b2d/f3cc9f5).

PAYOFF RECEIPT (the C4 stop/go gate): realization_schedule_witness_test.dag
(81 lines, 2 imports) — pre-fix killed at the 900s cap still inside
typecheck_module, env_flatten 69.7M and linear (~78k/s); patched seed:
1.14s TOTAL, env_flatten 0. Receipt logs: target/baseline/.

New constructor_owner_ruling_test.rs (7 tests, green): intra-file collision,
cross-import collision, unbound->UnresolvedType, enum-import/arm-import/
glob-import (brace-less form) construct green, re-export non-collision.

The collision wall found live prey immediately (sweep work, next commits):
dag/std/markup.dag Fragment.TextNode vs MarkupNode.TextNode (converted
cross-owner at :183 — the expected-type pick in vivo); integer.dag
DecimalDigit vs NonZeroDecimalDigit D1..D9; target_model.dag
TargetReferenceLayer{,Wrapped}; plus bare-None uses that resolved via the
transitive scan. Corpus-resolving tests stay red until the sweep lands —
fix-then-sweep ordering, full-suite green re-established pre-regen.

Also: dependency_pool_index whole-tree compile tests (release-binary
corpus walks) join the 2026-07-04 opt-in inversion; they had escaped it by
self-skipping on CI (no release binary) while running unbounded locally.

Gates run: cargo build -p v1-compiler; cargo test -p v1-compiler-tests
constructor_owner_ruling (7/7) + resolve_typed_cache + union_resolve +
source_identity (green); payoff receipt above.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Constructor-owner ruling: re-export chains + witness rewrites + fixture hygiene (C4 follow-through)

Re-export chains (dag authority + seed hand-patch, both sides): a module
re-exports its specific-name imports (get_exported_names), so
'import proxy { B }' where proxy itself imports B is an explicit import
under the ruling. New owner_of_exported_arm / exported_coproduct_item walk
the acyclic import chain to the defining module's coproduct;
build_imported_variants resolves every specific name through them (glob
imports stay own-items-only, matching the export surface which excludes
is_all pass-through). Receipt: all 4 self_gen8 re-export chain tests green.
Hand-patch grows to ~280 lines / still 1 generated file — over the ~200
budget line, accepted because the patched seed is the sweep census tool and
without chains it mis-censuses every re-export site in the tree.

Old-semantics witnesses rewritten to witness the ruling:
- variant_owner_disambiguation_test: expected-type-pick / local-shadow /
  per-site tests -> collision red-controls + a binding-edge emission green
  control (fixtures preserved).
- type_env_scope_chain_test: local-shadows-imported -> collision red-control
  with sole-owner green control.
- pipeline: ambiguous_variant_name_resolves_correctly deleted (redundant
  with constructor_owner_ruling_test collisions);
  duplicate_variant_names_across_enums_dont_collide -> rule-4 witness
  (pattern-position arms resolve via scrutinee with ZERO constructor
  bindings; emitted match still owner-qualified).

Fixture hygiene:
- 6 files moved off std::env::temp_dir() to workspace target/ (12 tests;
  build_module_path_index fails closed outside the workspace — the
  union_resolve_receipts_test precedent, same class as the C1 fix).
- 9 pipeline wire-contract fixtures gain 'VariantNaming' in their
  std.serialization imports (SnakeCase & friends are its arms — the
  rule-(i) migration class, in fixture strings).

Suite: 626 passed / 28 failed / 85 ignored in 167s. All 28 remaining
failures are enumerated corpus-sweep work (integer.dag D1..D9, extdeps
github Pending + openai UrlCitation collisions, dag/std markup TextNode,
samsung.dag Gen3, target_model + src/v2 test-fixture bare-None sites) or
the stale release binary (interp_dry_run) — zero unexplained. They re-green
with the sweep commits, before regen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Sweep wave 1 (regen-input closure): 3 census findings fixed

Patched-seed census over src/v1 + its dag closure (89 sources, 21s — the
same scope pre-fix was the 48-minute class) found exactly three violations:

1. dag/std/computation.dag: SizeBound.TreeSize collided with the imported
   RankingDimension.TreeSize in the module's own scope. Renamed the bound
   arm to SubtreeSize (the more precise fact — a tree-descent bound
   measures the shrinking subtree per step; rename fully contained in one
   file, SizeBound is imported by name nowhere else). RankingDimension
   keeps TreeSize (~12 sites in v1.complexity/std.induction).
2. src/v1/02_parse.dag constructed InternalError without importing it —
   previously resolved by the deleted whole-env scan (an undeclared-
   dependency fail-open, exactly the census class the ruling predicted).
3. src/v1/04_infer.dag used FieldNotFound without importing it (same
   class, in the compiler's own source).

Generated-seed counterparts of the SubtreeSize rename land at the regen
commit (all TreeSize references in stage0 are in generated files).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Sweep: markup TextNode collision + floor-closure unbound imports

Fragment.TextNode -> FragmentText (dag/std/markup.dag): Fragment and
MarkupNode both declared TextNode in one file, and
markup_node_to_fragment converted one to the other cross-owner via the
deleted expected-type pick. MarkupNode (the larger surface, ~15 consumer
files) keeps TextNode; the 5 Fragment-side consumers follow the rename
(std.markdown, extdeps languages/markdown, serializer witness, regime2
plan prose, medium-structure fixture).

Floor-closure unbound sites from the first CI run of #6235 (exactly the
census class - constructors resolved by the deleted scan without
imports): fleet_posix_accounts gains ConstructionMechanism
(SingleAuthority's owner); samsung + western_digital storage rows gain
PcieGeneration + NvmeFormFactor (Gen3/Gen4/M2_2280 owners).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* CI canary swap + constructor-owner red-control suite

The enrolled CI canary asserted the DELETED semantics (expected-type picks
the variant owner), so it is swapped for
github_merge_state_witness_test.dag :: witness_clean_and_blocked_are_distinct_variants
- small, pure, and exercises imported-variant construction through the new
binding-edge path (operator decision 3, 2026-07-04).

The retired canary fixture becomes the collision RED control: new
diagnostics_witness suite 'constructor_owner' (VariantCollision on the
two-local-owners fixture; UnresolvedType on an unbound constructor literal;
sole-owner green control), wired through the existing transport pair
(tools.diagnostics_witness_transport + test.claim.diagnostics_test).
variant_owner_expected_type_test.dag is deleted from the compiled tree -
its fixture is now illegal by design and lives on inside the red control.

Verified by execution: target/debug/diagnostics_witness constructor_owner
green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Sweep round 1 (10 parallel agents): 51 collisions renamed + 67 unbound sites imported across src/v2 + dag closures

The whole-tree census with the patched seed drove file-disjoint fix
groups; policy per operator decisions: bigger owner keeps the arm name,
smaller side renames along its distinguishing dimension; unbound
constructor literals gain their owner-enum import from the defining
module.

Collision renames (owners in parens keep the shared names):
- cache catalog twins: Catalog-side arms -> CatalogOpaqueStringKey /
  CatalogCasContentDigest / CatalogOpaqueStringEncoding /
  CatalogCasContentEncoding (std.cache_interface keeps); the
  catalog->std converter in extdeps/cache/cache.dag now reads
  per-side by scrutinee/produced type instead of the deleted
  expected-type pick; 5 cache witness suites green by execution.
- integer digits: NonZeroDecimalDigit arms D1..D9 -> NonZeroD1..D9
  (DecimalDigit keeps D0..D9); widen fn patterns renamed, constructed
  DecimalDigit results kept; subset-type modeling flagged as a §3
  follow-up rather than done ad hoc here.
- cpp_abi: singleton width enums' arms -> CppWidth8Fixed..CppWidth64Fixed
  (CppIntegerWidth keeps CppWidth8..64); per-model core-width arms ->
  CppILP32/LP64/LLP64/ILP64CoreIntegerWidthModel; anchor scalar ->
  SignedIntegerScalarAnchor (CppScalar keeps SignedIntegerScalar).
- language width models (rust, ptx, kotlin, java, go, swift): int-width
  enums keep BitsN; float/complex/ordered-ring/etc. sides renamed
  along their dimension (FloatBitsN, ComplexBits64, ...).
- effects + target_model: smaller-side renames per the same policy
  (WrappedReferenceLayerRc/Box on TargetReferenceLayerWrapped).

Unbound-import fixes: 30+ files across src/v2 (manual/execution/lens
test claims, std, compiler stages, program.dag, extdeps languages/
formats, workflow runner test) — each gains exactly the owner-enum
import its constructor literals need. Bare-None sites resolved per
expected type (enum arm import vs the lowercase optional keyword).

VERIFICATION (executable gate): whole-tree census re-run with src/v2
entries — 290 error lines before, 3 after, and all 3 are deliberate
red-fixture plants (parse-error + layering-scan plants, other walls'
fixtures). Zero constructor-ruling findings remain in src/v2 scope.
dag-root verification runs next alongside sweep round 2 (wave-2
findings: srv3 aggregate, same-file pairs, witness-test imports).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Sweep round 2 (4 parallel agents) + env-counter dissolution (unblocks regen)

Round 2 fixes the dag-tree census findings:
- srv3_os_install_diagnostic: 13 collision pairs resolved. The aggregate
  Srv3InstallDiagnostic KEEPS its arm names (larger use counts + owns the
  wire strings); sub-verdict copies renamed with the file's existing
  ...Verdict suffix convention (ReadyToBootVerdict, InstallerHungVerdict,
  OsInstalledVerdict, InconclusiveVerdict, ServePortAbsentVerdict,
  ServePortConflictVerdict, TokenMissingVerdict, IsoMissingVerdict,
  KvmWeakUntrusted) and OsInstallRuntimeDiagnosticVerdict's copies gain the
  Runtime prefix. All wire strings byte-identical.
- Same-file pairs: ReviewSource.Llm -> LlmSource (ReviewProvider keeps);
  ReviewEvent.Pending -> PendingEvent (ReviewState keeps the upstream-cited
  PENDING; not a wire event value upstream, so no cited string breaks;
  pipeline.rs wire-contract needle updated); OpenAI annotation UrlCitation
  -> ChatUrlCitation / ResponsesUrlCitation (both endpoints cited, zero
  uses, no wire-contract rows exist for these enums);
  ConvergeVerdict.Converged -> VerdictConverged (std Reconciliation keeps;
  fleet_show_effective_read's if-branch type mismatch was this collision's
  downstream shadow); workflow/types ArtifactKind.Design -> DesignDoc and
  OutcomeStatus.TerminalFailed -> OutcomeTerminalFailed (IssueLifecycleStage
  keeps both).
- Witness-test + gunbc/extdeps import batches: reviewer_source, hardware
  selection, transport fidelity (S/L/Xs size arms), pep440 (Ordering arms),
  uri path tokens, jedec/bmc/storage grounding rows, ci_render,
  gunbhub_serve, sk_hynix, transports file/rest/shell - each gains its
  owner-enum import from the defining module.

Env-counter dissolution (04_env.dag + 04_infer.dag): the 2026-07-04
pathology instrument's record_* statement calls and stub fns are deleted -
the pathology they measured is dead (900s-capped -> 1.14s), and they were
also the ONLY corpus instances of a statement-then-expression block the
Rust emitter renders without a separator. That emitter deficiency is why
regen has been silently broken since B1/B2 (whose commits hand-edited
generated files): the first regen probe failed parsing emitted
v1_compiler_infer_env.rs at exactly that construct. Getter stubs stay for
phase_profile API compatibility. Emitter statement-separator fix is
ledgered with the emit-stage work (regen probe: Rust emit completes in
~2 min, so C8 is time-feasible).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* regen_stage0: register phase_profile.rs as hand-maintained

The 2026-07-04 heartbeat module was added to stage0/src without a registry
entry, so --emit-fresh assembled a crate whose lib declares mod
phase_profile but carries no file (probe failure after the counter
dissolution unblocked emission). Its header carries its own dissolution
trigger (realization_measurement_loop Phase 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Rust emitter: shared_types dominates needs_box_wrapping (kills Box<Rc<T>> double-wrap)

A shared (Rc-rendered) type never needs Box - Rc is already the
cycle-breaking indirection. The old ordering short-circuited
recursive->Box before the shared check, which was benign only while
emit-time recursive_types stayed module-local; after B1's build_type_env
rework propagated imported recursive types, every Rc field of
Node/TypeEnv/PositiveDescentAmount/... double-wrapped, and regen output
stopped matching the committed seed ABI (596 of the 770 build errors on
the first regen attempt). This is one of the deficiencies that
accumulated while RegenVerifyGate was red-by-timeout: B1/B2 co-landed
hand-edited generated files because regen could not reproduce them.

Two-step: dag authority (05_emit_rust.dag) + functional hand-patch of the
generated emitter (v1_compiler_emit_rust.rs), replaced by regen's true
output in the convergence commit. Receipt: re-regen after the reorder
emits ZERO double-boxed fields (the only remaining Box<Rc grep hit is
this fix's own marker string); committed Box<ByteSize>-style non-shared
boxing (std_realization_schedule) preserved exactly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fix emitter-fix commit: restore hand-patched needs_box_wrapping (prior commit captured regen output)

The previous commit's v1_compiler_emit_rust.rs accidentally snapshotted
the REGENERATED emitter (regen write had overwritten the hand-patch
before the commit): the regenerated emitter carries the deref-side
boxing asymmetry and does not build. Restored the committed seed's
emitter with the shared_types-dominates reorder applied as intended.
Receipt: cargo build --workspace green on this commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Resolver design: emitter restoration ledger (§7b) — regen was semantically broken on main

The constructor-ruling PR's regen attempt discovered RegenVerifyGate's
red-by-timeout had been masking semantic regen breakage (B1/B2 co-landed
hand-edited generated files). Three deficiencies fixed in this PR
(statement-separator emission via counter dissolution; needs_box_wrapping
shared-dominates reorder; phase_profile registry); three ledgered with
receipts for the restoration PR (deref-side boxing asymmetry ~800 errs,
alias-brand rendering ~250, misc ~80). Seed stays the functionally-verified
hand-patched realization until restoration lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Diagnostics: locate error-typed nodes reaching evaluation

Two instrumentation edits for the fail-open seam where an inference-side
error node reaches the interpreter without a blocking diagnostic:
- v1_interpreter (hand-maintained): ExprError eval errors now carry the
  node's span (file:start-end).
- infer field-access cascade (seed hand-patch, replaced at regen): names
  the accessed field, the error-typed base, and the module.

Receipt: the parse_table_memo failure went from 'error type cascade' to
'error type cascade (field class on error-typed base tok in
v2.compiler.parse) at src/v2/compiler/02_parse.dag:31281-31282' — the
open investigation for the 7 remaining interpreted-parse suite reds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fix two pre-existing silent compiler seams (interpreted-parse suite reds) + walls

Both located via span-instrumented errors, a 14-fixture minimal-repro
ladder, and pristine-main worktree A/B (both reproduce identically on
main; both classes were unverifiable there through the pre-fix resolve
timeouts).

1. Interpreter kernel-optional unwrap (hand-maintained v1_interpreter.rs):
   kernel optionals at runtime are raw-value-or-Null, and match_pattern's
   raw-payload unwrap guards (Present+Optional, Holds+Witness) sat BELOW
   the kind-specific arms - Value::Record/List/Str/Int matched their kind
   arm first and returned None from inside it, so
   'match xs |> first { Present { value: t } => ... }' failed
   non-exhaustive on any record element (Variant payloads had an inlined
   fix; everything else fell through). Guards hoisted above the kind arms;
   Variant payloads excluded so the existing Variant-arm logic stays
   authoritative.

2. Kernel-prelude generic shadowing (dag authority 04_resolve.dag +
   seed two-step in v1_compiler_infer_resolve.rs): for multi-import
   modules the ancestry cache merges the kernel as OVERLAY, so a user
   generic coproduct NAMED Optional (v2.std.collection) resolved to the
   paramless kernel Optional at its consumers; is_user_generic_use_site
   went false, Optional<T> signatures were never expanded/stamped,
   lookup_variant_in_type returned Blocked with ZERO diagnostics, and
   pattern bindings went error-typed silently - the 'error type cascade'
   at eval (import-count-dependent because single-import modules skip the
   kernel overlay). Fix is surgical: a use site WITH type arguments whose
   primary lookup lands on a paramless decl retries the DIRECT import
   parents' str_bindings for a parameterized decl (the params filter
   naturally excludes the kernel parent). The wholesale precedence flip
   (kernel-as-base) was tried and reverted - it broke kernel function
   dispatch through an unmapped path; ledgered for the restoration PR.

Receipts: parse_table_grammar_memo_multi_file_ingest_parses PASS (was
'error type cascade at 02_parse.dag:31281'); all 11 repro fixtures PASS;
new permanent walls in kernel_shadow_seams_test.rs (record-payload
unwrap; imported-Optional shadowing). Located-diagnostics kept: ExprError
eval errors now carry spans; the infer cascade names field/base/module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Post-engine-PR roadmap: deferred ledger + compiler algorithm audit plan

Part A: the twelve items PR #6235 deliberately deferred, weighted -
emitter restoration -> regen convergence (§7b receipts), emit-stage cost
(the next resolver-class pathology, >20min/89 modules measured),
kernel-prelude shadowing root rule (wholesale flip blocked on the
unmapped kernel-fn-dispatch path), Value::Null split, flat-visibility
re-census decision, C9 receipts, determinism roster re-signing, binder
find-first hardening, diagnostics dedup, witness re-enrollment
dissolve-on, coverage-by-illusion census, resolver S2a/S2b/S3.

Part B: the algorithm audit method - every stage factored as units x
work-per-unit (the resolver failed both axes at once), inventory ->
verdict -> measure -> fix by displaced cost -> budget witness per stage.
Survey table lands from the eight-stage parallel inventory in flight.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Brace else-match in resolve_generic_use_decl (v1 grammar requirement)

The parents-retry fold used 'else match' without braces, which the v1
grammar rejects. Claim-path closures never parse src/v1, so only
resolve_expr_types_retraversal_guard_test caught it ("parse failed for
src/v1/04_resolve.dag"). Braced; guard test green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fix interp_dry_run hermetic fixture: workspace target/, not /tmp

The failure was misdiagnosed as a stale release binary. Real cause: the
hermetic witness fixture was written to std::env::temp_dir(), and
build_module_path_index fail-closes on module paths outside the
workspace — same seam as the 7 test files already migrated; this one
was missed. Fixture now lives under workspace target/ like the rest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Roadmap: record local full-suite green receipt (656/0/85)

Corrects the A.6 stale-binary diagnosis: the last two suite reds were
the resolve_generic_use_decl else-match brace and the interp_dry_run
/tmp fixture path, both fixed in the prior two commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Algorithm audit: 8-stage survey results + ranked fix order

Appends the survey synthesis to the post-engine-PR roadmap: 9
PATHOLOGICAL findings ranked with anchors (dag_collect Rc-accumulator
O(M^2) as the measured >20-min emit suspect; token-stream skip|>first
O(M^2) parse; whole-corpus rewire scan per name; per-entry closure
fixpoint regression vs the in-file worklist BFS; request-major
imported-variant binding; interpreter env chain O(d); v2 translate
facts/serialize quadratics; dead v2 packrat memo; v2 closure-chain
namespace), a SUSPICIOUS tier, six root-cause clusters, and a fix
order priced by displaced cost. Raw per-stage catalogs land as their
own receipt doc. Four top claims spot-verified against the live tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* rustfmt: format hand-edited interpreter guards + new test files

CI's cargo fmt --check flagged the hoisted match_pattern guard block in
v1_interpreter.rs, the fixture-dir join chain in
kernel_shadow_seams_test.rs, and the out-of-alphabetical-order mod
declaration in tests/lib.rs (rustfmt reorders modules). cargo fmt --all
applied; fmt --check, clippy -D warnings, and the seam tests verified
green locally. Also enabled the repo pre-push hook path in this clone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

* Fold hand-edited doc content into dag authorities; main_wet regen green

C9 item: main_wet regen + drift gate. Three findings, all fixed at the
authority layer, not the projection:

- PR #6186 added §11 (folded deltas) to the generated
  bounded-input-cost-envelope-scheduling.md without updating its dag
  authority — a parallel-representation slip the drift gate caught on
  this branch's first hooked push. §11 is now authored in
  dag/gunbc/plans/bounded_input_cost_envelope_scheduling.dag and the
  projection regenerates identically to the signed content.
- regime2-shared-emission-fold.md regenerates with FragmentText (this
  branch's markup collision rename), ROADMAP.md with normalized tail.
- Doc-graph orphans: linked the post-engine deferred-ledger/audit
  roadmap from the CI lane's receipts prose (survey receipt doc is
  reachable through it), and linked docs/plans/host-converge-inventory.md
  (orphaned since #6177 — no inbound link anywhere on main) from the
  converge-lane prose.

Receipts: PASS main_wet, PASS run_generated_artifact_drift_gate_body,
PASS doc_graph_has_no_orphan_docs, PASS doc_graph_has_no_dangling_links.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcouXUHJmm4NPqwDyvnDKf

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant