refactor(sessions): move inbound meta, goals, and delivery reads behind the session accessor#101180
Conversation
33cc0e0 to
5356a95
Compare
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: refactor(sessions): move inbound meta, goals, and delivery reads behind the session accessor This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 8:41 PM ET / 00:41 UTC. Summary PR surface: Source +71, Tests +122, Generated 0, Other +11. Total +204 across 20 files. Reproducibility: not applicable. this is a behavior-preserving refactor PR, not a bug report with a failing user path. The review used source, diff, tests in the PR, live PR state, and related tracker context. Review metrics: 3 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land this focused accessor slice after rebase and exact-head validation if maintainers want separate seam adoption; otherwise carry its unique migrations into the broader storage-flip branch before superseding it. Do we have a high-confidence way to reproduce the issue? Not applicable: this is a behavior-preserving refactor PR, not a bug report with a failing user path. The review used source, diff, tests in the PR, live PR state, and related tracker context. Is this the best way to solve the issue? Yes: the accessor boundary is the right layer for this storage-neutral cleanup, and preserving the SDK-facing names is the safer compatibility shape. It still needs maintainer sequencing and exact-head validation before merge. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 74bb2ad7a533. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +71, Tests +122, Generated 0, Other +11. Total +204 across 20 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…ough the accessor
5356a95 to
52c9e7e
Compare
…nd the session accessor (openclaw#101180)
…nd the session accessor (openclaw#101180)
What Problem This Solves
Four runtime surfaces still read/write the JSON session store directly through
store.ts, bypassing the session accessor (#88838): inbound session meta + last-route recording (channels core and the plugin SDK, on every channel message), session goals, delivery-info snapshot reads, and compaction-count reconciliation after subscribed runs. Anything behind the accessor can swap storage backends; these four cannot — they would split-brain against a non-file backend.Why This Change Was Made
Moves the persistence of all four surfaces behind the accessor, file-backed, with zero behavior change:
recordInboundSessionMetaandupdateSessionLastRoute, own inbound meta persistence. File-backed implementations delegate to the existingstore.tsbodies, preserving createIfMissing upsert, preserve-activity merges (inbound meta must not refreshupdatedAt— idle reset depends on it), legacy-key normalization, and cache ownership byte-identically.recordSessionMetaFromInbound,updateLastRoute) — internals route through the accessor; no SDK contract change.goals.tsand the compaction-count handler use accessor entry get/patch;delivery-info.tsreads through a new narrowopenSessionEntryReadView— a raw borrowed keyed view (exact-key probes stay cheap property reads; enumeration defers until a normalized fallback is actually needed), whichlistSessionEntriesnow also delegates to.readSessionStoreSnapshot,recordSessionMetaFromInbound, andupdateLastRouteso new bypasses of these operations fail CI.User Impact
None — behavior-preserving refactor. Channel routing metadata, goal tracking, delivery-info resolution, and compaction counts behave identically; delivery lookups keep their exact-key fast path (guarded by a restored enumeration-trap test).
Evidence
pnpm buildgreen with noINEFFECTIVE_DYNAMIC_IMPORT(the inbound lazy boundary re-export changed).node scripts/check-session-accessor-boundary.mjspasses; structured review (codex/gpt-5.5) clean after the delivery-laziness fix, zero remaining findings.Real behavior proof (A/B equivalence vs merge-base)
An identical scenario was run against isolated stores at this head and at the merge-base (
e80e8a2b673); all four normalized state dumps are byte-identical (one sha256 across two runs per side), with 36/36 raw-byte assertions passing on both sides — demonstrating zero behavior change on all four rerouted surfaces.updatedAttoken is byte-identical — idle-reset timing cannot drift. Proven three ways: inbound meta,updateLastRoute(whose base implementation is also preserve-activity per its Session idle/daily reset never fires: updateLastRoute() bumps updatedAt before freshness check #49515 contract comment — asserted identically on both sides), and through the legacy-alias collapse path.createIfMissingupsert,createIfMissing: falsenull-return, and structural alias-key collapse to the canonical key with seeded origin markers preserved through the merge.updatedAtmonotonicity.recordSessionMetaFromInbound/updateLastRoutestill resolve as callable exports fromsession-store-runtimeandconfig-runtime.Scope disclosure: the inbound leg drives the plugin-SDK facade exports — the exact seam channel plugins call in production — because every fully-real channel path requires a live network transport; goals and delivery-info legs are direct-seam probes against the isolated store for the same reason. The rerouted persistence code executes for real in every leg.