openclaw/docs
Ayaan Zaidi 5e209925e4
fix(doctor): retained session-source warning never clears after deferred plugin migrations complete (#160755)
Closes #160689

## What Problem This Solves

Fixes: `openclaw doctor --session-sqlite inspect` keeps reporting `plugin_migration_source_retained` after deferred plugin migrations complete, and repeated `openclaw doctor --fix` never clears it, when the import receipt includes unindexed session history with `.trajectory-path.json` pointer sidecars.

## User Impact

User impact: after upgrading with deferred plugin migrations (for example Codex or Brave), `doctor --fix` archives each unindexed transcript together with its trajectory pointer, and installs already left with stranded pointers get them archived on the next `doctor --fix`, so the warning clears.

## Why This Change Was Made

A deferred import receipt captures each discovered transcript together with its trajectory and pointer sidecar. When the plugin later completes, settlement no longer rediscovers that history, so its transcripts are moved by the unreferenced-JSONL sweep, which moved only `.jsonl` files. The pointer (a `.json` file) stayed live. The retained check fires while any receipt source is live, so the warning never cleared.

Doctor's archive sweep now moves a transcript's pointer sidecar with it. For installs an earlier release already left in that state, the same sweep also archives a receipt-captured pointer whose receipt-verified transcript is no longer live. Both paths use the existing archive move: identity and byte checks, a migration-manifest entry, and `doctor --session-sqlite restore` recovery. Nothing is deleted. Pointers still referenced by a live index, retained for another owner, in conflict with the receipt, or (during settlement) outside the receipt are left alone.

Update behavior: no schema, receipt or stored-field changes. The installed updater runs first, unchanged. The candidate's Doctor keys on the deferred-plugin session receipt and migration manifests that 2026.9.5/2026.9.6 already write, so the first `doctor --fix` after updating repairs existing stranded installs. Agent/state DB `user_version` and schema are identical to `main` after the same migration.

Related: introduced when deferred-import settlement began archiving receipt-captured unindexed history (#150015, first shipped in 2026.9.5).

No overlap with Pash/Sarah changes.

Thanks @spikewillcocks for the detailed report and receipt analysis.

## Evidence

Real CLI, isolated `--profile p160689base` / `p160689cand` with task-owned `OPENCLAW_HOME`, `OPENCLAW_STATE_DIR` and `OPENCLAW_CONFIG_PATH`; every Doctor run first printed the resolved state dir, config path and session DB path from the same binary. State: a file-era `sessions.json` (1 indexed session) plus 3 unindexed transcripts, each with `.trajectory.jsonl` and `.trajectory-path.json` (pointer format from v2026.9.5), plus unrelated `notes.txt` and `custom-settings.json`. The **published 2026.9.5** package ran `doctor --fix` with `brave` configured but its package unreachable, which deferred the migration and wrote the import receipt. The source checkout then completed the `brave` migration, as in the report.

- **Base** (`origin/main` 9366fd94e1): settlement archived the transcripts and left `history-{1,2,3}.trajectory-path.json` live. `inspect` → `1 issue(s)` `[plugin_migration_source_retained] … await archival. Run openclaw doctor --fix to finish.` A second `doctor --fix` changed nothing and `inspect` still reported it.
- **Candidate, same 2026.9.5 state**: `doctor --fix` archived all 4 pointers with their transcripts into `agents/main/session-sqlite-import-archive/` (for example `archive-tier.history-1.trajectory-path.json.imported-…`, manifest kind `trajectory`, reason `unreferenced-history`). Each archive's SHA-256 matches the receipt. `inspect` → `0 issue(s)`. A second `doctor --fix` wrote a run manifest with `completedMoves=0`, and no other file changed.
- **Candidate on the stranded base state** (the reporter's situation): `doctor --fix` → `Archived 3 legacy transcript artifact(s)`, the three stranded pointers now in the archive with receipt-matching SHA-256. `inspect` → `0 issue(s)`. A second run → `completedMoves=0`.
- **Controls**: `notes.txt` and `custom-settings.json` in the same sessions folder were byte-identical in every run. The regression test covers the explicit settlement path (`settleRetainedDoctorSessionSources`). There, a transcript and pointer written after the receipt (live, not covered by it) stay byte-identical, and so does an unrelated file. When the plugin completes during config preflight instead, Doctor's existing sweep archives every unreferenced JSONL in the folder, including ones written after the receipt. `main` does the same with `late.jsonl`, but leaves `late.trajectory-path.json` orphaned; the candidate moves that pointer with its transcript. A pointer still referenced by a live index or retained for another owner is skipped by the same guards that protect transcripts.
- Schema: after the same migration, base and candidate agent DB `user_version=23`, state DB `user_version=19`, with identical `sqlite_master` hashes.
- Regression test `doctor-session-sqlite.shared-orphan.test.ts` covers both paths. First, settlement of a deferred receipt with unindexed history and a pointer. Second, repair of a pointer an earlier settlement left behind; that half requires a distinct second archive move with receipt-matching bytes. The test fails on `main` because the pointer is still live after settlement. With only the stranded-pointer pass disabled, it fails at the repair step because the pointer stays live. It passes with the fix. Related suites (`deferred-plugin`, `manifests`, `retained-source-verification`, `active-settlement`, `indexless`, `archive-safety`, `recovery-shared-owners`, `discovery`, `recovery`, `receipt-recovery`, `doctor-session-sqlite`) pass: 12 files, 139 tests.
- Test cost: the new test is 1.7s locally and 1.8s in CI (`checks-node-changed-compact-large-19-1`, shard `agentic-commands-doctor-sessions-cron-hosted-1`, run 36491519850). `pnpm test src/commands/doctor-session-sqlite.shared-orphan.test.ts --maxWorkers=1` takes 34.4s wall for the whole file, which is mostly transform; its three tests run in about 6s. It uses no timers, sleeps, polling or process boots, and reuses the file's existing fixture and imports.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-29 05:40:51 +05:30
..
.generated fix: keep Codex chats working during slow model discovery (#160363) 2026-09-28 11:43:38 -07:00
.i18n fix(openai): retire the Sora video provider after the API shutdown (#159543) 2026-09-27 22:52:14 +00:00
announcements docs: STE pass on terminology consistency and run-on sentences (#143770) 2026-09-10 15:51:49 +09:00
assets docs: remove stale showcase section (#158575) 2026-09-25 21:11:35 -06:00
automation fix(cron): named-session jobs run in the wrong workspace (#159444) 2026-09-28 14:54:53 -07:00
channels fix(tlon): bound pending approval queue (#160679) 2026-09-28 17:08:58 -07:00
ci chore(ios): simplify store release workflow (#160791) 2026-09-28 19:00:37 -05:00
cli fix(doctor): retained session-source warning never clears after deferred plugin migrations complete (#160755) 2026-09-29 05:40:51 +05:30
concepts fix: streamed replies split Markdown tables that fit one message (#160701) 2026-09-29 03:41:47 +05:30
diagnostics perf(cli): keep client diagnostics off shared state 2026-09-24 12:56:28 +00:00
gateway perf(ui): stop forbidden canvas lease refresh loops (#160808) 2026-09-29 00:05:39 +00:00
help fix(ci): scope untouched line-limit diagnostics in changed checks (#158995) 2026-09-28 16:35:33 -07:00
images
install fix(node-host): updates never install on Bun-only macOS and Linux hosts (#160575) 2026-09-28 14:59:44 -07:00
maturity refactor: remove Tasks and TaskFlow runtime (#159179) 2026-09-27 10:40:29 -07:00
nodes perf(nodes): reuse warm workers so node session turns start as fast as local ones (#160265) 2026-09-28 16:07:44 -07:00
platforms fix(ios): preserve setup after bootstrap preparation refuses (#160218) 2026-09-28 09:25:24 -07:00
plugins fix(http): adapt rejection transport to Bun's Node-compatible closure (#160329) 2026-09-28 15:49:05 -07:00
providers feat: speak with Gemini 3.8 Flash TTS (#157331) 2026-09-28 15:23:34 -07:00
reference fix(active-memory): recalls on claude-cli never reuse the prompt cache (#160768) 2026-09-29 04:52:53 +05:30
releases fix: exclude repository instructions from public docs sync (#158253) 2026-09-25 13:15:24 -06:00
security fix(proxy): keep WebChat and Codex loopback calls direct (#154013) 2026-09-20 21:42:01 -07:00
snippets/plugin-publish chore(deps): refresh dependencies with seven-day cutoff (#158298) 2026-09-26 20:42:53 -07:00
specs fix(codex): restore native discovery and hide empty catalogs (#146305) 2026-09-12 13:03:31 -07:00
start fix(onboarding): stop claiming inference is ready after Skip for now (#160713) 2026-09-28 15:17:40 -07:00
tools feat: speak with Gemini 3.8 Flash TTS (#157331) 2026-09-28 15:23:34 -07:00
web fix(ui): open voice setup before history admission (#160686) 2026-09-28 15:50:18 -07:00
agent-runtime-architecture.md perf(agents): keep file edits from blocking other chats (#158443) 2026-09-26 03:55:55 -05:00
AGENTS.md fix: exclude repository instructions from public docs sync (#158253) 2026-09-25 13:15:24 -06:00
auth-credential-semantics.md fix(auth): keep session account selection after OAuth re-login (#149591) 2026-09-27 18:07:54 +05:30
ci.md fix(e2e): size first-hop budgets from measured update times 2026-09-28 13:22:12 -07:00
date-time.md
docs.json feat(video): add Kie AI, Z.AI, and Novita video generation (#160080) 2026-09-28 12:48:22 +00:00
docs_map.md
index.md docs: remove stale showcase section (#158575) 2026-09-25 21:11:35 -06:00
logging.md fix: restore steering across queued and active turns (#158699) 2026-09-26 13:29:49 -07:00
network.md docs: close remaining cross-link gaps across concepts, gateway, and security (#143923) 2026-09-10 18:34:34 +08:00
openclaw-agent-runtime.md docs: close remaining cross-link gaps across concepts, gateway, and security (#143923) 2026-09-10 18:34:34 +08:00
prose.md
vps.md docs(gateway,concepts,install,help): fix information-architecture findings (#143977) 2026-09-10 19:20:49 +08:00
whatsapp-openclaw.jpg