openclaw/src/cron
Thomas M 0a01386756
fix: canonicalize session keys at write time (#30654) (thanks @thomasxm)
* fix: canonicalize session keys at write time to prevent orphaned sessions (#29683)

resolveSessionKey() uses hardcoded DEFAULT_AGENT_ID="main", but all read
paths canonicalize via cfg. When the configured default agent differs
(e.g. "ops" with mainKey "work"), writes produce "agent:main:main" while
reads look up "agent:ops:work", orphaning transcripts on every restart.

Fix all three write-path call sites by wrapping with
canonicalizeMainSessionAlias:
- initSessionState (auto-reply/reply/session.ts)
- runWebHeartbeatOnce (web/auto-reply/heartbeat-runner.ts)
- resolveCronAgentSessionKey (cron/isolated-agent/session-key.ts)

Add startup migration (migrateOrphanedSessionKeys) to rename existing
orphaned keys to canonical form, merging by most-recent updatedAt.

* fix: address review — track agent IDs in migration map, align snapshot key

P1: migrateOrphanedSessionKeys now tracks agentId alongside each store
path in a Map instead of inferring from the filesystem path. This
correctly handles custom session.store templates outside the default
agents/<id>/ layout.

P2: Pass the already-canonicalized sessionKey to getSessionSnapshot so
the heartbeat snapshot reads/restores use the same key as the write path.

* fix: log migration results at all early return points

migrateOrphanedSessionKeys runs before detectLegacyStateMigrations, so
it can canonicalize legacy keys (e.g. "main" → "agent:main:main") before
the legacy detector sees them. This caused the early return path to skip
logging, breaking doctor-state-migrations tests that assert log.info was
called.

Extract logMigrationResults helper and call it at every return point.

* fix: handle shared stores and ~ expansion in migration

P1: When session.store has no {agentId}, all agents resolve to the same
file. Track all agentIds per store path (Map<path, Set<id>>) and run
canonicalization once per agent. Skip cross-agent "agent:main:*"
remapping when "main" is a legitimate configured agent sharing the store,
to avoid merging its data into another agent's namespace.

P2: Use expandHomePrefix (environment-aware ~ resolution) instead of
os.homedir() in resolveStorePathFromTemplate, matching the runtime
resolveStorePath behavior for OPENCLAW_HOME/HOME overrides.

* fix: narrow cross-agent remap to provable orphan aliases only

Only remap agent:main:* keys where the suffix is a main session alias
("main" or the configured mainKey). Other agent:main:* keys — hooks,
subagents, cron sessions, per-sender keys — may be intentional
cross-agent references and must not be silently moved into another
agent's namespace.

* fix: run orphan-key session migration at gateway startup (#29683)

* fix: canonicalize cross-agent legacy main aliases in session keys (#29683)

* fix: guard shared-store migration against cross-agent legacy alias remap (#29683)

* refactor: split session-key migration out of pr 30654

---------

Co-authored-by: Your Name <your_email@example.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-29 18:59:25 +05:30
..
isolated-agent fix: canonicalize session keys at write time (#30654) (thanks @thomasxm) 2026-03-29 18:59:25 +05:30
service test: debrand pairing and dm policy fixtures 2026-03-27 22:18:20 +00:00
cron-protocol-conformance.test.ts cron: record lastErrorReason in job state (#14382) 2026-03-10 00:01:45 -05:00
delivery.failure-notify.test.ts
delivery.test.ts
delivery.ts
heartbeat-policy.test.ts
heartbeat-policy.ts Plugin SDK: route reply payload through public subpath 2026-03-18 12:01:15 -07:00
isolated-agent.auth-profile-propagation.test.ts
isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts Tests: fix green check typing regressions 2026-03-16 12:54:01 +00:00
isolated-agent.delivery-awareness.test.ts cron: queue isolated delivery awareness 2026-03-25 15:21:14 +05:30
isolated-agent.delivery-target-thread-session.test.ts test: move extension-owned coverage into plugins 2026-03-27 15:11:33 +00:00
isolated-agent.delivery.test-helpers.ts build: update deps and fix vitest 4 regressions 2026-03-13 01:02:00 +00:00
isolated-agent.direct-delivery-core-channels.test.ts refactor: move remaining channel seams into plugins 2026-03-15 23:47:30 -07:00
isolated-agent.direct-delivery-forum-topics.test.ts build: update deps and fix vitest 4 regressions 2026-03-13 01:02:00 +00:00
isolated-agent.helpers.test.ts test: trim more local test startup overhead 2026-03-22 09:35:36 +00:00
isolated-agent.lane.test.ts test: harden no-isolate mock and timer cleanup 2026-03-22 13:32:59 -07:00
isolated-agent.mocks.ts
isolated-agent.model-formatting.test.ts perf: extract lightweight runtime seams 2026-03-22 05:03:10 +00:00
isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts tests: cron coverage and NO_REPLY delivery fixes (#53366) 2026-03-23 22:52:13 -05:00
isolated-agent.subagent-model.test.ts
isolated-agent.test-harness.ts
isolated-agent.test-setup.ts refactor: route plugin runtime through bundled seams 2026-03-27 16:40:27 +00:00
isolated-agent.ts
isolated-agent.uses-last-non-empty-agent-text-as.test.ts fix(gateway): preserve async hook ingress provenance 2026-03-22 22:21:49 -07:00
legacy-delivery.ts
normalize.test.ts feat(cron): support custom session IDs and auto-bind to current session (#16511) 2026-03-14 16:48:46 +11:00
normalize.ts feat(cron): support custom session IDs and auto-bind to current session (#16511) 2026-03-14 16:48:46 +11:00
parse.ts
payload-migration.ts
run-log.test.ts
run-log.ts
schedule.test.ts
schedule.ts
service.armtimer-tight-loop.test.ts
service.delivery-plan.test.ts
service.every-jobs-fire.test.ts
service.failure-alert.test.ts
service.get-job.test.ts
service.heartbeat-ok-summary-suppressed.test.ts
service.issue-13992-regression.test.ts
service.issue-16156-list-skips-cron.test.ts
service.issue-17852-daily-skip.test.ts
service.issue-19676-at-reschedule.test.ts
service.issue-22895-every-next-run.test.ts
service.issue-35195-backup-timing.test.ts
service.issue-regressions.test-helpers.ts test: speed up plugin-sdk and cron suites 2026-03-24 17:49:25 +00:00
service.issue-regressions.test.ts test: update codex test fixtures to gpt-5.4 2026-03-23 02:14:00 -07:00
service.jobs.test.ts test: dedupe config and utility suites 2026-03-28 00:46:53 +00:00
service.jobs.top-of-hour-stagger.test.ts
service.list-page-sort-guards.test.ts
service.main-job-passes-heartbeat-target-last.test.ts
service.persists-delivered-status.test.ts
service.prevents-duplicate-timers.test.ts
service.read-ops-nonblocking.test.ts
service.rearm-timer-when-running.test.ts
service.restart-catchup.test.ts refactor: share cron restart catchup harness 2026-03-13 20:37:53 +00:00
service.runs-one-shot-main-job-disables-it.test.ts Reduce lint suppressions in core tests and runtime 2026-03-27 02:11:26 -05:00
service.session-reaper-in-finally.test.ts refactor: split tracked ClawHub update flows 2026-03-23 20:01:51 -07:00
service.skips-main-jobs-empty-systemevent-text.test.ts
service.store-load-invalid-main-job.test.ts test: cover invalid main job store load 2026-03-17 07:06:25 +00:00
service.store-migration.test.ts feat(cron): support custom session IDs and auto-bind to current session (#16511) 2026-03-14 16:48:46 +11:00
service.store.migration.test.ts feat(cron): support custom session IDs and auto-bind to current session (#16511) 2026-03-14 16:48:46 +11:00
service.test-harness.ts refactor: split tracked ClawHub update flows 2026-03-23 20:01:51 -07:00
service.ts
session-reaper.test.ts
session-reaper.ts perf: optimize cold import paths 2026-03-26 23:11:00 +00:00
stagger.test.ts
stagger.ts
store-migration.test.ts test(models): refresh example model fixtures 2026-03-22 23:00:18 -07:00
store-migration.ts feat(cron): support custom session IDs and auto-bind to current session (#16511) 2026-03-14 16:48:46 +11:00
store.test.ts perf: reduce cron persistence churn 2026-03-22 21:28:16 +00:00
store.ts refactor: continue plugin seam cleanup 2026-03-27 13:46:16 +00:00
types-shared.ts
types.ts fix(gateway): preserve async hook ingress provenance 2026-03-22 22:21:49 -07:00
validate-timestamp.ts
webhook-url.ts