Skip to content

Keep memo key reads out of untracked callers (#122) - #126

Merged
ryanbliss merged 1 commit into
claude/peaceful-bardeen-isdb3a-118from
claude/peaceful-bardeen-isdb3a-122
Oct 8, 2026
Merged

ryanbliss merged 1 commit into
claude/peaceful-bardeen-isdb3a-118from
claude/peaceful-bardeen-isdb3a-122

Conversation

@ryanbliss

@ryanbliss ryanbliss commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Fixes #122. Stacked on #125.

When a keyed memo had to re-run its key, runKeyedMemo called replayDependencyComparisonAccesses without a guard. That happens on a memo's first read, and also after one of its key inputs changes. So even when the caller had paused tracking with Retree.untracked, the outer selector or effect inherited the key's reads. Validated hits went through replayTrappedMemo, which already checked isDependencyTrackingActive().

The check now lives in replayDependencyComparisonAccesses, so every replay honors it. runFrame resets the pause depth for nested frames, so a memo's own key frame still tracks its reads for gating.

Intended side effect: a keyed memo read inside another memo's body (which also pauses tracking) no longer replays its key into the enclosing frame on a cold run. That matches the warm path and runMemoBody's design.

Performance: the check stays the cheap isDependencyTrackingActive() exit outside any frame. Review measured warm memo hits in a 2M-read loop at the same speed as before this change.

Tests

  • A new it.each in memo.spec.ts covers a cold memo under Retree.select and Retree.effect, and a stale memo (key input changed) under Retree.select. All three fail without the fix.
  • npm run test (with NODE_PATH unset, see Keep the query baseline from owning cached results (#117) #124), core typecheck and npm run doctor all pass.
  • An Opus subagent reviewed this. I took its performance, wording and coverage findings.

A keyed memo whose key had to re-run (on its first read, or after a key
input changed) replayed its key reads into the enclosing frame even
when the caller had paused tracking with Retree.untracked, so the outer
selector or effect subscribed to them. Validated hits already skipped
the replay. The check now lives in replayDependencyComparisonAccesses,
so every replay honors it.

Claude-Session: https://claude.ai/code/session_01Us9f7SPLJUYScpdDnA8oM4
@ryanbliss
ryanbliss added this pull request to stack #128 October 8, 2026 21:18
@ryanbliss
ryanbliss merged commit 309ed6b into main Oct 8, 2026
3 checks passed
@ryanbliss
ryanbliss deleted the claude/peaceful-bardeen-isdb3a-122 branch October 8, 2026 21:24
ryanbliss added a commit that referenced this pull request Oct 8, 2026
A keyed memo whose key had to re-run (on its first read, or after a key
input changed) replayed its key reads into the enclosing frame even
when the caller had paused tracking with Retree.untracked, so the outer
selector or effect subscribed to them. Validated hits already skipped
the replay. The check now lives in replayDependencyComparisonAccesses,
so every replay honors it.

Claude-Session: https://claude.ai/code/session_01Us9f7SPLJUYScpdDnA8oM4
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.

Cold @memo key reads leak into the outer selector under Retree.untracked

2 participants