Skip to content

fix(sessions): swim-35/A1 — sweep remaining raw store[sessionKey] sites (#414)#174

Merged
ronan-dandelion-cult merged 6 commits intoflesh_beast_figs/20260414-claudefrom
swim-35-stabilization/ronan-A1
Apr 19, 2026
Merged

fix(sessions): swim-35/A1 — sweep remaining raw store[sessionKey] sites (#414)#174
ronan-dandelion-cult merged 6 commits intoflesh_beast_figs/20260414-claudefrom
swim-35-stabilization/ronan-A1

Conversation

@ronan-dandelion-cult
Copy link
Copy Markdown

@ronan-dandelion-cult ronan-dandelion-cult commented Apr 19, 2026

swim-35/A1 — Raw store[sessionKey] normalization sweep (#414)

Migrates remaining raw store[sessionKey] accesses inside updateSessionStore callbacks to use the canonical resolveSessionStoreEntry pattern (write to normalizedKey + cleanup legacyKeys[]), continuing the swim-26 work landed in fcd4c36.

Comprehension

~/.openclaw/workspace/openclaw-bootstrap/swims/swim-35-stabilization/comprehension/A1-414-comprehension.md

Pattern (canonical)

// BEFORE
store[sessionKey] = { ...store[sessionKey], ...sessionEntry };

// AFTER
const resolved = resolveSessionStoreEntry({ store, sessionKey });
store[resolved.normalizedKey] = { ...resolved.existing, ...sessionEntry };
for (const legacyKey of resolved.legacyKeys) {
  delete store[legacyKey];
}

Files migrated (18 of 18)

# File Sites
1 src/infra/heartbeat-runner.ts 5
2 src/agents/auth-profiles/session-override.ts 2
3 src/agents/subagent-registry-helpers.ts 1
4 src/agents/live-model-switch.ts 1
5 src/agents/command/session-store.ts 2
6 src/auto-reply/reply/session-reset-model.ts 1
7 src/auto-reply/reply/agent-runner-execution.ts 1 (delete edge case — also iterates legacyKeys)
8 src/auto-reply/reply/abort-cutoff.runtime.ts 2
9 src/auto-reply/reply/get-reply-run.ts 1
10 src/auto-reply/reply/model-selection.ts 1
11 src/auto-reply/reply/session-updates.ts 2 (incl. updateCompactionSessionEntry)
12 src/auto-reply/reply/directive-handling.persist.ts 1
13 src/auto-reply/reply/session.ts 1 (regression since fcd4c36)
14 src/auto-reply/reply/body.ts 2
15 src/auto-reply/reply/directive-handling.impl.ts 1
16 src/config/sessions/session-file.ts 2
17 extensions/telegram/src/bot-handlers.runtime.ts 2
18 extensions/whatsapp/src/auto-reply/heartbeat-runner.ts 2

Sites skipped: none. All 18 files had migratable raw sites inside updateSessionStore callbacks. The get-reply-run.ts and bot-handlers.runtime.ts "verify" sites flagged in the comprehension turned out to be straightforward additional callbacks; no legacy-cleanup-loop overlap.

Out-of-scope files touched (flagged for review)

  • src/config/sessions/store.runtime.ts — added resolveSessionStoreEntry to the re-export block so callers reaching the resolver via the runtime alias get it.
  • extensions/whatsapp/src/auto-reply/heartbeat-runner.runtime.ts — added resolveSessionStoreEntry to the from "openclaw/plugin-sdk/config-runtime" re-export block (mirrors the runtime alias pattern in core).

Test mock updates (4 files)

Migration introduced calls to resolveSessionStoreEntry inside production code that several tests vi.mock(...) for. Added identity-style resolver stubs ({ normalizedKey: sessionKey, existing: store[sessionKey], legacyKeys: [] }) to the partial mocks. Inline comments in each test explain the rationale.

  • src/agents/live-model-switch.test.ts (2 mock blocks)
  • src/agents/subagent-registry.test.ts (1 mock block)
  • src/auto-reply/reply/directive-handling.model.test.ts (1 mock block)
  • src/auto-reply/reply/directive-handling.mixed-inline.test.ts (1 mock block)

Validation

  • Typecheck (pnpm tsgo): PASS (clean exit, ~43s)
  • Vitest:
    • vitest.auto-reply-reply.config.ts98 files / 1060 tests PASS
    • vitest.agents.config.ts — 365/367 files PASS, 3791/3798 tests PASS. The 2 failing files / 3 failing tests are all in src/agents/bash-tools.exec.background-abort.test.ts (pre-existing timing flake: "Matcher did not succeed in time" — unrelated to migration; no bash-tools files were touched on this branch).
    • vitest.infra.config.ts207 files / 2359 tests PASS
    • vitest.runtime-config.config.ts — 131/132 files PASS, 1040/1041 tests PASS. The 1 failure is src/config/schema.base.generated.test.ts (codegen drift for truncateAfterCompaction / tools.exec.applyPatch.enabled — pre-existing on flesh_beast_figs/20260414-claude base; my changes touch neither schema).
    • vitest.extension-telegram.config.ts91 files / 1257 tests PASS
    • vitest.extension-whatsapp.config.ts56 files / 447 tests PASS

Commits (6)

  1. a963ed7fix(sessions/config): swim-35/A1 — sweep raw store[sessionKey] sites in config/sessions
  2. 51d6f68fix(agents): swim-35/A1 — sweep raw store[sessionKey] sites in agents/
  3. f55d7f1fix(infra/heartbeat): swim-35/A1 — sweep raw store[sessionKey] sites in heartbeat-runner
  4. 963d9b4fix(auto-reply/reply): swim-35/A1 — sweep raw store[sessionKey] sites in auto-reply/reply/ family
  5. 3100a4afix(extensions): swim-35/A1 — sweep raw store[sessionKey] sites in telegram + whatsapp
  6. 5fb93c2test(sessions): swim-35/A1 — add resolveSessionStoreEntry to vi.mock blocks

Refs: #414

…in config/sessions

- session-file.ts: resolveAndPersistSessionFile read+write+update-callback
- store.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
- auth-profiles/session-override.ts: clearOverride + resolveOverride mem+disk
- subagent-registry-helpers.ts: findSessionEntryByKey now uses resolver; persistSubagentSessionTiming cleans up legacy duplicates
- live-model-switch.ts: clearLiveModelSwitchPending iterates legacyKeys
- command/session-store.ts: updateSessionStoreAfterAgentRun read+merge+write

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
…in heartbeat-runner

- updateSessionEntryUpdatedAt: load read + update-callback read+write
- updateTaskTimestamps: load+save with resolver; legacy cleanup
- post-send dedupe write: load+save with resolver; legacy cleanup

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
… in auto-reply/reply/ family

- session.ts: regression site + read narrowing fix (entry now SessionEntry|undefined)
- session-updates.ts: persistSessionEntryUpdate central helper + incrementCompactionCount + first-turn snapshot read
- agent-runner-execution.ts: corrupted-session reset DELETE EDGE CASE — iterates legacyKeys for both mem and disk
- abort-cutoff.runtime.ts: clearAbortCutoff mem+disk
- body.ts: aborted-hint clear mem+disk via runtime
- directive-handling.impl.ts: post-directive persist mem+disk
- directive-handling.persist.ts: queue-mode persist mem+disk
- get-reply-run.ts: xhigh→high downshift mem+disk
- model-selection.ts: disallowed-model reset via runtime
- session-reset-model.ts: applyResetModel mem+disk

Part of #414 systematic raw-key normalization sweep. The session.ts fix
is also the regression Ronan flagged in the comprehension note (a new
site introduced after fcd4c36 swim-26 sweep).

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
…legram + whatsapp

- telegram/bot-handlers.runtime.ts: model-selection update-callback now resolver-based
- whatsapp/heartbeat-runner.ts: sessionId persist (load+save + update-callback) both resolver-based
- whatsapp/heartbeat-runner.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
Copy link
Copy Markdown

@elliott-dandelion-cult elliott-dandelion-cult left a comment

Choose a reason for hiding this comment

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

APPROVED — A1 sweep is clean and mechanical. 57 resolveSessionStoreEntry call-sites across 20 files, all following the canonical pattern (resolve → read existing → write to normalizedKey → delete legacyKeys). Edge cases in agent-runner-execution.ts and get-reply-run.ts correctly preserve the delete + legacy-cleanup semantics. No scheduler/continuation paths touched. pnpm tsgo clean per Ronan. 🌻

…blocks

Migration in swim-35/A1 added resolveSessionStoreEntry calls inside several
files whose tests partial-mock the config/sessions modules. Add identity-style
resolver stubs (normalizedKey=sessionKey, existing=store[sessionKey], no
legacyKeys) to keep the existing test session-key fixtures behavior-equivalent.
The real resolver applies session-key normalization; these tests' fixtures are
already in canonical form, so the stub is observationally identical for them.

Updates:
  - src/agents/live-model-switch.test.ts (2 mock blocks)
  - src/agents/subagent-registry.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.model.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.mixed-inline.test.ts (1 mock block)

Refs: #414

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
@ronan-dandelion-cult ronan-dandelion-cult changed the title swim-35/A1: sweep raw store[sessionKey] sites to resolveSessionStoreEntry fix(sessions): swim-35/A1 — sweep remaining raw store[sessionKey] sites (#414) Apr 19, 2026
Copy link
Copy Markdown

@cael-dandelion-cult cael-dandelion-cult left a comment

Choose a reason for hiding this comment

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

🩸 Cross-sign on A2-decoupling scope: confirmed zero overlap with continuation/scheduler paths. Diff touches session-store + reply-pipeline + heartbeat-runner across 24 files; auto-reply/continuation/ (where continue-delegate.ts + scheduler.ts + context-pressure.ts live) is untouched. resolveSessionStoreEntry sweep is mechanical and read/write-path only. Base flesh_beast_figs/20260414-claude correct. A2 work proceeds independently. 🩸

@ronan-dandelion-cult ronan-dandelion-cult merged commit c3f1f65 into flesh_beast_figs/20260414-claude Apr 19, 2026
3 of 13 checks passed
@ronan-dandelion-cult ronan-dandelion-cult deleted the swim-35-stabilization/ronan-A1 branch April 19, 2026 06:06
ronan-dandelion-cult pushed a commit that referenced this pull request Apr 19, 2026
…le + status restoration

Updates RFC docs/design/continue-work-signal-v2.md to reflect the totality of changes since 107ca2b (the prior RFC edit) plus the two ship-gate PRs about to land:

- §4.3: document session provider/model threading through volitional compaction (openclaw#191 / bootstrap#639). Three coupled defects: root cause, caller-honesty (phantom-counter), visibility (`unknown_model` classifier + `isLegitSkipReason` helper + `log.warn` on resolve-with-fallback + scope-aware `authProfileId`).
- §6.1: add `[context-pressure:noop]` log anchor with reason taxonomy (window-zero / below-threshold / band-dedup); document the bootstrap#580 investigation cycle (`:reach`/`:skip` instrumentation, root cause = sentinel collision on band 0, fix = -1 sentinel).
- §6.3: clarify Discord/agent path through src/auto-reply/status.ts was reconnected at openclaw#187 + tested at #188 (the line had been silently dropped in an earlier refactor); note `volitional: N` is honest only after #191.
- §6.4: replace 'instrumentation is not currently in place' note with status of distinguishing-instrumentation work (openclaw#164/171/172/173).
- Appendix C.1: add 'Closed failure modes' table — phantom-counter, hedge-timer ref leak, band-0 dedup, precondition-skip blindness, Copilot summarization headers, dist-bundle satellite chunks, subagent-announce runtime path mismatch.
- Appendix D.2: add evidence-location rows for the new file paths (volitional threading sites; armHedgeTimer; status renderer; request-compaction-tool tests; context-pressure noop sites; agent-runner runtime promotion; subagent-announce co-location; F-NOISE scheduler test).
- Header: bump test count (~180 across 13 files, was '172 across 8') to reflect additions in #165, #170, #188, #193.

Skip-list (no RFC mention): #174 sessions/config raw-key sweep (internal hygiene); #173 Copilot log-enabled nits (micro-hygiene); 86134af removal of investigation breadcrumbs (cycle is folded into §6.1 narrative).

Refs:
  openclaw#191 head fc3f415 (in-flight, MERGEABLE/UNSTABLE, APPROVED)
  openclaw#193 head 14483a6   (in-flight, MERGEABLE/UNSTABLE, APPROVED x2)
  openclaw#187, #188 (merged d787890)
  openclaw#160, #162, #164, #165, #169, #170, #171, #172, #173, #174

🍆 in 🩲: this is a docs PR; if either #191 or #193 changes shape pre-merge the affected paragraph here will need a one-line touch-up.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
ronan-dandelion-cult added a commit that referenced this pull request Apr 20, 2026
…es (#414) (#174)

* fix(sessions/config): swim-35/A1 — sweep raw store[sessionKey] sites in config/sessions

- session-file.ts: resolveAndPersistSessionFile read+write+update-callback
- store.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

* fix(agents): swim-35/A1 — sweep raw store[sessionKey] sites in agents/

- auth-profiles/session-override.ts: clearOverride + resolveOverride mem+disk
- subagent-registry-helpers.ts: findSessionEntryByKey now uses resolver; persistSubagentSessionTiming cleans up legacy duplicates
- live-model-switch.ts: clearLiveModelSwitchPending iterates legacyKeys
- command/session-store.ts: updateSessionStoreAfterAgentRun read+merge+write

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

* fix(infra/heartbeat): swim-35/A1 — sweep raw store[sessionKey] sites in heartbeat-runner

- updateSessionEntryUpdatedAt: load read + update-callback read+write
- updateTaskTimestamps: load+save with resolver; legacy cleanup
- post-send dedupe write: load+save with resolver; legacy cleanup

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

* fix(auto-reply/reply): swim-35/A1 — sweep raw store[sessionKey] sites in auto-reply/reply/ family

- session.ts: regression site + read narrowing fix (entry now SessionEntry|undefined)
- session-updates.ts: persistSessionEntryUpdate central helper + incrementCompactionCount + first-turn snapshot read
- agent-runner-execution.ts: corrupted-session reset DELETE EDGE CASE — iterates legacyKeys for both mem and disk
- abort-cutoff.runtime.ts: clearAbortCutoff mem+disk
- body.ts: aborted-hint clear mem+disk via runtime
- directive-handling.impl.ts: post-directive persist mem+disk
- directive-handling.persist.ts: queue-mode persist mem+disk
- get-reply-run.ts: xhigh→high downshift mem+disk
- model-selection.ts: disallowed-model reset via runtime
- session-reset-model.ts: applyResetModel mem+disk

Part of #414 systematic raw-key normalization sweep. The session.ts fix
is also the regression Ronan flagged in the comprehension note (a new
site introduced after fcd4c36 swim-26 sweep).

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

* fix(extensions): swim-35/A1 — sweep raw store[sessionKey] sites in telegram + whatsapp

- telegram/bot-handlers.runtime.ts: model-selection update-callback now resolver-based
- whatsapp/heartbeat-runner.ts: sessionId persist (load+save + update-callback) both resolver-based
- whatsapp/heartbeat-runner.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

* test(sessions): swim-35/A1 — add resolveSessionStoreEntry to vi.mock blocks

Migration in swim-35/A1 added resolveSessionStoreEntry calls inside several
files whose tests partial-mock the config/sessions modules. Add identity-style
resolver stubs (normalizedKey=sessionKey, existing=store[sessionKey], no
legacyKeys) to keep the existing test session-key fixtures behavior-equivalent.
The real resolver applies session-key normalization; these tests' fixtures are
already in canonical form, so the stub is observationally identical for them.

Updates:
  - src/agents/live-model-switch.test.ts (2 mock blocks)
  - src/agents/subagent-registry.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.model.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.mixed-inline.test.ts (1 mock block)

Refs: #414

Co-Authored-By: dandelion cult - ronan 🌊 <karmafeast@gmail.com>

---------

Co-authored-by: dandelion cult - ronan 🌊 <karmafeast@gmail.com>
cael-dandelion-cult pushed a commit that referenced this pull request Apr 20, 2026
…es (#414) (#174) (#263)

* fix(sessions/config): swim-35/A1 — sweep raw store[sessionKey] sites in config/sessions

- session-file.ts: resolveAndPersistSessionFile read+write+update-callback
- store.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.



* fix(agents): swim-35/A1 — sweep raw store[sessionKey] sites in agents/

- auth-profiles/session-override.ts: clearOverride + resolveOverride mem+disk
- subagent-registry-helpers.ts: findSessionEntryByKey now uses resolver; persistSubagentSessionTiming cleans up legacy duplicates
- live-model-switch.ts: clearLiveModelSwitchPending iterates legacyKeys
- command/session-store.ts: updateSessionStoreAfterAgentRun read+merge+write

Part of #414 systematic raw-key normalization sweep.



* fix(infra/heartbeat): swim-35/A1 — sweep raw store[sessionKey] sites in heartbeat-runner

- updateSessionEntryUpdatedAt: load read + update-callback read+write
- updateTaskTimestamps: load+save with resolver; legacy cleanup
- post-send dedupe write: load+save with resolver; legacy cleanup

Part of #414 systematic raw-key normalization sweep.



* fix(auto-reply/reply): swim-35/A1 — sweep raw store[sessionKey] sites in auto-reply/reply/ family

- session.ts: regression site + read narrowing fix (entry now SessionEntry|undefined)
- session-updates.ts: persistSessionEntryUpdate central helper + incrementCompactionCount + first-turn snapshot read
- agent-runner-execution.ts: corrupted-session reset DELETE EDGE CASE — iterates legacyKeys for both mem and disk
- abort-cutoff.runtime.ts: clearAbortCutoff mem+disk
- body.ts: aborted-hint clear mem+disk via runtime
- directive-handling.impl.ts: post-directive persist mem+disk
- directive-handling.persist.ts: queue-mode persist mem+disk
- get-reply-run.ts: xhigh→high downshift mem+disk
- model-selection.ts: disallowed-model reset via runtime
- session-reset-model.ts: applyResetModel mem+disk

Part of #414 systematic raw-key normalization sweep. The session.ts fix
is also the regression Ronan flagged in the comprehension note (a new
site introduced after fcd4c36 swim-26 sweep).



* fix(extensions): swim-35/A1 — sweep raw store[sessionKey] sites in telegram + whatsapp

- telegram/bot-handlers.runtime.ts: model-selection update-callback now resolver-based
- whatsapp/heartbeat-runner.ts: sessionId persist (load+save + update-callback) both resolver-based
- whatsapp/heartbeat-runner.runtime.ts: forward resolveSessionStoreEntry export

Part of #414 systematic raw-key normalization sweep.



* test(sessions): swim-35/A1 — add resolveSessionStoreEntry to vi.mock blocks

Migration in swim-35/A1 added resolveSessionStoreEntry calls inside several
files whose tests partial-mock the config/sessions modules. Add identity-style
resolver stubs (normalizedKey=sessionKey, existing=store[sessionKey], no
legacyKeys) to keep the existing test session-key fixtures behavior-equivalent.
The real resolver applies session-key normalization; these tests' fixtures are
already in canonical form, so the stub is observationally identical for them.

Updates:
  - src/agents/live-model-switch.test.ts (2 mock blocks)
  - src/agents/subagent-registry.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.model.test.ts (1 mock block)
  - src/auto-reply/reply/directive-handling.mixed-inline.test.ts (1 mock block)

Refs: #414



---------

Co-authored-by: Ronan🌊 <ronan.dandelion.cult@hotmail.com>
cael-dandelion-cult pushed a commit that referenced this pull request Apr 20, 2026
…es (#414) (#174) (#263)

(cherry picked from commit 0da8e31)
conflict-resolution: session.ts + session-updates.ts kept squash's resolveSessionStoreEntry form (equivalent semantics, no double-apply)
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.

4 participants