Skip to content

refactor(signals): store node reads select by readerSeesCommitted (Rule 1, one implementation) - #3516

Closed
ryansolid wants to merge 2 commits into
refactor/shared-read-predicatesfrom
refactor/store-node-rule1
Closed

ryansolid wants to merge 2 commits into
refactor/shared-read-predicatesfrom
refactor/store-node-rule1

Conversation

@ryansolid

Copy link
Copy Markdown
Member

Stacked on #3515. Step 2 of DESIGN-CONSOLIDATION move 3b.

What moved

nodeValue — the store's untracked node-read selection — restated core read()'s committed-vs-staged arm by hand (inOwnerContext, a stale-of-foreign foreignHold twin, the HELD-truth mask). It now calls readerSeesCommitted (from #3515) with core's context selection (readerContext(): a root reads as its parent computed, context persists under untrack) behind the two store-only tunnels that stay in the store: latest() reaching this path for store keys (#3075) and authoritativeServe() (truth authors: the projection derive's draft, write-override).

Tracked store reads already went through readNode → core read()readerSeesCommitted, so after this every store node read — tracked or untracked — selects by one Rule 1 implementation.

Not zero-change: the twin was missing a precondition

A stale reader (render effect) whose untracked read is of a store key held by a foreign action was served committed (correct, A15 / A26) but never recorded for replay at the commit (heldFromStale's _gatedSubs contract, which the signal path performs). The effect stayed on the pre-action value permanently after the action settled. Signal twin: [0, 0, 1]; store on next: [0, 0].

Pinned as S4 in posture-store-parity.test.ts (signal and store now both [0, 0, 1]; the store pin fails on next).

This is exactly the pattern the consolidation is for — one rule, N sites, one site missing a precondition — and it was invisible to the suite, the oracles and the 621-cell matrix (no reader kind there is "untracked inside a stale reader"). Found only by handing the store the shared predicate and asking what changed.

Remaining gaps, pinned / noted

  • Backing twin (step 3): a key with no node goes through pendingBackingVisible / heldFromReader — same committed value, but there's no node to record the reader on, so no replay. Pinned it.fails beside S4. Rule 1's backing-level form is the next item.
  • Lane arm: laneReadsCommitted (Existing and newly revealed latest readers display different values #3460) now also applies to untracked store node reads as it did to tracked ones. No matrix cell or test distinguishes; the matrix's foreignLane × untracked store cells are identical.

Gate

check result
signals suite 2748 pass, 1 expected fail (the backing-twin pin)
visibility oracles + 621-cell posture matrix byte-identical to next
fuzzer seed 3289 × 1000 994 / 0 / 6 — same as next (signals-only, so expected)
solid-js / web 623 pass / same 12 pre-existing server-diagnostics failures as origin/next
size minified store −5 B, full bundle brotli −44 B vs #3515; no caps exceeded

Made with Cursor

ryansolid and others added 2 commits September 17, 2026 01:21
…bleOverride, one hasActiveOverride

Zero-semantic-change step 1 of DESIGN-CONSOLIDATION move 3b (one implementation
per rule). read()'s slow tail called the full committed-vs-staged arm inline;
it is now readerSeesCommitted(el, c, owner, noCommitted), documented as the rule
it enforces, for the store's backing selection and the verdict arms to adopt.
hasActiveOverride existed twice (lanes.ts, store.ts) and the composite
'hasActiveOverride && !unflushedOverride' was restated at five sites
(latestRead, computePendingState ×2, the store's reader selection, plus the
store's own visibleOverride) — one visibleOverride in core now.

Gate: signals suite green; visibility oracles and the 738-line posture matrix
report are byte-identical to next.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
…le 1, one implementation)

Step 2 of DESIGN-CONSOLIDATION move 3b. nodeValue — the store's untracked
node-read selection — restated core read()'s committed-vs-staged arm by hand
(inOwnerContext, a stale-of-foreign 'foreignHold' twin, the HELD-truth mask).
It now calls readerSeesCommitted with core's context selection (readerContext:
a root reads as its parent computed) behind the two store-only tunnels,
latest() (#3075) and authoritativeServe (truth authors).

Not zero-change — the twin was missing a precondition of the rule it copied:
a stale reader (render effect) whose untracked read is of a store key held by
a foreign action was served committed (correct, A15/A26) but never recorded
for replay at the commit (heldFromStale's _gatedSubs contract, which the
signal path performs), so the effect stayed on the pre-action value after the
action settled. Pinned as S4 in posture-store-parity (signal vs store, both
now [0, 0, 1]). The backing twin (no node: pendingBackingVisible /
heldFromReader) has the same gap and no node to record the reader on —
pinned it.fails as the step-3 item. The lane arm (laneReadsCommitted) now
also applies to untracked store node reads as it does to tracked ones; no
matrix cell or test distinguishes.

Gate: suite green (+2 pins, 1 expected fail); visibility oracles and the
621-cell posture matrix byte-identical to next; minified store −5 B, full
bundle brotli −44 B vs step 1.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
@changeset-bot

changeset-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cfd4dc0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@solidjs/signals Patch
test-integration Patch
@solidjs/web Patch
@solidjs/babel-plugin Patch
@solidjs/compiler Patch
@solidjs/diagnostics Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
solid-js Patch
@solidjs/universal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ryansolid

Copy link
Copy Markdown
Member Author

Superseded by #3523, which now targets next directly and carries this PR's commit (rebased) along with the rest of the stack. Closing so the move-3b work is one review rather than five.

Claude via Cursor

@ryansolid ryansolid closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant