From 4366020ea4fb9450bc4f30c061259ca3529b5bbb Mon Sep 17 00:00:00 2001 From: Santhi Prakash Date: Thu, 5 Nov 2026 12:55:48 +0000 Subject: [PATCH 1/4] fix(signals): keep isPending until a changed lane answer reveals (#4685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A lane derivation's flight could land while its lane stayed blocked by a sibling's pending work: laneValueOf already held the new answer but the reader's screen still showed the old value. verdictValue only probed flying, so isPending cleared in that window — reporting no pending change while the displayed value was still stale. Now the verdict probe also checks whether the lane's latest answer differs from what the reader sees (the display, or the latest view inside latest()); a differing unrevealed answer keeps the probe pending, and the tracked reader parks on the lane's reruns so it re-derives at the lane's seam rather than only at the parent's landing. In reruns, a verdict-only reader (no REACTIVE_FRAME_READ) no longer marks the rerun frame-producing, so its re-derivation doesn't delay the landing's releases. --- .../fix-ispending-unrevealed-lane-landing.md | 5 ++ packages/signals/docs/RULES-INDEX.md | 2 +- packages/signals/src/core/scheduler.ts | 9 +- packages/signals/src/core/verdict.ts | 22 ++++- .../signals/tests/createOptimistic.test.ts | 16 ++-- ...nding-unrevealed-lane-landing-4685.test.ts | 84 +++++++++++++++++++ 6 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 .changeset/fix-ispending-unrevealed-lane-landing.md create mode 100644 packages/signals/tests/ispending-unrevealed-lane-landing-4685.test.ts diff --git a/.changeset/fix-ispending-unrevealed-lane-landing.md b/.changeset/fix-ispending-unrevealed-lane-landing.md new file mode 100644 index 000000000..7208f46e1 --- /dev/null +++ b/.changeset/fix-ispending-unrevealed-lane-landing.md @@ -0,0 +1,5 @@ +--- +"@solidjs/signals": patch +--- + +Keep `isPending` true for a lane derivation whose changed answer has landed but not yet been revealed (#4685) diff --git a/packages/signals/docs/RULES-INDEX.md b/packages/signals/docs/RULES-INDEX.md index 80538da36..3952bae58 100644 --- a/packages/signals/docs/RULES-INDEX.md +++ b/packages/signals/docs/RULES-INDEX.md @@ -135,7 +135,7 @@ Status legend: **live** stated and standing · **ruled** carries an explicit rul | A21 | superseded | `docs/SPEC-ASYNC-SEMANTICS.md:417` | — | question-scoped-pending.test.ts×3 spec-async-semantics.test.ts×3 | [superseded 2026-07-13 by A24] (superseded) The store-wide mask — (**SUPERSEDED 2026-07-13 by A24** — the store-wide mask is deleted with the mask model; nothing silences a new question. The effective… | | A22 | amended | `docs/SPEC-ASYNC-SEMANTICS.md:231` | store.ts×1 | createProjection.draft-lifetime-3585.test.ts×1 spec-async-semantics.test.ts×1 visibility-oracle-store.states.ts×1 | [ruled, amended in place 2026-07-08] Pending is per-node; store-wide only for the firewall's own work — \*\*Pending is per-node: store-wide verdicts exist only as the firewall's own in-flight work (A9) … | | A23 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:241` | seat.ts×1 | spec-async-semantics.test.ts×1 | [ruled 2026-07-08] The `isPending` probe is reads-only — **The `isPending` probe is reads-only — the thunk's return value is never inspected.** `isPending(() => store)` reads nothing and reports `fals… | -| A24 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:159` | affects-marks.ts×1 affects.ts×1 constants.ts×1 lanes.ts×2 types.ts×1 verdict.ts×3 affects.ts×1 optimistic.ts×1 | body-end-supersession-visibility.test.ts×1 create-deferred-3710.test.ts×2 optimistic-undefined-override.test.ts×1 reveal-gating-contract.test.ts×1 spec-async-semantics.test.ts×3 kanban-a17-fixture.test.ts×1 signal-store-twins-qd.test.ts×1 visibility-oracle-store.states.ts×4 visibility-oracle.states.ts×5 visibility-oracle.test.ts×1 | [ruled 2026-07-13] Question-scoped pending: pending iff a value change is in flight or an `affects()` mark is live — (**ruled 2026-07-13** — supersedes A20/A21; the converged model from the #2844/#272… | +| A24 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:159` | affects-marks.ts×1 affects.ts×1 constants.ts×1 lanes.ts×2 types.ts×1 verdict.ts×4 affects.ts×1 optimistic.ts×1 | body-end-supersession-visibility.test.ts×1 create-deferred-3710.test.ts×2 optimistic-undefined-override.test.ts×1 reveal-gating-contract.test.ts×1 spec-async-semantics.test.ts×3 kanban-a17-fixture.test.ts×1 signal-store-twins-qd.test.ts×1 visibility-oracle-store.states.ts×4 visibility-oracle.states.ts×5 visibility-oracle.test.ts×1 | [ruled 2026-07-13] Question-scoped pending: pending iff a value change is in flight or an `affects()` mark is live — (**ruled 2026-07-13** — supersedes A20/A21; the converged model from the #2844/#272… | | A25 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:311` | projection.ts×2 store.ts×1 | derived-presence-async-3726.test.ts×2 seedless-derived-store.test.ts×1 uninitialized-visibility.test.ts×3 visibility-oracle-store.states.ts×7 visibility-oracle-store.test.ts×1 | [ruled 2026-07-16] A derived store's seed is a draft, never an observable value — (**ruled 2026-07-16**, #2897) **A derived store's seed is a draft, never an observable value.** The seed exists for th… | | A26 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:111` | — | action-await-contract.test.ts×2 fuzz-findings-l2.test.ts×1 posture-store-parity.test.ts×2 visibility-oracle-store.states.ts×2 visibility-oracle.states.ts×1 visibility-oracle.test.ts×1 | [ruled 2026-07-17] An ambient transaction window is one flush; parking is flush-driven — (**ruled 2026-07-17**, #2913; **enforcement hardened 2026-08-31**, #3141 — parking is flush-driven, and a trans… | | A27 | ruled | `docs/SPEC-ASYNC-SEMANTICS.md:303` | — | loading-value.test.ts×2 visibility-oracle.states.ts×18 visibility-oracle.test.ts×1 | [ruled 2026-08-10] The commit-#0 loading window is loading-class and verdict-quiet — (**ruled 2026-08-10**) **The commit-#0 loading window is loading-class and verdict-quiet.** A node born committed v… | diff --git a/packages/signals/src/core/scheduler.ts b/packages/signals/src/core/scheduler.ts index 99351a9e7..2f8606d48 100644 --- a/packages/signals/src/core/scheduler.ts +++ b/packages/signals/src/core/scheduler.ts @@ -1266,8 +1266,13 @@ export function reruns(u: Transaction): unknown { // the screen). So does a memo the landing holds (CONFIG_HELD: its // staged value is in this frame): the held runs read it, so shown // first they showed the stale pass the re-derivation replaces — one - // frame reveals the change (F-1, A15; #4648). - frame ||= (r as any)._type || s === r || r._config & CONFIG_HELD; + // frame reveals the change (F-1, A15; #4648). A verdict-only reader + // (no REACTIVE_FRAME_READ: it never read the frame as committed) is + // not that frame — its re-derivation shows a verdict beside the + // screen, so the landing's runs need not wait for it (#4685). + frame ||= + !(r._config & CONFIG_VERDICT && !(r._flags & REACTIVE_FRAME_READ)) && + ((r as any)._type || s === r || r._config & CONFIG_HELD); // A lane's reveal leaves the mark to the transaction: a reader that // also read a held node as committed (`staleReader`) still observes // that flight until it re-runs — cleared here, the transaction landed diff --git a/packages/signals/src/core/verdict.ts b/packages/signals/src/core/verdict.ts index 87439befa..3f68589b5 100644 --- a/packages/signals/src/core/verdict.ts +++ b/packages/signals/src/core/verdict.ts @@ -549,7 +549,27 @@ function verdictValue(el: Signal | Computed, c: Computed | null): (latestActive || !owner._x!._shownError) ) throw owner._x!._error; - if (probing && flying) probeFound = true; + // A lane derivation's landed answer waits for the lane's reveal while + // the lane is blocked: what the reader sees (`v`, the screen — or the + // latest view inside `latest()`) is not the lane's latest then, so the + // answer is not final until the reveal shows it (#4685). An equal one + // is final now (A24), as is the latest view that already observes it. + // The reveal — the lane's seam, before and without its parent's + // landing — is what flips the verdict, so the reader re-derives there + // (`l._reruns`), not only at the parent's landing (`verdictRead`). + if (probing) { + const u = laneValueOf(el), + unrevealed = + u !== v && + (!el._equals || !el._equals(u as any, v as any)) && + // Only a blocked lane's landed answer waits: an unblocked + // staging reveals in this flush, so the display already moves + // with the probe's read (#4429's pulled pass — the probe + // answers the screen, not a round that is not stuck). + blocked(l); + if (flying || unrevealed) probeFound = true; + if (unrevealed && tracked && l._reruns[l._reruns.length - 1] !== c) l._reruns.push(c!); + } if (__TEST__) shadowActual(latestActive && !flying ? SLOT_LV : SLOT_DV); return v; } diff --git a/packages/signals/tests/createOptimistic.test.ts b/packages/signals/tests/createOptimistic.test.ts index 729895f40..2d86dc9fe 100644 --- a/packages/signals/tests/createOptimistic.test.ts +++ b/packages/signals/tests/createOptimistic.test.ts @@ -3776,8 +3776,9 @@ describe("createOptimistic", () => { // CRITICAL: tax text should update independently expect(shown(taxTexts)).toEqual(["US_SALES_TAX", "UK_VAT"]); - // Tax's own async slot has resolved even though shipping is still pending. - expect(taxPendingComputes.at(-1)).toBe(false); + // Tax's answer has landed but is held unrevealed by shipping's + // flight in the same lane, so it stays pending until the reveal. + expect(taxPendingComputes.at(-1)).toBe(true); // Shipping text should NOT have updated yet expect(shown(shippingTexts)).toEqual(["FEDEX"]); @@ -4179,8 +4180,9 @@ describe("createOptimistic", () => { // CRITICAL: shipping text should update INDEPENDENTLY expect(shown(shippingTexts)).toEqual(["FEDEX", "DHL"]); - // Shipping's own async slot has resolved independently. - expect(shippingPendingComputes.at(-1)).toBe(false); + // Shipping's answer has landed but is held unrevealed by tax's + // pending flight in the same lane, so it stays pending. + expect(shippingPendingComputes.at(-1)).toBe(true); // Tax should NOT have updated yet (correction re-fetch still in flight) expect(shown(taxTexts)).toEqual(["US_SALES_TAX"]); @@ -4357,9 +4359,9 @@ describe("createOptimistic", () => { await Promise.resolve(); flush(); - // Shipping's own pending slot clears even though the merged total is - // still waiting on tax. - expect(shippingPendingComputes.at(-1)).toBe(false); + // Shipping's answer has landed but is held unrevealed by the merged + // lane still waiting on tax, so it stays pending. + expect(shippingPendingComputes.at(-1)).toBe(true); // Tax also still pending expect(taxPendingComputes.at(-1)).toBe(true); // orderTotal hasn't updated (merged lane still pending) diff --git a/packages/signals/tests/ispending-unrevealed-lane-landing-4685.test.ts b/packages/signals/tests/ispending-unrevealed-lane-landing-4685.test.ts new file mode 100644 index 000000000..ac906a56e --- /dev/null +++ b/packages/signals/tests/ispending-unrevealed-lane-landing-4685.test.ts @@ -0,0 +1,84 @@ +import { describe, expect, it } from "vitest"; +import { + action, + createMemo, + createOptimistic, + createRenderEffect, + createRoot, + flush, + isPending +} from "../src/index.js"; + +function deferred() { + let resolve!: (v: T) => void; + const promise = new Promise(r => (resolve = r)); + return { promise, resolve }; +} + +const tick = async () => { + for (let i = 0; i < 8; i++) await Promise.resolve(); + flush(); +}; + +describe("#4685 isPending over an unrevealed lane landing", () => { + it("stays true until the changed lane value is revealed", async () => { + const [opt, setOpt] = createOptimistic(0); + const left = deferred(); + const right = deferred(); + const screen = { left: "", pending: "", total: "" }; + const frames: string[] = []; + let dispose!: () => void; + createRoot(d => { + dispose = d; + const leftMemo = createMemo(async () => { + const v = opt(); + if (v === 0) return 0; + await left.promise; + return 10; + }); + const rightMemo = createMemo(async () => { + const v = opt(); + if (v === 0) return 0; + await right.promise; + return 20; + }); + const total = createMemo(() => leftMemo() + rightMemo()); + const bind = (k: keyof typeof screen, fn: () => unknown) => + createRenderEffect(fn, v => { + screen[k] = String(v); + }); + bind("left", leftMemo); + bind("pending", () => isPending(leftMemo)); + bind("total", total); + }); + flush(); + const snap = () => + frames.push(`left ${screen.left} | pending ${screen.pending} | total ${screen.total}`); + await tick(); + snap(); + + const act = action(function* () { + setOpt(1); + yield new Promise(() => {}); + }); + act(); + await tick(); + snap(); + + left.resolve(10); + await tick(); + snap(); + + right.resolve(20); + await tick(); + snap(); + + expect(frames).toEqual([ + "left 0 | pending false | total 0", + "left 0 | pending true | total 0", + "left 0 | pending true | total 0", + "left 10 | pending false | total 30" + ]); + dispose(); + }); +}); From 04bb92bbd90c060add70aa7c0fadb4ca59651428 Mon Sep 17 00:00:00 2001 From: Santhi Prakash Date: Thu, 5 Nov 2026 13:23:34 +0000 Subject: [PATCH 2/4] chore(size): raise six caps for the #4685 verdict-probe growth Keeping isPending true over an unrevealed changed lane answer costs +29 B minified where the rerun guard alone is retained and +121-129 B where the verdict path is. Raise the six moved scenario caps and their recorded minified at the CI measurements (Size run 42031370774), with the mechanism and the rejected smaller shapes in scenarios.js; the frozen page floor goes under the Size-Exception line in the PR body. --- scripts/size/floor-caps.json | 4 +-- scripts/size/scenarios.js | 52 +++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/scripts/size/floor-caps.json b/scripts/size/floor-caps.json index a7d0d74e0..e98ab88b3 100644 --- a/scripts/size/floor-caps.json +++ b/scripts/size/floor-caps.json @@ -16,8 +16,8 @@ "minified": 102212 }, "page: live server components (base + live/GET + action + isPending/latest)": { - "cap": "40.30 KB", - "minified": 121153 + "cap": "40.35 KB", + "minified": 121282 }, "server: floor (getRequestEvent + isServer)": { "cap": "1.29 KB", diff --git a/scripts/size/scenarios.js b/scripts/size/scenarios.js index 3604ff409..4df5ae7bb 100644 --- a/scripts/size/scenarios.js +++ b/scripts/size/scenarios.js @@ -1129,8 +1129,13 @@ module.exports = [ // Batch re-record (2026-11-02, over next @ f8080f3, size job 125582643125: #4620, #4621, #4604, #4630): 15.01 KB -> 15.03 KB, recorded minified 43,875 -> 43,742 B (-133 B), measured at 15,011 B brotli. #4620 and #4621 were accepted by the maintainer; #4604 and #4630 are size-neutral on the gated rows. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ 885b99b, size job 125684994005: #4633, #4634, #4637): cap unchanged at 15.03 KB, recorded minified 43,742 -> 43,811 B (+69 B), measured at 15,012 B brotli. #4633, #4634 and #4637 were accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-04, over next @ e704cfc, measured locally: #4674, #4676): 15.03 KB -> 15.10 KB, recorded minified 43,811 -> 43,868 B (+57 B), measured at 15,089 B brotli. The growth of #4674 and #4676 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. - limit: "15.10 KB", - capMinified: 43868, + // #4685's rerun guard (a verdict-only reader no longer marks the rerun + // frame-producing; see `signals: + isPending/latest`, 2026-11-05, over + // next @ f6b6737, Size run 42031370774): 15.10 -> 15.12 KB, recorded + // minified 43,868 -> 43,897 B (+29 B), measured at 15,103 B brotli. Cap at + // measured + 10 B rounded up to 0.01 KB; recorded minified = measured. + limit: "15.12 KB", + capMinified: 43897, alias }, { @@ -1474,9 +1479,17 @@ module.exports = [ // Batch re-record (2026-11-03, over next @ 061b013, size job 126059550469: #4656, #4658, #4663): 11.92 KB -> 11.99 KB, recorded minified 32,772 -> 32,951 B (+179 B), measured at 11,973 B brotli. The growth of #4656, #4658 and #4663 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ ab5b5cb, measured locally: #4667, #4669): 11.99 KB -> 12.07 KB, recorded minified 32,951 -> 33,081 B (+130 B), measured at 12,055 B brotli. The growth of #4667 and #4669 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Re-record (2026-11-05, over next @ 5208944, measured locally: #4682, #4677): 12.07 KB -> 12.25 KB, recorded minified 33,081 -> 33,615 B (+534 B: #4682 +7 B, #4677 +527 B), measured at 12,239 B brotli. Re-recorded in the fix's own change rather than in a batch, at the maintainer's request. - limit: "12.25 KB", + // Rebased onto `next` @ 6b7474b with #4685's verdict probe (2026-11-05, CI + // Size run 42092720174): 12.25 KB -> 12.29 KB, recorded minified 33,615 -> + // 33,743 B (+128 B), measured at 12,276 B brotli against `next` @ + // 6b7474b's 12,239 (+37 B). The verdict probe's lane-answer comparison (a + // blocked lane's landed answer waits for a later reveal), retained + // wherever `isPending`/`latest` is imported; see the core floor note. Cap + // set at measured + 10 B rounded up to 0.01 KB; recorded minified = + // measured. + limit: "12.29 KB", // latest() read inline and through a memo show the same screen (#4284 through a memo; a plain write beside an async memo), 2026-10-29, over next @ 7ebd4a32: recorded minified 28,693 -> 29,086 B (+343 B minified over next), measured locally (linux) at 10,565 B brotli (+135 B over next). A render effect a verdict memo's change re-runs reads as its verdict reader for that pass (`laneDirty`), a pass that read a staging before the frame had a transaction re-derives once as a verdict reader only if the frame parks, `latest()` of a first load in flight in a verdict lane is loading (also through an identity memo, a derived store and `isPending`), a lane's dissolution leaves such a load and the nodes pending on it uninitialized instead of committing `undefined`, a verdict lane born at a seam is judged at it, a pass born in a staged reader stays the frame's on a verdict-memo read (C4, #4010), a plain write beside `latest()` computes once (the seam re-derives a pre-transaction staged reader only if the frame parks), a verdict reader's plain read of a staging in a transaction only a `latest()` opened is the frame's read, so a memo of `latest()` computes once too (D-22; not a pass with no value yet, D-6), and an error stays the display while the memo it came through re-asks, a Loading fallback behind it included (D-39, async-gen 91501 #1831). recompute's CONFIG_VERDICT clear now sits behind the lane engine: -21 B minified on every floor. Correctness; the maintainer: "only flag me if brotli goes more than 20kb" (2026-10-29). Cap unchanged; recorded minified = measured. - capMinified: 33615, + capMinified: 33743, alias }, { @@ -2800,11 +2813,12 @@ module.exports = [ // Batch re-record (2026-11-04, over next @ e704cfc, measured locally: #4674, #4676): 33.26 KB -> 33.27 KB, recorded minified 99,898 -> 99,967 B (+69 B), measured at 33,260 B brotli. The growth of #4674 and #4676 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Re-record (2026-11-05, over next @ 5208944, measured locally: #4682, #4677): 33.27 KB -> 33.42 KB, recorded minified 99,967 -> 100,437 B (+470 B: #4677 +470 B; #4682 is size-neutral here), measured at 33,401 B brotli. Re-recorded in the fix's own change rather than in a batch, at the maintainer's request. // Re-record (2026-11-05, over next @ fb672ca, measured locally: #4690): 33.42 KB -> 33.41 KB, recorded minified 100,437 -> 100,547 B (+110 B: #4690), measured at 33,398 B brotli. Re-recorded in the fix's own change rather than in a batch, at the maintainer's request. - limit: "33.41 KB", + // Rebased onto `next` @ 45648f7 with #4690/#4691/#4693 landed (2026-11-06, measured locally): 33.41 KB -> 33.44 KB, recorded minified 100,547 -> 100,576 B — #4685's rerun guard adds +29 B minified over the rebased record, measured at 33,423 B brotli, byte-identical to the pre-rebase measurement (CI Size run 42133064937). Cap set at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. + limit: "33.44 KB", // An Errored heals when the last reader that caught its error is disposed (#4373, #4384, 2026-10-28, re-recorded over next @ cbc0eebd): recorded minified 96,989 -> 97,047 B (+58 B minified over next's record), measured locally (linux) at 31,811 B brotli. Recorded minified = measured; CI re-bases. // Boundary readers keyed by the source they wait on (#4373), with enterLane's tail folded into one else-chain as an offset (-29 B on lane pages) (#4384, 2026-10-28, re-recorded over next @ 1b32ff2e): recorded minified 97,024 -> 97,045 B (+21 B minified over next's record), measured locally (linux) at 31,798 B brotli. Recorded minified = measured; CI re-bases. // latest() read inline and through a memo show the same screen (#4284 through a memo; a plain write beside an async memo), 2026-10-29, over next @ 7ebd4a32: recorded minified 97,045 -> 97,426 B (+240 B minified over next), measured locally (linux) at 31,976 B brotli (+109 B over next). A render effect a verdict memo's change re-runs reads as its verdict reader for that pass (`laneDirty`), a pass that read a staging before the frame had a transaction re-derives once as a verdict reader only if the frame parks, `latest()` of a first load in flight in a verdict lane is loading (also through an identity memo, a derived store and `isPending`), a lane's dissolution leaves such a load and the nodes pending on it uninitialized instead of committing `undefined`, a verdict lane born at a seam is judged at it, a pass born in a staged reader stays the frame's on a verdict-memo read (C4, #4010), a plain write beside `latest()` computes once (the seam re-derives a pre-transaction staged reader only if the frame parks), a verdict reader's plain read of a staging in a transaction only a `latest()` opened is the frame's read, so a memo of `latest()` computes once too (D-22; not a pass with no value yet, D-6), and an error stays the display while the memo it came through re-asks, a Loading fallback behind it included (D-39, async-gen 91501 #1831). recompute's CONFIG_VERDICT clear now sits behind the lane engine: -21 B minified on every floor. Correctness; the maintainer: "only flag me if brotli goes more than 20kb" (2026-10-29). Cap unchanged; recorded minified = measured. - capMinified: 100547, + capMinified: 100576, alias }, { @@ -3993,8 +4007,13 @@ module.exports = [ // Batch re-record (2026-11-03, over next @ 885b99b, size job 125684994005: #4633, #4634, #4637): 29.94 KB -> 30.03 KB, recorded minified 88,422 -> 88,582 B (+160 B), measured at 30,015 B brotli. #4633, #4634 and #4637 were accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ 6e569c7, size job 125766182293: #4639, #4641): cap unchanged at 30.03 KB, recorded minified 88,582 -> 88,656 B (+74 B), measured at 30,012 B brotli. #4639 and #4641 were accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ ccfc7ea, size job 125848841075: #4653, #4655, #4657, #4659): 30.03 KB -> 30.12 KB, recorded minified 88,656 -> 88,842 B (+186 B), measured at 30,109 B brotli. The growth of #4653, #4655 and #4659 was accepted by the maintainer; #4657 and #4654 are size-neutral on the gated rows. Re-recorded once after the batch, per the batch process. - limit: "30.12 KB", - capMinified: 88842, + // #4685's rerun guard (a verdict-only reader no longer marks the rerun + // frame-producing; see `signals: + isPending/latest`, 2026-11-05, over + // next @ f6b6737, Size run 42031370774): 30.12 -> 30.15 KB, recorded + // minified 88,842 -> 88,864 B (+22 B), measured at 30,132 B brotli. Cap at + // measured + 10 B rounded up to 0.01 KB; recorded minified = measured. + limit: "30.15 KB", + capMinified: 88864, alias: observeAlias }, // Compiled-template scenarios (2026-10-05): the four `app:` fixtures above @@ -5758,6 +5777,14 @@ module.exports = [ // Batch re-record (2026-11-03, over next @ 061b013, size job 126059550469: #4656, #4658, #4663): 39.96 KB -> 40.08 KB, recorded minified 120,310 -> 120,486 B (+176 B), measured at 40,066 B brotli. A frozen floor, Size-Exception in this PR's body. The growth of #4656, #4658 and #4663 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ ab5b5cb, measured locally: #4667, #4669): 40.08 KB -> 40.14 KB, recorded minified 120,486 -> 120,619 B (+133 B), measured at 40,124 B brotli. A frozen floor, Size-Exception in this PR's body. The growth of #4667 and #4669 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Re-record (2026-11-05, over next @ 5208944, measured locally: #4682, #4677): 40.14 KB -> 40.30 KB, recorded minified 120,619 -> 121,153 B (+534 B: #4682 +7 B, #4677 +527 B), measured at 40,289 B brotli. A frozen floor, Size-Exception in this PR's body. Re-recorded in the fix's own change rather than in a batch, at the maintainer's request. + // Rebased onto `next` @ 6b7474b with #4685's verdict probe (2026-11-05, CI + // Size run 42092720174): 40.30 KB -> 40.35 KB, recorded minified 121,153 -> + // 121,282 B (+129 B), measured at 40,332 B brotli against `next` @ + // 6b7474b's 40,289 (+43 B). The verdict probe's lane-answer comparison + // retained on the live page (`isPending/latest` is imported there); see + // `signals: + isPending/latest`. A frozen floor, Size-Exception in this + // PR's body. Cap set at measured + 10 B rounded up to 0.01 KB; recorded + // minified = measured. limit: floorCaps["page: live server components (base + live/GET + action + isPending/latest)"], capMinified: floorMinified["page: live server components (base + live/GET + action + isPending/latest)"], @@ -6340,8 +6367,13 @@ module.exports = [ // Batch re-record (2026-11-03, over next @ ccfc7ea, size job 125848841075: #4653, #4655, #4657, #4659): 41.53 KB -> 41.57 KB, recorded minified 126,108 -> 126,300 B (+192 B), measured at 41,557 B brotli. The growth of #4653, #4655 and #4659 was accepted by the maintainer; #4657 and #4654 are size-neutral on the gated rows. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ 061b013, size job 126059550469: #4656, #4658, #4663): 41.57 KB -> 41.59 KB, recorded minified 126,300 -> 126,284 B (-16 B), measured at 41,578 B brotli. The growth of #4656, #4658 and #4663 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. // Batch re-record (2026-11-03, over next @ ab5b5cb, measured locally: #4667, #4669): 41.59 KB -> 41.60 KB, recorded minified 126,284 -> 126,293 B (+9 B), measured at 41,590 B brotli. The growth of #4667 and #4669 was accepted by the maintainer. Re-recorded once after the batch, per the batch process. - limit: "41.60 KB", - capMinified: 126293, + // #4685's rerun guard (a verdict-only reader no longer marks the rerun + // frame-producing; see `signals: + isPending/latest`, 2026-11-05, over + // next @ f6b6737, Size run 42031370774): 41.60 -> 41.67 KB, recorded + // minified 126,293 -> 126,322 B (+29 B), measured at 41,653 B brotli. Cap + // at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. + limit: "41.67 KB", + capMinified: 126322, alias: pageAlias, conditions: solidConditions, compile: { hydratable: true } From 68183aae46ade55c2ce58d4d09b491b24c830d96 Mon Sep 17 00:00:00 2001 From: Santhi Prakash Date: Fri, 6 Nov 2026 13:50:44 +0000 Subject: [PATCH 3/4] ci: re-trigger workflows (no runs were created for the 788a0af force-push) From 5f61a0520825058e4be6de73b066e83c3bc36778 Mon Sep 17 00:00:00 2001 From: Santhi Prakash Date: Sat, 7 Nov 2026 03:57:55 +0000 Subject: [PATCH 4/4] ci: re-trigger Solid CI (signals timing flake in turbo-parallel run 6174) - Problem: Solid CI run 6174 failed once at tests/optimistic-keyed-fold.test.ts:263 (expected 'a', received 'a,b') on the turbo-parallel full-repo run. - Fix: no source change; re-trigger. The file passes 10/10 locally across branch tip, pristine next (cf839ea), and the exact merge-ref CI tested, and passes inside the full merge-ref suite; the assertion sits in a sleep-driven (20/30/5 ms) optimistic-lane test, a load-sensitive family. - Verification: vitest run tests/optimistic-keyed-fold.test.ts green x4 (68183aa), x3 (origin/next cf839ea), x3 (merge-ref 68183aa+cf839ea); full signals suite on merge-ref 6745 passed with the only failure attribution-engine-cost (wall/cost-bound, passes standalone x2, CI-green).