diff --git a/docs/known-gaps.md b/docs/known-gaps.md index 1b1fbacb8..e097dc815 100644 --- a/docs/known-gaps.md +++ b/docs/known-gaps.md @@ -30,7 +30,7 @@ | Severity | Open | |---|---| -| HIGH | 76 | +| HIGH | 77 | | MED | 204 | | LOW | 87 | | Nominal (spec-ahead-of-impl) | 7 | @@ -53,6 +53,11 @@ + + +### g-tilde-lin-enforcement-does-not-fire-on-spec-own-examples — §32's `~` exactly-once (`lin`) enforcement produces **ZERO diagnostics on SPEC's own worked examples**. **PA-MEASURED ON MERGED MAIN — six probes, all exit 0, all zero `E-TILDE`:** §32.5's verbatim `${ process(~) }` (spec'd `E-TILDE-001`) · `~` read with no initialization at all · a double-initialization with no consumption between (spec'd `E-TILDE-002` per §32.3) · an initialization never consumed before scope exit (also spec'd `E-TILDE-002`) · a double-init inside a function body · §17.6.6's partial-`if` example (`if (cond) { lift a }` then `const dbl = ~ * 2`, which §17.6.6 says the compiler **SHALL** emit `E-TILDE-001` for). ⛑ **NOT from absence, which is why this is filed as a defect rather than as spec-ahead:** `TildeTracker` (`type-system.ts:18380`), `MustUseTracker`, `checkLinear` and BOTH codes exist with real user-facing messages, and `checkLinear` is invoked **unconditionally** at file level (`:24470`, gated only on `allLinNodes.length > 0`). The pass runs and does not fire on the documented shapes. ⛑ **CAUSE NOT TRACED — stated as an observation, not a diagnosis.** `hasNonLiftTildeConsumer` gates only loop-body elision (`:18956`) and one site at `:19549`, not the pass as a whole, so the obvious gate is NOT the explanation; whether `~` reaches the tracker as a `tilde-ref` node in these shapes was not established. **A fix must start by tracing that, not by assuming the pass is unimplemented.** ⛑ **WHY IT MATTERS BEYOND THE MISSING DIAGNOSTICS:** this silence is what let §17.6.2 and §32.2 contradict each other unnoticed — §17.6.2 says a bare call in an if-as-expression arm is a side effect, §32.2 says an unassigned expression statement SHALL initialize `~`, and with §32.3 that shape should have been a hard `E-TILDE-002` for as long as both sentences have coexisted. Nobody saw it because nothing enforced it. **This is the S322 re-examination test in its purest form:** a normative SHALL delivered by a tracker pass that scans for states — RETROFIT, not by construction — and the predicted hole duly appeared. Composes with **dpa-040** (should an arm body be a `~` boundary?), whose phase 1 is required to re-verify this by execution before reasoning from it. — `NEW S395-bryan (surfaced while reading §32 in full for the `~` ruling; six probes PA-executed on merged main)`; **HIGH**; open + + ### g-same-named-branch-declarations-bind-to-the-last-definition — two sibling `if=`/`else` branches declaring the SAME function name emit BOTH definitions but bind **every** call site to the LAST one, with zero diagnostics. Surfaced by the S239 pass on #818 and **PA-verified PRE-EXISTING, not introduced**: on merged main two *lone* `if=` divs each declaring `dup()` already emit `_scrml_dup_7` + `_scrml_dup_8` and route the calls to the last definition (measured 1 call to the first, 5 to the second). #818 brings the collapsed-chain shape to PARITY with that lone-`if=` oracle, which is its stated goal — so the chain now inherits the oracle's own defect rather than introducing one. ⛑ **The direction of the change at this shape is loud→silent**, and that is why it is filed rather than shrugged at: on base the chain produced a `ReferenceError` (nothing was defined at all); it now returns the WRONG branch's value silently. In the `server fn` / plain `function` mix the `if`-arm's call binds to the else-arm's CLIENT function while the emitted route goes unreferenced — a live POST endpoint with no caller. **No server body leaked in any duplicate-name shape tested** (`SERVER-SECRET` never reached `client.js`), so this is a correctness defect, not a confidentiality one. The real question underneath is whether a branch body is its own DECLARATION SCOPE — the same scoping question `g-if-chain-all-arms-run-at-module-init` asks about `${}` bodies, and it should be ruled once for both rather than twice. — `NEW S395-bryan (S239 finding on #818; PA-verified pre-existing on the lone-if= oracle)`; **MED**; open diff --git a/handOffs/delta-log.md b/handOffs/delta-log.md index c1e375757..7efc0bd74 100644 --- a/handOffs/delta-log.md +++ b/handOffs/delta-log.md @@ -3262,3 +3262,8 @@ flagged `(deputy)`, observation-only, recording an agent that landed while the P [2035] find · **(S396-peter) E-ROUTE-004 HAS AN UNTYPED-PARAM HOLE — dog-fooded flogenceP, root-caused end-to-end, filed + routed.** flogenceP compiles clean on HEAD (21 files, 94 routes, 1 WS channel, validate-emit) + boots clean (server + MCP 11 tools); all 92 server-fns swept, every 500 triaged to app-level (empty-args / schema-init-order — e.g. `edit_mode` created by digest-tool not app's ensureSchema, init-order-dependent = flogenceP app bug), ZERO codegen-signature errors. The ONE scrml find: `checkRouteWireSerializability` (`type-system.ts:4734`) `continue`s on un-annotated params ("un-annotated param defaults asIs → allow"), so a server-boundary fn with an untyped-but-CALLED function param escapes E-ROUTE-004 and is routed as a **silent dead-500 endpoint**. Manifested on `runGatedAgentic` (untyped `run`, POST→500 `run is not a function`); import-only by intent so blast-radius LOW + pre-existing. **Two-sided minimal repro, runtime-confirmed:** `function f(cb){?{}…return cb(rows)}` (untyped) → exit 0 + dead route → POST 500; `function f(cb: () -> number)` (typed) → E-ROUTE-004 fires. Filed `g-route-004-untyped-fn-param-escapes-serializability-gate` (MED, open) + routed to bryan (the `continue` is deliberate — asIs hatch — so the fix is a normative fork: usage-based signal / require annotation / warn). ⚑ I STOPPED SHORT before routing (invoked "bryan's lane" to avoid reading his files) — Peter pushed, and READING for diagnosis ≠ EDITING; then I root-caused to the exact line. [[be-the-authority-root-cause-dont-hand-wave]]. [2036] state · **(S396-peter) WRAP.** Dog-food + adopter-ops session; NO compiler `src` touched (no FACTS/state code regen owed; maps unchanged). Landed: aM pin bumped + `g-route-004` filed (`state.ts` regen MED 203→204) + routed to bryan. Also flipped `~/.claude/settings.json` `blockReadsOutsideWorkingDirectories`→false (Peter's ask; needs restart/`/add-dir`); BLOCKED by the auto-mode classifier from self-editing permission config (dir-adds are Peter's own `/add-dir`). Continuity rides a light PR off `8f3c5b74`: this delta-log [2033]-[2036] + changelog S396 + the S396 hand-off PICKUP (bryan's S393/S395 owed-queue reconciled — S395 closures removed, the "inverted ruling" + value-form-null struck as resolved, the #818 security gap struck as closed). Pre-existing agent worktrees retained (not this session's). Gaps HIGH 76 · MED 204 · LOW 87. +[2037] state · **(S395-bryan) THE `~` RULING — limb (a), and it exposed that SPEC answers the question TWICE.** bryan: *"lets look at ~"* then *"your rec"*. **RATIFIED: §17.6.2 governs an if-as-expression arm body** — a bare expression statement inside an arm is a SIDE EFFECT; it does not initialize `~`, does not rebind the tilde context, does not touch the arm's result; only `lift` or the §17.6.10 sugar designates it. Per S276/S130 the terse ratification adopted the FULL text — *"(a) now, with (c) named as the question behind it"* — so **limb (c) is banked, not closed** (dpa-040). The reading found **§17.6.2 and §32.2 in direct conflict**: §32.2's *"an expression statement whose value is not bound SHALL initialize `~`"* plus §32.3's exactly-once rule makes `{ note("a") lift "pos" }` an `E-TILDE-002`, while §17.6.2 calls the same statement a side effect. **The compiler implements NEITHER** — it mints a fresh tilde and rebinds the context, so the `lift` writes the wrong var and the binding is silently null. Arc dispatched: codegen fix + the SPEC reconciliation it owes (§32.2 arm-body carve-out + reciprocal cross-ref + Rule 4b provenance), same arc, with a warning that #802's reconciliation surface turned out to be 3× what its ruling named. + +[2038] find · ⚑ **(S395-bryan) §32's `~` ENFORCEMENT DOES NOT FIRE — AND THAT SILENCE IS WHY THE CONTRADICTION SURVIVED.** Six probes on merged main, all exit 0 with ZERO `E-TILDE`: SPEC §32.5's own verbatim `${ process(~) }`, `~` read with no init, double-init without consumption, init-never-consumed-at-scope-exit, double-init in a function body, and §17.6.6's partial-`if` example that SPEC says the compiler **SHALL** diagnose. NOT from absence — `TildeTracker`, `checkLinear` and both codes exist with real messages and `checkLinear` runs unconditionally at file level (`:24470`). **Cause NOT traced and the entry says so**; `hasNonLiftTildeConsumer` gates only loop-body elision, so the obvious explanation is ruled out but no replacement is offered. Filed HIGH as `g-tilde-lin-enforcement-does-not-fire-on-spec-own-examples`. **The S322 test in its purest form:** a normative SHALL delivered by a state-scanning tracker — retrofit, not by construction — and the predicted hole appeared. + +[2039] friction · ⚑ **(S395-bryan) I BANKED dpa-040 IN A FORM THE PROBE COULD NOT READ, AND CAUGHT IT ONLY BY RUNNING THE PROBE.** Wrote the full `## [dpa-040]` section into `dpa-queue.md` — the right FILE, per the S319 drain-path rule — and `dpa-debt.ts` still reported **39 items / 2 UNRUN**. The probe reads the **status TABLE**, not the per-item sections; `scripts/dpa-debt.ts`'s own header says reading the per-item `status:` lines instead *"would reproduce the exact obligation/probe mismatch this file exists to close."* Adding the table row moved it to **40 / 3 UNRUN**. **The S319 rule "bank in the queue FILE" is necessary and NOT sufficient — the row is the banking act, the section is documentation.** Same base §10 class as everything else this session, self-inflicted, and caught only because the probe was run rather than assumed. [[feedback_the_probe_answered_a_different_question]] diff --git a/handOffs/dpa-queue.md b/handOffs/dpa-queue.md index 6c5d9ac31..71c06e9b5 100644 --- a/handOffs/dpa-queue.md +++ b/handOffs/dpa-queue.md @@ -58,6 +58,7 @@ Item format + drain protocol: `scrml-support/dpa-scrml.md` + the design DD | dpa-035 | **COMPLETE (ADVISORY) dPA 2026-08-19 — awaiting PA/bryan ratification.** ★★ **THE QUESTION IS ASKED AGAINST THE WRONG LEDGER — the "16 KB budget" is the assembled SPA *RUNTIME* gzip budget** (`g-spa-runtime-gzip-budget-knife-edge`, 16,257/16,384 B, **127 B margin**, open HIGH with a live hold-vs-raise fork, asserted at `v0-3-x-spa-tree-shake-phase-b.test.js:145`) — **NOT an app-payload budget.** Above-the-fold partitions APP markup; the app budget is a separate SOFT `W-CG-CHUNK-LARGE` at 100,000 B sitting at **2.4% utilisation**. Fold-preferencing therefore **cannot relieve the budget that motivated the question**, and the mechanism to realise it is paid for OUT of the constrained ledger. ★★ **The bank's load-bearing claim is CONFIRMED by execution** (a 4-arm `` ships all 3 non-initial arm bodies into the initial client chunk) — **but the half the bank did not state is decisive: arms are DEFINED, not MOUNTED** (absent from HTML; no DOM, listeners or subscriptions). ⚑ **I CORRECTED MY OWN CEILING 19x MID-DELIBERATION** — trivial arms gave 37 B gz, heavy dissimilar arms (form/table/error-panel) give **2,659 B raw / 689 B gz = 28.4% of the app chunk but 2.40% of payload**; three poles had already reasoned from 37 B and **all three were re-polled against it and all three moved**. ★★ **THE ARITHMETIC THAT DECIDES IT (source-verified):** there is **no component-tiering machinery to extend** (`reachability-solver.ts:434-454` — component/cell/vendor tier sets are `new Set()`, literally empty; the tier axis carries server-fn ids ONLY, so this builds the FIRST component tier) · deferring arms **inverts a normative SHALL** (worst-case union, *"under-inclusion is the disallowed failure mode"*, `SPEC.md:22980`) → a §40.9 amendment, **120-220h** · and **no executing loader exists** (`_scrml_fetch_chunk` returns chunk TEXT, never evaluates) so one costs **400-900 B gzip of RUNTIME to save 689 B of APP** — *spend the ledger with 127 B of margin to relieve the one that is 97.6% unused.* ★ **§65 critical-CSS claim REFUTED by execution** — `#{}` emits verbatim into one global `@layer global`; a class used **nowhere at all** still ships (no dead-rule elimination, no per-arm partition). ★ **HTML byte pool = ZERO** (heavy vs empty arm HTML both 603 B, no `