Context
Third leaf of Epic #12986 (the vdom delta-stream contract). The kernel (#12987, PR #12988) ships the vocabulary and the U1–U4 universal predicates as pure functions — consumed by nothing at runtime yet. This leaf wires them at the enforcement boundary the #12942 OQ3 resolution fixed: Main-thread pre-apply, where the final batch truth lives (post any listener mutation), validated before the first delta applies.
Release classification: post-release (contract-layer substrate).
The Problem
Today a grammatically illegal batch fails in one of three accidental modes (insertNode console.errors, replaceChild can natively throw, everything else silently no-ops), and the worst mode is structural: an unknown action throws mid-loop, leaving every delta before it applied — the DOM now diverges from the worker's vnode model, which is precisely how stale-baseline defects are born (src/Main.mjs:325-346 contains the throw per-operation but cannot un-apply the prefix). Defects of the #12930/#12939 family rot latent because nothing screams at birth.
The Architectural Reality
- The enforcement point:
src/main/DeltaUpdates.mjs#update() — normalizes the batch, fires the mutable pre-apply update event (:890-895), then loops. Guard placement is AFTER the event (final truth, post-mutation) and BEFORE the loop's first dispatch — converting partial-apply+reject into no-apply+reject. The existing processQueue containment then rejects the operation's promise loudly: the failure surface already exists, the guard just moves the failure earlier and makes it whole-batch-atomic.
- The kernel consumption:
validateBatch(deltas, {useDomApiRenderer}) from src/vdom/util/DeltaGrammar.mjs (cross-realm import precedent: DeltaUpdates.mjs:4 already imports vdom/domConstants.mjs).
- Config precedent: dev-mode levers live in
src/DefaultConfig.mjs (logDeltaUpdates, renderCountDeltas, useDomApiRenderer — the renderer flag the guard must pass through to U2).
- U5 falsification corpus:
checkStructuralUniqueness (kernel, candidate: true) needs a real-world run before any promotion — the unit suite's delta-emitting specs plus example-app interaction flows are the corpus; the #12942 Step-Back binds U5-as-candidate-until-falsified.
The Fix
useDeltaGrammarGuards config (new, src/DefaultConfig.mjs, default false): dev/test-only lever, same family as logDeltaUpdates.
- Guard wiring in
DeltaUpdates.update(): when enabled, run validateBatch after the pre-apply event, before the dispatch loop. On findings: console.error the structured findings (full batch context) and throw before any delta applies — the existing per-operation containment converts that into a rejected caller promise; no delta of an illegal batch reaches the DOM.
- U5 falsification run: with guards enabled in observe-mode for U5 (log-only, never throw), execute the delta-emitting unit-spec corpus + a portal/grid example interaction pass; document every U5 finding (or the absence) in the PR. Promotion decision recorded explicitly (promote into the default rule set / keep candidate with the blocking evidence cited) — the run's outcome, not a default.
- Unit spec: guard disabled = zero behavior change (the default path untouched); guard enabled = illegal batch rejects atomically (DOM untouched — assert no partial application), legal batches pass through unchanged; the renderer flag reaches U2.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
Neo.config.useDeltaGrammarGuards (NEW) |
src/DefaultConfig.mjs dev-lever family (logDeltaUpdates: sibling) |
Boolean, default false; enables atomic pre-apply batch validation in dev/test |
false = today's behavior byte-for-byte |
DefaultConfig JSDoc block |
Sibling levers verified at DefaultConfig.mjs (logDeltaUpdates, renderCountDeltas) |
src/main/DeltaUpdates.mjs#update() (EXISTING, modified) |
Source :879-943 |
Guarded branch after the pre-apply event, before the dispatch loop; throw-before-first-apply on findings |
Config off = no new code path executes |
Method JSDoc |
Census DC_kwDODSospM4BB6bh §A/§E; containment Main.mjs:325-346 |
src/vdom/util/DeltaGrammar.mjs (EXISTING #12987 — consumed) |
Kernel exports |
validateBatch + (observe-mode) checkStructuralUniqueness; never re-implemented |
n/a |
n/a |
Kernel PR #12988 (this leaf is blocked-by #12987) |
Decision Record impact: none (aligned with the #12942-graduated epic shape; no ADR governs the boundary).
Acceptance Criteria
Out of Scope
- The stateful coherence registry (cross-batch rules — its own leaf; this leaf is per-batch only).
- Production-mode always-on guards (dev/test lever by design).
- Capture API (#12991) and signature shape-classes (OQ2 leaf).
- Any change to the kernel's predicate semantics (drift goes back to #12987's contract, not silently patched here).
Avoided Traps
- Guarding before the pre-apply event — would validate a batch listeners may still mutate; the OQ3 two-layer resolution places enforcement at final truth.
- Throwing per-delta inside the loop — recreates partial application; the entire point is whole-batch atomicity.
- U5 enforce-by-default — the Step-Back carry-through; promotion only on falsification evidence.
- Swallowing findings into a boolean — the structured findings are the diagnostic product; a bare reject would re-create silent-failure with extra steps.
Related
Epic #12986 (parent). Blocked-by #12987 (consumes the kernel). Census: #12942 comment DC_kwDODSospM4BB6bh (§A atomicity, §E placement). Siblings: #12991 (capture), OQ2/OQ4/OQ5 leaves to come.
Live latest-open sweep: checked latest 12 open issues at 2026-06-12T12:35Z; no equivalent found. A2A in-flight sweep: clean (recent traffic = the #12988/#12989 review cycle + my own epic broadcasts).
Origin Session ID: 3e1566f6-6336-4db4-8726-189004578d8b
Retrieval Hint: "delta grammar guards atomic pre-apply useDeltaGrammarGuards U5 falsification promotion"
Context
Third leaf of Epic #12986 (the vdom delta-stream contract). The kernel (#12987, PR
#12988) ships the vocabulary and the U1–U4 universal predicates as pure functions — consumed by nothing at runtime yet. This leaf wires them at the enforcement boundary the#12942OQ3 resolution fixed: Main-thread pre-apply, where the final batch truth lives (post any listener mutation), validated before the first delta applies.Release classification:post-release (contract-layer substrate).The Problem
Today a grammatically illegal batch fails in one of three accidental modes (insertNode
console.errors, replaceChild can natively throw, everything else silently no-ops), and the worst mode is structural: an unknown action throws mid-loop, leaving every delta before it applied — the DOM now diverges from the worker's vnode model, which is precisely how stale-baseline defects are born (src/Main.mjs:325-346contains the throw per-operation but cannot un-apply the prefix). Defects of the#12930/#12939family rot latent because nothing screams at birth.The Architectural Reality
src/main/DeltaUpdates.mjs#update()— normalizes the batch, fires the mutable pre-applyupdateevent (:890-895), then loops. Guard placement is AFTER the event (final truth, post-mutation) and BEFORE the loop's first dispatch — converting partial-apply+reject into no-apply+reject. The existingprocessQueuecontainment then rejects the operation's promise loudly: the failure surface already exists, the guard just moves the failure earlier and makes it whole-batch-atomic.validateBatch(deltas, {useDomApiRenderer})fromsrc/vdom/util/DeltaGrammar.mjs(cross-realm import precedent:DeltaUpdates.mjs:4already importsvdom/domConstants.mjs).src/DefaultConfig.mjs(logDeltaUpdates,renderCountDeltas,useDomApiRenderer— the renderer flag the guard must pass through to U2).checkStructuralUniqueness(kernel,candidate: true) needs a real-world run before any promotion — the unit suite's delta-emitting specs plus example-app interaction flows are the corpus; the#12942Step-Back binds U5-as-candidate-until-falsified.The Fix
useDeltaGrammarGuardsconfig (new,src/DefaultConfig.mjs, defaultfalse): dev/test-only lever, same family aslogDeltaUpdates.DeltaUpdates.update(): when enabled, runvalidateBatchafter the pre-apply event, before the dispatch loop. On findings:console.errorthe structured findings (full batch context) and throw before any delta applies — the existing per-operation containment converts that into a rejected caller promise; no delta of an illegal batch reaches the DOM.Contract Ledger Matrix
Neo.config.useDeltaGrammarGuards(NEW)src/DefaultConfig.mjsdev-lever family (logDeltaUpdates:sibling)false; enables atomic pre-apply batch validation in dev/testfalse= today's behavior byte-for-byteDefaultConfig.mjs(logDeltaUpdates,renderCountDeltas)src/main/DeltaUpdates.mjs#update()(EXISTING, modified):879-943DC_kwDODSospM4BB6bh§A/§E; containmentMain.mjs:325-346src/vdom/util/DeltaGrammar.mjs(EXISTING #12987 — consumed)validateBatch+ (observe-mode)checkStructuralUniqueness; never re-implemented#12988(this leaf is blocked-by #12987)Decision Record impact:none (aligned with the #12942-graduated epic shape; no ADR governs the boundary).Acceptance Criteria
useDeltaGrammarGuards: false(default): byte-for-byte unchanged behavior — no validation executes, no perf cost beyond one config read.useDomApiRendereris forwarded to U2 (pinned-renderer payload contract enforced correctly per mode).{rule, deltaIndex, detail}+ batch context) — diagnosable without a debugger.Out of Scope
Avoided Traps
Related
Epic #12986 (parent). Blocked-by #12987 (consumes the kernel). Census:
#12942commentDC_kwDODSospM4BB6bh(§A atomicity, §E placement). Siblings: #12991 (capture), OQ2/OQ4/OQ5 leaves to come.Live latest-open sweep: checked latest 12 open issues at 2026-06-12T12:35Z; no equivalent found. A2A in-flight sweep: clean (recent traffic = the #12988/#12989 review cycle + my own epic broadcasts).
Origin Session ID: 3e1566f6-6336-4db4-8726-189004578d8b
Retrieval Hint: "delta grammar guards atomic pre-apply useDeltaGrammarGuards U5 falsification promotion"