vilvona 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (812) hide show
  1. package/CHANGELOG.md +12331 -0
  2. package/LICENSE +24 -0
  3. package/README.md +314 -0
  4. package/THIRD_PARTY_NOTICES.md +37 -0
  5. package/docs/.i18n/README.md +81 -0
  6. package/docs/.i18n/ar-navigation.json +18 -0
  7. package/docs/.i18n/de-navigation.json +18 -0
  8. package/docs/.i18n/es-navigation.json +18 -0
  9. package/docs/.i18n/fr-navigation.json +18 -0
  10. package/docs/.i18n/glossary.ar.json +82 -0
  11. package/docs/.i18n/glossary.de.json +82 -0
  12. package/docs/.i18n/glossary.es.json +82 -0
  13. package/docs/.i18n/glossary.fa.json +82 -0
  14. package/docs/.i18n/glossary.fr.json +82 -0
  15. package/docs/.i18n/glossary.id.json +82 -0
  16. package/docs/.i18n/glossary.it.json +82 -0
  17. package/docs/.i18n/glossary.ja-JP.json +102 -0
  18. package/docs/.i18n/glossary.ko.json +82 -0
  19. package/docs/.i18n/glossary.nl.json +82 -0
  20. package/docs/.i18n/glossary.pl.json +82 -0
  21. package/docs/.i18n/glossary.pt-BR.json +82 -0
  22. package/docs/.i18n/glossary.th.json +82 -0
  23. package/docs/.i18n/glossary.tr.json +82 -0
  24. package/docs/.i18n/glossary.uk.json +82 -0
  25. package/docs/.i18n/glossary.vi.json +82 -0
  26. package/docs/.i18n/glossary.zh-CN.json +1182 -0
  27. package/docs/.i18n/glossary.zh-TW.json +162 -0
  28. package/docs/.i18n/id-navigation.json +18 -0
  29. package/docs/.i18n/it-navigation.json +18 -0
  30. package/docs/.i18n/ja-navigation.json +18 -0
  31. package/docs/.i18n/ko-navigation.json +18 -0
  32. package/docs/.i18n/pl-navigation.json +18 -0
  33. package/docs/.i18n/pt-BR-navigation.json +18 -0
  34. package/docs/.i18n/tr-navigation.json +18 -0
  35. package/docs/.i18n/translation-workflow.md +111 -0
  36. package/docs/.i18n/zh-Hans-navigation.json +552 -0
  37. package/docs/AGENTS.md +36 -0
  38. package/docs/agent-runtime-architecture.md +48 -0
  39. package/docs/announcements/bluebubbles-imessage.md +79 -0
  40. package/docs/auth-credential-semantics.md +124 -0
  41. package/docs/automation/auth-monitoring.md +11 -0
  42. package/docs/automation/clawflow.md +12 -0
  43. package/docs/automation/cron-jobs.md +569 -0
  44. package/docs/automation/cron-vs-heartbeat.md +11 -0
  45. package/docs/automation/gmail-pubsub.md +11 -0
  46. package/docs/automation/hooks.md +387 -0
  47. package/docs/automation/index.md +135 -0
  48. package/docs/automation/poll.md +12 -0
  49. package/docs/automation/standing-orders.md +250 -0
  50. package/docs/automation/taskflow.md +155 -0
  51. package/docs/automation/tasks.md +374 -0
  52. package/docs/automation/troubleshooting.md +12 -0
  53. package/docs/automation/webhook.md +12 -0
  54. package/docs/brave-search.md +11 -0
  55. package/docs/channels/access-groups.md +201 -0
  56. package/docs/channels/ambient-room-events.md +214 -0
  57. package/docs/channels/bot-loop-protection.md +131 -0
  58. package/docs/channels/broadcast-groups.md +472 -0
  59. package/docs/channels/channel-routing.md +162 -0
  60. package/docs/channels/clickclack.md +146 -0
  61. package/docs/channels/discord.md +1758 -0
  62. package/docs/channels/feishu.md +654 -0
  63. package/docs/channels/googlechat.md +286 -0
  64. package/docs/channels/group-messages.md +95 -0
  65. package/docs/channels/groups.md +610 -0
  66. package/docs/channels/imessage-from-bluebubbles.md +259 -0
  67. package/docs/channels/imessage.md +864 -0
  68. package/docs/channels/index.md +65 -0
  69. package/docs/channels/irc.md +253 -0
  70. package/docs/channels/line.md +243 -0
  71. package/docs/channels/location.md +71 -0
  72. package/docs/channels/matrix-migration.md +375 -0
  73. package/docs/channels/matrix-presentation.md +77 -0
  74. package/docs/channels/matrix-push-rules.md +150 -0
  75. package/docs/channels/matrix.md +935 -0
  76. package/docs/channels/mattermost.md +542 -0
  77. package/docs/channels/msteams.md +1097 -0
  78. package/docs/channels/nextcloud-talk.md +176 -0
  79. package/docs/channels/nostr.md +253 -0
  80. package/docs/channels/pairing.md +214 -0
  81. package/docs/channels/qqbot.md +317 -0
  82. package/docs/channels/signal.md +417 -0
  83. package/docs/channels/slack.md +1623 -0
  84. package/docs/channels/sms.md +380 -0
  85. package/docs/channels/synology-chat.md +187 -0
  86. package/docs/channels/telegram.md +1121 -0
  87. package/docs/channels/tlon.md +296 -0
  88. package/docs/channels/troubleshooting.md +162 -0
  89. package/docs/channels/twitch.md +431 -0
  90. package/docs/channels/wechat.md +171 -0
  91. package/docs/channels/whatsapp.md +796 -0
  92. package/docs/channels/yuanbao.md +416 -0
  93. package/docs/channels/zalo.md +253 -0
  94. package/docs/channels/zalouser.md +217 -0
  95. package/docs/ci.md +665 -0
  96. package/docs/clawhub/cli.md +82 -0
  97. package/docs/clawhub/publishing.md +96 -0
  98. package/docs/cli/acp.md +370 -0
  99. package/docs/cli/agent.md +109 -0
  100. package/docs/cli/agents.md +253 -0
  101. package/docs/cli/approvals.md +193 -0
  102. package/docs/cli/backup.md +98 -0
  103. package/docs/cli/browser.md +322 -0
  104. package/docs/cli/channels.md +154 -0
  105. package/docs/cli/clawbot.md +25 -0
  106. package/docs/cli/commitments.md +90 -0
  107. package/docs/cli/completion.md +39 -0
  108. package/docs/cli/config.md +504 -0
  109. package/docs/cli/configure.md +77 -0
  110. package/docs/cli/crestodian.md +337 -0
  111. package/docs/cli/cron.md +344 -0
  112. package/docs/cli/daemon.md +67 -0
  113. package/docs/cli/dashboard.md +33 -0
  114. package/docs/cli/devices.md +240 -0
  115. package/docs/cli/directory.md +68 -0
  116. package/docs/cli/dns.md +53 -0
  117. package/docs/cli/docs.md +63 -0
  118. package/docs/cli/doctor.md +254 -0
  119. package/docs/cli/flows.md +52 -0
  120. package/docs/cli/gateway.md +572 -0
  121. package/docs/cli/health.md +43 -0
  122. package/docs/cli/hooks.md +345 -0
  123. package/docs/cli/index.md +406 -0
  124. package/docs/cli/infer.md +364 -0
  125. package/docs/cli/logs.md +68 -0
  126. package/docs/cli/mcp.md +851 -0
  127. package/docs/cli/memory.md +183 -0
  128. package/docs/cli/message.md +317 -0
  129. package/docs/cli/migrate.md +334 -0
  130. package/docs/cli/models.md +239 -0
  131. package/docs/cli/node.md +178 -0
  132. package/docs/cli/nodes.md +76 -0
  133. package/docs/cli/onboard.md +251 -0
  134. package/docs/cli/pairing.md +77 -0
  135. package/docs/cli/path.md +511 -0
  136. package/docs/cli/plugins.md +480 -0
  137. package/docs/cli/policy.md +929 -0
  138. package/docs/cli/proxy.md +89 -0
  139. package/docs/cli/qr.md +56 -0
  140. package/docs/cli/reset.md +39 -0
  141. package/docs/cli/sandbox.md +208 -0
  142. package/docs/cli/secrets.md +202 -0
  143. package/docs/cli/security.md +135 -0
  144. package/docs/cli/sessions.md +178 -0
  145. package/docs/cli/setup.md +60 -0
  146. package/docs/cli/skills.md +156 -0
  147. package/docs/cli/status.md +45 -0
  148. package/docs/cli/system.md +89 -0
  149. package/docs/cli/tasks.md +111 -0
  150. package/docs/cli/transcripts.md +151 -0
  151. package/docs/cli/tui.md +92 -0
  152. package/docs/cli/uninstall.md +45 -0
  153. package/docs/cli/update.md +283 -0
  154. package/docs/cli/voicecall.md +204 -0
  155. package/docs/cli/webhooks.md +117 -0
  156. package/docs/cli/wiki.md +256 -0
  157. package/docs/cli/workboard.md +228 -0
  158. package/docs/concepts/active-memory.md +856 -0
  159. package/docs/concepts/agent-loop.md +185 -0
  160. package/docs/concepts/agent-runtimes.md +276 -0
  161. package/docs/concepts/agent-workspace.md +230 -0
  162. package/docs/concepts/agent.md +142 -0
  163. package/docs/concepts/architecture.md +154 -0
  164. package/docs/concepts/channel-docking.md +145 -0
  165. package/docs/concepts/commitments.md +150 -0
  166. package/docs/concepts/compaction.md +203 -0
  167. package/docs/concepts/context-engine.md +347 -0
  168. package/docs/concepts/context.md +199 -0
  169. package/docs/concepts/delegate-architecture.md +319 -0
  170. package/docs/concepts/dreaming.md +279 -0
  171. package/docs/concepts/experimental-features.md +111 -0
  172. package/docs/concepts/features.md +91 -0
  173. package/docs/concepts/mantis-slack-desktop-runbook.md +231 -0
  174. package/docs/concepts/mantis.md +744 -0
  175. package/docs/concepts/markdown-formatting.md +139 -0
  176. package/docs/concepts/memory-builtin.md +151 -0
  177. package/docs/concepts/memory-honcho.md +144 -0
  178. package/docs/concepts/memory-qmd.md +277 -0
  179. package/docs/concepts/memory-search.md +175 -0
  180. package/docs/concepts/memory.md +299 -0
  181. package/docs/concepts/message-lifecycle-refactor.md +1126 -0
  182. package/docs/concepts/messages.md +216 -0
  183. package/docs/concepts/model-failover.md +405 -0
  184. package/docs/concepts/model-providers.md +719 -0
  185. package/docs/concepts/models.md +371 -0
  186. package/docs/concepts/multi-agent.md +625 -0
  187. package/docs/concepts/oauth.md +218 -0
  188. package/docs/concepts/parallel-specialist-lanes.md +127 -0
  189. package/docs/concepts/personal-agent-benchmark-pack.md +74 -0
  190. package/docs/concepts/presence.md +117 -0
  191. package/docs/concepts/progress-drafts.md +406 -0
  192. package/docs/concepts/qa-e2e-automation.md +979 -0
  193. package/docs/concepts/qa-matrix.md +139 -0
  194. package/docs/concepts/queue-steering.md +90 -0
  195. package/docs/concepts/queue.md +136 -0
  196. package/docs/concepts/retry.md +86 -0
  197. package/docs/concepts/session-pruning.md +104 -0
  198. package/docs/concepts/session-tool.md +201 -0
  199. package/docs/concepts/session.md +164 -0
  200. package/docs/concepts/soul.md +116 -0
  201. package/docs/concepts/streaming.md +258 -0
  202. package/docs/concepts/system-prompt.md +330 -0
  203. package/docs/concepts/timezone.md +47 -0
  204. package/docs/concepts/typebox.md +309 -0
  205. package/docs/concepts/typing-indicators.md +88 -0
  206. package/docs/concepts/usage-tracking.md +72 -0
  207. package/docs/date-time.md +126 -0
  208. package/docs/debug/node-issue.md +90 -0
  209. package/docs/diagnostics/flags.md +182 -0
  210. package/docs/docs.json +1885 -0
  211. package/docs/gateway/authentication.md +286 -0
  212. package/docs/gateway/background-process.md +147 -0
  213. package/docs/gateway/bonjour.md +303 -0
  214. package/docs/gateway/bridge-protocol.md +97 -0
  215. package/docs/gateway/cli-backends.md +463 -0
  216. package/docs/gateway/config-agents.md +1525 -0
  217. package/docs/gateway/config-channels.md +942 -0
  218. package/docs/gateway/config-tools.md +806 -0
  219. package/docs/gateway/configuration-examples.md +706 -0
  220. package/docs/gateway/configuration-reference.md +1449 -0
  221. package/docs/gateway/configuration.md +748 -0
  222. package/docs/gateway/diagnostics.md +213 -0
  223. package/docs/gateway/discovery.md +154 -0
  224. package/docs/gateway/doctor.md +576 -0
  225. package/docs/gateway/external-apps.md +86 -0
  226. package/docs/gateway/gateway-lock.md +37 -0
  227. package/docs/gateway/health.md +73 -0
  228. package/docs/gateway/heartbeat.md +498 -0
  229. package/docs/gateway/index.md +385 -0
  230. package/docs/gateway/local-model-services.md +205 -0
  231. package/docs/gateway/local-models.md +355 -0
  232. package/docs/gateway/logging.md +149 -0
  233. package/docs/gateway/multiple-gateways.md +178 -0
  234. package/docs/gateway/network-model.md +15 -0
  235. package/docs/gateway/openai-http-api.md +379 -0
  236. package/docs/gateway/openresponses-http-api.md +349 -0
  237. package/docs/gateway/openshell.md +316 -0
  238. package/docs/gateway/opentelemetry.md +440 -0
  239. package/docs/gateway/operator-scopes.md +119 -0
  240. package/docs/gateway/pairing.md +207 -0
  241. package/docs/gateway/prometheus.md +249 -0
  242. package/docs/gateway/protocol.md +839 -0
  243. package/docs/gateway/remote-gateway-readme.md +169 -0
  244. package/docs/gateway/remote.md +280 -0
  245. package/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md +148 -0
  246. package/docs/gateway/sandboxing.md +546 -0
  247. package/docs/gateway/secrets-plan-contract.md +159 -0
  248. package/docs/gateway/secrets.md +805 -0
  249. package/docs/gateway/security/audit-checks.md +127 -0
  250. package/docs/gateway/security/exposure-runbook.md +212 -0
  251. package/docs/gateway/security/index.md +1344 -0
  252. package/docs/gateway/security/secure-file-operations.md +76 -0
  253. package/docs/gateway/security/shrinkwrap.md +111 -0
  254. package/docs/gateway/tailscale.md +180 -0
  255. package/docs/gateway/tools-invoke-http-api.md +175 -0
  256. package/docs/gateway/troubleshooting.md +881 -0
  257. package/docs/gateway/trusted-proxy-auth.md +483 -0
  258. package/docs/help/debugging.md +341 -0
  259. package/docs/help/environment.md +240 -0
  260. package/docs/help/faq-first-run.md +872 -0
  261. package/docs/help/faq-models.md +557 -0
  262. package/docs/help/faq.md +2115 -0
  263. package/docs/help/index.md +39 -0
  264. package/docs/help/scripts.md +56 -0
  265. package/docs/help/testing-live.md +592 -0
  266. package/docs/help/testing-updates-plugins.md +299 -0
  267. package/docs/help/testing.md +977 -0
  268. package/docs/help/troubleshooting.md +500 -0
  269. package/docs/index.md +196 -0
  270. package/docs/install/ansible.md +233 -0
  271. package/docs/install/azure.md +315 -0
  272. package/docs/install/bun.md +59 -0
  273. package/docs/install/clawdock.md +112 -0
  274. package/docs/install/development-channels.md +148 -0
  275. package/docs/install/digitalocean.md +174 -0
  276. package/docs/install/docker-vm-runtime.md +154 -0
  277. package/docs/install/docker.md +564 -0
  278. package/docs/install/exe-dev.md +201 -0
  279. package/docs/install/fly.md +524 -0
  280. package/docs/install/gcp.md +418 -0
  281. package/docs/install/hetzner.md +285 -0
  282. package/docs/install/hostinger.md +98 -0
  283. package/docs/install/index.md +236 -0
  284. package/docs/install/installer.md +447 -0
  285. package/docs/install/kubernetes.md +196 -0
  286. package/docs/install/macos-vm.md +281 -0
  287. package/docs/install/migrating-claude.md +165 -0
  288. package/docs/install/migrating-hermes.md +178 -0
  289. package/docs/install/migrating.md +137 -0
  290. package/docs/install/nix.md +112 -0
  291. package/docs/install/node.md +142 -0
  292. package/docs/install/northflank.mdx +44 -0
  293. package/docs/install/oracle.md +218 -0
  294. package/docs/install/podman.md +216 -0
  295. package/docs/install/railway.mdx +92 -0
  296. package/docs/install/raspberry-pi.md +234 -0
  297. package/docs/install/render.mdx +167 -0
  298. package/docs/install/uninstall.md +140 -0
  299. package/docs/install/updating.md +284 -0
  300. package/docs/install/upstash.md +96 -0
  301. package/docs/logging.md +322 -0
  302. package/docs/maturity-scores.yaml +5361 -0
  303. package/docs/nav-tabs-underline.js +104 -0
  304. package/docs/network.md +72 -0
  305. package/docs/nodes/audio.md +216 -0
  306. package/docs/nodes/camera.md +166 -0
  307. package/docs/nodes/images.md +77 -0
  308. package/docs/nodes/index.md +444 -0
  309. package/docs/nodes/location-command.md +102 -0
  310. package/docs/nodes/media-understanding.md +495 -0
  311. package/docs/nodes/talk.md +160 -0
  312. package/docs/nodes/troubleshooting.md +123 -0
  313. package/docs/nodes/voicewake.md +93 -0
  314. package/docs/openclaw-agent-runtime.md +82 -0
  315. package/docs/perplexity.md +11 -0
  316. package/docs/plan/codex-context-engine-harness.md +624 -0
  317. package/docs/plan/ui-channels.md +284 -0
  318. package/docs/platforms/android.md +286 -0
  319. package/docs/platforms/digitalocean.md +12 -0
  320. package/docs/platforms/easyrunner.md +109 -0
  321. package/docs/platforms/index.md +65 -0
  322. package/docs/platforms/ios.md +287 -0
  323. package/docs/platforms/linux.md +141 -0
  324. package/docs/platforms/mac/bundled-gateway.md +79 -0
  325. package/docs/platforms/mac/canvas.md +128 -0
  326. package/docs/platforms/mac/child-process.md +72 -0
  327. package/docs/platforms/mac/dev-setup.md +112 -0
  328. package/docs/platforms/mac/health.md +39 -0
  329. package/docs/platforms/mac/icon.md +36 -0
  330. package/docs/platforms/mac/logging.md +62 -0
  331. package/docs/platforms/mac/menu-bar.md +93 -0
  332. package/docs/platforms/mac/peekaboo.md +96 -0
  333. package/docs/platforms/mac/permissions.md +73 -0
  334. package/docs/platforms/mac/remote.md +123 -0
  335. package/docs/platforms/mac/signing.md +52 -0
  336. package/docs/platforms/mac/skills.md +45 -0
  337. package/docs/platforms/mac/voice-overlay.md +66 -0
  338. package/docs/platforms/mac/voicewake.md +79 -0
  339. package/docs/platforms/mac/webchat.md +54 -0
  340. package/docs/platforms/mac/xpc.md +66 -0
  341. package/docs/platforms/macos.md +228 -0
  342. package/docs/platforms/oracle.md +12 -0
  343. package/docs/platforms/raspberry-pi.md +13 -0
  344. package/docs/platforms/windows.md +304 -0
  345. package/docs/plugins/adding-capabilities.md +146 -0
  346. package/docs/plugins/admin-http-rpc.md +216 -0
  347. package/docs/plugins/agent-tools.md +13 -0
  348. package/docs/plugins/architecture-internals.md +1203 -0
  349. package/docs/plugins/architecture.md +483 -0
  350. package/docs/plugins/building-extensions.md +13 -0
  351. package/docs/plugins/building-plugins.md +343 -0
  352. package/docs/plugins/bundles.md +310 -0
  353. package/docs/plugins/cli-backend-plugins.md +328 -0
  354. package/docs/plugins/codex-computer-use.md +297 -0
  355. package/docs/plugins/codex-harness-reference.md +480 -0
  356. package/docs/plugins/codex-harness-runtime.md +268 -0
  357. package/docs/plugins/codex-harness.md +800 -0
  358. package/docs/plugins/codex-native-plugins.md +280 -0
  359. package/docs/plugins/community.md +77 -0
  360. package/docs/plugins/compatibility.md +198 -0
  361. package/docs/plugins/copilot.md +355 -0
  362. package/docs/plugins/dependency-resolution.md +176 -0
  363. package/docs/plugins/google-meet.md +1737 -0
  364. package/docs/plugins/hooks.md +525 -0
  365. package/docs/plugins/install-overrides.md +80 -0
  366. package/docs/plugins/llama-cpp.md +58 -0
  367. package/docs/plugins/manage-plugins.md +214 -0
  368. package/docs/plugins/manifest.md +1468 -0
  369. package/docs/plugins/memory-lancedb.md +385 -0
  370. package/docs/plugins/memory-wiki.md +529 -0
  371. package/docs/plugins/message-presentation.md +487 -0
  372. package/docs/plugins/oc-path.md +166 -0
  373. package/docs/plugins/plugin-inventory.md +318 -0
  374. package/docs/plugins/plugin-permission-requests.md +193 -0
  375. package/docs/plugins/reference/acpx.md +23 -0
  376. package/docs/plugins/reference/admin-http-rpc.md +23 -0
  377. package/docs/plugins/reference/alibaba.md +23 -0
  378. package/docs/plugins/reference/amazon-bedrock-mantle.md +23 -0
  379. package/docs/plugins/reference/amazon-bedrock.md +23 -0
  380. package/docs/plugins/reference/anthropic-vertex.md +29 -0
  381. package/docs/plugins/reference/anthropic.md +23 -0
  382. package/docs/plugins/reference/arcee.md +23 -0
  383. package/docs/plugins/reference/azure-speech.md +23 -0
  384. package/docs/plugins/reference/bonjour.md +19 -0
  385. package/docs/plugins/reference/brave.md +23 -0
  386. package/docs/plugins/reference/browser.md +23 -0
  387. package/docs/plugins/reference/byteplus.md +19 -0
  388. package/docs/plugins/reference/canvas.md +19 -0
  389. package/docs/plugins/reference/cerebras.md +23 -0
  390. package/docs/plugins/reference/chutes.md +23 -0
  391. package/docs/plugins/reference/clickclack.md +23 -0
  392. package/docs/plugins/reference/cloudflare-ai-gateway.md +23 -0
  393. package/docs/plugins/reference/codex-supervisor.md +27 -0
  394. package/docs/plugins/reference/codex.md +23 -0
  395. package/docs/plugins/reference/comfy.md +23 -0
  396. package/docs/plugins/reference/copilot-proxy.md +19 -0
  397. package/docs/plugins/reference/copilot.md +23 -0
  398. package/docs/plugins/reference/deepgram.md +23 -0
  399. package/docs/plugins/reference/deepinfra.md +23 -0
  400. package/docs/plugins/reference/deepseek.md +23 -0
  401. package/docs/plugins/reference/diagnostics-otel.md +19 -0
  402. package/docs/plugins/reference/diagnostics-prometheus.md +19 -0
  403. package/docs/plugins/reference/diffs-language-pack.md +31 -0
  404. package/docs/plugins/reference/diffs.md +19 -0
  405. package/docs/plugins/reference/discord.md +23 -0
  406. package/docs/plugins/reference/document-extract.md +23 -0
  407. package/docs/plugins/reference/duckduckgo.md +23 -0
  408. package/docs/plugins/reference/elevenlabs.md +23 -0
  409. package/docs/plugins/reference/exa.md +23 -0
  410. package/docs/plugins/reference/fal.md +23 -0
  411. package/docs/plugins/reference/feishu.md +23 -0
  412. package/docs/plugins/reference/file-transfer.md +19 -0
  413. package/docs/plugins/reference/firecrawl.md +23 -0
  414. package/docs/plugins/reference/fireworks.md +23 -0
  415. package/docs/plugins/reference/github-copilot.md +23 -0
  416. package/docs/plugins/reference/gmi.md +23 -0
  417. package/docs/plugins/reference/google-meet.md +23 -0
  418. package/docs/plugins/reference/google.md +23 -0
  419. package/docs/plugins/reference/googlechat.md +23 -0
  420. package/docs/plugins/reference/gradium.md +23 -0
  421. package/docs/plugins/reference/groq.md +23 -0
  422. package/docs/plugins/reference/huggingface.md +23 -0
  423. package/docs/plugins/reference/imessage.md +23 -0
  424. package/docs/plugins/reference/inworld.md +23 -0
  425. package/docs/plugins/reference/irc.md +23 -0
  426. package/docs/plugins/reference/kilocode.md +23 -0
  427. package/docs/plugins/reference/kimi.md +23 -0
  428. package/docs/plugins/reference/line.md +23 -0
  429. package/docs/plugins/reference/litellm.md +23 -0
  430. package/docs/plugins/reference/llama-cpp.md +23 -0
  431. package/docs/plugins/reference/llm-task.md +19 -0
  432. package/docs/plugins/reference/lmstudio.md +23 -0
  433. package/docs/plugins/reference/lobster.md +19 -0
  434. package/docs/plugins/reference/matrix.md +23 -0
  435. package/docs/plugins/reference/mattermost.md +23 -0
  436. package/docs/plugins/reference/memory-core.md +19 -0
  437. package/docs/plugins/reference/memory-lancedb.md +23 -0
  438. package/docs/plugins/reference/memory-wiki.md +23 -0
  439. package/docs/plugins/reference/microsoft-foundry.md +113 -0
  440. package/docs/plugins/reference/microsoft.md +19 -0
  441. package/docs/plugins/reference/migrate-claude.md +19 -0
  442. package/docs/plugins/reference/migrate-hermes.md +19 -0
  443. package/docs/plugins/reference/minimax.md +23 -0
  444. package/docs/plugins/reference/mistral.md +23 -0
  445. package/docs/plugins/reference/moonshot.md +23 -0
  446. package/docs/plugins/reference/msteams.md +23 -0
  447. package/docs/plugins/reference/nextcloud-talk.md +23 -0
  448. package/docs/plugins/reference/nostr.md +23 -0
  449. package/docs/plugins/reference/novita.md +23 -0
  450. package/docs/plugins/reference/nvidia.md +23 -0
  451. package/docs/plugins/reference/oc-path.md +23 -0
  452. package/docs/plugins/reference/ollama.md +24 -0
  453. package/docs/plugins/reference/open-prose.md +19 -0
  454. package/docs/plugins/reference/openai.md +23 -0
  455. package/docs/plugins/reference/opencode-go.md +23 -0
  456. package/docs/plugins/reference/opencode.md +23 -0
  457. package/docs/plugins/reference/openrouter.md +23 -0
  458. package/docs/plugins/reference/openshell.md +19 -0
  459. package/docs/plugins/reference/perplexity.md +23 -0
  460. package/docs/plugins/reference/pixverse.md +23 -0
  461. package/docs/plugins/reference/policy.md +79 -0
  462. package/docs/plugins/reference/qa-channel.md +23 -0
  463. package/docs/plugins/reference/qa-lab.md +19 -0
  464. package/docs/plugins/reference/qa-matrix.md +19 -0
  465. package/docs/plugins/reference/qianfan.md +23 -0
  466. package/docs/plugins/reference/qqbot.md +23 -0
  467. package/docs/plugins/reference/qwen.md +24 -0
  468. package/docs/plugins/reference/runway.md +23 -0
  469. package/docs/plugins/reference/searxng.md +19 -0
  470. package/docs/plugins/reference/senseaudio.md +23 -0
  471. package/docs/plugins/reference/sglang.md +23 -0
  472. package/docs/plugins/reference/signal.md +23 -0
  473. package/docs/plugins/reference/slack.md +23 -0
  474. package/docs/plugins/reference/sms.md +23 -0
  475. package/docs/plugins/reference/stepfun.md +23 -0
  476. package/docs/plugins/reference/synology-chat.md +23 -0
  477. package/docs/plugins/reference/synthetic.md +23 -0
  478. package/docs/plugins/reference/tavily.md +23 -0
  479. package/docs/plugins/reference/telegram.md +23 -0
  480. package/docs/plugins/reference/tencent.md +23 -0
  481. package/docs/plugins/reference/tlon.md +23 -0
  482. package/docs/plugins/reference/together.md +23 -0
  483. package/docs/plugins/reference/tokenjuice.md +23 -0
  484. package/docs/plugins/reference/tts-local-cli.md +19 -0
  485. package/docs/plugins/reference/twitch.md +23 -0
  486. package/docs/plugins/reference/venice.md +23 -0
  487. package/docs/plugins/reference/vercel-ai-gateway.md +23 -0
  488. package/docs/plugins/reference/vllm.md +23 -0
  489. package/docs/plugins/reference/voice-call.md +23 -0
  490. package/docs/plugins/reference/volcengine.md +23 -0
  491. package/docs/plugins/reference/voyage.md +19 -0
  492. package/docs/plugins/reference/vydra.md +23 -0
  493. package/docs/plugins/reference/web-readability.md +19 -0
  494. package/docs/plugins/reference/webhooks.md +23 -0
  495. package/docs/plugins/reference/whatsapp.md +23 -0
  496. package/docs/plugins/reference/workboard.md +23 -0
  497. package/docs/plugins/reference/xai.md +23 -0
  498. package/docs/plugins/reference/xiaomi.md +23 -0
  499. package/docs/plugins/reference/zai.md +23 -0
  500. package/docs/plugins/reference/zalo.md +23 -0
  501. package/docs/plugins/reference/zalouser.md +24 -0
  502. package/docs/plugins/reference.md +19 -0
  503. package/docs/plugins/sdk-agent-harness.md +339 -0
  504. package/docs/plugins/sdk-channel-inbound.md +70 -0
  505. package/docs/plugins/sdk-channel-ingress.md +137 -0
  506. package/docs/plugins/sdk-channel-message.md +18 -0
  507. package/docs/plugins/sdk-channel-outbound.md +113 -0
  508. package/docs/plugins/sdk-channel-plugins.md +770 -0
  509. package/docs/plugins/sdk-channel-turn.md +9 -0
  510. package/docs/plugins/sdk-entrypoints.md +344 -0
  511. package/docs/plugins/sdk-migration.md +1011 -0
  512. package/docs/plugins/sdk-overview.md +525 -0
  513. package/docs/plugins/sdk-provider-plugins.md +1019 -0
  514. package/docs/plugins/sdk-runtime.md +683 -0
  515. package/docs/plugins/sdk-setup.md +550 -0
  516. package/docs/plugins/sdk-subpaths.md +401 -0
  517. package/docs/plugins/sdk-testing.md +403 -0
  518. package/docs/plugins/tool-plugins.md +411 -0
  519. package/docs/plugins/voice-call.md +942 -0
  520. package/docs/plugins/webhooks.md +192 -0
  521. package/docs/plugins/workboard.md +402 -0
  522. package/docs/plugins/zalouser.md +86 -0
  523. package/docs/prose.md +191 -0
  524. package/docs/providers/alibaba.md +158 -0
  525. package/docs/providers/anthropic.md +386 -0
  526. package/docs/providers/arcee.md +144 -0
  527. package/docs/providers/azure-speech.md +119 -0
  528. package/docs/providers/bedrock-mantle.md +224 -0
  529. package/docs/providers/bedrock.md +433 -0
  530. package/docs/providers/cerebras.md +130 -0
  531. package/docs/providers/chutes.md +153 -0
  532. package/docs/providers/claude-max-api-proxy.md +191 -0
  533. package/docs/providers/cloudflare-ai-gateway.md +119 -0
  534. package/docs/providers/comfy.md +362 -0
  535. package/docs/providers/deepgram.md +184 -0
  536. package/docs/providers/deepinfra.md +92 -0
  537. package/docs/providers/deepseek.md +146 -0
  538. package/docs/providers/ds4.md +309 -0
  539. package/docs/providers/elevenlabs.md +130 -0
  540. package/docs/providers/fal.md +240 -0
  541. package/docs/providers/fireworks.md +144 -0
  542. package/docs/providers/github-copilot.md +257 -0
  543. package/docs/providers/gmi.md +92 -0
  544. package/docs/providers/google.md +472 -0
  545. package/docs/providers/gradium.md +123 -0
  546. package/docs/providers/groq.md +171 -0
  547. package/docs/providers/huggingface.md +235 -0
  548. package/docs/providers/index.md +105 -0
  549. package/docs/providers/inferrs.md +272 -0
  550. package/docs/providers/inworld.md +120 -0
  551. package/docs/providers/kilocode.md +135 -0
  552. package/docs/providers/litellm.md +234 -0
  553. package/docs/providers/lmstudio.md +224 -0
  554. package/docs/providers/minimax.md +518 -0
  555. package/docs/providers/mistral.md +235 -0
  556. package/docs/providers/models.md +64 -0
  557. package/docs/providers/moonshot.md +413 -0
  558. package/docs/providers/novita.md +92 -0
  559. package/docs/providers/nvidia.md +208 -0
  560. package/docs/providers/ollama-cloud.md +115 -0
  561. package/docs/providers/ollama.md +1225 -0
  562. package/docs/providers/openai.md +1091 -0
  563. package/docs/providers/opencode-go.md +123 -0
  564. package/docs/providers/opencode.md +149 -0
  565. package/docs/providers/openrouter.md +390 -0
  566. package/docs/providers/perplexity-provider.md +123 -0
  567. package/docs/providers/pixverse.md +165 -0
  568. package/docs/providers/qianfan.md +132 -0
  569. package/docs/providers/qwen-oauth.md +115 -0
  570. package/docs/providers/qwen.md +364 -0
  571. package/docs/providers/runway.md +103 -0
  572. package/docs/providers/senseaudio.md +68 -0
  573. package/docs/providers/sglang.md +161 -0
  574. package/docs/providers/stepfun.md +229 -0
  575. package/docs/providers/synthetic.md +154 -0
  576. package/docs/providers/tencent.md +130 -0
  577. package/docs/providers/together.md +140 -0
  578. package/docs/providers/venice.md +312 -0
  579. package/docs/providers/vercel-ai-gateway.md +128 -0
  580. package/docs/providers/vllm.md +407 -0
  581. package/docs/providers/volcengine.md +199 -0
  582. package/docs/providers/vydra.md +180 -0
  583. package/docs/providers/xai.md +571 -0
  584. package/docs/providers/xiaomi.md +286 -0
  585. package/docs/providers/zai.md +224 -0
  586. package/docs/refactor/access.md +9 -0
  587. package/docs/refactor/acp.md +298 -0
  588. package/docs/refactor/canvas.md +131 -0
  589. package/docs/refactor/database-first.md +2263 -0
  590. package/docs/refactor/ingress-core.md +341 -0
  591. package/docs/reference/AGENTS.default.md +131 -0
  592. package/docs/reference/RELEASING.md +844 -0
  593. package/docs/reference/api-usage-costs.md +208 -0
  594. package/docs/reference/application-modernization-plan.md +208 -0
  595. package/docs/reference/code-mode.md +1058 -0
  596. package/docs/reference/credits.md +33 -0
  597. package/docs/reference/device-models.md +50 -0
  598. package/docs/reference/full-release-validation.md +206 -0
  599. package/docs/reference/memory-config.md +630 -0
  600. package/docs/reference/prompt-caching.md +358 -0
  601. package/docs/reference/release-performance-sweep.md +347 -0
  602. package/docs/reference/rich-output-protocol.md +93 -0
  603. package/docs/reference/rpc.md +43 -0
  604. package/docs/reference/secret-placeholder-conventions.md +33 -0
  605. package/docs/reference/secretref-credential-surface.md +163 -0
  606. package/docs/reference/secretref-user-supplied-credentials-matrix.json +691 -0
  607. package/docs/reference/session-management-compaction.md +474 -0
  608. package/docs/reference/templates/AGENTS.dev.md +90 -0
  609. package/docs/reference/templates/AGENTS.md +227 -0
  610. package/docs/reference/templates/BOOT.md +16 -0
  611. package/docs/reference/templates/BOOTSTRAP.md +66 -0
  612. package/docs/reference/templates/HEARTBEAT.md +24 -0
  613. package/docs/reference/templates/IDENTITY.dev.md +52 -0
  614. package/docs/reference/templates/IDENTITY.md +34 -0
  615. package/docs/reference/templates/SOUL.dev.md +82 -0
  616. package/docs/reference/templates/SOUL.md +49 -0
  617. package/docs/reference/templates/TOOLS.dev.md +29 -0
  618. package/docs/reference/templates/TOOLS.md +51 -0
  619. package/docs/reference/templates/USER.dev.md +23 -0
  620. package/docs/reference/templates/USER.md +28 -0
  621. package/docs/reference/test.md +248 -0
  622. package/docs/reference/token-use.md +246 -0
  623. package/docs/reference/transcript-hygiene.md +226 -0
  624. package/docs/reference/wizard.md +252 -0
  625. package/docs/security/CONTRIBUTING-THREAT-MODEL.md +101 -0
  626. package/docs/security/THREAT-MODEL-ATLAS.md +611 -0
  627. package/docs/security/formal-verification.md +170 -0
  628. package/docs/security/incident-response.md +59 -0
  629. package/docs/security/network-proxy.md +268 -0
  630. package/docs/snippets/plugin-publish/minimal-openclaw.plugin.json +12 -0
  631. package/docs/snippets/plugin-publish/minimal-package.json +16 -0
  632. package/docs/specs/claw-supervisor.md +247 -0
  633. package/docs/start/bootstrapping.md +49 -0
  634. package/docs/start/docs-directory.md +69 -0
  635. package/docs/start/getting-started.md +152 -0
  636. package/docs/start/hubs.md +201 -0
  637. package/docs/start/lore.md +223 -0
  638. package/docs/start/onboarding-overview.md +72 -0
  639. package/docs/start/onboarding.md +98 -0
  640. package/docs/start/openclaw.md +246 -0
  641. package/docs/start/quickstart.md +25 -0
  642. package/docs/start/setup.md +178 -0
  643. package/docs/start/showcase.md +371 -0
  644. package/docs/start/wizard-cli-automation.md +232 -0
  645. package/docs/start/wizard-cli-reference.md +331 -0
  646. package/docs/start/wizard.md +142 -0
  647. package/docs/style.css +137 -0
  648. package/docs/tools/acp-agents-setup.md +356 -0
  649. package/docs/tools/acp-agents.md +865 -0
  650. package/docs/tools/agent-send.md +130 -0
  651. package/docs/tools/apply-patch.md +64 -0
  652. package/docs/tools/brave-search.md +139 -0
  653. package/docs/tools/browser-control.md +405 -0
  654. package/docs/tools/browser-linux-troubleshooting.md +173 -0
  655. package/docs/tools/browser-login.md +77 -0
  656. package/docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md +219 -0
  657. package/docs/tools/browser.md +866 -0
  658. package/docs/tools/btw.md +159 -0
  659. package/docs/tools/capability-cookbook.md +12 -0
  660. package/docs/tools/clawhub.md +5 -0
  661. package/docs/tools/code-execution.md +173 -0
  662. package/docs/tools/creating-skills.md +271 -0
  663. package/docs/tools/diffs.md +527 -0
  664. package/docs/tools/duckduckgo-search.md +109 -0
  665. package/docs/tools/elevated.md +128 -0
  666. package/docs/tools/exa-search.md +152 -0
  667. package/docs/tools/exec-approvals-advanced.md +457 -0
  668. package/docs/tools/exec-approvals.md +520 -0
  669. package/docs/tools/exec.md +294 -0
  670. package/docs/tools/firecrawl.md +155 -0
  671. package/docs/tools/gemini-search.md +114 -0
  672. package/docs/tools/goal.md +217 -0
  673. package/docs/tools/grok-search.md +129 -0
  674. package/docs/tools/image-generation.md +538 -0
  675. package/docs/tools/index.md +176 -0
  676. package/docs/tools/kimi-search.md +105 -0
  677. package/docs/tools/llm-task.md +137 -0
  678. package/docs/tools/lobster.md +365 -0
  679. package/docs/tools/loop-detection.md +154 -0
  680. package/docs/tools/media-overview.md +161 -0
  681. package/docs/tools/minimax-search.md +102 -0
  682. package/docs/tools/multi-agent-sandbox-tools.md +409 -0
  683. package/docs/tools/music-generation.md +372 -0
  684. package/docs/tools/ollama-search.md +153 -0
  685. package/docs/tools/parallel-search.md +154 -0
  686. package/docs/tools/pdf.md +213 -0
  687. package/docs/tools/permission-modes.md +111 -0
  688. package/docs/tools/perplexity-search.md +220 -0
  689. package/docs/tools/plugin.md +378 -0
  690. package/docs/tools/reactions.md +100 -0
  691. package/docs/tools/searxng-search.md +141 -0
  692. package/docs/tools/skill-workshop.md +283 -0
  693. package/docs/tools/skills-config.md +457 -0
  694. package/docs/tools/skills.md +591 -0
  695. package/docs/tools/slash-commands.md +518 -0
  696. package/docs/tools/steer.md +77 -0
  697. package/docs/tools/subagents.md +652 -0
  698. package/docs/tools/tavily.md +162 -0
  699. package/docs/tools/thinking.md +142 -0
  700. package/docs/tools/tokenjuice.md +84 -0
  701. package/docs/tools/tool-search.md +269 -0
  702. package/docs/tools/trajectory.md +229 -0
  703. package/docs/tools/tts.md +1013 -0
  704. package/docs/tools/video-generation.md +555 -0
  705. package/docs/tools/web-fetch.md +210 -0
  706. package/docs/tools/web.md +476 -0
  707. package/docs/tts.md +11 -0
  708. package/docs/vps.md +139 -0
  709. package/docs/web/control-ui.md +530 -0
  710. package/docs/web/dashboard.md +107 -0
  711. package/docs/web/index.md +133 -0
  712. package/docs/web/tui.md +258 -0
  713. package/docs/web/webchat.md +102 -0
  714. package/npm-shrinkwrap.json +3485 -0
  715. package/openclaw.mjs +661 -0
  716. package/package.json +1971 -0
  717. package/patches/.gitkeep +0 -0
  718. package/patches/@agentclientprotocol__claude-agent-acp@0.39.0.patch +40 -0
  719. package/pnpm-workspace.yaml +124 -0
  720. package/scripts/crabbox-wrapper.mjs +2470 -0
  721. package/scripts/lib/official-external-channel-catalog.json +570 -0
  722. package/scripts/lib/official-external-plugin-catalog.json +284 -0
  723. package/scripts/lib/official-external-provider-catalog.json +158 -0
  724. package/scripts/lib/package-dist-imports.mjs +174 -0
  725. package/scripts/npm-runner.mjs +95 -0
  726. package/scripts/postinstall-bundled-plugins.mjs +978 -0
  727. package/scripts/preinstall-package-manager-warning.mjs +74 -0
  728. package/scripts/prepare-git-hooks.mjs +73 -0
  729. package/scripts/windows-cmd-helpers.mjs +29 -0
  730. package/skills/1password/SKILL.md +70 -0
  731. package/skills/1password/references/cli-examples.md +29 -0
  732. package/skills/1password/references/get-started.md +17 -0
  733. package/skills/apple-notes/SKILL.md +77 -0
  734. package/skills/apple-reminders/SKILL.md +118 -0
  735. package/skills/bear-notes/SKILL.md +107 -0
  736. package/skills/blogwatcher/SKILL.md +69 -0
  737. package/skills/blucli/SKILL.md +47 -0
  738. package/skills/camsnap/SKILL.md +45 -0
  739. package/skills/canvas/SKILL.md +78 -0
  740. package/skills/clawhub/SKILL.md +77 -0
  741. package/skills/coding-agent/SKILL.md +143 -0
  742. package/skills/diagram-maker/SKILL.md +53 -0
  743. package/skills/diagram-maker/references/excalidraw-patterns.md +85 -0
  744. package/skills/diagram-maker/references/svg-template.md +112 -0
  745. package/skills/discord/SKILL.md +136 -0
  746. package/skills/eightctl/SKILL.md +50 -0
  747. package/skills/gemini/SKILL.md +47 -0
  748. package/skills/gh-issues/SKILL.md +213 -0
  749. package/skills/gifgrep/SKILL.md +85 -0
  750. package/skills/github/SKILL.md +84 -0
  751. package/skills/gog/SKILL.md +116 -0
  752. package/skills/goplaces/SKILL.md +52 -0
  753. package/skills/healthcheck/SKILL.md +105 -0
  754. package/skills/himalaya/SKILL.md +80 -0
  755. package/skills/himalaya/references/configuration.md +184 -0
  756. package/skills/himalaya/references/message-composition.md +199 -0
  757. package/skills/imsg/SKILL.md +122 -0
  758. package/skills/mcporter/SKILL.md +61 -0
  759. package/skills/meme-maker/SKILL.md +42 -0
  760. package/skills/meme-maker/references/templates.json +358 -0
  761. package/skills/meme-maker/scripts/meme.mjs +398 -0
  762. package/skills/model-usage/SKILL.md +71 -0
  763. package/skills/model-usage/references/codexbar-cli.md +33 -0
  764. package/skills/model-usage/scripts/model_usage.py +319 -0
  765. package/skills/model-usage/scripts/test_model_usage.py +40 -0
  766. package/skills/nano-pdf/SKILL.md +38 -0
  767. package/skills/node-connect/SKILL.md +143 -0
  768. package/skills/node-inspect-debugger/SKILL.md +85 -0
  769. package/skills/notion/SKILL.md +150 -0
  770. package/skills/obsidian/SKILL.md +119 -0
  771. package/skills/openai-whisper/SKILL.md +38 -0
  772. package/skills/openai-whisper-api/SKILL.md +71 -0
  773. package/skills/openai-whisper-api/scripts/transcribe.sh +154 -0
  774. package/skills/openhue/SKILL.md +112 -0
  775. package/skills/oracle/SKILL.md +126 -0
  776. package/skills/ordercli/SKILL.md +78 -0
  777. package/skills/peekaboo/SKILL.md +198 -0
  778. package/skills/pyproject.toml +10 -0
  779. package/skills/python-debugpy/SKILL.md +73 -0
  780. package/skills/sag/SKILL.md +87 -0
  781. package/skills/session-logs/SKILL.md +151 -0
  782. package/skills/sherpa-onnx-tts/SKILL.md +109 -0
  783. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  784. package/skills/skill-creator/SKILL.md +78 -0
  785. package/skills/skill-creator/license.txt +202 -0
  786. package/skills/skill-creator/scripts/init_skill.py +378 -0
  787. package/skills/skill-creator/scripts/package_skill.py +144 -0
  788. package/skills/skill-creator/scripts/quick_validate.py +169 -0
  789. package/skills/skill-creator/scripts/test_package_skill.py +199 -0
  790. package/skills/skill-creator/scripts/test_quick_validate.py +116 -0
  791. package/skills/slack/SKILL.md +78 -0
  792. package/skills/songsee/SKILL.md +49 -0
  793. package/skills/sonoscli/SKILL.md +65 -0
  794. package/skills/spike/SKILL.md +51 -0
  795. package/skills/spotify-player/SKILL.md +64 -0
  796. package/skills/summarize/SKILL.md +87 -0
  797. package/skills/taskflow/SKILL.md +149 -0
  798. package/skills/taskflow/examples/inbox-triage.lobster +33 -0
  799. package/skills/taskflow/examples/pr-intake.lobster +32 -0
  800. package/skills/taskflow-inbox-triage/SKILL.md +119 -0
  801. package/skills/things-mac/SKILL.md +86 -0
  802. package/skills/tmux/SKILL.md +91 -0
  803. package/skills/tmux/scripts/find-sessions.sh +112 -0
  804. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  805. package/skills/trello/SKILL.md +108 -0
  806. package/skills/video-frames/SKILL.md +46 -0
  807. package/skills/video-frames/scripts/frame.sh +81 -0
  808. package/skills/voice-call/SKILL.md +45 -0
  809. package/skills/wacli/SKILL.md +72 -0
  810. package/skills/weather/SKILL.md +87 -0
  811. package/skills/xurl/SKILL.md +120 -0
  812. package/src/agents/templates/HEARTBEAT.md +5 -0
@@ -0,0 +1,2263 @@
1
+ ---
2
+ summary: "Migration plan for making SQLite the primary durable state and cache layer while keeping config file-backed"
3
+ title: "Database-first state refactor"
4
+ read_when:
5
+ - Moving OpenClaw runtime data, cache, transcripts, task state, or scratch files into SQLite
6
+ - Designing doctor migrations from legacy JSON or JSONL files
7
+ - Changing backup, restore, VFS, or worker storage behavior
8
+ - Removing session locks, pruning, truncation, or JSON compatibility paths
9
+ ---
10
+
11
+ # Database-First State Refactor
12
+
13
+ ## Decision
14
+
15
+ Use a two-level SQLite layout:
16
+
17
+ - Global database: `~/.openclaw/state/openclaw.sqlite`
18
+ - Agent database: one SQLite database per agent for agent-owned workspace,
19
+ transcript, VFS, artifact, and large per-agent runtime state
20
+ - Configuration stays file-backed: `openclaw.json` remains outside the
21
+ database. Runtime auth profiles move to SQLite; external provider or CLI
22
+ credential files remain owner-managed outside OpenClaw's database.
23
+
24
+ The global database is the control-plane database. It owns agent discovery,
25
+ shared gateway state, pairing, device/node state, task and flow ledgers, plugin
26
+ state, scheduler runtime state, backup metadata, and migration state.
27
+
28
+ The agent database is the data-plane database. It owns the agent's session
29
+ metadata, transcript event stream, VFS workspace or scratch namespace, tool
30
+ artifacts, run artifacts, and searchable/indexable agent-local cache data.
31
+
32
+ This gives one durable global view without forcing large agent workspaces,
33
+ transcripts, and binary scratch data into the shared gateway write lane.
34
+
35
+ ## Hard Contract
36
+
37
+ This migration has one canonical runtime shape:
38
+
39
+ - Session rows persist session metadata only. They must not persist
40
+ `transcriptLocator`, transcript file paths, sibling JSONL paths, lock paths,
41
+ pruning metadata, or file-era compatibility pointers.
42
+ - Transcript identity is always SQLite identity: `{agentId, sessionId}` plus
43
+ optional topic metadata where the protocol needs it.
44
+ - `sqlite-transcript://...` is not a runtime or protocol identity. New code must
45
+ not derive, persist, pass, parse, or migrate transcript locators. Runtime and
46
+ tests should not contain pseudo-locators at all; docs may mention the string
47
+ only to ban it.
48
+ - Legacy `sessions.json`, transcript JSONL, `.jsonl.lock`, pruning, truncation,
49
+ and old session-path logic belong only to the doctor migration/import path.
50
+ - Legacy session config aliases belong only to doctor migration. Runtime does
51
+ not interpret `session.idleMinutes`, `session.resetByType.dm`, or
52
+ cross-agent `agent:main:*` main-session aliases for another configured agent.
53
+ - Session routing identity is typed relational state. Hot runtime and UI paths
54
+ should read `sessions.session_scope`, `sessions.account_id`,
55
+ `sessions.primary_conversation_id`, `conversations`, and
56
+ `session_conversations`; they must not parse `session_key` or mine
57
+ `session_entries.entry_json` for provider identity except as a compatibility
58
+ shadow while old call sites are being deleted.
59
+ - Channel-level direct-message markers such as `dm` versus `direct` are routing
60
+ vocabulary, not transcript locators or file-store compatibility handles.
61
+ - Legacy hook handler config belongs only to doctor warning/migration surfaces.
62
+ Runtime must not load `hooks.internal.handlers`; hooks run through discovered
63
+ hook directories and `HOOK.md` metadata only.
64
+ - Runtime startup, hot reply paths, compaction, reset, recovery, diagnostics,
65
+ TTS, memory hooks, subagents, plugin command routing, protocol boundaries, and
66
+ hooks must pass `{agentId, sessionId}` through the runtime.
67
+ - Tests should seed and assert SQLite transcript rows through
68
+ `{agentId, sessionId}`. Tests that only prove JSONL path forwarding,
69
+ caller-supplied locator preservation, or transcript-file compatibility should
70
+ be deleted unless they cover doctor import, non-session support/debug
71
+ materialization, or protocol shape.
72
+ - `runEmbeddedPiAgent(...)`, prepared worker runs, and the inner embedded
73
+ attempt must not accept transcript locators. They open the SQLite transcript
74
+ manager by `{agentId, sessionId}` and pass that manager to the internalized
75
+ PI-compatible agent session, so stale callers cannot make the runner write
76
+ JSON/JSONL transcripts.
77
+ - Runner diagnostics must store runtime/cache/payload trace records in SQLite.
78
+ Runtime diagnostics must not expose JSONL file override knobs or generic
79
+ transcript JSONL export helpers; user-facing exports can materialize explicit
80
+ artifacts from database rows without feeding file names back into runtime.
81
+ - Raw stream logging uses `OPENCLAW_RAW_STREAM=1` plus SQLite diagnostics rows.
82
+ The old pi-mono `PI_RAW_STREAM`, `PI_RAW_STREAM_PATH`, and
83
+ `raw-openai-completions.jsonl` file logger contract is not part of OpenClaw
84
+ runtime or tests.
85
+ - QMD memory indexing must not export SQLite transcripts to markdown files.
86
+ QMD indexes configured memory files only; session transcript search stays
87
+ SQLite-backed.
88
+ - The QMD SDK subpath is QMD-only for new code. SQLite session transcript
89
+ indexing helpers live on `memory-core-host-engine-session-transcripts`; any
90
+ QMD re-export is compatibility only and must not be used by runtime code.
91
+ - Built-in memory indexes live in the owning agent database. Runtime config and
92
+ resolved runtime contracts must not expose `memorySearch.store.path`; doctor
93
+ deletes that legacy config key and current code passes the agent
94
+ `databasePath` internally.
95
+
96
+ Implementation work should keep deleting code until these statements are true
97
+ without exceptions outside doctor/import/export/debug boundaries.
98
+
99
+ ## Goal state and progress
100
+
101
+ ### Hard goal
102
+
103
+ - One global SQLite database owns control-plane state:
104
+ `state/openclaw.sqlite`.
105
+ - One per-agent SQLite database owns data-plane state:
106
+ `agents/<agentId>/agent/openclaw-agent.sqlite`.
107
+ - Config remains file-backed. `openclaw.json` is not part of this database
108
+ refactor.
109
+ - Legacy files are doctor migration inputs only.
110
+ - Runtime never writes or reads session or transcript JSONL as active state.
111
+
112
+ ### Goal states
113
+
114
+ - `not-started`: file-era runtime code still writes active state.
115
+ - `migrating`: doctor/import code can move file data into SQLite.
116
+ - `dual-read`: temporary bridge reads both SQLite and legacy files. This state
117
+ is forbidden for this refactor unless it is explicitly documented as
118
+ doctor-only.
119
+ - `sqlite-runtime`: runtime reads and writes SQLite only.
120
+ - `clean`: legacy runtime APIs and tests are removed, and the guard prevents
121
+ regressions.
122
+ - `done`: docs, tests, backup, doctor migration, and changed checks prove the
123
+ clean state.
124
+
125
+ ### Current state
126
+
127
+ - Sessions: `clean` for runtime. Session rows live in the per-agent database,
128
+ runtime APIs use `{agentId, sessionId}` or `{agentId, sessionKey}`, and
129
+ `sessions.json` is doctor-only legacy input.
130
+ - Transcripts: `clean` for runtime. Transcript events, identities, snapshots,
131
+ and trajectory runtime events live in the per-agent database. Runtime no
132
+ longer accepts transcript locators or JSONL transcript paths.
133
+ - PI embedded runner: `clean`. Embedded PI runs, prepared workers, compaction,
134
+ and retry loops use SQLite session scope and reject stale transcript handles.
135
+ - Cron: `clean` for runtime. Runtime uses `cron_jobs` and `cron_run_logs`;
136
+ runtime tests use SQLite `storeKey` naming, and file-era cron paths remain in
137
+ doctor legacy migration tests only.
138
+ - Task registry: `clean`. Task and Task Flow runtime rows live in
139
+ `state/openclaw.sqlite`; unshipped sidecar SQLite importers are deleted.
140
+ - Plugin state: `clean`. Plugin state/blob rows live in the shared global
141
+ database; old plugin-state sidecar SQLite helpers are guarded against.
142
+ - Memory: `sqlite-runtime` for built-in memory and session transcript indexing.
143
+ Memory index tables live in the per-agent database, plugin memory state uses
144
+ shared plugin-state rows, and legacy memory files are doctor migration inputs
145
+ or user workspace content.
146
+ - Backup: `sqlite-runtime`. Backup stages compact SQLite snapshots, omits live
147
+ WAL/SHM sidecars, verifies SQLite integrity, and records backup runs in the
148
+ global database.
149
+ - Doctor migration: `migrating`, intentionally. Doctor imports legacy JSON,
150
+ JSONL, and retired sidecar stores into SQLite, records migration runs/sources,
151
+ and removes successful sources.
152
+ - E2E scripts: `clean` for runtime coverage. Docker MCP seeding writes SQLite
153
+ rows. The runtime-context Docker script creates legacy JSONL only inside the
154
+ doctor migration seed and names the legacy session index path explicitly.
155
+
156
+ ### Remaining work
157
+
158
+ - [x] Rename cron runtime-test store variables away from `storePath` unless
159
+ they are doctor legacy inputs.
160
+ Files: `src/cron/service.test-harness.ts`,
161
+ `src/cron/service.runs-one-shot-main-job-disables-it.test.ts`,
162
+ `src/cron/service/timer.regression.test.ts`,
163
+ `src/cron/service/ops.test.ts`, `src/cron/service/store.test.ts`,
164
+ `src/cron/service.heartbeat-ok-summary-suppressed.test.ts`,
165
+ `src/cron/service.main-job-passes-heartbeat-target-last.test.ts`,
166
+ `src/cron/store.test.ts`.
167
+ Proof: `pnpm check:database-first-legacy-stores`; `rg -n 'storePath' src/cron --glob '!**/commands/doctor/**'`.
168
+ - [x] Remove or rename obsolete file-era export test mocks.
169
+ File: `src/auto-reply/reply/commands-export-test-mocks.ts`.
170
+ Proof: `rg -n 'resolveSessionFilePath|sessionFile|storePath|transcriptLocator' src/auto-reply/reply`.
171
+ - [x] Make the Docker runtime-context legacy JSONL seed obviously doctor-only.
172
+ File: `scripts/e2e/session-runtime-context-docker-client.ts`.
173
+ Proof: `rg -n 'sessions\\.json|sessionFile|\\.jsonl' scripts/e2e/session-runtime-context-docker-client.ts` shows only
174
+ `seedBrokenLegacySessionForDoctorMigration`.
175
+ - [x] Keep Kysely generated types aligned after any schema change.
176
+ Files: `src/state/openclaw-state-schema.sql`,
177
+ `src/state/openclaw-agent-schema.sql`,
178
+ `src/state/*generated*`.
179
+ Proof: no schema change in this pass; `pnpm db:kysely:check`;
180
+ `pnpm lint:kysely`.
181
+ - [x] Re-run focused tests for touched stores, commands, and scripts.
182
+ Proof: `pnpm test src/cron/service/store.test.ts src/cron/store.test.ts src/cron/service.heartbeat-ok-summary-suppressed.test.ts src/cron/service.main-job-passes-heartbeat-target-last.test.ts src/cron/service.every-jobs-fire.test.ts src/cron/service.persists-delivered-status.test.ts src/cron/service.runs-one-shot-main-job-disables-it.test.ts src/cron/service/ops.test.ts src/cron/service/timer.regression.test.ts src/auto-reply/reply/commands-export-trajectory.test.ts extensions/telegram/src/thread-bindings.test.ts extensions/slack/src/monitor/message-handler/prepare.test.ts src/acp/translator.session-lineage-meta.test.ts`; `git diff --check`.
183
+ - [x] Before declaring `done`, run the changed gate or remote broad proof.
184
+ Proof: `pnpm check:changed --timed -- <changed extension paths>` passed on
185
+ Hetzner Crabbox run `run_3f1cabf6b25c` after temporary Node 24/pnpm setup and
186
+ explicit path routing for the synced no-`.git` workspace.
187
+
188
+ ### Do not regress
189
+
190
+ - No transcript locators.
191
+ - No active session files.
192
+ - No fake JSONL test fixtures except doctor legacy migration tests.
193
+ - No raw SQLite access where Kysely is expected.
194
+ - No new legacy DB migrations. This layout has not shipped; keep schema version
195
+ at `1` unless there is a strong reason.
196
+
197
+ ## Code-Read Assumptions
198
+
199
+ No follow-up product decisions are blocking this plan. The implementation should
200
+ proceed with these assumptions:
201
+
202
+ - Use `node:sqlite` directly and require the Node 22+ runtime for this storage
203
+ path.
204
+ - Keep exactly one normal configuration file. Do not move config, plugin
205
+ manifests, or Git workspaces into SQLite in this refactor.
206
+ - Runtime compatibility files are not required. Legacy JSON and JSONL files are
207
+ migration inputs only. The branch-local SQLite sidecars never shipped and are
208
+ deleted instead of imported.
209
+ - `openclaw doctor --fix` owns the legacy file-to-database migration step.
210
+ Runtime startup and `openclaw migrate` should not carry legacy OpenClaw
211
+ database-upgrade paths.
212
+ - Credential compatibility follows the same rule: runtime credentials live in
213
+ SQLite. Old `auth-profiles.json`, per-agent `auth.json`, and shared
214
+ `credentials/oauth.json` files are doctor migration inputs, then removed
215
+ after import.
216
+ - Generated model catalog state is database-backed. Runtime code must not write
217
+ `agents/<agentId>/agent/models.json`; existing `models.json` files are legacy
218
+ doctor inputs and are removed after import into `agent_model_catalogs`.
219
+ - Runtime must not migrate, normalize, or bridge transcript locators. Active
220
+ transcript identity is `{agentId, sessionId}` in SQLite. File paths are
221
+ legacy doctor inputs only, and `sqlite-transcript://...` must disappear from
222
+ runtime, protocol, hook, and plugin surfaces instead of being treated as a
223
+ boundary handle.
224
+ - Runtime SQLite transcript reads do not run old JSONL entry-shape migrations or
225
+ rewrite whole transcripts for compatibility. Legacy entry normalization stays in
226
+ explicit doctor/import utilities. Doctor normalizes legacy JSONL transcript
227
+ files before inserting SQLite rows; current runtime rows are
228
+ already written in the current transcript schema. Trajectory/session export
229
+ reads those rows as-is and must not perform export-time legacy migrations.
230
+ - Legacy transcript JSONL parse/migration helpers are doctor-only. Runtime
231
+ transcript format code builds current SQLite transcript context only; doctor
232
+ owns old JSONL entry upgrades before inserting rows.
233
+ - The old runtime-owned JSONL transcript streaming helper was deleted. Doctor
234
+ import code owns explicit legacy file reads; runtime session history reads
235
+ SQLite rows.
236
+ - Codex app-server bindings use the OpenClaw `sessionId` as the canonical
237
+ key in the Codex plugin-state namespace. `sessionKey` is metadata for
238
+ routing/display and must not replace the durable session id or resurrect
239
+ transcript-file identity.
240
+ - Context engines receive the current runtime contract directly. The registry
241
+ must not wrap engines with retry shims that delete `sessionKey`,
242
+ `transcriptScope`, or `prompt`; engines that cannot accept the current
243
+ database-first params should fail loudly instead of being bridged.
244
+ - Backup output should remain one archive file. Database contents should enter
245
+ that archive as compact SQLite snapshots, not raw live WAL sidecars.
246
+ - Transcript search is useful but not required for the first database-first
247
+ cut. Design the schema so FTS can be added later.
248
+ - Worker execution should stay experimental behind settings while the database
249
+ boundary settles.
250
+
251
+ ## Code-Read Findings
252
+
253
+ The current branch is already past the proof-of-concept stage. The shared
254
+ database exists, Node `node:sqlite` is wired through a small runtime helper, and
255
+ former stores now write to `state/openclaw.sqlite` or the owning
256
+ `openclaw-agent.sqlite` database.
257
+
258
+ The remaining work is not choosing SQLite; it is keeping the new boundary clean
259
+ and deleting any compatibility-shaped interfaces that still look like the old
260
+ file world:
261
+
262
+ - Session `storePath` is no longer a runtime identity, test fixture shape, or
263
+ status payload field. Runtime and bridge tests no longer contain the
264
+ `storePath` contract name; doctor/migration code owns that legacy vocabulary.
265
+ - Session writes no longer pass through the old in-process `store-writer.ts`
266
+ queue. SQLite patch writes use conflict detection and bounded retry instead.
267
+ - Legacy path discovery still has valid migration uses, but runtime code should
268
+ stop treating `sessions.json` and transcript JSONL files as possible write
269
+ targets.
270
+ - Agent-owned tables live in per-agent SQLite databases. The global DB keeps
271
+ registry/control-plane rows; transcript identity is `{agentId, sessionId}` in
272
+ the per-agent transcript rows. Runtime code must not persist transcript file
273
+ paths or migrate transcript locators.
274
+ - Doctor already imports several legacy files. The cleanup is to make that a
275
+ single explicit migration implementation that doctor calls, with a durable
276
+ migration report.
277
+
278
+ No additional product questions are blocking implementation.
279
+
280
+ ## Current Code Shape
281
+
282
+ The branch already has a real shared SQLite base:
283
+
284
+ - The runtime floor is now Node 22+: `package.json`, the CLI runtime guard,
285
+ installer defaults, macOS runtime locator, CI, and public install docs all
286
+ agree. The old Node 22 compatibility lane is removed.
287
+ - `src/state/openclaw-state-db.ts` opens `openclaw.sqlite`, sets WAL,
288
+ `synchronous=NORMAL`, `busy_timeout=30000`, `foreign_keys=ON`, and applies
289
+ the generated schema module derived from
290
+ `src/state/openclaw-state-schema.sql`.
291
+ - Kysely table types and runtime schema modules are generated from disposable
292
+ SQLite databases created from the committed `.sql` files; runtime code no
293
+ longer keeps copy-pasted schema strings for global, per-agent, or proxy
294
+ capture databases.
295
+ - Runtime stores derive selected and inserted row types from those generated
296
+ Kysely `DB` interfaces instead of shadowing SQLite row shapes by hand. Raw SQL
297
+ remains limited to schema application, pragmas, and migration-only DDL.
298
+ - The SQLite schemas are collapsed to `user_version = 1` because this database
299
+ layout has not shipped yet. Runtime openers create the current schema only;
300
+ file-to-database import remains in doctor code, and branch-local
301
+ database upgrade helpers have been deleted.
302
+ - Relational ownership is enforced where the ownership boundary is canonical:
303
+ source migration rows cascade from `migration_runs`, task delivery state
304
+ cascades from `task_runs`, and transcript identity rows cascade from
305
+ transcript events.
306
+ - Current shared tables include `agent_databases`,
307
+ `auth_profile_stores`, `auth_profile_state`,
308
+ `plugin_state_entries`, `plugin_blob_entries`, `media_blobs`,
309
+ `skill_uploads`, `capture_sessions`, `capture_events`, `capture_blobs`,
310
+ `sandbox_registry_entries`, `cron_run_logs`, `cron_jobs`, `commitments`,
311
+ `delivery_queue_entries`, `model_capability_cache`,
312
+ `workspace_setup_state`, `native_hook_relay_bridges`,
313
+ `current_conversation_bindings`, `plugin_binding_approvals`,
314
+ `tui_last_sessions`, `acp_sessions`, `acp_replay_sessions`,
315
+ `acp_replay_events`, `task_runs`, `task_delivery_state`, `flow_runs`,
316
+ `subagent_runs`, `migration_runs`, and `backup_runs`.
317
+ - Arbitrary plugin-owned state does not get host-owned typed tables. Installed
318
+ plugins use `plugin_state_entries` for versioned JSON payloads and
319
+ `plugin_blob_entries` for bytes, with namespace/key ownership, TTL cleanup,
320
+ backup, and plugin migration records. Host-owned plugin orchestration state can
321
+ still have typed tables when the host owns the query contract, such as
322
+ `plugin_binding_approvals`.
323
+ - Plugin migrations are data migrations over plugin-owned namespaces, not host
324
+ schema migrations. A plugin can migrate its own versioned state/blob entries
325
+ through a migration provider, and the host records source/run status in the
326
+ normal migration ledger. New plugin installs do not require changing
327
+ `openclaw-state-schema.sql` unless the host itself is taking ownership of a
328
+ new cross-plugin contract.
329
+ - `src/state/openclaw-agent-db.ts` opens
330
+ `agents/<agentId>/agent/openclaw-agent.sqlite`, registers the database in the
331
+ global DB, and owns agent-local session, transcript, VFS, artifact, cache,
332
+ and memory-index tables. Shared runtime discovery now reads the generated-typed
333
+ `agent_databases` registry instead of reimplementing that query at each call
334
+ site.
335
+ - Global and per-agent databases record a `schema_meta` row with database role,
336
+ schema version, timestamps, and agent id for agent databases. The layout still
337
+ stays at `user_version = 1` because this SQLite schema has not shipped yet.
338
+ - Per-agent session identity now has a canonical `sessions` root table keyed by
339
+ `session_id`, with `session_key`, `session_scope`, `account_id`,
340
+ `primary_conversation_id`, timestamps, display fields, model metadata,
341
+ harness id, and parent/spawn linkage as queryable columns. `session_routes`
342
+ is the unique active route index from `session_key` to the current
343
+ `session_id`, so a route key can move to a fresh durable session without
344
+ making hot reads pick between duplicate `sessions.session_key` rows. The old
345
+ `session_entries.entry_json` compatibility-shaped payload hangs off the
346
+ durable `session_id` root by foreign key; it is no longer the only
347
+ schema-level representation of a session.
348
+ - Per-agent external conversation identity is relational too:
349
+ `conversations` stores normalized provider/account/conversation identity, and
350
+ `session_conversations` links one OpenClaw session to one or more external
351
+ conversations. This covers shared-main DM sessions where multiple peers can
352
+ intentionally map to one session without lying in `session_key`. SQLite also
353
+ enforces uniqueness for the natural provider identity so the same
354
+ channel/account/kind/peer/thread tuple cannot fork across conversation ids.
355
+ Shared-main direct peers are linked with a `participant` role, so one
356
+ OpenClaw session can represent multiple external DM peers without demoting
357
+ older peers into vague related rows. `sessions.primary_conversation_id` still
358
+ points at the current typed delivery target. Closed routing/status columns
359
+ are enforced with SQLite `CHECK` constraints instead of relying only on
360
+ TypeScript unions.
361
+ Runtime session projection clears compatibility routing shadows from
362
+ `session_entries.entry_json` before applying typed session/conversation
363
+ columns, so stale JSON payloads cannot resurrect delivery targets.
364
+ Subagent announce routing likewise requires the typed SQLite delivery context;
365
+ it no longer falls back to compatibility `SessionEntry` route fields.
366
+ Gateway `chat.send` explicit delivery inheritance reads the typed SQLite
367
+ delivery context instead of `origin`/`last*` compatibility fields.
368
+ `tools.effective` likewise derives provider/account/thread context from typed
369
+ SQLite delivery/routing rows, not stale `last*` session-entry shadows.
370
+ System-event prompt context rebuilds channel/to/account/thread fields from
371
+ typed delivery fields instead of `origin` shadows.
372
+ The shared `deliveryContextFromSession` helper and session-to-conversation
373
+ mapper now ignore `SessionEntry.origin` entirely; only typed delivery fields
374
+ and relational conversation rows can create hot route identity.
375
+ Runtime session entry normalization strips `origin` before persisting or
376
+ projecting `entry_json`, and inbound metadata writes typed channel/chat
377
+ fields plus relational conversation rows instead of creating new origin
378
+ shadows.
379
+ - Transcript events, transcript snapshots, and trajectory runtime events now
380
+ reference the canonical per-agent `sessions` root and cascade on session
381
+ deletion. Transcript identity/idempotency rows continue to cascade from the
382
+ exact transcript event row.
383
+ - Memory-core indexes now use explicit agent-database tables
384
+ `memory_index_meta`, `memory_index_sources`, `memory_index_chunks`, and
385
+ `memory_embedding_cache`; optional FTS/vector side indexes use the same
386
+ `memory_index_*` prefix instead of generic `meta`, `files`, `chunks`, or
387
+ `chunks_vec` tables. `memory_index_sources` is keyed by
388
+ `(source_kind, source_key)` and carries optional `session_id` ownership, so
389
+ session-derived sources and chunks cascade when a session is deleted. Cached
390
+ chunk embeddings are stored as Float32 SQLite BLOBs, not JSON text arrays.
391
+ These tables are derived/search cache, not canonical transcript storage; they
392
+ can be deleted and rebuilt from `sessions`, `transcript_events`, and memory
393
+ workspace files.
394
+ - Subagent run recovery state now lives in typed shared `subagent_runs` rows
395
+ with indexed child, requester, and controller session keys. The old
396
+ `subagents/runs.json` file is doctor migration input only.
397
+ - Current conversation bindings now live in typed shared
398
+ `current_conversation_bindings` rows keyed by normalized conversation id, with
399
+ target agent/session columns, conversation kind, status, expiry, and metadata
400
+ stored as relational columns instead of a duplicated opaque binding record.
401
+ The durable binding key includes the normalized conversation kind so
402
+ direct/group/channel refs cannot collide, and SQLite rejects invalid binding
403
+ kind/status values. The old
404
+ `bindings/current-conversations.json` file is doctor migration input only.
405
+ - Delivery queue recovery now overlays typed queue columns for channel, target,
406
+ account, session, retry, error, platform-send, and recovery state onto the
407
+ replay JSON. `entry_json` keeps the replay payloads, hooks, and formatting
408
+ payload, but typed columns are authoritative for hot queue routing/state.
409
+ - TUI last-session restore pointers now live in typed shared
410
+ `tui_last_sessions` rows keyed by the hashed TUI connection/session scope.
411
+ The old TUI JSON file is doctor migration input only.
412
+ - Default TTS prefs now live in shared plugin-state SQLite rows keyed under the
413
+ `speech-core` plugin. The old `settings/tts.json` file is doctor migration
414
+ input only; runtime no longer reads or writes TTS prefs JSON files, and the
415
+ legacy path resolver lives in the doctor migration module.
416
+ - Secret target metadata now talks about stores instead of pretending every
417
+ credential target is a config file. `openclaw.json` remains the config store;
418
+ auth-profile targets use typed SQLite `auth_profile_stores` rows with
419
+ provider-shaped credentials kept as JSON payloads.
420
+ - Secret audit no longer scans retired per-agent `auth.json` files. Doctor owns
421
+ warning about, importing, and removing that legacy file.
422
+ - Legacy auth profile path helpers now live in doctor legacy code. Core auth
423
+ profile path helpers expose SQLite auth-store identity and display locations,
424
+ not `auth-profiles.json` or `auth-state.json` runtime paths.
425
+ - Subagent run recovery and OpenRouter model capability cache runtime modules
426
+ now keep SQLite snapshot readers/writers separate from doctor-only legacy JSON
427
+ import helpers. OpenRouter capabilities use the typed generic
428
+ `model_capability_cache` rows under `provider_id = "openrouter"` instead of
429
+ one opaque cache blob or a provider-specific host table. Subagent run
430
+ `taskName` is stored in the typed `subagent_runs.task_name` column; the
431
+ `payload_json` copy is replay/debug data, not the source for hot display or
432
+ lookup fields.
433
+ - `src/agents/filesystem/virtual-agent-fs.sqlite.ts` implements a SQLite VFS
434
+ over the agent database `vfs_entries` table. Directory reads, recursive
435
+ exports, deletes, and renames use indexed `(namespace, path)` prefix ranges
436
+ instead of scanning a whole namespace or relying on `LIKE` path matching.
437
+ - `src/agents/runtime-worker.entry.ts` creates per-run SQLite VFS, tool artifact,
438
+ run artifact, and scoped cache stores for workers.
439
+ - Workspace bootstrap completion markers now live in typed shared
440
+ `workspace_setup_state` rows keyed by resolved workspace path instead of
441
+ `.openclaw/workspace-state.json`; runtime no longer reads or rewrites the
442
+ legacy workspace marker, and helper APIs no longer pass around a fake
443
+ `.openclaw/setup-state` path just to derive storage identity.
444
+ - Exec approvals now live in the typed shared SQLite `exec_approvals_config`
445
+ singleton row. Doctor imports legacy `~/.openclaw/exec-approvals.json`;
446
+ runtime writes no longer create, rewrite, or report that file as its active
447
+ store location. The macOS companion reads and writes the same
448
+ `state/openclaw.sqlite` table row; it keeps only the Unix prompt socket on disk
449
+ because that is IPC, not durable runtime state.
450
+ - Device identity, device auth, and bootstrap runtime modules now keep their
451
+ SQLite snapshot readers/writers separate from doctor-only legacy JSON import
452
+ helpers. Device identity uses typed `device_identities` rows and device auth
453
+ tokens use typed `device_auth_tokens` rows. Device auth writes reconcile rows
454
+ by device/role instead of truncating the token table, and runtime no longer
455
+ routes single-token updates through the old whole-store adapter. The legacy
456
+ version-1 JSON payloads exist only as doctor import/export shapes.
457
+ - GitHub Copilot token exchange cache uses the shared SQLite plugin-state table
458
+ under `github-copilot/token-cache/default`. It is provider-owned cache state,
459
+ so it intentionally does not add a host schema table.
460
+ - GitHub Copilot compaction no longer writes `openclaw-compaction-*.json`
461
+ workspace sidecars. The harness calls the SDK history compaction RPC for the
462
+ tracked SDK session, and OpenClaw keeps durable session/transcript state in
463
+ SQLite instead of compatibility marker files.
464
+ - The shared Swift runtime (`OpenClawKit`) uses the same
465
+ `state/openclaw.sqlite` rows for device identity and device auth. macOS app
466
+ helpers import the shared SQLite helpers instead of owning a second JSON or
467
+ SQLite path. A leftover legacy `identity/device.json` blocks identity creation
468
+ until doctor imports it into SQLite, matching the TypeScript and Android
469
+ startup gate.
470
+ - Android device identity uses the same TypeScript-compatible key material
471
+ stored in typed `state/openclaw.sqlite#table/device_identities` rows. It never
472
+ reads or writes `openclaw/identity/device.json`; a leftover legacy file blocks
473
+ startup until doctor imports it into SQLite.
474
+ - Android cached device auth tokens also use typed
475
+ `state/openclaw.sqlite#table/device_auth_tokens` rows and share the same
476
+ version-1 token semantics as TypeScript and Swift. Runtime no longer reads `SecurePrefs`
477
+ `gateway.deviceToken*` compatibility keys; those belong to migration/doctor
478
+ logic only.
479
+ - Android notification recent-package history uses typed
480
+ `android_notification_recent_packages` rows. Runtime no longer migrates or
481
+ reads the old SharedPreferences CSV keys.
482
+ - Device identity creation fails closed when legacy `identity/device.json`
483
+ exists, when the SQLite identity row is invalid, or when the SQLite identity
484
+ store cannot be opened. Doctor imports and removes that file first, so runtime
485
+ startup cannot silently rotate pairing identity before migration.
486
+ - Device identity selection is a SQLite row key, not a JSON file locator. Tests
487
+ and gateway helpers pass explicit identity keys; only doctor migration and the
488
+ fail-closed startup gate know the retired `identity/device.json` filename.
489
+ - Session reset compatibility now lives in doctor config migration:
490
+ `session.idleMinutes` is moved into `session.reset.idleMinutes`,
491
+ `session.resetByType.dm` is moved into `session.resetByType.direct`, and the
492
+ runtime reset policy only reads canonical reset keys.
493
+ - Legacy config compatibility now lives under `src/commands/doctor/`. Normal
494
+ `readConfigFileSnapshot()` validation does not import doctor legacy detectors
495
+ or annotate legacy issues; `runDoctorConfigPreflight()` adds those issues for
496
+ doctor repair/reporting. The doctor config flow imports
497
+ `src/commands/doctor/legacy-config.ts`, and old OAuth profile-id repair lives
498
+ under
499
+ `src/commands/doctor/legacy/oauth-profile-ids.ts`.
500
+ - Non-doctor commands do not auto-run legacy config repair. For example,
501
+ `openclaw update --channel` now fails on invalid legacy config and asks the
502
+ user to run doctor, rather than silently importing doctor migration code.
503
+ - Web push, APNs, Voice Wake, update checks, and config health now use typed shared SQLite
504
+ tables for subscriptions, VAPID keys, node registrations, trigger rows,
505
+ routing rows, update-notification state, and config health entries instead of
506
+ whole opaque JSON blobs. Web push and APNs snapshot writes now reconcile
507
+ subscriptions/registrations by primary key instead of clearing their tables;
508
+ config health does the same by config path.
509
+ Their runtime modules keep SQLite snapshot readers/writers separate from
510
+ doctor-only legacy JSON import helpers.
511
+ - Node-host config now uses a typed singleton row in the shared SQLite database;
512
+ doctor imports the old `node.json` file before normal runtime use.
513
+ - Device/node pairing, channel pairing, channel allowlists, and bootstrap state
514
+ now use typed SQLite rows instead of whole opaque JSON blobs. Plugin binding
515
+ approvals and cron job state follow the same split: runtime modules expose
516
+ SQLite-backed operations and neutral snapshot helpers, and pairing/bootstrap
517
+ plus plugin binding approval snapshot writes reconcile rows by primary key
518
+ instead of truncating tables, while doctor imports/removes the old JSON files through
519
+ `src/commands/doctor/legacy/*` modules.
520
+ - Installed plugin records now live in the SQLite installed-plugin index.
521
+ Runtime config read/write no longer migrates or preserves old
522
+ `plugins.installs` authored-config data; doctor imports that legacy config
523
+ shape into SQLite before normal runtime use.
524
+ - QQBot credential recovery snapshots now live in SQLite plugin state under
525
+ `qqbot/credential-backups`. Runtime no longer writes
526
+ `qqbot/data/credential-backup*.json`; doctor imports and removes those
527
+ legacy backup files with the other QQBot state inputs.
528
+ - Gateway reload planning compares SQLite installed-plugin index snapshots under
529
+ an internal `installedPluginIndex.installRecords.*` diff namespace. Runtime
530
+ reload decisions no longer wrap those rows in fake `plugins.installs` config
531
+ objects.
532
+ - Matrix named-account credential upgrade no longer happens during runtime
533
+ reads. Doctor owns the old top-level `credentials/matrix/credentials.json`
534
+ rename when a single/default Matrix account can be resolved.
535
+ - Core pairing and cron runtime modules no longer export legacy JSON path
536
+ builders. Doctor-owned legacy modules construct `pending.json`, `paired.json`,
537
+ `bootstrap.json`, and `cron/jobs.json` source paths for import tests and
538
+ migration only. Legacy cron job-shape normalization and cron run-log import
539
+ live under `src/commands/doctor/legacy/cron*.ts`.
540
+ - `src/commands/doctor/legacy/runtime-state.ts` imports legacy JSON state
541
+ files, including node host config, into SQLite from doctor. New legacy file
542
+ importers stay under `src/commands/doctor/legacy/`.
543
+ - `src/commands/doctor/state-migrations.ts` imports legacy `sessions.json` and
544
+ `*.jsonl` transcripts directly into SQLite and removes successful sources. It
545
+ no longer stages root legacy transcripts through
546
+ `agents/<agentId>/sessions/*.jsonl` or creates a canonical JSONL target before
547
+ import.
548
+ - State integrity doctor checks no longer scan legacy session directories or
549
+ offer orphan JSONL deletion. Legacy transcript files are migration inputs
550
+ only, and the migration step owns import plus source removal.
551
+ - Legacy sandbox registry import lives under
552
+ `src/commands/doctor/legacy/sandbox-registry.ts`; active sandbox registry
553
+ reads and writes remain SQLite-only.
554
+ - The legacy session transcript health/import repair lives under
555
+ `src/commands/doctor/legacy/session-transcript-health.ts`; runtime command
556
+ modules no longer carry JSONL transcript parsing or active-branch repair code.
557
+
558
+ Completed consolidation/deletion highlights:
559
+
560
+ - Plugin state now uses the shared `state/openclaw.sqlite` database. The old
561
+ branch-local `plugin-state/state.sqlite` sidecar importer is removed because
562
+ that SQLite layout never shipped. Probe/test helpers report the shared
563
+ `databasePath` instead of exposing a plugin-state-specific SQLite path.
564
+ - Task and Task Flow runtime tables now live in the shared
565
+ `state/openclaw.sqlite` database instead of `tasks/runs.sqlite` and
566
+ `tasks/flows/registry.sqlite`; the old sidecar importers are removed for the
567
+ same unshipped-layout reason.
568
+ - `src/config/sessions/store.ts` no longer needs `storePath` for inbound
569
+ metadata, route updates, or updated-at reads. Command persistence, CLI
570
+ session cleanup, subagent depth, auth overrides, and transcript session
571
+ identity use agent/session row APIs. Writes are applied as SQLite row patches
572
+ with optimistic conflict retry.
573
+ - Session target resolution now exposes per-agent database targets, not legacy
574
+ `sessions.json` paths. Shared gateway, ACP metadata, doctor route repair, and
575
+ `openclaw sessions` enumerate `agent_databases` plus configured agents.
576
+ - Gateway session routing now uses `resolveGatewaySessionDatabaseTarget`; the
577
+ returned target carries `databasePath` and candidate SQLite row keys instead
578
+ of a legacy session-store file path.
579
+ - Channel session runtime types now expose `{agentId, sessionKey}` for
580
+ updated-at reads, inbound metadata, and last-route updates. The old
581
+ `saveSessionStore(storePath, store)` compatibility type is gone.
582
+ - Plugin runtime, extension API, and `config/sessions` barrel surfaces now steer
583
+ plugin code to SQLite-backed session row helpers. Root library compatibility
584
+ exports (`loadSessionStore`, `saveSessionStore`, `resolveStorePath`) remain as
585
+ deprecated shims for existing consumers. The old
586
+ `resolveLegacySessionStorePath` helper is gone; legacy `sessions.json` path
587
+ construction is now local to migration and test fixtures.
588
+ - `src/config/sessions/session-entries.sqlite.ts` now stores canonical session
589
+ entries in the per-agent database and has row-level read/upsert/delete patch
590
+ support. Runtime upsert/patch/delete no longer scans for case variants or
591
+ prunes legacy alias keys; doctor owns canonicalization. The
592
+ standalone JSON import helper is gone, and migration merges upsert newer rows
593
+ instead of replacing the whole session table. Public read/list/load helpers
594
+ project hot session metadata from typed `sessions` and `conversations` rows;
595
+ `entry_json` is a compatibility/debug shadow and can be stale or invalid
596
+ without losing typed session identity or delivery context.
597
+ - `src/config/sessions/delivery-info.ts` now resolves delivery context from the
598
+ typed per-agent `sessions` + `conversations` + `session_conversations` rows.
599
+ It no longer reconstructs runtime delivery identity from
600
+ `session_entries.entry_json`; a missing typed conversation row is a doctor
601
+ migration/repair problem, not a runtime fallback.
602
+ - Stored-session reset decisions now prefer typed `sessions.session_scope`,
603
+ `sessions.chat_type`, and `sessions.channel` metadata. `sessionKey` parsing
604
+ remains only for explicit thread/topic suffixes on command targets; group vs
605
+ direct reset classification no longer comes from key shape.
606
+ - Session list/status display classification now uses typed chat metadata and
607
+ gateway session kind. It no longer treats `:group:` or `:channel:` substrings
608
+ inside `session_key` as durable group/direct truth.
609
+ - Silent-reply policy selection now uses explicit conversation type or surface
610
+ metadata only. It no longer guesses direct/group policy from
611
+ `session_key` substrings.
612
+ - Session display model resolution now receives the agent id from the SQLite
613
+ session database target instead of splitting it out of `session_key`.
614
+ - Agent-to-agent announce target hydration now uses typed `sessions.list`
615
+ `deliveryContext` only. It no longer recovers channel/account/thread routing
616
+ from legacy `origin`, mirrored `last*` fields, or `session_key` shape.
617
+ - `sessions_send` thread-target rejection now reads typed SQLite routing
618
+ metadata. It no longer rejects or accepts targets by parsing thread suffixes
619
+ out of the target key.
620
+ - Group-scoped tool policy validation now reads typed SQLite conversation
621
+ routing for the current or spawned session. It no longer trusts group/channel
622
+ identity by decoding `sessionKey`; caller-provided group ids are dropped when
623
+ no typed session row vouches for them.
624
+ - Channel model override matching now uses explicit group and parent
625
+ conversation metadata. It no longer decodes parent conversation ids from
626
+ `parentSessionKey`.
627
+ - Stored model override inheritance now requires an explicit parent session key
628
+ from typed session context. It no longer derives parent overrides from
629
+ `:thread:` or `:topic:` suffixes in `sessionKey`.
630
+ - The old session thread-info wrapper and loaded-plugin thread parser are gone;
631
+ no runtime code imports `config/sessions/thread-info`.
632
+ - The channel conversation helper no longer exposes full-session-key parsing
633
+ bridges. Core still normalizes provider-owned raw conversation ids through
634
+ `resolveSessionConversation(...)`, but it does not reconstruct route facts
635
+ from `sessionKey`.
636
+ - Completion delivery, send policy, and task maintenance no longer derive chat
637
+ type from `session_key` shape. The old chat-type key parser has been deleted;
638
+ these paths require typed session metadata, typed delivery context, or
639
+ explicit delivery target vocabulary.
640
+ - Session list/status, diagnostics, approval account binding, TUI heartbeat
641
+ filtering, and usage summaries no longer mine `SessionEntry.origin` for
642
+ provider/account/thread/display routing. The only remaining runtime
643
+ `origin` reads are non-session concepts or current-turn delivery objects.
644
+ - Approval-request native conversation lookup now reads typed per-agent session
645
+ routing rows. It no longer parses channel/group/thread conversation identity
646
+ from `sessionKey`; missing typed metadata is a migration/repair issue.
647
+ - Gateway session changed/chat/session event payloads no longer echo
648
+ `SessionEntry.origin` or `last*` route shadows; clients receive typed
649
+ `channel`, `chatType`, and `deliveryContext`.
650
+ - Heartbeat delivery resolution can now receive the typed SQLite
651
+ `deliveryContext` directly, and heartbeat runtime passes the per-agent
652
+ session delivery row instead of relying on compatibility `session_entries`
653
+ shadows for current routing.
654
+ - Cron isolated-agent delivery target resolution also hydrates its current
655
+ route from the typed per-agent session delivery row before falling back to the
656
+ compatibility entry payload.
657
+ - Subagent announce origin resolution now threads the typed requester-session
658
+ delivery context through `loadRequesterSessionEntry` and prefers that row over
659
+ compatibility `last*`/`deliveryContext` shadows.
660
+ - Inbound session metadata updates now merge against the typed per-agent
661
+ delivery row first; old `SessionEntry` delivery fields are only the fallback
662
+ when no typed conversation row exists.
663
+ - Restart/update delivery extraction now lets the typed SQLite delivery
664
+ `threadId` win over topic/thread fragments parsed from `sessionKey`; parsing
665
+ is only a fallback for legacy thread-shaped keys.
666
+ - Hook agent context channel ids now prefer typed SQLite conversation identity,
667
+ then explicit message metadata. They no longer parse provider/group/channel
668
+ fragments from `sessionKey`.
669
+ - Gateway `chat.send` external-route inheritance now reads typed SQLite session
670
+ routing metadata instead of inferring channel/direct/group scope from
671
+ `sessionKey` pieces. Channel-scoped sessions inherit only when the typed
672
+ session channel and chat type match the stored delivery context; shared-main
673
+ sessions keep their stricter CLI/no-client-metadata rule.
674
+ - Restart-sentinel wake and continuation routing now reads typed SQLite
675
+ delivery/routing rows before queueing heartbeat wakes or routed agent-turn
676
+ continuations. It no longer reconstructs delivery context from the
677
+ session-entry JSON shadow.
678
+ - Gateway `tools.effective` context resolution now reads typed SQLite
679
+ delivery/routing rows for provider, account, target, thread, and reply-mode
680
+ inputs. It no longer recovers those hot routing fields from stale
681
+ `session_entries.entry_json` origin shadows.
682
+ - Realtime voice consult routing now resolves parent/call delivery from typed
683
+ per-agent SQLite session rows. It no longer falls back to compatibility
684
+ `SessionEntry.deliveryContext` shadows when choosing the embedded agent
685
+ message route.
686
+ - ACP spawn heartbeat relay and parent-stream routing now read parent delivery
687
+ from typed SQLite session rows. They no longer reconstruct parent delivery
688
+ context from compatibility session-entry shadows.
689
+ - Session delivery route preservation now follows typed chat metadata and
690
+ persisted delivery columns. It no longer extracts channel hints, direct/main
691
+ markers, or thread shape from `sessionKey`; internal webchat routes only
692
+ inherit an external target when SQLite already has typed/persisted delivery
693
+ identity for the session.
694
+ - Generic session delivery extraction now reads only the exact typed SQLite
695
+ session delivery row. It no longer parses thread/topic suffixes or falls back
696
+ from a thread-shaped key to a base session key.
697
+ - Reply dispatch, restart sentinel recovery, and realtime voice consult routing
698
+ now use exact typed SQLite session/conversation rows for thread routing. They
699
+ no longer recover thread ids or base-session delivery context by parsing
700
+ thread-shaped session keys.
701
+ - Embedded PI history limiting now uses the typed SQLite session routing
702
+ projection (`sessions` + primary `conversations`) for provider, chat type,
703
+ and peer identity. It no longer parses provider, DM, group, or thread shape
704
+ out of `sessionKey`.
705
+ - Cron tool delivery inference now uses explicit delivery or the current typed
706
+ delivery context only. It no longer decodes channel, peer, account, or thread
707
+ targets from `agentSessionKey`.
708
+ - Runtime session rows no longer carry the old `lastProvider` route alias.
709
+ Helpers and tests use typed `lastChannel` and `deliveryContext` fields;
710
+ doctor migration is the only place that should translate older route aliases
711
+ or persisted `origin` shadows.
712
+ - Transcript events, VFS rows, and tool artifact rows now write to the per-agent
713
+ database. The unshipped global transcript-file mapping table is gone; doctor
714
+ records legacy source paths in durable migration rows instead.
715
+ - Runtime transcript lookup no longer scans JSONL byte offsets or probes legacy
716
+ transcript files. Gateway chat/media/history paths read transcript rows from
717
+ SQLite; session JSONL is now only a legacy doctor input, not a runtime state
718
+ or export format.
719
+ - Transcript parent and branch relationships use structured
720
+ `parentTranscriptScope: {agentId, sessionId}` metadata in SQLite transcript
721
+ headers, not path-like `agent-db:...transcript_events...` locator strings.
722
+ - The transcript manager contract no longer exposes implicit persisted
723
+ `create(cwd)` or `continueRecent(cwd)` constructors. Persisted transcript
724
+ managers are opened with an explicit `{agentId, sessionId}` scope; only
725
+ in-memory managers remain scope-free for tests and pure transcript transforms.
726
+ - Runtime transcript store APIs resolve SQLite scope, not filesystem paths. The
727
+ old `resolve...ForPath` helper and unused `transcriptPath` write options are
728
+ gone from runtime callers.
729
+ - Runtime session resolution now uses `{agentId, sessionId}` and must not derive
730
+ `sqlite-transcript://<agent>/<session>` strings for external boundaries.
731
+ Legacy absolute JSONL paths are doctor migration inputs only.
732
+ - Native hook relay direct-bridge records now live in typed shared
733
+ `native_hook_relay_bridges` rows keyed by relay id. Runtime no longer writes a
734
+ `/tmp` JSON registry or opaque generic records for those short-lived bridge
735
+ records.
736
+ - `runEmbeddedPiAgent(...)` no longer has a transcript-locator parameter.
737
+ Prepared worker descriptors also omit transcript locators. Runtime session
738
+ state and queued follow-up runs carry `{agentId, sessionId}` instead of
739
+ derived transcript handles.
740
+ - Embedded compaction now takes SQLite scope from `agentId` and `sessionId`.
741
+ Compaction hooks, context-engine calls, CLI delegation, and protocol replies
742
+ must not receive derived `sqlite-transcript://...` handles. Export/debug code
743
+ can materialize explicit user artifacts from rows, but it does not provide a
744
+ generic session JSONL export path or feed file names back into runtime
745
+ identity.
746
+ - `/export-session` reads transcript rows from SQLite and writes the requested
747
+ standalone HTML view only. The embedded viewer no longer reconstructs or
748
+ downloads session JSONL from those rows.
749
+ - Context-engine delegation no longer parses a transcript locator to recover
750
+ agent identity. The prepared runtime context carries the resolved `agentId`
751
+ into the built-in compaction adapter.
752
+ - Transcript rewrite and live tool-result truncation now read and persist
753
+ transcript state by `{agentId, sessionId}` and do not derive temporary
754
+ locators for transcript-update event payloads.
755
+ - The transcript-state helper surface no longer has locator-based
756
+ `readTranscriptState`, `replaceTranscriptStateEvents`, or
757
+ `persistTranscriptStateMutation` variants. Runtime callers must use the
758
+ `{agentId, sessionId}` APIs. Doctor import reads legacy files by explicit file
759
+ path and writes SQLite rows; it does not migrate locator strings.
760
+ - The runtime session-manager contract no longer exposes `open(locator)`,
761
+ `forkFrom(locator)`, or `setTranscriptLocator(...)`. Persisted session
762
+ managers open by `{agentId, sessionId}` only; list/fork helpers live on
763
+ row-oriented session and checkpoint APIs instead of the transcript manager
764
+ facade.
765
+ - Gateway transcript reader APIs are scope-first. They take
766
+ `{agentId, sessionId}` and do not accept a positional transcript locator that
767
+ could accidentally become runtime identity. Active transcript locator parsing
768
+ is gone; legacy source paths are read only by doctor import code.
769
+ - Transcript update events are also scope-first. `emitSessionTranscriptUpdate`
770
+ no longer accepts a bare locator string, and listeners route by
771
+ `{agentId, sessionId}` without parsing a handle.
772
+ - Gateway session-message broadcast resolves session keys from agent/session
773
+ scope, not from a transcript locator. The old transcript-locator-to-session
774
+ key resolver/cache is gone.
775
+ - Gateway session-history SSE filters live updates by agent/session scope. It no
776
+ longer canonicalizes transcript locator candidates, realpaths, or file-shaped
777
+ transcript identities to decide whether a stream should receive an update.
778
+ - Session lifecycle hooks no longer derive or expose transcript locators on
779
+ `session_end`. Hook consumers get `sessionId`, `sessionKey`, next-session
780
+ ids, and agent context; transcript files are not part of the lifecycle
781
+ contract.
782
+ - Reset hooks no longer derive or expose transcript locators either. The
783
+ `before_reset` payload carries recovered SQLite messages plus the reset
784
+ reason, while session identity stays in hook context.
785
+ - Agent harness reset no longer accepts a transcript locator. Reset dispatch is
786
+ scoped by `sessionId`/`sessionKey` plus reason.
787
+ - Agent extension session types no longer expose `transcriptLocator`; extensions
788
+ should use session context and runtime APIs rather than reaching for a
789
+ file-shaped transcript identity.
790
+ - Plugin compaction hooks no longer expose transcript locators. Hook context
791
+ already carries session identity, and transcript reads must go through SQLite
792
+ scope-aware APIs instead of file-shaped handles.
793
+ - `before_agent_finalize` hooks no longer expose `transcriptPath`, including
794
+ native hook relay payloads. Finalization hooks use session context only.
795
+ - Gateway reset responses no longer synthesize a transcript locator on the
796
+ returned entry. The reset creates SQLite transcript rows, returns the clean
797
+ session entry, and leaves transcript access to scope-aware readers.
798
+ - Embedded run and compaction results no longer surface transcript locators for
799
+ session accounting. Automatic compaction updates only the active `sessionId`,
800
+ compaction counters, and token metadata.
801
+ - Embedded attempt results no longer return `transcriptLocatorUsed`, and
802
+ context-engine `compact()` results no longer return transcript locators.
803
+ Runtime retry loops only accept a successor `sessionId`.
804
+ - Delivery-mirror transcript append results no longer return transcript
805
+ locators. Callers get the appended `messageId`; transcript update signals use
806
+ SQLite scope.
807
+ - Parent-session fork helpers return only the forked `sessionId`. Subagent
808
+ preparation passes the child agent/session scope to engines.
809
+ - CLI runner params and history reseeding no longer accept transcript locators.
810
+ CLI history reads resolve the SQLite transcript scope from `{agentId,
811
+ sessionId}` and session key context.
812
+ - CLI and embedded-runner test fixtures now seed and read SQLite transcript rows
813
+ by session id instead of pretending active sessions are `*.jsonl` files or
814
+ passing a `sqlite-transcript://...` string through runtime params.
815
+ - Session tool-result guard events emit from known session scope even when an
816
+ in-memory manager has no derived locator. Its tests no longer fake active
817
+ `/tmp/*.jsonl` transcript files.
818
+ - BTW and compaction-checkpoint helpers now read and fork transcript rows by
819
+ SQLite scope. Checkpoint metadata now stores session ids and leaf/entry ids
820
+ only; derived locators are no longer written into checkpoint payloads.
821
+ - Gateway transcript-key lookup uses SQLite transcript scope at protocol
822
+ boundaries and no longer realpaths or stats transcript filenames.
823
+ - Automatic compaction transcript rotation writes successor transcript rows
824
+ directly through the SQLite transcript store. Session rows keep only the
825
+ successor session identity, not a durable JSONL path or persisted locator.
826
+ - Embedded context-engine compaction uses SQLite-named transcript rotation
827
+ helpers. The rotation tests no longer construct JSONL successor paths or
828
+ model active sessions as files.
829
+ - Managed outgoing image retention keys its transcript-message cache from
830
+ SQLite transcript stats instead of filesystem stat calls.
831
+ - Runtime session locks and the standalone legacy `.jsonl.lock` doctor
832
+ lane have been removed.
833
+ - The Microsoft Teams runtime barrel and public plugin SDK no longer re-export
834
+ the old file-lock helper; durable plugin state paths are SQLite-backed.
835
+ - Session age/count pruning and explicit session cleanup have been removed.
836
+ Doctor owns legacy import; stale sessions are reset or deleted explicitly.
837
+ - Doctor integrity checks no longer count a legacy JSONL file as a valid active
838
+ transcript for a SQLite session row. Active transcript health is SQLite-only;
839
+ legacy JSONL files are reported as migration/orphan-cleanup inputs.
840
+ - Doctor no longer treats `agents/<agent>/sessions/` as required runtime
841
+ state. It only scans that directory when it already exists, as legacy import
842
+ or orphan-cleanup input.
843
+ - Gateway `sessions.resolve`, session patch/reset/compact paths, subagent
844
+ spawning, fast abort, ACP metadata, heartbeat-isolated sessions, and TUI
845
+ patching no longer migrate or prune legacy session keys as a side effect of
846
+ normal runtime work.
847
+ - CLI command session resolution now returns the owning `agentId` instead of a
848
+ `storePath`, and it no longer copies legacy main-session rows during normal
849
+ `--to` or `--session-id` resolution. Legacy main-row canonicalization belongs
850
+ to doctor only.
851
+ - Runtime subagent depth resolution no longer reads `sessions.json` or JSON5
852
+ session stores. It reads SQLite `session_entries` by agent id, and legacy
853
+ depth/session metadata can only enter through the doctor import path.
854
+ - Auth profile session overrides persist through direct `{agentId, sessionKey}`
855
+ row upserts instead of lazy-loading a file-shaped session-store runtime.
856
+ - Auto-reply verbose gating and session update helpers now read/upsert SQLite
857
+ session rows by session identity and no longer require a legacy store path
858
+ before touching persisted row state.
859
+ - Command-run session metadata helpers now use entry-oriented names and module
860
+ paths; the old `session-store` command helper surface has been removed.
861
+ - Bootstrap header seeding and manual compaction boundary hardening now mutate
862
+ SQLite transcript rows directly. Runtime callers pass session identity, not
863
+ writable `.jsonl` paths.
864
+ - Silent session-rotation replay copies recent user/assistant turns by
865
+ `{agentId, sessionId}` from SQLite transcript rows. It no longer accepts
866
+ source or target transcript locators.
867
+ - Fresh runtime session rows no longer store transcript locators. Callers use
868
+ `{agentId, sessionId}` directly; export/debug commands can choose output file
869
+ names when they materialize rows.
870
+ - Starting a new persisted transcript session now always opens SQLite rows by
871
+ scope. The session manager no longer reuses a previous file-era transcript
872
+ path or locator as the identity for the new session.
873
+ - Persisted transcript sessions use the explicit
874
+ `openTranscriptSessionManagerForSession({agentId, sessionId})` API. The old
875
+ static `SessionManager.create/openForSession/list/forkFromSession` facades are
876
+ gone so tests and runtime code cannot accidentally recreate file-era session
877
+ discovery.
878
+ - Plugin runtime no longer exposes `api.runtime.agent.session.resolveTranscriptLocatorPath`;
879
+ plugin code uses SQLite row helpers and scope values.
880
+ - The public `session-store-runtime` SDK surface now only exports session row
881
+ and transcript row helpers. Raw SQLite database open/path and close/reset
882
+ helpers live in the focused `sqlite-runtime` SDK surface, so plugin tests no
883
+ longer pull the deprecated broad testing barrel for database cleanup.
884
+ - Legacy `.jsonl` trajectory/checkpoint filename classifiers now live in the
885
+ doctor legacy session-file module. Core session validation no longer imports
886
+ file-artifact helpers to decide normal SQLite session ids.
887
+ - Active-memory blocking subagent runs use SQLite transcript rows instead of
888
+ creating temporary or persisted `session.jsonl` files under plugin state. The
889
+ old `transcriptDir` option is removed.
890
+ - One-off slug generation and Crestodian planner runs use SQLite transcript rows
891
+ instead of creating temporary `session.jsonl` files.
892
+ - `llm-task` helper runs and hidden commitment extraction also use SQLite
893
+ transcript rows, so these model-only helper sessions no longer create
894
+ temporary JSON/JSONL transcript files.
895
+ - `TranscriptSessionManager` is only an opened SQLite transcript scope now.
896
+ Runtime code opens it with `openTranscriptSessionManagerForSession({agentId,
897
+ sessionId})`; create, branch, continue, list, and fork flows live in their
898
+ owning SQLite row helpers rather than static manager facades.
899
+ Doctor/import/debug code handles explicit legacy source files outside the
900
+ runtime session manager.
901
+ - The stale `SessionManager.newSession()` and
902
+ `SessionManager.createBranchedSession()` facade methods were removed. New
903
+ sessions and transcript descendants are created by their owning SQLite
904
+ workflow instead of mutating an already-open manager into a different
905
+ persisted session.
906
+ - Parent transcript fork decisions and fork creation no longer accept
907
+ `storePath` or `sessionsDir`; they use `{agentId, sessionId}` SQLite
908
+ transcript scope instead of retained filesystem path metadata.
909
+ - Memory-host no longer exports no-op session-directory transcript
910
+ classification helpers; transcript filtering now derives from SQLite row
911
+ metadata during entry construction.
912
+ - Memory-host and QMD session-export tests use SQLite transcript scopes. Old
913
+ `agents/<agentId>/sessions/*.jsonl` paths stay covered only where a test is
914
+ intentionally proving doctor/import/export compatibility.
915
+ - QA-lab raw session inspection now uses `sessions.list` through the gateway
916
+ instead of reading `agents/qa/sessions/sessions.json`; MSteams feedback
917
+ appends directly to SQLite transcripts without fabricating a JSONL path.
918
+ - Shared inbound channel turns now carry `{agentId, sessionKey}` rather than a
919
+ legacy `storePath`. LINE, WhatsApp, Slack, Discord, Telegram, Matrix, Signal,
920
+ iMessage, BlueBubbles, Feishu, Google Chat, IRC, Nextcloud Talk, Zalo,
921
+ Zalo Personal, QA Channel, Microsoft Teams, Mattermost, Synology Chat, Tlon,
922
+ Twitch, and QQBot recording paths now read updated-at metadata and record
923
+ inbound session rows through SQLite identity.
924
+ - Transcript locator persistence is removed from active session rows.
925
+ `resolveSessionTranscriptTarget` returns `agentId`, `sessionId`, and optional
926
+ topic metadata; doctor is the only code that imports legacy transcript file
927
+ names.
928
+ - Runtime transcript headers start at SQLite version `1`. Old JSONL V1/V2/V3
929
+ shape upgrades live only in doctor import and normalize imported headers to
930
+ the current SQLite transcript version before rows are stored.
931
+ - The database-first guard now bans `SessionManager.listAll` and
932
+ `SessionManager.forkFromSession`; session listing and fork/restore workflows
933
+ must stay on row/scoped SQLite APIs.
934
+ - The guard also bans legacy transcript JSONL parse/active-branch repair helper
935
+ names outside doctor/import code, so runtime cannot grow a second legacy
936
+ transcript migration path.
937
+ - Embedded PI runs reject incoming transcript handles. They use the SQLite
938
+ `{agentId, sessionId}` identity before worker launch and again before the
939
+ attempt touches transcript state. A stale `/tmp/*.jsonl` input cannot select a
940
+ runtime write target.
941
+ - Cache trace, Anthropic payload, raw stream, and diagnostics timeline records
942
+ now write to typed SQLite `diagnostic_events` rows. Gateway stability bundles
943
+ now write to typed SQLite `diagnostic_stability_bundles` rows. The old
944
+ `diagnostics.cacheTrace.filePath`, `OPENCLAW_CACHE_TRACE_FILE`,
945
+ `OPENCLAW_ANTHROPIC_PAYLOAD_LOG_FILE`, and
946
+ `OPENCLAW_DIAGNOSTICS_TIMELINE_PATH` JSONL override paths are removed, and
947
+ normal stability capture no longer writes `logs/stability/*.json` files.
948
+ - Cron persistence now reconciles SQLite `cron_jobs` rows instead of
949
+ deleting/reinserting the whole job table on each save. Plugin target
950
+ writebacks update matching cron rows directly and keep runtime cron state in
951
+ the same state-database transaction.
952
+ - Cron runtime callers now use a stable SQLite cron store key. Legacy
953
+ `cron.store` paths are doctor import inputs only; production gateway, task
954
+ maintenance, status, run-log, and Telegram target writeback paths use
955
+ `resolveCronStoreKey` and no longer path-normalize the key. Cron status now
956
+ reports `storeKey` rather than the old file-shaped `storePath` field.
957
+ - Cron runtime load and scheduling no longer normalize legacy persisted job
958
+ shapes such as `jobId`, `schedule.cron`, numeric `atMs`, string booleans, or
959
+ missing `sessionTarget`. Doctor legacy import owns those repairs before rows
960
+ are inserted into SQLite.
961
+ - ACP spawn no longer resolves or persists transcript JSONL file paths. Spawn
962
+ and thread-bind setup persist the SQLite session row directly and keep the
963
+ session id as the retained transcript identity.
964
+ - ACP session metadata APIs now read/list/upsert SQLite rows by `agentId` and
965
+ no longer expose `storePath` as part of the ACP session entry contract.
966
+ - Session usage accounting and gateway usage aggregation now resolve transcripts
967
+ by `{agentId, sessionId}` only. The cost/usage cache and discovered-session
968
+ summaries no longer synthesize or return transcript locator strings.
969
+ - Gateway chat append, abort-partial persistence, `/sessions.send`, and
970
+ webchat media transcript writes append directly through SQLite transcript
971
+ scope. The gateway transcript-injection helper no longer accepts a
972
+ `transcriptLocator` parameter.
973
+ - SQLite transcript discovery now lists transcript scopes and stats only:
974
+ `{agentId, sessionId, updatedAt, eventCount}`. The dead
975
+ `listSqliteSessionTranscriptLocators` compatibility helper and per-row
976
+ `locator` field are gone.
977
+ - Transcript repair runtime now exposes only
978
+ `repairTranscriptSessionStateIfNeeded({agentId, sessionId})`. The old
979
+ locator-based repair helper is deleted; doctor/debug code reads explicit
980
+ source file paths and never migrates locator strings.
981
+ - ACP replay ledger runtime now stores per-session replay rows in the shared
982
+ SQLite state database instead of `acp/event-ledger.json`; doctor imports and
983
+ removes the legacy file.
984
+ - Gateway transcript reader helpers now live in
985
+ `src/gateway/session-transcript-readers.ts` instead of the old
986
+ `session-utils.fs` module name. The fallback retry history check is named for
987
+ SQLite transcript content instead of the old file-helper surface.
988
+ - Gateway injected-chat and compaction helpers now pass SQLite transcript scope
989
+ through internal helper APIs instead of naming values transcript paths or
990
+ source files.
991
+ - Bootstrap continuation detection now checks SQLite transcript rows through
992
+ `hasCompletedBootstrapTranscriptTurn`; it no longer exposes a file-shaped
993
+ helper name.
994
+ - Embedded-runner tests now use SQLite transcript identity, and opening a new
995
+ transcript manager always requires an explicit `sessionId`.
996
+ - Memory indexing helpers now use SQLite transcript terminology end to end:
997
+ host exports `listSessionTranscriptScopesForAgent` and
998
+ `sessionTranscriptKeyForScope`, targeted sync queues `sessionTranscripts`,
999
+ public session-search hits expose opaque `transcript:<agent>:<session>` paths,
1000
+ and the internal DB source key is `session:<session>` under
1001
+ `source_kind='sessions'` instead of a fake file path.
1002
+ - The generic plugin SDK persistent-dedupe helper no longer exposes file-shaped
1003
+ options. Callers provide SQLite scope keys and durable dedupe rows live in
1004
+ shared plugin state.
1005
+ - Microsoft Teams SSO tokens moved from locked JSON files to SQLite plugin
1006
+ state. Doctor imports `msteams-sso-tokens.json`, rebuilds canonical SSO token
1007
+ keys from payloads, and removes the source file. Delegated OAuth tokens stay
1008
+ on their existing private credential-file boundary.
1009
+ - Matrix sync cache state moved from `bot-storage.json` to SQLite plugin
1010
+ state. Doctor imports legacy raw or wrapped sync payloads and removes the
1011
+ source file. Active Matrix and QA Matrix clients pass a SQLite sync-store root
1012
+ directory, not a fake `sync-store.json` or `bot-storage.json` path.
1013
+ - Matrix legacy crypto migration status moved from
1014
+ `legacy-crypto-migration.json` to SQLite plugin state. Doctor imports the
1015
+ old status file; Matrix SDK IndexedDB snapshots moved from
1016
+ `crypto-idb-snapshot.json` to SQLite plugin blobs. Matrix recovery keys and
1017
+ credentials are SQLite plugin-state rows; their old JSON files are doctor
1018
+ migration inputs only.
1019
+ - Memory Wiki activity logs now use SQLite plugin state instead of
1020
+ `.openclaw-wiki/log.jsonl`. The Memory Wiki migration provider imports old
1021
+ JSONL logs; wiki markdown and user vault content stay file-backed as
1022
+ workspace content.
1023
+ - Memory Wiki no longer creates `.openclaw-wiki/state.json` or the unused
1024
+ `.openclaw-wiki/locks` directory. The migration provider removes those retired
1025
+ plugin metadata files if an older vault still has them.
1026
+ - Crestodian audit entries now use core SQLite plugin state instead of
1027
+ `audit/crestodian.jsonl`. Doctor imports the legacy JSONL audit log and
1028
+ removes it after successful import.
1029
+ - Config write/observe audit entries now use core SQLite plugin state instead
1030
+ of `logs/config-audit.jsonl`. Doctor imports the legacy JSONL audit log and
1031
+ removes it after successful import.
1032
+ - The macOS companion no longer writes app-local `logs/config-audit.jsonl` or
1033
+ `logs/config-health.json` sidecars while editing `openclaw.json`. The config
1034
+ file remains file-backed, recovery snapshots stay next to the config file,
1035
+ and durable config audit/health state belongs to the Gateway SQLite store.
1036
+ - Crestodian rescue pending approvals now use core SQLite plugin state instead
1037
+ of `crestodian/rescue-pending/*.json`. Doctor imports legacy pending approval
1038
+ files and removes them after successful import.
1039
+ - Phone Control temporary arm state now uses SQLite plugin state instead of
1040
+ `plugins/phone-control/armed.json`. Doctor imports the legacy armed-state
1041
+ file into the `phone-control/arm-state` namespace and removes the file.
1042
+ - Doctor no longer repairs JSONL transcripts in place or creates backup JSONL
1043
+ files. It imports the active branch into SQLite and removes the legacy source.
1044
+ - Session-memory hook transcript lookup uses `{agentId, sessionId}` scope-only
1045
+ SQLite reads. Its helper no longer accepts or derives transcript locators,
1046
+ legacy file reads, or file-rewrite options.
1047
+ - Codex app-server conversation bindings now key SQLite plugin state by
1048
+ OpenClaw session key or explicit `{agentId, sessionId}` scope. They must not
1049
+ preserve transcript-path fallback bindings.
1050
+ - Codex app-server mirrored-history reads use the SQLite transcript scope only;
1051
+ they must not recover identity from transcript file paths.
1052
+ - Role-ordering and compaction reset paths no longer unlink old transcript
1053
+ files; reset only rotates the SQLite session row and transcript identity.
1054
+ - Gateway reset and checkpoint responses return clean session rows plus session
1055
+ ids. They no longer synthesize SQLite transcript locators for clients.
1056
+ - Memory-core dreaming no longer prunes session rows by probing for missing
1057
+ JSONL files. Subagent cleanup goes through the session runtime API instead of
1058
+ filesystem existence checks. Its transcript-ingestion tests seed SQLite rows
1059
+ directly instead of creating `agents/<id>/sessions` fixtures or locator
1060
+ placeholders.
1061
+ - Memory transcript indexing may expose `transcript:<agentId>:<sessionId>` as a
1062
+ virtual search-hit path for citation/read helpers. The durable index source is
1063
+ relational (`source_kind='sessions'`, `source_key='session:<sessionId>'`,
1064
+ `session_id=<sessionId>`), so the value is not a runtime transcript locator,
1065
+ not a filesystem path, and must never be passed back into session runtime APIs.
1066
+ - Gateway doctor memory status reads short-term recall and phase-signal counts
1067
+ from SQLite plugin-state rows instead of `memory/.dreams/*.json`; CLI and
1068
+ doctor output now label that storage as a SQLite store, not a path.
1069
+ - Memory-core runtime, CLI status, Gateway doctor methods, and plugin SDK
1070
+ facades no longer audit or archive legacy `.dreams/session-corpus` files.
1071
+ Those files are migration inputs only; doctor imports them into SQLite and
1072
+ deletes the source after verification. Active session-ingestion evidence rows
1073
+ now use the virtual SQLite path `memory/session-ingestion/<day>.txt`; runtime
1074
+ never writes or derives state from `.dreams/session-corpus`.
1075
+ - Memory-core public artifacts expose SQLite host events as the virtual JSON
1076
+ artifact `memory/events/memory-host-events.json`; they no longer reuse the
1077
+ legacy `.dreams/events.jsonl` source path.
1078
+ - Sandbox container/browser registries now use the shared
1079
+ `sandbox_registry_entries` SQLite table with typed session, image, timestamp,
1080
+ backend/config, and browser port columns. Doctor imports legacy monolithic and
1081
+ sharded JSON registry files and removes successful sources. Runtime reads use
1082
+ the typed row columns as source of truth; `entry_json` is only a replay/debug
1083
+ copy.
1084
+ - Commitments now use a typed shared `commitments` table instead of a
1085
+ whole-store JSON blob. Snapshot saves upsert by commitment id and delete only
1086
+ missing rows instead of clearing and reinserting the table. Runtime loads
1087
+ commitments from typed scope, delivery-window, status, attempt, and text
1088
+ columns; `record_json` is only a replay/debug copy. Doctor imports legacy
1089
+ `commitments.json` and removes it after a successful import.
1090
+ - Cron job definitions, schedule state, and run history no longer have runtime
1091
+ JSON writers or readers. Runtime uses `cron_jobs` rows with typed schedule,
1092
+ payload, delivery, failure-alert, session, status, and runtime-state columns plus typed
1093
+ `cron_run_logs` metadata for status, diagnostics summary, delivery status/error,
1094
+ session/run, model, and token totals. `job_json` is only a replay/debug copy; `state_json` keeps nested
1095
+ runtime diagnostics that do not yet have hot query fields, while runtime
1096
+ rehydrates hot state fields from typed columns. Doctor imports
1097
+ legacy `jobs.json`, `jobs-state.json`, and `runs/*.jsonl` files and removes
1098
+ the imported sources. Plugin target writebacks update matching `cron_jobs`
1099
+ rows instead of loading and replacing the whole cron store.
1100
+ - Doctor and Gateway startup translate legacy `notify: true` webhook fallback
1101
+ into explicit SQLite delivery before the scheduler runs. Jobs that already
1102
+ announce to a chat keep that delivery and receive a webhook
1103
+ `completionDestination`; jobs without `cron.webhook` are reported for manual
1104
+ repair.
1105
+ - Outbound and session delivery queues now store queue status, entry kind,
1106
+ session key, channel, target, account id, retry count, last attempt/error,
1107
+ recovery state, and platform-send markers as typed columns in the shared
1108
+ `delivery_queue_entries` table. Runtime recovery reads those hot fields from
1109
+ the typed columns, and retry/recovery mutations update those columns directly
1110
+ without rewriting replay JSON. The full JSON payload remains only as the
1111
+ replay/debug blob for message bodies and other cold replay data.
1112
+ - Managed outgoing image records now use typed shared
1113
+ `managed_outgoing_image_records` rows with media bytes still stored in
1114
+ `media_blobs`. The JSON record remains only as a replay/debug copy.
1115
+ - Discord model-picker preferences, command-deploy hashes, and thread bindings
1116
+ now use shared SQLite plugin state. Their legacy JSON import plans live in the
1117
+ Discord plugin setup/doctor migration surface, not in core migration code.
1118
+ - Plugin legacy import detectors use doctor-named modules such as
1119
+ `doctor-legacy-state.ts` or `doctor-state-imports.ts`; normal channel runtime
1120
+ modules must not import legacy JSON detectors.
1121
+ - BlueBubbles catchup cursors and inbound dedupe markers now use shared SQLite
1122
+ plugin state. Their legacy JSON import plans live in the BlueBubbles plugin
1123
+ setup/doctor migration surface, not in core migration code.
1124
+ - Telegram update offsets, sticker cache rows, sent-message cache rows,
1125
+ topic-name cache rows, and thread bindings now use shared SQLite plugin
1126
+ state. Their legacy JSON import plans live in the Telegram plugin
1127
+ setup/doctor migration surface, not in core migration code.
1128
+ - iMessage catchup cursors, reply short-id mappings, and sent-echo dedupe rows
1129
+ now use shared SQLite plugin state. The old `imessage/catchup/*.json`,
1130
+ `imessage/reply-cache.jsonl`, and `imessage/sent-echoes.jsonl` files are
1131
+ doctor inputs only.
1132
+ - Feishu message dedupe rows now use shared SQLite plugin state instead of
1133
+ `feishu/dedup/*.json` files. Its legacy JSON import plan lives in the Feishu
1134
+ plugin setup/doctor migration surface, not in core migration code.
1135
+ - Microsoft Teams conversations, polls, pending upload buffers, and feedback
1136
+ learnings now use shared SQLite plugin state/blob tables. The pending upload
1137
+ path uses `plugin_blob_entries` so media buffers are stored as SQLite BLOBs
1138
+ instead of base64 JSON. The runtime helper names now use SQLite/state naming
1139
+ rather than `*-fs` file-store naming, and the old `storePath` shim is gone
1140
+ from these stores. Its legacy JSON import plan lives in the Microsoft Teams
1141
+ plugin setup/doctor migration surface.
1142
+ - Zalo hosted outbound media now uses shared SQLite `plugin_blob_entries`
1143
+ instead of `openclaw-zalo-outbound-media` JSON/bin temp sidecars.
1144
+ - Diffs viewer HTML and metadata now use shared SQLite `plugin_blob_entries`
1145
+ instead of `meta.json`/`viewer.html` temp files. Rendered PNG/PDF outputs stay
1146
+ temp materializations because channel delivery still needs a file path.
1147
+ - Canvas managed documents now use shared SQLite `plugin_blob_entries` instead
1148
+ of a default `state/canvas/documents` directory. The Canvas host serves those
1149
+ blobs directly; local files are created only for explicit `host.root`
1150
+ operator content or temporary materialization when a downstream media reader
1151
+ requires a path.
1152
+ - File Transfer audit decisions now use shared SQLite `plugin_state_entries`
1153
+ instead of the unbounded `audit/file-transfer.jsonl` runtime log. Doctor
1154
+ imports the legacy JSONL audit file into plugin state and removes the source
1155
+ after a clean import.
1156
+ - ACPX process leases and gateway instance identity now use shared SQLite plugin
1157
+ state. Doctor imports the legacy `gateway-instance-id` file into plugin state
1158
+ and removes the source.
1159
+ - ACPX generated wrapper scripts and the isolated Codex home are temporary
1160
+ materialization under the OpenClaw temp root, not durable OpenClaw state. The
1161
+ durable ACPX runtime records are the SQLite lease and gateway-instance rows;
1162
+ the old ACPX `stateDir` config surface is removed because no runtime state is
1163
+ written there anymore.
1164
+ - Gateway media attachments now use the shared `media_blobs` SQLite table as
1165
+ the canonical byte store. Local paths returned to channel and sandbox
1166
+ compatibility surfaces are temp materializations of the database row, not the
1167
+ durable media store. Runtime media allowlists no longer include legacy
1168
+ `$OPENCLAW_STATE_DIR/media` or config-dir `media` roots; those directories are
1169
+ doctor import sources only.
1170
+ - Shell completion no longer writes `$OPENCLAW_STATE_DIR/completions/*` cache
1171
+ files. Install, doctor, update, and release smoke paths use generated
1172
+ completion output or profile sourcing instead of durable completion cache
1173
+ files.
1174
+ - Gateway skill-upload staging now uses shared `skill_uploads` rows. Upload
1175
+ metadata, idempotency keys, and archive bytes live in SQLite; the installer
1176
+ only receives a temporary materialized archive path while an install is
1177
+ running.
1178
+ - Subagent inline attachments no longer materialize under workspace
1179
+ `.openclaw/attachments/*`. The spawn path prepares SQLite VFS seed entries,
1180
+ inline runs seed those entries into the per-agent runtime scratch namespace,
1181
+ and disk-backed tools overlay that SQLite scratch for attachment paths. The
1182
+ old subagent-run attachment-dir registry columns and cleanup hooks are gone.
1183
+ - CLI image hydration no longer maintains stable `openclaw-cli-images` cache
1184
+ files. External CLI backends still receive file paths, but those paths are
1185
+ per-run temp materializations with cleanup.
1186
+ - Cache-trace diagnostics, Anthropic payload diagnostics, raw model stream
1187
+ diagnostics, diagnostics timeline events, and Gateway stability bundles now
1188
+ write SQLite rows instead of `logs/*.jsonl` or
1189
+ `logs/stability/*.json` files.
1190
+ Runtime path override flags and env vars have been removed; export/debug
1191
+ commands can materialize files explicitly from database rows.
1192
+ - The macOS companion no longer has a rolling `diagnostics.jsonl` writer. App
1193
+ logs go to unified logging, and durable Gateway diagnostics stay SQLite-backed.
1194
+ - The macOS port-guardian record list now uses typed shared SQLite
1195
+ `macos_port_guardian_records` rows instead of an Application Support JSON file
1196
+ or opaque singleton blob.
1197
+ - Gateway singleton locks now use typed shared SQLite `state_leases` rows under
1198
+ the `gateway_locks` scope instead of temp-dir lock files. Fly and OAuth
1199
+ troubleshooting docs now point at the SQLite lease/auth refresh lock instead
1200
+ of stale file-lock cleanup.
1201
+ - Gateway restart sentinel state now uses typed shared SQLite
1202
+ `gateway_restart_sentinel` rows instead of `restart-sentinel.json`; runtime
1203
+ reads sentinel kind, status, routing, message, continuation, and stats from
1204
+ typed columns. `payload_json` is only a replay/debug copy. Runtime code clears
1205
+ the SQLite row directly and no longer carries file cleanup plumbing.
1206
+ - Gateway restart intent and supervisor handoff state now use typed shared
1207
+ SQLite `gateway_restart_intent` and `gateway_restart_handoff` rows instead of
1208
+ `gateway-restart-intent.json` and
1209
+ `gateway-supervisor-restart-handoff.json` sidecars.
1210
+ - Gateway singleton coordination now uses typed `state_leases` rows under
1211
+ `gateway_locks` instead of writing `gateway.<hash>.lock` files. The lease row
1212
+ owns the lock owner, expiry, heartbeat, and debug payload; SQLite owns the
1213
+ atomic acquire/release boundary. The retired file-lock directory option is
1214
+ gone; tests use the SQLite row identity directly.
1215
+ - The old unreferenced cron usage-report helper that scanned `cron/runs/*.jsonl`
1216
+ files was deleted. Cron run history reports should read the typed
1217
+ `cron_run_logs` SQLite rows.
1218
+ - Main-session restart recovery now discovers candidate agents through the
1219
+ SQLite `agent_databases` registry instead of scanning `agents/*/sessions`
1220
+ directories.
1221
+ - Gemini session-corruption recovery now deletes only the SQLite session row;
1222
+ it no longer needs a legacy `storePath` gate or tries to unlink a derived
1223
+ transcript JSONL path.
1224
+ - Path override handling now treats literal `undefined`/`null` environment
1225
+ values as unset, preventing accidental repo-root `undefined/state/*.sqlite`
1226
+ databases during tests or shell handoffs.
1227
+ - Config health fingerprints now use typed shared SQLite `config_health_entries`
1228
+ rows instead of `logs/config-health.json`, keeping the normal config file as
1229
+ the only non-credential configuration document. The macOS companion keeps only
1230
+ process-local health state and does not recreate the old JSON sidecar.
1231
+ - Auth profile runtime no longer imports or writes credential JSON files. The
1232
+ canonical credential store is SQLite; `auth-profiles.json`, per-agent
1233
+ `auth.json`, and shared `credentials/oauth.json` are doctor migration inputs
1234
+ that are removed after import.
1235
+ - Auth profile save/state tests now assert typed SQLite auth tables directly
1236
+ and only use legacy auth-profile filenames for doctor migration inputs.
1237
+ - `openclaw secrets apply` scrubs the config file, env file, and SQLite
1238
+ auth-profile store only. It no longer carries compatibility logic that edits
1239
+ retired per-agent `auth.json`; doctor owns importing and deleting that file.
1240
+ - Hermes secret migration plans and applies imported API-key profiles directly
1241
+ into the SQLite auth-profile store. It no longer writes or verifies
1242
+ `auth-profiles.json` as an intermediate target.
1243
+ - User-facing auth docs now describe
1244
+ `state/openclaw.sqlite#table/auth_profile_stores/<agentDir>` instead of
1245
+ telling users to inspect or copy `auth-profiles.json`; legacy OAuth/auth JSON
1246
+ names remain documented only as doctor-import inputs.
1247
+ - Core state-path helpers no longer expose the retired `credentials/oauth.json`
1248
+ file. The legacy filename is local to the doctor auth import path.
1249
+ - Install, security, onboarding, model-auth, and SecretRef docs now describe
1250
+ SQLite auth-profile rows and whole-state backup/migration instead of
1251
+ per-agent auth-profile JSON files.
1252
+ - PI model discovery now passes canonical credentials into in-memory
1253
+ `pi-coding-agent` auth storage. It no longer creates, scrubs, or writes
1254
+ per-agent `auth.json` during discovery.
1255
+ - Voice Wake trigger and routing settings now use typed shared SQLite tables
1256
+ instead of `settings/voicewake.json`, `settings/voicewake-routing.json`, or
1257
+ opaque generic rows; doctor imports the legacy JSON files and removes them after a
1258
+ successful migration.
1259
+ - Update-check state now uses a typed shared `update_check_state` row instead of
1260
+ `update-check.json` or an opaque generic blob; doctor imports
1261
+ the legacy JSON file and removes it after a successful migration.
1262
+ - Config health state now uses typed shared `config_health_entries` rows instead
1263
+ of `logs/config-health.json` or an opaque generic blob; doctor
1264
+ imports the legacy JSON file and removes it after a successful migration.
1265
+ - Plugin conversation binding approvals now use typed
1266
+ `plugin_binding_approvals` rows instead of opaque shared SQLite state or
1267
+ `plugin-binding-approvals.json`; the legacy file is a doctor migration input.
1268
+ - Generic current-conversation bindings now store typed
1269
+ `current_conversation_bindings` rows instead of rewriting
1270
+ `bindings/current-conversations.json`; doctor imports the legacy JSON file and
1271
+ removes it after a successful migration.
1272
+ - Memory Wiki imported-source sync ledgers now store one SQLite plugin-state row
1273
+ per vault/source key instead of rewriting `.openclaw-wiki/source-sync.json`;
1274
+ the migration provider imports and removes the legacy JSON ledger.
1275
+ - Memory Wiki ChatGPT import-run records now store one SQLite plugin-state row
1276
+ per vault/run id instead of writing `.openclaw-wiki/import-runs/*.json`.
1277
+ Rollback snapshots remain explicit vault files until import-run snapshot
1278
+ archival is moved into blob storage.
1279
+ - Memory Wiki compiled digests now store SQLite plugin blob rows instead of
1280
+ writing `.openclaw-wiki/cache/agent-digest.json` and
1281
+ `.openclaw-wiki/cache/claims.jsonl`. The migration provider imports old cache
1282
+ files and removes the cache directory when it becomes empty.
1283
+ - ClawHub skill install tracking now stores one SQLite plugin-state row per
1284
+ workspace/skill instead of writing or reading `.clawhub/lock.json` and
1285
+ `.clawhub/origin.json` sidecars at runtime. Runtime code uses tracked-install
1286
+ state objects rather than file-shaped lockfile/origin abstractions. Doctor
1287
+ imports the legacy sidecars from configured agent workspaces and removes them
1288
+ after a clean import.
1289
+ - The installed plugin index now reads and writes the typed shared SQLite
1290
+ `installed_plugin_index` singleton row instead of `plugins/installs.json`; the
1291
+ legacy JSON file is only a doctor migration input and is removed after import.
1292
+ - The legacy `plugins/installs.json` path helper now lives in doctor legacy
1293
+ code. Runtime plugin-index modules expose only SQLite-backed persistence
1294
+ options, not a JSON file path.
1295
+ - Gateway restart sentinel, restart intent, and supervisor handoff state now use
1296
+ typed shared SQLite rows (`gateway_restart_sentinel`,
1297
+ `gateway_restart_intent`, and `gateway_restart_handoff`) instead of generic
1298
+ opaque blobs. Runtime restart code has no file-shaped sentinel/intent/handoff
1299
+ contract.
1300
+ - Matrix sync cache, storage metadata, thread bindings, inbound dedupe markers,
1301
+ startup verification cooldown state, SDK IndexedDB crypto snapshots,
1302
+ credentials, and recovery keys now use shared SQLite plugin state/blob
1303
+ tables. Runtime path structs no longer expose a `storage-meta.json` metadata
1304
+ path; that filename is a legacy migration input only. Their legacy JSON import
1305
+ plan lives in the Matrix plugin setup/doctor migration surface.
1306
+ - Matrix startup no longer scans, reports, or completes legacy Matrix file
1307
+ state. Matrix file detection, legacy crypto snapshot creation, room-key
1308
+ restore migration state, import, and source removal are all doctor-owned.
1309
+ - Matrix runtime migration barrels were removed. Legacy state/crypto detection
1310
+ and mutation helpers are imported by Matrix doctor directly instead of being
1311
+ part of runtime API surface.
1312
+ - Matrix migration snapshot reuse markers now live in SQLite plugin state
1313
+ instead of `matrix/migration-snapshot.json`; doctor can still reuse the same
1314
+ verified pre-migration archive without writing a sidecar state file.
1315
+ - Nostr bus cursors and profile publish state now use shared SQLite plugin
1316
+ state. Their legacy JSON import plan lives in the Nostr plugin setup/doctor
1317
+ migration surface.
1318
+ - Active Memory session toggles now use shared SQLite plugin state instead of
1319
+ `session-toggles.json`; toggling memory back on deletes the row instead of
1320
+ rewriting a JSON object.
1321
+ - Skill Workshop proposals and review counters now use shared SQLite plugin
1322
+ state instead of per-workspace `skill-workshop/<workspace>.json` stores. Each
1323
+ proposal is a separate row under `skill-workshop/proposals`, and the review
1324
+ counter is a separate row under `skill-workshop/reviews`.
1325
+ - Skill Workshop reviewer subagent runs now use the runtime session transcript
1326
+ resolver instead of creating `skill-workshop/<sessionId>.json` sidecar session
1327
+ paths.
1328
+ - ACPX process leases now use shared SQLite plugin state under
1329
+ `acpx/process-leases` instead of a whole-file `process-leases.json` registry.
1330
+ Each lease is stored as its own row, preserving startup stale-process reaping
1331
+ without a runtime JSON rewrite path.
1332
+ - ACPX wrapper scripts and the isolated Codex home are generated in the
1333
+ OpenClaw temp root. They are recreated as needed and are not backup or
1334
+ migration inputs.
1335
+ - Subagent run registry persistence uses typed shared `subagent_runs` rows. The
1336
+ old `subagents/runs.json` path is now only a doctor migration input, and
1337
+ runtime helper names no longer describe the state layer as disk-backed.
1338
+ Runtime tests no longer create invalid or empty `runs.json` fixtures to prove
1339
+ registry behavior; they seed/read SQLite rows directly.
1340
+ - Backup stages the state directory before archiving, copies non-database files,
1341
+ snapshots `*.sqlite` databases with `VACUUM INTO`, omits live WAL/SHM
1342
+ sidecars, records snapshot metadata in the archive manifest, and records
1343
+ completed backup runs in SQLite with the archive manifest. `openclaw backup
1344
+ create` validates the written archive by default; `--no-verify` is the
1345
+ explicit fast path.
1346
+ - `openclaw backup restore` validates the archive before extraction, reuses the
1347
+ verifier's normalized manifest, and restores verified manifest assets to their
1348
+ recorded source paths. It requires `--yes` for writes and supports `--dry-run`
1349
+ for a restore plan.
1350
+ - The old backup volatile-path filter is deleted. Backup no longer needs a
1351
+ live-tar skip list for legacy session or cron JSON/JSONL files because SQLite
1352
+ snapshots are staged before archive creation.
1353
+ - Plain setup and onboarding workspace preparation no longer create
1354
+ `agents/<agentId>/sessions/` directories. They create config/workspace only;
1355
+ SQLite session rows and transcript rows are created on demand in the
1356
+ per-agent database.
1357
+ - Security permission repair now targets the global and per-agent SQLite
1358
+ databases plus WAL/SHM sidecars instead of `sessions.json` and transcript
1359
+ JSONL files.
1360
+ - Sandbox registry runtime names now describe SQLite registry kinds directly
1361
+ instead of carrying legacy JSON registry terminology through the active store.
1362
+ - `openclaw reset --scope config+creds+sessions` removes per-agent
1363
+ `openclaw-agent.sqlite` databases plus WAL/SHM sidecars, not only legacy
1364
+ `sessions/` directories.
1365
+ - Gateway aggregate session helpers now use entry-oriented names:
1366
+ `loadCombinedSessionEntriesForGateway` returns `{ databasePath, entries }`.
1367
+ The old combined-store naming has been removed from runtime callers.
1368
+ - Docker MCP channel seeding now writes the main session row and transcript
1369
+ events into the per-agent SQLite database instead of creating
1370
+ `sessions.json` and a JSONL transcript.
1371
+ - The bundled session-memory hook now resolves previous-session context from
1372
+ SQLite by `{agentId, sessionId}`. It no longer scans, stores, or synthesizes
1373
+ transcript paths or `workspace/sessions` directories.
1374
+ - The bundled command-logger hook now writes command audit rows to the shared
1375
+ SQLite `command_log_entries` table instead of appending
1376
+ `logs/commands.log`.
1377
+ - Channel pairing allowlists now expose only SQLite-backed read/write helpers at
1378
+ runtime and in the plugin SDK. The old `*-allowFrom.json` path resolver and
1379
+ file reader live only under doctor legacy import code.
1380
+ - `migration_runs` records legacy-state migration executions with status,
1381
+ timestamps, and JSON reports.
1382
+ - `migration_sources` records each imported legacy file source with hash, size,
1383
+ record count, target table, run id, status, and source-removal state.
1384
+ - `backup_runs` records backup archive paths, status, and JSON manifests.
1385
+ - The global schema does not keep an unused `agents` registry table. Agent
1386
+ database discovery is the canonical `agent_databases` registry until runtime
1387
+ has a real agent-record owner.
1388
+ - Generated model catalog config is stored in typed global SQLite
1389
+ `agent_model_catalogs` rows keyed by agent directory. Runtime callers use
1390
+ `ensureOpenClawModelCatalog`; there is no `models.json` compatibility API in
1391
+ runtime code. The implementation writes SQLite and the embedded PI registry is
1392
+ hydrated from that stored payload without creating a `models.json` file.
1393
+ - QMD session transcript markdown export and `memory.qmd.sessions` config were
1394
+ removed. There is no QMD transcript collection, no `qmd/sessions*` runtime
1395
+ path, and no file-backed session memory bridge.
1396
+ - Memory-core runtime imports SQLite transcript indexing helpers from
1397
+ `openclaw/plugin-sdk/memory-core-host-engine-session-transcripts`, not the
1398
+ QMD SDK subpath. The QMD subpath keeps a compatibility re-export only for
1399
+ external callers until a major SDK cleanup can remove it.
1400
+ - QMD's own `index.sqlite` is now a temp runtime materialization backed by the
1401
+ main SQLite `plugin_blob_entries` table. Runtime no longer creates a durable
1402
+ `~/.openclaw/agents/<agentId>/qmd` sidecar.
1403
+ - The optional `memory-lancedb` plugin no longer creates
1404
+ `~/.openclaw/memory/lancedb` as an implicit OpenClaw-managed store. It is an
1405
+ external LanceDB backend and stays disabled until the operator configures an
1406
+ explicit `dbPath`.
1407
+ - `check:database-first-legacy-stores` fails new runtime source that pairs
1408
+ legacy store names with write-style filesystem APIs. It also fails runtime
1409
+ source that reintroduces transcript bridge contracts such as
1410
+ `transcriptLocator`, `sqlite-transcript://...`, `sessionFile`, or
1411
+ `storePath`, and scans tests for those bridge-contract names too. It also
1412
+ bans `SessionManager.open(...)` and the old static SessionManager facades so
1413
+ runtime and tests cannot silently re-create a file-backed session opener or
1414
+ file-era session discovery. It also bans the old session JSONL downloader
1415
+ hook/class from export UI. It also bans sidecar-shaped plugin-state/task
1416
+ SQLite helper names; tests should assert `databasePath` and the shared
1417
+ `state/openclaw.sqlite` location instead of pretending those features own
1418
+ separate SQLite files. It also bans the old generic memory index SQL table
1419
+ names (`meta`, `files`, `chunks`, `chunks_vec`,
1420
+ `chunks_fts`, `embedding_cache`) in runtime source so the agent database keeps
1421
+ its explicit `memory_index_*` schema. It also bans embedding TEXT schemas and
1422
+ embedding JSON-array writes so vectors stay compact SQLite BLOBs. Migration,
1423
+ doctor, import, and explicit non-session export code remain allowed. The
1424
+ guard now also covers runtime `cache/*.json` stores, generic
1425
+ `thread-bindings.json` sidecars, cron state/run-log JSON, config health JSON,
1426
+ restart and lock sidecars, Voice Wake settings, plugin binding approvals,
1427
+ installed plugin index JSON, File Transfer audit JSONL, Memory Wiki activity
1428
+ logs, the old bundled `command-logger` text log, and pi-mono raw-stream JSONL
1429
+ diagnostics knobs. It also bans old root-level doctor legacy module names so
1430
+ compatibility code stays under `src/commands/doctor/`. Android debug handlers
1431
+ also use logcat/in-memory output instead of staging `camera_debug.log` or
1432
+ `debug_logs.txt` cache files.
1433
+
1434
+ ## Target Schema Shape
1435
+
1436
+ Keep schemas explicit. Host-owned runtime state uses typed tables. Plugin-owned
1437
+ opaque state uses `plugin_state_entries` / `plugin_blob_entries`; there is no
1438
+ generic host `kv` table.
1439
+
1440
+ Global database:
1441
+
1442
+ ```text
1443
+ state_leases(scope, lease_key, owner, expires_at, heartbeat_at, payload_json, created_at, updated_at)
1444
+ exec_approvals_config(config_key, raw_json, socket_path, has_socket_token, default_security, default_ask, default_ask_fallback, auto_allow_skills, agent_count, allowlist_count, updated_at_ms)
1445
+ schema_meta(meta_key, role, schema_version, agent_id, app_version, created_at, updated_at)
1446
+ agent_databases(agent_id, path, schema_version, last_seen_at, size_bytes)
1447
+ task_runs(...)
1448
+ task_delivery_state(...)
1449
+ flow_runs(...)
1450
+ subagent_runs(run_id, child_session_key, requester_session_key, controller_session_key, created_at, ended_at, cleanup_handled, payload_json)
1451
+ current_conversation_bindings(binding_key, binding_id, target_agent_id, target_session_id, target_session_key, channel, account_id, conversation_kind, parent_conversation_id, conversation_id, target_kind, status, bound_at, expires_at, metadata_json, updated_at)
1452
+ plugin_binding_approvals(plugin_root, channel, account_id, plugin_id, plugin_name, approved_at)
1453
+ tui_last_sessions(scope_key, session_key, updated_at)
1454
+ plugin_state_entries(plugin_id, namespace, entry_key, value_json, created_at, expires_at)
1455
+ plugin_blob_entries(plugin_id, namespace, entry_key, metadata_json, blob, created_at, expires_at)
1456
+ media_blobs(subdir, id, content_type, size_bytes, blob, created_at, updated_at)
1457
+ skill_uploads(upload_id, kind, slug, force, size_bytes, sha256, actual_sha256, received_bytes, archive_blob, created_at, expires_at, committed, committed_at, idempotency_key_hash)
1458
+ web_push_subscriptions(endpoint_hash, subscription_id, endpoint, p256dh, auth, created_at_ms, updated_at_ms)
1459
+ web_push_vapid_keys(key_id, public_key, private_key, subject, updated_at_ms)
1460
+ apns_registrations(node_id, transport, token, relay_handle, send_grant, installation_id, topic, environment, distribution, token_debug_suffix, updated_at_ms)
1461
+ node_host_config(config_key, version, node_id, token, display_name, gateway_host, gateway_port, gateway_tls, gateway_tls_fingerprint, updated_at_ms)
1462
+ device_identities(identity_key, device_id, public_key_pem, private_key_pem, created_at_ms, updated_at_ms)
1463
+ device_auth_tokens(device_id, role, token, scopes_json, updated_at_ms)
1464
+ macos_port_guardian_records(pid, port, command, mode, timestamp)
1465
+ workspace_setup_state(workspace_key, workspace_path, version, bootstrap_seeded_at, setup_completed_at, updated_at)
1466
+ native_hook_relay_bridges(relay_id, pid, hostname, port, token, expires_at_ms, updated_at_ms)
1467
+ model_capability_cache(provider_id, model_id, name, input_text, input_image, reasoning, supports_tools, context_window, max_tokens, cost_input, cost_output, cost_cache_read, cost_cache_write, updated_at_ms)
1468
+ agent_model_catalogs(catalog_key, agent_dir, raw_json, updated_at)
1469
+ managed_outgoing_image_records(attachment_id, session_key, message_id, created_at, updated_at, retention_class, alt, original_media_id, original_media_subdir, original_content_type, original_width, original_height, original_size_bytes, original_filename, record_json)
1470
+ gateway_restart_sentinel(sentinel_key, version, kind, status, ts, session_key, thread_id, delivery_channel, delivery_to, delivery_account_id, message, continuation_json, doctor_hint, stats_json, payload_json, updated_at_ms)
1471
+ channel_pairing_requests(channel_key, account_id, request_id, code, created_at, last_seen_at, meta_json)
1472
+ channel_pairing_allow_entries(channel_key, account_id, entry, sort_order, updated_at)
1473
+ voicewake_triggers(config_key, position, trigger, updated_at_ms)
1474
+ voicewake_routing_config(config_key, version, default_target_mode, default_target_agent_id, default_target_session_key, updated_at_ms)
1475
+ voicewake_routing_routes(config_key, position, trigger, target_mode, target_agent_id, target_session_key, updated_at_ms)
1476
+ update_check_state(state_key, last_checked_at, last_notified_version, last_notified_tag, last_available_version, last_available_tag, auto_install_id, auto_first_seen_version, auto_first_seen_tag, auto_first_seen_at, auto_last_attempt_version, auto_last_attempt_at, auto_last_success_version, auto_last_success_at, updated_at_ms)
1477
+ config_health_entries(config_path, last_known_good_json, last_promoted_good_json, last_observed_suspicious_signature, updated_at_ms)
1478
+ sandbox_registry_entries(registry_kind, container_name, session_key, backend_id, runtime_label, image, created_at_ms, last_used_at_ms, config_label_kind, config_hash, cdp_port, no_vnc_port, entry_json, updated_at)
1479
+ cron_run_logs(store_key, job_id, seq, ts, status, error, summary, diagnostics_summary, delivery_status, delivery_error, delivered, session_id, session_key, run_id, run_at_ms, duration_ms, next_run_at_ms, model, provider, total_tokens, entry_json, created_at)
1480
+ cron_jobs(store_key, job_id, name, description, enabled, delete_after_run, created_at_ms, agent_id, session_key, schedule_kind, schedule_expr, schedule_tz, every_ms, anchor_ms, at, stagger_ms, session_target, wake_mode, payload_kind, payload_message, payload_model, payload_fallbacks_json, payload_thinking, payload_timeout_seconds, payload_allow_unsafe_external_content, payload_external_content_source_json, payload_light_context, payload_tools_allow_json, delivery_mode, delivery_channel, delivery_to, delivery_thread_id, delivery_account_id, delivery_best_effort, failure_delivery_mode, failure_delivery_channel, failure_delivery_to, failure_delivery_account_id, failure_alert_disabled, failure_alert_after, failure_alert_channel, failure_alert_to, failure_alert_cooldown_ms, failure_alert_include_skipped, failure_alert_mode, failure_alert_account_id, next_run_at_ms, running_at_ms, last_run_at_ms, last_run_status, last_error, last_duration_ms, consecutive_errors, consecutive_skipped, schedule_error_count, last_delivery_status, last_delivery_error, last_delivered, last_failure_alert_at_ms, job_json, state_json, runtime_updated_at_ms, schedule_identity, sort_order, updated_at)
1481
+ delivery_queue_entries(queue_name, id, status, entry_kind, session_key, channel, target, account_id, retry_count, last_attempt_at, last_error, recovery_state, platform_send_started_at, entry_json, enqueued_at, updated_at, failed_at)
1482
+ commitments(id, agent_id, session_key, channel, account_id, recipient_id, thread_id, sender_id, kind, sensitivity, source, status, reason, suggested_text, dedupe_key, confidence, due_earliest_ms, due_latest_ms, due_timezone, source_message_id, source_run_id, created_at_ms, updated_at_ms, attempts, last_attempt_at_ms, sent_at_ms, dismissed_at_ms, snoozed_until_ms, expired_at_ms, record_json)
1483
+ migration_runs(id, started_at, finished_at, status, report_json)
1484
+ migration_sources(source_key, migration_kind, source_path, target_table, source_sha256, source_size_bytes, source_record_count, last_run_id, status, imported_at, removed_source, report_json)
1485
+ backup_runs(id, created_at, archive_path, status, manifest_json)
1486
+ ```
1487
+
1488
+ Agent database:
1489
+
1490
+ ```text
1491
+ schema_meta(meta_key, role, schema_version, agent_id, app_version, created_at, updated_at)
1492
+ sessions(session_id, session_key, session_scope, created_at, updated_at, started_at, ended_at, status, chat_type, channel, account_id, primary_conversation_id, model_provider, model, agent_harness_id, parent_session_key, spawned_by, display_name)
1493
+ conversations(conversation_id, channel, account_id, kind, peer_id, parent_conversation_id, thread_id, native_channel_id, native_direct_user_id, label, metadata_json, created_at, updated_at)
1494
+ session_conversations(session_id, conversation_id, role, first_seen_at, last_seen_at)
1495
+ session_routes(session_key, session_id, updated_at)
1496
+ session_entries(session_id, session_key, entry_json, updated_at)
1497
+ transcript_events(session_id, seq, event_json, created_at)
1498
+ transcript_event_identities(session_id, event_id, seq, event_type, has_parent, parent_id, message_idempotency_key, created_at)
1499
+ transcript_snapshots(session_id, snapshot_id, reason, event_count, created_at, metadata_json)
1500
+ vfs_entries(namespace, path, kind, content_blob, metadata_json, updated_at)
1501
+ tool_artifacts(run_id, artifact_id, kind, metadata_json, blob, created_at)
1502
+ run_artifacts(run_id, path, kind, metadata_json, blob, created_at)
1503
+ trajectory_runtime_events(session_id, run_id, seq, event_json, created_at)
1504
+ memory_index_meta(meta_key, schema_version, provider, model, provider_key, sources_json, scope_hash, chunk_tokens, chunk_overlap, vector_dims, fts_tokenizer, config_hash, updated_at)
1505
+ memory_index_sources(source_kind, source_key, path, session_id, hash, mtime, size)
1506
+ memory_index_chunks(id, source_kind, source_key, path, session_id, start_line, end_line, hash, model, text, embedding, embedding_dims, updated_at)
1507
+ memory_embedding_cache(provider, model, provider_key, hash, embedding, dims, updated_at)
1508
+ cache_entries(scope, key, value_json, blob, expires_at, updated_at)
1509
+ ```
1510
+
1511
+ Future search can add FTS tables without changing the canonical event tables:
1512
+
1513
+ ```text
1514
+ transcript_events_fts(session_id, seq, text)
1515
+ vfs_entries_fts(namespace, path, text)
1516
+ ```
1517
+
1518
+ Large values should use `blob` columns, not JSON string encoding. Keep
1519
+ `value_json` for small structured data that must remain inspectable with plain
1520
+ SQLite tooling.
1521
+
1522
+ `agent_databases` is the canonical registry for this branch. Do not add an
1523
+ `agents` table until a real agent-record owner exists; agent config remains in
1524
+ `openclaw.json`.
1525
+
1526
+ ## Doctor Migration Shape
1527
+
1528
+ Doctor should call one explicit migration step that is reportable and safe to
1529
+ rerun:
1530
+
1531
+ ```bash
1532
+ openclaw doctor --fix
1533
+ ```
1534
+
1535
+ `openclaw doctor --fix` invokes the state migration implementation after
1536
+ ordinary config preflight and creates a verified backup before import. Runtime
1537
+ startup and `openclaw migrate` must not import legacy OpenClaw state files.
1538
+
1539
+ Migration properties:
1540
+
1541
+ - One migration pass discovers all legacy file sources and produces a plan
1542
+ before mutating anything.
1543
+ - Doctor creates a verified pre-migration backup archive before importing
1544
+ legacy files.
1545
+ - Imports are idempotent and keyed by source path, mtime, size, hash, and target
1546
+ table.
1547
+ - Successful source files are removed or archived after the target database has
1548
+ committed.
1549
+ - Failed imports leave the source untouched and record a warning in
1550
+ `migration_runs`.
1551
+ - Runtime code reads SQLite only after the migration exists.
1552
+ - No downgrade/export-to-runtime-files path is required.
1553
+
1554
+ ## Migration Inventory
1555
+
1556
+ Move these into the global database:
1557
+
1558
+ - Task registry runtime writes now use the shared database; the unshipped
1559
+ `tasks/runs.sqlite` sidecar importer is deleted. Snapshot saves upsert by task
1560
+ id and delete only missing task/delivery rows.
1561
+ - Task Flow runtime writes now use the shared database; the unshipped
1562
+ `tasks/flows/registry.sqlite` sidecar importer is deleted. Snapshot saves
1563
+ upsert by flow id and delete only missing flow rows.
1564
+ - Plugin state runtime writes now use the shared database; the unshipped
1565
+ `plugin-state/state.sqlite` sidecar importer is deleted.
1566
+ - Builtin memory search no longer defaults to `memory/<agentId>.sqlite`; its
1567
+ index tables live in the owning agent database, and the explicit
1568
+ `memorySearch.store.path` sidecar opt-in has been retired to doctor config
1569
+ migration.
1570
+ - Builtin memory reindex resets only memory-owned tables in the agent database.
1571
+ It must not replace the whole SQLite file, because the same database owns
1572
+ sessions, transcripts, VFS rows, artifacts, and runtime caches.
1573
+ - Sandbox container/browser registries from monolithic and sharded JSON. Runtime
1574
+ writes now use the shared database; legacy JSON import remains.
1575
+ - Cron job definitions, schedule state, and run history now use shared SQLite;
1576
+ doctor imports/removes legacy `jobs.json`, `jobs-state.json`, and
1577
+ `cron/runs/*.jsonl` files
1578
+ - Device identity/auth, push, update check, commitments, OpenRouter model
1579
+ cache, installed plugin index, and app-server bindings
1580
+ - Device/node pairing and bootstrap records now use typed SQLite tables
1581
+ - Device-pair notification subscribers and delivered-request markers now use the
1582
+ shared SQLite plugin-state table instead of `device-pair-notify.json`.
1583
+ - Voice-call call records now use the shared SQLite plugin-state table under the
1584
+ `voice-call` / `calls` namespace instead of `calls.jsonl`; the plugin CLI
1585
+ tails and summarizes SQLite-backed call history.
1586
+ - QQBot gateway sessions, known-user records, and ref-index quote cache now use
1587
+ SQLite plugin state under `qqbot` namespaces (`sessions`, `known-users`,
1588
+ `ref-index`) instead of `session-*.json`, `known-users.json`, and
1589
+ `ref-index.jsonl`; the QQBot doctor/setup migration imports and removes the
1590
+ legacy files.
1591
+ - Discord model-picker preferences, command-deploy hashes, and thread bindings
1592
+ now use SQLite plugin state under `discord` namespaces
1593
+ (`model-picker-preferences`, `command-deploy-hashes`, `thread-bindings`)
1594
+ instead of `model-picker-preferences.json`, `command-deploy-cache.json`, and
1595
+ `thread-bindings.json`; the Discord doctor/setup migration imports and
1596
+ removes the legacy files.
1597
+ - BlueBubbles catchup cursors and inbound dedupe markers now use SQLite plugin
1598
+ state under `bluebubbles` namespaces (`catchup-cursors`, `inbound-dedupe`)
1599
+ instead of `bluebubbles/catchup/*.json` and
1600
+ `bluebubbles/inbound-dedupe/*.json`; the BlueBubbles doctor/setup migration
1601
+ imports and removes the legacy files.
1602
+ - Telegram update offsets, sticker cache entries, reply-chain message cache
1603
+ entries, sent-message cache entries, topic-name cache entries, and thread
1604
+ bindings now use SQLite plugin state under `telegram` namespaces
1605
+ (`update-offsets`, `sticker-cache`, `message-cache`, `sent-messages`,
1606
+ `topic-names`, `thread-bindings`) instead of `update-offset-*.json`,
1607
+ `sticker-cache.json`, `*.telegram-messages.json`,
1608
+ `*.telegram-sent-messages.json`, `*.telegram-topic-names.json`, and
1609
+ `thread-bindings-*.json`; the Telegram doctor/setup migration imports and
1610
+ removes the legacy files.
1611
+ - iMessage catchup cursors, reply short-id mappings, and sent-echo dedupe rows
1612
+ now use SQLite plugin state under `imessage` namespaces (`catchup-cursors`,
1613
+ `reply-cache`, `sent-echoes`) instead of `imessage/catchup/*.json`,
1614
+ `imessage/reply-cache.jsonl`, and `imessage/sent-echoes.jsonl`; the iMessage
1615
+ doctor/setup migration imports and removes the legacy files.
1616
+ - Microsoft Teams conversations, polls, SSO tokens, and feedback learnings now
1617
+ use SQLite plugin state namespaces (`conversations`, `polls`, `sso-tokens`,
1618
+ `feedback-learnings`) instead of `msteams-conversations.json`,
1619
+ `msteams-polls.json`, `msteams-sso-tokens.json`, and `*.learnings.json`; the
1620
+ Microsoft Teams doctor/setup migration imports and archives the legacy files.
1621
+ Pending uploads are a short-lived SQLite cache and old JSON cache files are
1622
+ not migrated.
1623
+ - Matrix sync cache, storage metadata, thread bindings, inbound dedupe markers,
1624
+ startup verification cooldown state, credentials, recovery keys, and SDK
1625
+ IndexedDB crypto snapshots now use SQLite plugin state/blob namespaces under
1626
+ `matrix` (`sync-store`, `storage-meta`, `thread-bindings`, `inbound-dedupe`,
1627
+ `startup-verification`, `credentials`, `recovery-key`, `idb-snapshots`)
1628
+ instead of `bot-storage.json`, `storage-meta.json`, `thread-bindings.json`,
1629
+ `inbound-dedupe.json`, `startup-verification.json`, `credentials.json`,
1630
+ `recovery-key.json`, and `crypto-idb-snapshot.json`; the Matrix doctor/setup
1631
+ migration imports and removes those legacy files from account-scoped Matrix
1632
+ storage roots.
1633
+ - Nostr bus cursors and profile publish state now use SQLite plugin state under
1634
+ `nostr` namespaces (`bus-state`, `profile-state`) instead of
1635
+ `bus-state-*.json` and `profile-state-*.json`; the Nostr doctor/setup
1636
+ migration imports and removes the legacy files.
1637
+ - Active Memory session toggles now use SQLite plugin state under
1638
+ `active-memory/session-toggles` instead of `session-toggles.json`.
1639
+ - Skill Workshop proposal queues and review counters now use SQLite plugin state
1640
+ under `skill-workshop/proposals` and `skill-workshop/reviews` instead of
1641
+ per-workspace `skill-workshop/<workspace>.json` files.
1642
+ - Outbound delivery and session delivery queues now share the global SQLite
1643
+ `delivery_queue_entries` table under separate queue names
1644
+ (`outbound-delivery`, `session-delivery`) instead of durable
1645
+ `delivery-queue/*.json`, `delivery-queue/failed/*.json`, and
1646
+ `session-delivery-queue/*.json` files. The doctor legacy-state step imports
1647
+ pending and failed rows, removes stale delivered markers, and deletes the old
1648
+ JSON files after import. Hot routing and retry fields are typed columns; the
1649
+ JSON payload is retained only for replay/debug.
1650
+ - ACPX process leases now use SQLite plugin state under `acpx/process-leases`
1651
+ instead of `process-leases.json`.
1652
+ - Backup and migration run metadata
1653
+
1654
+ Move these into agent databases:
1655
+
1656
+ - Agent session roots and compatibility-shaped session-entry payloads. Done for
1657
+ runtime writes: hot session metadata is queryable in `sessions`, while the
1658
+ legacy-shaped full `SessionEntry` payload remains in `session_entries`.
1659
+ - Agent transcript events. Done for runtime writes.
1660
+ - Compaction checkpoints and transcript snapshots. Done for runtime writes:
1661
+ checkpoint transcript copies are SQLite transcript rows and checkpoint
1662
+ metadata is recorded in `transcript_snapshots`. Gateway checkpoint helpers
1663
+ now name these values as transcript snapshots rather than source files.
1664
+ - Agent VFS scratch/workspace namespaces. Done for runtime VFS writes.
1665
+ - Subagent attachment payloads. Done for runtime writes: they are SQLite VFS
1666
+ seed entries and never durable workspace files.
1667
+ - Tool artifacts. Done for runtime writes.
1668
+ - Run artifacts. Done for worker runtime writes through the per-agent
1669
+ `run_artifacts` table.
1670
+ - Agent-local runtime caches. Done for worker runtime scoped cache writes through
1671
+ the per-agent `cache_entries` table. Gateway-wide model caches stay in the
1672
+ global database unless they become agent-specific.
1673
+ - ACP parent stream logs. Done for runtime writes.
1674
+ - ACP replay ledger sessions. Done for runtime writes via
1675
+ `acp_replay_sessions` and `acp_replay_events`; legacy `acp/event-ledger.json`
1676
+ remains only as doctor input.
1677
+ - ACP session metadata. Done for runtime writes via `acp_sessions`; legacy
1678
+ `entry.acp` blocks in `sessions.json` are doctor migration input only.
1679
+ - Trajectory sidecars when they are not explicit export files. Done for runtime
1680
+ writes: trajectory capture writes agent-database `trajectory_runtime_events`
1681
+ rows and mirrors run-scoped artifacts into SQLite. Legacy sidecars are doctor
1682
+ import inputs only; export can materialize fresh JSONL support-bundle outputs
1683
+ but does not read or migrate old trajectory/transcript sidecars at runtime.
1684
+ Runtime trajectory capture exposes SQLite scope; JSONL path helpers are
1685
+ isolated to export/debug support and are not re-exported from the runtime module.
1686
+ Embedded-runner trajectory metadata records `{agentId, sessionId, sessionKey}`
1687
+ identity instead of persisting a transcript locator.
1688
+
1689
+ Keep these file-backed for now:
1690
+
1691
+ - `openclaw.json`
1692
+ - provider or CLI credential files
1693
+ - plugin/package manifests
1694
+ - user workspaces and Git repositories when disk mode is selected
1695
+ - logs intended for operator tailing, unless a specific log surface is moved
1696
+
1697
+ ## Migration Plan
1698
+
1699
+ ### Phase 0: Freeze The Boundary
1700
+
1701
+ Make the durable-state boundary explicit before moving more rows:
1702
+
1703
+ - Add a `migration_runs` table to the global database.
1704
+ Done for legacy-state migration execution reports.
1705
+ - Add a single doctor-owned state migration service for file-to-database import.
1706
+ Done: `openclaw doctor --fix` uses the legacy-state migration implementation.
1707
+ - Make `plan` read-only and make `apply` create a backup, import, verify, and
1708
+ then delete or quarantine old files.
1709
+ Done: doctor creates a verified pre-migration backup, passes the backup path
1710
+ into `migration_runs`, and reuses the importer/removal paths.
1711
+ - Add static bans so new runtime code cannot write legacy state files while
1712
+ migration code and tests can still seed/read them.
1713
+ Done for the currently migrated legacy stores; the guard also scans nested
1714
+ tests for forbidden runtime transcript locator contracts.
1715
+
1716
+ ### Phase 1: Finish The Global Control Plane
1717
+
1718
+ Keep shared coordination state in `state/openclaw.sqlite`:
1719
+
1720
+ - Agents and agent database registry
1721
+ - Task and Task Flow ledgers
1722
+ - Plugin state
1723
+ - Sandbox container/browser registry
1724
+ - Cron/scheduler run history
1725
+ - Pairing, device, push, update-check, TUI, OpenRouter/model caches, and other
1726
+ small gateway-scoped runtime state
1727
+ - Backup and migration metadata
1728
+ - Gateway media attachment bytes. Done for runtime writes; direct file paths
1729
+ are temp materializations for compatibility with channel senders and sandbox
1730
+ staging. Runtime allowlists accept SQLite materialization paths, not legacy
1731
+ state/config media roots. Doctor imports legacy media files into
1732
+ `media_blobs` and removes the source files after successful row writes.
1733
+ - Debug proxy capture sessions, events, and payload blobs. Done: captures live
1734
+ in the shared state DB and open through the shared state DB bootstrap, schema,
1735
+ WAL, and busy-timeout settings. There is no debug proxy runtime sidecar DB
1736
+ override, blob directory, or proxy-capture-only generated schema/codegen
1737
+ target.
1738
+
1739
+ This phase also deletes duplicate sidecar openers, permission helpers, WAL
1740
+ setup, filesystem pruning, and compatibility writers from those subsystems.
1741
+
1742
+ ### Phase 2: Introduce Per-Agent Databases
1743
+
1744
+ Create one database per agent and register it from the global DB:
1745
+
1746
+ ```text
1747
+ ~/.openclaw/state/openclaw.sqlite
1748
+ ~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite
1749
+ ```
1750
+
1751
+ The global `agent_databases` row stores the path, schema version, last-seen
1752
+ timestamp, and basic size/integrity metadata. Runtime code asks the registry for
1753
+ the agent DB instead of deriving file paths directly.
1754
+
1755
+ The agent DB owns:
1756
+
1757
+ - `sessions` as the canonical session root, with `session_entries` as the
1758
+ compatibility-shaped payload table attached to that root, and
1759
+ `session_routes` as the unique active `session_key` lookup
1760
+ - `conversations` and `session_conversations` as the normalized provider
1761
+ routing identity attached to sessions
1762
+ - `transcript_events`
1763
+ - transcript snapshots and compaction checkpoints. Done for runtime writes.
1764
+ - `vfs_entries`
1765
+ - `tool_artifacts` and run artifacts
1766
+ - agent-local runtime/cache rows. Done for worker scoped caches.
1767
+ - ACP parent stream events
1768
+ - trajectory runtime events when they are not explicit export artifacts
1769
+
1770
+ ### Phase 3: Replace Session Store APIs
1771
+
1772
+ Done for runtime. The file-shaped session store surface is not an active
1773
+ runtime contract:
1774
+
1775
+ - Runtime no longer calls `loadSessionStore(storePath)` or treats `storePath` as
1776
+ session identity.
1777
+ - Runtime row operations are `getSessionEntry`, `upsertSessionEntry`,
1778
+ `patchSessionEntry`, `deleteSessionEntry`, and `listSessionEntries`.
1779
+ - Whole-store rewrite helpers, file writers, queue tests, alias pruning, and
1780
+ legacy-key deletion parameters are gone from runtime.
1781
+ - Deprecated root-package compatibility exports still adapt canonical
1782
+ `sessions.json` paths onto the SQLite row APIs.
1783
+ - `sessions.json` parsing remains only in doctor migration/import code and
1784
+ doctor tests.
1785
+ - Runtime lifecycle fallback reads SQLite transcript headers, not JSONL first
1786
+ lines.
1787
+
1788
+ Keep deleting anything that reintroduces file-lock parameters,
1789
+ pruning/truncation-as-file-maintenance vocabulary, store-path identity, or tests
1790
+ whose only assertion is JSON persistence.
1791
+
1792
+ ### Phase 4: Move Transcripts, ACP Streams, Trajectories, And VFS
1793
+
1794
+ Make every agent data stream database-native:
1795
+
1796
+ - Transcript append writes go through one SQLite transaction that ensures the
1797
+ session header, checks message idempotency, selects the parent tail, inserts
1798
+ into `transcript_events`, and records queryable identity metadata in
1799
+ `transcript_event_identities`. Done for direct transcript message appends and
1800
+ normal persisted `TranscriptSessionManager` appends; explicit branch
1801
+ operations keep their explicit parent choice and still write SQLite rows
1802
+ without deriving any file locator.
1803
+ - ACP parent stream logs become rows, not `.acp-stream.jsonl` files. Done.
1804
+ - ACP spawn setup no longer persists transcript JSONL paths. Done.
1805
+ - Runtime trajectory capture writes event rows/artifacts directly. The explicit
1806
+ support/export command can still produce support-bundle JSONL artifacts as an
1807
+ export format, but session export does not recreate session JSONL. Done.
1808
+ - Disk workspaces stay on disk when configured as disk mode.
1809
+ - VFS scratch and experimental VFS-only workspace mode use the agent DB.
1810
+
1811
+ The migration imports old JSONL files once, records counts/hashes in
1812
+ `migration_runs`, and removes imported files after integrity checks.
1813
+
1814
+ ### Phase 5: Backup, Restore, Vacuum, And Verify
1815
+
1816
+ Backups remain one archive file:
1817
+
1818
+ - Checkpoint every global and agent database.
1819
+ - Snapshot each DB with SQLite backup semantics or `VACUUM INTO`.
1820
+ - Archive compact DB snapshots, config, external credentials, and requested
1821
+ workspace exports.
1822
+ - Omit raw live `*.sqlite-wal` and `*.sqlite-shm` files.
1823
+ - Verify by opening every DB snapshot and running `PRAGMA integrity_check`.
1824
+ `openclaw backup create` does this archive verification by default;
1825
+ `--no-verify` skips only the post-write archive pass, not the snapshot
1826
+ creation integrity check.
1827
+ - Restore copies snapshots back to their target paths. This branch resets the
1828
+ unshipped SQLite layout to `user_version = 1`; future shipped schema changes
1829
+ can add explicit migrations when they are needed.
1830
+
1831
+ ### Phase 6: Worker Runtime
1832
+
1833
+ Keep worker mode experimental while the database split lands:
1834
+
1835
+ - Workers receive agent id, run id, filesystem mode, and DB registry identity.
1836
+ - Each worker opens its own SQLite connection.
1837
+ - Parent keeps channel delivery, approvals, config, and cancellation authority.
1838
+ - Start with one worker per active run; add pooling only after lifecycle and DB
1839
+ connection ownership are stable.
1840
+
1841
+ ### Phase 7: Delete The Old World
1842
+
1843
+ Done for runtime session management. The old world is allowed only as explicit
1844
+ doctor input or support/export output:
1845
+
1846
+ - No runtime `sessions.json`, transcript JSONL, sandbox registry JSON, task
1847
+ sidecar SQLite, or plugin-state sidecar SQLite writes.
1848
+ - No JSON/session file pruning, file transcript truncation, session file locks,
1849
+ or lock-shaped session tests.
1850
+ - No runtime compatibility exports whose purpose is keeping old session files
1851
+ current.
1852
+ - Explicit support exports remain user-requested archive/materialization
1853
+ formats and must not feed file names back into runtime identity.
1854
+
1855
+ ## Backup And Restore
1856
+
1857
+ Backups should be one archive file, but database capture should be
1858
+ SQLite-native:
1859
+
1860
+ 1. Stop long-running write activity or enter a short backup barrier.
1861
+ 2. For every global and agent database, run a checkpoint.
1862
+ 3. Snapshot each database using SQLite backup semantics or `VACUUM INTO` into a
1863
+ temporary backup directory.
1864
+ 4. Archive the compacted database snapshots, config file, credentials directory,
1865
+ selected workspaces, and a manifest.
1866
+ 5. Verify the archive by opening every included SQLite snapshot and running
1867
+ `PRAGMA integrity_check`.
1868
+ `openclaw backup create` does this by default; `--no-verify` is only for
1869
+ intentionally skipping the post-write archive pass.
1870
+
1871
+ Do not rely on raw live `*.sqlite`, `*.sqlite-wal`, and `*.sqlite-shm` copies as
1872
+ the primary backup format. The archive manifest should record database role,
1873
+ agent id, schema version, source path, snapshot path, byte size, and integrity
1874
+ status.
1875
+
1876
+ Restore should rebuild the global database and agent database files from the
1877
+ archive snapshots. Because the SQLite layout has not shipped yet, this refactor
1878
+ keeps only the version-1 schema plus doctor file-to-database import. The restore
1879
+ command validates the archive first, then replaces each manifest asset from the
1880
+ verified extracted payload.
1881
+
1882
+ ## Runtime Refactor Plan
1883
+
1884
+ 1. Add database registry APIs.
1885
+ - Resolve global DB and per-agent DB paths.
1886
+ - Keep the unshipped schemas at `user_version = 1`; do not add schema
1887
+ migration runner code until a shipped schema needs it.
1888
+ - Add close/checkpoint/integrity helpers used by tests, backup, and doctor.
1889
+
1890
+ 2. Collapse sidecar SQLite stores.
1891
+ - Move plugin state tables into the global database. Done for runtime
1892
+ writes; the unshipped legacy sidecar importer is deleted.
1893
+ - Move task registry tables into the global database. Done for runtime
1894
+ writes; the unshipped legacy sidecar importer is deleted.
1895
+ - Move Task Flow tables into the global database. Done for runtime writes;
1896
+ the unshipped legacy sidecar importer is deleted.
1897
+ - Move builtin memory-search tables into each agent database. Done; explicit
1898
+ custom `memorySearch.store.path` is now removed by doctor config migration.
1899
+ Full reindex runs in place against memory tables only; the old whole-file
1900
+ swap path and sidecar index swap helper are deleted.
1901
+ - Delete duplicate database openers, WAL setup, permission helpers, and
1902
+ close paths from those subsystems.
1903
+
1904
+ 3. Move agent-owned tables into per-agent databases.
1905
+ - Create agent DB on demand through the global database registry. Done.
1906
+ - Move runtime session entries, transcript events, VFS rows, and tool
1907
+ artifacts to agent DBs. Done.
1908
+ - Do not migrate branch-local shared-DB session entries, transcript events,
1909
+ VFS rows, or tool artifacts; that layout never shipped. Keep only legacy
1910
+ file-to-database import in doctor.
1911
+
1912
+ 4. Replace session store APIs.
1913
+ - Remove `storePath` as the runtime identity. Done for runtime and guarded
1914
+ by `check:database-first-legacy-stores`: session metadata, route updates,
1915
+ command persistence, CLI session cleanup, Feishu reasoning previews,
1916
+ transcript-state persistence, subagent depth, auth profile session
1917
+ overrides, parent-fork logic, and QA-lab inspection now resolve the
1918
+ database from canonical agent/session keys.
1919
+ Gateway/TUI/UI/macOS session-list responses now expose `databasePath`
1920
+ instead of legacy `path`; macOS debug surfaces show the per-agent database
1921
+ as read-only state instead of writing `session.store` config.
1922
+ `/status`, chat-driven trajectory export, and CLI dependency proxies no
1923
+ longer propagate legacy store paths; transcript usage fallback reads
1924
+ SQLite by agent/session identity. Runtime and bridge tests no longer expose
1925
+ `storePath`; doctor/migration inputs own that legacy field name.
1926
+ Gateway combined-session loading no longer has a special runtime branch for
1927
+ non-templated `session.store` values; it aggregates per-agent SQLite rows.
1928
+ The legacy session-lock doctor lane and its `.jsonl.lock` cleanup helper
1929
+ were removed; SQLite is the session concurrency boundary now.
1930
+ Hot runtime call sites use row-oriented helper names such as
1931
+ `resolveSessionRowEntry`; the old `resolveSessionStoreEntry` compatibility
1932
+ alias has been removed from runtime and plugin SDK exports.
1933
+
1934
+ - Use `{ agentId, sessionKey }` row operations.
1935
+ Done: `getSessionEntry`, `upsertSessionEntry`, `deleteSessionEntry`,
1936
+ `patchSessionEntry`, and `listSessionEntries` are SQLite-first APIs that do
1937
+ not require a session store path. Status summary, local agent status, health,
1938
+ and the `openclaw sessions` listing command now read per-agent rows directly
1939
+ and display per-agent SQLite database paths instead of `sessions.json` paths.
1940
+ - Replace whole-store delete/insert with `upsertSessionEntry`,
1941
+ `deleteSessionEntry`, `listSessionEntries`, and SQL cleanup queries.
1942
+ Done for runtime: hot paths now use row APIs and conflict-retried row patches;
1943
+ remaining whole-store import/replace helpers are limited to migration import
1944
+ code and SQLite backend tests.
1945
+ - Delete `store-writer.ts` and writer-queue tests. Done.
1946
+ - Delete runtime legacy-key pruning and alias-delete parameters from session
1947
+ row upserts/patches. Done.
1948
+
1949
+ 5. Delete runtime JSON registry behavior.
1950
+ - Make sandbox registry reads and writes SQLite-only. Done.
1951
+ - Import monolithic and sharded JSON only from the migration step. Done.
1952
+ - Remove sharded registry locks and JSON writes. Done.
1953
+
1954
+ - Keep one typed registry table instead of storing registry rows as generic
1955
+ opaque JSON if the shape remains hot-path operational state. Done.
1956
+
1957
+ 6. Delete file-lock-shaped session mutation.
1958
+ - Done for runtime lock creation and runtime lock APIs.
1959
+ - The standalone legacy `.jsonl.lock` doctor cleanup lane is removed.
1960
+ - `session.writeLock` is doctor-migrated legacy config, not a typed runtime
1961
+ setting.
1962
+ - State integrity no longer has a separate orphan transcript-file pruning
1963
+ path; doctor migration imports/removes legacy JSONL sources in one place.
1964
+ - Gateway singleton coordination uses typed SQLite `state_leases` rows under
1965
+ `gateway_locks` and no longer exposes a file-lock directory seam.
1966
+ - Generic plugin SDK dedupe persistence no longer uses file locks or JSON
1967
+ files; it writes shared SQLite plugin-state rows. Done.
1968
+ - QMD embed coordination uses a SQLite state lease instead of
1969
+ `qmd/embed.lock`. Done.
1970
+
1971
+ 7. Make workers database-aware.
1972
+ - Workers open their own SQLite connections.
1973
+ - Parent owns delivery, channel callbacks, and config.
1974
+ - Worker receives agent id, run id, filesystem mode, and DB registry
1975
+ identity, not live handles.
1976
+ - `vfs-only` stays experimental and uses the agent database as its storage
1977
+ root.
1978
+ - Keep one worker per active run first. Pooling can wait until DB connection
1979
+ lifetime and cancellation behavior are boring.
1980
+
1981
+ 8. Backup integration.
1982
+ - Teach backup to snapshot global and agent databases via SQLite backup or
1983
+ `VACUUM INTO`. Done for discovered `*.sqlite` files under the state asset.
1984
+ - Add backup verification for SQLite integrity and schema version. Done for
1985
+ backup creation and default archive verification integrity checks.
1986
+ - Record backup run metadata in SQLite. Done via the shared `backup_runs`
1987
+ table with archive path, status, and manifest JSON.
1988
+ - Add restore from verified archive snapshots. Done: `openclaw backup
1989
+ restore` validates before extraction, uses the verifier's normalized
1990
+ manifest, supports `--dry-run`, and requires `--yes` before replacing
1991
+ recorded source paths.
1992
+ - Include VFS/workspace export only when requested; do not export session
1993
+ internals as JSON or JSONL.
1994
+
1995
+ 9. Delete obsolete tests and code. Done for the known runtime session surfaces.
1996
+
1997
+ - Remove tests that assert runtime creation of `sessions.json` or transcript
1998
+ JSONL files. Done for core session store, chat, gateway transcript events,
1999
+ preview, lifecycle, command session-entry updates, auto-reply reset/trace, and
2000
+ memory-core dreaming fixtures, approval target routing, session transcript
2001
+ repair, security permission repair, trajectory export, and session export.
2002
+ Active-memory transcript tests now assert SQLite scopes and no temporary or
2003
+ persisted JSONL file creation.
2004
+ The old heartbeat transcript-pruning regression was removed because
2005
+ runtime no longer truncates JSONL transcripts.
2006
+ Agent session-list tool tests no longer model legacy `sessions.json` paths
2007
+ as the gateway response shape; app/UI/macOS tests use `databasePath`.
2008
+ `/status` transcript-usage tests now seed SQLite transcript rows directly
2009
+ instead of writing JSONL files.
2010
+ Gateway session lifecycle tests now use SQLite transcript seeding helpers
2011
+ directly; the old single-line session-file fixture shape is gone from reset
2012
+ and delete coverage.
2013
+ `sessions.delete` no longer returns a file-era `archived: []` field; deletion
2014
+ reports only the row mutation result. The old `deleteTranscript` option is
2015
+ gone too: deleting a session removes the canonical `sessions` root and lets
2016
+ SQLite cascade session-owned transcript, snapshot, and trajectory rows, so no
2017
+ caller can leave transcript orphans behind or forget a cleanup branch.
2018
+ Context-engine trajectory capture tests now read `trajectory_runtime_events`
2019
+ rows from an isolated agent database instead of reading
2020
+ `session.trajectory.jsonl`.
2021
+ Docker MCP channel seed scripts now seed SQLite rows directly. Direct
2022
+ `sessions.json` writes are limited to doctor fixtures.
2023
+ Tool Search Gateway E2E reads tool-call evidence from SQLite transcript rows
2024
+ instead of scanning `agents/<agentId>/sessions/*.jsonl` files.
2025
+ Memory-core host events and session-corpus scratch rows now live in shared
2026
+ SQLite plugin-state; `events.jsonl` and `session-corpus/*.txt` are legacy
2027
+ doctor migration inputs only. Active rows use `memory/session-ingestion/`
2028
+ virtual paths, not `.dreams/session-corpus`. The old memory-core dreaming
2029
+ repair module and its CLI/Gateway tests were removed because runtime no
2030
+ longer owns file archive repair for that corpus. Memory-core
2031
+ bridge/public-artifact tests no longer surface `.dreams/events.jsonl`; they
2032
+ use the SQLite-backed virtual JSON artifact name.
2033
+ Public SDK/Codex testing docs now say SQLite session state instead of session
2034
+ files, and the channel-turn example no longer exposes a `storePath` argument.
2035
+ Matrix sync state now uses the SQLite plugin-state store directly. Active
2036
+ client/runtime contracts pass an account storage root, not a `bot-storage.json`
2037
+ path, and doctor imports legacy `bot-storage.json` into SQLite before deleting
2038
+ the source. QA Matrix restart/destructive scenarios now mutate the SQLite sync
2039
+ row directly instead of creating or deleting fake `bot-storage.json` files, and
2040
+ the E2EE substrate passes a sync-store root instead of a fake
2041
+ `sync-store.json` path.
2042
+ Matrix storage-root selection no longer scores roots by legacy sync/thread JSON
2043
+ files; it uses durable root metadata plus real crypto state.
2044
+ The runtime SQLite session backend test suite no longer fabricates a
2045
+ `sessions.json`; legacy source fixtures now live in the doctor
2046
+ tests that import them.
2047
+ Gateway session tests no longer expose a `createSessionStoreDir` helper or
2048
+ unused temp session-store path setup; fixture dirs are explicit, and direct
2049
+ row setup uses SQLite session-row naming.
2050
+ Doctor-only JSON5 session-store parser coverage moved out of infra tests and
2051
+ into doctor migration tests, so runtime test suites no longer own legacy
2052
+ session-file parsing.
2053
+ Microsoft Teams runtime SSO/pending-upload tests no longer carry JSON sidecar
2054
+ fixtures or parsers; legacy SSO token parsing lives only in the plugin
2055
+ migration module. Telegram tests no longer seed fake `/tmp/*.json` store
2056
+ paths; they reset the SQLite-backed message cache directly. The generic
2057
+ OpenClaw test-state helper no longer exposes a legacy `auth-profiles.json`
2058
+ writer; doctor auth migration tests own that fixture locally.
2059
+ Runtime tests for TUI last-session pointers, exec approvals, active-memory
2060
+ toggles, Matrix dedupe/startup verification, Memory Wiki source sync,
2061
+ current-conversation bindings, onboarding auth, and Hermes secret imports no
2062
+ longer manufacture old sidecar files or assert old filenames are absent. They
2063
+ prove behavior through SQLite rows and public store APIs; doctor/migration
2064
+ tests are the only place legacy source filenames belong.
2065
+ Runtime tests for device/node pairing, channel allowFrom, restart intents,
2066
+ restart handoff, session delivery queue entries, config health, iMessage
2067
+ caches, cron jobs, PI transcript headers, subagent registries, and managed
2068
+ image attachments also no longer create retired JSON/JSONL files just to prove
2069
+ they are ignored or absent.
2070
+ PI overflow recovery no longer has a SessionManager rewrite/truncation
2071
+ fallback: tool-result truncation and context-engine transcript rewrites mutate
2072
+ SQLite transcript rows, then refresh active prompt state from the database.
2073
+ Persisted SessionManager message appends delegate to the atomic SQLite
2074
+ transcript append helper for parent selection and idempotency. Normal
2075
+ metadata/custom entry appends also select the current parent inside SQLite, so
2076
+ stale manager instances do not resurrect pre-SQLite parent-chain races.
2077
+ Synthetic PI tail cleanup for mid-turn prechecks and `sessions_yield` now
2078
+ trims SQLite transcript state directly; the old SessionManager tail-removal
2079
+ bridge and its tests are deleted.
2080
+ Compaction checkpoint capture also snapshots from SQLite only; callers no
2081
+ longer pass a live SessionManager as an alternate transcript source.
2082
+ - Keep tests that seed legacy files only for migration.
2083
+ - JSON-file proof has been replaced with SQL row proof for active runtime
2084
+ surfaces.
2085
+
2086
+ - Add static bans for runtime writes to legacy session/cache JSON paths.
2087
+ Done for the repo guard.
2088
+
2089
+ 10. Make the migration report auditable.
2090
+ - Record migration runs in SQLite with started/finished timestamps, source
2091
+ paths, source hashes, counts, warnings, and backup path.
2092
+ Done: legacy-state migration executions now persist a `migration_runs`
2093
+ report with source path/table inventory, source file SHA-256, sizes,
2094
+ record counts, warnings, and backup path.
2095
+ Done: legacy-state migration executions also persist `migration_sources`
2096
+ rows for source-level audit and future skip/backfill decisions.
2097
+ - Make apply idempotent. Re-running after a partial import should either
2098
+ skip an already imported source or merge by stable key.
2099
+ Done: session indexes, transcripts, delivery queues, plugin state, task
2100
+ ledgers, and agent-owned global SQLite rows import through stable keys or
2101
+ upsert/replace semantics, so reruns merge without duplicating durable
2102
+ rows.
2103
+ - Failed imports must keep the original source file in place.
2104
+ Done: failed transcript imports now leave the original JSONL source at
2105
+ its detected path, and `migration_sources` records the source as
2106
+ `warning` with `removed_source=0` for the next doctor run.
2107
+
2108
+ ## Performance Rules
2109
+
2110
+ - One connection per thread/process is fine; do not share handles across
2111
+ workers.
2112
+ - Use WAL, `foreign_keys=ON`, a 30s busy timeout, and short `BEGIN IMMEDIATE`
2113
+ write transactions.
2114
+ - Keep write transaction helpers synchronous unless/until an async transaction
2115
+ API adds explicit mutex/backpressure semantics.
2116
+ - Keep parent delivery writes small and transactional.
2117
+ - Avoid whole-store rewrites; use row-level upsert/delete.
2118
+ - Add indexes for list-by-agent, list-by-session, updated-at, run id, and
2119
+ expiration paths before moving hot code.
2120
+ - Store large artifacts, media, and vectors as BLOBs or chunked BLOB rows, not
2121
+ base64 or numeric-array JSON.
2122
+ - Keep opaque plugin-state entries small and scoped.
2123
+ - Add SQL cleanup for TTL/expiration instead of filesystem pruning.
2124
+ Done for database-owned runtime stores: media, plugin state, plugin blobs,
2125
+ persistent dedupe, and agent cache all expire through SQLite rows. Remaining
2126
+ filesystem cleanup is limited to temporary materializations or explicit
2127
+ removal commands.
2128
+
2129
+ ## Static Bans
2130
+
2131
+ Add a repo check that fails new runtime writes to legacy state paths:
2132
+
2133
+ - `sessions.json`
2134
+ - `*.trajectory.jsonl` except materialized support-bundle outputs
2135
+ - `.acp-stream.jsonl`
2136
+ - `acp/event-ledger.json`
2137
+ - `cache/*.json` runtime cache files
2138
+ - `agents/<agentId>/agent/auth.json`
2139
+ - `agents/<agentId>/agent/models.json`
2140
+ - `credentials/oauth.json`
2141
+ - `github-copilot.token.json`
2142
+ - `openrouter-models.json`
2143
+ - `auth-profiles.json`
2144
+ - `auth-state.json`
2145
+ - `exec-approvals.json`
2146
+ - `workspace-state.json`
2147
+ - Matrix `credentials*.json` and `recovery-key.json`
2148
+ - `cron/runs/*.jsonl`
2149
+ - `cron/jobs.json`
2150
+ - `jobs-state.json`
2151
+ - `device-pair-notify.json`
2152
+ - `devices/pending.json`
2153
+ - `devices/paired.json`
2154
+ - `devices/bootstrap.json`
2155
+ - `nodes/pending.json`
2156
+ - `nodes/paired.json`
2157
+ - `identity/device.json`
2158
+ - `identity/device-auth.json`
2159
+ - `push/web-push-subscriptions.json`
2160
+ - `push/vapid-keys.json`
2161
+ - `push/apns-registrations.json`
2162
+ - `process-leases.json`
2163
+ - `gateway-instance-id`
2164
+ - `session-toggles.json`
2165
+ - Memory-core `.dreams/events.jsonl`
2166
+ - Memory-core `.dreams/session-corpus/`
2167
+ - Memory-core `.dreams/daily-ingestion.json`
2168
+ - Memory-core `.dreams/session-ingestion.json`
2169
+ - Memory-core `.dreams/short-term-recall.json`
2170
+ - Memory-core `.dreams/phase-signals.json`
2171
+ - Memory-core `.dreams/short-term-promotion.lock`
2172
+ - Skill Workshop `skill-workshop/<workspace>.json`
2173
+ - Skill Workshop `skill-workshop/skill-workshop-review-*.json`
2174
+ - Nostr `bus-state-*.json`
2175
+ - Nostr `profile-state-*.json`
2176
+ - `calls.jsonl`
2177
+ - `known-users.json`
2178
+ - `ref-index.jsonl`
2179
+ - QQBot `session-*.json`
2180
+ - BlueBubbles `bluebubbles/catchup/*.json`
2181
+ - BlueBubbles `bluebubbles/inbound-dedupe/*.json`
2182
+ - Telegram `update-offset-*.json`
2183
+ - Telegram `sticker-cache.json`
2184
+ - Telegram `*.telegram-messages.json`
2185
+ - Telegram `*.telegram-sent-messages.json`
2186
+ - Telegram `*.telegram-topic-names.json`
2187
+ - Telegram `thread-bindings-*.json`
2188
+ - iMessage `catchup/*.json`
2189
+ - iMessage `reply-cache.jsonl`
2190
+ - iMessage `sent-echoes.jsonl`
2191
+ - Microsoft Teams `msteams-conversations.json`
2192
+ - Microsoft Teams `msteams-polls.json`
2193
+ - Microsoft Teams `msteams-sso-tokens.json`
2194
+ - Microsoft Teams `*.learnings.json`
2195
+ - Matrix `bot-storage.json`
2196
+ - Matrix `sync-store.json`
2197
+ - Matrix `thread-bindings.json`
2198
+ - Matrix `inbound-dedupe.json`
2199
+ - Matrix `startup-verification.json`
2200
+ - Matrix `storage-meta.json`
2201
+ - Matrix `crypto-idb-snapshot.json`
2202
+ - Discord `model-picker-preferences.json`
2203
+ - Discord `command-deploy-cache.json`
2204
+ - sandbox registry shard JSON files
2205
+ - native hook relay `/tmp` bridge JSON files
2206
+ - `plugin-state/state.sqlite`
2207
+ - ad-hoc `openclaw-state.sqlite` runtime sidecars
2208
+ - `tasks/runs.sqlite`
2209
+ - `tasks/flows/registry.sqlite`
2210
+ - `bindings/current-conversations.json`
2211
+ - `restart-sentinel.json`
2212
+ - `gateway-restart-intent.json`
2213
+ - `gateway-supervisor-restart-handoff.json`
2214
+ - `gateway.<hash>.lock`
2215
+ - `qmd/embed.lock`
2216
+ - `commands.log`
2217
+ - `config-health.json`
2218
+ - `port-guard.json`
2219
+ - `settings/voicewake.json`
2220
+ - `settings/voicewake-routing.json`
2221
+ - `plugin-binding-approvals.json`
2222
+ - `plugins/installs.json`
2223
+ - `audit/file-transfer.jsonl`
2224
+ - `audit/crestodian.jsonl`
2225
+ - `crestodian/rescue-pending/*.json`
2226
+ - `plugins/phone-control/armed.json`
2227
+ - Memory Wiki `.openclaw-wiki/log.jsonl`
2228
+ - Memory Wiki `.openclaw-wiki/state.json`
2229
+ - Memory Wiki `.openclaw-wiki/locks/`
2230
+ - Memory Wiki `.openclaw-wiki/source-sync.json`
2231
+ - Memory Wiki `.openclaw-wiki/import-runs/*.json`
2232
+ - Memory Wiki `.openclaw-wiki/cache/agent-digest.json`
2233
+ - Memory Wiki `.openclaw-wiki/cache/claims.jsonl`
2234
+ - ClawHub `.clawhub/lock.json`
2235
+ - ClawHub `.clawhub/origin.json`
2236
+ - Browser profile decoration `.openclaw-profile-decorated`
2237
+ - `SessionManager.open(...)` file-backed session openers
2238
+ - `SessionManager.listAll(...)` and `TranscriptSessionManager.listAll(...)`
2239
+ transcript listing facades
2240
+ - `SessionManager.forkFromSession(...)` and
2241
+ `TranscriptSessionManager.forkFromSession(...)` transcript fork facades
2242
+ - `SessionManager.newSession(...)` and `TranscriptSessionManager.newSession(...)`
2243
+ mutable session replacement facades
2244
+ - `SessionManager.createBranchedSession(...)` and
2245
+ `TranscriptSessionManager.createBranchedSession(...)` branch-session facades
2246
+
2247
+ The ban should allow tests to create legacy fixtures and allow migration code to
2248
+ read/import/remove legacy file sources. Unshipped SQLite sidecars stay banned
2249
+ and do not get doctor import allowances.
2250
+
2251
+ ## Done Criteria
2252
+
2253
+ - Runtime data and cache writes go to the global or agent SQLite database.
2254
+ - Runtime no longer writes session indexes, transcript JSONL, sandbox registry
2255
+ JSON, task sidecar SQLite, or plugin-state sidecar SQLite. The unshipped task
2256
+ and plugin-state sidecar SQLite importers are deleted.
2257
+ - Legacy file import is doctor-only.
2258
+ - Backup produces one archive with compact SQLite snapshots and integrity proof.
2259
+ - Agent workers can run with disk, VFS scratch, or experimental VFS-only
2260
+ storage.
2261
+ - Config and explicit credential files remain the only expected persistent
2262
+ non-database control files.
2263
+ - Repo checks prevent reintroducing legacy runtime file stores.