Skip to content

test(signals): store oracle + four signal states; latest() seed leak and body-end visibility fixes - #3455

Merged
ryansolid merged 2 commits into
nextfrom
test/oracle-stores
Sep 15, 2026
Merged

ryansolid merged 2 commits into
nextfrom
test/oracle-stores

Conversation

@ryansolid

Copy link
Copy Markdown
Member

Follow-up to #3449 / #3451 (both merged). One commit, rebased onto next.

Oracle: 90 → 207 cells

The harness (cell vocabulary, nine readers, hold management, runner) moves to tests/visibility-oracle.harness.ts, shared by:

The store side tracked the signal side far more closely than expected (67/72 on the first run): A18 supersession — tracked pass derives from the landed truth, fresh reader born held, overlay stays displayed — works through store nodes exactly as through signals. #3434's store carve-out is about the body-end settle order, not landing supersession.

Runtime fixes

latest() leaked a projection's seed. latest(() => store.key) on an unresolved createStore(fn, seed) returned the seed; untracked and tracked reads correctly threw (A25). read() routes a latest() read to the companion before its firewall/status logic, and the leaf's own _value is the seed. latestRead now judges "uninitialized" on the leaf's owner (the firewall). verdict.ts only.

Body-end supersession read differently from landing supersession (3 oracle violations). After the action body ends and the override is superseded by the committed truth (#3427): a stale reader re-run by an unrelated write showed the truth while the display showed the override; a fresh mainline memo published the truth instead of being held; isPending read false while latest read the truth. One cause: the node had no _transition stamp — an override written inside an action goes straight into the transaction's _optimisticNodes without the adoption loop that stamps, and body-end stages nothing that would queue it. #2912 already ruled that an override node's owner is _overrideOwner; supersededRead and the verdict now resolve it (resolveTransition). A superseded read enters as a staged read whether the truth is staged or committed.

A latest() call captured the caller's block. Found while pinning the above: the latest() shadow's pull reads through supersededReadenterStagedRead; verdict pulls are excluded from born-held and so fell to the initTransition path — from an event handler, outside any flush. Verdict pulls are observations and now never enter from mainline. tests/body-end-supersession-visibility.test.ts reads the verdicts before the display checks on purpose.

Rulings recorded (2026-09-15)

  • A27: verdict-quiet through the window is a hydration invariant (server answers false; client must match on creation); the window's first real landing is initial-load class — like a boundary's first content reveal — and commits on arrival even when the re-asking input is action-held. From that landing on the node is an ordinary memo.
  • A18 body-end visibility: identical to a landing supersession; owner via _overrideOwner.
  • A29: verdict pulls never enter from mainline.
  • A7: uninitialized judged on the owner.

Verification

  • @solidjs/signals 178 files / 2014 · solid-js 618 · @solidjs/web 783 — green (one attribution-holds timing flake on one run; clean on two reruns and in isolation)
  • Oracle: 207 cells, zero violations; 15 observed (12 pre-flush cells parked on A28/fix(signals): writes become visible at flush — latest() reads the flushed staged world (A28) #3337; un-superseded/held-truth fresh-reader cells; held-truth isPending)
  • Brotli: all signals caps pass (core floor 8,806 of 8,850; verdict and supersession changes live outside the floor)

Co-authored-by: Cursor cursoragent@cursor.com

Made with Cursor

…eak and body-end visibility

Oracle grows from 90 to 207 cells. The harness (cell vocabulary, readers,
hold management, runner) moves to tests/visibility-oracle.harness.ts,
shared by the signal oracle (now 14 states: + body ended, un-superseded,
held truth, loading window over a held input) and a new store oracle
(8 states through plain stores, optimistic stores and projections).

Two runtime fixes the new cells found:

- latest(() => store.key) on an unresolved projection returned the SEED.
  read() routes a latest() read to the companion before its firewall
  logic, and the leaf's own _value is the seed; latestRead now judges
  "uninitialized" on the leaf's owner (the firewall) and throws like
  every other read (A25, A7).

- The body-end supersession window (#3427) read differently from a
  landing supersession: a stale re-run showed the committed truth beside
  a display still showing the override, a fresh mainline memo published
  it, isPending read false while latest read the truth. One cause: an
  override written inside an action never passes the adoption loop that
  stamps _transition, and body-end stages nothing that would queue it, so
  the node carried no stamp. Ownership for an override node is
  _overrideOwner (#2912); supersededRead and the verdict resolve it now.
  Pinning that exposed a fourth: a latest() pull through supersededRead
  fell to enterStagedRead's initTransition path and captured the caller's
  block — verdict pulls are observations and never enter from mainline.

Rulings recorded: A27 (verdict-quiet is a hydration invariant; the
window's first real landing is initial-load class even over a held
input), A18 body-end visibility, A29 verdict-pull note, A7 owner-judged.
Also a type fix in born-held (bornHeld narrowed to never).

Signals 2005 / solid 618 / web 783 green; brotli caps pass (core floor
8806 of 8850). Oracle: 207 cells, zero violations, 15 observed (12 on
A28/#3337).

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Sep 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e15b322

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

@codspeed

codspeed Bot commented Sep 15, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 172 untouched benchmarks


Comparing test/oracle-stores (e15b322) with next (0d8347a)

Open in CodSpeed

…visibility fixes (#3455)

Measured at 11267 B against next's 11213 (+54): supersededRead's owner
resolution and committed-truth entry, the verdict's body-end A18 (d)
branch, and uninitializedSource's owner walk — all in the verdict/
optimistic modules this scenario retains. Core floor and +createStore
stay in cap.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 34955159006

Coverage remained the same at 71.898%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1007
Covered Lines: 772
Line Coverage: 76.66%
Relevant Branches: 790
Covered Branches: 520
Branch Coverage: 65.82%
Branches in Coverage %: Yes
Coverage Strength: 15.1 hits per line

💛 - Coveralls

@ryansolid
ryansolid merged commit a8a8949 into next Sep 15, 2026
7 checks passed
@ryansolid
ryansolid deleted the test/oracle-stores branch September 15, 2026 10:18
ryansolid added a commit that referenced this pull request Sep 15, 2026
…ether tip it by 9 B

Each PR fit alone; the union measures 15809 B on next a8a8949 against
the 15800 cap. No source change.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants