From 07f0840ccb0975f8f7aaebc691406c4798168c1e Mon Sep 17 00:00:00 2001 From: Nicholas Date: Sun, 18 Oct 2026 19:56:38 -0700 Subject: [PATCH 1/3] fix(signals): a write clears a writable memo's previous error STATUS_ERROR was only cleared by a recompute or an async settle, neither of which a direct write performs, so an errored memo kept throwing the stale error to every later reader. --- .../writable-memo-write-clears-error.md | 5 ++ packages/signals/src/core/core.ts | 5 ++ ...table-memo-write-clears-error-4110.test.ts | 56 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 .changeset/writable-memo-write-clears-error.md create mode 100644 packages/signals/tests/writable-memo-write-clears-error-4110.test.ts diff --git a/.changeset/writable-memo-write-clears-error.md b/.changeset/writable-memo-write-clears-error.md new file mode 100644 index 0000000000..835cf4182b --- /dev/null +++ b/.changeset/writable-memo-write-clears-error.md @@ -0,0 +1,5 @@ +--- +"@solidjs/signals": patch +--- + +A write to a writable memo clears an error its derivation left behind (#4110). Clearing `STATUS_ERROR` only happened on a recompute or an async settle, and a direct write does neither, so a memo that had thrown kept throwing the stale error to every later reader: effects stayed on their error arm, error boundaries never recovered, and the written value sat committed underneath a node that still reported an error. A write equal to the last good value was dropped entirely by the equality gate. Writing to such a memo now recovers it, which is what "a write lands at once and never re-runs `fn` on its own" already promised. diff --git a/packages/signals/src/core/core.ts b/packages/signals/src/core/core.ts index 7469764f69..24c59b1b40 100644 --- a/packages/signals/src/core/core.ts +++ b/packages/signals/src/core/core.ts @@ -63,6 +63,7 @@ import { REACTIVE_SNAPSHOT_STALE, REACTIVE_ZOMBIE, STATUS_ERROR, + STATUS_NONE, STATUS_PENDING, STATUS_UNINITIALIZED, type Refreshable @@ -2211,7 +2212,11 @@ export function setMemo(el: Computed, v: T | ((prev: T) => T)): T { const value = (v as (prev: T) => T)(el._value); v = () => value; } + // #4110: the write replaces a failed derivation's outcome. It lands without + // re-running `_fn`, and nothing else clears STATUS_ERROR, so without this + // every later read keeps throwing the error the derivation left behind. v = setSignal(el, v); + if (el._statusFlags & STATUS_ERROR) notifyStatus(el, STATUS_NONE, undefined); if (held) { // The one write that re-runs: the staging it replaced was derived from // inputs the writer never saw, so the hold re-derives over the write. diff --git a/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts b/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts new file mode 100644 index 0000000000..a8be2cc326 --- /dev/null +++ b/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts @@ -0,0 +1,56 @@ +/** + * A writable memo that throws keeps throwing for every later reader. Clearing + * STATUS_ERROR only happens on a recompute or an async settle, and a direct + * write deliberately does neither, so the written value commits underneath a + * node that still reports an error and the memo cannot be recovered. + * + * @see https://github.com/solidjs/solid/issues/4110 + */ +import { expect, it } from "vitest"; +import { createEffect, createRoot, createSignal, flush } from "../src/index.js"; + +it("a write clears an error the derivation left behind", () => { + const seen: unknown[] = []; + const { value, setValue } = createRoot(() => { + const [failing] = createSignal(true); + const [value, setValue] = createSignal(() => { + if (failing()) throw new Error("boom"); + return 1; + }); + createEffect(() => value(), { + effect: v => void seen.push({ ok: v }), + error: e => void seen.push({ err: (e as Error).message }) + }); + return { value, setValue }; + }); + + flush(); + expect(seen).toEqual([{ err: "boom" }]); + + setValue(2); + flush(); + expect(seen).toEqual([{ err: "boom" }, { ok: 2 }]); + expect(value()).toBe(2); +}); + +it("a write of the last good value still recovers the memo", () => { + const { value, setValue, setFailing } = createRoot(() => { + const [failing, setFailing] = createSignal(false); + const [value, setValue] = createSignal(() => { + if (failing()) throw new Error("boom"); + return 1; + }); + return { value, setValue, setFailing }; + }); + + expect(value()).toBe(1); + + setFailing(true); + flush(); + expect(() => value()).toThrow("boom"); + + // equal to the last good value, so the equality gate must not drop it + setValue(1); + flush(); + expect(value()).toBe(1); +}); From cf4e5c87dd95cc9a80cdc0afeb34b0503dee4be4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 04:22:50 +0000 Subject: [PATCH 2/3] fix(signals): keep a writable memo's error shown until the write commits (#4110) Builds on #4143. The error stays the display until the write commits, so a read between the write and its flush, or under the action holding it, still throws instead of returning the old value. A write also clears an error a pass staged under the same hold, so effects see the written value instead of their error arm (the action-write case left from #4148). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1 --- .../writable-memo-write-clears-error.md | 2 + packages/signals/src/core/core.ts | 8 +- ...table-memo-write-clears-error-4110.test.ts | 160 +++++++++++++++++- 3 files changed, 167 insertions(+), 3 deletions(-) diff --git a/.changeset/writable-memo-write-clears-error.md b/.changeset/writable-memo-write-clears-error.md index 835cf4182b..c33a8ffc09 100644 --- a/.changeset/writable-memo-write-clears-error.md +++ b/.changeset/writable-memo-write-clears-error.md @@ -3,3 +3,5 @@ --- A write to a writable memo clears an error its derivation left behind (#4110). Clearing `STATUS_ERROR` only happened on a recompute or an async settle, and a direct write does neither, so a memo that had thrown kept throwing the stale error to every later reader: effects stayed on their error arm, error boundaries never recovered, and the written value sat committed underneath a node that still reported an error. A write equal to the last good value was dropped entirely by the equality gate. Writing to such a memo now recovers it, which is what "a write lands at once and never re-runs `fn` on its own" already promised. + +The error stays what readers see until the write commits, so a read between the write and its flush, or during an action that holds the write, still throws instead of returning the old value. A write after a pass staged an error under the same action now lands as a value, instead of reaching effects' error arm. diff --git a/packages/signals/src/core/core.ts b/packages/signals/src/core/core.ts index 24c59b1b40..a49dc13c5b 100644 --- a/packages/signals/src/core/core.ts +++ b/packages/signals/src/core/core.ts @@ -2215,8 +2215,14 @@ export function setMemo(el: Computed, v: T | ((prev: T) => T)): T { // #4110: the write replaces a failed derivation's outcome. It lands without // re-running `_fn`, and nothing else clears STATUS_ERROR, so without this // every later read keeps throwing the error the derivation left behind. + // The error stays the display until the write commits (D-41). + if (el._statusFlags & STATUS_ERROR) { + el._x!._shownError = el._x!._error; + notifyStatus(el, STATUS_NONE, undefined); + } v = setSignal(el, v); - if (el._statusFlags & STATUS_ERROR) notifyStatus(el, STATUS_NONE, undefined); + // A write replaces an error a pass staged (D-41): it is a value again. + el._config &= ~CONFIG_STAGED_ERROR; if (held) { // The one write that re-runs: the staging it replaced was derived from // inputs the writer never saw, so the hold re-derives over the write. diff --git a/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts b/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts index a8be2cc326..035b825c7f 100644 --- a/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts +++ b/packages/signals/tests/writable-memo-write-clears-error-4110.test.ts @@ -6,8 +6,38 @@ * * @see https://github.com/solidjs/solid/issues/4110 */ -import { expect, it } from "vitest"; -import { createEffect, createRoot, createSignal, flush } from "../src/index.js"; +import { afterEach, expect, it } from "vitest"; +import { + action, + createEffect, + createErrorBoundary, + createRenderEffect, + createRoot, + createSignal, + flush, + resetErrorHalt, + untrack +} from "../src/index.js"; + +afterEach(() => resetErrorHalt()); + +const tick = async () => { + await new Promise(r => setTimeout(r, 0)); + flush(); +}; +const deferred = () => { + let resolve!: () => void; + const promise = new Promise(r => (resolve = r)); + return { promise, resolve }; +}; +const message = (e: any) => String(e?.cause?.message ?? e?.message ?? e); +const read = (f: () => unknown) => { + try { + return f(); + } catch (e) { + return "throws:" + message(e); + } +}; it("a write clears an error the derivation left behind", () => { const seen: unknown[] = []; @@ -54,3 +84,129 @@ it("a write of the last good value still recovers the memo", () => { flush(); expect(value()).toBe(1); }); + +// The error stays the display until the write commits (D-41): a read between +// the write and its flush still throws instead of tearing to the old value. +it("a read before the write's flush still throws the error", () => { + const { value, setValue, setFailing } = createRoot(() => { + const [failing, setFailing] = createSignal(false); + const [value, setValue] = createSignal(() => { + if (failing()) throw new Error("boom"); + return 1; + }); + createEffect(value, { effect: () => {}, error: () => {} }); + return { value, setValue, setFailing }; + }); + flush(); + setFailing(true); + flush(); + setValue(2); + expect(read(value)).toBe("throws:boom"); + flush(); + expect(value()).toBe(2); +}); + +it("a write held by an action shows the error until the action commits", async () => { + const gate = deferred(); + const log: unknown[] = []; + const [failing, setFailing] = createSignal(false); + let value!: () => number, setValue!: (v: number) => void; + const dispose = createRoot(d => { + [value, setValue] = createSignal(() => { + if (failing()) throw new Error("boom"); + return 1; + }) as any; + createEffect(value, { + effect: v => void log.push({ ok: v }), + error: e => void log.push({ err: message(e) }) + }); + return d; + }); + const act = action(function* () { + setValue(3); + yield gate.promise; + }); + flush(); + setFailing(true); + flush(); + act(); + flush(); + log.push({ mid: read(() => untrack(value)) }); + gate.resolve(); + await tick(); + await tick(); + expect(log).toEqual([{ ok: 1 }, { err: "boom" }, { mid: "throws:boom" }, { ok: 3 }]); + expect(value()).toBe(3); + dispose(); + flush(); +}); + +it("an error boundary recovers when the action's write commits", async () => { + const gate = deferred(); + const log: unknown[] = []; + const [failing, setFailing] = createSignal(false); + let value!: () => number, setValue!: (v: number) => void; + const dispose = createRoot(d => { + [value, setValue] = createSignal(() => { + if (failing()) throw new Error("boom"); + return 1; + }) as any; + const b = createErrorBoundary( + () => value(), + e => "fallback:" + message(e()) + ); + createRenderEffect(b, v => void log.push(v)); + return d; + }); + const act = action(function* () { + setValue(3); + yield gate.promise; + }); + flush(); + setFailing(true); + flush(); + act(); + flush(); + log.push("--mid"); + gate.resolve(); + await tick(); + await tick(); + expect(log).toEqual([1, "fallback:boom", "--mid", 3]); + dispose(); + flush(); +}); + +// A write replaces an error a pass staged under the action's hold: the effect +// receives the written value, not the error arm with the value as the "error". +it("a write after a staged error in the same action lands as a value", async () => { + const gate = deferred(); + const seen: unknown[] = []; + const [step, setStep] = createSignal(0); + let value!: () => number, setValue!: (v: number) => void; + const dispose = createRoot(d => { + [value, setValue] = createSignal(() => { + if (step() === 1) throw new Error("boom"); + return step(); + }) as any; + createEffect(value, { + effect: v => void seen.push({ ok: v }), + error: e => void seen.push({ err: message(e) }) + }); + return d; + }); + const act = action(function* () { + setStep(1); + yield gate.promise; + setValue(5); + }); + flush(); + act(); + flush(); + gate.resolve(); + await tick(); + await tick(); + expect(seen).toEqual([{ ok: 0 }, { ok: 5 }]); + expect(value()).toBe(5); + dispose(); + flush(); +}); From bdc5d4f7a1754152726dcce283b010db3be5685c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 04:27:08 +0000 Subject: [PATCH 3/3] chore(size): raise caps for the #4110 writable-memo error fix Accepted by the maintainer on 2026-10-20: about +50 B minified on the core floor. Also re-records #4163's +9 B, which merged without a re-record. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1 --- scripts/size/floor-caps.json | 18 +++++----- scripts/size/scenarios.js | 67 +++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/scripts/size/floor-caps.json b/scripts/size/floor-caps.json index 3c3705fc89..99ba465321 100644 --- a/scripts/size/floor-caps.json +++ b/scripts/size/floor-caps.json @@ -1,23 +1,23 @@ { "signals: core floor (createSignal/Memo/Effect/Root/flush)": { - "cap": "7.35 KB", - "minified": 19962 + "cap": "7.39 KB", + "minified": 20021 }, "app: render + one signal (the simple-app floor)": { - "cap": "9.67 KB", - "minified": 26852 + "cap": "9.70 KB", + "minified": 26911 }, "app: hydrating (no stores) with Show/For/Loading/Errored/lazy": { "cap": "18.32 KB", - "minified": 53428 + "minified": 53488 }, "page: base server components (hydrating + dynamic + frames + sf reference)": { - "cap": "33.18 KB", - "minified": 101384 + "cap": "33.20 KB", + "minified": 101444 }, "page: live server components (base + live/GET + action + isPending/latest)": { - "cap": "37.46 KB", - "minified": 114922 + "cap": "37.48 KB", + "minified": 114982 }, "server: floor (getRequestEvent + isServer)": { "cap": "1.34 KB", diff --git a/scripts/size/scenarios.js b/scripts/size/scenarios.js index cc02dc4950..f47785e1b7 100644 --- a/scripts/size/scenarios.js +++ b/scripts/size/scenarios.js @@ -596,6 +596,7 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 7.25 KB -> 7.27 KB, measured in CI at 7,257 B brotli / 19,827 B minified (+37 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 7.27 -> 7.35 KB, recorded minified 19,827 -> 19,934 B, measured locally (linux) at 7,336 B brotli / 19,934 B minified (+107 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 7.35 KB unchanged, recorded minified 19,934 -> 19,962 B (+28 B), measured in CI at 7,338 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 7.35 -> 7.39 KB, recorded minified 19,962 -> 20,021 B, measured locally (linux) at 7,374 B brotli / 20,021 B minified (+59 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: floorCaps["signals: core floor (createSignal/Memo/Effect/Root/flush)"], capMinified: floorMinified["signals: core floor (createSignal/Memo/Effect/Root/flush)"], alias @@ -1089,8 +1090,9 @@ module.exports = [ // Unread key beside a held sibling publishes at flush (#4146), re-measured after merging next @ 8c75f82f (2026-10-19): 14.82 -> 14.85 KB, measured locally (linux) at 14,837 B brotli / 44,972 B minified (+48 B minified over next). // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 14.85 -> 14.90 KB, recorded minified 44,972 -> 45,089 B, measured locally (linux) at 14,882 B brotli / 45,089 B minified (+117 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 14.90 KB -> 14.94 KB, recorded minified 45,089 -> 45,115 B (+26 B), measured in CI at 14,927 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "14.94 KB", - capMinified: 45115, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 14.94 -> 14.95 KB, recorded minified 45,115 -> 45,175 B, measured locally (linux) at 14,932 B brotli / 45,175 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "14.95 KB", + capMinified: 45175, alias }, { @@ -1396,8 +1398,9 @@ module.exports = [ // Re-recorded on next @ fb6006eb (2026-10-19, accepted by the maintainer): recorded minified 28,197 -> 28,247 B, measured locally (linux) at 10,023 B brotli. #4156 grew this scenario without re-recording it, so next sat past the 20 B minified allowance and brotli noise failed unrelated PRs. Cap unchanged. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 10.03 -> 10.12 KB, recorded minified 28,247 -> 28,356 B, measured locally (linux) at 10,103 B brotli / 28,356 B minified (+109 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 10.12 KB -> 10.14 KB, recorded minified 28,356 -> 28,383 B (+27 B), measured in CI at 10,121 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "10.14 KB", - capMinified: 28383, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 10.14 -> 10.16 KB, recorded minified 28,383 -> 28,443 B, measured locally (linux) at 10,144 B brotli / 28,443 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "10.16 KB", + capMinified: 28443, alias }, { @@ -1430,8 +1433,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 7.86 KB -> 7.88 KB, measured in CI at 7,863 B brotli / 21,639 B minified (+38 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 7.88 -> 7.95 KB, recorded minified 21,639 -> 21,745 B, measured locally (linux) at 7,937 B brotli / 21,745 B minified (+106 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 7.95 KB -> 7.96 KB, recorded minified 21,745 -> 21,773 B (+28 B), measured in CI at 7,941 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "7.96 KB", - capMinified: 21773 + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 7.96 -> 7.98 KB, recorded minified 21,773 -> 21,832 B, measured locally (linux) at 7,969 B brotli / 21,832 B minified (+59 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "7.98 KB", + capMinified: 21832 }, { name: "app: render + one signal (the simple-app floor)", @@ -1682,6 +1686,7 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 9.56 KB -> 9.59 KB, measured in CI at 9,576 B brotli / 26,715 B minified (+38 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 9.59 -> 9.66 KB, recorded minified 26,715 -> 26,824 B, measured locally (linux) at 9,644 B brotli / 26,824 B minified (+109 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 9.66 KB -> 9.67 KB, recorded minified 26,824 -> 26,852 B (+28 B), measured in CI at 9,651 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 9.67 -> 9.70 KB, recorded minified 26,852 -> 26,911 B, measured locally (linux) at 9,681 B brotli / 26,911 B minified (+59 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: floorCaps["app: render + one signal (the simple-app floor)"], capMinified: floorMinified["app: render + one signal (the simple-app floor)"], alias @@ -2072,6 +2077,7 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 18.19 KB -> 18.24 KB, measured in CI at 18,226 B brotli / 53,291 B minified (+42 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 18.24 -> 18.29 KB, recorded minified 53,291 -> 53,401 B, measured locally (linux) at 18,275 B brotli / 53,401 B minified (+110 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 18.29 KB -> 18.32 KB, recorded minified 53,401 -> 53,428 B (+27 B), measured in CI at 18,308 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 18.32 KB (unchanged), recorded minified 53,428 -> 53,488 B, measured locally (linux) at 18,309 B brotli / 53,488 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: floorCaps["app: hydrating (no stores) with Show/For/Loading/Errored/lazy"], capMinified: floorMinified["app: hydrating (no stores) with Show/For/Loading/Errored/lazy"], alias @@ -2621,8 +2627,9 @@ module.exports = [ // Unread key beside a held sibling publishes at flush (#4146), re-measured after merging next @ 8c75f82f (2026-10-19): 30.23 KB (unchanged), measured locally (linux) at 30,220 B brotli / 94,882 B minified (+48 B minified over next). // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 30.23 -> 30.30 KB, recorded minified 94,882 -> 94,999 B, measured locally (linux) at 30,289 B brotli / 94,999 B minified (+117 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 30.30 KB unchanged, recorded minified 94,999 -> 95,025 B (+26 B), measured in CI at 30,267 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "30.30 KB", - capMinified: 95025, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 30.30 -> 30.32 KB, recorded minified 95,025 -> 95,085 B, measured locally (linux) at 30,308 B brotli / 95,085 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "30.32 KB", + capMinified: 95085, alias }, { @@ -2909,8 +2916,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 13.14 KB -> 13.19 KB, measured in CI at 13,173 B brotli / 36,948 B minified (+35 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 13.19 -> 13.24 KB, recorded minified 36,948 -> 37,060 B, measured locally (linux) at 13,226 B brotli / 37,060 B minified (+112 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 13.24 KB unchanged, recorded minified 37,060 -> 37,087 B (+27 B), measured in CI at 13,217 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "13.24 KB", - capMinified: 37087, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 13.24 -> 13.28 KB, recorded minified 37,087 -> 37,147 B, measured locally (linux) at 13,264 B brotli / 37,147 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "13.28 KB", + capMinified: 37147, alias }, { @@ -3250,8 +3258,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 14.91 KB -> 14.95 KB, measured in CI at 14,939 B brotli / 41,908 B minified (+36 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 14.95 -> 14.99 KB, recorded minified 41,908 -> 42,019 B, measured locally (linux) at 14,971 B brotli / 42,019 B minified (+111 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 14.99 KB -> 15.00 KB, recorded minified 42,019 -> 42,046 B (+27 B), measured in CI at 14,988 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "15.00 KB", - capMinified: 42046, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 15.00 -> 15.03 KB, recorded minified 42,046 -> 42,106 B, measured locally (linux) at 15,016 B brotli / 42,106 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "15.03 KB", + capMinified: 42106, alias: observeAlias }, { @@ -3742,8 +3751,9 @@ module.exports = [ // mapArray window-staged commit (perf, #4114, 2026-10-16, merged over next @ dbc5d0005 after #4104's ratchet and #4108's observe raises): 29.19 -> 29.48 KB, measured at 29,462 B brotli / 88,235 B minified (+272 B brotli over the cap, +653 B minified over the recorded size): updateKeyedMap stages only the changed window, commits its bookkeeping arrays in place and takes a Map-free pure-removal path. Local measurement; CI's bytes re-base this cap. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 29.48 -> 29.59 KB, recorded minified 88,235 -> 88,339 B, measured locally (linux) at 29,572 B brotli / 88,339 B minified (+104 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 29.59 KB unchanged, recorded minified 88,339 -> 88,365 B (+26 B), measured in CI at 29,535 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "29.59 KB", - capMinified: 88365, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 29.59 -> 29.63 KB, recorded minified 88,365 -> 88,425 B, measured locally (linux) at 29,612 B brotli / 88,425 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "29.63 KB", + capMinified: 88425, alias: observeAlias }, // Compiled-template scenarios (2026-10-05): the four `app:` fixtures above @@ -3830,8 +3840,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 9.77 KB -> 9.79 KB, measured in CI at 9,775 B brotli / 27,247 B minified (+38 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 9.79 -> 9.86 KB, recorded minified 27,247 -> 27,356 B, measured locally (linux) at 9,849 B brotli / 27,356 B minified (+109 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 9.86 KB unchanged, recorded minified 27,356 -> 27,383 B (+27 B), measured in CI at 9,846 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "9.86 KB", - capMinified: 27383, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 9.86 -> 9.89 KB, recorded minified 27,383 -> 27,442 B, measured locally (linux) at 9,879 B brotli / 27,442 B minified (+59 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "9.89 KB", + capMinified: 27442, alias }, { @@ -3950,8 +3961,9 @@ module.exports = [ // Unread key beside a held sibling publishes at flush (#4146), re-measured after merging next @ 8c75f82f (2026-10-19): 26.03 KB (unchanged), recorded minified 80,929 -> 80,977 B, measured locally (linux) at 26,025 B brotli / 80,977 B minified (+48 B minified over next). // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 26.03 -> 26.10 KB, recorded minified 80,977 -> 81,083 B, measured locally (linux) at 26,089 B brotli / 81,083 B minified (+106 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 26.10 KB unchanged, recorded minified 81,083 -> 81,112 B (+29 B), measured in CI at 26,086 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 26.10 KB (unchanged), recorded minified 81,112 -> 81,172 B, measured locally (linux) at 26,087 B brotli / 81,172 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: "26.10 KB", - capMinified: 81112, + capMinified: 81172, alias }, { @@ -4104,8 +4116,9 @@ module.exports = [ // Unread key beside a held sibling publishes at flush (#4146), re-measured after merging next @ 8c75f82f (2026-10-19): 31.98 -> 32.02 KB, measured locally (linux) at 32,002 B brotli / 101,548 B minified (+48 B minified over next). // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 32.02 -> 32.13 KB, recorded minified 101,548 -> 101,651 B, measured locally (linux) at 32,111 B brotli / 101,651 B minified (+103 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 32.13 KB unchanged, recorded minified 101,651 -> 101,677 B (+26 B), measured in CI at 32,067 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 32.13 KB (unchanged), recorded minified 101,677 -> 101,737 B, measured locally (linux) at 32,091 B brotli / 101,737 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: "32.13 KB", - capMinified: 101677, + capMinified: 101737, alias }, { @@ -5024,6 +5037,7 @@ module.exports = [ // Re-recorded on next @ fb6006eb (2026-10-19, accepted by the maintainer): recorded minified 101,200 -> 101,246 B, measured locally (linux) at 33,107 B brotli. #4156 grew this scenario without re-recording it, so next sat past the 20 B minified allowance and brotli noise failed unrelated PRs. Cap unchanged. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 33.12 -> 33.16 KB, recorded minified 101,246 -> 101,352 B, measured locally (linux) at 33,149 B brotli / 101,352 B minified (+106 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 33.16 KB -> 33.18 KB, recorded minified 101,352 -> 101,384 B (+32 B), measured in CI at 33,166 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 33.18 -> 33.20 KB, recorded minified 101,384 -> 101,444 B, measured locally (linux) at 33,190 B brotli / 101,444 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: floorCaps["page: base server components (hydrating + dynamic + frames + sf reference)"], capMinified: floorMinified["page: base server components (hydrating + dynamic + frames + sf reference)"], @@ -5362,6 +5376,7 @@ module.exports = [ // Re-recorded on next @ fb6006eb (2026-10-19, accepted by the maintainer): recorded minified 114,737 -> 114,782 B, measured locally (linux) at 37,341 B brotli. #4156 grew this scenario without re-recording it, so next sat past the 20 B minified allowance and brotli noise failed unrelated PRs. Cap unchanged. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 37.37 -> 37.46 KB, recorded minified 114,782 -> 114,901 B, measured locally (linux) at 37,442 B brotli / 114,901 B minified (+119 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 37.46 KB unchanged, recorded minified 114,901 -> 114,922 B (+21 B), measured in CI at 37,410 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 37.46 -> 37.48 KB, recorded minified 114,922 -> 114,982 B, measured locally (linux) at 37,467 B brotli / 114,982 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: floorCaps["page: live server components (base + live/GET + action + isPending/latest)"], capMinified: floorMinified["page: live server components (base + live/GET + action + isPending/latest)"], @@ -5518,8 +5533,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 35.14 KB -> 35.16 KB, measured in CI at 35,148 B brotli / 107,588 B minified (+38 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 35.16 -> 35.19 KB, recorded minified 107,588 -> 107,701 B, measured locally (linux) at 35,175 B brotli / 107,701 B minified (+113 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 35.19 KB -> 35.23 KB, recorded minified 107,701 -> 107,725 B (+24 B), measured in CI at 35,212 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 35.23 KB (unchanged), recorded minified 107,725 -> 107,785 B, measured locally (linux) at 35,212 B brotli / 107,785 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: "35.23 KB", - capMinified: 107725, + capMinified: 107785, alias: pageAlias }, { @@ -5645,8 +5661,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 41.17 KB -> 41.23 KB, measured in CI at 41,215 B brotli / 122,766 B minified (+29 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 41.23 -> 41.31 KB, recorded minified 122,766 -> 122,880 B, measured locally (linux) at 41,294 B brotli / 122,880 B minified (+114 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 41.31 KB unchanged, recorded minified 122,880 -> 122,907 B (+27 B), measured in CI at 41,283 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 41.31 KB (unchanged), recorded minified 122,907 -> 122,967 B, measured locally (linux) at 41,300 B brotli / 122,967 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. limit: "41.31 KB", - capMinified: 122907, + capMinified: 122967, alias: pageAlias }, { @@ -5842,8 +5859,9 @@ module.exports = [ // Re-recorded on next @ fb6006eb (2026-10-19, accepted by the maintainer): recorded minified 125,035 -> 125,074 B, measured locally (linux) at 40,538 B brotli. #4156 grew this scenario without re-recording it, so next sat past the 20 B minified allowance and brotli noise failed unrelated PRs. Cap unchanged. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 40.58 -> 40.71 KB, recorded minified 125,074 -> 125,181 B, measured locally (linux) at 40,699 B brotli / 125,181 B minified (+107 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): cap 40.71 KB unchanged, recorded minified 125,181 -> 125,207 B (+26 B), measured in CI at 40,645 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "40.71 KB", - capMinified: 125207, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 40.71 -> 40.72 KB, recorded minified 125,207 -> 125,267 B, measured locally (linux) at 40,706 B brotli / 125,267 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "40.72 KB", + capMinified: 125267, alias: pageAlias, conditions: solidConditions, compile: { hydratable: true } @@ -6015,8 +6033,9 @@ module.exports = [ // Stale staged error cleared on re-run (#4109, 2026-10-19, over next @ fda29a4c): 46.76 KB -> 46.79 KB, measured in CI at 46,776 B brotli / 140,055 B minified (+29 B minified over next): a re-run pass drops an earlier pass's staged error before it computes, so a recompute that no longer throws does not publish the old one. Correctness; Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB; recorded minified = measured. // Lazy memo read through a rebuilt child memo (#4142, 2026-10-19, over next @ a9b9f9e4, accepted by the maintainer): 46.79 -> 46.86 KB, recorded minified 140,055 -> 140,165 B, measured locally (linux) at 46,845 B brotli / 140,165 B minified (+110 B minified over the recorded size): a disposal during a pending pass defers releasing lazy memos until the pass ends, so a memo the rebuilt child reads again is not released and re-run. Correctness; CI re-bases. // Every comparator call guarded, default comparators on a fast path (#4111, 2026-10-20, over next @ 6371b910): 46.86 KB -> 46.90 KB, recorded minified 140,165 -> 140,198 B (+33 B), measured in CI at 46,884 B brotli. `isSame` is the one guarded comparator call (a NotReady read is a change, any other throw goes to the node's boundary, A3), with `isEqual` on a fast path so the propagation benches keep next's speed. Size-Exception accepted by the maintainer (2026-10-19). Cap at measured + 10 B rounded up to 0.01 KB, never lowered here; recorded minified = measured. - limit: "46.90 KB", - capMinified: 140198, + // Writable memo write clears its error without a torn read (#4110, 2026-10-20, over next @ 7014aca4, accepted by the maintainer): 46.90 -> 46.91 KB, recorded minified 140,198 -> 140,258 B, measured locally (linux) at 46,896 B brotli / 140,258 B minified (+60 B minified over the recorded size), which includes #4163's +9 B merged without re-recording: a write to an errored writable memo recovers it at commit and keeps the error shown until then, and clears an error a pass staged under the same hold. Correctness; matches CI's numbers. + limit: "46.91 KB", + capMinified: 140258, alias: pageAlias, conditions: solidConditions, compile: { hydratable: true }