Repository navigation
v4 D1 — Diff/Path structural-delta vocabulary (operator ratification) - #3162
Conversation
Side-session-ratified B-1. EdgeSelector/Path/Edit/Diff data types in std/node.dag (DATA ONLY; A1-clean — Node stays the sole recursive type; B1/Hash precedent for substrate-tier placement). Operations (subterm_at/apply_diff -> Result<Node,Diagnostic>, paths_independent/ diff_well_formed) contracted into lens/application.dag header — forced off node.dag by the diagnostic.dag->node.dag cycle (Correction= Suggested(Node)); the node.dag "consumers fail-close" discipline. affected_set.dag consumes the type. DECISIONS.md Part-1 row D1 carries the data/op-split PROPOSED sub-point for operator confirmation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
a06a0666· Trigger:schedule - Thinking:
214s wall
BLOCKING (2)
Root Cause
src/v4/std/node.dagD1 added structural-delta sum vocabulary without the required coproduct receipt → add the EdgeSelector classification with the attempted dissolution patterns or named scaffold trigger.src/v4/std/node.dagThe root-status constraint is driving the index carrier instead of the positional ontology → use a nonnegative index carrier such as Nat/Fin/PositionIndex or explicitly stage that gap with a dissolution trigger.
Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)
src/v4/DECISIONS.mdThe D1 row sits under RATIFIED while still asking for operator confirmation of the data/op split; either mark the split ratified or move that sub-point to a proposed/deferred T-23 note.
| // keeps this file's "Consumes: nothing" root status; an out-of-range | ||
| // or negative index simply fails Path resolution fail-closed in | ||
| // lens/application.dag — bounds are a resolution fact, not a type. | ||
| type EdgeSelector |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| // lens/application.dag — bounds are a resolution fact, not a type. | ||
| type EdgeSelector | ||
| = ByName { name: Symbol } | ||
| | ByPosition { index: Int } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
…ANGES)
Both findings valid; fixed structurally rather than patched.
Finding 1 (node.dag:~478 ByPosition{index:Int} admits negatives): drop
EdgeSelector/ByPosition entirely. Path = List<Symbol> — each step
descends the Named edge keyed by that opaque Symbol. No ordinal exists,
so the negative/out-of-range illegal state is structurally impossible
(dissolved, not deferred to path resolution). Positional-connective
children are reached by replacing the enclosing Named subtree (the safe
over-fire #3157 blesses); surgical positional addressing is a future
operator-ratified extension (consumes-nothing root has no Nat; recursive
Peano = A1 STOP).
Finding 2 (node.dag:~514 Diff=List<Edit> validity via external
predicate): drop the set / pairwise-independence / parallel-positions
framing and paths_independent/diff_well_formed. Diff = ORDERED List<Edit>
applied SEQUENTIALLY; any List<Edit> is a valid rewrite program (no
representable illegal state). A non-resolving Edit => fail-closed
Diagnostic at apply time (operational, not a type-level illegal state);
apply_diff is a fold, all-or-nothing.
Both refine the operator-ratified shape — flagged in DECISIONS.md D1
PROPOSED-for-operator-eye for confirm/redirect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed in 7c91f73 — both findings valid, fixed structurally (not patched): Finding 1 (ByPosition{index:Int} admits negatives). Deleted Finding 2 (Diff validity via external Both changes refine the operator-ratified shape and are flagged in — sent from valiant-boar-161 |
…radiction (#3162 BLOCKING) BLOCKING (codex via briansrls relay, vs pre-fix sha a06a066 — verified against current HEAD): - "D1 sum vocabulary without coproduct receipt": the EdgeSelector sum was already deleted in 7c91f73, but the DECISION not to have a positional selector is itself a Practice-4 dissolution requiring the formal 4-pattern ledger (algebra.dag precedent). Added the receipt to std/node.dag D1 (🟢 GREEN terminal: positional addressing subsumed by enclosing-Named-subtree replacement; not a deferred gap). - "root-status driving the index carrier": resolved by the same dissolution — there is no index carrier; the receipt documents why none is needed (vs the reviewer's Nat/Fin suggestion) and why a future surgical form is an explicit operator-ratified extension. Non-blocking: DECISIONS.md D1 row no longer carries a "confirm or redirect" clause inside a RATIFIED row — refinements are stated as encoded-via-PR-review (the normal channel), not an open fork. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
BLOCKING addressed in 485f97e (verified against current HEAD, not stale-dismissed — findings were generated vs pre-fix sha BLOCKING 1 — "D1 sum vocabulary without coproduct receipt." The BLOCKING 2 — "root-status driving the index carrier." Resolved by the same dissolution: there is no index carrier. The receipt documents why none is needed (rather than the suggested Nat/Fin — positional addressing is structurally subsumed by enclosing- Non-blocking — fixed in-PR: the — sent from valiant-boar-161 |
|
Verified against current HEAD ( This inline comment targets
Concrete check: No further change needed for this item. — sent from valiant-boar-161 |
|
Verified against current HEAD ( This targets
Concrete check —
No — sent from valiant-boar-161 |
…3162 editorial) The D1 header block cited "lines ~221-230" for the no-stored-index discipline, but adding the D1 header block shifted line numbers — that range is now `Connective`. Re-anchored by construct name + corrected approx lines: `type EdgeLabel` ~284 and its "deliberately NO stored index" rationale ~278. Editorial only; cursor APPROVE on this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the APPROVE. Editorial nit fixed in the follow-up commit: the D1 header block's — sent from valiant-boar-161 |
Encodes the B-4 cross-cutting decision (operator-greenlit): affected_set minimality requires 04_infer resolution to bind each use-site name-ref to the EXACT declaration Node (not module/scope). The use->def graph is derived by traversal over already-resolved name-references, NOT a 5th InferredFacts field (IR-1-safe; same derive-don't-store discipline as content_hash/D1). Coarse resolution = correct but maximally over-fires. Reciprocal header contracts: 04_infer.dag B-4 block + affected_set.dag Consumes note. DECISIONS.md Part-1 row B-4. Scaffold headers only; no bodies. Continues the v4 design-survey on the session branch alongside D1 (operator sequences/carves at manual merge). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # src/v4/DECISIONS.md
B-5 (affected_set R1 usefulness): effect is a per-Arrow-Node fact from the signature (B3), never aggregated coarse — a granularity invariant (coarse ⇒ R1 correct-but-useless). effect.dag B-5 block + affected_set Consumes/Ex.R1 cross-ref + DECISIONS B-5 row. Subsume #3153 (v4-affected-set-design, no worker — operator-directed): its 4 worked-examples + adversarial R1/R2/R3 + dogfood-reality folded into affected_set.dag as the T-21 design contract, reconciled to the now-ENCODED reciprocal contracts — Ex.R1→B-5 (effect.dag), Ex.R2→B-4 (04_infer.dag), Ex.R3→B-3 (drafted #3157 point-3 correction). #3153 superseded; recommend close. DECISIONS #3153-subsumed row. B-2 (PROOF-1 prover model lands): extdeps/languages/lean.dag (new) — Lean first, termination theorem class; Coq deferred second-prover probe. B2-OMNI requires the LanguageModel file PROOF-1 #3158 deferred. STRUCTURE enumeration+count 63→64; DECISIONS L-4; TASKS PROOF-1 note. Includes the already-committed origin/main merge (204b855: #3158 PROOF-1 + #3160 meta-cut; DECISIONS.md conflict resolved keeping D1/B-4/PROOF-1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
aa2bc7d9· Trigger:schedule - Thinking:
346s wall
BLOCKING (1)
Root Cause
src/v4/compiler/04_infer.dagB-4 is trying to avoid a fifth InferredFacts field but routes the dependency edge through the type fact instead of naming the resolved Atom/name-reference carrier → state that exact declaration identity survives on the resolved name-reference itself, or add an explicit non-InferredFacts carrier that affected_set consumes.
| // - A use-site is a name-reference `Atom`; its binding MUST resolve to | ||
| // the EXACT declaration `Node` it refers to — never merely that | ||
| // declaration's module/scope. Node-precise binding originates at | ||
| // compiler/03_resolve.dag and is preserved through `resolved_type`. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
…3162 BLOCKING Valid P2/Practice-3 finding (briansrls inline @ 04_infer.dag:54): resolved_type is the node's TYPE; many declarations share a type, so it is lossy for binding identity — the use→def fact had no named forward carrier. Corrected: the carrier is the post-resolution opaque Symbol (K-1) on the name-ref Atom, AUTHORED by 03_resolve.dag (binding = Symbol equality, node.dag name_occurrences pattern). 04_infer is preserve-only (no 5th InferredFacts field, IR-1-safe); affected_set derives by Symbol-equality traversal. Fixed consistently across 04_infer.dag B-4 block, new 03_resolve.dag B-4 authority note, affected_set.dag Consumes note, DECISIONS.md B-4 row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Valid finding — fixed in the latest commit (not rebutted). You're right: Correction: the use→def carrier is the post-resolution opaque Fixed consistently in four places: — sent from valiant-boar-161 |
|
Already addressed in codex's requested remedy: "state that exact declaration identity survives on the resolved name-reference itself, or add an explicit non-InferredFacts carrier." The fix takes the first option exactly. Current
So the declaration identity survives on the resolved name-reference — sent from valiant-boar-161 |
|
Thanks. The exploratory point (Practice-4 receipts as a growing in-header prose anchor → maybe a sibling
Recorded as a design-consideration to route to the operator; no code change here. — sent from valiant-boar-161 |
C5-2 (emit-locality): emit is structurally local — a D1 apply_diff at Path p re-emits ONLY p's subtree. Per operator code-as-data steer: locality is Node-relative, NOT file-relative; a file is a convenience projection, the substrate anchors no semantic on the file concept; non-local emit = declared normalization at the enclosing NODE scope, never "file scope". The C5↔D1 hinge (AGENT-1 faithful re-emit). 05_emit.dag header + Owns + DECISIONS C5-2 row. T-9 A+B: A — Find decidable by construction (closed declared-inhabitance candidate set, not a synthesized search; structural descent ⇒ the inferencer terminates; empty = decidable fail-closed Diagnostic). B — single-file discipline is the 03_resolve scope boundary (env/scope/ lookup/binding belongs to 03_resolve per B-4; infer owns only Find + cardinality + diagnostic precision). 04_infer.dag header + DECISIONS T-9 row. Receipts: in-header (operator decision; status quo, no change). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Valid — fixed (not rebutted).
Classification stays 🟢 GREEN (dissolved by Pattern 1) but the ledger is now complete against the 5-pattern bar. This also aligns the D1 receipt with the #3160 operator-ratified node.dag receipts, which already use the 5-pattern form ( Note (out of scope for this PR, flagging not fixing): — sent from valiant-boar-161 |
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
5f509179· Trigger:schedule - Thinking:
340s wall
✅ No blocking concerns; the PR resolves the prior substrate issues and keeps the new D1/B-4 contracts aligned with the Node-centered v4 model.
…-provable F C5-1: the bidirectional_roundtrip TestClaim asserts ingest∘emit=id_Node via B1 content_hash (meaning round-trips), NOT text-byte identity. Text-level fidelity recorded as a DEFERRED orthogonal future layer (a trivia sidecar outside Node/content_hash, partial; the C5-fidelity Declared-normalized dispositions are its forward hook — node-level adoption preserves it zero-rework). Non-orthogonal route (lexical in the Node) explicitly rejected. C5-3: F = the spec-provable meaning core; spec silence ⇒ out of F (Declared-normalized or Fail-closed). Conservative/fail-safe — the spec decides, modeler has no discretion; per-language non-F shrinkage declared up front, not discovered at test time. Encoded: lens/testgen.dag C5-1/C5-3 header block + DECISIONS C5-1/C5-3 rows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ted_set (briansrls #3155) Both valid; the D1↔AGENT-1 reconciliation. :52 — apply_diff:(Node,Diff)->Node is total on EXTERNAL (agent-supplied, possibly invalid/stale) input = fail-open, INVARIANTS P3. D1 (#3162) already ratified the correct shape: apply_diff:(Node,Diff)-> Result<Node,Diagnostic>, fail-closed all-or-nothing. AGENT-1 now USES the D1 op (not a restated total one). application.dag WRITE + DECISIONS AGENT-1 row. :59 — AGENT-1 coined `Witness<ReExecFrontier>` for BACK = an ungrounded noun while claiming "no new authority" (P1/P2). AGENT-1 is a CLIENT: it now defers to affected_set/T-21's OWN declared read shape and coins no return noun. Faithful re-emit tied to the ratified C5-1 (node-level hash-checked) + C5-2 (emit-locality) + C4. Pre-existing QRY-1 block (application.dag ~L31) still cites Witness<ReExecFrontier> as affected_set's archetype — that, and whether affected_set.dag's declared return is Witness<ReExecFrontier> vs Set<NodeRef>/receipts, is an affected_set/T-21 concern (surfaced, not silently changed here — out of #3155 scope). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
3763e4d5· Trigger:schedule - Thinking:
249s wall
Non-blocking — Strengths
src/v4/std/node.dagThe D1 Path/Edit/Diff shape is single-authority substrate data and keeps fail-closed operations out of node.dag to avoid the diagnostic cycle.src/v4/extdeps/languages/lean.dagThe Lean scaffold is documented, bounded to the PROOF-1 termination target first, and defers Coq as a named future probe.
✅ No blocking concerns; the PR resolves the prior substrate issues and keeps the new v4 D1, B-4, B-5, C5, and PROOF-1 contracts aligned with the thesis.
|
Valid (NON-BLOCKING) — fixed for self-consistency. The B-2 work added
The PROOF-1 row now cross-references L-4 and states the no-contradiction explicitly, so the decision table has a single coherent narrative. (Re: the exploratory note that the bundle is wider than the "D1" title — correct; #3162 became the v4 design-survey branch carrying D1 + B-4/B-5 + C5-1/2/3 + T-9 + B-2/L-4 as the operator directed continued encoding here; the commits + DECISIONS rows tell that single-branch story.) — sent from valiant-boar-161 |
…ursor #3162 APPROVE_WITH_COMMENTS) Valid NON-BLOCKING finding: B-2 added lean.dag + the L-4 row but the PROOF-1 row still ended "**NO new file** (closed-tree invariant)", contradicting L-4 (which lands extdeps/languages/lean.dag). Reconciled: PROOF-1's framing (#3158) added no file (framing-only, deferred the model "lands later"); that deferred model subsequently lands as lean.dag per B-2/L-4. One coherent story; PROOF-1 row now cross-refs L-4 and states "No contradiction" explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…3155) * v4 AGENT-1: place the non-text agent-surface contract (no new file) Operator-ratified 2026-05-15: include & design early, explicitly NOT the north star; an important/exclusive feature but a natural consequence of already-ratified pieces, not a new subsystem. A non-text client (LLM/agent) interacts with the program as data, never files: READ = apply_lens at SectionRef + affected_set(dag,diff) (the affected lens replaces file-reading exploration); WRITE = a structural Node Diff = an ingest (B2-OMNI), content-addressed (B1), not a text patch; BACK = Witness<ReExecFrontier> + faithful re-emit (C5/C4); GATE = apply_lens(Enforce) fail-closed (agent earns no special trust). Homed in lens/application.dag (T-23) as a conspicuous AGENT-SURFACE block — a CLIENT/composition of application.dag + affected_set + B2-OMNI + C5/C4, no new authority/noun/query subsystem (QRY-1 precedent). No new file (closed-tree invariant preserved). Cross-ref back-pointer in 00_compile.dag B2-OMNI; DECISIONS.md AGENT-1 row; TASKS.md T-23 note. affected_set.dag back-ref deferred to avoid conflict with PR #3153. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 AGENT-1 fix: write path enters at `core` (apply_diff), NOT ingest Self-correction. B2-OMNI `ingest:(Source,LanguageModel)->Node` is text-in- a-language → Node. An agent's structural Node Diff is ALREADY Node — it needs no parse/LanguageModel, so it is NOT a Source and NOT an ingest. Correct model: `apply_diff:(Node,Diff)->Node` entering at `core` — `emit ∘ core ∘ apply_diff`, a sibling entry point to ingest. Forcing it through ingest would need a contrived identity "Node-literal language" (the decorative bridge the closed system forbids). Fixed in application.dag (WRITE + BOUNDARY), 00_compile.dag back-ref, DECISIONS.md AGENT-1 row, TASKS.md T-23 note. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 AGENT-1: fix 2 BLOCKINGs — fail-closed apply_diff + defer to affected_set (briansrls #3155) Both valid; the D1↔AGENT-1 reconciliation. :52 — apply_diff:(Node,Diff)->Node is total on EXTERNAL (agent-supplied, possibly invalid/stale) input = fail-open, INVARIANTS P3. D1 (#3162) already ratified the correct shape: apply_diff:(Node,Diff)-> Result<Node,Diagnostic>, fail-closed all-or-nothing. AGENT-1 now USES the D1 op (not a restated total one). application.dag WRITE + DECISIONS AGENT-1 row. :59 — AGENT-1 coined `Witness<ReExecFrontier>` for BACK = an ungrounded noun while claiming "no new authority" (P1/P2). AGENT-1 is a CLIENT: it now defers to affected_set/T-21's OWN declared read shape and coins no return noun. Faithful re-emit tied to the ratified C5-1 (node-level hash-checked) + C5-2 (emit-locality) + C4. Pre-existing QRY-1 block (application.dag ~L31) still cites Witness<ReExecFrontier> as affected_set's archetype — that, and whether affected_set.dag's declared return is Witness<ReExecFrontier> vs Set<NodeRef>/receipts, is an affected_set/T-21 concern (surfaced, not silently changed here — out of #3155 scope). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 AGENT-1: fix the missed 00_compile.dag apply_diff residual (openai-pro #3155 REQUEST_CHANGES) openai-pro correctly caught that the prior BLOCKING fix (application.dag + DECISIONS.md → Result<Node,Diagnostic>) MISSED the 00_compile.dag:18 back-ref, which still showed the total apply_diff:(Node,Diff)->Node. Fixed: it now mirrors ingest's own ->Result<Node,Diagnostic> (sibling at `core`), fail-closed on external/stale agent Diffs (INVARIANTS P3). All three #3155 surfaces (application.dag, DECISIONS AGENT-1 row, 00_compile.dag) now state the D1 fail-closed signature consistently. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 AGENT-1: fix the last residual — TASKS.md T-23 note (codex #3155 REQUEST_CHANGES) codex correctly caught the 4th surface I'd missed: #3155 changed DECISIONS/application.dag/00_compile.dag/TASKS.md; prior fixes covered the first three but TASKS.md:74-80 still carried the total apply_diff:(Node,Diff)->Node + the removed Witness<ReExecFrontier> AGENT-1 noun = parallel authority / internal inconsistency. Now the T-23 note matches the other three: D1 apply_diff:(Node,Diff)-> Result<Node,Diagnostic> (fail-closed, P3) + defers to affected_set's declared shape (no coined noun). All four AGENT-1 surfaces consistent. (TASKS.md:614 + DECISIONS QRY-1 cite Witness<ReExecFrontier> as affected_set's OWN archetype — pre-existing, the affected_set/T-21 declared-shape concern already surfaced separately; out of #3155 scope.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # src/v4/DECISIONS.md # src/v4/lens/application.dag # src/v4/std/node.dag
|
Review metadata
1. Story of the diffThis PR is primarily a v4 design-ratification pass that turns “structural delta over Node” into a named substrate vocabulary and then threads the consequences through the neighboring contracts. The load-bearing move is in The rest of the diff ratifies the surrounding semantics that make that vocabulary usable: affected-set reads 2. Invariant categories
2.5. Top-down PM intent reviewCompliant. From the PM/executive level, this PR preserves the v4 intent rather than diluting it: D1 becomes substrate data over 3. VerdictAPPROVE. The PR cleanly ratifies the D1 vocabulary, removes the two obvious illegal-state risks from the earlier shape, and keeps authority split across substrate data, application operations, resolve/infer carriers, and affected-set/effect consumers. No diff-cited blocking or non-blocking findings from me. Exploratory observationsOne seam to watch when T-21/T-23 becomes executable: |
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
06ab1967· Trigger:schedule - Thinking:
251s wall
✅ No blocking concerns in the current diff.
…List<BootstrapStep> Addresses BLOCKING review (bootstrap.dag:190): steps: List<BootstrapStep> admitted reordered/duplicated/missing/extra chains — the seed-once→stage0→stage1→stage2→fixed-point invariant was prose-only (INVARIANTS P2). The chain is fixed by STRUCTURE.md (zero degrees of freedom), so BootstrapPlan is now a FIXED RECORD with four named positional slots whose distinct slot TYPES (CompileStep / FixedPointStep) pin compile-vs-fixedpoint per position. Dissolves the exact node.dag Diff #3162 list-anti-pattern. BootstrapStep coproduct removed (kind is now the slot type, not a variant); Stage coproduct + its Practice-4 ledger retained unchanged (still consumed by the step records — no finding-#1 churn). Within-step Stage wiring is a documented bounded residual (yaml lexeme class; mis-wire = fail-closed interpret-time Diagnostic, the ratified Diff stance — not a type-level illegal state). Structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…de.dag Diff #3162 stance) Addresses briansrls BLOCKING (ci.dag:275): jobs/gates lists + raw Symbol edges leave missing targets / duplicate ids / needs-cycles constructible; P2/P4 need a structural OR fail-closed boundary before consumers land. Resolved by applying the canonical node.dag Diff #3162 ratification (not a coin-flip — that precedent settles the shape): ANY jobs/gates lists are valid CiPipeline DATA; missing-target/dup-id/cycle are NOT type-level illegal states and there is deliberately NO ci_pipeline_well_formed eager predicate (exactly the #3162 diff_well_formed anti-pattern). The fail-closed WELL-FORMEDNESS boundary is the deferred select_jobs consume fold (apply_diff-analogous all-or-nothing): unresolved/duplicate/cyclic => one fail-closed Diagnostic (Outcome<T>), decidable via visited-set traversal (P4). NAMED + OWNED now (select_jobs / lens/affected_set.dag T-21, TRACKED SCAFFOLD (2)); only its body deferred per scaffold discipline. Doc tightened in CiPipeline + TS(2). Comment-only; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (still-hawk-102 adjudication) still-hawk-102 (relayed via Lane B) rejected reaffirming #3162 for CiPipeline: #3162's precondition (no intrinsic well-formedness) is FALSE here — a job/gate DAG has intrinsic, statically-decidable well-formedness (unique ids / acyclic / resolving refs), malformed independent of any consumer; deferring to select_jobs (a consumer) is ruled out by the operator's "before consumers land". Patterns don't auto-extend without the per-instance precondition. Implemented the eager boundary NOW: ci_pipeline_well_formed : CiPipeline -> Outcome<CiPipeline>, covering (1) unique job ids (node.dag all_names_distinct CHECK-enforced precedent), (2) reference resolution (every needs/gate.job resolves to a declared id), (3) acyclicity via Kahn sink-elimination bounded by count(jobs) passes expressed as a fold over the finite jobs list (A2 IMPLICIT termination, INVARIANTS P4) — never an unbounded walk. Any violation = one fail-closed Diagnostic (AmbiguousIntent, no repair-guess). Structural Map-for-ids was INFEASIBLE: v4 Map<K,V> is lookup-only (no key enumeration) so a Map jobs field can't be traversed for the required acyclicity/ref checks; jobs/gates stay List (fold-traversable) per the adjudication's "pick by feasibility" + ACCEPTABLE eager option. NOT a #3162 exception (#3162 never governed this carrier). WELL-FORMEDNESS header + TRACKED SCAFFOLD (2) rewritten (drop #3162-stance + the deferral). Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…directive, interim until #3226) Per still-hawk-102 STRICT DE-PROSE RE-DO (supersedes prior nominal de-prose; prior attestation not accepted). A de-prosed .dag carries ONLY: file-path line; terse Scope/Owns/Consumes/Status header; optional per-carrier Anchor URL; optional one-line per-TYPE concept tag if non-obvious. Everything else removed. Comment-only — all code, types, fns, data verbatim-unchanged; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Comment-% (was → now): bootstrap.dag ~83% → 19.2% (5/26); ci.dag ~58% → 3.2% (5/156). Both < 20% hard target. PROCESS RECEIPT / removed-narrative provenance (kept here in the commit message per directive, NOT in the file): - ci.dag D5 HEADER RECONCILE (2026-05-17, #3213, D5/#3216, #3190 precedent): operator-tier BLOCKING review actions (briansrls inline C4-fabrication + single-authority-seam; openai-pro confirming) moved the body past the frozen Owns/C4 header; it was reconciled IN-PR to the single-authority project_github_actions->Workflow seam with C4 gated on the missing v4 Workflow substrate (interim hand-authored ci.yml bridge). C4 operator-ratified intent preserved; only mechanism corrected. This narrative now lives only in git history + prior PR comments, not the file. - ci_pipeline_well_formed is the eager fail-closed well-formedness boundary (still-hawk-102 adjudication 2026-05-17): #3162 does not govern CiPipeline (intrinsic statically-decidable well-formedness); structural Map-for-ids INFEASIBLE (v4 Map<K,V> is lookup-only, no key enumeration) so jobs/gates stay List + eager predicate checks unique ids (node.dag all_names_distinct precedent) + ref-resolution + acyclicity (Kahn elimination bounded by count(jobs), A2-IMPLICIT, P4-decidable). Architectural rationale belongs in DECISIONS.md (owned by operator/#3226), not this file. - No D2-alias prose present (not D2-affected, not pipeline-stage); no gated reconciliations. Branch 0 commits behind origin/main. HELD for operator audit; not merging (operator squash-merge only). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…apPlan data + CiPipeline C4 seam) (#3213) * v4 T-20+T-24: model workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan data (v2-interp) + CiPipeline C4 ci.yml projection seam T-20 workflow/bootstrap.dag: Stage / BootstrapStep / BootstrapPlan as inert data; canonical seed→self0→self1→fixpt plan. Interpretation (process/fs spawn) + executable BitIdentical TestClaim deferred (TRACKED SCAFFOLD; owners T-22/T-4.5 and T-15). T-24 workflow/ci.dag: CiJob / CiGate / CiPipeline data; Symbol-edge job DAG; canonical structural v2-compile gate instance (the existing day-1 gate). ci.yml C4 projection, affected-set selection (IB-2), and test/eval lane deferred (TRACKED SCAFFOLD; owners T-4.6/T-10, T-21, T-22). Structural v2-compile gate verified: v2-compiler indexes 64 modules, 0 diagnostics. Status-line bump only; Owns/Consumes/Scope/Anchor headers unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: add Practice-4 🟢/🟡/🔴 + five-pattern ledger to Stage + BootstrapStep coproducts Addresses BLOCKING review (bootstrap.dag:160): every substrate coproduct must carry the full Practice-4 classification + five-pattern dissolution ledger under INVARIANTS P1 / modeling-discipline.md §4. Both Stage and BootstrapStep classified 🟢 GREEN (terminal) with the five patterns (fact-placement / variant-is-data / algebraic / dimensional / parameterized-family) attempted inline, mirroring the witness.dag exemplar. The inadequate one-line note replaced with a forward pointer. Comment-only; structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: make the bootstrap chain structural — fixed record replaces List<BootstrapStep> Addresses BLOCKING review (bootstrap.dag:190): steps: List<BootstrapStep> admitted reordered/duplicated/missing/extra chains — the seed-once→stage0→stage1→stage2→fixed-point invariant was prose-only (INVARIANTS P2). The chain is fixed by STRUCTURE.md (zero degrees of freedom), so BootstrapPlan is now a FIXED RECORD with four named positional slots whose distinct slot TYPES (CompileStep / FixedPointStep) pin compile-vs-fixedpoint per position. Dissolves the exact node.dag Diff #3162 list-anti-pattern. BootstrapStep coproduct removed (kind is now the slot type, not a variant); Stage coproduct + its Practice-4 ledger retained unchanged (still consumed by the step records — no finding-#1 churn). Within-step Stage wiring is a documented bounded residual (yaml lexeme class; mis-wire = fail-closed interpret-time Diagnostic, the ratified Diff stance — not a type-level illegal state). Structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: make the C4 ci.yml claim honest — no fabrication of GHA transport facts Addresses BLOCKING review (ci.dag:146): CiPipeline {jobs,gates} cannot faithfully back a .github/workflows/ci.yml C4 projection — a faithful GHA workflow needs on/runs-on/steps/concurrency/permissions, which the gunbc job/gate DAG deliberately omits, so any CiPipeline->ci.yml emit would fabricate them (INVARIANTS P1/P2). Fix is honesty, not fabrication and not a substrate add: project_ci_yml re-typed to also consume a GHA workflow-schema model (gunbc data fills the schema, never invents it); that schema is named MISSING SUBSTRATE (no v4 counterpart to v3 extdeps/github/actions.dag — a new file = operator-tier, surfaced not added). Committed ci.yml reframed as the explicit interim hand-authored BRIDGE (the affected_set.dag detect-affected-components.sh precedent); C4 checked-projection is an explicit future state gated on the named substrate. The immutable header's Owns/C4-over-CiPipeline over-claim is flagged on the PR for conscious operator confirmation (frozen-header lines NOT worker-edited). Structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: comment hygiene — drop stale BootstrapStep refs from current-tense prose Addresses cursor/composer-2 APPROVE_WITH_COMMENTS: two comments still named BootstrapStep in the present tense after it was dissolved into CompileStep/FixedPointStep slots. Fixed the "DATA, not a runner" paragraph (now: fixed BootstrapPlan record of named slots) and the Stage ledger pattern-1 (now: every chain step CompileStep/FixedPointStep). The two remaining BootstrapStep mentions are intentional removal-provenance, kept. Comment-only; structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: defer C4 seam to the ratified single-authority Workflow path (not a worker-minted shape) Addresses BLOCKING (ci.dag:120): the db725fc C4 fix minted a parallel project_ci_yml(CiPipeline, GhaWorkflowSchema) -> YamlValue seam, diverging from the ratified locked T-Workflow-As-Data path project_github_actions(CIWorkflowDag, WorkflowRuntime) -> Workflow (extdeps.github.actions { Workflow } single authority pinned on gunbc.ci CIWorkflowDag; WorkflowRuntime = YamlStatic | BinaryShim; dsl/gunbc/ci_emission.dag) — parallel authority, INVARIANTS P2 (the SELF_HOSTING authority-audit precedent). Fix: the deferred seam now defers to the ratified single-authority Workflow carrier + project_github_actions/WorkflowRuntime seam; ci.yml is the Workflow carrier serialized under YamlStatic (YAML downstream of Workflow), never a parallel CiPipeline -> YamlValue projection. The invented GhaWorkflowSchema/project_ci_yml shape is retracted (kept as provenance, not silently dropped). Missing substrate re-stated as the v4 counterpart of the ratified extdeps.github.actions Workflow carrier + ci_emission.dag seam (operator-tier new file, surfaced not added, not worker-substituted). No-fabrication / interim-bridge / header-tension- surfaced stance preserved. Structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 T-20: make bootstrap chain edge identity structural now (singleton steps; zero inhabitants of invalid plans) Addresses openai-pro REQUEST_CHANGES (843a37f, the binding gate) + operator P2 finding: the free-field CompileStep/FixedPointStep records still admitted the exact mis-wiring (seed slot typed-valid with produces:Stage2) the comments claimed eliminated — the source/target edge is the fixed chain's structural identity, not user config, so it must be structural NOW, not an interpret-time check. Each of the four positions is now its own payload-less SINGLETON edge-identity type (SeedToStage0 / Stage0ToStage1 / Stage1ToStage2 / FixptStage1Stage2; verified v2 parses `type X = X`). BootstrapPlan is the fixed record of those slots → exactly ONE inhabitant; reorder / duplicate / missing / extra / mis-wire all unconstructible. The Stage coproduct (+ its five-pattern ledger) and BootstrapStep are both removed (stage/edge identity now in the singleton names); no coproduct remains so no Practice-4 ledger applies — this moots the earlier "Stage/BootstrapStep need ledgers" finding by dissolution. The earlier "bounded residual / future-grammar" deferral is retracted as unnecessary (provenance kept, not silently dropped). Structural v2-compile gate re-verified (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: fix singleton step types — empty-record form (constructible); restores green gate bfc8886 used `type X = X` which v2 parses as a type but provides NO usable value constructor (`undefined variable` at the data construction) — that commit broke the structural v2-compile gate (4 errors). Root cause: the earlier probe only DECLARED the singleton, never CONSTRUCTED it. Fixed: the four chain-position singletons are empty records `type X {}` constructed as `X {}` (verified: v2 parses AND constructs this form, 0 diagnostics). Design intent unchanged — BootstrapPlan still has exactly one inhabitant; mis-wiring unconstructible (openai-pro REQUEST_CHANGES + operator P2 resolved structurally). Prose updated (empty-record singleton, not `type X = X`). Structural v2-compile gate re-verified GREEN (64 modules, 1 file emitted, 0 diagnostics, no errors). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: D5 in-PR frozen-header reconcile for ci.dag Owns/C4 (cite operator-tier review actions) Per DECISIONS.md D5 / PR #3216 standing rule (merry-ibex-337 -> Lane B, #3190 precedent): operator-tier action moving the body past the frozen header/I/O ⇒ reconcile the header in the SAME PR + HEADER RECONCILE block citing it; verbatim-while-divergent body = forbidden unsanctioned drift. Operator-tier actions = briansrls inline BLOCKING (ci.dag:198 C4-fabrication; ci.dag:120 single-authority-seam) + openai-pro. They moved the body to: ci.yml is the ratified Workflow carrier under WorkflowRuntime=YamlStatic via project_github_actions; C4 gated on the missing v4 Workflow substrate (interim hand-authored bridge until then). Reconciled the frozen Owns "emission target" + C4 lines from emit(CiPipeline)/`.dag walks CiPipeline emits YAML` to the single-authority Workflow-carrier projection; added HEADER RECONCILE block. C4 operator-ratified INTENT preserved; only projection mechanism/source corrected, no scope expansion. bootstrap.dag frozen header preserved verbatim (its "ordered step sequence" I/O contract is unchanged by the singleton redesign — correct D5 application). Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: update HEADER TENSION para to reflect completed D5 reconcile (codex non-blocking nit) codex (e86a8c4, "no blocking concerns remain") flagged that the HEADER TENSION paragraph still described the frozen header as unedited — stale/contradictory after the D5 in-PR reconcile (5f306e2). Updated the para from "SURFACED, worker does NOT edit frozen lines" to "RECONCILED in-PR (D5)" pointing at the HEADER RECONCILE block. Comment hygiene only; no model change. Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: make CiJob.command faithful + explicitly non-executable (codex BLOCKING) codex BLOCKING (sha 99753a3): CiJob.command was a lossy paraphrase ("v2-compiler compile --source-root src/v4") while documented as the command line the deferred interpreter executes — fabricating process facts (INVARIANTS P1) and not faithfully reproducing the live v4 CI gate command. Fix (both options the finding allowed): (a) store the EXACT primary gate invocation verbatim from .github/workflows/ci.yml ("target/release/v2-compiler compile --source-root src/v4 --output-dir /tmp/v4-stage1 --target dag"); (b) reframe the field as NON-EXECUTABLE documentation data — there is no interpreter (process carrier extdeps/process.dag is T-4.5 scaffold) and a single String cannot carry a GHA job (the live step is a multi-line shell wrapper + a `cargo build` prerequisite). The full faithful step + process spawn stay deferred to extdeps/process.dag (T-4.5) + T-22 (TRACKED SCAFFOLD (3)), explicitly NOT fabricated into the String. Field doc + CiJob doc + gate-instance comment updated. Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: unify fixed-point vocab in body — bit-identical (property) + RoundTrips (AssertKind) cursor APPROVE_WITH_COMMENTS (non-blocking): body prose said "`BitIdentical` TestClaim" (implying a kind) in places while the TRACKED SCAFFOLD correctly ties the deferred check to std/verification.dag `kind: RoundTrips` (no `BitIdentical` AssertKind exists). One editorial pass: all BODY occurrences now use "bit-identical" for the stage1==stage2 PROPERTY and `RoundTrips` for the substrate AssertKind (Status note, WHY-PINNED-HASH note, FixptStage1Stage2 type comment; TRACKED SCAFFOLD (2) was already correct). Frozen Owns/Consumes header lines (22/26/76) preserved VERBATIM — a non-blocking hygiene nit is not the operator-tier D5 sanction required to edit frozen header lines; "BitIdentical" there is the property/anchor name, reconcilable with verification.dag's RoundTrips ("self-host bit-identity") once the body is consistent. Comment-only; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: name the fail-closed CiPipeline well-formedness boundary (node.dag Diff #3162 stance) Addresses briansrls BLOCKING (ci.dag:275): jobs/gates lists + raw Symbol edges leave missing targets / duplicate ids / needs-cycles constructible; P2/P4 need a structural OR fail-closed boundary before consumers land. Resolved by applying the canonical node.dag Diff #3162 ratification (not a coin-flip — that precedent settles the shape): ANY jobs/gates lists are valid CiPipeline DATA; missing-target/dup-id/cycle are NOT type-level illegal states and there is deliberately NO ci_pipeline_well_formed eager predicate (exactly the #3162 diff_well_formed anti-pattern). The fail-closed WELL-FORMEDNESS boundary is the deferred select_jobs consume fold (apply_diff-analogous all-or-nothing): unresolved/duplicate/cyclic => one fail-closed Diagnostic (Outcome<T>), decidable via visited-set traversal (P4). NAMED + OWNED now (select_jobs / lens/affected_set.dag T-21, TRACKED SCAFFOLD (2)); only its body deferred per scaffold discipline. Doc tightened in CiPipeline + TS(2). Comment-only; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 T-24: implement eager fail-closed ci_pipeline_well_formed boundary (still-hawk-102 adjudication) still-hawk-102 (relayed via Lane B) rejected reaffirming #3162 for CiPipeline: #3162's precondition (no intrinsic well-formedness) is FALSE here — a job/gate DAG has intrinsic, statically-decidable well-formedness (unique ids / acyclic / resolving refs), malformed independent of any consumer; deferring to select_jobs (a consumer) is ruled out by the operator's "before consumers land". Patterns don't auto-extend without the per-instance precondition. Implemented the eager boundary NOW: ci_pipeline_well_formed : CiPipeline -> Outcome<CiPipeline>, covering (1) unique job ids (node.dag all_names_distinct CHECK-enforced precedent), (2) reference resolution (every needs/gate.job resolves to a declared id), (3) acyclicity via Kahn sink-elimination bounded by count(jobs) passes expressed as a fold over the finite jobs list (A2 IMPLICIT termination, INVARIANTS P4) — never an unbounded walk. Any violation = one fail-closed Diagnostic (AmbiguousIntent, no repair-guess). Structural Map-for-ids was INFEASIBLE: v4 Map<K,V> is lookup-only (no key enumeration) so a Map jobs field can't be traversed for the required acyclicity/ref checks; jobs/gates stay List (fold-traversable) per the adjudication's "pick by feasibility" + ACCEPTABLE eager option. NOT a #3162 exception (#3162 never governed this carrier). WELL-FORMEDNESS header + TRACKED SCAFFOLD (2) rewritten (drop #3162-stance + the deferral). Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 T-20+T-24: de-prose bootstrap.dag + ci.dag in-PR (operator HOLD/audit directive) Per still-hawk-102 → Lane B directive (HOLD all PRs for operator audit; de-prose in-PR; load-bearing files keep structured header contract). Collapsed the review-cycle-accreted body modeling-notes essays to terse load-bearing comments (CODING.md "default no comments; only non-obvious WHY"): bootstrap.dag 257→173, ci.dag 508→374. Comment-only — code, types, fns, data unchanged; structural v2-compile gate GREEN (64 modules, 0 diagnostics). KEPT (mandated artifacts, not de-prosed): the immutable structured headers (Scope/Anchor/Owns/A3/Discipline/Consumes/Status/Brief); the ci.dag D5 HEADER RECONCILE block (#3216 standing rule); TRACKED SCAFFOLD owner/trigger items; the WELL-FORMEDNESS eager-boundary doc incl. the Map-infeasibility one-liner (Lane-B-mandated visible) + still-hawk-102 adjudication provenance; ledger-provenance + supersession one-liners; no-fabrication/single-authority + command-non-executable facts. REMOVED/COLLAPSED: multi-paragraph restated rationale, defensive review-cycle elaboration. RELOCATE: n/a (no in-scope target; design narrative already captured in PR comments + DECISIONS). No D2-alias prose present (verified — file is not D2-affected, no D2 reconcile). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20+T-24: STRICT de-prose bootstrap.dag + ci.dag (still-hawk-102 directive, interim until #3226) Per still-hawk-102 STRICT DE-PROSE RE-DO (supersedes prior nominal de-prose; prior attestation not accepted). A de-prosed .dag carries ONLY: file-path line; terse Scope/Owns/Consumes/Status header; optional per-carrier Anchor URL; optional one-line per-TYPE concept tag if non-obvious. Everything else removed. Comment-only — all code, types, fns, data verbatim-unchanged; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Comment-% (was → now): bootstrap.dag ~83% → 19.2% (5/26); ci.dag ~58% → 3.2% (5/156). Both < 20% hard target. PROCESS RECEIPT / removed-narrative provenance (kept here in the commit message per directive, NOT in the file): - ci.dag D5 HEADER RECONCILE (2026-05-17, #3213, D5/#3216, #3190 precedent): operator-tier BLOCKING review actions (briansrls inline C4-fabrication + single-authority-seam; openai-pro confirming) moved the body past the frozen Owns/C4 header; it was reconciled IN-PR to the single-authority project_github_actions->Workflow seam with C4 gated on the missing v4 Workflow substrate (interim hand-authored ci.yml bridge). C4 operator-ratified intent preserved; only mechanism corrected. This narrative now lives only in git history + prior PR comments, not the file. - ci_pipeline_well_formed is the eager fail-closed well-formedness boundary (still-hawk-102 adjudication 2026-05-17): #3162 does not govern CiPipeline (intrinsic statically-decidable well-formedness); structural Map-for-ids INFEASIBLE (v4 Map<K,V> is lookup-only, no key enumeration) so jobs/gates stay List + eager predicate checks unique ids (node.dag all_names_distinct precedent) + ref-resolution + acyclicity (Kahn elimination bounded by count(jobs), A2-IMPLICIT, P4-decidable). Architectural rationale belongs in DECISIONS.md (owned by operator/#3226), not this file. - No D2-alias prose present (not D2-affected, not pipeline-stage); no gated reconciliations. Branch 0 commits behind origin/main. HELD for operator audit; not merging (operator squash-merge only). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: ci_pipeline_well_formed also proves gate-id uniqueness (briansrls BLOCKING) Valid finding (ci.dag:27): CiGate.id is an addressable identity but the eager well-formedness predicate checked job-id uniqueness only, so duplicate gate ids were accepted → ambiguous downstream selection authority (INVARIANTS P2). Same intrinsic, statically-decidable, consumer-independent well-formedness class the still-hawk-102 adjudication required for jobs. Fix (code-only; strict-de-prose preserved, ci.dag 2.9% comment): added ci_gate_id_occurrences + ci_all_gate_ids_unique (mirroring the job-id check / node.dag all_names_distinct CHECK-enforced precedent) + a ci_duplicate_gate_id reason symbol, and a gate-id-uniqueness branch in ci_pipeline_well_formed (duplicate gate id ⇒ fail-closed Rejected). Structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: fix ci.dag Consumes header drift (std/* → v4.std.*) cursor APPROVE exploratory nit: terse Consumes header said `std/node, std/diagnostic` but the actual imports are `v4.std.node` / `v4.std.diagnostic`. The terse header is now the sole in-file contract under operator audit, so header precision matters. One-line accuracy fix; strict de-prose preserved; structural v2-compile gate GREEN (64 modules, 0 diagnostics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: expand bootstrap.dag four stages as v4 orchestration DATA (operator directive; resolves codex finding-1) Operator (still-hawk-102 via loyal-wren-802) adjudicated codex #3213 finding-1: bootstrap.dag DOES own/define/source/orchestrate the four stages now (supersedes the prior minimal-singleton/deferred-interpret framing). Expanded per directive: - DEFINE: each stage is a distinct record with real fields (no more empty `{}` markers). SeedToStage0/Stage0ToStage1/Stage1ToStage2 carry consumes/produces/via; FixptStage1Stage2 carries left/right/via. - SOURCE: inputs are real Symbol identities — v4_dag_source (the src/v4 .dag compiler corpus), v4_stage0/1/2_binary, v2_pipeline (the frozen seed executor), bit_identical_check. `Consumes: none` → v4.std.node. - ORCHESTRATE: BootstrapPlan record + canonical bootstrap_plan wiring the four stages with concrete consumes/produces in order, as v4 DATA. - TRIVIAL v2-DELEGATING BODIES (sanctioned): all compile stages' executor `via = v2_pipeline` initially; per-stage shift delegate-to-v2 → use-v4's-own as v4's pipeline is built (file FILLED IN, never replaced). Orchestration is v4 data from day one. Per-position type distinctness retained (seed slot must be SeedToStage0, etc.) so cross-position mis-wiring stays type-prevented. No coproducts introduced (all records) — emoji-tag directive N/A. Strict de-prose preserved: bootstrap.dag 7.1% comment (5/70), terse 4-line header only. Structural v2-compile gate GREEN (64 modules, 0 diagnostics). HELD for operator audit; in-PR expansion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 T-24: port v3 CICommand → typed v4 CiCommand carrier (still-hawk-102 fork-2; Option-1 DECISIONS row) still-hawk-102 fork-2 directive: replace ci.dag CiJob.command:String with a proper v4 typed command carrier, PORT (not import) of v3 dsl/gunbc/ci.dag CICommand. Faithful re-express (no shape fork): type CiCommand = LintCommand | TestCommand | IgnoredTestCommand { test_name: String } | ShellCommand { command: String } CiJob.command: CiCommand (was String); v2_compile_gate_job → ShellCommand { command: "<verbatim v2-compile invocation>" }. Coproduct ⇒ per modeling-discipline.md Practice 4/9 + the coproduct-emoji directive: in-file one-line tag `// 🟡 coproduct dissolution — DECISIONS.md LB-P4-3213` on `type CiCommand`; full classification ledger authored as DECISIONS.md Part-6 row LB-P4-3213 (id assigned by still-hawk-102 Option-1: worker authors provisional, operator ratifies on audit). Classification 🟡 YELLOW (scaffold): richer source nameable (the T-4.5 extdeps/process.dag typed Command{program,args,env} carrier + v3 ROADMAP-F12); ShellCommand{command:String} is the bounded interim; named trigger = T-4.5 typed Command carrier lands. 5 dissolution patterns tried, recorded in the ledger row. ci.dag strict de-prose preserved (3.3% comment, <20%). Structural v2-compile gate GREEN (64 modules, 0 diagnostics). bootstrap.dag NOT touched — codex F1/F2 reconciliation pending still-hawk-102 (orthogonal). #3213 HELD for operator audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-20: bootstrap.dag F1/F2 fixes (still-hawk-102 reconciliation; implement, not rebut) still-hawk-102 reconciled the codex CR — implement (not rebut): F1 (Practice-3 forward chain): `via: v2_pipeline` kept (sanctioned executor-is-v2-initially). `consumes` is now List<Symbol> carrying the prior stage's produced artifact so the orchestration DATA is a chain, not three independent compiles: seed consumes [v4_dag_source] produces stage0 self0 consumes [v4_dag_source, v4_stage0_binary] produces stage1 self1 consumes [v4_dag_source, v4_stage1_binary] produces stage2 fixpt left=stage1 right=stage2 via=bit_identical_check F2 (Practice-7 enumerated-copy): the three identical {consumes,produces,via} stage types (SeedToStage0/Stage0ToStage1/ Stage1ToStage2) collapsed into ONE `CompileStage { consumes, produces, via }`. FixptStage1Stage2 { left, right, via } stays its own type (not collapsed, per directive). Order/multiplicity expressed as fixed named BootstrapPlan slots (seed/self0/self1: CompileStage; fixpt: FixptStage1Stage2) — keeps the exactly-3-compiles+1-fixpt fixed shape (no over-general List reintroduced) while removing the enumerated copy. No coproducts (records only) — emoji directive vacuous. Strict de-prose preserved: bootstrap.dag 8.6% (5/58), <20%. Structural v2-compile gate GREEN (64 modules, 0 diagnostics). #3213 HELD for operator audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 T-24: export ci_pipeline as fail-closed Outcome (briansrls BLOCKING — non-bypassable boundary) Valid finding (ci.dag:54): canonical `ci_pipeline` was exported as raw CiPipeline, so consumers could read it without passing through the operator-adjudicated eager `ci_pipeline_well_formed` boundary — bypassing the P2/P3 fail-closed check. Faithful completion of the still-hawk-102-directed eager-well-formedness boundary (no shape fork, no directive conflict): the boundary now cannot be bypassed. Fix: raw construction is internal `ci_pipeline_unchecked: CiPipeline`; the exported canonical `ci_pipeline: Outcome<CiPipeline> = ci_pipeline_well_formed(p: ci_pipeline_unchecked)`. Downstream consumers must handle Produced/Rejected — the eager fail-closed boundary is now the only way to obtain the pipeline. v2 supports the fn-application data initializer (verified). Strict de-prose preserved (ci.dag still <20%); structural v2-compile gate GREEN (64 modules, 0 diagnostics). Orthogonal to the bootstrap P2/F1/F2 trilemma (routed, pending still-hawk-102; bootstrap.dag NOT touched). #3213 HELD for audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 T-20: bootstrap (b) expose-only-checked — drop consumable bootstrap_plan_unchecked (still-hawk-102 GO) still-hawk-102 RULING on the openai-pro (heaviest-weight) REQUEST_CHANGES re-litigating the adjudicated bootstrap-P2: implement (b). (a) structural per-stage nominal identities FORBIDDEN — do not revert F2 (codex-F2 / Practice-7 stays closed). (b): removed the named consumable `data bootstrap_plan_unchecked: BootstrapPlan`; the BootstrapPlan{...} literal is now inlined as the sole argument to bootstrap_plan_well_formed(p: BootstrapPlan {...}). The ONLY named export consumers can bind is now `bootstrap_plan: Outcome<BootstrapPlan>` (the checked carrier) — the consumable-boundary leak (unchecked raw record had a name to grab) is closed. Mirrors the ci_pipeline expose-only-checked precedent (Lane-B-PASSED). F1 (forward consumes chain) + F2 (single CompileStage) intact; no codex-F2 re-trigger; no shape fork. v2-compiler parses the inlined nested record literal (verified, not shipped blind); structural v2-compile gate GREEN (64 modules, 0 diagnostics). Strict de-prose intact (bootstrap.dag 4.5%, <20%). #3213 HELD for operator re-audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 #3213 IB-3: Practice-10 List-op dissolution pass (operator merge gate) std/collection.dag (T-3) declares zero derived List ops -> zero RED (nothing to dissolve into in-PR); every hand-rolled generic List primitive marked YELLOW gated feature: (owner T-3 std/collection.dag, named missing op + dissolve-on-arrival obligation). Kahn composition classified GREEN terminal domain-logic (peer of the well-formed predicates). One terse in-file tag per file (LB-P4-3213 precedent); full LB-P10-3213 ledger in DECISIONS.md Part 7. #3244 disposition vocabulary. Structural v2-compile gate: indexed 67 modules, 0 diagnostics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: ci.dag expose-only-checked — drop consumable ci_pipeline_unchecked/v2_compile_gate_job (operator REQUEST_CHANGES) Operator (briansrls) BLOCKING: top-level raw ci_pipeline_unchecked: CiPipeline was a second authority beside checked ci_pipeline, bypassable by downstream consumers (P2 single-authority / P3 fail-closed). Fix mirrors the operator-accepted bootstrap (b) expose-only-checked shape: inline the CiPipeline literal (CiJob/CiGate inlined) as the sole arg to ci_pipeline_well_formed; remove the named ci_pipeline_unchecked and v2_compile_gate_job composites so the only consumable pipeline authority is data ci_pipeline: Outcome<CiPipeline>. Header Owns updated. Structural v2-compile gate: indexed 68 modules, 0 diagnostics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: ci.dag rename ci_kahn_fixpoint fold param counter->job (CODING.md names-describe-the-mapping) Recurring multi-reviewer readability observation (cursor 13938 exploratory): the fold's 2nd callback parameter is the folded `jobs` element, not a counter; `counter` misdescribed the mapping. Renamed to `job` per CODING.md "names describe the mapping". Semantically inert (param remains deliberately unused — the fold is the bounded-iteration driver per LB-P10-3213-KAHN); structural v2-compile gate: indexed 68 modules, 0 diagnostics. Resolves the observation permanently rather than restating "intentional". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: rewrite LB-P4-3213 ledger to #3244 precision (consumer-gate, landed target) CORE ruling (still-hawk-102, Option-1 + #3244): reframe LB-P4-3213 as a valid plan-bound 🟡 with gate kind = consumer: (first meaning-consumer of typed-command shape, deferred-by-brief, gate CLOSED). process.dag::Command is the LANDED migration target (#3209), not the meaning-consumer — future consumer consumes typed Command directly; #3213 does NO migration / NO local CiCommand parse. Anti-#3250: NOT "no change needed". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: bootstrap.dag — split stage compiler-of-record from executor (self-hosting identity) codex BLOCKING + 2 BLOCKING-inline (P1/P2): every CompileStage.via was v2_pipeline, conflating the orchestration executor with the stage compiler-of-record and making the fixpt (stage1==stage2) check vacuous. Fix grounded in load-bearing docs: - STRUCTURE.md:404-405 "Seed used once": v2 produces v4-stage0, then v4 compiles itself; v2 is never in the loop again. - SELF_HOSTING.md §meta-circular: stage0 compiles source->stage1, stage1 compiles source->stage2, assert byte-identical. via -> compiled_by (CODING.md names-describe-the-mapping): seed compiled_by v2_pipeline, self0 by v4_stage0_binary, self1 by v4_stage1_binary. No executor bridge field — STRUCTURE.md is explicit that v2 is seed-once, so no "v2 executes every stage" fact exists; the brief's "v2 is the initial executor" framing contradicted the doc and the doc wins. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: ci.dag consumes bootstrap seed authority — single-authority fix (P2/Practice 5) openai-pro 13971 (BLOCKING, at HEAD 52c207b): ci.dag:52 restated the bootstrap seed action as a raw ShellCommand argv string, a parallel authority for the seed→stage chain that bootstrap.dag BootstrapPlan.seed now canonically owns — drift-prone, violates INVARIANTS P2 single- authority / modeling-discipline Practice 5; the duplication was also untracked debt (review §6). Fix (in-PR, structural model only — not the brief-deferred ci.yml projection / T-22 lane): add typed CiCommand variant BootstrapStageCompile{produces: Symbol}; the v2_compile_src_v4 job now references v4_stage0_binary imported from v4.workflow.bootstrap. A real machine-readable cross-module edge to the bootstrap authority — the raw argv is removed entirely; BootstrapPlan.seed is the sole source of truth. No import cycle (bootstrap does not import ci). Distinct from / orthogonal to CORE-adjudicated LB-P4-3213: that 🟡 is the ShellCommand{String} raw-argv command-SHAPE decomposition, deferred to the consumer lane. This is single-AUTHORITY wiring (an invariant), resolved now. LB-P4-3213 ledger updated to record the resolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan * v4 #3213: Practice-9 de-prose — in-file rationale → ≤1-line ledger pointers cursor 13986 (NON-BLOCKING, APPROVE_WITH_COMMENTS): ci.dag mid-carrier comment recorded single-authority/P2 rationale as in-file prose (Practice 9 — rationale belongs in DECISIONS.md, already covered by LB-P4-3213). Replace with a one-line `// 🟢 single-authority — DECISIONS.md LB-P4-3213` pointer; strip the same-shape parenthetical from ci.dag Consumes line and tighten bootstrap.dag compiled_by tag for consistency. No semantic change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: Practice-9 — drop bootstrap.dag compiled_by field-prose cursor 13998 (APPROVE_WITH_COMMENTS): the `// stage compiler-of-record` field comment is rationale-on-carrier, not an allowed comment class. The field name + header Scope line already convey the self-hosting identity; structure speaks for itself. No DECISIONS pointer needed (no dedicated ledger entry; header already documents seed-once semantics). No semantic change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: structurally enforce BootstrapStageCompile single-authority at the CI boundary openai-pro 14006 (BLOCKING, manual re-review @ 5d4468d): BootstrapStageCompile{produces:Symbol} took an unconstrained Symbol and ci_pipeline_well_formed never validated it against the canonical BootstrapPlan outputs — the single-authority seam the ledger claims as resolved was prose/convention, not structural enforcement (INVARIANTS P2 / modeling-discipline Practice 5/6). Fix (structural model, in-scope — not the brief-deferred T-22 executable lane): - bootstrap.dag owns bootstrap_stage_output(s: Symbol) -> Bool — the single authority on the canonical stage-output set {v4_stage0_binary, v4_stage1_binary, v4_stage2_binary}. - ci.dag imports it; ci_pipeline_well_formed now consumes the bootstrap authority via ci_all_commands_authority_ok and fail-closed rejects any BootstrapStageCompile.produces outside that set (ci_bootstrap_authority_violation). A dangling payload cannot reach Produced — the invariant is enforced at the substrate boundary, not asserted in prose. - LB-P4-3213 ledger updated: single-authority is now boundary-ENFORCED, not prose. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: ADDRESSED-BY-CONSTRUCTION + plan-bound 🟡 to T-22 (CORE horn (i)) still-hawk-102 ruling (2026-05-18): the BootstrapStageCompile single- authority seam is addressed-by-construction (pure structural predicate; out-of-set produces cannot satisfy the gate — modeled Rejected Outcome, no imperative side-channel; verified in code @6353d695e). Horn (ii) in-PR executable harness REJECTED (T-22-in-#3213 = brief violation). Records the deferred executable demonstration as an explicit plan-bound 🟡 with bilateral binding: - DECISIONS.md LB-T22-3213: arrival (T-22 TestClaim runner) + follow-up (negative TestClaims for the bootstrap-stage rejection family) that dissolves the 🟡. - TASKS.md T-22 scope: same obligation, cross-referencing LB-T22-3213 (neither side vague). - ci.dag in-file one-line tag → LB-T22-3213. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: Practice-9 — single coproduct tag on CiCommand (drop variant-level 🟢) cursor 14020 (APPROVE_WITH_COMMENTS): CiCommand carried two emoji dissolution lines (coproduct-level 🟡 + variant-level 🟢), reading as conflicting dispositions on one type. Rubric wants one required 🟢/🟡/🔴 tag per coproduct; the LB-P4-3213 ledger already carries the single-authority/command-shape nuance. Drop the redundant variant-level 🟢 line; the coproduct-level 🟡 tag + DECISIONS.md ledger stand. No semantic change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: CI bootstrap-authority consumes bootstrap_plan Outcome, fail-closed (P2/P3) Operator BLOCKING inline (#3213 ci.dag:168): bootstrap_stage_output checked static stage-symbol membership {v4_stage0_binary,1,2} instead of consuming bootstrap_plan: Outcome<BootstrapPlan> — so CiPipeline could be Produced even when the canonical bootstrap plan is Rejected, bypassing the fail-closed bootstrap authority (INVARIANTS P2 single-authority / P3 fail-closed). Fix: bootstrap_stage_output now takes Outcome<BootstrapPlan>, matches it — Rejected ⇒ false (fail-closed: CI cannot pass while bootstrap is Rejected), Produced{value: bp} ⇒ produces ∈ {bp.seed/self0/self1 .produces} (validated-plan actual outputs, not a static set). ci.dag imports bootstrap_plan and threads it through ci_command_authority_ok → ci_pipeline_well_formed. The validated bootstrap_plan is now the sole authority. LB-P4-3213 ledger updated (P2/P3, plan-Outcome consumed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: add mandatory // Ledger: pointer line to load-bearing workflow headers CORE ruling (still-hawk-102 via Lane B): the de-prose-vs-rail fork was FALSE — strict de-prose stands AND one mandatory `// Ledger:` pointer line per load-bearing file (pointer class, not prose). Adds the CORE-specified line after Status: in bootstrap.dag + ci.dag. No body churn; consistent with strict-de-prose (concrete ref pointer, ≤1 line). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: CORE Option B — rescind // Ledger: line, keystone wins (registry doc→files) CORE ruling (still-hawk-102) on the openai-pro 14070 RC vs the modeling-discipline.md:503-531 keystone contradiction: the // Ledger: mandate is RESCINDED — strict de-prose keystone wins (header stays exactly four lines; no see-docs/X pointer in .dag). - bootstrap.dag / ci.dag: remove the // Ledger: line (-1 each). - Registry moves doc→files (Practice 5, top-down): design-pure-bootstrap-zero.md names the two load-bearing workflow files + A3/PROOF-1/STOP-rail + C4; INVARIANTS.md + src/v3/SELF_HOSTING.md add short Practice-5 registry cross-refs. Authority flows doc→files, not per-file upward pointers. Replays swift-ram-178 a94a312 verbatim onto the #3213 branch. Clears openai-pro 14070; consistent with the keystone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v4 #3213: reconcile to authoritative trimmed spec — drop INVARIANTS.md registry para still-hawk TRIM relay (post-a94a3123f) set the authoritative one-commit spec = NO INVARIANTS.md edit: registry lives only in docs/design-pure-bootstrap-zero.md + src/v3/SELF_HOSTING.md + the .dag // Ledger: strips. 9fda2f0 over-included the INVARIANTS.md para (replayed from the pre-trim a94a312). Drop it to conform; the two authoritative registry homes + .dag strips stand unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… spec) Frames the substrate's read/edit surface for arbitrary code at the Node level — not the file level. Files are a delivery / persistence mechanism modeled via extdeps/file_system.dag; the language doesn't couple to them. Reads target Nodes (and scopes within Nodes); writes are structural Edits to Nodes; Node-to-File binding is its own concern, modeled alongside Node, not inside it. Operator-stated motivation (2026-05-19): the mechanical part of shifting bits isn't the hard part — the INTERFACE is. This doc captures the design intent + worked examples + open interface questions, especially for LLM/agent consumers. Doc structure: - §0-1: framing — why node-centric, not file-centric (3 reasons: files decoupled from concepts; edits should be structural; agent reasoning is at concept level) - §2: read interface — apply_lens(lens, scope, mode) per QRY-1 ratification (2026-05-15); no separate query subsystem; lens catalog + composition - §3: write interface — Path/Edit/Diff per #3162 ratification; apply_diff fold semantics (all-or-nothing fail-closed) - §4: read → edit pipeline — six-step closed loop (Read → Diagnose → Propose → Gate → Apply → Re-emit). Files only re-enter at Re-emit; they're a downstream effect of substrate state. - §5: three worked examples — (A) bare-alias refactor to canonical-B (same shape as #3338); (B) rename a concept across the corpus via CanonicalConcept registry cascade; (C) TestClaim breakage diagnosis + fix - §6: six open interface questions — higher-order Edit combinators, composition under overlap, intent-shaped declarations (generalized Track 2), LLM-targeted diagnostic shape, workflow-as-data for the agent loop, structural provenance traces - §7-8: scope clarifications + status Status: design spec; mechanical primitives exist, T-23 realizes them; the six open interface questions are where the substantive interface design work lives. No implementation prescribed. This is operator-requested framing work, not action work. Each open question becomes its own follow-up doc / PR when picked up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* design-dissolution-lens: propose L1.7–L1.12 from 2026-05-18 ingest Adds six proposed Layer-1 lenses derived from the 2026-05-18 review ingest against `main@e7b8a8d` (corroborated against worktree HEAD). Each section follows the existing L1.x format (signature / decidability / verdict / escape / kills) and includes concrete code-level match cases + clean-shape examples, so the structural signature is reviewable without chasing repo paths. - L1.7 Off-substrate-fact — prose-asserted facts (F3 lattice, F4 width, F11 opacity). Generalizes the standing "machine-readable inhabitance" ruling. - L1.8 Wrong-home — orphan operations (F5 `nat_compare` in float.dag). Mechanizes MODELING M9. - L1.9 Vacuous-arm — exhaustive-but-empty match (F1 `ComputationNode { behavior: _ } => true`). - L1.10 String-escape-hatch — typed-model bypass via String (F6 `ShellCommand { command: String }` vs typed `process.Command`). Generalizes L1.6. - L1.11 Plausible-fallback — fabricated-sibling fallthrough (F10 `DELETE None => CreateEffect`). - L1.12 Parallel-authority — unmarked duplicate concept homes (F9 `dsl/std` vs `src/v4/std`; D2-resolver provisional + planned-absent). Each carries `Status: proposed` in the section header. Slipped-by ledger (§8) gains corresponding rows pinned to current main file locations so the evidence is grep-anchored per §3 methodology. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.12 F9 snippet: show existing classification tags, sharpen authority gap cursor/composer-2 review noted that the F9 "Concrete match" block implied both `dsl/std/types.dag` and `src/v4/std/logic.dag` were bare, when both files actually carry annotations above their `type Bool` line (legacy-scanner anchor prose in dsl/std/types.dag:163-172; 🟢 coproduct-dissolution classification tag at src/v4/std/logic.dag:13). The lens's case is sharper, not weaker, once the existing tags are visible: they classify the finding shape (dissolution status, scanner anchor) but neither *designates authority* between the two parallel declarations. L1.12 specifically requires a designator that picks a canonical winner, which is the gap classification tags don't fill. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * L1.7 / L1.8 / L1.12: tighten hard-gate semantics per codex review Addresses three BLOCKING findings on the L1.7–L1.12 proposal: L1.7 — width discharge must be recursive. The previous signature/clean shape allowed a `Word64 { bytes: List<Byte> where len(_) == 8 }` that bottomed out at an unconstrained `Byte`, so an arbitrary-bit-count `Byte` still inhabited a "well-formed" `Word64`. Signature now requires a recursively-discharged refinement chain down to a fixed-cardinality leaf or primitive bit; clean-shape example shows the full Word64 → Byte → Bit chain and structurally distinct Float32/Float64 exponent/significand widths instead of a shared `FloatBody`. L1.8 — primary-concept selector replaces the argument-files heuristic. Previous signature ("every argument's type lives in file X") missed witness-target homing (a `meet` field of `Lattice<T>` belongs with T, not with whichever file declared its argument types). New four-rule structural cascade in priority order: (1) declared witness target → algebra's type parameter is the home; (2) same-type closure (`fn(T,T)→T` etc.) → T is the home; (3) upstream argument+return convergence on file X → X is the home; (4) no single owner → cross-cutting, lens does not fire. L1.12 — escape valve must be structural, not prose. The previous "// Authority: canonical | historical" comment markers were prose- as-authority — exactly the shape L1.7 exists to kill. The lens is now self-consistent: only structural shapes discharge it — alias/import identity from historical to canonical, a `data ... : HistoricalDeclaration` row in a retirement ledger read as data, or deletion+migration in the same change. Comment markers explicitly do not satisfy the escape, by construction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.9 / L1.10 / L1.12: remove naming heuristics; substrate-declared facts only Addresses three BLOCKING findings from codex review on cfbc247: L1.9 — replace function-name suffix vocabulary with intra-match asymmetry. The previous signature gated on `*_well_formed` / `*_valid` suffixes — naming as a structural fact, which violates P1 ("heuristics are never structurally necessary"). New signature is purely structural: a single match where ≥1 arm has a trivial-literal RHS AND ≥1 sibling arm does non-trivial structural work. The discipline-role is inferred from the fact that the author already wrote real work for some variants, which makes the trivial siblings a vacuum. The F1 node_locally_well_formed case still fires (TypeNode arm calls edges_conform, ComputationNode arm returns true). L1.10 — replace hardcoded `command`→Command / `path`→Path / `url`→Url field-name table with a substrate-declared canonical-carrier registry. A typed carrier declares `data X: CanonicalCarrier<X> = { supersedes_string: { in_role: <role-tag> } }`; the lens reads the registry. Adding a new typed carrier is now a `data` row in `extdeps/`, not an edit to the lens definition. The lens carries no domain names. L1.12 — split planned-absent-import out of the duplicate-authority lens. They are different failure shapes: duplicate `type T` in two files is a duplicate-authority finding; a dangling import path is an unresolved-reference / fail-closed P3 finding. Collapsing them under one verdict reports the wrong root cause. L1.12 narrows to duplicate-declaration; planned-absent moves to an L0.8-extended row in the slipped-by ledger. The D2-resolver concrete-match block is retitled as a cross-reference note explaining why it does *not* collapse into L1.12. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * L1.10 / L1.12: close opt-in bypass, broaden type-decl signature codex review on 3fb3e4d raised two valid findings: L1.10 — the role-tag refinement created an opt-in opportunity for authors to bypass the typed-carrier rule by omitting the tag. The escape "no role-tag refinement, passes" was convention-level enforcement, not API-level. New signature drops the role-tag mechanism entirely. The CanonicalCarrier registry declares a `supersedes_string_at_field_named` set (substrate data); the lens fires on any String field whose name appears in any in-scope registry entry, unconditionally. The author cannot bypass by omitting an annotation because there is no annotation — the trigger is the field name they chose plus the registry-declared coverage. Legitimate raw-string exemptions move to structural Exemption rows in the same registry, read as data. L1.12 — the prior signature said "type T = ..." literally, which only matches the alias/sum form. The slipped-by ledger row claims coverage of duplicate machine-word homes, but `type Word64 { bytes: List<Byte> }` is record form and would have escaped the literal signature. Broadened to "any `type T` declaration form" — sum/alias, record, unit, generic — with explicit enumeration of the covered forms so the signature unambiguously matches the cases in the section's own examples and ledger. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * L1.1–L1.6: add Concrete match + Clean shape code examples The original L1.1–L1.6 sections describe each lens by signature / decidability / verdict / escape / kills, but did not show what the matching code or the discharging code actually look like. Adds the same "Concrete match" + "Clean shape" example blocks the proposed L1.7–L1.12 sections use, so each lens is concretely readable without chasing the referenced PRs. - L1.1: basic discriminant shape (`nat_is_zero`) + the laundered constant-algebra fold (`free_monoid_is_empty`-via-fold). - L1.2: (a) struct-of-functions (`ListMap<A,B>` wrapper) and (b) N near-identical single-field structs (`{ spelling: String }` ×N). - L1.3: declared-but-never-inhabited type (`ParseError` with no constructor, no `data`, no alias, no field). - L1.4: `Outcome<T>` clone (`NormalizeChildrenResult`), with the three-variant `Cached | Produced | Rejected` shape as the escape. - L1.5: clean recursion mirroring data shape (`ci_member` over List) and the short-circuit `match acc { Rejected => propagate; Ok => continue }` ladder (resolve/normalize walkers). - L1.6: type-construction template tables (`list_template: "Vec<{0}>"`) vs. structural target-type modeling. No signature, verdict, or escape semantics changed; this commit only adds illustrative code blocks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * A0 umbrella + cross-cutting themes + L1.6→L1.10 merge Implements the consolidation feedback as a middle path: tightens the conceptual scaffolding without dismantling the lens catalog. - §1: introduces A0 ("every semantic fact must have exactly one structural witness") as the umbrella invariant, with A1 retained underneath as the operation-specific specialization. Explicitly framed as operationalizing modeling-discipline.md Practice 10, not as a parallel rulebook, to avoid the L1.12-class parallel-authority hazard of duplicating Practice 10's principles here. - §5.0 (new): adds the three-levels framing (Invariant / Theme / Lens), the lens → theme(s) catalog (derive / witness / canonical-home / fail-closed), and the explicit disclaimer "themes are explanatory tags only — they do not define CI gates, test-corpus boundaries, or implementation passes; the mechanically enforced unit remains the L1.x lens signature." Per the §3 methodology, each lens's signature must be the smallest structural pattern that catches its finding's class with zero false positives, so theme-sharing alone does not collapse machinery. - L1.6 → L1.10 merge: the only mechanical merge in this rev, because the prior doc already stated that L1.10 generalizes L1.6. L1.10 is renamed "Textual-bypass lens" with two sub-signatures: L1.10.a TemplateHole — registry-free, catches `{0}`/`{1}` positional-placeholder string literals used as emitters L1.10.b CanonicalCarrier — substrate-declared registry, catches String fields whose name appears in a CanonicalCarrier coverage set L1.6 section becomes a one-paragraph pointer to L1.10.a, preserving anchor compatibility. The slipped-by ledger's F6 row is repointed to L1.10.b and a new F8 row is added for L1.10.a. L1.2/L1.3/L1.4, L1.8/L1.12, and L1.9/L1.11 are intentionally not merged — their detection machines are mechanically distinct (different signatures, decidability arguments, escape valves) and the operator TDD-pairs directive requires distinct test corpora per lens. They share themes in the §5.0 catalog without sharing implementation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * A0 tightening: witness-path / lens-family / Practice-10 ratification Five sharpening edits from operator review of the A0/themes pass: 1. A0 rephrased: "exactly one structural witness" → "exactly one canonical structural witness *path*". Alias / re-export edges, retirement-ledger rows, and derived operations reading the same witness all point at one authority; they are the path, not a multiplicity that violates A0. 2. §2 "one substrate gap" claim updated. The original sentence was true for the L1.1/L1.5 seed findings but too narrow for A0's broader territory. Now distinguishes the seed gap (no derived discriminant/catamorphism → workers hand-roll them) from the general gap (missing witness table / authority map / refinement edge / diagnostic carrier → workers encode locally in prose / names / strings / duplicate homes / plausible defaults). 3. L1.10 explicitly renamed "Textual-bypass lens family" with an "Exception to §5.0" note: L1.10.a TemplateHole and L1.10.b CanonicalCarrier are the mechanical units, sharing a finding family and reporting label but keeping separate signatures, decidability arguments, escapes, and test corpora. Resolves the tension between §5.0 ("the mechanically enforced unit is the L1.x signature") and L1.10's two-detector structure. 4. L1.6 stub retitled "Deprecated alias — see L1.10.a `TemplateHole`" so old test names and slipped-by references remain traceable. 5. §8 trailing prose fixed: "all four are burn-down substrate PRs" was true when the ledger had four rows; now it has the four seed rows plus the ingest extension. Reframed as "Pattern from the seed PR rows" with an explicit note that the ingest rows extend the ledger to A0's broader territory. 6. A0/A1 ratification sentence made authority-chain explicit: "Once ratified into Practice 10, A0/A1 become citable hard rules; this doc remains the enforcement mechanism." Avoids the rulebook-ish phrasing that suggested A0/A1 were independently citable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * §10 Dependency model — lenses are pipeline stages, not infrastructure Adds a new §10 (renumbering audit to §11) answering the "how does this run / is it parallelizable / how much work" questions operationally. The core framing: there is no "lens framework" separate from the compiler pipeline. Lenses are .dag stages that declare consumes: edges against the existing parse/resolve/infer producers, and the compiler's stage-ordering schedules them automatically. - §10.1: shared-indices taxonomy — maps each shared structural fact (AST, symbol resolution, variant lists, inhabitance edges, witness registries, refinement clauses, import graph, fail-closed return- type carriers) to the existing pipeline stage that produces it and the lenses that consume it. Most of what lenses need is already computed; lenses just query. - §10.2: three small derived stages cover what the existing pipeline doesn't yet expose — match_arm_shape (reusable by L1.1, L1.9, L1.11, L0.7, L0.13), closed_vocab_scan (L1.7), concept_home (L1.8). Each is a single deterministic fold; reusable across multiple lenses by design. - §10.3: a lens is just another .dag stage with declared dependencies. Adding a lens = land a stage; the existing compiler stage-ordering handles scheduling. No new framework. - §10.4: per-file and per-lens parallelism fall out of the dependency graph automatically; affected_set integration scales CI cost with PR size, not corpus size. - §10.5: summary of operational properties — one dependency model across pipeline + lenses, lens addition = stage land, index addition = small derivation stage shared by all lenses that need it, self-application clean (the compiler enforces the discipline it follows). This is the L1.12-class self-consistency check: a separate "lens framework" with its own dependency model would itself be parallel authority, which the lens suite exists to kill. The dependency-model section makes explicit that the lens framework reuses the pipeline's existing modeling — one dependency system for everything. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-dissolution-lens: stabilize #3313 — L1.11/L1.12 fixes + canonical L1.x keys Bundles three changes operator-routed via witty-cat-59 as the #3313 stabilization trigger: 1. **L1.11 plausible-fallback** — drop the "return type is not Outcome<_>" carve-out that was a false negative on `fn(...) -> Outcome<T>; None => Produced { value: ... }`. Replaces with a structural FailClosedDiagnostic registry declaring Outcome::Rejected as the registered fail-closed constructor. The lens fires on RHS Ctors that are not registered as fail-closed, covering both the F10 bare-return case AND the Outcome-wrapped fabricated-success case the prior signature missed. or_default-style total-by-design helpers escape via a structural PlausibleFallbackExemption row, same shape as L1.8 WrongHomeExemption and L1.9 VacuousArmExemption — no comment anchors. 2. **L1.12 parallel-authority** — reframe so lexical-name collision is the *trigger* (not the conclusion), with four resolution paths the lens checks against the substrate: (1) same-concept-with-alias (CanonicalConcept row + alias edge) → passes (2) same-concept-without-alias (CanonicalConcept row but no alias) → fires (the original duplicate-authority case) (3) distinct-concepts (ConceptDisambiguation row marks them as legitimately different) → passes (4) silence (no row in either registry) → **fires as unresolved-duplicate** The prior formulation only fired on (2) and missed (4) — the F9 motivating case where Bool was declared in two files with no CanonicalConcept row anywhere. The substrate must take a position on every cross-file lexical collision; silence fails closed. 3. **§5.1 Canonical L1.x acceptance-key names** — new subsection enumerating the stable canonical key names downstream consumers (e.g. coverage.dag's dissolution_l1_* rows) must use. The lens suite is the single authority; downstream key sets are projections. Includes explicit migration notes: - `dissolution_l1_6_emit_template` → retired, no L1.6 key - `dissolution_l1_10_string_escape_hatch` → split into `dissolution_l1_10_a_template_hole` AND `dissolution_l1_10_b_canonical_carrier` This is the #3313-stabilization step in #3322's closeout register (item 7). On land: - warm-koi-304's #3318 (held-at-track-not-finalize) can rebase against the stable §5.1 enumeration - batch-(d) remains held until A1 invariant placement PR lands too Routed via witty-cat-59 (program-coordination); follow-up PR owned by sunny-wolf-435 as #3313 author per #3322 closeout-register row 7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.12 wording: "three resolutions" → "four outcomes (three passing + silence)" cursor/composer-2 review noted editorial inconsistency: the text said "exactly one of three resolutions" but the list enumerated 1-4 with silence as case (4). Corrected to "one of four outcomes — three passing resolutions plus a fail-closed silence case" so the prose matches the structural enumeration that follows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.12: close the decision table — five outcomes, all in-table Reviewer (briansrls 2026-05-18T23:26Z) flagged that the prior wording said "three passing resolutions" but the enumerated 1-4 list had only TWO passing (alias, ConceptDisambiguation) and TWO firing (same-concept-without-alias, silence). The HistoricalDeclaration retirement-ledger and deletion/migration paths from the Escape section were "outside the stated decision table" — a P2 decidable-single- authority violation. Fix: restructure the enumeration to cover ALL mechanically-distinct outcomes inline, so the decision table is closed: (1) Same-concept-with-alias → passes (2) Same-concept-with-retirement-record → passes (new: was in Escape) (3) Distinct concepts (ConceptDisambiguation) → passes (4) Same-concept-without-alias-or-retirement → fires (original duplicate-authority case) (5) Silence → fires (unresolved-duplicate) Three passing + two firing = the arithmetic now matches. Deletion / migration is explicitly noted as "not a fifth resolution" — it removes the trigger condition entirely (no lexical collision), so the lens never engages, which is mechanically distinct from a resolution. The Escape section is collapsed to a pointer at outcomes (1)/(2)/(3) to avoid duplicating the decision-table content. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.12 Decidable bullet: include HistoricalDeclaration registry Closes the residual gap on the wrap BLOCKING review: outcome (2) "Same-concept-with-retirement-record" consults a HistoricalDeclaration registry row, but the prior Decidable bullet listed only CanonicalConcept + structural-alias + ConceptDisambiguation. Now every registry the 5-outcome decision table consults is named in the decidability statement explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * L1.11 Verdict: per-case fix guidance (bare-return vs Outcome-wrapped) cursor/composer-2 review caught a contradictory-guidance bug: the new L1.11 bullets explicitly include the Outcome-wrapped case (fn(...) -> Outcome<T>; None => Produced { value: ... }) as firing, but the Verdict still said "lift the return type to Outcome<T> and return Rejected" — which doesn't address the case that's already Outcome-wrapped. Split the fix into two case-specific guidances: - Bare-return case: lift return type to Outcome<T>, return Rejected. - Outcome-wrapped case: replace Produced ctor with Rejected { diagnostic: DerivationUnknown } on the missing-info arm. Same underlying fix shape (escalate missing info through the registered fail-closed-diagnostic variant) — just two distinct starting points depending on which form of fabricated-success the lens caught. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * L1.12: restore concept-level detection via two-trigger union (lexical OR CanonicalConcept co-membership) codex review (REQUEST_CHANGES) caught a real semantic weakening in the prior "lexical collision is the trigger" rewrite: two parallel homes for ONE concept with DIFFERENT names would slip past the lens entirely, contradicting P2 / Practice 5's concept-level single-authority demand. Fix: restore concept-level detection by adding Trigger B (concept- graph) alongside the existing Trigger A (lexical). The lens fires on parallel authority detectable in EITHER way: - **Trigger A (lexical):** cross-file `type T` declarations sharing a simple name. (Existing; catches the F9 motivating case.) - **Trigger B (concept-graph):** two `type T1` / `type T2` declarations in different files that are co-members of a `CanonicalConcept` row, regardless of whether their lexical names match. (NEW; catches the same-concept-different-name case the prior rewrite missed.) Either trigger enters the same 5-outcome resolution table. Per-outcome under Trigger B: - (1) alias / (2) retirement-record / (4) no-resolution apply cleanly to both triggers - (3) ConceptDisambiguation under Trigger B would CONTRADICT the CanonicalConcept co-membership row — registry-inconsistency, caught by L0-class checks, not L1.12 - (5) silence is NOT reachable under Trigger B (the trigger IS a registry row's presence); only reachable under Trigger A Also added an explicit Decidability Boundary note: the lens cannot catch the case where two homes use different names AND no CanonicalConcept row registers them as the same concept. That's a P2 violation but mechanically undetectable from parsed substrate alone — closing it requires either operator judgment or a future structural-similarity-fold primitive. Per §3 methodology, lens signatures catch their class with zero false positives; Trigger B's CanonicalConcept-driven gate is the structural surface decidable today. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * docs(design): read/edit pipeline — node-centric agent surface (design spec) Frames the substrate's read/edit surface for arbitrary code at the Node level — not the file level. Files are a delivery / persistence mechanism modeled via extdeps/file_system.dag; the language doesn't couple to them. Reads target Nodes (and scopes within Nodes); writes are structural Edits to Nodes; Node-to-File binding is its own concern, modeled alongside Node, not inside it. Operator-stated motivation (2026-05-19): the mechanical part of shifting bits isn't the hard part — the INTERFACE is. This doc captures the design intent + worked examples + open interface questions, especially for LLM/agent consumers. Doc structure: - §0-1: framing — why node-centric, not file-centric (3 reasons: files decoupled from concepts; edits should be structural; agent reasoning is at concept level) - §2: read interface — apply_lens(lens, scope, mode) per QRY-1 ratification (2026-05-15); no separate query subsystem; lens catalog + composition - §3: write interface — Path/Edit/Diff per #3162 ratification; apply_diff fold semantics (all-or-nothing fail-closed) - §4: read → edit pipeline — six-step closed loop (Read → Diagnose → Propose → Gate → Apply → Re-emit). Files only re-enter at Re-emit; they're a downstream effect of substrate state. - §5: three worked examples — (A) bare-alias refactor to canonical-B (same shape as #3338); (B) rename a concept across the corpus via CanonicalConcept registry cascade; (C) TestClaim breakage diagnosis + fix - §6: six open interface questions — higher-order Edit combinators, composition under overlap, intent-shaped declarations (generalized Track 2), LLM-targeted diagnostic shape, workflow-as-data for the agent loop, structural provenance traces - §7-8: scope clarifications + status Status: design spec; mechanical primitives exist, T-23 realizes them; the six open interface questions are where the substantive interface design work lives. No implementation prescribed. This is operator-requested framing work, not action work. Each open question becomes its own follow-up doc / PR when picked up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * WIP: PM * design-read-edit-pipeline: fix two P2 / THESIS-narrowing findings from openai-pro RC openai-pro (gpt-5-5-pro) review on f15b2b0 flagged two valid issues: **Finding 1: affected_set as implicit third scope (P2 violation).** §2 said "frontier is itself a scope" and §5/§6 examples passed `affected_set(dag, diff)` as `NodeScope(affected)`, but the ratified SectionRef is two-branch only (DeclarationScope | NodeScope). Treating `Witness<ReExecFrontier>` as a NodeScope-compatible value is an implicit coercion the typed surface doesn't model — violates P2 illegal-states-unrepresentable. Fix: clarify §2 that the frontier is a SET of declaration/node refs the caller folds over by re-applying the lens at each member's existing DeclarationScope/NodeScope. Rewrite all five affected worked-example sites (Examples A + 6.3 + 6.6) to fold over `affected.frontier.for_each(ref => apply_lens(_, ref, Enforce))` instead of passing `NodeScope(affected)`. SectionRef stays two-branch; gating over the affected frontier is composition, not a new scope shape. **Finding 2: workflow/agent_loop.dag conflicts with THESIS narrowing (LOCKED DESIGN DECISIONS).** §7.5 proposed extending self-application to `workflow/agent_loop.dag`, but THESIS retracted meta-process / work-direction modeling on 2026-05-15; self-application is narrowed to gunbc's own build/CI pipeline (workflow/{bootstrap, ci} only). The reviewer correctly noted my open question would reopen exactly the surface THESIS removed. Fix: reframe the open question per the reviewer's "out-of-scope / user-program workflow" option. The agent loop is a USER PROGRAM composing substrate primitives (apply_lens, apply_diff, affected_set, emit) — not an extension of gunbc's workflow/ surface. Renamed §7.5 from "Workflow-as-data for the agent loop" to "Agent-loop composition at the user-program level" and explicitly stated `workflow/agent_loop.dag` is not the right place; THESIS narrowing stands. The substantive open question (what user-program-side carriers ship with gunbc as conveniences vs are user-program-authored) is preserved without reopening the locked surface. §6.6 (CLI-driven concept declaration hero case) cross-reference also updated to call it out as a user-program composing primitives, not gunbc self-application. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: honest accounting of Node→File binding gap openai-pro BLOCKING inline at line 33 (sha c431266) flagged that the doc overclaimed file_system.dag's coverage: it models POSIX file operations (open/read/write/close) but does NOT yet carry a Node→File rendering binding as a first-class substrate fact. The relationship is currently emergent from the emit stage, not stored as queryable substrate data — claiming "file-tying is a structural fact" left the central file-binding authority off-substrate. Fixes: 1. **§1 rewrite (lines 41-44)**: replace the overclaim "the substrate models File explicitly ... so file-tying is a structural fact" with an honest accounting: file_system.dag is POSIX ops only; the Node-to-File relationship is currently emergent from emit, NOT a queryable data row. Design intent is right (file-tying as substrate data so it's queryable and auditable, not implicit in emit behavior), but the primitive doesn't exist yet. Tracked as a §6.8 gap. 2. **§6.8 addition (item 6)**: add Node→File binding registry to the missing-substrate list. Concrete shape: `data <node>_rendered_into: NodeToFileBinding = { node, file, region }`. Closes the "files are a downstream effect of substrate state" framing — that effect becomes a structurally-recorded fact, not just a compile-time side effect. The design intent (node-centric, file-as-effect) survives intact; the honest update is that one of the substrate primitives needed to make it fully structural still has to land. That's the right shape per INVARIANTS P2 (illegal-states-unrepresentable / single authority): don't claim a structural fact that isn't yet stored as queryable data — name the gap as a tracked dependency. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: mirror ratified Edit definition exactly (replacement only) openai-pro BLOCKING inline at line 81 flagged that the doc's description of Edit as "Replace / insert / delete at a position" contradicted the ratified std/node.dag authority, which defines: type Edit { at: Path, replacement: Node } type Diff { edits: List<Edit> } type Path { steps: List<Symbol> } Edit is a SINGLE replacement at a Path — no separate insert / delete variants. The "Replace / insert / delete" prose introduced operations the ratified type doesn't model, violating P2 single-authority. Fix: replace the prose with the exact ratified shape, noting that insertions and deletions are expressed by replacing the parent node with a new parent whose children list includes / excludes the targeted child. This is the natural decomposition under the ratified single-Edit shape and avoids inventing a parallel contract. Same single-authority fix shape as the earlier SectionRef + apply_diff alignments — point at the ratified definition rather than restate with diverged wording. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: mark §5/§6 examples as future-combinator-layer pseudo-code codex BLOCKING review (sha:1dcf5193) wrap raised three findings; two were already addressed in prior commits (c431266 affected_set scope collapse + ab4bcdb Edit shape mismatch). The third is the worked examples using higher-level edit verbs (replace_with, replace, insert, insert_field) that don't map directly to the ratified Edit { at: Path, replacement: Node } shape. Per the reviewer's "either express as replacement-at-path rewrites or mark them as a future combinator layer" binary: chose mark-as-future- combinator-layer because the examples are illustrative intent shapes, not authoritative Edit constructors. Rewriting each into explicit parent-replacement decomposition would make the examples much longer and harder to read for the design intent they're meant to convey. Added a clear pseudo-code disclaimer at the top of §5 ("worked examples") that covers both §5 and §6 examples: - States the verbs (replace_with, replace, insert, insert_field) are future-combinator-layer shorthand, NOT literal .dag - Cites §3 for the ratified Edit { at: Path, replacement: Node } - Explains the decomposition: insertions/field-additions land as parent-replacement (build a new parent node whose children list includes the desired child, single Edit at parent_path) - Points at §6.8 items 1 + 3 (machine-readable Clean shape + DAG-of-edits composition) as the substrate work that builds the combinator layer - "Treat the examples as intent illustrations, not authoritative Edit constructors" This restores single-authority discipline: §3 names the ratified Edit shape, and the examples are explicitly framed as combinator-layer pseudo-code that compresses common intent shapes for readability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * design-read-edit-pipeline: candidate-state gating + grounded L1.12 transform openai-pro REQUEST_CHANGES on b26f0d8 raised two valid design-level defects, both blocking: **Finding 1 — gate/apply ordering bug** (P3 fail-closed / structure gates emission). The §4 pipeline was: 4. Gate on affected_set (pre-edit graph) 5. Apply diff That gates the PRE-edit state then applies the Diff, letting a Diff introduce post-edit invariant violations that never get enforced before re-emit. Violates THESIS:13-15 + :453-457 "compiler validates every causal link before emitting to targets." Fix: rewrite §4 as a SEVEN-step candidate-state pattern: 1. Read 2. Diagnose 3. Propose Diff 4. Candidate: candidate_dag = apply_diff(dag, Diff) # uncommitted 5. Gate: enforce lenses against the CANDIDATE state 6. Commit: dag := candidate_dag (only if every gate passed) 7. Re-emit Added explicit "Why gate the candidate, not the pre-edit graph" paragraph naming the semantic gap the prior ordering would have created. The "fail-closed promise honest" framing: validation happens against the state that will be emitted, not against a state already known to be valid. Updated worked examples (§5.A, §6.3 catamorphism pipeline, §6.6 CLI pipeline) to use the candidate-state ordering throughout — apply_diff to candidate, gate against candidate, commit if green. **Finding 2 — L1.12 transform with ungrounded canonical-home pick.** §6.4 L1_12_transform called `pick_canonical_home(matched_pair)` in the outcome (5) silence case (no CanonicalConcept row anywhere). That's ungrounded inference — picking which side is canonical when the substrate has no canonical authority declared. INVARIANTS:31-32 says missing facts should be authored, not inferred by shortcuts. Fix: rewrite L1_12_transform to branch on outcome: - **Outcome (4)** same-concept-without-alias-or-retirement: a CanonicalConcept row EXISTS; READ canonical_home from it. Auto(Diff). - **Outcome (5)** silence: no canonical authority declared. NeedsDecision { because: no_canonical_authority, needs: operator_authors_CanonicalConcept_row { candidates: pair } }. Never an inferred pick. Added the general pattern statement: "transforms ground in substrate-declared authority; absence of authority becomes NeedsDecision, never an inferred guess." This is the design rule for every L1.x transform — auto-fix only when the substrate gives you grounded structural facts to fix toward. Both fixes preserve the design direction and tighten it on the fail-closed-and-no-inferred-authority discipline the project thesis demands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: add hero case (f) — mechanical refactor Operator-articulated hero case (2026-05-19): mechanical refactors — declarative model-A → model-B transitions across the corpus — are "a good use case for more mechanical things (i.e. the only judgement applied is in which command to run, not literally changing each line)." Adds §6.7b as the sixth hero case, between merge-sort synthesis (§6.7) and the missing-substrate enumeration (§6.8). Key positioning: - **Cleanest convolution shape** — judgment at command-selection, zero per-site judgment. Distinguished from the other cases: (a) one lens auto-fix (b) one lens with conditional outcomes (c) per-site conditional cascade (f) declarative target, uniform per-site application - **Substrate guarantees** — uses the §4 candidate-state pattern to give the atomicity guarantee the user asked about ("how can we guarantee a successful migration"): either complete or no-op, never a half-migrated state. LOC count is irrelevant; the substrate handles 10 sites or 10,000 the same way. - **Affected-LOC enumeration** — pre-execution preview of site_count + exact_paths + re_exec_scope, structurally, not by grep. Direct answer to the user's "what are all the affected LOC" question. - **Composes per-lens transforms from §6.2** — a mechanical refactor often decomposes into per-lens auto-fixes from the L1.x catalog. Canonical-B decomposes into L1.7 transforms + L1.12 outcome (4) transforms. Agent picks the named refactor; substrate composes the per-lens transforms that implement it. - **PR #3338 as the worked example** — canonical-B across 6 languages + 7 v3 ratchet dissolutions, two operator decisions ("use decl-ref for Bool" + "dissolve the 7 v3 ratchets") plus 13 uniform per-class site applications. Hand-executed in #3338; the substrate (had it been operational) could have applied the entire refactor mechanically from those two decisions. §6.9 recommended ordering updated: (f) mechanical refactor slots between (b) L1.12 and (c) interface cascade — it's the most directly useful hero shape for day-to-day refactoring work, and demonstrates the composition pattern that the agent-shape cases (c)/(d)/(e) build on. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * design-read-edit-pipeline: fix §6.10 RootScope slip — use the §2 corpus-fold idiom cursor/composer-2 review caught a slip: §6.10 wrote `auto_fix_for_lens(L1.5, RootScope)` while §2 (lines 74-77) explicitly rules out RootScope as a scope variant ("no separate RootScope / corpus-wide variant — corpus-wide application is achieved by composition over the declaration set"). Replaced the RootScope call with the explicit fold over `declarations_in(dag)`: declarations_in(dag).for_each(d => auto_fix_for_lens(L1.5, DeclarationScope(d)) ) Added clarifying sentence: "auto_fix_for_lens itself takes a SectionRef (DeclarationScope or NodeScope) — never an invented RootScope." Keeps the doc internally consistent on the single structural scope vocabulary per INVARIANTS P2 / Practice 5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: track L1.12 concept-identity carriers as §6.8 item 8 + §6.4 dependency caveat codex BLOCKING (sha:77469d84) raised two findings; one valid, one factually wrong. **Finding 1 — valid.** L1.12 concept identity depends on undeclared registry carriers (CanonicalConcept, ConceptDisambiguation, HistoricalDeclaration). Verified absent from src/v4/std/*.dag, src/v4/lens/*.dag, src/v4/extdeps/*.dag — they only exist as design in docs/design-dissolution-lens.md (PR #3334, operator manual-merge queue), not as ratified .dag substrate. Fix: - Added §6.8 item 8 explicitly tracking the L1.12 concept-identity carriers as missing substrate (alongside item 1 machine-readable Clean shapes, item 2 ConditionalDiff ADT, etc.). Lists the three carrier shapes and notes the design-pending status. - Added a dependency caveat callout at the top of §6.4 hero case (b) pointing at §6.8 item 8 so a reader hitting the example sees the carrier-not-yet-substrate dependency immediately. Finding 2 — factually wrong (rebutted on-PR, not in this commit). THESIS.md:232 explicitly carries the retraction with the "operator-ratified 2026-05-15" stamp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: add §5 Example B dependency caveat matching §6.4 Same finding fired again at line 255 of pre-fix sha (§5 Example B "rename a concept across the corpus", which also references CanonicalConcept). The global §6.8 item 8 + §6.4 inline caveat from 07d862f cover the case, but a reader entering at §5 Example B should see the dependency callout immediately — same shape as the §6.4 callout. Both inline caveats point at §6.8 item 8 as the global tracking entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: PM * design-read-edit-pipeline: candidate root explicit in gate surface + LOC rename openai-pro REQUEST_CHANGES on f3d146b raised two valid design-level findings; both addressed. **Finding 1 — candidate authority not typed into gate surface.** The candidate-state pattern from earlier was correct in intent, but the worked examples called `apply_lens(_, ref, Enforce)` with a bare ref — leaving the candidate-vs-pre-edit context to a prose comment ("evaluated in candidate_dag context"). A worker following the pseudo-code could accidentally enforce against the wrong root. Fix: introduce `scope_in(root: Node, ref: NodeRef) -> SectionRef` as the helper that **explicitly binds a frontier ref to a dag root**. Updated §4 pipeline + §5 Example A + §6.3 catamorphism + §6.6 CLI + §6.7b mechanical refactor — every gate call now reads `apply_lens(_, scope_in(candidate_dag, ref), Enforce)`. The candidate root is structurally visible in every call; can't be lost via comment-level convention. **Finding 2 — "affected LOC" reintroduces file/line authority before Node→File binding exists.** §6.7b promised "affected LOC" structurally — but §1 explicitly says file/line is emergent-not-substrate. Promising LOC enumeration before the Node→File binding registry (§6.8 item 6) is built contradicts the node-centric framing. Fix: rename §6.7b "Affected-LOC enumeration" → "Affected-structural- paths enumeration"; the inline preview computes structural Paths, not file:line. Added a callout explicitly tying the LOC translation to the Node→File binding registry (§6.8 item 6) — until that registry lands, the substrate-native answer is in terms of Paths. LOC is the downstream projection of "affected sites" via emit's mapping; the substrate-native fact is "affected structural sites." Also updated the "guarantee is structural" close-out: "LOC count is irrelevant" → "Site count is irrelevant." Keeps the doc consistent that the substrate-native unit is the Path/site, not LOC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design-read-edit-pipeline: fix §6.10 auto_fix_for_lens straggler — scope_in everywhere codex APPROVE_WITH_COMMENTS caught one remaining apply_lens call site I missed in the prior candidate-authority pass: §6.10 auto_fix_for_lens workflow at line 851 still used `apply_lens(lens, ref, Enforce)` with the bare ref. Fixed to `apply_lens(lens, scope_in(candidate_dag, ref), Enforce)` matching §4's "candidate root explicit in the gate surface" rule and the rest of the worked examples. Verified: only remaining `apply_lens(_, ref, Enforce)` in the doc is the §4 anti-pattern call-out itself (explaining what NOT to do). All actual call sites are consistent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…olf-435 review) Major doc amendment integrating the substantive review from PR #3437's sister doc (sunny-wolf-435 PM, against docs/design-read-edit-pipeline.md which merged in PR #3364 on 2026-05-19). Reviewer feedback was that the compiler-architecture doc had a substantial gap: it covered the COMPILE direction (text/data → target) thoroughly but was silent on the EDIT direction (CoreNode + Diff → CoreNode'), the read/edit pipeline merged in PR #3364, and the closely-related question "how will the compiler edit itself / regenerate stage0?" CHANGES: 1. NEW "Load-bearing references" section (after "What this document is"): Comprehensive list of foundational + adjacent ratified design docs the compiler architecture composes with. Includes THESIS / MODELING / modeling-discipline / INVARIANTS / TASKS as foundational, and 11 adjacent design docs (read-edit-pipeline, emit-stage-l25, infer-stage-l25, lens-application-surface, lens-framework, affected-set-lens, dissolution-lens, v4-close-interrogation, v4-dag-rationale, pure-bootstrap-zero, substrate-lambda-calculus-grounding, bootstrap-fact-model) plus 6 lens-specific design docs. 2. NEW 9th substrate primitive: apply_diff - Path / Edit / Diff vocabulary ratified in PR #3162 (std/node.dag) - apply_diff scaffold in lens/application.dag (T-23) - The substrate is read/write-symmetric: reads via fold_node / apply_lens; writes via apply_diff - Primitive set is now 9 things (was 8); TL;DR + tally line updated 3. NEW "The EDIT direction — symmetric to compile" section: - Read/edit primitives table (Path, Edit, Diff, apply_diff, subterm_at, apply_lens, affected_set) - The seven-step read→edit pipeline from PR #3364 § 4 - Candidate-state pattern: gates run against apply_diff(dag, Diff), NOT the pre-edit graph. Same monotonic-facts invariant as P3's facts-flow-forward, applied to mutation. - EDIT direction = the "Query-driven rewrite" ingest path (cross-link to the ingest paths table) - Library-first agent surface (per read/edit doc § 6.10) — extended to apply to compile() too - Lens as (find, transform) convolution view; cross-ref to mechanical refactor hero case (f) in read/edit doc § 6.7b 4. NEW "Self-modification, stage0, self-edit" section addressing the reviewer's specific question: - Compiler reads its own source as CoreNode (same lens surface as user code; no special introspection) - Compiler writes to its own source via apply_diff (two paths: hand-authored Diff or mechanical-refactor lens) - stage0 regeneration is compile(self, dag, TranslateTo(rust)) — no special mode; the homomorphism mechanic applies identically - Candidate-state for self-modification safety — lenses gate the candidate; compiler cannot break itself silently - Implications: no new substrate needed; self-hosting is one specific compile invocation; hand-Rust-to-zero IS the loop closing. 5. Glossary expanded with Path / Edit / Diff / apply_diff / apply_lens / SectionRef / scope_in / candidate-state pattern / affected_set / self-edit-stage0 vocabulary. The compile + edit directions are now both represented in the doc. The two designs (this one + read/edit pipeline) compose cleanly — same CoreNode, fold_node, Diagnostic substrate; the read/edit doc owns the agent-surface mechanics, this doc owns the homomorphism architecture, both are the same nine substrate primitives at different angles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Findings on PR #3437 from codex 2026-05-20T05:24:15Z, all addressed in this commit: FINDING 1 — Validate-then-compile gate not type-enforced. P3 commitment 6 said the project-mandatory wrapper preserves the "by construction" guarantee, but that was convention, not type-level enforcement. Updated to require Validated<Output>-style carrier discharged only by the wrapper; bare compile() now explicitly marked as internal/non-terminal (accessible to advanced consumers — lens framework, build tooling, self-edit — but NOT the everyday user surface). The wrapper-as-terminal pattern is invariant at the type level. FINDING 2 — Substrate inventory verifiability. The reviewer flagged "live-substrate inventory was not verified against the v4 tree." Verified refinement.dag IS on main (1143 bytes, status "T-25-core modeled" — landed via #3354); the doc claim was correct. Added a "Verifiability note" pointing at the verification commands (ls + head -10) + added commit refs (#3354 for refinement.dag, #3162 for Path/Edit/Diff vocabulary, #3436 for in-flight T-8 PR) so future reviews can verify independently. Also added lens/application.dag and lens/affected_set.dag to the inventory (they were missing). FINDING 3 — Scaffold-vs-design divergence. The reviewer correctly identified that the compiler scaffolds in src/v4/compiler/ predate this doc's ratifications and have divergent signatures (00_compile.dag's `compile(Source, TargetModel) -> TargetSource` vs this doc's `compile(CoreNode, LanguageModel, CompileMode) -> Outcome<Output>`, 04_infer.dag's `v4.lens.cost` import vs P3's no-named-lens rule, etc.). Added a "Scaffold-vs-design divergence — implementation migration plan" section that explicitly catalogs the divergences and prescribes the migration. The scaffolds are shape placeholders; implementation workers should land the ratified interface, not preserve stale signatures. NOT addressing as a separate finding — eager-bat-439 archive refused because PR #3436 is still open. Worker delivered cleanly (2 approvals, CI green, conflict markers resolved); operator manual squash-merge is the gate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ussion) (#3437) * WIP: V4 work * WIP: V4 work * design: ratify P3 lens contract — side-channel over InferredTree Resolves the codex BLOCKING finding on PR #3437 line 33: - P3 was flagged as contradicting THESIS lines 105 + 342 ("compiler validates dimensions / by construction, not by opt-in"). Original framing made lens enforcement entirely external; too strong. - Resolution: lenses are orthogonal to the homomorphism (they observe; they don't participate). Six commitments now ratified: 1. InferredTree is the lens consumption point (stable contract). 2. Lenses are folds over InferredTree (shared fold_node primitive). 3. Lens outputs are side-channel (not feeding translate/eval). 4. Built-in and user-defined lenses share one algebra contract; compiler core does not name any specific lens. 5. Multi-lens execution is dependency-managed (no re-walks). 6. "By construction" guarantee preserved by project-mandatory wrapper. - B-style (lenses inside compile) vs C-style (lenses in a wrapper) is not architecturally load-bearing under 1-6; refactoring B<->C is mechanical. Side effects: - Open Q0 (lens architecture) marked Ratified. - Open Q2 (InferredTree dimensional facts) marked Ratified — tree carries grounding only; dimensions are lens side-channel. - New Open Q6 — multi-lens dependency-management substrate primitive (the substrate work commitment 5 implies). - Note in End-to-end I/O section updated (no longer "under reconsideration"). The 04_infer.dag import of v4.lens.cost.SymbolicCost remains a violation of commitment 4 and is fix-needed regardless of surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: integrate reviewer feedback — P5 + P6 + ratify Q1/Q3/Q4/Q5 + Q7-Q14 Major amendment integrating the second-round review on PR #3437 and the operator's dependency-management question. Doc grows from ~440 to ~640 lines. New ratified premises: - P5 — Fold discipline does not imply purely local bottom-up computation. Stage algebras may be higher-order, effectful, constraint-bearing, or fixpoint-seeking. Non-local mechanisms (resolve's inherited scope, ground's constraint solving, coercion fold) are substrate machinery, not ad-hoc compiler logic. - P6 — Dependencies are first-class typed edges. The compiler maintains a typed dependency graph (BindsTo / TypeDependsOn / DataDependsOn / EffectDependsOn / ResourceDependsOn / ModuleDependsOn / BarrierBefore / PlacementDependsOn) alongside the containment tree. Parallelism, MapReduce-style sharding, CUDA placement, memoization, and incremental rebuild are derived from this graph + algebra-inhabitance witnesses, not special compiler modes. Substrate primitive set updated to six (added typed dependency graph + topological/SCC machinery; probably lands in std/dependency.dag — T-21's affected_set.dag is the incremental-rebuild specialization). InferredTree carrier now explicitly includes the semantic dependency graph alongside containment / binding / typeshape / inhabitance witness. Doc notes the future-rename consideration to InferredGraph but keeps the historical name for now. ModelCore factored as the shared substrate of LanguageModel + HostModel (per ratified Q1a). HostModel is a distinct peer of LanguageModel, not a VoidGrammar variant. LanguageModel expanded per ratified Q5 to include binding/scope rules, effect/partiality declarations, version/dialect metadata. Carrier taxonomy clarified: SurfaceNode / CoreNode / ResolvedCoreNode / InferredCoreNode / TargetSurfaceNode / TargetSource. Compiler core operates over CoreNode and its enrichments; source/target Node shapes are boundary-only. Ratifications: - Q1 → Q1a + factored ModelCore. - Q3 → Q3a (parse + normalize separate logically; inspectability). - Q4 → Q4a with required substrate laws + accumulate-vs-short-circuit policy via Q11. - Q5 → Q5a with expanded LanguageModel. New open questions: - Q7 — LanguageModel declarative-only vs executable predicates? (Hidden emitter prevention.) - Q8 — Coercion-fold completeness vs fail-closed-incomplete. Diagnostics must distinguish. - Q9 — Independent witness checking (search untrusted; checker trusted). - Q10 — Partiality and effects on ModelCore — substrate representation. - Q11 — Outcome<T> accumulate vs short-circuit per-stage policy. - Q12 — Bidirectional grammar law (parse-after-print target stability is the default; source-text-faithful round-tripping is opt-in for code-mod tools). - Q13 — Language versions / dialects on LanguageModel. - Q14 — Target selection policy under multiple valid homomorphisms. Doc cleanups: - "Two parameters" → "Three arguments" (input_text is also an argument). - "project" boundary-action removed (rescinded lens-as-compile-mode artifact). - "Nothing re-walks" rewording: each stage performs at most one disciplined fold/traverse and monotonically extends; facts are monotonic; no stage re-derives facts from raw text or duplicated source-of-truth. Glossary expanded: ModelCore, DependencyEdge / DependencyKind, synthesized attribute, inherited attribute, SCC condensation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: V4 work * design: address 3 BLOCKING reviews — Q1 prose / Q8 framing / Q9 + P5 search leakage Reviewer (codex) flagged three remaining stale spots after the previous amendment commit dc4c41b: 1. Line 97 (End-to-end I/O prose): still described HostModel as "LanguageModel minus the grammar" + "Open Q1" even though Q1 had been ratified as ModelCore + distinct HostModel. Rewrote line 97 to align with the ratified shape. 2. Open Q8 (coercion-fold completeness): admitted an "incomplete bounded search" mode (Q8b) that contradicts T-9's decidable-by-construction ratification. The fold is mechanical over a closed candidate set; there is no "search may have missed something" mode. Reframed Q8 from a completeness question to a diagnostic-shape question (what provenance / near-miss / reason-differentiation belongs in the fail-closed diagnostic). 3. P5 + Open Q9: legacy "search" framing leaked back in: - P5 said "performs structural-equality search against the target language model's declared inhabitants. The search is bounded..." — reworded to "enumerates the target language model's declared candidates and performs a structural-equality zip-fold ... deterministic candidate enumeration, not a heuristic search." - Q9 said "without re-running the search" / "search is untrusted; checker is trusted" — reworded around "the coercion fold's candidate enumeration" / "the derivation is untrusted; the witness check is trusted." Added Q9b for the legitimate-ambiguity question (multiple candidates passing structure preservation), which is a target-policy question (links to Q14), not a search-completeness question. The historical "search" mentions in TL;DR / primitive set table / glossary ("supersedes search", "never a search", "(not search)") are correct historical references and preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: V4 work * design: integrate reviewer's ratification-edits — P7 LawfulRewriteWitness + sharpened boundaries Operator-direct review of the dc4c41b+524c2ad6c iteration. Landing all amendments in one commit. NEW PREMISE: - P7 (ratified) — Structure-changing target lowerings (sequential→parallel map, left-fold→tree-reduce, CPU loop→CUDA kernel, sequential reduce→ MapReduce) require a LawfulRewriteWitness primitive. The witness is declared by the target/runtime model with precondition algebra laws; the rewritten plan grounding is then checked by the coercion fold's EXACT zip-fold. Keeps "coercion fold is not heuristic search" intact while making room for structure-changing lowerings. Without this distinction implementation workers would face a false fork between cementing CUDA/ MapReduce into the compiler (Practice 10 row 3 failure) or extending the coercion fold to do search (T-9 D2 violation). NEW SUBSTRATE PRIMITIVES (table now lists 8 total — was 6): - solve_constraints — declared constraint-solving primitive consumed by ground/infer. Produces a UNIQUE canonical source grounding (or ambiguity diagnostic). Distinct from the coercion fold. P5 wording fixed — solver is no longer called "the coercion fold." - LawfulRewriteWitness — per P7, witness primitive for structure-changing lowerings. P6 EXTENSIONS: - Edge orientation convention: A → B means "A is required before B." Applies uniformly across all DependencyKinds. - Conservative-by-default rule: absence of an edge is evidence of independence ONLY under a ClosedWorldDependencyWitness. Unknown effect/ resource facts conservatively introduce ordering or fail-closed. Prevents unsound parallelism inference. - Source-core vs TargetPlan tiers: PlacementDependsOn is TargetPlan-tier, introduced during translate/lowering — NOT source semantics. Source-core kinds: Contains, BindsTo, TypeDependsOn, DataDependsOn, EffectDependsOn, ResourceDependsOn, ModuleDependsOn. TargetPlan kinds: PlacementConstraint, TransferDependsOn, BarrierBefore (synthetic sync), shard/partition/ device-binding. P3 SHARPENING: - Commitment 5 reworded: "Lenses with no interdependencies are coalesced into a shared traversal. Lenses with dependencies are scheduled by a lens-dependency DAG." Replaces the too-strong "no re-walks" wording while preserving Practice 3 discipline. - Commitment 6 reworded to sharpen the lens-doesn't-feed-homomorphism vs wrapper-may-gate-emit/eval distinction. GRAMMAR-AS-BIDIR-DATA DEFAULT LAW: now in the primitive description — parse_target(serialize_target(node)) == node. Serialization is canonicalizing; full source-text round-tripping is opt-in (Q12c), not the default. Prevents over-commitment to impossible full bidirectionality. CANONICAL-GROUNDING INVARIANT on ground: ground must produce EXACTLY ONE canonical grounding per Node (with witness) OR an ambiguity diagnostic. Translate never receives ambiguous source grounding. Prevents target selection from leaking backward into inference. STALE-CONTRADICTION CLEANUPS: - P2 "Open question on HostModel shape" → "Ratified per Q1." - "What's NOT in scope" lens line → "Lens framework implementation — out of initial compiler-core scope. Contract ratified by P3 + Q0; multi-lens substrate remains Open Q6." - Q2 wording: "carries only grounding facts" → "carries compiler-core semantic facts only: locus, binding, typeshape, inhabitance witness, AND the P6 semantic dependency graph." Reconciles the apparent contradiction with P6. Glossary expanded: solve_constraints, LawfulRewriteWitness, ConstraintGraph, ClosedWorldDependencyWitness, canonical (source) grounding. Doc grew to 667 lines. The strongest form of the thesis now: the compiler transforms a canonical grounded program graph, not just a syntax tree. Containment enables folds; typed dependencies enable scheduling/incrementality/parallelism; canonical grounding enables decidable coercion; lawful rewrite witnesses enable CUDA/MapReduce-style structure changes; lenses observe the grounded graph but do not participate in the homomorphism. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: separate ingest layer from compile-core (data-first surface) Operator-direct ratification: compile-core operates on data (CoreNode), not text. Text is one of several legitimate ingest entry points, not THE entry point. Substrate is data-first. Motivation: lens/query/affected-set/IDE workflows operate on Node data, not text. Forcing every entry through text would either require lossless code-mod tooling for all cases or constrain the substrate's expressiveness. The cleanest separation is to make ingest a separable layer with multiple entry paths, all producing CoreNode. Signature change: compile(source: CoreNode, input_lang, mode) -> Outcome<Output> ingest_text(text, input_lang) -> Outcome<CoreNode> Other ingest paths (no text involved): - Programmatic builder (IDE plugins, code generators). - Query-driven rewrite (affected_set + transformation). - Round-trip from a prior TargetNodeTree. All produce CoreNode; compile takes it from there. Pipeline diagram updated to show the INGEST / COMPILE-CORE separation. Stage table now has a "Layer" column distinguishing INGEST stages (parse, normalize) from COMPILE-CORE stages (resolve, ground, translate, serialize, eval). Carrier shape progression diagram updated to show the multi-source funnel into CoreNode. Boundary actions: - Compile-core: write output text (or execute), report diagnostics. Pure data-in / data-out otherwise. - Ingest layer (separable): read input text only when ingesting from text. The CoreNode is the substrate-canonical Node — six connectives + five behaviors only, sugar dissolved. The compile contract is uniform regardless of how CoreNode was authored. Glossary expanded: ingest, ingest_text. This sharpens what was already implicit (the carrier taxonomy already distinguished SurfaceNode/CoreNode) and makes the lens/query story cleaner: those operate on Node data directly, without going through text. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: V4 work * design: integrate read/edit pipeline + self-modification (per sunny-wolf-435 review) Major doc amendment integrating the substantive review from PR #3437's sister doc (sunny-wolf-435 PM, against docs/design-read-edit-pipeline.md which merged in PR #3364 on 2026-05-19). Reviewer feedback was that the compiler-architecture doc had a substantial gap: it covered the COMPILE direction (text/data → target) thoroughly but was silent on the EDIT direction (CoreNode + Diff → CoreNode'), the read/edit pipeline merged in PR #3364, and the closely-related question "how will the compiler edit itself / regenerate stage0?" CHANGES: 1. NEW "Load-bearing references" section (after "What this document is"): Comprehensive list of foundational + adjacent ratified design docs the compiler architecture composes with. Includes THESIS / MODELING / modeling-discipline / INVARIANTS / TASKS as foundational, and 11 adjacent design docs (read-edit-pipeline, emit-stage-l25, infer-stage-l25, lens-application-surface, lens-framework, affected-set-lens, dissolution-lens, v4-close-interrogation, v4-dag-rationale, pure-bootstrap-zero, substrate-lambda-calculus-grounding, bootstrap-fact-model) plus 6 lens-specific design docs. 2. NEW 9th substrate primitive: apply_diff - Path / Edit / Diff vocabulary ratified in PR #3162 (std/node.dag) - apply_diff scaffold in lens/application.dag (T-23) - The substrate is read/write-symmetric: reads via fold_node / apply_lens; writes via apply_diff - Primitive set is now 9 things (was 8); TL;DR + tally line updated 3. NEW "The EDIT direction — symmetric to compile" section: - Read/edit primitives table (Path, Edit, Diff, apply_diff, subterm_at, apply_lens, affected_set) - The seven-step read→edit pipeline from PR #3364 § 4 - Candidate-state pattern: gates run against apply_diff(dag, Diff), NOT the pre-edit graph. Same monotonic-facts invariant as P3's facts-flow-forward, applied to mutation. - EDIT direction = the "Query-driven rewrite" ingest path (cross-link to the ingest paths table) - Library-first agent surface (per read/edit doc § 6.10) — extended to apply to compile() too - Lens as (find, transform) convolution view; cross-ref to mechanical refactor hero case (f) in read/edit doc § 6.7b 4. NEW "Self-modification, stage0, self-edit" section addressing the reviewer's specific question: - Compiler reads its own source as CoreNode (same lens surface as user code; no special introspection) - Compiler writes to its own source via apply_diff (two paths: hand-authored Diff or mechanical-refactor lens) - stage0 regeneration is compile(self, dag, TranslateTo(rust)) — no special mode; the homomorphism mechanic applies identically - Candidate-state for self-modification safety — lenses gate the candidate; compiler cannot break itself silently - Implications: no new substrate needed; self-hosting is one specific compile invocation; hand-Rust-to-zero IS the loop closing. 5. Glossary expanded with Path / Edit / Diff / apply_diff / apply_lens / SectionRef / scope_in / candidate-state pattern / affected_set / self-edit-stage0 vocabulary. The compile + edit directions are now both represented in the doc. The two designs (this one + read/edit pipeline) compose cleanly — same CoreNode, fold_node, Diagnostic substrate; the read/edit doc owns the agent-surface mechanics, this doc owns the homomorphism architecture, both are the same nine substrate primitives at different angles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: address 3 BLOCKING codex findings on commit 77fe746 Findings on PR #3437 from codex 2026-05-20T05:24:15Z, all addressed in this commit: FINDING 1 — Validate-then-compile gate not type-enforced. P3 commitment 6 said the project-mandatory wrapper preserves the "by construction" guarantee, but that was convention, not type-level enforcement. Updated to require Validated<Output>-style carrier discharged only by the wrapper; bare compile() now explicitly marked as internal/non-terminal (accessible to advanced consumers — lens framework, build tooling, self-edit — but NOT the everyday user surface). The wrapper-as-terminal pattern is invariant at the type level. FINDING 2 — Substrate inventory verifiability. The reviewer flagged "live-substrate inventory was not verified against the v4 tree." Verified refinement.dag IS on main (1143 bytes, status "T-25-core modeled" — landed via #3354); the doc claim was correct. Added a "Verifiability note" pointing at the verification commands (ls + head -10) + added commit refs (#3354 for refinement.dag, #3162 for Path/Edit/Diff vocabulary, #3436 for in-flight T-8 PR) so future reviews can verify independently. Also added lens/application.dag and lens/affected_set.dag to the inventory (they were missing). FINDING 3 — Scaffold-vs-design divergence. The reviewer correctly identified that the compiler scaffolds in src/v4/compiler/ predate this doc's ratifications and have divergent signatures (00_compile.dag's `compile(Source, TargetModel) -> TargetSource` vs this doc's `compile(CoreNode, LanguageModel, CompileMode) -> Outcome<Output>`, 04_infer.dag's `v4.lens.cost` import vs P3's no-named-lens rule, etc.). Added a "Scaffold-vs-design divergence — implementation migration plan" section that explicitly catalogs the divergences and prescribes the migration. The scaffolds are shape placeholders; implementation workers should land the ratified interface, not preserve stale signatures. NOT addressing as a separate finding — eager-bat-439 archive refused because PR #3436 is still open. Worker delivered cleanly (2 approvals, CI green, conflict markers resolved); operator manual squash-merge is the gate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: V4 work * design: P8 compiler-self-application + refined testgen lens-family + regeneration substrate Integrates the operator's review per 2026-05-20 — two ratifications + named regeneration substrate. NEW PREMISE P8 — The compiler is not exempt from its own discipline: The compiler is itself a modeled system. Its layers (stages, language models, lenses, testgen, target models, diagnostics, glue derivation) are modeled as dependency graphs over the same substrate primitives. When an upstream model changes, the compiler computes the affected downstream subgraph (T-21 affected_set) and regenerates derivable artifacts; non-derivable consequences fail-closed. "No hidden anything" generalized: no implicit conventions, no manual synchronization, no hidden emitter / parser / test-generator / integration- updater / layer-specific-patcher / ad-hoc-Node-traversal-outside-primitives. Every compiler-internal artifact must be a substrate primitive OR a declared algebra OR a lens OR a projection OR a target/runtime policy. The slogan: the compiler is the first consumer of its own modeling discipline. If implementation workers find themselves writing ad hoc code to keep compiler layers in sync, that is a STOP condition. Two worked examples added under P8: - testgen self-regeneration: Refinement<T> shape changes → affected_set computes which TestClaims/TestCases/target test files regenerate → lens family re-fires automatically on the affected subgraph. - LanguageModel self-regeneration: LanguageModel gains a new field (e.g., effect-semantics per Q10) → affected_set computes which stages/lenses depend on it → each extends or fails-closed on the new field. NEW "Named regeneration substrate" section (under P8) cataloging the substrate concepts P0 + P8 need that are not yet declared: - ChangeSet (std/change.dag) - AffectedSet (T-21 is the lens-frontier specialization; full version not yet declared) - Projection (std/projection.dag) - Artifact (std/artifact.dag) - RecomputePlan REFINED TESTGEN LENS FAMILY (per reviewer's three-layer taxonomy): - Layer 1: TestClaimLens — InferredTree → TestClaim Witnesses (abstract behavioral claims: roundtrip / refinement-boundary / algebra-law / protocol-compat / effect-idempotency) - Layer 2: TestCaseLens — TestClaim Witnesses → TestCase Witnesses (concrete cases: examples, boundary cases, property-test generators, fuzz seeds, regression fixtures) - Layer 3: TargetTestProjection — TestCase Witnesses + target LanguageModel → target test source (Rust #[test], pytest, Jest, integration harness) Profile invocations expanded with reviewer's full taxonomy: smoke, boundary, property, algebra_law, effect, integration, roundtrip, equivalence, fuzz, regression. All share std/verification.dag (landed) + std/refinement.dag (landed) + std/dependency.dag (P6 substrate, not yet declared) + std/testgen.dag (renamed from lens/testgen.dag, follow-up bookkeeping). Self-regeneration cross-reference: when a model fact changes, affected_set computes which testgen lenses re-fire on which subgraph — no manual sync. GLOSSARY EXPANDED: TestClaimLens, TestCaseLens, TargetTestProjection, ChangeSet, AffectedSet, Projection, Artifact, RecomputePlan. The compiler architecture now has the full mental model: - Semantic substrate: 6 connectives + 5 behaviors - Compiler substrate: 9 primitives (fold_node, traverse, grammar-as-data, solve_constraints, coercion fold, LawfulRewriteWitness, dep graph, apply_diff, diagnostic+locus) - System substrate (not yet declared): ChangeSet, AffectedSet, Projection, Artifact, RecomputePlan - Derived outputs: target code, eval values, tests, dim facts, glue, diagnostics, and compiler artifacts themselves (P8) The big idea: v4 does not merely compile .dag programs. v4 models systems — including itself — as dependency graphs, then regenerates all downstream projections when upstream facts change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: P9 stratified bootstrap — stage0 as generated artifact, not self-modifying code Integrates the reviewer's critical clarification (2026-05-20): "compiler edits itself" is loose; the precise framing is "compiler models itself; generates candidates; promotion is guarded." Resolves the architectural ambiguity in the prior self-modification framing without falling into v2's manual-stage0-patch failure mode OR free-runtime-self-modification (intractable). NEW PREMISE P9 — Bootstrap is stratified; stage0 is a generated artifact: The compiler may model and regenerate its own implementation, INCLUDING stage0, but no running compiler generation mutates itself in place. The compiler can DERIVE AND VERIFY a replacement stage0 from Stage0Spec; it cannot arbitrarily rewrite itself at runtime. THREE-PIPELINE FRAMING (must not collapse): 1. Semantic compile pipeline — text → InferredGraph → target/eval. 2. Artifact projection pipeline — InferredGraph → generated compiler code / tests / docs / schemas / glue / stage1 source. 3. Bootstrap promotion pipeline — current Stage0[k] + candidates → Stage0[k+1] (or rejection diagnostic), guarded by BootstrapWitness + FixedPointWitness. The mistake is collapsing all three into "the compiler edits itself." WHAT STAGE0 IS: - A minimal seed runner (NOT "the whole compiler but worse"). - Consumes a stable canonical CorePackage (NOT arbitrary evolving surface syntax). - Stage0Contract declares: load CorePackage; understand stable Node/Core schema; run minimal fold_node/traverse; fail-closed diagnostics; emit verified artifact. This decoupling is the structural answer to v2's pain — surface language / parser / normalizer / lenses can all evolve without breaking stage0 because stage0 consumes the canonical package, not the surface. BOOTSTRAP EPOCH LOOP: - Stage0[k] + CorePackage[k] → Stage1[k] - Stage1[k] + SourceModels[k] → Stage1'[k] - verify(Stage1[k] == Stage1'[k]) → FixedPointWitness[k] - Upgrade k → k+1: ChangeSet + AffectedSet + RecomputePlan → Stage0Candidate + Stage1Candidate → verify → promote. Only the promotion protocol replaces the active stage0. No back edge anywhere else. THREE CASES for compiler-contract changes: 1. Normal downstream (no stage0 impact) — affected artifacts recomputed. 2. Bootstrap-compatible stage0 change — current compiler generates Stage0Candidate; verify; promote. No manual edit. 3. Bootstrap-breaking change — requires modeled Bridge[k → k+1] migration package, or fails closed with BootstrapBreak diagnostic. CRITICAL INVARIANT: "At no point does an artifact become source of truth merely because it is needed for bootstrapping." Generated stage0.rs / compiler.corepkg / generated compiler source / generated tests are NOT authorities — they're disposable artifacts with witnesses. The source of truth remains .dag models + Stage0Contract + CorePackageSchema + Projection definitions. CONCEPTUAL STACK (Layer 0-4): - Layer 0: Seed (stage0 executable, minimal, audited, consumes CorePackage) - Layer 1: Substrate models (.dag, source of truth) - Layer 2: Compiler models (.dag, source of truth) - Layer 3: Generated compiler artifacts (disposable, regeneratable) - Layer 4: Verification / promotion (procedural and conservative gatekeeper) Only Layer 0 is hand-seeded. Layers 1-2 are source of truth. Layer 3 is disposable. Layer 4 is the gatekeeper. TWO DISTINCT DEPENDENCY GRAPHS (must be separated): - Program dependency graph (P6) — Contains / BindsTo / TypeDependsOn / DataDependsOn / EffectDependsOn / ResourceDependsOn / ModuleDependsOn / BarrierBefore / PlacementConstraint. - Build / bootstrap dependency graph (new) — ModelDependsOn / ProjectionDependsOn / GeneratedFrom / VerifiedBy / PromotedBy / BootstrapDependsOn. Keeping them separate prevents the confusion "does the compiler's own resolver depend on the resolver it is resolving?" — answer: at epoch k, Stage0[k] resolves model[k] enough to build Stage1[k]. No active stage depends on its own output. NEW BOOTSTRAP SUBSTRATE (P9 implies these; not yet declared): - Stage0Contract, BootstrapEpoch - CorePackage, CorePackageSchema - Bridge (migration package for bootstrap-breaking changes) - BootstrapWitness, FixedPointWitness - PromotionPlan, PromotionDiagnostic / BootstrapBreak Likely lands in std/bootstrap.dag alongside P8's regeneration substrate (ChangeSet / AffectedSet / Projection / Artifact / RecomputePlan). WHAT THIS RULES OUT (STOP conditions for implementation workers): - Code letting stage0 directly edit itself at runtime. - A "bootstrap workaround" that hand-edits stage0 outside the candidate / promotion path. - A "we know this is safe" that skips fixed-point verification. - Generated-artifact files treated as authorities. UPDATED EXISTING SELF-MODIFICATION SECTION to cross-reference P9 and clarify that the "compiler edits itself" framing is loose; the precise mechanic is candidate generation + verification + promotion. GLOSSARY EXPANDED: Stage0Contract, CorePackage / CorePackageSchema, BootstrapEpoch, Bridge, BootstrapWitness / FixedPointWitness, promotion protocol. The "fractal feeling" of self-application is now resolved structurally: the pattern is stratified (Layer 0 → Layer 4), not infinitely recursive. Only the model layer is source of truth; the bootstrap layer is intentionally tiny; the promotion layer is procedural; the artifact layer is disposable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: V4 work * design: address 3 new BLOCKING codex findings on P8/P9 work Findings on commit b1cfdb8 (codex 2026-05-20T06:44:32Z): FINDING A (3271748181) — P2 boundary discipline: T-21 affected_set as specialization vs full AffectedSet undeclared = split regeneration authority. Fix: clarified in "Named regeneration substrate" section that these substrate concepts must land as a UNIFIED coherent declaration (std/regeneration.dag or tightly-related cluster), not piecemeal. T-21's affected_set must be MIGRATED into the unified AffectedSet — not left as a parallel concept (which would itself be a P2 violation). Implementation order updated: declare the regeneration substrate as a unit; migrate T-21 into the unified shape. FINDING B (3271748191) — P3 fail-closed: "fail-closed-or-default" wording in the language-model self-regeneration worked example allowed silent default acceptance of missing newly-required facts. Fix: removed "fail-closed-or-default". Replaced with explicit choice — either (a) a typed Default<T> witness declared as substrate data (modeled default, NOT implicit silent default), or (b) a fail-closed diagnostic. No silent default acceptance — per P3, missing newly-required facts produce typed witness OR diagnostic, never unsignalled default. FINDING C (3271748200) — P2 boundary discipline: stage0 self-compile path appeared to fold parse + normalize back into compile(...), contradicting the text/data separation where compile-core consumes CoreNode. Fix: rewrote the stage0-regeneration code block to show explicit ingest_text + compile composition. Compile-core takes CoreNode (data), never text. ingest_text is the separable boundary; compile is the pure data-in / data-out core. Added "Equivalent paths" note showing other ways to obtain CoreNode (already-cached, programmatic builder, query-driven rewrite) — all funnel through compile() taking CoreNode. The "no special regenerate stage0 mode" claim is preserved (stage0 regeneration is still compile(self_corenode, dag, TranslateTo(rust))) but the ingest boundary is now explicit and separable. v2's manual-patch failure mode is structurally precluded by the ratified text/data separation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: tighten I/O — no boundary actions; everything is modeled effects Operator-direct refinement: the "shim/modeling thing extends to reads/writes as well." The architecturally pure approach models files, file_system, shell, and OS independently in extdeps/; all I/O is modeled effects against modeled resources; compile-core has no boundary actions. CHANGES: 1. TL;DR boundary actions reframed: FROM: "Compile-core boundary actions: write output text (or execute), report diagnostics. Two actions; compile-core is otherwise pure data-in / data-out. Ingest-layer boundary actions (separable): read input text only when ingesting from a text source." TO: "Compile-core has no boundary actions. The compile core is purely data-in / data-out. All real-world I/O — reading source from disk, writing target source to disk, executing on a host, reporting diagnostics to stderr — is modeled as effects against modeled resources (extdeps/file_system.dag for files, extdeps/process.dag for shell/OS, extdeps/network.dag for network), composed by peripheral shims outside the compile-core surface." 2. End-to-end I/O section rewritten: - Removed ingest_text from the public substrate primitive signature. - Added explicit "Peripheral shims for text and file I/O" subsection showing the composition: file_read (modeled effect) + ingest_text (shim) + compile (pure) + file_write (modeled effect) — each step is its own substrate-modeled operation, NOT a compile-core boundary action. - Added "Why this matters architecturally" — no hidden side effects; dry-run works as composition; incremental rebuild works because every artifact's provenance is modeled; self-modification is safe because apply_diff is modeled, not implicit. - Slogan: "No implicit I/O. Files are not the architecture. Effects are modeled, not assumed." 3. Glossary added: - peripheral shim — user-facing convenience composing modeled effects with compile-core; NOT a substrate primitive. - modeled effect — real-world I/O declared as substrate data in extdeps/ carrying EffectDependsOn / ResourceDependsOn edges; visible to lenses; substitutable for dry-run. This sharpens P0 + P8 + P3-dry-run: there are no implicit side effects anywhere in the architecture. Files are orthogonal to the architecture; they're modeled in extdeps/file_system.dag, NOT load-bearing for compile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * design: tighten catamorphism/homomorphism/coercion terminology + MVP routes Four targeted tightenings before this wave of worker dispatch: 1. NEW "Terminology" subsection before P5: catamorphism / homomorphism / coercion are three terms at three levels (mechanism / noun / verb). The coercion fold is a catamorphism whose job is to verify a homomorphism. Translation IS the homomorphism (the noun); coercion is the verification verb. Doc passages conflating "coercion fold" with "homomorphism mechanic" generically are sloppy and should be flagged. 2. Coercion fold primitive description now names the TranslatePlan extension slot: conceptually TranslatePlan = ExactCoercion(source_grounding, target_node) | RewrittenThenCoerced(rewrite_witness, ...) MVP implements only ExactCoercion; future LawfulRewriteWitness (P7) lands the second variant without refactor. 3. Artifact carrier (in the regeneration substrate) now reserves bootstrap-related ArtifactKind variants up front: Stage0Candidate, CorePackage, WitnessBundle. Lets P9 bootstrap substrate land later without forcing artifact/projection refactor. 4. NEW "MVP routes — named explicitly" section before "What's NOT in scope": - Core MVP: compile-core homomorphism produces TargetSource from CoreNode - MVP-A (translate-only): Core MVP + file_system shim → file-to-file - MVP-B (eval-only): Core MVP + host_model + T-22 → Value Either MVP-A or MVP-B is sufficient as the first proof point; both together is the strongest exercise. The terminology section is the key piece — operator + reviewer were unclear on whether we were moving from coercion to homomorphism; the answer is they coexist at different levels and the doc should use them precisely. The other three are scope-reservation moves that prevent future refactor when held substrate (LawfulRewrite, bootstrap, multi-lens) eventually lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What this is
Encodes the side-session-ratified B-1 decision: the structural-delta
vocabulary over
Node(theDifftype thataffected_setconsumes,apply_diffproduces, and incremental eval / structural caching key on).This is a substrate addition to the immutable-header T-1 file, so the PR
is the operator-ratification vehicle (DECISIONS.md Part-5 flow).
Ratified (operator-decided in session)
Diff= a set ofEdits;Editreplaces the subtree at aPathwitha
Node(term-rewritingt[s]p).Path = List<EdgeSelector>(ByName/ByPosition, mirroringEdgeLabel). Flat & finite — NOT a new recursive type (A1:Nodestays the sole recursion). This eliminates the "structural edit-script
ADT" option outright.
Path(the route), notPosition(operator pick — aposition is a coordinate; a path is how you get there). "position /
occurrence" (JSON Pointer, RFC 6901) retained only as anchor citation.
Diff= pairwise-independent Paths (term-rewriting"parallel positions") ⇒
apply_diffis deterministic-total orfail-closed.
apply_diffconsumer = CLI / test harness / app code.Encoded in (4 files)
std/node.dagEdgeSelector/Path/Edit/Diffdecls + D1 header block (DATA ONLY)lens/application.dagsubterm_at/apply_diff/predicate I/O contract in header (T-23 fill)lens/affected_set.dagDiffis the consumed node.dag D1 typeDECISIONS.mdThe session ratified "homed in
std/node.dag". On encoding I hit aforcing constraint and split it, which needs your confirmation:
EdgeSelector/Path/Edit/Diff) →std/node.dag✅ (asratified; B1/
Hashprecedent — a structural delta overNodeissubstrate-tier).
subterm_at/apply_diff→Result<Node,Diagnostic>,paths_independent/diff_well_formed) →lens/application.dag, notnode.dag. Forced, not stylistic:
std/diagnostic.dagalreadyConsumes std/node.dag(Correction = Suggested(Node)), so a node.dagop returning
Result<_,Diagnostic>is a substrate cycle. This isexactly node.dag's existing "the root declares the structural data +
named invariant; CONSUMERS evaluate fail-closed" discipline (the
node_well_formedprecedent, node.dag ~L262).Also corrected vs the initial briefing: the briefing said "owner = T-21"
and "
Pathis K-1-exempt like the diagnostics renderer." Both wrong —single-authority puts the type in node.dag (not a lens), and Path
resolution needs only
Symbolequality (K-1 grants that) so it isK-1-clean, no exemption.
Status
Draft. Operator ratifies (confirm the data/op split) + merges per current
manual-merge policy. No code bodies added — node.dag gets inert data
decls; application.dag/affected_set.dag are scaffold (header contracts
only, bodies are T-23/T-21).