Skip to content

fix(engine): stop telling a bare-getter store that no store is registered - #1170

Merged
divshekhar merged 3 commits into
reticlehq:mainfrom
drakeo338:claude/1146-fix
Sep 28, 2026
Merged

divshekhar merged 3 commits into
reticlehq:mainfrom
drakeo338:claude/1146-fix

Conversation

@drakeo338

Copy link
Copy Markdown
Contributor

What & why

Closes #1146

registerStore('app', () => state) registers a readable store with no subscribe, so a state assertion passes off it while the same response says "no store is registered" and tells the reader to call registerStore(name, getState), already done. stateUnwatched means no subscribable store, and the gap can't tell that app from one with nothing registered, or from a React app whose only store is Reticle's own render-meter getter. The sentence now says no subscribable store is registered, true in all three cases, drops the false DOM-fallback claim, and asks for registerStore(name, store) or registerStore(name, getState, subscribe). This is the minimum the issue names; a dedicated gap kind is a follow-up.

How it was verified

Added a unit test per layer, plus an end-to-end one through reticle_assert. Reverted the fix: four of five fail without it. The fifth, the React-only case, already passes on main — a regression guard, not a failing-first test.

Gates run

  • pnpm lint && pnpm typecheck && pnpm test:unit (~2 min — always)
  • pnpm test:e2e (~8 min) — touched the tool surface, core, an observer, or telemetry
  • pnpm gate:install (~15 min) — touched reticle init, vite-plugin, next, or babel-plugin
  • pnpm test:e2e:desktop (~3 min) — touched adapters/realm/electron, adapters/realm/tauri, or desktop capture
  • None of the above tiers apply to this change

Checklist

  • Every commit is signed off (git commit -s) — CI's DCO check fails the PR without it. Already pushed? git rebase --signoff origin/main && git push --force-with-lease
  • Tests added/updated (RED → GREEN); the change is covered by a test that would fail without it
  • No any, no free strings (wire strings live in @reticlehq/core), no non-null !
  • No console.log or internal tracking codes left in the diff
  • Each changed file is under the 1000-line cap
  • Docs updated, and a user-facing change adds a new file under .changes/ (never edit CHANGELOG.md — that file is assembled at release time, and editing it is what makes PRs conflict; format in .changes/README.md)
  • Security-affecting? Auth/redaction/trust-boundary changes keep the localhost-only, no-app-data-leaves-the-machine, no-arbitrary-JS posture (usage telemetry stays anonymous + opt-out per docs/telemetry.md) and are covered by a test

…ered

registerStore('app', () => state) registers a store reticle_state can
read, so a state assertion passes off it, but with no subscribe the
state channel stays unwatched. The no-store-registered gap read that as
"no store is registered", said the assertion fell back to the DOM, and
told the reader to call registerStore(name, getState), the call they had
already made (reticlehq#1146).

stateUnwatched means no subscribable store, and the gap cannot tell an
app with a bare getter from one with nothing registered, or from a React
app whose only store is the render meter Reticle registers itself. So
the sentence now says no subscribable store is registered, which is true
in all three cases, and the cost no longer claims a DOM fallback. The
remedy asks for registerStore(name, store) or registerStore(name,
getState, subscribe), and the self-instrument proposal for the same gap
passes the store itself instead of a getter.

Closes reticlehq#1146

Signed-off-by: drakeo338 <paranoyouz@gmail.com>
@github-actions

Copy link
Copy Markdown

Thanks for your first pull request to Reticle! A maintainer aims to review within two days. Before then, pnpm verify locally catches most of what CI will, and CONTRIBUTING.md explains the rest. If CI does not start, a maintainer needs to approve it for first-time contributors; that is normal.

@github-actions github-actions Bot added area/core Affects packages/core area/server Affects packages/server area/docs Documentation and docs site labels Sep 28, 2026
@greptile-apps

greptile-apps Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Fixes error messages about store registration.

The PR appears safe to merge, with a non-blocking correction needed to the no-store explanation.

Findings

  1. P2 No-store message implies readability ▶

Summary

The PR changes the unwatched-state gap and its suggested fix so a readable bare-getter store is not described as unregistered. It also updates the instrumentation proposal and adds unit and assertion-path tests.

  • The revised cost text still implies state is readable when no store is registered.

Reviews (1) · Last reviewed commit: "fix(engine): stop telling a bare-getter ..."

declaredNothing
? 'every verdict here rests on what the DOM happens to show, and reticle_state will stay empty however many flows are driven'
: 'the assertion could not be answered from the deterministic channel and had to fall back to what the DOM happens to show',
: 'no state change is observed, so state can at best be read as it stands and never seen changing',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No-store message implies readability When an app has test IDs or declared signals but no registered store, a state assertion still reaches this gap. The state read returns no stores and the assertion is inconclusive. Saying state “can at best be read as it stands” suggests the agent can read it on demand, which is not true in this case and may send them looking for state that is unavailable.

The no-subscribable-store gap's cost text said state "can at best be
read as it stands", which is only true of a bare-getter store. The same
facts also describe an app that registered no store at all, or a React
app whose only store is the render meter Reticle registers itself, and
in both of those nothing can be read, not even a one-off snapshot
(greptile review on PR reticlehq#1170).

The sentence now hedges on whether a read is possible at all, which
holds for all three cases the facts cannot tell apart.

Signed-off-by: drakeo338 <paranoyouz@gmail.com>
@divshekhar

Copy link
Copy Markdown
Contributor

All three places the contradiction lived are fixed (the engine sentence, the core fix text, the server proposal), and registerStore('cart', useCart) does the right thing with a Zustand hook because isStoreLike accepts it. Two small things: drop the "greptile finding on PR #1170" line from the test comment, since review-bot references do not belong in shipped test prose, and tick a box in "Gates run" so we know what you ran. Kicked off CI.

The greptile PR-number pointer does not belong in shipped test prose.

Signed-off-by: drakeo338 <paranoyouz@gmail.com>
@drakeo338

Copy link
Copy Markdown
Contributor Author

Dropped the greptile reference from the test comment; the pnpm test:e2e box stays unchecked because the battery didn't finish in this sandbox, though CI's own run of it on this commit is green.

@divshekhar divshekhar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both nits addressed. Good to go once CI is green.

@divshekhar
divshekhar added this pull request to the merge queue Sep 28, 2026
Merged via the queue into reticlehq:main with commit 2afb9a5 Sep 28, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Affects packages/core area/docs Documentation and docs site area/server Affects packages/server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[agent] A store registered with a bare getter is reported as "no store is registered" in the same response that read it

2 participants