continuity(S395): the ~ ruling banked — limb (c) queued where the probe can see it, and the enforcement that should have caught the contradiction - #820
Merged
Conversation
…robe can see it, and the enforcement that should have caught the contradiction
THE RULING (bryan, user-voice S395: "lets look at ~" then "your rec"). Limb (a) 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 it answered — "(a) now, with (c) named as the
question behind it" — so limb (c) is BANKED, NOT CLOSED.
WHAT THE READING FOUND. §17.6.2 and §32.2 are in direct conflict about the same three
lines. §32.2 — "an expression statement whose value is not bound to any identifier SHALL
initialize `~`" — plus §32.3's exactly-once rule makes `{ note("a") lift "pos" }` an
E-TILDE-002. §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
variable and the binding is silently null. The fix arc is dispatched and owes BOTH halves
— codegen AND the §32.2 arm-body carve-out with a Rule 4b provenance line, in the same
arc, because a codegen-only landing leaves the contradiction standing in the text.
⚑ NEW HIGH — g-tilde-lin-enforcement-does-not-fire-on-spec-own-examples. Six probes on
merged main, all exit 0, all ZERO E-TILDE: §32.5's 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 rather than guessing: hasNonLiftTildeConsumer gates only
loop-body elision, so the obvious explanation is ruled out without a replacement offered.
That silence is the point. It is why two normative sections could contradict each other
for as long as both have existed without anyone noticing — and it is the S322
re-examination test in its purest form: a normative SHALL delivered by a state-scanning
tracker pass, retrofit rather than by construction, producing exactly the hole that
predicts.
⚑ AND I BANKED dpa-040 IN A FORM THE PROBE COULD NOT READ. I 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; the script'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.
Self-inflicted, same base §10 class as the rest of this session, and caught only because
the probe was RUN rather than assumed.
dpa-040 asks whether an arm body should be a `~` CONTEXT BOUNDARY in its own right (§32.4,
beside `${}` contexts and function bodies) — under which the conflict cannot recur by
construction rather than by carve-out. Constraints recorded so the DD cannot drift:
`~`-as-lin is NOT on the table (the boundary SET is the question); adding a boundary is the
LIMIT direction but is semantics-changed and owes a MEASURED migration; and corpus-zero is
blast radius ONLY, never demand evidence (bryan, S346).
bryanmaclee
force-pushed
the
continuity/s395-tilde-ruling
branch
from
September 2, 2026 20:33
4bd0e7a to
e39b980
Compare
…-[2035] concurrently The cloud `gate` caught this, not me: step 14, the delta-log sequence gate. S396-peter's #821 and this branch independently appended [2033]-[2035] while both sessions were live, and a rebase does not reconcile sequence numbers — it just stacks both. ⚑ WHY A DUPLICATE IS NOT COSMETIC: the flogence bridge uses the sequence as a CHECKPOINT CURSOR, so the second entry to merge is skipped as already-absorbed and DROPS OUT of the digest entirely. A silent single-entry loss, invisible on both sides. `delta-lint --fix` renumbers later occurrences in file order — and its own warning is the load-bearing part: "check by hand that the renumbered side is YOURS — renumbering an entry another repo has already checkpointed drops it from THAT repo's digest." Checked: peter's #821 is already MERGED and therefore published, so his [2033]/[2035]/[2036] keep their numbers and mine moved to [2037]+. The renumbered side is the unpublished one. Correct. Gate now PASS — 1746 entries, 1737 distinct, max [2039]; the 9 baselined historical duplicates are unchanged known debt.
bryanmaclee
added a commit
that referenced
this pull request
Sep 3, 2026
…at `/` — one gated path now, not two (#823) * fix(§52.13): `scrml dev` served a protected document unauthenticated at `/` — one gated path now, not two Closes g-dev-root-path-fallback-serves-a-protected-document-unauthenticated (HIGH, security). Ruling 2b (bryan, user-voice S395 "your recs"): limb (b). Ruling to SPLIT the §52.13 case variant into its own arc (bryan, "your rec"). THE LEAK. `scrml dev` served an auth="required" document's rendered content to an unauthenticated `GET /` whenever the protected document was not named index.html. PA-reproduced two-sided: entry secure.scrml → `GET /` 200 with SECRET DASHBOARD in the body; entry index.scrml (the control) → 302 both before and after. The leak reproduced on BOTH root-resolution paths — the single-input entry candidate and the sorted-readdir scan. THE FIX IS A DELETION. `registeredProtectedDocs` was read at exactly one place, inside the gated candidate loop; the `pathname === "/"` branch sat AFTER that loop and returned HTML from two paths, neither consulting the gate. dev.js:1027 ALREADY folded `/`→/index.html into the loop's candidates (which is why the index.scrml control gated correctly), so the defect was an ADDITIONAL ungated branch, not a missing fold. Deleted it; `/`'s candidates moved into the one gated loop. Two serving paths → one. Net on compiler/src: +94/-61. ⚑ WHAT WAS MEASURED AND THEN NOT SHIPPED. Literal deletion of the root candidates took `scrml dev app.scrml` from 200 to 404 at `/` — and `/` is the ONLY URL dev prints — while stranding resolveRootEntryCandidate as dead code still covered by its own tests. Per the brief's STOP clause the agent measured, refused, and reported instead of shipping it. ⚑ AND WHAT WAS SPLIT BACK OUT, RULED. Making §52.13's case variant filesystem-independent requires gating on the REQUEST PATH — necessarily a SECOND place that decides protection, because it cannot know what the resolution loop would pick. Three adversarial rounds found three distinct divergences (answering for absent documents; hijacking a request the loop would serve publicly; ignoring candidate resolution priority), each fix converging the pre-gate toward BEING the loop. That reintroduced the exact shape ruling 2b chose limb (b) to remove — FORK RULE row 4, "(b) removes a second code path". bryan ruled SPLIT. The pre-gate is gone, mustExistIn and the {guard, rel} registry value went with it, and the JSDoc at :214 became true again by reversion rather than by editing. ⚑ THE SPLIT CLOSED A DEV/PROD DIVERGENCE RATHER THAN OPENING ONE, which is stronger than the ruling claimed: build.js:541 also gates on relative(SERVE_DIR, candidate).toLowerCase() — the resolved file, not the request path. Dev now matches prod's model exactly. VERIFICATION. - Two-sided leak control, PA-run by executing the new tests against base dev.js: `GET /` leaked=TRUE at base, 302 on the fix. Not asserted — executed. - Structural guard PA-verified to BITE: module-wide (so extracting serving into a helper cannot make it vacuous), expects exactly 2 `return new Response(injectHotReloadScript(` sites with the reason stated for each, and reports "expected 2, received 4" against main. - commands suite 256 pass / 0 fail — the suite that runs in NO blocking job on any platform, which is precisely how a §52.13 assertion sat silently RED on Linux for months. Full suite vs base: one removed, zero added; the removed entry is that assertion. - 9-scenario root-path ordering byte-identical; prod entry re-emitted byte-identical; compiler/src diff vs origin/main is dev.js alone. ⚑ A HAZARD IN THE PA'S OWN INSTRUCTION, CAUGHT BY THE AGENT. I directed `test.failing` on the knowingly-red case-variant test. `.failing` passes when the body fails for ANY reason, so that would have MASKED A LEAK: if `/SECURE.html` ever returned the markup, `expect(leaked).toBe(false)` fails and `.failing` swallows it as expected. Split instead into a HARD test asserting the platform-invariant half (never leaks, whatever status) and a `.failing` test carrying only the genuinely-unruled STATUS. The durable form, recorded: a mechanism that makes a red acceptable also makes a red invisible — every time you suppress a signal, check what else was riding on it. FILED, NOT FIXED — a new HIGH, PA-verified byte-identical on origin/main so pre-existing: loadServerRoutes catches an import() failure with console.error + continue, so a .server.js that fails at module-init never registers its guard and the auth="required" document is then served IN FULL, unauthenticated (agent-reproduced twice: an appended throw, and a duplicate-declaration syntax error). This falsifies "fail-open is gone by construction"; the invariant is narrowed to "every path that RESOLVES a serve-dir document passes the gate". Fix direction recorded: fail CLOSED on a module-load error — "unknown" must not resolve to "public". Base-drift filtered: the agent's branch predates #820/#822, so a wholesale pull would have reverted docs/changes/s395-runanchored-continue/, known-gaps.md, delta-log.md and dpa-queue.md. Verified 0 such paths staged. provenance: ruling:user-voice-scrml.md S395 — "your recs" (limb b) + "your rec" (the split) Agent branch: worktree-agent-a21f5afd26f7c6d3c @ 7c1fbf86 * chore(facts): regen after the dev-root auth-gate landing
bryanmaclee
added a commit
that referenced
this pull request
Sep 3, 2026
…reen while wrong (#824) Ran concurrently with S396-peter throughout. Five rulings given, four code arcs landed, the review floor drained twice to zero, maps refreshed. ONE ARC HELD on a ruling, worktree retained. ⚑ THE SESSION'S REAL OUTPUT IS NOT THE LANDINGS. Nine separate checks read green or authoritative while being wrong, and every one was caught by RUNNING something rather than by remembering. Three were my own claims. TWO WERE CAUGHT BY GATES I DID NOT WRITE. Three were agents' own instruments, found by those agents. RULINGS · the trailing-`else` question — direction stands, and the reported "inverted ruling" was MY OWN mis-description: §17.6.4 has always said a missing `else` is valid. I relayed a hand-off's framing into the boot report without opening the section. · the `~` arm-body question — limb (a) ratified, limb (c) BANKED as dpa-040, not closed. · 2a / 2b / 2c — the runAnchored fix (sequenced), the dev-root auth gate (limb b), and the tracking-job sequence with its first step folded in. · SPLIT the dev-auth arc when its §52.13 half turned out to require a second decider. LANDED #815 the §17.6.2 value-form sugar binds its result at a binding site — it bound null forever. #818 a branch-declared function is ROUTED before it is COLLECTED; closing the client half alone put a `server fn` BODY into client.js. #822 18 conformance assertions read as coverage and checked nothing. ⚑ MY BRIEF WAS WRONG — a naive `continue` deletion would have reddened 62 count:0 ABSENCE assertions — and the agent deviated with a stated reason. Only 2 of the 18 were covered elsewhere; 16 were entirely unguarded. #823 `scrml dev` served a protected document unauthenticated at `/`. The fix is a DELETION: two serving paths become one. #816 #819 #820 continuity + filings; #817 the overdue wrap-6c maps refresh, which corrected three premises in my own concurrently-dispatched brief. ⚑ HELD, NOT LANDED — the `~` build, worktree RETAINED at agent-ac264a1015c0da19d @ c2ad6f49. Four fix rounds, four adversarial passes, 7 SPEC loci reconciled. Blocked on bryan's revert-vs-press-on for the READ half, whose widening PA-verifiably DELETES A DOM LIFT (base emits _scrml_lift/createTextNode, the branch pushes into a dead array, exit 0). Resume the agent; do not re-dispatch. FINDINGS WORTH CARRYING · SUPPRESSING A SIGNAL SUPPRESSES WHATEVER RODE ON IT — three instances, one of them my own instruction. The `tracking` job's routine red concealed a REAL §52.13 assertion failing on Linux (compiler/tests/commands/ runs in NO blocking job on any platform). A knowingly-red assertion placed FIRST in a test turned the four after it into dead code that still read as coverage. And I instructed `test.failing` on that test — which passes when the body fails for ANY reason, so it would have MASKED A LEAK. The agent's formulation is the keeper: a mechanism that makes a red acceptable also makes a red invisible. · A FIX THAT NEEDS A SECOND DECIDER IS THE FORK RULE SAYING NO. Three rounds found three distinct divergences between the dev pre-gate and the resolution loop; the split then CLOSED a dev/prod divergence rather than opening one. · A REVIEW FINDING WAS FALSIFIED RATHER THAN FILED — the first time this session verification prevented a FABRICATED finding instead of catching a missed one. The corpus IS gated; corpus-bridge.test.js reaches it from inside the gated root. · TWO SHARED-DOC CONCURRENCY HAZARDS, both caught by machinery: conflicting @generated gap counts (resolved by regenerating from the merged population — the union, not a pick), and duplicate delta-log sequence numbers with peter (caught by the cloud gate's step 14; a duplicate makes the flogence bridge DROP the second entry from the digest). · BASE-DRIFT nearly reverted landed work FOUR times. · EVERY ONE of the five agent deviations from my instructions this session was correct. WRAP STEPS: hand-off rewritten (S396-peter's rotated to handOffs/hand-off-282.md, his live items carried) · changelog block · delta-log [2040]-[2045], sequence gate PASS · review floor 6 OWED -> 0 · inbox: TWO items deliberately left unarchived because both await bryan (the E-ROUTE-004 fork and the ~11-day-old FSP Initialize deliberation), both summarised in the hand-off · suite 30945 pass / 54 fail — ONE FEWER than base, the §52.13 assertion · worktrees: four landed swept, one retained · maps refreshed to 2d8dd8c, watermark verified via state.ts not by reading the file · @generated + facts gates PASS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Continuity-only — no compiler source touched. The fix arc itself is dispatched separately.
The ruling
bryan, user-voice S395 — "lets look at ~" then "your rec". Limb (a) 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; onlyliftor the §17.6.10 sugar designates it.Per the S276/S130 durable the terse ratification adopted the full text it answered — "(a) now, with (c) named as the question behind it" — so limb (c) is banked, not closed.
What the reading found
§17.6.2 and §32.2 are in direct conflict about the same three lines. §32.2 ("an expression statement whose value is not bound to any identifier SHALL initialize
~") plus §32.3's exactly-once rule makes{ note("a") lift "pos" }anE-TILDE-002. §17.6.2 calls the same statement a side effect. The compiler implements neither — it mints a fresh tilde and rebinds the context, so theliftwrites the wrong variable and the binding is silentlynull.The dispatched arc owes both halves — codegen and the §32.2 arm-body carve-out with a Rule 4b provenance line — because a codegen-only landing leaves the contradiction standing in the text.
⛑ New HIGH — the enforcement doesn't fire
g-tilde-lin-enforcement-does-not-fire-on-spec-own-examples. Six probes on merged main, all exit 0, all zeroE-TILDE: §32.5's 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-ifexample that SPEC says the compiler SHALL diagnose.Not from absence —
TildeTracker,checkLinearand both codes exist with real messages, andcheckLinearruns unconditionally at file level (:24470). Cause not traced, and the entry says so rather than guessing:hasNonLiftTildeConsumergates only loop-body elision, so the obvious explanation is ruled out without a replacement offered.That silence is the point — it's why two normative sections could contradict each other for as long as both have existed without anyone noticing. The S322 re-examination test in its purest form: a normative SHALL delivered by a state-scanning tracker pass, retrofit rather than by construction, producing exactly the hole that predicts.
⛑ And I banked dpa-040 in a form the probe could not read
I wrote the full
## [dpa-040]section intodpa-queue.md— the right file, per the S319 drain-path rule — anddpa-debt.tsstill reported 39 items / 2 UNRUN. The probe reads the status table, not the per-item sections; the script's own header says reading the per-itemstatus: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. Self-inflicted, same base §10 class as the rest of this session, and caught only because the probe was run rather than assumed.
dpa-040
Should an arm body be a
~context boundary in its own right (§32.4, beside${}contexts and function bodies)? Under it the conflict cannot recur by construction rather than by carve-out. Constraints recorded so the DD can't drift:~-as-linis not on the table (the boundary set is the question); adding a boundary is the LIMIT direction but issemantics-changedand owes a measured migration; and corpus-zero is blast radius only, never demand evidence (bryan, S346).🤖 Generated with Claude Code
https://claude.ai/code/session_019eHiNS6uvnGPFz55fzinNJ