@north-light/crouter 0.3.353 → 0.3.355

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 (626) hide show
  1. package/dist/api/client.d.ts +35 -25
  2. package/dist/api/client.js +2 -2
  3. package/dist/api/dto/broker-ops.d.ts +2 -36
  4. package/dist/api/dto/canvas.d.ts +8 -13
  5. package/dist/api/dto/config.d.ts +4 -0
  6. package/dist/api/dto/delivery.d.ts +61 -0
  7. package/dist/api/dto/docs.d.ts +135 -0
  8. package/dist/api/dto/docs.js +1 -0
  9. package/dist/api/dto/health.d.ts +26 -79
  10. package/dist/api/dto/node-outcomes.d.ts +1 -3
  11. package/dist/api/dto/nodes.d.ts +5 -26
  12. package/dist/api/dto/objects.d.ts +168 -0
  13. package/dist/api/dto/objects.js +1 -0
  14. package/dist/api/dto/profiles.d.ts +14 -8
  15. package/dist/api/dto/reports.d.ts +9 -7
  16. package/dist/api/dto/reviews.d.ts +11 -3
  17. package/dist/api/dto/worktree.d.ts +1 -1
  18. package/dist/api/index.d.ts +0 -1
  19. package/dist/api/index.js +1 -1
  20. package/dist/api/routes.d.ts +14 -12
  21. package/dist/api/routes.js +1 -1
  22. package/dist/build-root.js +1 -1
  23. package/dist/builtin-memory/00-runtime-base/00-authoring.md +10 -5
  24. package/dist/builtin-memory/02-turn-lifecycle/02-resident.md +1 -0
  25. package/dist/builtin-memory/04-orchestration-kernel.md +10 -31
  26. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -1
  27. package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
  28. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +2 -2
  29. package/dist/builtin-memory/crouter-concepts/INDEX.md +2 -2
  30. package/dist/builtin-memory/crouter-concepts/lifecycle-and-wakes.md +1 -1
  31. package/dist/builtin-memory/crouter-concepts/memory.md +15 -15
  32. package/dist/builtin-memory/crouter-concepts/nodes-and-the-canvas.md +1 -1
  33. package/dist/builtin-memory/crouter-concepts/profiles-kinds-and-modes.md +5 -5
  34. package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +1 -1
  35. package/dist/builtin-memory/crouter-concepts/why-a-daemon.md +1 -1
  36. package/dist/builtin-memory/crouter-sdk/INDEX.md +2 -2
  37. package/dist/builtin-memory/crouter-sdk/README.md +5 -6
  38. package/dist/builtin-memory/crouter-sdk/errors.md +0 -13
  39. package/dist/builtin-memory/crouter-sdk/guides/README.md +0 -1
  40. package/dist/builtin-memory/crouter-sdk/guides/event-driven-assistant.md +2 -2
  41. package/dist/builtin-memory/crouter-sdk/nodes.md +0 -2
  42. package/dist/builtin-memory/crouter-sdk/resources.md +0 -1
  43. package/dist/builtin-memory/explore/exploration-doc.md +4 -4
  44. package/dist/builtin-memory/insights/capture.md +6 -6
  45. package/dist/builtin-memory/insights/init.md +14 -14
  46. package/dist/builtin-memory/internal/INDEX.md +4 -4
  47. package/dist/builtin-memory/internal/agent-shaping.md +20 -20
  48. package/dist/builtin-memory/internal/examples/imessage-assistant.md +2 -2
  49. package/dist/builtin-memory/internal/marketplaces.md +2 -2
  50. package/dist/builtin-memory/internal/memory-loading.md +31 -30
  51. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  52. package/dist/builtin-memory/internal/plugins.md +16 -14
  53. package/dist/builtin-memory/internal/storage-tiers.md +4 -4
  54. package/dist/builtin-memory/memory-read-orientation.md +1 -1
  55. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +32 -40
  56. package/dist/clients/attach/input/controller.js +1 -1
  57. package/dist/clients/attach/input/ref-autocomplete.js +1 -1
  58. package/dist/clients/attach/input/titled-editor.js +1 -1
  59. package/dist/clients/attach/overlays/file-review.d.ts +1 -0
  60. package/dist/clients/attach/overlays/file-review.js +2 -2
  61. package/dist/clients/attach/render/chat-view.d.ts +6 -0
  62. package/dist/clients/attach/render/chat-view.js +2 -2
  63. package/dist/clients/attach/render/crtr-output.d.ts +1 -2
  64. package/dist/clients/attach/render/crtr-output.js +17 -17
  65. package/dist/clients/attach/render/doc-links.d.ts +34 -0
  66. package/dist/clients/attach/render/doc-links.js +1 -0
  67. package/dist/clients/attach/render/group-activity.d.ts +8 -8
  68. package/dist/clients/attach/render/group-activity.js +2 -2
  69. package/dist/clients/attach/render/group-recap.js +1 -1
  70. package/dist/clients/attach/render/markdown-source.js +5 -5
  71. package/dist/clients/attach/render/tool-calls.d.ts +1 -1
  72. package/dist/clients/attach/session/doc-materialize.d.ts +53 -0
  73. package/dist/clients/attach/session/doc-materialize.js +3 -0
  74. package/dist/clients/attach/session/document-links.d.ts +21 -0
  75. package/dist/clients/attach/session/document-links.js +1 -0
  76. package/dist/clients/attach/session/file-links.d.ts +2 -0
  77. package/dist/clients/attach/session/file-links.js +1 -1
  78. package/dist/clients/attach/session/profile-files.js +1 -1
  79. package/dist/clients/attach/slash/dispatch.js +1 -1
  80. package/dist/clients/attach/viewer.js +816 -1561
  81. package/dist/clients/inbox/review/review-client.d.ts +5 -1
  82. package/dist/clients/inbox/review/review-client.js +1 -1
  83. package/dist/commands/api-client.d.ts +2 -0
  84. package/dist/commands/api-client.js +3 -3
  85. package/dist/commands/canvas/edges.d.ts +2 -0
  86. package/dist/commands/canvas/edges.js +2 -0
  87. package/dist/commands/canvas/list.d.ts +4 -0
  88. package/dist/commands/canvas/list.js +3 -0
  89. package/dist/commands/canvas/read.d.ts +8 -0
  90. package/dist/commands/canvas/read.js +5 -0
  91. package/dist/commands/canvas/search.d.ts +2 -0
  92. package/dist/commands/canvas/search.js +3 -0
  93. package/dist/commands/canvas/unwatch.d.ts +2 -0
  94. package/dist/commands/canvas/unwatch.js +1 -0
  95. package/dist/commands/canvas/watch.d.ts +3 -0
  96. package/dist/commands/canvas/watch.js +1 -0
  97. package/dist/commands/canvas-analytics.js +1 -1
  98. package/dist/commands/canvas-history/grep.js +4 -4
  99. package/dist/commands/canvas-history/read.js +2 -2
  100. package/dist/commands/canvas-history/search.js +7 -7
  101. package/dist/commands/canvas-history/shared.d.ts +0 -1
  102. package/dist/commands/canvas-history/shared.js +1 -1
  103. package/dist/commands/canvas-history/stats.js +2 -2
  104. package/dist/commands/canvas-history.js +1 -1
  105. package/dist/commands/canvas.js +1 -1
  106. package/dist/commands/doc/delete.d.ts +2 -0
  107. package/dist/commands/doc/delete.js +1 -0
  108. package/dist/commands/doc/edit.d.ts +2 -0
  109. package/dist/commands/doc/edit.js +1 -0
  110. package/dist/commands/doc/history.d.ts +2 -0
  111. package/dist/commands/doc/history.js +2 -0
  112. package/dist/commands/doc/lint.d.ts +2 -0
  113. package/dist/commands/doc/lint.js +2 -0
  114. package/dist/commands/doc/list.d.ts +2 -0
  115. package/dist/commands/doc/list.js +1 -0
  116. package/dist/commands/doc/move.d.ts +2 -0
  117. package/dist/commands/doc/move.js +1 -0
  118. package/dist/commands/doc/read.d.ts +2 -0
  119. package/dist/commands/doc/read.js +1 -0
  120. package/dist/commands/doc/shared.d.ts +25 -0
  121. package/dist/commands/doc/shared.js +2 -0
  122. package/dist/commands/doc/write.d.ts +2 -0
  123. package/dist/commands/doc/write.js +1 -0
  124. package/dist/commands/{memory.d.ts → doc.d.ts} +1 -1
  125. package/dist/commands/doc.js +1 -0
  126. package/dist/commands/human/review.js +1 -1
  127. package/dist/commands/node/bash.js +2 -2
  128. package/dist/commands/node/create.js +1 -1
  129. package/dist/commands/node/inspect.js +10 -10
  130. package/dist/commands/node/lifecycle.js +2 -2
  131. package/dist/commands/node/outcome.js +1 -1
  132. package/dist/commands/node/subscription.js +1 -1
  133. package/dist/commands/node-context.js +2 -2
  134. package/dist/commands/pkg/browse/catalog.js +1 -1
  135. package/dist/commands/pkg/browse/doc-view.js +1 -1
  136. package/dist/commands/pkg/browse/model.d.ts +9 -17
  137. package/dist/commands/pkg/plugin-inspect.js +1 -1
  138. package/dist/commands/pkg/plugin-manage.d.ts +4 -8
  139. package/dist/commands/pkg/plugin-manage.js +15 -17
  140. package/dist/commands/profile/list.js +1 -1
  141. package/dist/commands/profile/new.js +1 -1
  142. package/dist/commands/profile/project.js +1 -1
  143. package/dist/commands/profile/show.js +1 -1
  144. package/dist/commands/push.js +3 -3
  145. package/dist/commands/sys/config.js +1 -1
  146. package/dist/commands/sys/context/admin/actions.d.ts +18 -43
  147. package/dist/commands/sys/context/admin/actions.js +1 -2
  148. package/dist/commands/sys/context/admin/detail-panel.d.ts +17 -25
  149. package/dist/commands/sys/context/admin/detail-panel.js +2 -1
  150. package/dist/commands/sys/context/admin/docs-panel.d.ts +7 -6
  151. package/dist/commands/sys/context/admin/docs-panel.js +1 -1
  152. package/dist/commands/sys/context/admin/list-view.d.ts +12 -12
  153. package/dist/commands/sys/context/admin/list-view.js +1 -1
  154. package/dist/commands/sys/context/admin/model.d.ts +96 -69
  155. package/dist/commands/sys/context/admin/model.js +1 -1
  156. package/dist/commands/sys/context/admin/rail-panel.d.ts +7 -5
  157. package/dist/commands/sys/context/admin/rail-panel.js +1 -1
  158. package/dist/commands/sys/context/admin/read-view.d.ts +10 -14
  159. package/dist/commands/sys/context/admin/read-view.js +1 -2
  160. package/dist/commands/sys/context/admin/shell.d.ts +26 -31
  161. package/dist/commands/sys/context/admin/shell.js +1 -1
  162. package/dist/commands/sys/context/admin.js +2 -2
  163. package/dist/commands/sys/context/doc.js +2 -3
  164. package/dist/commands/sys/context/expose.js +2 -2
  165. package/dist/commands/sys/context/prompt-review.js +4 -4
  166. package/dist/commands/sys/context/resolve.d.ts +92 -65
  167. package/dist/commands/sys/context/resolve.js +7 -9
  168. package/dist/commands/sys/context.js +1 -1
  169. package/dist/commands/sys/doctor.js +1 -1
  170. package/dist/commands/sys/migrate.js +1 -1
  171. package/dist/commands/sys/panels/profiles-panel.d.ts +3 -1
  172. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  173. package/dist/commands/sys/sync-deps.d.ts +6 -11
  174. package/dist/commands/sys/sync-deps.js +7 -8
  175. package/dist/commands/sys/sync-project-guidance.js +5 -4
  176. package/dist/commands/sys/sync-shared.d.ts +41 -4
  177. package/dist/commands/sys/sync-shared.js +1 -1
  178. package/dist/commands/sys/sync-skills.js +2 -2
  179. package/dist/commands/sys/sync.js +1 -1
  180. package/dist/core/bash-job-supervisor.d.ts +2 -3
  181. package/dist/core/bash-job-supervisor.js +3 -3
  182. package/dist/core/bash-jobs.d.ts +0 -5
  183. package/dist/core/bash-jobs.js +7 -7
  184. package/dist/core/bootstrap.js +2 -2
  185. package/dist/core/canvas/canvas.d.ts +6 -50
  186. package/dist/core/canvas/canvas.js +16 -21
  187. package/dist/core/canvas/db.d.ts +4 -1
  188. package/dist/core/canvas/db.js +2 -2
  189. package/dist/core/canvas/history.d.ts +11 -39
  190. package/dist/core/canvas/history.js +9 -20
  191. package/dist/core/canvas/install-id.d.ts +2 -2
  192. package/dist/core/canvas/install-id.js +1 -1
  193. package/dist/core/canvas/memory-reads.d.ts +5 -0
  194. package/dist/core/canvas/memory-reads.js +1 -1
  195. package/dist/core/canvas/migrations.js +215 -41
  196. package/dist/core/canvas/node-agent-paths.js +1 -1
  197. package/dist/core/canvas/node-tokens.js +1 -1
  198. package/dist/core/canvas/paths.d.ts +0 -4
  199. package/dist/core/canvas/paths.js +1 -1
  200. package/dist/core/canvas/remote-canvas-source.d.ts +0 -1
  201. package/dist/core/canvas/remote-canvas-source.js +1 -1
  202. package/dist/core/canvas/render-source.d.ts +9 -6
  203. package/dist/core/canvas/render-source.js +6 -6
  204. package/dist/core/canvas/sessions.js +2 -2
  205. package/dist/core/canvas/source.d.ts +6 -0
  206. package/dist/core/canvas/tree.d.ts +29 -0
  207. package/dist/core/canvas/tree.js +12 -0
  208. package/dist/core/canvas/types.d.ts +0 -20
  209. package/dist/core/command-plugins/bundle.js +1 -1
  210. package/dist/core/config.d.ts +1 -1
  211. package/dist/core/conversation-store/listener.js +4 -2
  212. package/dist/core/feed/feed.d.ts +9 -7
  213. package/dist/core/feed/feed.js +3 -7
  214. package/dist/core/feed/inbox.d.ts +3 -5
  215. package/dist/core/feed/inbox.js +1 -10
  216. package/dist/core/feed/messages.d.ts +33 -6
  217. package/dist/core/feed/messages.js +10 -7
  218. package/dist/core/feed/reports.d.ts +10 -0
  219. package/dist/core/feed/reports.js +2 -0
  220. package/dist/core/grants/remove.js +1 -1
  221. package/dist/core/graph/access.d.ts +24 -0
  222. package/dist/core/graph/access.js +8 -0
  223. package/dist/core/graph/bodies.d.ts +6 -0
  224. package/dist/core/graph/bodies.js +1 -0
  225. package/dist/core/graph/deletion.d.ts +10 -0
  226. package/dist/core/graph/deletion.js +5 -0
  227. package/dist/core/graph/diff.d.ts +4 -0
  228. package/dist/core/graph/diff.js +4 -0
  229. package/dist/core/graph/documents.d.ts +167 -0
  230. package/dist/core/graph/documents.js +10 -0
  231. package/dist/core/graph/edges.d.ts +25 -0
  232. package/dist/core/graph/edges.js +1 -0
  233. package/dist/core/graph/events.d.ts +26 -0
  234. package/dist/core/graph/events.js +7 -0
  235. package/dist/core/graph/exposures.d.ts +53 -0
  236. package/dist/core/graph/exposures.js +4 -0
  237. package/dist/core/graph/jobs.d.ts +31 -0
  238. package/dist/core/graph/jobs.js +2 -0
  239. package/dist/core/graph/names.d.ts +30 -0
  240. package/dist/core/graph/names.js +3 -0
  241. package/dist/core/graph/objects.d.ts +55 -0
  242. package/dist/core/graph/objects.js +9 -0
  243. package/dist/core/graph/package-docs.d.ts +31 -0
  244. package/dist/core/graph/package-docs.js +5 -0
  245. package/dist/core/graph/package-files.d.ts +20 -0
  246. package/dist/core/graph/package-files.js +2 -0
  247. package/dist/core/graph/reader.d.ts +21 -0
  248. package/dist/core/graph/reader.js +3 -0
  249. package/dist/core/graph/repo-sync/exchange.d.ts +34 -0
  250. package/dist/core/graph/repo-sync/exchange.js +2 -0
  251. package/dist/core/graph/repo-sync/identity.d.ts +30 -0
  252. package/dist/core/graph/repo-sync/identity.js +1 -0
  253. package/dist/core/graph/repo-sync/index.d.ts +4 -0
  254. package/dist/core/graph/repo-sync/index.js +1 -0
  255. package/dist/core/graph/repo-sync/mirror.d.ts +30 -0
  256. package/dist/core/graph/repo-sync/mirror.js +6 -0
  257. package/dist/core/graph/repo-sync/ref-format.d.ts +76 -0
  258. package/dist/core/graph/repo-sync/ref-format.js +2 -0
  259. package/dist/core/graph/repo-sync/repos.d.ts +17 -0
  260. package/dist/core/graph/repo-sync/repos.js +3 -0
  261. package/dist/core/graph/repo-sync/sync.d.ts +42 -0
  262. package/dist/core/graph/repo-sync/sync.js +2 -0
  263. package/dist/core/graph/rules.d.ts +26 -0
  264. package/dist/core/graph/rules.js +3 -0
  265. package/dist/core/graph/spaces/app.d.ts +3 -0
  266. package/dist/core/graph/spaces/app.js +1 -0
  267. package/dist/core/graph/spaces/index.d.ts +19 -0
  268. package/dist/core/graph/spaces/index.js +1 -0
  269. package/dist/core/graph/spaces/person.d.ts +5 -0
  270. package/dist/core/graph/spaces/person.js +2 -0
  271. package/dist/core/graph/spaces/repo.d.ts +4 -0
  272. package/dist/core/graph/spaces/repo.js +1 -0
  273. package/dist/core/graph/types.d.ts +75 -0
  274. package/dist/core/graph/types.js +1 -0
  275. package/dist/core/graph/watches.d.ts +62 -0
  276. package/dist/core/graph/watches.js +18 -0
  277. package/dist/core/human/feedback-companion.js +1 -1
  278. package/dist/core/human/requests.d.ts +3 -1
  279. package/dist/core/human/requests.js +6 -6
  280. package/dist/core/inspector/model.js +2 -2
  281. package/dist/core/io.js +5 -5
  282. package/dist/core/layout-migrate/index.d.ts +24 -1
  283. package/dist/core/layout-migrate/index.js +4 -4
  284. package/dist/core/layout-migrate/paths.d.ts +4 -0
  285. package/dist/core/layout-migrate/paths.js +1 -1
  286. package/dist/core/layout-migrate/stored-paths.d.ts +7 -0
  287. package/dist/core/layout-migrate/stored-paths.js +11 -11
  288. package/dist/core/layout-migrate/stores.d.ts +19 -6
  289. package/dist/core/layout-migrate/stores.js +3 -4
  290. package/dist/core/manifest.d.ts +0 -2
  291. package/dist/core/manifest.js +1 -1
  292. package/dist/core/{memory/extensions.d.ts → plugin-extensions.d.ts} +9 -10
  293. package/dist/core/plugin-extensions.js +1 -0
  294. package/dist/core/preview-registry.d.ts +1 -1
  295. package/dist/core/preview-registry.js +3 -2
  296. package/dist/core/profiles/manifest.d.ts +7 -7
  297. package/dist/core/profiles/manifest.js +1 -1
  298. package/dist/core/profiles/select.js +3 -3
  299. package/dist/core/review/birth.js +1 -1
  300. package/dist/core/review/companion.js +1 -1
  301. package/dist/core/review/stage.d.ts +12 -1
  302. package/dist/core/review/stage.js +1 -1
  303. package/dist/core/review/store.d.ts +2 -0
  304. package/dist/core/review/store.js +1 -1
  305. package/dist/core/review/types.d.ts +7 -1
  306. package/dist/core/runs/events.js +1 -1
  307. package/dist/core/runs/operations.js +5 -5
  308. package/dist/core/runs/questions.js +2 -2
  309. package/dist/core/runtime/bearings-render.d.ts +13 -7
  310. package/dist/core/runtime/bearings-render.js +12 -12
  311. package/dist/core/runtime/bearings.d.ts +8 -18
  312. package/dist/core/runtime/bearings.js +7 -7
  313. package/dist/core/runtime/broker/daemon-ops.d.ts +7 -12
  314. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  315. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  316. package/dist/core/runtime/broker/fault-retry.js +1 -1
  317. package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
  318. package/dist/core/runtime/broker/frame-memory-refs.d.ts +7 -2
  319. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  320. package/dist/core/runtime/broker/inbox.d.ts +1 -4
  321. package/dist/core/runtime/broker/inbox.js +1 -10
  322. package/dist/core/runtime/broker/rebind.js +1 -1
  323. package/dist/core/runtime/broker/retry-card-elision.d.ts +7 -0
  324. package/dist/core/runtime/broker/retry-card-elision.js +1 -0
  325. package/dist/core/runtime/broker-extension-render.d.ts +0 -13
  326. package/dist/core/runtime/broker-extension-render.js +2 -4
  327. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  328. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  329. package/dist/core/runtime/broker.js +1 -1
  330. package/dist/core/runtime/close.d.ts +9 -4
  331. package/dist/core/runtime/close.js +1 -1
  332. package/dist/core/runtime/deliver-live.js +1 -1
  333. package/dist/core/runtime/kickoff.js +17 -19
  334. package/dist/core/runtime/launch-target.d.ts +7 -0
  335. package/dist/core/runtime/launch-target.js +1 -1
  336. package/dist/core/runtime/ledger.d.ts +10 -0
  337. package/dist/core/runtime/ledger.js +3 -0
  338. package/dist/core/runtime/lifecycle.js +2 -2
  339. package/dist/core/runtime/nodes.d.ts +10 -2
  340. package/dist/core/runtime/nodes.js +1 -1
  341. package/dist/core/runtime/outcome-document.d.ts +2 -2
  342. package/dist/core/runtime/outcome-document.js +1 -1
  343. package/dist/core/runtime/persona.js +2 -2
  344. package/dist/core/runtime/placement.js +1 -1
  345. package/dist/core/runtime/promote.d.ts +2 -2
  346. package/dist/core/runtime/promote.js +1 -1
  347. package/dist/core/runtime/prospective-inventory-cli.js +2 -2
  348. package/dist/core/runtime/recycle.js +1 -1
  349. package/dist/core/runtime/reopen.js +1 -1
  350. package/dist/core/runtime/revive.js +2 -2
  351. package/dist/core/runtime/roadmap.d.ts +20 -9
  352. package/dist/core/runtime/roadmap.js +10 -6
  353. package/dist/core/runtime/spawn-env.js +1 -1
  354. package/dist/core/runtime/spawn.d.ts +5 -3
  355. package/dist/core/runtime/spawn.js +2 -2
  356. package/dist/core/runtime/structured-output.d.ts +3 -1
  357. package/dist/core/runtime/structured-output.js +4 -4
  358. package/dist/core/scope.d.ts +1 -32
  359. package/dist/core/scope.js +1 -1
  360. package/dist/core/scoped-state/db.js +2 -1
  361. package/dist/core/scoped-state/migrate.js +2 -2
  362. package/dist/core/scoped-state/profiles.d.ts +11 -0
  363. package/dist/core/scoped-state/profiles.js +1 -1
  364. package/dist/core/scoped-state/schema.d.ts +1 -1
  365. package/dist/core/scoped-state/schema.js +7 -5
  366. package/dist/core/spaces/permissions.d.ts +0 -14
  367. package/dist/core/spaces/permissions.js +1 -1
  368. package/dist/core/spaces/stop.d.ts +13 -0
  369. package/dist/core/spaces/stop.js +2 -2
  370. package/dist/core/storage/tables.d.ts +1 -1
  371. package/dist/core/substrate/delivery/corpus.d.ts +21 -0
  372. package/dist/core/substrate/delivery/corpus.js +3 -0
  373. package/dist/core/substrate/delivery/deliver.d.ts +76 -0
  374. package/dist/core/substrate/delivery/deliver.js +6 -0
  375. package/dist/core/substrate/delivery/listings.d.ts +30 -0
  376. package/dist/core/substrate/delivery/listings.js +7 -0
  377. package/dist/core/substrate/delivery/match.d.ts +28 -0
  378. package/dist/core/substrate/delivery/match.js +1 -0
  379. package/dist/core/substrate/delivery/plan.d.ts +67 -0
  380. package/dist/core/substrate/delivery/plan.js +3 -0
  381. package/dist/core/substrate/delivery/render-boot.d.ts +20 -0
  382. package/dist/core/substrate/delivery/render-boot.js +54 -0
  383. package/dist/core/substrate/delivery/render-event.d.ts +54 -0
  384. package/dist/core/substrate/delivery/render-event.js +8 -0
  385. package/dist/core/substrate/delivery/sub-persona-menu.d.ts +2 -0
  386. package/dist/core/substrate/delivery/sub-persona-menu.js +6 -0
  387. package/dist/core/substrate/delivery/types.d.ts +30 -0
  388. package/dist/core/substrate/delivery/types.js +0 -0
  389. package/dist/core/substrate/gate-explain.d.ts +0 -13
  390. package/dist/core/substrate/gate-explain.js +1 -1
  391. package/dist/core/substrate/schema.d.ts +11 -139
  392. package/dist/core/substrate/schema.js +1 -1
  393. package/dist/core/substrate/subject-fields.d.ts +3 -0
  394. package/dist/core/substrate/subject.d.ts +2 -1
  395. package/dist/core/substrate/subject.js +1 -1
  396. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  397. package/dist/daemon/api/handlers/bash-jobs.js +1 -2
  398. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  399. package/dist/daemon/api/handlers/canvas.js +5 -5
  400. package/dist/daemon/api/handlers/daemon.js +1 -1
  401. package/dist/daemon/api/handlers/delivery.d.ts +2 -0
  402. package/dist/daemon/api/handlers/delivery.js +1 -0
  403. package/dist/daemon/api/handlers/{memory.d.ts → docs.d.ts} +1 -1
  404. package/dist/daemon/api/handlers/docs.js +1 -0
  405. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  406. package/dist/daemon/api/handlers/messages.js +2 -2
  407. package/dist/daemon/api/handlers/node-records.js +2 -2
  408. package/dist/daemon/api/handlers/nodes.js +1 -1
  409. package/dist/daemon/api/handlers/objects.d.ts +2 -0
  410. package/dist/daemon/api/handlers/objects.js +5 -0
  411. package/dist/daemon/api/handlers/package-docs.d.ts +2 -0
  412. package/dist/daemon/api/handlers/package-docs.js +1 -0
  413. package/dist/daemon/api/handlers/profiles.js +1 -1
  414. package/dist/daemon/api/handlers/reports.d.ts +2 -2
  415. package/dist/daemon/api/handlers/reports.js +4 -4
  416. package/dist/daemon/api/handlers/reviews.d.ts +4 -1
  417. package/dist/daemon/api/handlers/reviews.js +1 -1
  418. package/dist/daemon/api/map.d.ts +2 -2
  419. package/dist/daemon/api/map.js +2 -2
  420. package/dist/daemon/api/operations.d.ts +1 -1
  421. package/dist/daemon/api/operations.js +1 -1
  422. package/dist/daemon/api/reader.d.ts +17 -0
  423. package/dist/daemon/api/reader.js +1 -0
  424. package/dist/daemon/api/server.js +1 -1
  425. package/dist/daemon/control.d.ts +2 -3
  426. package/dist/daemon/crtrd.js +8 -6
  427. package/dist/daemon/fleet.js +4 -4
  428. package/dist/daemon/reconcilers/bash-deadline.d.ts +11 -1
  429. package/dist/daemon/reconcilers/bash-deadline.js +2 -1
  430. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  431. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  432. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  433. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  434. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -0
  435. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  436. package/dist/daemon/review/deliver.js +2 -2
  437. package/dist/daemon/review/finish.js +1 -1
  438. package/dist/hook-authoring.d.ts +0 -1
  439. package/dist/hook-authoring.js +3 -3
  440. package/dist/migrations/004-canvas-documents/apply.d.ts +10 -0
  441. package/dist/migrations/004-canvas-documents/apply.js +1 -0
  442. package/dist/migrations/004-canvas-documents/fields.d.ts +24 -0
  443. package/dist/migrations/004-canvas-documents/fields.js +2 -0
  444. package/dist/migrations/004-canvas-documents/index.d.ts +16 -0
  445. package/dist/migrations/004-canvas-documents/index.js +2 -0
  446. package/dist/migrations/004-canvas-documents/legacy/discover.d.ts +16 -0
  447. package/dist/migrations/004-canvas-documents/legacy/discover.js +1 -0
  448. package/dist/migrations/004-canvas-documents/legacy/history.d.ts +5 -0
  449. package/dist/migrations/004-canvas-documents/legacy/history.js +2 -0
  450. package/dist/migrations/004-canvas-documents/legacy/nested.d.ts +7 -0
  451. package/dist/migrations/004-canvas-documents/legacy/nested.js +1 -0
  452. package/dist/migrations/004-canvas-documents/legacy/parse.d.ts +14 -0
  453. package/dist/migrations/004-canvas-documents/legacy/parse.js +1 -0
  454. package/dist/migrations/004-canvas-documents/legacy/types.d.ts +91 -0
  455. package/dist/migrations/004-canvas-documents/legacy/types.js +0 -0
  456. package/dist/migrations/004-canvas-documents/legacy-edges.d.ts +6 -0
  457. package/dist/migrations/004-canvas-documents/legacy-edges.js +18 -0
  458. package/dist/migrations/004-canvas-documents/plan.d.ts +102 -0
  459. package/dist/migrations/004-canvas-documents/plan.js +3 -0
  460. package/dist/migrations/004-canvas-documents/pointers.d.ts +23 -0
  461. package/dist/migrations/004-canvas-documents/pointers.js +4 -0
  462. package/dist/migrations/activation.d.ts +9 -18
  463. package/dist/migrations/activation.js +2 -2
  464. package/dist/pi-extensions/broker-local.d.ts +2 -2
  465. package/dist/pi-extensions/broker-local.js +2 -2
  466. package/dist/pi-extensions/canvas-bash-valve.js +5 -4
  467. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  468. package/dist/pi-extensions/canvas-doc-substrate.d.ts +0 -1
  469. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  470. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  471. package/dist/pi-extensions/canvas-passive-context.js +1 -1
  472. package/dist/pi-extensions/canvas-recap.js +2 -2
  473. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  474. package/dist/pi-extensions/canvas-stophook.js +1 -1
  475. package/dist/prompts/review.js +3 -3
  476. package/dist/shared/env.d.ts +5 -0
  477. package/dist/shared/env.js +1 -1
  478. package/dist/shared/generated-context.js +2 -10
  479. package/dist/shared/inbox-entry-body.d.ts +22 -0
  480. package/dist/shared/inbox-entry-body.js +10 -0
  481. package/dist/{core/memory → shared}/inline-ref-guidance.d.ts +2 -2
  482. package/dist/shared/inline-ref-guidance.js +2 -0
  483. package/dist/types.d.ts +3 -1
  484. package/docs/cli/memory-and-preferences.md +12 -14
  485. package/docs/concepts/README.md +1 -1
  486. package/docs/concepts/lifecycle-and-wakes.md +1 -1
  487. package/docs/concepts/memory.md +15 -15
  488. package/docs/concepts/nodes-and-the-canvas.md +1 -1
  489. package/docs/concepts/profiles-kinds-and-modes.md +5 -5
  490. package/docs/concepts/scopes-and-trust.md +1 -1
  491. package/docs/concepts/why-a-daemon.md +1 -1
  492. package/docs/sdk/README.md +5 -6
  493. package/docs/sdk/errors.md +0 -13
  494. package/docs/sdk/guides/README.md +0 -1
  495. package/docs/sdk/nodes.md +0 -2
  496. package/docs/sdk/resources.md +0 -1
  497. package/package.json +2 -2
  498. package/packages/crouter-identity/package.json +1 -1
  499. package/runtime.lock.json +11 -11
  500. package/scripts/lib/isolation-env.mjs +8 -2
  501. package/dist/api/dto/memory.d.ts +0 -171
  502. package/dist/api/dto/memory.js +0 -1
  503. package/dist/builtin-memory/crouter-sdk/guides/app-memory.md +0 -73
  504. package/dist/builtin-memory/crouter-sdk/memory.md +0 -87
  505. package/dist/commands/broker-permissions.d.ts +0 -2
  506. package/dist/commands/broker-permissions.js +0 -1
  507. package/dist/commands/memory/client.d.ts +0 -11
  508. package/dist/commands/memory/client.js +0 -1
  509. package/dist/commands/memory/delete.d.ts +0 -1
  510. package/dist/commands/memory/delete.js +0 -1
  511. package/dist/commands/memory/edit.d.ts +0 -1
  512. package/dist/commands/memory/edit.js +0 -21
  513. package/dist/commands/memory/find.d.ts +0 -1
  514. package/dist/commands/memory/find.js +0 -1
  515. package/dist/commands/memory/history.d.ts +0 -1
  516. package/dist/commands/memory/history.js +0 -5
  517. package/dist/commands/memory/lint.d.ts +0 -1
  518. package/dist/commands/memory/lint.js +0 -1
  519. package/dist/commands/memory/list.d.ts +0 -1
  520. package/dist/commands/memory/list.js +0 -1
  521. package/dist/commands/memory/move.d.ts +0 -1
  522. package/dist/commands/memory/move.js +0 -1
  523. package/dist/commands/memory/origin.d.ts +0 -1
  524. package/dist/commands/memory/origin.js +0 -1
  525. package/dist/commands/memory/read.d.ts +0 -1
  526. package/dist/commands/memory/read.js +0 -6
  527. package/dist/commands/memory/shared.d.ts +0 -22
  528. package/dist/commands/memory/shared.js +0 -1
  529. package/dist/commands/memory/write.d.ts +0 -1
  530. package/dist/commands/memory/write.js +0 -13
  531. package/dist/commands/memory.js +0 -1
  532. package/dist/commands/node-inspect-artifacts.d.ts +0 -1
  533. package/dist/commands/node-inspect-artifacts.js +0 -8
  534. package/dist/core/help/memory-extensions.d.ts +0 -3
  535. package/dist/core/help/memory-extensions.js +0 -2
  536. package/dist/core/memory/cli-selector.d.ts +0 -13
  537. package/dist/core/memory/cli-selector.js +0 -1
  538. package/dist/core/memory/doc-link-grammar.d.ts +0 -20
  539. package/dist/core/memory/doc-link-grammar.js +0 -2
  540. package/dist/core/memory/extensions.js +0 -1
  541. package/dist/core/memory/history.d.ts +0 -87
  542. package/dist/core/memory/history.js +0 -6
  543. package/dist/core/memory/identity.d.ts +0 -65
  544. package/dist/core/memory/identity.js +0 -1
  545. package/dist/core/memory/inline-ref-guidance.js +0 -2
  546. package/dist/core/memory/inline-ref-inventory.d.ts +0 -9
  547. package/dist/core/memory/inline-ref-inventory.js +0 -1
  548. package/dist/core/memory/lint.d.ts +0 -163
  549. package/dist/core/memory/lint.js +0 -2
  550. package/dist/core/memory/mutation-domain.d.ts +0 -113
  551. package/dist/core/memory/mutation-domain.js +0 -12
  552. package/dist/core/memory/mutations.d.ts +0 -74
  553. package/dist/core/memory/mutations.js +0 -1
  554. package/dist/core/memory/project-namespace.d.ts +0 -31
  555. package/dist/core/memory/project-namespace.js +0 -2
  556. package/dist/core/memory/repository-association.d.ts +0 -31
  557. package/dist/core/memory/repository-association.js +0 -1
  558. package/dist/core/memory/service.d.ts +0 -145
  559. package/dist/core/memory/service.js +0 -2
  560. package/dist/core/memory/tree.d.ts +0 -39
  561. package/dist/core/memory/tree.js +0 -1
  562. package/dist/core/memory-resolver.d.ts +0 -280
  563. package/dist/core/memory-resolver.js +0 -2
  564. package/dist/core/nested-stores.d.ts +0 -18
  565. package/dist/core/nested-stores.js +0 -1
  566. package/dist/core/runtime/memory.d.ts +0 -3
  567. package/dist/core/runtime/memory.js +0 -1
  568. package/dist/core/substrate/frontmatter-validation.d.ts +0 -11
  569. package/dist/core/substrate/frontmatter-validation.js +0 -1
  570. package/dist/core/substrate/gate.d.ts +0 -16
  571. package/dist/core/substrate/gate.js +0 -1
  572. package/dist/core/substrate/index.d.ts +0 -18
  573. package/dist/core/substrate/index.js +0 -1
  574. package/dist/core/substrate/injected-store.d.ts +0 -75
  575. package/dist/core/substrate/injected-store.js +0 -2
  576. package/dist/core/substrate/listings.d.ts +0 -28
  577. package/dist/core/substrate/listings.js +0 -1
  578. package/dist/core/substrate/memory-events.d.ts +0 -6
  579. package/dist/core/substrate/memory-events.js +0 -1
  580. package/dist/core/substrate/on-read-node.d.ts +0 -6
  581. package/dist/core/substrate/on-read-node.js +0 -1
  582. package/dist/core/substrate/on-read.d.ts +0 -101
  583. package/dist/core/substrate/on-read.js +0 -9
  584. package/dist/core/substrate/plan.d.ts +0 -94
  585. package/dist/core/substrate/plan.js +0 -1
  586. package/dist/core/substrate/render-node.d.ts +0 -12
  587. package/dist/core/substrate/render-node.js +0 -1
  588. package/dist/core/substrate/render.d.ts +0 -41
  589. package/dist/core/substrate/render.js +0 -65
  590. package/dist/core/substrate/session-cache.d.ts +0 -27
  591. package/dist/core/substrate/session-cache.js +0 -1
  592. package/dist/core/substrate/surface-match.d.ts +0 -73
  593. package/dist/core/substrate/surface-match.js +0 -1
  594. package/dist/daemon/api/handlers/memory.js +0 -5
  595. package/dist/migrations/001-surfaces-frontmatter.d.ts +0 -2
  596. package/dist/migrations/001-surfaces-frontmatter.js +0 -1
  597. package/dist/migrations/002-profile-project-memory.d.ts +0 -2
  598. package/dist/migrations/002-profile-project-memory.js +0 -1
  599. package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +0 -26
  600. package/dist/migrations/003-repository-root-memory-identity/front-door.js +0 -11
  601. package/dist/migrations/003-repository-root-memory-identity/index.d.ts +0 -2
  602. package/dist/migrations/003-repository-root-memory-identity/index.js +0 -5
  603. package/dist/migrations/003-repository-root-memory-identity/references.d.ts +0 -95
  604. package/dist/migrations/003-repository-root-memory-identity/references.js +0 -5
  605. package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +0 -39
  606. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +0 -3
  607. package/dist/migrations/convergent.d.ts +0 -43
  608. package/dist/migrations/convergent.js +0 -2
  609. package/dist/migrations/corpus.d.ts +0 -75
  610. package/dist/migrations/corpus.js +0 -3
  611. package/dist/migrations/frontmatter-splice.d.ts +0 -15
  612. package/dist/migrations/frontmatter-splice.js +0 -8
  613. package/dist/migrations/profile-manifests.d.ts +0 -30
  614. package/dist/migrations/profile-manifests.js +0 -2
  615. package/dist/migrations/registry.d.ts +0 -7
  616. package/dist/migrations/registry.js +0 -1
  617. package/dist/migrations/runner.d.ts +0 -43
  618. package/dist/migrations/runner.js +0 -1
  619. package/dist/migrations/types.d.ts +0 -211
  620. package/dist/shared/birth-announcement.d.ts +0 -12
  621. package/dist/shared/birth-announcement.js +0 -1
  622. package/docs/sdk/guides/app-memory.md +0 -22
  623. package/docs/sdk/memory.md +0 -85
  624. /package/dist/{migrations/types.js → api/dto/delivery.js} +0 -0
  625. /package/dist/{core/memory → shared}/inline-ref-grammar.d.ts +0 -0
  626. /package/dist/{core/memory → shared}/inline-ref-grammar.js +0 -0
@@ -1,4 +1,4 @@
1
- var U=Object.defineProperty;var p=(r,e)=>U(r,"name",{value:e,configurable:!0});import{DatabaseSync as D}from"node:sqlite";import{randomUUID as x}from"node:crypto";import{chmodSync as T,chownSync as A,closeSync as b,cpSync as C,existsSync as d,fsyncSync as L,lchownSync as R,lstatSync as m,mkdirSync as E,openSync as S,readFileSync as v,readlinkSync as P,readSync as j,readdirSync as h,renameSync as k,rmSync as I,rmdirSync as $,unlinkSync as W,writeSync as F}from"node:fs";import{request as z}from"node:http";import{dirname as w,join as s}from"node:path";import{LAYOUT_VERSION as M}from"../layout.js";import{InputError as _}from"../io.js";import{oldToNewPathMap as B}from"./paths.js";import{conversations as G,memoryAndProfiles as H,profileFolders as Q,repairMovedRepositories as V,worktrees as Y}from"./stores.js";import{storedPaths as J}from"./stored-paths.js";import{OldToNewPathMap as ge,oldToNewPathMap as ve}from"./paths.js";function y(r,e,n){if(d(r)&&r!==e){if(d(e)){if(!m(r).isDirectory()||!m(e).isDirectory())throw new Error(`migration destination already exists: ${e}`);for(const t of h(r))y(s(r,t),s(e,t),n);$(r);return}E(w(e),{recursive:!0}),k(r,e),n.moved++,n.changes.push(`${r} -> ${e}`)}}p(y,"movePath");function K(r){const{map:e}=r,n=s(e.old.canvas,"nodes"),t=s(e.old.canvas,"canvas.db"),c=s(e.old.root,"runtime","canvas.db"),a=d(t)?t:c;if(!d(a)){if(d(n))throw new Error("old node records exist without canvas.db");return}const i=new D(a,{readOnly:!d(t)});let l;try{if(a===t&&i.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get().busy!==0)throw new Error("old canvas WAL is busy; stop every database user before migrating");l=new Map(i.prepare("SELECT node_id, grantee FROM nodes").all().map(o=>{const f=o.grantee==="user:local"?"terminal":o.grantee.startsWith("app:")?o.grantee.slice(4):"";if(!f)throw new Error(`node ${o.node_id} has no app assignment`);return[o.node_id,f]}))}finally{i.close()}for(const[o,f]of l)e.node(o,f);if(d(n)){for(const o of h(n)){const f=l.get(o);if(!f)throw new Error(`node directory ${o} has no canvas row`);const u=s(n,o);if(!m(u).isDirectory())throw new Error(`node path is not a directory: ${u}`);for(const g of["context","reports","attachments"])y(s(u,g),s(e.old.root,"apps",f,"nodes",o,g),r);for(const g of h(u))["worktree","view.sock","broker-launch.json","system-prompt.md","situational-context.md","injected-docs.json"].includes(g)||y(s(u,g),s(e.old.root,"runtime","nodes",o,g),r);h(u).length===0&&$(u)}h(n).length===0&&$(n)}}p(K,"records");const q=["auth.json","anthropic-credentials.json","openai-codex-credentials.json","crouter-operations.db"];function X(r,e,n){if(!d(r))return;if(!m(r).isFile())throw new Error(`credential source is not a regular file: ${r}`);const t=v(r);if(d(e)){if(!m(e).isFile()||!v(e).equals(t))throw new Error(`credential destination differs: ${e}`);return}E(w(e),{recursive:!0});const c=s(w(e),`.${x()}.tmp`);try{const a=S(c,"wx",384);try{for(let i=0;i<t.length;)i+=F(a,t,i,t.length-i);L(a)}finally{b(a)}if(k(c,e),!v(e).equals(t))throw new Error(`credential verification failed: ${e}`)}finally{d(c)&&W(c)}n.moved++,n.changes.push(`${r} -> ${e} (source retained)`)}p(X,"copyCredential");function O(r){if(!d(r))return;const e=new D(r);try{if(e.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get().busy!==0)throw new Error(`SQLite WAL is busy: ${r}`)}finally{e.close()}}p(O,"checkpointDb");function Z(r,e){if(m(r).size!==m(e).size)return!1;const n=S(r,"r"),t=S(e,"r"),c=Buffer.allocUnsafe(64*1024),a=Buffer.allocUnsafe(c.length);try{for(;;){const i=j(n,c,0,c.length,null);if(i===0)return!0;let l=0;for(;l<i;){const o=j(t,a,l,i-l,null);if(o===0)return!1;l+=o}if(!c.subarray(0,i).equals(a.subarray(0,i)))return!1}}finally{b(n),b(t)}}p(Z,"sameFile");function N(r,e,n=!1){let t;try{t=m(e)}catch(o){if(o.code==="ENOENT")return!1;throw o}const c=m(r);if(c.isSymbolicLink())return t.isSymbolicLink()&&P(r)===P(e);if(c.isFile())return t.isFile()&&Z(r,e);if(!c.isDirectory()||!t.isDirectory())return!1;const a=h(r).filter(o=>!n||o!==".git"),i=h(e).filter(o=>!n||o!==".git"),l=new Set(i);return a.length===i.length&&a.every(o=>l.has(o)&&N(s(r,o),s(e,o),n))}p(N,"sameTree");function ee(r,e,n){if(!d(r))return;if(!m(r).isDirectory())throw new Error(`hosted work is not a directory: ${r}`);if(d(e)){if(N(r,e,!0))return;if(!m(e).isDirectory()||h(e).length!==0)throw new Error(`hosted work destination differs: ${e}`);$(e)}E(w(e),{recursive:!0});const t=s(w(e),`.work-${x()}.migrating`);try{if(C(r,t,{recursive:!0,verbatimSymlinks:!0,preserveTimestamps:!0}),!N(r,t))throw new Error(`hosted work copy verification failed: ${r}`);k(t,e),n.moved++,n.changes.push(`${r} -> ${e} (source retained)`)}finally{d(t)&&I(t,{recursive:!0,force:!0})}}p(ee,"copyHostedWork");function re(r){const{old:e}=r.map,n=s(e.root,"runtime"),t=s(n,"scope");for(const c of["canvas.db","canvas.db-wal","canvas.db-shm","requests","reviews","plugins","marketplaces","crtrd.log","crtrd.err","cache"])y(s(e.canvas,c),s(n,c),r);O(s(e.scope,"operations.db"));for(const c of["prompts","personas","config.json","profile-defaults.json","operations.db","operations.db-wal","operations.db-shm"])y(s(e.scope,c),s(t,c),r);for(const c of["support","prompt-reviews","plugins","marketplaces"])y(s(e.scope,c),s(n,c),r);y(s(e.canvas,"secrets"),s(n,"secrets"),r),O(s(e.agent,"crouter-operations.db"));for(const c of q)X(s(e.agent,c),s(n,"secrets",c),r);process.platform==="linux"&&ee(e.work,s(e.root,"user","files"),r)}p(re,"topLevel");function ne(r){if(process.platform!=="linux")return;if(process.getuid?.()!==0)throw new Error("Linux layout migration requires root for the ownership pass");const e=v("/etc/passwd","utf8").split(`
2
- `).find(i=>i.startsWith("crtrd:")),n=v("/etc/group","utf8").split(`
3
- `).find(i=>i.startsWith("nl-data:"));if(!e||!n)throw new Error("layout migration requires crtrd user and nl-data group");const t=Number(e.split(":")[2]),c=Number(n.split(":")[2]);if(!Number.isInteger(t)||!Number.isInteger(c))throw new Error("invalid migration user or group");const a=p((i,l)=>{if(!d(i))return;const o=m(i);if(o.isSymbolicLink()){R(i,t,l?c:o.gid);return}if(A(i,t,l?c:o.gid),o.isDirectory()){T(i,l?1528:448);for(const f of h(i))a(s(i,f),l)}else l&&T(i,o.mode&73?504:432)},"walk");a(s(r,"runtime"),!1),a(s(r,"user"),!0),a(s(r,"apps"),!0)}p(ne,"ownership");function te(r){return new Promise(e=>{const n=z({socketPath:r,path:"/healthz",method:"GET",timeout:1e3},t=>{t.resume(),e(!0)});n.on("timeout",()=>n.destroy(new Error("daemon probe timed out"))),n.on("error",t=>{t.code==="ENOENT"||t.code==="ECONNREFUSED"?e(!1):e(!0)}),n.end()})}p(te,"daemonAnswers");async function he(r){const e=B(),n=e.old,t=s(n.root,"runtime","layout");if(d(t)){if(v(t,"utf8").trim()!==M)throw new Error("unsupported runtime layout version");return null}const c=new Set([s(n.canvas,"crtrd.sock"),s(n.scope,"crtrd.sock"),process.platform==="linux"?"/run/crtr/api.sock":s(n.root,"runtime","api.sock")]);for(const u of c)if(await te(u))throw new _({error:"daemon_running",message:`cannot migrate while a daemon answers on ${u}`,next:"Stop the daemon that owns this volume, then run `crtr sys migrate` again."});if(Q(e),process.platform==="linux"&&!d(n.agent))throw new _({error:"credential_volume_missing",message:`the old credential volume is not mounted at ${n.agent}`,next:`Mount the old provider-auth volume at ${n.agent}, then run \`crtr sys migrate\` again.`});const a=q.map(u=>s(n.agent,u)).filter(u=>!d(u)),i={map:e,moved:0,changes:[],absentCredentials:a};if(r)return i;const l=[K,Y,re,V,H,G,J];for(const u of l)u(i);ne(n.root),E(w(t),{recursive:!0});const o=`${t}.${x()}.tmp`,f=S(o,"wx",384);try{if(process.platform==="linux"){const u=m(w(t));A(o,u.uid,u.gid)}F(f,`${M}
4
- `),L(f)}finally{b(f)}return k(o,t),i}p(he,"migrateLayout");export{ge as OldToNewPathMap,te as daemonAnswers,he as migrateLayout,y as movePath,ve as oldToNewPathMap,Z as sameFile};
1
+ var X=Object.defineProperty;var l=(t,e)=>X(t,"name",{value:e,configurable:!0});import{DatabaseSync as _}from"node:sqlite";import{randomUUID as N}from"node:crypto";import{symlinkSync as Z,chmodSync as M,chownSync as j,closeSync as $,cpSync as ee,existsSync as d,fsyncSync as R,lchownSync as te,lstatSync as f,mkdirSync as w,openSync as k,readFileSync as y,readlinkSync as D,readSync as U,readdirSync as h,renameSync as b,rmSync as L,rmdirSync as g,unlinkSync as A,writeSync as q}from"node:fs";import{request as ne}from"node:http";import{basename as T,dirname as m,isAbsolute as re,join as c,relative as S,resolve as oe}from"node:path";import{LAYOUT_VERSION as C}from"../layout.js";import{InputError as O}from"../io.js";import{oldToNewPathMap as se}from"./paths.js";import{conversations as ie,memoryAndProfiles as ce,previewStores as ae,profileFolders as ue,repairMovedRepositories as le,worktrees as de}from"./stores.js";import{storedPaths as fe}from"./stored-paths.js";import{OldToNewPathMap as Ce,oldToNewPathMap as Oe}from"./paths.js";const pe=new Set([".DS_Store","Thumbs.db","desktop.ini"]);function he(t){return pe.has(t)||t.startsWith("._")}l(he,"isJunkFile");function F(t,e,n){const o=c(t.map.old.root,"runtime","set-aside",e);let r=c(o,n);for(let i=2;d(r);i++)r=c(o,`${n}.${i}`);return r}l(F,"setAsidePath");function I(t,e,n,o=T(t)){const r=F(n,e,o);return w(m(r),{recursive:!0}),b(t,r),n.moved++,n.changes.push(`${t} -> ${r} (set aside)`),r}l(I,"setAside");function me(t){const e=f(t);return e.isDirectory()?h(t).length===0:e.isFile()&&e.size===0}l(me,"empty");function W(t,e,n,o=!1){const r=f(t),i=f(e);if(r.isDirectory()&&i.isDirectory()&&!o)return{action:"merge"};if(r.isFile()&&i.isFile()&&Q(t,e))return{action:"drop-source"};if(me(e))return{action:"remove-destination",line:`stray-destination: removed empty ${i.isDirectory()?"folder":"file"} ${e} that predates the migration`};const s=F(n,"replaced",S(n.map.old.root,e));return{action:"set-aside-destination",line:`stray-destination: ${e} predates the migration; moved it to ${s} and put ${t} in its place`}}l(W,"claim");function E(t,e,n,o=!1){if(d(t)&&t!==e){if(d(e)){const r=W(t,e,n,o);if(r.line&&n.resolutions.push(r.line),r.action==="merge"){for(const i of h(t))E(c(t,i),c(e,i),n);g(t);return}if(r.action==="drop-source"){L(t,{recursive:!0}),n.changes.push(`${t} (identical to ${e}; removed)`);return}r.action==="remove-destination"?(L(e,{recursive:!0}),n.changes.push(`${e} (removed)`)):I(e,"replaced",n,S(n.map.old.root,e))}w(m(e),{recursive:!0}),b(t,e),n.moved++,n.changes.push(`${t} -> ${e}`)}}l(E,"movePath");function z(t,e,n,o=!1){if(!d(t)||t===e||!d(e))return;const r=W(t,e,n,o);if(r.line&&n.resolutions.push(r.line),r.action==="merge")for(const i of h(t))z(c(t,i),c(e,i),n)}l(z,"previewMove");function B(t){const{map:e}=t,n=c(e.old.canvas,"nodes"),o=c(e.old.canvas,"canvas.db"),r=c(e.old.root,"runtime","canvas.db"),i=d(o)?o:d(r)&&f(r).size>0?r:"";if(!i){if(d(n))throw new Error("old node records exist without canvas.db");return null}const s=new _(i,{readOnly:t.dryRun||i!==o});try{if(i===o&&!t.dryRun&&s.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get().busy!==0)throw new Error("old canvas WAL is busy; stop every database user before migrating");return new Map(s.prepare("SELECT node_id, grantee FROM nodes").all().map(a=>{const u=a.grantee==="user:local"?"terminal":a.grantee.startsWith("app:")?a.grantee.slice(4):"";if(!u)throw new Error(`node ${a.node_id} has no app assignment`);return[a.node_id,u]}))}finally{s.close()}}l(B,"canvasNodeApps");function J(t,e){const n=c(t.map.old.canvas,"nodes");if(!d(n))return[];const o=[];for(const r of h(n)){const i=c(n,r),s=f(i).isDirectory();e.has(r)&&s||o.push({path:i,remove:!s&&he(r)})}return o}l(J,"orphanNodeEntries");function G(t,e){return t.remove?`node-leftover: deleted ${t.path} (not a node record)`:`node-leftover: ${t.path} has no node row; moved to ${F(e,"nodes",T(t.path))}`}l(G,"orphanLine");function ye(t){const{map:e}=t,n=c(e.old.canvas,"nodes"),o=B(t);if(o){for(const[r,i]of o)e.node(r,i);if(d(n)){for(const r of J(t,o)){if(t.resolutions.push(G(r,t)),r.remove){A(r.path),t.changes.push(`${r.path} (removed)`);continue}const i=I(r.path,"nodes",t),s=c(e.old.targetRoot,S(e.old.root,i));for(const a of new Set([e.old.storedCanvas,e.old.storedScope,c(e.old.storedScope,"canvas")]))e.add(c(a,"nodes",T(r.path)),s)}for(const[r,i]of o){const s=c(n,r);if(d(s)){for(const a of["context","reports","attachments"])E(c(s,a),c(e.old.root,"apps",i,"nodes",r,a),t);for(const a of h(s))["worktree","view.sock","broker-launch.json","system-prompt.md","situational-context.md","injected-docs.json"].includes(a)||E(c(s,a),c(e.old.root,"runtime","nodes",r,a),t);h(s).length===0&&g(s)}}h(n).length===0&&g(n)}}}l(ye,"records");const H=["auth.json","anthropic-credentials.json","openai-codex-credentials.json","crouter-operations.db"];function ve(t,e,n){if(!d(t))return;if(!f(t).isFile())throw new Error(`credential source is not a regular file: ${t}`);const o=y(t);if(d(e)){(!f(e).isFile()||!y(e).equals(o))&&n.resolutions.push(`credential: kept the existing ${e}; the older ${t} differs and stays where it is`);return}w(m(e),{recursive:!0});const r=c(m(e),`.${N()}.tmp`);try{const i=k(r,"wx",384);try{for(let s=0;s<o.length;)s+=q(i,o,s,o.length-s);R(i)}finally{$(i)}if(b(r,e),!y(e).equals(o))throw new Error(`credential verification failed: ${e}`)}finally{d(r)&&A(r)}n.moved++,n.changes.push(`${t} -> ${e} (source retained)`)}l(ve,"copyCredential");function K(t){if(!d(t))return;const e=new _(t);try{if(e.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get().busy!==0)throw new Error(`SQLite WAL is busy: ${t}`)}finally{e.close()}}l(K,"checkpointDb");function Q(t,e){if(f(t).size!==f(e).size)return!1;const n=k(t,"r"),o=k(e,"r"),r=Buffer.allocUnsafe(64*1024),i=Buffer.allocUnsafe(r.length);try{for(;;){const s=U(n,r,0,r.length,null);if(s===0)return!0;let a=0;for(;a<s;){const u=U(o,i,a,s-a,null);if(u===0)return!1;a+=u}if(!r.subarray(0,s).equals(i.subarray(0,s)))return!1}}finally{$(n),$(o)}}l(Q,"sameFile");function P(t,e,n=!1){let o;try{o=f(e)}catch(u){if(u.code==="ENOENT")return!1;throw u}const r=f(t);if(r.isSymbolicLink())return o.isSymbolicLink()&&D(t)===D(e);if(r.isFile())return o.isFile()&&Q(t,e);if(!r.isDirectory()||!o.isDirectory())return!1;const i=h(t).filter(u=>!n||u!==".git"),s=h(e).filter(u=>!n||u!==".git"),a=new Set(s);return i.length===s.length&&i.every(u=>a.has(u)&&P(c(t,u),c(e,u),n))}l(P,"sameTree");function we(t,e,n){if(!d(t))return;if(!f(t).isDirectory())throw new Error(`hosted work is not a directory: ${t}`);if(d(e)){if(P(t,e,!0))return;if(!f(e).isDirectory()||h(e).length!==0){n.resolutions.push(`hosted-work: kept the existing ${e}; the old ${t} differs and stays where it is`);return}g(e)}w(m(e),{recursive:!0});const o=c(m(e),`.work-${N()}.migrating`);try{if(ee(t,o,{recursive:!0,verbatimSymlinks:!0,preserveTimestamps:!0}),!P(t,o))throw new Error(`hosted work copy verification failed: ${t}`);b(o,e),n.moved++,n.changes.push(`${t} -> ${e} (source retained)`)}finally{d(o)&&L(o,{recursive:!0,force:!0})}}l(we,"copyHostedWork");function V(t){const{old:e}=t.map,n=c(e.root,"runtime"),o=c(n,"scope"),r=[];for(const i of["canvas.db","canvas.db-wal","canvas.db-shm","on-disk-migrations.json","requests","reviews","plugins","marketplaces","crtrd.log","crtrd.err","cache"])r.push([c(e.canvas,i),c(n,i)]);for(const i of["prompts","personas","config.json","profile-defaults.json","operations.db","operations.db-wal","operations.db-shm"])r.push([c(e.scope,i),c(o,i)]);for(const i of["support","prompt-reviews","plugins","marketplaces"])r.push([c(e.scope,i),c(n,i)]);return r.push([c(e.canvas,"secrets"),c(n,"secrets")]),r}l(V,"topLevelMoves");function be(t){const{old:e}=t.map,n=c(e.root,"runtime");K(c(e.scope,"operations.db"));for(const[o,r]of V(t)){const i=ge(o);E(o,r,t,!0),$e(i,o,r,t)}K(c(e.agent,"crouter-operations.db"));for(const o of H)ve(c(e.agent,o),c(n,"secrets",o),t);process.platform==="linux"&&we(e.work,c(e.root,"user","files"),t)}l(be,"topLevel");function ge(t){if(!d(t)||!f(t).isDirectory())return[];const e=[];for(const n of h(t)){const o=c(t,n);if(!f(o).isSymbolicLink())continue;const r=D(o);re(r)||e.push({name:n,target:r})}return e}l(ge,"relativeLinks");function $e(t,e,n,o){if(!(t.length===0||!d(n)))for(const{name:r,target:i}of t){const s=c(n,r);if(!ke(s))continue;const a=o.map.mapPath(oe(e,i)),u=S(n,a);u!==i&&(A(s),Z(u,s),o.changes.push(`${s}: link ${i} -> ${u}`))}}l($e,"retargetLinks");function ke(t){try{return f(t),!0}catch{return!1}}l(ke,"lstatExists");function Se(t){if(process.platform!=="linux")return;if(process.getuid?.()!==0)throw new Error("Linux layout migration requires root for the ownership pass");const e=y("/etc/passwd","utf8").split(`
2
+ `).find(s=>s.startsWith("crtrd:")),n=y("/etc/group","utf8").split(`
3
+ `).find(s=>s.startsWith("nl-data:"));if(!e||!n)throw new Error("layout migration requires crtrd user and nl-data group");const o=Number(e.split(":")[2]),r=Number(n.split(":")[2]);if(!Number.isInteger(o)||!Number.isInteger(r))throw new Error("invalid migration user or group");const i=l((s,a)=>{if(!d(s))return;const u=f(s);if(u.isSymbolicLink()){te(s,o,a?r:u.gid);return}if(j(s,o,a?r:u.gid),u.isDirectory()){M(s,a?1528:448);for(const v of h(s))i(c(s,v),a)}else a&&M(s,u.mode&73?504:432)},"walk");i(c(t,"runtime"),!1),i(c(t,"user"),!0),i(c(t,"apps"),!0)}l(Se,"ownership");function Ee(t){return new Promise(e=>{const n=ne({socketPath:t,path:"/healthz",method:"GET",timeout:1e3},o=>{o.resume(),e(!0)});n.on("timeout",()=>n.destroy(new Error("daemon probe timed out"))),n.on("error",o=>{o.code==="ENOENT"||o.code==="ECONNREFUSED"?e(!1):e(!0)}),n.end()})}l(Ee,"daemonAnswers");async function Re(t){const e=se(),n=e.old,o=c(n.root,"runtime","layout");if(d(o)){if(y(o,"utf8").trim()!==C)throw new Error("unsupported runtime layout version");return null}const r=new Set([c(n.canvas,"crtrd.sock"),c(n.scope,"crtrd.sock"),process.platform==="linux"?"/run/crtr/api.sock":c(n.root,"runtime","api.sock")]);for(const p of r)if(await Ee(p))throw new O({error:"daemon_running",message:`cannot migrate while a daemon answers on ${p}`,next:"Stop the daemon that owns this volume, then run `crtr sys migrate` again."});if(process.platform==="linux"&&!d(n.agent))throw new O({error:"credential_volume_missing",message:`the old credential volume is not mounted at ${n.agent}`,next:`Mount the old provider-auth volume at ${n.agent}, then run \`crtr sys migrate\` again.`});const i=H.map(p=>c(n.agent,p)).filter(p=>!d(p)),s={map:e,moved:0,changes:[],resolutions:[],bodyPaths:[],absentCredentials:i,dryRun:t};if(t){const p=B(s);if(p)for(const x of J(s,p))s.resolutions.push(G(x,s));for(const[x,Y]of V(s))z(x,Y,s,!0);return ae(s),s}ue(s);const a=[ye,de,be,le,ce,ie,fe];for(const p of a)p(s);n.canvas!==n.root&&d(n.canvas)&&h(n.canvas).length===0&&g(n.canvas),Se(n.root),w(m(o),{recursive:!0});const u=`${o}.${N()}.tmp`,v=k(u,"wx",384);try{if(process.platform==="linux"){const p=f(m(o));j(u,p.uid,p.gid)}q(v,`${C}
4
+ `),R(v)}finally{$(v)}return b(u,o),s}l(Re,"migrateLayout");export{Ce as OldToNewPathMap,W as claim,Ee as daemonAnswers,he as isJunkFile,Re as migrateLayout,E as movePath,Oe as oldToNewPathMap,z as previewMove,Q as sameFile,I as setAside,F as setAsidePath};
@@ -15,8 +15,12 @@ export declare class OldToNewPathMap {
15
15
  readonly old: OldLayout;
16
16
  private readonly entries;
17
17
  private readonly retired;
18
+ /** Stored paths inside a removed folder with no new location; left unchanged. */
19
+ readonly dangling: Set<string>;
18
20
  constructor(old: OldLayout);
19
21
  add(from: string, to: string): void;
22
+ /** A path whose planned destination changed: a worktree folder set aside instead of moving into its node. */
23
+ redirect(from: string, to: string): void;
20
24
  /** A removed folder: the folder itself maps to `to`, and a stored path inside it with no finer entry is refused. */
21
25
  retire(from: string, to: string): void;
22
26
  node(nodeId: string, app: string): void;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var d=(a,t)=>f(a,"name",{value:t,configurable:!0});import{existsSync as u}from"node:fs";import{homedir as g}from"node:os";import{isAbsolute as c,join as e,relative as l,resolve as h,sep as m}from"node:path";import{layoutRoot as w}from"../layout.js";function v(){const a=w(),t=process.platform==="linux",s=t&&a==="/"?"/volume":a,r=t?"/home/agent/.crouter":s,o=u(e(s,"canvas"))?e(s,"canvas"):s,n=t?"/home/agent/.pi/agent":h(process.env.PI_CODING_AGENT_DIR||e(g(),".pi","agent"));return{root:s,targetRoot:a,canvas:o,scope:s,agent:n,storedCanvas:o===s?r:e(r,"canvas"),storedScope:r,storedAgent:n,work:"/home/crtr/work"}}d(v,"oldLayout");class S{static{d(this,"OldToNewPathMap")}old;entries=new Map;retired=new Map;constructor(t){this.old=t;const s=e(t.targetRoot,"runtime"),r=e(s,"scope");for(const o of new Set([t.storedCanvas,t.storedScope,e(t.storedScope,"canvas")]))for(const n of["canvas.db","canvas.db-wal","canvas.db-shm","requests","reviews","plugins","marketplaces","secrets","crtrd.log","crtrd.err","cache"])this.add(e(o,n),e(s,n));for(const o of["prompts","personas","config.json","profile-defaults.json","operations.db","operations.db-wal","operations.db-shm"])this.add(e(t.storedScope,o),e(r,o));for(const o of["support","prompt-reviews","plugins","marketplaces"])this.add(e(t.storedScope,o),e(s,o));this.add(e(t.storedScope,"memory"),e(t.targetRoot,"user","memory")),this.add(t.storedScope,r),this.add(t.work,e(t.targetRoot,"user","files"));for(const o of["auth.json","anthropic-credentials.json","openai-codex-credentials.json","crouter-operations.db"])this.add(e(t.storedAgent,o),e(s,"secrets",o));for(const o of new Set([t.storedCanvas,t.storedScope,e(t.storedScope,"canvas")]))this.add(e(o,"secrets","runtime-client.json"),e(s,"secrets","runtime-client.json"))}add(t,s){if(!c(t)||!c(s))throw new Error("migration paths must be absolute");const r=this.entries.get(t);if(r&&r!==s)throw new Error(`conflicting migration path: ${t}`);this.entries.set(t,s)}retire(t,s){if(!c(t)||!c(s))throw new Error("migration paths must be absolute");const r=this.retired.get(t);if(r&&r!==s)throw new Error(`conflicting migration path: ${t}`);this.retired.set(t,s)}node(t,s){if(!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(t)||!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(s))throw new Error("unsafe migration node or app id");const r=e(this.old.targetRoot,"runtime","nodes",t),o=e(this.old.targetRoot,"apps",s,"nodes",t);for(const n of new Set([this.old.storedCanvas,this.old.storedScope,e(this.old.storedScope,"canvas")])){const p=e(n,"nodes",t);for(const i of["job","messages","meta.json","inbox.jsonl","passive.jsonl","transcript.jsonl","session.ptr"])this.add(e(p,i),e(r,i));for(const i of["context","reports","attachments","worktree"])this.add(e(p,i),e(o,i));this.add(e(p,"context","memory"),e(this.old.targetRoot,"apps",s,"memory","nodes",t))}}mapPath(t){if(!c(t))return t;const s=this.retired.get(t);if(s)return s;let r="";for(const o of this.entries.keys())(t===o||t.startsWith(o+m))&&o.length>r.length&&(r=o);for(const o of this.retired.keys())if(t.startsWith(o+m)&&o.length>r.length)throw new Error(`stored path names a removed folder: ${t}`);return r?h(this.entries.get(r),l(r,t)):t}}function R(){return new S(v())}d(R,"oldToNewPathMap");export{S as OldToNewPathMap,v as oldLayout,R as oldToNewPathMap};
1
+ var f=Object.defineProperty;var d=(i,t)=>f(i,"name",{value:t,configurable:!0});import{existsSync as g}from"node:fs";import{homedir as u}from"node:os";import{isAbsolute as a,join as s,relative as l,resolve as h,sep as m}from"node:path";import{layoutRoot as w}from"../layout.js";function v(){const i=w(),t=process.platform==="linux",e=t&&i==="/"?"/volume":i,r=t?"/home/agent/.crouter":e,o=g(s(e,"canvas"))?s(e,"canvas"):e,n=t?"/home/agent/.pi/agent":h(process.env.PI_CODING_AGENT_DIR||s(u(),".pi","agent"));return{root:e,targetRoot:i,canvas:o,scope:e,agent:n,storedCanvas:o===e?r:s(r,"canvas"),storedScope:r,storedAgent:n,work:"/home/crtr/work"}}d(v,"oldLayout");class b{static{d(this,"OldToNewPathMap")}old;entries=new Map;retired=new Map;dangling=new Set;constructor(t){this.old=t;const e=s(t.targetRoot,"runtime"),r=s(e,"scope");for(const o of new Set([t.storedCanvas,t.storedScope,s(t.storedScope,"canvas")]))for(const n of["canvas.db","canvas.db-wal","canvas.db-shm","requests","reviews","plugins","marketplaces","secrets","crtrd.log","crtrd.err","cache"])this.add(s(o,n),s(e,n));for(const o of["prompts","personas","config.json","profile-defaults.json","operations.db","operations.db-wal","operations.db-shm"])this.add(s(t.storedScope,o),s(r,o));for(const o of["support","prompt-reviews","plugins","marketplaces"])this.add(s(t.storedScope,o),s(e,o));this.add(s(t.storedScope,"memory"),s(t.targetRoot,"user","memory")),this.add(t.storedScope,r),this.add(t.work,s(t.targetRoot,"user","files"));for(const o of["auth.json","anthropic-credentials.json","openai-codex-credentials.json","crouter-operations.db"])this.add(s(t.storedAgent,o),s(e,"secrets",o));for(const o of new Set([t.storedCanvas,t.storedScope,s(t.storedScope,"canvas")]))this.add(s(o,"secrets","runtime-client.json"),s(e,"secrets","runtime-client.json"))}add(t,e){if(!a(t)||!a(e))throw new Error("migration paths must be absolute");const r=this.entries.get(t);if(r&&r!==e)throw new Error(`conflicting migration path: ${t}`);this.entries.set(t,e)}redirect(t,e){if(!a(t)||!a(e))throw new Error("migration paths must be absolute");this.entries.set(t,e)}retire(t,e){if(!a(t)||!a(e))throw new Error("migration paths must be absolute");const r=this.retired.get(t);if(r&&r!==e)throw new Error(`conflicting migration path: ${t}`);this.retired.set(t,e)}node(t,e){if(!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(t)||!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(e))throw new Error("unsafe migration node or app id");const r=s(this.old.targetRoot,"runtime","nodes",t),o=s(this.old.targetRoot,"apps",e,"nodes",t);for(const n of new Set([this.old.storedCanvas,this.old.storedScope,s(this.old.storedScope,"canvas")])){const p=s(n,"nodes",t);for(const c of["job","messages","meta.json","inbox.jsonl","passive.jsonl","transcript.jsonl","session.ptr"])this.add(s(p,c),s(r,c));for(const c of["context","reports","attachments","worktree"])this.add(s(p,c),s(o,c));this.add(s(p,"context","memory"),s(this.old.targetRoot,"apps",e,"memory","nodes",t))}}mapPath(t){if(!a(t))return t;const e=this.retired.get(t);if(e)return e;let r="";for(const o of this.entries.keys())(t===o||t.startsWith(o+m))&&o.length>r.length&&(r=o);for(const o of this.retired.keys())if(t.startsWith(o+m)&&o.length>r.length)return this.dangling.add(t),t;return r?h(this.entries.get(r),l(r,t)):t}}function R(){return new b(v())}d(R,"oldToNewPathMap");export{b as OldToNewPathMap,v as oldLayout,R as oldToNewPathMap};
@@ -1,2 +1,9 @@
1
1
  import type { LayoutMigration } from './index.js';
2
2
  export declare function storedPaths(migration: LayoutMigration): void;
3
+ /**
4
+ * Markdown links a moved profile folder by its old absolute path (or its `~/`
5
+ * spelling); point each at the new location. Scans the documents the canvas
6
+ * import reads: user and app memory, profile files, and node context. A dry
7
+ * run scans the same documents at their old locations and writes nothing.
8
+ */
9
+ export declare function rewriteBodyPaths(migration: LayoutMigration): void;
@@ -1,11 +1,11 @@
1
- var F=Object.defineProperty;var u=(s,i)=>F(s,"name",{value:i,configurable:!0});import{DatabaseSync as b}from"node:sqlite";import{closeSync as x,existsSync as y,fsyncSync as P,lstatSync as k,openSync as C,readFileSync as S,readdirSync as D,renameSync as J,unlinkSync as v,writeFileSync as B}from"node:fs";import{basename as M,dirname as L,join as p,relative as R,resolve as q,sep as N}from"node:path";function W(s,i){return typeof s=="string"?i.map.mapPath(s):Array.isArray(s)?s.map(o=>W(o,i)):s!==null&&typeof s=="object"?Object.fromEntries(Object.entries(s).map(([o,r])=>[o,W(r,i)])):s}u(W,"mappedJson");function j(s,i){const o=JSON.parse(s),r=W(o,i);return JSON.stringify(r)===JSON.stringify(o)?s:JSON.stringify(r)}u(j,"rewriteJson");function O(s,i){return s.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(i)!==void 0}u(O,"tableExists");function T(s,i,o){if(!y(s))return;const r=new b(s);try{r.exec("BEGIN IMMEDIATE");try{for(const[a,d]of Object.entries(i)){if(!O(r,a))continue;const l=new Set(r.prepare(`PRAGMA table_info("${a}")`).all().map(t=>t.name)),f=[...(d.paths??[]).filter(t=>l.has(t)),...(d.json??[]).filter(t=>l.has(t))];if(f.length===0)continue;const e=r.prepare(`SELECT rowid AS migration_rowid, ${f.map(t=>`"${t}"`).join(", ")} FROM "${a}"`).all();for(const t of e){const n=[];for(const c of f){const h=t[c];if(typeof h!="string")continue;const E=(d.json??[]).includes(c)?j(h,o):o.map.mapPath(h);E!==h&&n.push([c,E])}n.length&&(r.prepare(`UPDATE "${a}" SET ${n.map(([c])=>`"${c}" = ?`).join(", ")} WHERE rowid = ?`).run(...n.map(([,c])=>c),t.migration_rowid),o.moved+=n.length,o.changes.push(`${s}:${a}:${String(t.migration_rowid)} (${n.map(([c])=>c).join(", ")})`))}}r.exec("COMMIT")}catch(a){throw r.exec("ROLLBACK"),a}}finally{r.close()}}u(T,"rewriteDb");const g={nodes:{paths:["cwd","fork_source_file","pi_session_file"],json:["launch_config_json","review_binding_json","metadata_json","outcome_detail_json"]},sessions:{paths:["transcript_path","fork_source_path"]},worktrees:{paths:["path","repo_root"],json:["sweep_observed_json","abandoned_json","land_intent_json","disposal_json"]},crons:{paths:["cwd"],json:["env_json","sink"]},human_action_deliveries:{paths:["cwd"],json:["argv_json","completion_json","last_failure_json"]},deliveries:{json:["adapter_json"]},reviews:{paths:["origin_session_file","review_dir","branch_file","output_path","file","presentation_dir"],json:["result_json","specification_json"]},human_requests:{paths:["request_dir","file","presentation_dir"],json:["specification_json","action_json","progress_json","feedback_json","result_json"]},run_events:{json:["body_json"]},webhook_deliveries:{json:["payload_json","document_json","last_failure_json","argv_json"]}},A={scope_owners:{paths:["root"]},profiles:{paths:["home"]},profile_projects:{paths:["path"]},profile_defaults:{paths:["directory"]},scope_bookkeeping:{paths:["active_canvas"]},scope_settings:{json:["raw_json"]}};function m(s,i,o){if(!y(s))return;const r=S(s,"utf8"),a=o(r);if(a===r)return;const d=k(s);if(!d.isFile())throw new Error(`migration path is not a regular file: ${s}`);const l=`${s}.migration-tmp`;if(y(l))throw new Error(`migration temporary file already exists: ${l}`);try{B(l,a,{flag:"wx",mode:d.mode});const f=C(l,"r");try{P(f)}finally{x(f)}J(l,s)}finally{y(l)&&v(l)}i.moved++,i.changes.push(`${s} (stored paths)`)}u(m,"rewriteFile");function _(s,i){if(y(s))for(const o of D(s,{withFileTypes:!0})){const r=p(s,o.name);o.isDirectory()?_(r,i):o.isFile()&&i(r)}}u(_,"walk");function H(s,i,o){const{map:r}=s,{old:a}=r,d=new Map,l=new Set;_(i,n=>{if(!n.includes("/conversations/")||!n.endsWith(".jsonl"))return;const c=M(n);d.has(c)?l.add(c):d.set(c,p(a.targetRoot,R(a.root,n)))});const f=u(n=>{if(typeof n=="string"){if(!n.startsWith(a.storedAgent+N+"sessions"+N)||r.mapPath(n)!==n)return;const c=M(n);if(l.has(c)||!d.has(c))throw new Error(`cannot recover old conversation path: ${n}`);r.add(n,d.get(c))}else if(Array.isArray(n))for(const c of n)f(c);else if(n!==null&&typeof n=="object")for(const c of Object.values(n))f(c)},"reference"),e=u(n=>{if(n.endsWith("/meta.json")||n.endsWith(".json")&&(n.includes("/tickets/")||n.includes("/requests/")))f(JSON.parse(S(n,"utf8")));else if(n.endsWith(".jsonl")&&n.includes("/conversations/")){const c=S(n,"utf8");f(JSON.parse(c.slice(0,c.indexOf(`
2
- `)<0?void 0:c.indexOf(`
3
- `))))}else if(n.endsWith(".md")&&n.includes("/memory/")){const c=S(n,"utf8");if(!c.startsWith(`---
4
- `))return;const h=c.indexOf(`
5
- ---`,4);if(h<0)return;for(const E of c.slice(0,h).split(`
6
- `)){const w=E.match(/^\s*session_file:\s*["']?([^"'\n]+)["']?$/);w&&f(w[1])}}},"inspect");_(i,e),_(p(a.root,"user","memory"),e),_(p(o,"nodes"),e),_(p(o,"tickets"),e),_(p(o,"requests"),e);const t=p(o,"canvas.db");if(y(t)){const n=new b(t,{readOnly:!0});try{for(const[c,h]of Object.entries(g)){if(!O(n,c))continue;const E=new Set(n.prepare(`PRAGMA table_info("${c}")`).all().map(w=>w.name));for(const w of[...h.paths??[],...h.json??[]].filter($=>E.has($)))for(const $ of n.prepare(`SELECT "${w}" AS value FROM "${c}" WHERE "${w}" LIKE ?`).all(`%${a.storedAgent}/sessions/%`))(h.json??[]).includes(w)?f(JSON.parse($.value)):f($.value)}}finally{n.close()}}}u(H,"recoverSessionMappings");function V(s){const{root:i}=s.map.old,o=p(i,"runtime"),r=p(i,"apps");H(s,r,o),T(p(o,"canvas.db"),g,s),T(p(o,"scope","operations.db"),A,s);const a=new Set,d=p(o,"canvas.db");if(y(d)){const e=new b(d,{readOnly:!0});try{if(O(e,"nodes")&&e.prepare("PRAGMA table_info(nodes)").all().some(t=>t.name==="cwd"))for(const t of e.prepare("SELECT cwd FROM nodes").all())a.add(t.cwd)}finally{e.close()}}const l=p(o,"scope","operations.db");if(y(l)){const e=new b(l,{readOnly:!0});try{if(O(e,"profile_projects"))for(const t of e.prepare("SELECT path FROM profile_projects").all())a.add(t.path)}finally{e.close()}}for(const e of a){const t=s.map.old.targetRoot;let n=e.startsWith(t+"/")?q(i,R(t,e)):e;for(;n!==L(n);)T(p(n,".crouter","operations.db"),A,s),n=L(n)}_(p(r),e=>{e.endsWith("/.crouter/operations.db")&&T(e,A,s),e.endsWith("/meta.json")&&m(e,s,t=>j(t,s)),e.endsWith(".md")&&e.includes("/memory/")&&I(e,s),e.endsWith(".jsonl")&&e.includes("/conversations/")&&G(e,s)}),_(p(i,"user","memory"),e=>{e.endsWith(".md")&&I(e,s)}),_(p(i,"user","files"),e=>{e.endsWith("/.crouter/operations.db")&&T(e,A,s)}),_(p(o,"nodes"),e=>{e.endsWith("/meta.json")&&m(e,s,t=>j(t,s)),e.endsWith("/session.ptr")&&v(e)}),_(p(o,"tickets"),e=>{e.endsWith(".json")&&m(e,s,t=>j(t,s))}),_(p(o,"requests"),e=>{e.endsWith(".json")&&m(e,s,t=>j(t,s))});const f=p(o,"canvas.db");if(y(f)){const e=new b(f);try{e.exec("DROP TABLE IF EXISTS layout_header_rewrites")}finally{e.close()}}}u(V,"storedPaths");function I(s,i){m(s,i,o=>{if(!o.startsWith(`---
7
- `))return o;const r=o.indexOf(`
8
- ---`,4);return r<0?o:o.slice(0,r).replace(/^(\s*session_file:\s*)([^\n]+)$/gm,(d,l,f)=>{const e=f.match(/^(["'])(.*)\1$/),t=e?e[2]:f.trim(),n=i.map.mapPath(t);return n===t?d:`${l}${e?e[1]:""}${n}${e?e[1]:""}`})+o.slice(r)})}u(I,"rewriteMemory");function G(s,i){const o=p(i.map.old.root,"runtime","canvas.db");if(!y(o)){m(s,i,a=>{const d=a.indexOf(`
9
- `),l=d<0?a:a.slice(0,d);return j(l,i)+(d<0?"":a.slice(d))});return}const r=new b(o);try{r.exec("CREATE TABLE IF NOT EXISTS layout_header_rewrites (path TEXT PRIMARY KEY, old_header TEXT NOT NULL, new_header TEXT NOT NULL)");const a=r.prepare("SELECT old_header, new_header FROM layout_header_rewrites WHERE path = ?").get(s),d=S(s,"utf8"),l=d.indexOf(`
10
- `),f=l<0?d:d.slice(0,l),e=a?.new_header??j(f,i);if(a&&f!==a.old_header&&f!==e)throw new Error(`conversation header changed during migration: ${s}`);if(!a&&e!==f){const t=p(i.map.old.targetRoot,R(i.map.old.root,s)),n=Buffer.byteLength(e)-Buffer.byteLength(f);r.exec("BEGIN IMMEDIATE");try{r.prepare("INSERT INTO layout_header_rewrites (path, old_header, new_header) VALUES (?, ?, ?)").run(s,f,e),n!==0&&O(r,"sessions")&&r.prepare("UPDATE sessions SET event_offset = event_offset + ? WHERE transcript_path = ? AND event_offset > 0").run(n,t),r.exec("COMMIT")}catch(c){throw r.exec("ROLLBACK"),c}}f!==e&&m(s,i,t=>{const n=t.indexOf(`
11
- `);if((n<0?t:t.slice(0,n))!==f)throw new Error(`conversation header changed during migration: ${s}`);return e+(n<0?"":t.slice(n))}),(a||e!==f)&&r.prepare("DELETE FROM layout_header_rewrites WHERE path = ?").run(s)}finally{r.close()}}u(G,"rewriteHeader");export{V as storedPaths};
1
+ var P=Object.defineProperty;var y=(e,c)=>P(e,"name",{value:c,configurable:!0});import{DatabaseSync as S}from"node:sqlite";import{closeSync as F,existsSync as m,fsyncSync as C,lstatSync as D,openSync as B,readFileSync as $,readdirSync as g,renameSync as J,unlinkSync as x,writeFileSync as q}from"node:fs";import{basename as L,dirname as N,join as a,relative as v,resolve as H,sep as A}from"node:path";import{homedir as G}from"node:os";function M(e,c){return typeof e=="string"?c.map.mapPath(e):Array.isArray(e)?e.map(r=>M(r,c)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,i])=>[r,M(i,c)])):e}y(M,"mappedJson");function b(e,c){const r=JSON.parse(e),i=M(r,c);return JSON.stringify(i)===JSON.stringify(r)?e:JSON.stringify(i)}y(b,"rewriteJson");function O(e,c){return e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(c)!==void 0}y(O,"tableExists");function T(e,c,r){if(!m(e))return;const i=new S(e);try{i.exec("BEGIN IMMEDIATE");try{for(const[f,p]of Object.entries(c)){if(!O(i,f))continue;const u=new Set(i.prepare(`PRAGMA table_info("${f}")`).all().map(o=>o.name)),d=[...(p.paths??[]).filter(o=>u.has(o)),...(p.json??[]).filter(o=>u.has(o))];if(d.length===0)continue;const s=i.prepare(`SELECT rowid AS migration_rowid, ${d.map(o=>`"${o}"`).join(", ")} FROM "${f}"`).all();for(const o of s){const l=[];for(const n of d){const t=o[n];if(typeof t!="string")continue;const h=(p.json??[]).includes(n)?b(t,r):r.map.mapPath(t);h!==t&&l.push([n,h])}l.length&&(i.prepare(`UPDATE "${f}" SET ${l.map(([n])=>`"${n}" = ?`).join(", ")} WHERE rowid = ?`).run(...l.map(([,n])=>n),o.migration_rowid),r.moved+=l.length,r.changes.push(`${e}:${f}:${String(o.migration_rowid)} (${l.map(([n])=>n).join(", ")})`))}}i.exec("COMMIT")}catch(f){throw i.exec("ROLLBACK"),f}}finally{i.close()}}y(T,"rewriteDb");const k={nodes:{paths:["cwd","fork_source_file","pi_session_file"],json:["launch_config_json","review_binding_json","metadata_json","outcome_detail_json"]},sessions:{paths:["transcript_path","fork_source_path"]},worktrees:{paths:["path","repo_root"],json:["sweep_observed_json","abandoned_json","land_intent_json","disposal_json"]},crons:{paths:["cwd"],json:["env_json","sink"]},human_action_deliveries:{paths:["cwd"],json:["argv_json","completion_json","last_failure_json"]},deliveries:{json:["adapter_json"]},reviews:{paths:["origin_session_file","review_dir","branch_file","output_path","file","presentation_dir"],json:["result_json","specification_json"]},human_requests:{paths:["request_dir","file","presentation_dir"],json:["specification_json","action_json","progress_json","feedback_json","result_json"]},run_events:{json:["body_json"]},webhook_deliveries:{json:["payload_json","document_json","last_failure_json","argv_json"]}},W={scope_owners:{paths:["root"]},profiles:{paths:["home"]},profile_projects:{paths:["path"]},profile_defaults:{paths:["directory"]},scope_bookkeeping:{paths:["active_canvas"]},scope_settings:{json:["raw_json"]}};function E(e,c,r){if(!m(e))return;const i=$(e,"utf8"),f=r(i);if(f===i)return;const p=D(e);if(!p.isFile())throw new Error(`migration path is not a regular file: ${e}`);const u=`${e}.migration-tmp`;if(m(u))throw new Error(`migration temporary file already exists: ${u}`);try{q(u,f,{flag:"wx",mode:p.mode});const d=B(u,"r");try{C(d)}finally{F(d)}J(u,e)}finally{m(u)&&x(u)}c.moved++,c.changes.push(`${e} (stored paths)`)}y(E,"rewriteFile");function _(e,c){if(m(e))for(const r of g(e,{withFileTypes:!0})){const i=a(e,r.name);r.isDirectory()?_(i,c):r.isFile()&&c(i)}}y(_,"walk");function U(e,c,r){const{map:i}=e,{old:f}=i,p=new Map,u=new Set,d=new Set;_(c,n=>{if(!n.includes("/conversations/")||!n.endsWith(".jsonl"))return;const t=L(n);p.has(t)?u.add(t):p.set(t,a(f.targetRoot,v(f.root,n)))});const s=y(n=>{if(typeof n=="string"){if(!n.startsWith(f.storedAgent+A+"sessions"+A)||d.has(n)||i.mapPath(n)!==n)return;const t=L(n);if(u.has(t)||!p.has(t)){d.has(n)||e.resolutions.push(`lost-transcript: ${n} is referenced but ${u.has(t)?"matches more than one moved transcript":"exists nowhere"}; left the reference unchanged`),d.add(n);return}i.add(n,p.get(t))}else if(Array.isArray(n))for(const t of n)s(t);else if(n!==null&&typeof n=="object")for(const t of Object.values(n))s(t)},"reference"),o=y(n=>{if(n.endsWith("/meta.json")||n.endsWith(".json")&&(n.includes("/tickets/")||n.includes("/requests/")))s(JSON.parse($(n,"utf8")));else if(n.endsWith(".jsonl")&&n.includes("/conversations/")){const t=$(n,"utf8");s(JSON.parse(t.slice(0,t.indexOf(`
2
+ `)<0?void 0:t.indexOf(`
3
+ `))))}else if(n.endsWith(".md")&&n.includes("/memory/")){const t=$(n,"utf8");if(!t.startsWith(`---
4
+ `))return;const h=t.indexOf(`
5
+ ---`,4);if(h<0)return;for(const j of t.slice(0,h).split(`
6
+ `)){const w=j.match(/^\s*session_file:\s*["']?([^"'\n]+)["']?$/);w&&s(w[1])}}},"inspect");_(c,o),_(a(f.root,"user","memory"),o),_(a(r,"nodes"),o),_(a(r,"tickets"),o),_(a(r,"requests"),o);const l=a(r,"canvas.db");if(m(l)){const n=new S(l,{readOnly:!0});try{for(const[t,h]of Object.entries(k)){if(!O(n,t))continue;const j=new Set(n.prepare(`PRAGMA table_info("${t}")`).all().map(w=>w.name));for(const w of[...h.paths??[],...h.json??[]].filter(R=>j.has(R)))for(const R of n.prepare(`SELECT "${w}" AS value FROM "${t}" WHERE "${w}" LIKE ?`).all(`%${f.storedAgent}/sessions/%`))(h.json??[]).includes(w)?s(JSON.parse(R.value)):s(R.value)}}finally{n.close()}}}y(U,"recoverSessionMappings");function se(e){const{root:c}=e.map.old,r=a(c,"runtime"),i=a(c,"apps");U(e,i,r),T(a(r,"canvas.db"),k,e),T(a(r,"scope","operations.db"),W,e);const f=new Set,p=a(r,"canvas.db");if(m(p)){const s=new S(p,{readOnly:!0});try{if(O(s,"nodes")&&s.prepare("PRAGMA table_info(nodes)").all().some(o=>o.name==="cwd"))for(const o of s.prepare("SELECT cwd FROM nodes").all())f.add(o.cwd)}finally{s.close()}}const u=a(r,"scope","operations.db");if(m(u)){const s=new S(u,{readOnly:!0});try{if(O(s,"profile_projects"))for(const o of s.prepare("SELECT path FROM profile_projects").all())f.add(o.path)}finally{s.close()}}for(const s of f){const o=e.map.old.targetRoot;let l=s.startsWith(o+"/")?H(c,v(o,s)):s;for(;l!==N(l);)T(a(l,".crouter","operations.db"),W,e),l=N(l)}_(a(i),s=>{s.endsWith("/.crouter/operations.db")&&T(s,W,e),s.endsWith("/meta.json")&&E(s,e,o=>b(o,e)),s.endsWith(".md")&&s.includes("/memory/")&&I(s,e),s.endsWith(".jsonl")&&s.includes("/conversations/")&&X(s,e)}),_(a(c,"user","memory"),s=>{s.endsWith(".md")&&I(s,e)}),Y(e);for(const s of e.map.dangling)e.resolutions.push(`dangling-path: ${s} names a file the new layout drops; left the stored path unchanged`);_(a(c,"user","files"),s=>{s.endsWith("/.crouter/operations.db")&&T(s,W,e)}),_(a(r,"nodes"),s=>{s.endsWith("/meta.json")&&E(s,e,o=>b(o,e)),s.endsWith("/session.ptr")&&x(s)}),_(a(r,"tickets"),s=>{s.endsWith(".json")&&E(s,e,o=>b(o,e))}),_(a(r,"requests"),s=>{s.endsWith(".json")&&E(s,e,o=>b(o,e))});const d=a(r,"canvas.db");if(m(d)){const s=new S(d);try{s.exec("DROP TABLE IF EXISTS layout_header_rewrites")}finally{s.close()}}}y(se,"storedPaths");function I(e,c){E(e,c,r=>{if(!r.startsWith(`---
7
+ `))return r;const i=r.indexOf(`
8
+ ---`,4);return i<0?r:r.slice(0,i).replace(/^(\s*session_file:\s*)([^\n]+)$/gm,(p,u,d)=>{const s=d.match(/^(["'])(.*)\1$/),o=s?s[2]:d.trim(),l=c.map.mapPath(o);return l===o?p:`${u}${s?s[1]:""}${l}${s?s[1]:""}`})+r.slice(i)})}y(I,"rewriteMemory");function X(e,c){const r=a(c.map.old.root,"runtime","canvas.db");if(!m(r)){E(e,c,f=>{const p=f.indexOf(`
9
+ `),u=p<0?f:f.slice(0,p);return b(u,c)+(p<0?"":f.slice(p))});return}const i=new S(r);try{i.exec("CREATE TABLE IF NOT EXISTS layout_header_rewrites (path TEXT PRIMARY KEY, old_header TEXT NOT NULL, new_header TEXT NOT NULL)");const f=i.prepare("SELECT old_header, new_header FROM layout_header_rewrites WHERE path = ?").get(e),p=$(e,"utf8"),u=p.indexOf(`
10
+ `),d=u<0?p:p.slice(0,u),s=f?.new_header??b(d,c);if(f&&d!==f.old_header&&d!==s)throw new Error(`conversation header changed during migration: ${e}`);if(!f&&s!==d){const o=a(c.map.old.targetRoot,v(c.map.old.root,e)),l=Buffer.byteLength(s)-Buffer.byteLength(d);i.exec("BEGIN IMMEDIATE");try{i.prepare("INSERT INTO layout_header_rewrites (path, old_header, new_header) VALUES (?, ?, ?)").run(e,d,s),l!==0&&O(i,"sessions")&&i.prepare("UPDATE sessions SET event_offset = event_offset + ? WHERE transcript_path = ? AND event_offset > 0").run(l,o),i.exec("COMMIT")}catch(n){throw i.exec("ROLLBACK"),n}}d!==s&&E(e,c,o=>{const l=o.indexOf(`
11
+ `);if((l<0?o:o.slice(0,l))!==d)throw new Error(`conversation header changed during migration: ${e}`);return s+(l<0?"":o.slice(l))}),(f||s!==d)&&i.prepare("DELETE FROM layout_header_rewrites WHERE path = ?").run(e)}finally{i.close()}}y(X,"rewriteHeader");function K(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}y(K,"escape");function Y(e){const c=e.bodyPaths;if(c.length===0)return;const r=G(),i=[];for(const[t,h]of c)i.push([t,h]),t.startsWith(r+A)&&i.push([`~${t.slice(r.length)}`,h.startsWith(r+A)?`~${h.slice(r.length)}`:h]);i.sort((t,h)=>h[0].length-t[0].length);const f=new RegExp(`(${i.map(([t])=>K(t)).join("|")})(?![A-Za-z0-9_-])`,"g"),p=new Map(i),{root:u,scope:d,canvas:s}=e.map.old,o=y(t=>{if(!t.endsWith(".md"))return;if(e.dryRun){const j=$(t,"utf8").match(f)?.length??0;j&&e.resolutions.push(`profile-extra-link: rewrote ${j} link(s) to moved profile files in ${t}`);return}let h=0;E(t,e,j=>j.replace(f,w=>(h++,p.get(w)))),h&&e.resolutions.push(`profile-extra-link: rewrote ${h} link(s) to moved profile files in ${t}`)},"visit"),l=y(t=>{if(m(t))for(const h of g(t))_(a(t,h,"context"),o)},"nodeContexts");if(e.dryRun){_(a(d,"memory"),o),_(a(d,"profiles"),o),l(a(s,"nodes"));return}_(a(u,"user","memory"),o);const n=a(u,"apps");if(m(n))for(const t of g(n))_(a(n,t,"memory"),o),_(a(n,t,"files","profiles"),o),l(a(n,t,"nodes"))}y(Y,"rewriteBodyPaths");export{Y as rewriteBodyPaths,se as storedPaths};
@@ -1,17 +1,30 @@
1
1
  import { profileSpace } from '../layout.js';
2
2
  import type { LayoutMigration } from './index.js';
3
+ export interface ProfileFolder {
4
+ id: string;
5
+ source: string;
6
+ /** No scoped-state row: the whole folder moves to `files`. */
7
+ target: ReturnType<typeof profileSpace> | null;
8
+ files: string;
9
+ /** Entries with no slot in the new layout, moved under `files` at the same name. */
10
+ extras: string[];
11
+ }
3
12
  /**
4
13
  * A profile is its scoped-state row; the row is authoritative even when an
5
14
  * interrupted run already removed the old profile folder. There is no profile
6
15
  * folder in the new layout: the old folder's own path (the profile's
7
- * scope_owners.root) becomes its memory folder. Runs before any step moves a
8
- * file, so a folder holding data with no new location refuses the whole run.
16
+ * scope_owners.root) becomes its memory folder. What else the folder holds is
17
+ * the profile's own files and moves to `apps/<app>/files/profiles/<id>/`; a
18
+ * folder with no row moves there whole, under the terminal app.
9
19
  */
10
- export declare function profileFolders(map: LayoutMigration['map']): Array<{
11
- source: string;
12
- target: ReturnType<typeof profileSpace>;
13
- }>;
20
+ export declare function profileFolders(migration: LayoutMigration): {
21
+ folders: ProfileFolder[];
22
+ junk: string[];
23
+ aside: string[];
24
+ };
14
25
  export declare function memoryAndProfiles(migration: LayoutMigration): void;
15
26
  export declare function conversations(migration: LayoutMigration): void;
16
27
  export declare function repairMovedRepositories(migration: LayoutMigration): void;
17
28
  export declare function worktrees(migration: LayoutMigration): void;
29
+ /** Every resolution the real run would make, computed without changing anything. */
30
+ export declare function previewStores(migration: LayoutMigration): void;
@@ -1,4 +1,3 @@
1
- var Z=Object.defineProperty;var w=(e,t)=>Z(e,"name",{value:t,configurable:!0});import{DatabaseSync as j}from"node:sqlite";import{closeSync as q,copyFileSync as J,existsSync as h,fsyncSync as Y,lstatSync as y,mkdirSync as N,openSync as G,readFileSync as P,readdirSync as _,renameSync as A,rmdirSync as b,unlinkSync as g,writeFileSync as z}from"node:fs";import{execFileSync as K}from"node:child_process";import{basename as H,dirname as $,isAbsolute as I,join as r,relative as S,resolve as L,sep as F}from"node:path";import{profileSpace as Q}from"../layout.js";import{movePath as k,sameFile as O}from"./index.js";function C(e,t){K("git",["-c",`safe.directory=${e}`,"-C",e,...t],{stdio:"pipe"})}w(C,"gitInRepo");function E(e,t){const{root:i,targetRoot:c}=t.map.old;return L(i,S(c,e))}w(E,"physical");function R(e){const{old:t}=e.map,i=r(t.canvas,"canvas.db"),c=r(t.root,"runtime","canvas.db"),o=h(i)?i:c;return h(o)?new j(o,{readOnly:!0}):null}w(R,"canvasDb");function x(e){return new Map(e.prepare("SELECT node_id, grantee FROM nodes").all().map(({node_id:t,grantee:i})=>{const c=i==="user:local"?"terminal":i.startsWith("app:")?i.slice(4):"";if(!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(c))throw new Error(`node ${t} has no valid app`);return[t,c]}))}w(x,"nodeApps");function B(e,t,i){if(h(e)){if(!h(t)){k(e,t,i);return}if(!y(e).isDirectory()||!y(t).isDirectory()){if(!y(e).isFile()||!y(t).isFile()||!O(e,t))throw new Error(`profile home file differs: ${e} and ${t}`);g(e);return}for(const c of _(e))B(r(e,c),r(t,c),i);b(e)}}w(B,"mergeHome");function V(e){const t=[r(e.old.scope,"operations.db"),r(e.old.root,"runtime","scope","operations.db")].find(h),i=t?new j(t,{readOnly:!0}):null,c=new Map;try{if(i&&i.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='profiles'").get())for(const s of i.prepare("SELECT id, grantee FROM profiles").all())c.set(s.id,s.grantee)}finally{i?.close()}const o=new Map;for(const[s,p]of c){const d=p==null||p==="user:local"?"terminal":p.startsWith("app:")?p.slice(4):"",l=Q(d,s),f=r(e.old.storedScope,"profiles",s);e.retire(f,l.memory),e.add(r(f,"memory"),l.memory),e.add(r(f,"env.json"),l.env),e.add(r(f,"home"),l.home),o.set(s,l)}const a=r(e.old.scope,"profiles");if(!h(a))return[];const n=[],u=[];for(const s of _(a)){const p=r(a,s);if(!y(p).isDirectory()){n.push(p);continue}if(s===".locks"){for(const l of _(p)){const f=r(p,l);(!l.endsWith(".lock")||!y(f).isFile())&&n.push(f)}continue}const d=o.get(s);if(!d){n.push(`${p} (no scoped-state profile row)`);continue}for(const l of _(p)){const f=r(p,l),m=y(f);l==="memory"||l==="home"?m.isDirectory()||n.push(f):(l==="env.json"||l==="profile.json"||l.endsWith(".lock"))&&m.isFile()||n.push(f)}u.push({source:p,target:d})}if(n.length)throw new Error(`profile folders hold data the new layout has no place for; move or delete each path, then rerun:
2
- ${n.join(`
3
- `)}`);return u}w(V,"profileFolders");function ae(e){const{map:t}=e;k(r(t.old.scope,"memory"),r(t.old.root,"user","memory"),e);const i=R(e);if(i)try{for(const[o,a]of x(i)){const n=r(t.old.root,"apps",a,"memory","nodes",o);k(r(t.old.root,"apps",a,"nodes",o,"context","memory"),n,e),k(r(t.old.canvas,"nodes",o,"context","memory"),n,e)}}finally{i.close()}for(const{source:o,target:a}of V(t)){k(r(o,"memory"),E(a.memory,e),e),k(r(o,"env.json"),E(a.env,e),e),B(r(o,"home"),E(a.home,e),e);for(const n of _(o))g(r(o,n));b(o),e.moved++,e.changes.push(`${o} (removed)`)}const c=r(t.old.scope,"profiles");if(h(c)){const o=r(c,".locks");if(h(o)){for(const a of _(o))g(r(o,a));b(o)}b(c)}}w(ae,"memoryAndProfiles");function X(e,t,i,c){if(!h(e)){if(!h(t))throw new Error(`session file missing from both migration paths: ${e}`);return}if(!y(e).isFile())throw new Error(`session path is not a file: ${e}`);if(N($(t),{recursive:!0}),h(t)){if(!y(t).isFile()||!O(e,t))throw new Error(`session destination differs: ${t}`);return}if(c){const o=r($(t),`.${H(t)}.migrating`);h(o)&&g(o),J(e,o);const a=G(o,"r");try{Y(a)}finally{q(a)}if(!O(e,o))throw new Error(`session copy verification failed: ${e}`);A(o,t),i.moved++,i.changes.push(`${e} -> ${t} (source retained)`);return}A(e,t),i.moved++,i.changes.push(`${e} -> ${t}`)}w(X,"moveSession");function ce(e){const t=R(e);if(t)try{const i=x(t),c=t.prepare("SELECT session_id, node_id, transcript_path FROM sessions WHERE transcript_path IS NOT NULL ORDER BY session_id, (unbound_at IS NULL) DESC, created_at DESC, rowid DESC").all(),o=new Map,a=new Map,n=new Map;for(const s of c){o.has(s.session_id)||o.set(s.session_id,s.node_id),n.set(s.transcript_path,(n.get(s.transcript_path)??0)+1);const p=a.get(s.transcript_path)??new Set;p.add(s.session_id),a.set(s.transcript_path,p)}const u=new Set;for(const{session_id:s,node_id:p,transcript_path:d}of c){if(u.has(d))continue;if(u.add(d),a.get(d).size!==1)throw new Error(`two conversations share a transcript: ${d}`);const l=n.get(d)>1?o.get(s):p,f=i.get(l);if(!f)throw new Error(`session belongs to unknown node: ${l}`);if(!I(d))throw new Error(`session path is not absolute: ${d}`);const m=r(e.map.old.targetRoot,"apps",f,"conversations",l,H(d));if(d===m)continue;e.map.add(d,m);const v=d===e.map.old.storedAgent||d.startsWith(e.map.old.storedAgent+F)?r(e.map.old.agent,S(e.map.old.storedAgent,d)):d;X(v,E(m,e),e,process.platform==="linux"&&(d===e.map.old.storedAgent||d.startsWith(e.map.old.storedAgent+F)))}}finally{t.close()}}w(ce,"conversations");function pe(e){if(process.platform!=="linux")return;const t=R(e);if(t)try{const i=t.prepare("SELECT node_id, path, repo_root FROM worktrees").all(),c=x(t);for(const o of i){const a=e.map.mapPath(o.repo_root);if(a===o.repo_root)continue;const n=c.get(o.node_id);if(!n)throw new Error(`worktree belongs to unknown node: ${o.node_id}`);const u=E(r(e.map.old.targetRoot,"apps",n,"nodes",o.node_id,"worktree"),e);if(!h(u))continue;C(E(a,e),["worktree","repair",u]);const s=o.path.startsWith(e.map.old.storedCanvas+F)?r(e.map.old.canvas,S(e.map.old.storedCanvas,o.path)):o.path;W(s,u,e)}}finally{t.close()}}w(pe,"repairMovedRepositories");function W(e,t,i){const c=w(o=>{for(const a of _(o)){const n=r(o,a);if(a===".git"&&n!==r(t,".git")&&y(n).isFile()){const u=P(n,"utf8");if(!u.startsWith("gitdir: "))throw new Error(`invalid submodule git link: ${n}`);const s=u.slice(8).trim(),p=L($(n),s),d=r(e,S(t,n)),l=L($(d),s),f=h(p)?p:l;if(!h(f))throw new Error(`submodule git directory missing: ${d}`);const m=i?.map.mapPath(f)??f,v=i&&m!==f?E(m,i):f;if(!h(v))throw new Error(`moved submodule git directory missing: ${v}`);p!==v&&z(n,`gitdir: ${S($(n),v)}
4
- `);const D=r(v,"config"),M=P(D,"utf8");if(!/^\s*worktree\s*=.*$/m.test(M))throw new Error(`submodule has no worktree setting: ${D}`);const U=JSON.stringify(S(v,$(n))),T=M.replace(/^(\s*worktree\s*=).*$/m,`$1 ${U}`);T!==M&&z(D,T)}else a!==".git"&&y(n).isDirectory()&&c(n)}},"visit");c(t)}w(W,"repairSubmoduleLinks");function de(e){const t=R(e);if(t)try{const i=x(t),c=t.prepare("SELECT node_id, state, cleanup_state, path, repo_root FROM worktrees").all();for(const o of c){const a=i.get(o.node_id);if(!a)throw new Error(`worktree belongs to unknown node: ${o.node_id}`);if(!I(o.path))throw new Error(`worktree path is not absolute: ${o.path}`);const n=r(e.map.old.targetRoot,"apps",a,"nodes",o.node_id,"worktree");if(o.path===n)continue;e.map.add(o.path,n);const u=o.path===e.map.old.storedCanvas||o.path.startsWith(e.map.old.storedCanvas+F)?r(e.map.old.canvas,S(e.map.old.storedCanvas,o.path)):o.path,s=E(n,e);if(!h(u)){if(!h(s)&&!(o.state!=="open"&&o.cleanup_state==="complete"))throw new Error(`managed worktree missing from both migration paths: ${o.path}`);h(s)&&(C(o.repo_root,["worktree","repair",s]),W(u,s));continue}if(h(s))throw new Error(`managed worktree destination already exists: ${s}`);N($(s),{recursive:!0});try{C(o.repo_root,["worktree","move",u,s])}catch(p){if(!String(p.stderr??"").includes("submodule"))throw p;A(u,s),C(o.repo_root,["worktree","repair",s])}W(u,s),e.moved++,e.changes.push(`${u} -> ${s} (git worktree move)`)}}finally{t.close()}}w(de,"worktrees");export{ce as conversations,ae as memoryAndProfiles,V as profileFolders,pe as repairMovedRepositories,de as worktrees};
1
+ var oe=Object.defineProperty;var h=(e,t)=>oe(e,"name",{value:t,configurable:!0});import{DatabaseSync as z}from"node:sqlite";import{closeSync as se,copyFileSync as re,existsSync as u,realpathSync as ne,fsyncSync as pe,lstatSync as $,mkdirSync as B,openSync as ce,readFileSync as T,readdirSync as E,renameSync as M,rmdirSync as F,unlinkSync as D,writeFileSync as J}from"node:fs";import{execFileSync as Z}from"node:child_process";import{basename as x,dirname as R,isAbsolute as q,join as n,relative as k,resolve as C,sep as P}from"node:path";import{profileSpace as ae}from"../layout.js";import{isJunkFile as j,movePath as S,sameFile as A,setAside as O,setAsidePath as H}from"./index.js";import{rewriteBodyPaths as ie}from"./stored-paths.js";function L(e,t){Z("git",["-c",`safe.directory=${e}`,"-C",e,...t],{stdio:"pipe"})}h(L,"gitInRepo");function _(e,t){const{root:s,targetRoot:p}=t.map.old;return C(s,k(p,e))}h(_,"physical");function N(e,t=!1){const{old:s}=e.map,p=n(s.canvas,"canvas.db"),o=n(s.root,"runtime","canvas.db"),r=u(p)?p:o;return u(r)&&$(r).size>0?new z(r,{readOnly:!t||e.dryRun}):null}h(N,"canvasDb");function W(e){return new Map(e.prepare("SELECT node_id, grantee FROM nodes").all().map(({node_id:t,grantee:s})=>{const p=s==="user:local"?"terminal":s.startsWith("app:")?s.slice(4):"";if(!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(p))throw new Error(`node ${t} has no valid app`);return[t,p]}))}h(W,"nodeApps");function Y(e,t,s){return n(s.map.old.targetRoot,"apps",e,"files","profiles",t)}h(Y,"profileFiles");function G(e,t,s,p){if(!u(e))return;if(!u(t)){S(e,t,p);return}const o=$(e),r=$(t);if(o.isDirectory()&&r.isDirectory()){for(const d of E(e))G(n(e,d),n(t,d),n(s,d),p);F(e);return}if(o.isFile()&&r.isFile()&&A(e,t)){D(e);return}const a=_(s,p);p.dryRun||S(e,a,p),p.resolutions.push(`profile-home: ${t} differs from the profile's ${e}; kept the app home's copy, moved the profile's to ${a}`)}h(G,"mergeHome");function K(e,t,s,p){if(!u(e)||!u(t))return;const o=$(e),r=$(t);if(o.isDirectory()&&r.isDirectory()){for(const a of E(e))K(n(e,a),n(t,a),n(s,a),p);return}o.isFile()&&r.isFile()&&A(e,t)||p.resolutions.push(`profile-home: ${t} differs from the profile's ${e}; kept the app home's copy, moved the profile's to ${_(s,p)}`)}h(K,"previewHome");function Q(e,t,s){e.bodyPaths.some(([p])=>p===t)||e.bodyPaths.push([t,s])}h(Q,"bodyPath");function V(e){const{map:t}=e,s=[n(t.old.scope,"operations.db"),n(t.old.root,"runtime","scope","operations.db")].find(u),p=s?new z(s,{readOnly:!0}):null,o=new Map;try{if(p&&p.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='profiles'").get())for(const i of p.prepare("SELECT id, grantee FROM profiles").all())o.set(i.id,i.grantee)}finally{p?.close()}const r=new Map;for(const[i,c]of o){const w=c==null||c==="user:local"?"terminal":c.startsWith("app:")?c.slice(4):"",f=ae(w,i),y=n(t.old.storedScope,"profiles",i);t.retire(y,f.memory),t.add(n(y,"memory"),f.memory),t.add(n(y,"env.json"),f.env),t.add(n(y,"home"),f.home),r.set(i,{target:f,app:w})}const a=n(t.old.scope,"profiles"),d={folders:[],junk:[],aside:[]};if(!u(a))return d;for(const i of E(a)){const c=n(a,i);if(!$(c).isDirectory()){(j(i)?d.junk:d.aside).push(c);continue}if(i===".locks"){for(const l of E(c)){const v=n(c,l);!(l.endsWith(".lock")&&$(v).isFile())&&!j(l)&&d.aside.push(v)}continue}const w=n(t.old.storedScope,"profiles",i),f=r.get(i);if(!f){const l=Y("terminal",i,e);t.add(w,l),Q(e,w,l),d.folders.push({id:i,source:c,target:null,files:l,extras:[]});continue}const y=Y(f.app,i,e),b=[];for(const l of E(c)){const v=$(n(c,l));(l==="memory"||l==="home"?v.isDirectory():l==="env.json"||l==="profile.json"||l.endsWith(".lock")?v.isFile():j(l))||(b.push(l),t.add(n(w,l),n(y,l)),Q(e,n(w,l),n(y,l)))}d.folders.push({id:i,source:c,target:f.target,files:y,extras:b})}return d}h(V,"profileFolders");function X(e,t){for(const s of e.folders){s.target||t.resolutions.push(`profile-folder: ${s.source} has no profile row; moved whole to ${_(s.files,t)}`);for(const p of s.extras)t.resolutions.push(`profile-extra: ${n(s.source,p)} moved to ${_(n(s.files,p),t)}`)}for(const s of e.junk)t.resolutions.push(`profile-leftover: deleted ${s} (not profile data)`);for(const s of e.aside)t.resolutions.push(`profile-leftover: ${s} is not a profile; moved to ${H(t,"profiles",x(s))}`)}h(X,"profileLines");function Fe(e){const{map:t}=e;S(n(t.old.scope,"memory"),n(t.old.root,"user","memory"),e);const s=N(e);if(s)try{for(const[r,a]of W(s)){const d=n(t.old.root,"apps",a,"memory","nodes",r);S(n(t.old.root,"apps",a,"nodes",r,"context","memory"),d,e),S(n(t.old.canvas,"nodes",r,"context","memory"),d,e)}}finally{s.close()}const p=V(e);X(p,e);for(const{source:r,target:a,files:d,extras:i}of p.folders){if(!a){S(r,_(d,e),e,!0);continue}for(const c of i)S(n(r,c),_(n(d,c),e),e);S(n(r,"memory"),_(a.memory,e),e),S(n(r,"env.json"),_(a.env,e),e),G(n(r,"home"),_(a.home,e),n(d,"home"),e);for(const c of E(r))D(n(r,c));F(r),e.moved++,e.changes.push(`${r} (removed)`)}for(const r of p.junk)D(r);for(const r of p.aside)O(r,"profiles",e);const o=n(t.old.scope,"profiles");if(u(o)){const r=n(o,".locks");if(u(r)){for(const a of E(r))D(n(r,a));F(r)}F(o)}}h(Fe,"memoryAndProfiles");function de(e,t,s,p){if(u(e)){if(!$(e).isFile())throw new Error(`session path is not a file: ${e}`);if(B(R(t),{recursive:!0}),u(t)){if($(t).isFile()&&A(e,t))return;const o=O(t,"replaced",s,k(s.map.old.root,t));s.resolutions.push(`stray-destination: ${t} predates the migration; moved it to ${o} and put ${e} in its place`)}if(p){const o=n(R(t),`.${x(t)}.migrating`);u(o)&&D(o),re(e,o);const r=ce(o,"r");try{pe(r)}finally{se(r)}if(!A(e,o))throw new Error(`session copy verification failed: ${e}`);M(o,t),s.moved++,s.changes.push(`${e} -> ${t} (source retained)`);return}M(e,t),s.moved++,s.changes.push(`${e} -> ${t}`)}}h(de,"moveSession");function le(e,t,s){const p=new Set(t.prepare("SELECT s.transcript_path AS path FROM sessions s JOIN nodes n ON n.node_id = s.node_id WHERE s.unbound_at IS NULL AND n.status IN ('active', 'idle') AND s.transcript_path IS NOT NULL").all().map(r=>r.path)),o=e.dryRun?null:t.prepare("UPDATE sessions SET transcript_path = NULL WHERE transcript_path = ?");for(const r of s)if(!(u(r.source)||u(_(r.destination,e)))){if(p.has(r.transcript_path)){e.resolutions.push(`lost-transcript: ${r.transcript_path} is missing but is a live node's current session; kept its path`);continue}o?.run(r.transcript_path),e.resolutions.push(`lost-transcript: ${r.transcript_path} is missing from both paths; cleared the session's transcript path`)}}h(le,"lostTranscripts");function fe(e){const t=N(e,!0);if(t)try{const s=W(t),p=t.prepare("SELECT session_id, node_id, transcript_path FROM sessions WHERE transcript_path IS NOT NULL ORDER BY session_id, (unbound_at IS NULL) DESC, created_at DESC, rowid DESC").all(),o=new Map,r=new Map,a=new Map;for(const c of p){o.has(c.session_id)||o.set(c.session_id,c.node_id),a.set(c.transcript_path,(a.get(c.transcript_path)??0)+1);const w=r.get(c.transcript_path)??new Set;w.add(c.session_id),r.set(c.transcript_path,w)}const d=new Set,i=[];for(const{session_id:c,node_id:w,transcript_path:f}of p){if(d.has(f))continue;if(d.add(f),r.get(f).size!==1)throw new Error(`two conversations share a transcript: ${f}`);const y=a.get(f)>1?o.get(c):w,b=s.get(y);if(!b)throw new Error(`session belongs to unknown node: ${y}`);if(!q(f))throw new Error(`session path is not absolute: ${f}`);const l=n(e.map.old.targetRoot,"apps",b,"conversations",y,x(f));if(f===l)continue;const v=f===e.map.old.storedAgent||f.startsWith(e.map.old.storedAgent+P),m=v?n(e.map.old.agent,k(e.map.old.storedAgent,f)):f;i.push({transcript_path:f,destination:l,source:m,retain:process.platform==="linux"&&v})}le(e,t,i);for(const{transcript_path:c,destination:w}of i)e.map.add(c,w);if(e.dryRun)return;for(const{destination:c,source:w,retain:f}of i)de(w,_(c,e),e,f)}finally{t.close()}}h(fe,"conversations");function De(e){if(process.platform!=="linux")return;const t=N(e);if(t)try{const s=t.prepare("SELECT node_id, path, repo_root FROM worktrees").all(),p=W(t);for(const o of s){const r=e.map.mapPath(o.repo_root);if(r===o.repo_root)continue;const a=p.get(o.node_id);if(!a)throw new Error(`worktree belongs to unknown node: ${o.node_id}`);const d=_(n(e.map.old.targetRoot,"apps",a,"nodes",o.node_id,"worktree"),e);if(!u(d))continue;L(_(r,e),["worktree","repair",d]);const i=o.path.startsWith(e.map.old.storedCanvas+P)?n(e.map.old.canvas,k(e.map.old.storedCanvas,o.path)):o.path;I(i,d,e)}}finally{t.close()}}h(De,"repairMovedRepositories");function I(e,t,s){const p=h(o=>{for(const r of E(o)){const a=n(o,r);if(r===".git"&&a!==n(t,".git")&&$(a).isFile()){const d=T(a,"utf8");if(!d.startsWith("gitdir: "))throw new Error(`invalid submodule git link: ${a}`);const i=d.slice(8).trim(),c=C(R(a),i),w=n(e,k(t,a)),f=C(R(w),i),y=u(c)?c:f;if(!u(y))throw new Error(`submodule git directory missing: ${w}`);const b=s?.map.mapPath(y)??y,l=s&&b!==y?_(b,s):y;if(!u(l))throw new Error(`moved submodule git directory missing: ${l}`);c!==l&&J(a,`gitdir: ${k(R(a),l)}
2
+ `);const v=n(l,"config"),m=T(v,"utf8");if(!/^\s*worktree\s*=.*$/m.test(m))throw new Error(`submodule has no worktree setting: ${v}`);const te=JSON.stringify(k(l,R(a))),U=m.replace(/^(\s*worktree\s*=).*$/m,`$1 ${te}`);U!==m&&J(v,U)}else r!==".git"&&$(a).isDirectory()&&p(a)}},"visit");p(t)}h(I,"repairSubmoduleLinks");function ue(e,t){return Z("git",["-c",`safe.directory=${e}`,"-C",e,...t],{stdio:"pipe",encoding:"utf8"})}h(ue,"gitOut");function g(e){try{return ne(e)}catch{return C(e)}}h(g,"real");function he(e,t){try{const s=g(t);return ue(e,["worktree","list","--porcelain"]).split(`
3
+ `).some(p=>p.startsWith("worktree ")&&g(p.slice(9))===s)}catch{return!1}}h(he,"registered");function we(e,t){if(!u(e))return!1;try{const s=T(n(t,".git"),"utf8");return s.startsWith("gitdir: ")?u(C(t,s.slice(8).trim())):!1}catch{return!1}}h(we,"repairable");function ee(e,t,s){s.dryRun||t.state!=="open"&&t.cleanup_state==="complete"||e.prepare("UPDATE worktrees SET state = CASE WHEN state = 'open' THEN 'closed' ELSE state END, cleanup_state = 'complete', closed_at = COALESCE(closed_at, ?) WHERE node_id = ?").run(new Date().toISOString(),t.node_id)}h(ee,"closeRow");function ye(e){const t=N(e,!0);if(t){try{const s=W(t),p=t.prepare("SELECT node_id, state, cleanup_state, path, repo_root FROM worktrees").all();for(const o of p){const r=s.get(o.node_id);if(!r)throw new Error(`worktree belongs to unknown node: ${o.node_id}`);if(!q(o.path))throw new Error(`worktree path is not absolute: ${o.path}`);const a=n(e.map.old.targetRoot,"apps",r,"nodes",o.node_id,"worktree");if(o.path===a)continue;const d=o.path===e.map.old.storedCanvas||o.path.startsWith(e.map.old.storedCanvas+P)?n(e.map.old.canvas,k(e.map.old.storedCanvas,o.path)):o.path,i=_(a,e);if(!u(d)){e.map.add(o.path,a),u(i)?!e.dryRun&&u(o.repo_root)&&(L(o.repo_root,["worktree","repair",i]),I(d,i)):o.state!=="open"&&o.cleanup_state==="complete"||(ee(t,o,e),e.resolutions.push(`missing-worktree: ${o.path} (node ${o.node_id}) is gone; closed its row`));continue}if(!he(o.repo_root,d))if(o.state==="open"&&we(o.repo_root,d))e.resolutions.push(`unregistered-worktree: ${o.path} (node ${o.node_id}) is not registered in ${o.repo_root}; relinked it with git worktree repair`),e.dryRun||L(o.repo_root,["worktree","repair",d]);else{const c=H(e,"worktrees",x(d));e.resolutions.push(`unregistered-worktree: ${o.path} (node ${o.node_id}${o.state==="open"?"":`, ${o.state}`}) is not a worktree of ${u(o.repo_root)?o.repo_root:`the missing repository ${o.repo_root}`}; ${o.state==="open"?"closed its row and ":""}moved the folder to ${c}`),e.map.redirect(o.path,n(e.map.old.targetRoot,k(e.map.old.root,c))),e.dryRun||(O(d,"worktrees",e),ee(t,o,e));continue}if(e.map.add(o.path,a),u(i)){const c=H(e,"replaced",k(e.map.old.root,i));e.resolutions.push(`stray-destination: ${i} predates the migration; moved it to ${c} and put the worktree ${d} in its place`),e.dryRun||O(i,"replaced",e,k(e.map.old.root,i))}if(!e.dryRun){B(R(i),{recursive:!0});try{L(o.repo_root,["worktree","move",d,i])}catch(c){if(!String(c.stderr??"").includes("submodule"))throw c;M(d,i),L(o.repo_root,["worktree","repair",i])}I(d,i),e.moved++,e.changes.push(`${d} -> ${i} (git worktree move)`)}}}finally{t.close()}e.dryRun||_e(e)}}h(ye,"worktrees");function _e(e){const t=n(e.map.old.canvas,"nodes");if(u(t)){for(const s of E(t)){const p=n(t,s);$(p).isDirectory()&&E(p).length===0&&F(p)}E(t).length===0&&F(t)}}h(_e,"pruneOldNodeFolders");function Ce(e){ye(e);const t=V(e);X(t,e);for(const{source:s,target:p,files:o}of t.folders)p&&K(n(s,"home"),_(p.home,e),n(o,"home"),e);fe(e),ie(e)}h(Ce,"previewStores");export{fe as conversations,Fe as memoryAndProfiles,Ce as previewStores,V as profileFolders,De as repairMovedRepositories,ye as worktrees};
@@ -2,6 +2,4 @@ import type { MarketplaceManifest, PluginManifest } from '../types.js';
2
2
  export declare function pluginManifestPath(pluginRoot: string): string;
3
3
  export declare function marketplaceManifestPath(mktRoot: string): string;
4
4
  export declare function readPluginManifest(pluginRoot: string): PluginManifest | null;
5
- /** Validate an optional memory-extension declaration at package preflight. */
6
- export declare function validatePluginManifestMemoryExtensions(manifest: PluginManifest): void;
7
5
  export declare function readMarketplaceManifest(mktRoot: string): MarketplaceManifest | null;
@@ -1 +1 @@
1
- var o=Object.defineProperty;var n=(t,i)=>o(t,"name",{value:i,configurable:!0});import{join as r}from"node:path";import{MARKETPLACE_MANIFEST_DIR as a,MARKETPLACE_MANIFEST_FILE as f,PLUGIN_MANIFEST_DIR as M,PLUGIN_MANIFEST_FILE as u}from"../types.js";import{validatePluginMemoryExtensions as E}from"./memory/extensions.js";import{readJsonIfExists as e}from"./fs-utils.js";function p(t){return r(t,M,u)}n(p,"pluginManifestPath");function s(t){return r(t,a,f)}n(s,"marketplaceManifestPath");function A(t){return e(p(t))}n(A,"readPluginManifest");function _(t){E(t)}n(_,"validatePluginManifestMemoryExtensions");function c(t){return e(s(t))}n(c,"readMarketplaceManifest");export{s as marketplaceManifestPath,p as pluginManifestPath,c as readMarketplaceManifest,A as readPluginManifest,_ as validatePluginManifestMemoryExtensions};
1
+ var i=Object.defineProperty;var r=(t,o)=>i(t,"name",{value:o,configurable:!0});import{join as n}from"node:path";import{MARKETPLACE_MANIFEST_DIR as a,MARKETPLACE_MANIFEST_FILE as f,PLUGIN_MANIFEST_DIR as E,PLUGIN_MANIFEST_FILE as I}from"../types.js";import{readJsonIfExists as e}from"./fs-utils.js";function M(t){return n(t,E,I)}r(M,"pluginManifestPath");function p(t){return n(t,a,f)}r(p,"marketplaceManifestPath");function s(t){return e(M(t))}r(s,"readPluginManifest");function P(t){return e(p(t))}r(P,"readMarketplaceManifest");export{p as marketplaceManifestPath,M as pluginManifestPath,P as readMarketplaceManifest,s as readPluginManifest};
@@ -1,5 +1,4 @@
1
- import type { MemoryExtensionDeclarations, MemoryExtensionScalar, PluginManifest } from '../../types.js';
2
- import type { MemoryDoc } from '../memory-resolver.js';
1
+ import type { MemoryExtensionDeclarations, MemoryExtensionScalar, PluginManifest, Scope } from '../types.js';
3
2
  export type MemoryExtensionCatalog = Record<string, MemoryExtensionDeclarations>;
4
3
  export interface MemoryExtensionValidationIssue {
5
4
  path: string;
@@ -16,15 +15,15 @@ export declare function isMemoryExtensionScalar(value: unknown): value is Memory
16
15
  export declare function validateMemoryExtensionDeclarations(raw: unknown): MemoryExtensionDeclarations;
17
16
  /** Throw when a manifest carries an invalid addendum; absent is valid. */
18
17
  export declare function validatePluginMemoryExtensions(manifest: Pick<PluginManifest, 'memory_extensions'>): void;
19
- /** Installed declarations used for validation and authoring. Disabled plugins
20
- * remain present so existing values can still be checked and edited. */
21
- export declare function memoryExtensionValidationCatalog(doc: Pick<MemoryDoc, 'scope' | 'path'>, options?: MemoryExtensionCatalogOptions): MemoryExtensionCatalog;
22
- /** Winning enabled declarations used only to interpret structured output. */
23
- export declare function memoryExtensionEffectiveCatalog(doc: Pick<MemoryDoc, 'scope' | 'path'>): MemoryExtensionCatalog;
18
+ /** Declarations for a native document. Project documents use their owning
19
+ * project scope only, then user scope; profile/node/user docs use user scope. */
20
+ /** Installed declarations a package candidate's documents validate against:
21
+ * a project-scope candidate sees its project's plugins, then user scope; any
22
+ * other scope sees user scope. Disabled plugins remain present so existing
23
+ * values can still be checked. The candidate's namespace shadows an installed
24
+ * copy of the same name. */
25
+ export declare function pluginExtensionCatalog(scope: Scope, scopeRootPath: string, options?: MemoryExtensionCatalogOptions): MemoryExtensionCatalog;
24
26
  /** Validate the raw `extensions` frontmatter value. Unresolved namespaces are
25
27
  * intentionally reported rather than discarded: removal leaves raw metadata
26
28
  * intact but lint-invalid until its plugin returns. */
27
29
  export declare function validateMemoryExtensionValues(raw: unknown, catalog: MemoryExtensionCatalog): MemoryExtensionValidationIssue[];
28
- /** Effective plugin metadata for structured consumers. It overlays only valid
29
- * explicit scalars onto defaults and never mutates or serializes frontmatter. */
30
- export declare function projectEffectiveMemoryExtensions(raw: unknown, catalog: MemoryExtensionCatalog): Record<string, Record<string, MemoryExtensionScalar>>;
@@ -0,0 +1 @@
1
+ var _=Object.defineProperty;var l=(e,o)=>_(e,"name",{value:o,configurable:!0});import{listInstalledPlugins as y,listInstalledPluginsInRoot as $}from"./resolver.js";const v=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,j=new Set(["type","values","default","write_help","edit_help"]);function p(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}l(p,"isRecord");function m(e){return typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)}l(m,"isMemoryExtensionScalar");function f(e,o){return new Error(`invalid memory_extensions declaration at ${e}: ${o}`)}l(f,"declarationError");function g(e){return typeof e=="string"&&e.trim()!==""&&!/[\r\n]/.test(e)}l(g,"validHelp");function h(e,o){return m(o)?e.type==="enum"?typeof o=="string"&&e.values.includes(o):typeof o===e.type:!1}l(h,"validDefault");function x(e){if(!p(e))throw f("memory_extensions","expected a non-empty object");const o={},i=Object.entries(e);if(i.length===0)throw f("memory_extensions","must not be empty");for(const[a,n]of i){const t=`memory_extensions.${a}`;if(!v.test(a))throw f(t,"field names must be lowercase kebab-case");if(!p(n))throw f(t,"expected a declaration object");for(const s of Object.keys(n))if(!j.has(s))throw f(t,`unknown key \`${s}\``);const r=n.type;if(r!=="boolean"&&r!=="string"&&r!=="number"&&r!=="enum")throw f(`${t}.type`,"expected boolean, string, number, or enum");if(!g(n.write_help))throw f(`${t}.write_help`,"expected a nonblank single-line string");if(!g(n.edit_help))throw f(`${t}.edit_help`,"expected a nonblank single-line string");if(r==="enum"){const s=n.values;if(!Array.isArray(s)||s.length===0||!s.every(c=>typeof c=="string"&&c!==""))throw f(`${t}.values`,"expected a non-empty string list");if(new Set(s).size!==s.length)throw f(`${t}.values`,"values must be unique");const d={type:r,values:[...s],write_help:n.write_help,edit_help:n.edit_help};if("default"in n){if(!h(d,n.default))throw f(`${t}.default`,"must be one of the declared enum values");d.default=n.default}o[a]=d;continue}if("values"in n)throw f(`${t}.values`,"is allowed only for enum declarations");const u={type:r,write_help:n.write_help,edit_help:n.edit_help};if("default"in n){if(!h(u,n.default))throw f(`${t}.default`,`must be a ${r}`);u.default=n.default}o[a]=u}return o}l(x,"validateMemoryExtensionDeclarations");function O(e){e.memory_extensions!==void 0&&x(e.memory_extensions)}l(O,"validatePluginMemoryExtensions");function b(e,o){if(e.memory_extensions!==void 0)try{return x(e.memory_extensions)}catch(i){if(o)throw i;return}}l(b,"declarationsFromManifest");function E(e,o,i){const a={},n=new Set;if(i!==void 0){n.add(i.name);const t=b(i,!0);t!==void 0&&(a[i.name]=t)}for(const t of e)for(const r of t){if(o&&!r.enabled)continue;const u=r.manifest.name;if(n.has(u)||a[u]!==void 0)continue;const s=b(r.manifest,!1);s!==void 0&&(a[u]=s)}return a}l(E,"catalogForPlugins");function M(e,o,i={}){const a=e==="project"?[$("project",o),y("user")]:e==="builtin"?[]:[y("user")];return E(a,!1,i.candidate)}l(M,"pluginExtensionCatalog");function I(e,o){if(e===void 0)return[];if(!p(e))return[{path:"extensions",message:"expected a mapping"}];const i=[];for(const[a,n]of Object.entries(e)){const t=`extensions.${a}`;if(!p(n)){i.push({path:t,message:"expected a mapping"});continue}const r=o[a];if(r===void 0){i.push({path:t,message:"unresolved extension namespace"});for(const[u,s]of Object.entries(n))m(s)||i.push({path:`${t}.${u}`,message:"expected a string, boolean, or finite number"});continue}for(const[u,s]of Object.entries(n)){const d=`${t}.${u}`;if(!m(s)){i.push({path:d,message:"expected a string, boolean, or finite number"});continue}const c=r[u];if(c===void 0){i.push({path:d,message:"undeclared extension field"});continue}if(!h(c,s)){const w=c.type==="enum"?`one of ${c.values.join("|")}`:c.type;i.push({path:d,message:`expected ${w}`})}}}return i}l(I,"validateMemoryExtensionValues");export{m as isMemoryExtensionScalar,M as pluginExtensionCatalog,x as validateMemoryExtensionDeclarations,I as validateMemoryExtensionValues,O as validatePluginMemoryExtensions};
@@ -14,7 +14,7 @@ export declare const HELP_ICON: string;
14
14
  * paints lives in one file: terminal for `bash`, file-text for `read`, floppy for
15
15
  * `write` (content committed to disk), pencil-square for `edit`. */
16
16
  export declare const TOOL_ICON: Readonly<Record<'bash' | 'read' | 'write' | 'edit', string>>;
17
- /** Per-leaf overrides, keyed by full leaf help-name path (e.g. "memory
17
+ /** Per-leaf overrides, keyed by full leaf help-name path (e.g. "doc
18
18
  * lint"), same shape as SUPPRESS_OUTPUT_LEAVES. */
19
19
  export declare const LEAF_ICON_CP: Record<string, number>;
20
20
  /** Resolve the Nerd Font glyph for a command's argv tokens: the longest
@@ -1,2 +1,3 @@
1
- var v=Object.defineProperty;var u=(n,e)=>v(n,"name",{value:e,configurable:!0});const g=new Set(["canvas roster","canvas snapshot","node inspect snapshot","node inspect show","sys context sysprompt"]);function M(n){return g.has(n)}u(M,"suppressOutputForLeaf");function N(n){for(const e of g){const t=e.split(" ");if(t.length<=n.length&&t.every((r,s)=>n[s]===r))return!0}return!1}u(N,"suppressOutputForPath");const b=61529,R=String.fromCodePoint(b),T={bash:String.fromCodePoint(61728),read:String.fromCodePoint(61788),write:String.fromCodePoint(61639),edit:String.fromCodePoint(61508)},w={canvas:61672,capture:61501,device:61705,human:61447,memory:61485,node:61842,pkg:61874,profile:62141,push:61678,"exa-search":61442,surface:61704,sys:61459},k={"canvas dashboard":61668,"canvas snapshot":61488,"canvas browse":61774,"canvas attention count":62098,"canvas attention list":61498,"canvas attention map":62073,"canvas revive":61473,"node lifecycle revive":61473,"canvas history search":61442,"canvas history read":61485,"canvas history grep":61616,"node inspect artifacts":61914,"sys daemon start":61515,"sys daemon status":61713,"sys daemon stop":61517,"canvas chord":61441,"surface tmux-spread":61449,"canvas issue new":61832,"canvas prune":61636,"human send":61529,"human review":61508,"human show":61704,"human cancel":61453,"human list":61498,"human resolve":61452,"memory list":61498,"memory read":61485,"memory find":61442,"memory write":61504,"memory edit":61508,"memory history":61914,"memory origin":61883,"memory lint":61770,"node new":61543,"node message send":61664,"node message request":61664,"cron add":61463,"node wait deadline":61463,"node subscription add":61683,"node subscription remove":61942,"node promote":61698,"node yield":62093,"surface node focus":61531,"surface node cycle":61473,"node inspect list":61498,"node inspect show":61550,"node inspect snapshot":61488,"node inspect context":61564,"node lifecycle recycle":61880,"node lifecycle close":61453,"node lifecycle demote":61699,"node config":61459,"cron list":61463,"cron cancel":61534,"pkg plugin install":61465,"pkg plugin remove":61460,"pkg plugin enable":61452,"pkg plugin disable":61534,"pkg plugin update":61473,"pkg plugin list":61498,"pkg plugin show":61550,"pkg market add":61543,"pkg market remove":61460,"pkg market update":61473,"pkg market list":61498,"pkg market browse":61774,"push update":61587,"push final":61726,"exa-search web":61612,"exa-search answer":61557,"exa-search contents":61686,"surface attach to":61926,"sys config get":61465,"sys config set":61504,"sys config path":61563,"sys settings":61459,"sys setup":61613,"sys doctor":61681,"sys context sysprompt":61788,"sys context prompt-review":61442,"sys feedback":61557,"sys update":61473,"sys version":61483,"sys sync":61561};function H(n){let e;for(const[r,s]of Object.entries(k)){const o=r.split(" ");o.length<=n.length&&o.every((i,a)=>n[a]===i)&&(e===void 0||o.length>e.words)&&(e={words:o.length,cp:s})}if(e!==void 0)return String.fromCodePoint(e.cp);const t=n.length>0?w[n[0]]:void 0;return t!==void 0?String.fromCodePoint(t):"\u25C6"}u(H,"iconForPath");function x(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)?n:void 0}u(x,"plainObject");function U(n){const e=x(x(n)?.details);if(e===void 0)return[];const t=e.crtrPreviews;return(Array.isArray(t)?t:[e.crtrPreview]).flatMap(s=>{const o=x(s);if(o===void 0||typeof o.path!="string")return[];const i=o.jsonl;return[{path:o.path,result:x(o.result),jsonl:Array.isArray(i)?i.flatMap(a=>{const p=x(a);return p===void 0?[]:[p]}):void 0,error:x(o.error)}]})}u(U,"crtrPreviewRecords");const P=3;function c(n){return n.result}u(c,"record");function f(n,e){const t=n[e];return typeof t=="string"&&t!==""?t:void 0}u(f,"stringField");function m(n,e){return typeof n[e]=="boolean"?n[e]:void 0}u(m,"booleanField");function l(n,e){return typeof n[e]=="number"&&Number.isFinite(n[e])?n[e]:void 0}u(l,"numberField");function $(n,e){const t=n[e];return Array.isArray(t)&&t.every(r=>r!==null&&typeof r=="object"&&!Array.isArray(r))?t:void 0}u($,"arrayField");function D(n){const e=n.replace(/[\\/]+$/,""),t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t===-1?e:e.slice(t+1)}u(D,"basename");function A(n,e){return n.length>e?`${n.slice(0,e).trimEnd()}\u2026`:n}u(A,"truncateLine");function S(n,e,t=5){const r=n.map(i=>f(i,e));if(r.some(i=>i===void 0))return;const s=r.slice(0,t),o=r.length-s.length;return o>0?`${s.join(", ")}, \u2026 ${o} more`:s.join(", ")}u(S,"topNames");function C(n){const e=n.error;if(e===void 0)return null;const t=f(e,"error"),r=f(e,"message");return t===void 0||r===void 0?null:[{text:t,tone:"error"},{text:A(r,160),tone:"muted"}]}u(C,"summarizeError");function _(n){const e=c(n);if(e===void 0)return null;const t=f(e,"name"),r=f(e,"kind"),s=f(e,"scope"),o=f(e,"content");if(t===void 0||r===void 0||s===void 0)return null;const i=[{text:`${t} \xB7 ${r} \xB7 ${s}`}];if(o!==void 0){const a=o.trim().split(`
2
- `).slice(0,P);a.length>0&&a.some(p=>p!=="")&&i.push({text:""},...a.map(p=>({text:p})))}return i}u(_,"summarizeMemoryRead");function j(n,e=!1){return t=>{const r=c(t),s=r===void 0?void 0:l(r,"count")??l(r,"total");return s===void 0?null:s===0&&e?[{text:`PASS \xB7 no ${n}`,tone:"success"}]:[{text:`${s} ${n}`,tone:s===0?"muted":"plain"}]}}u(j,"summarizeCount");function d(n,e="items"){return t=>{const r=c(t);if(r===void 0)return null;const s=$(r,e),o=l(r,"total")??s?.length;if(s===void 0||o===void 0)return null;const i=[{text:`${o} ${n}`,tone:o===0?"muted":"plain"}],a=S(s,"name");return a!==void 0&&a!==""&&i.push({text:a,tone:"muted"}),i}}u(d,"summarizeArray");function O(n){const t=c(n)?.counts;if(t===null||typeof t!="object"||Array.isArray(t))return null;const r=Object.entries(t);if(r.some(([,i])=>typeof i!="number"))return null;const s=r.reduce((i,[,a])=>i+a,0);if(s===0)return[{text:"PASS \xB7 no pending asks",tone:"success"}];const o=r.filter(([,i])=>i>0).sort((i,a)=>a[1]-i[1])[0];return o===void 0?null:[{text:`${s} asks`,tone:"warning"},{text:`hottest: ${o[0]} (${o[1]})`,tone:"muted"}]}u(O,"summarizeAttentionMap");function h(n,e,t){return r=>{const s=c(r);if(s===void 0)return null;const o=m(s,n);if(o===void 0)return null;const i=l(s,"pid")??l(s,"existing_pid");return[{text:o?`${e}${i===void 0?"":` \xB7 pid ${i}`}`:t,tone:o?"success":"muted"}]}}u(h,"summarizeDaemon");function E(n){const e=c(n);if(e===void 0||f(e,"page_id")===void 0)return null;const t=m(e,"reply");return t===void 0?null:[{text:t?"page sent \u2192 waiting on human":"announcement sent",tone:t?"accent":"success"}]}u(E,"summarizeHumanSend");function z(n){const e=c(n);if(e===void 0)return null;const t=m(e,"resolved"),r=f(e,"job_id");return t===void 0||r===void 0?null:[{text:`${t?"resolved":"not resolved"} ${r}`,tone:t?"success":"warning"}]}u(z,"summarizeHumanResolve");function y(n){const e=c(n);if(e===void 0)return null;const t=f(e,"status");return t===void 0?null:[{text:t,tone:["done","success","submitted","filed"].includes(t)?"success":t==="failed"?"error":"plain"}]}u(y,"summarizeStatus");function F(n){const e=n.jsonl;if(e===void 0)return null;const t=e.filter(r=>f(r,"name")!==void 0&&l(r,"projects_count")!==void 0);return t.length===0&&e.length>0?null:[{text:`${t.length} profile${t.length===1?"":"s"}`},...t.slice(0,5).map(r=>({text:`${f(r,"name")} \xB7 ${l(r,"projects_count")} projects`,tone:"muted"}))]}u(F,"summarizeProfileList");const I=[{path:"memory read",run:_},{path:"memory list",run:d("docs")},{path:"memory find",run:d("hits","hits")},{path:"canvas attention count",run:j("pending asks",!0)},{path:"canvas attention list",run:d("pending asks")},{path:"canvas attention map",run:O},{path:"human send",run:E},{path:"human list",run:d("pending")},{path:"human resolve",run:z},{path:"pkg plugin list",run:d("plugins")},{path:"pkg market list",run:d("marketplaces")},{path:"pkg market browse",run:d("plugins")},{path:"canvas dashboard",run:d("nodes","rows")},{path:"node inspect list",run:d("nodes","nodes")},{path:"sys daemon start",run:h("started","started","already running")},{path:"sys daemon status",run:h("running","running","not running")},{path:"sys daemon stop",run:h("stopped","stopped","was not running")},{path:"sys update",run:y},{path:"sys feedback",run:y},{path:"profile list",run:F}];function Y(n,e=[]){const t=C(n);return t!==null?t:I.find(({path:s})=>s===n.path)?.run(n,e)??null}u(Y,"summarizePath");export{R as HELP_ICON,k as LEAF_ICON_CP,I as SUMMARIZERS,g as SUPPRESS_OUTPUT_LEAVES,T as TOOL_ICON,U as crtrPreviewRecords,H as iconForPath,Y as summarizePath,M as suppressOutputForLeaf,N as suppressOutputForPath};
1
+ var v=Object.defineProperty;var u=(n,e)=>v(n,"name",{value:e,configurable:!0});const g=new Set(["canvas roster","canvas snapshot","node inspect snapshot","node inspect show","sys context sysprompt"]);function N(n){return g.has(n)}u(N,"suppressOutputForLeaf");function M(n){for(const e of g){const t=e.split(" ");if(t.length<=n.length&&t.every((r,s)=>n[s]===r))return!0}return!1}u(M,"suppressOutputForPath");const b=61529,R=String.fromCodePoint(b),H={bash:String.fromCodePoint(61728),read:String.fromCodePoint(61788),write:String.fromCodePoint(61639),edit:String.fromCodePoint(61508)},w={canvas:61672,capture:61501,device:61705,doc:61485,human:61447,node:61842,pkg:61874,profile:62141,push:61678,"exa-search":61442,surface:61704,sys:61459},k={"canvas dashboard":61668,"canvas snapshot":61488,"canvas browse":61774,"canvas attention count":62098,"canvas attention list":61498,"canvas attention map":62073,"canvas revive":61473,"node lifecycle revive":61473,"canvas list":61498,"canvas read":61485,"canvas search":61442,"canvas history search":61442,"canvas history grep":61616,"sys daemon start":61515,"sys daemon status":61713,"sys daemon stop":61517,"canvas chord":61441,"surface tmux-spread":61449,"canvas issue new":61832,"canvas prune":61636,"human send":61529,"human review":61508,"human show":61704,"human cancel":61453,"human list":61498,"human resolve":61452,"doc write":61504,"doc edit":61508,"doc history":61914,"doc lint":61770,"node new":61543,"node message send":61664,"node message request":61664,"cron add":61463,"node wait deadline":61463,"node subscription add":61683,"node subscription remove":61942,"node promote":61698,"node yield":62093,"surface node focus":61531,"surface node cycle":61473,"node inspect list":61498,"node inspect show":61550,"node inspect snapshot":61488,"node inspect context":61564,"node lifecycle recycle":61880,"node lifecycle close":61453,"node lifecycle demote":61699,"node config":61459,"cron list":61463,"cron cancel":61534,"pkg plugin install":61465,"pkg plugin remove":61460,"pkg plugin enable":61452,"pkg plugin disable":61534,"pkg plugin update":61473,"pkg plugin list":61498,"pkg plugin show":61550,"pkg market add":61543,"pkg market remove":61460,"pkg market update":61473,"pkg market list":61498,"pkg market browse":61774,"push update":61587,"push final":61726,"exa-search web":61612,"exa-search answer":61557,"exa-search contents":61686,"surface attach to":61926,"sys config get":61465,"sys config set":61504,"sys config path":61563,"sys settings":61459,"sys setup":61613,"sys doctor":61681,"sys context sysprompt":61788,"sys context prompt-review":61442,"sys feedback":61557,"sys update":61473,"sys version":61483,"sys sync":61561};function U(n){let e;for(const[r,s]of Object.entries(k)){const o=r.split(" ");o.length<=n.length&&o.every((a,i)=>n[i]===a)&&(e===void 0||o.length>e.words)&&(e={words:o.length,cp:s})}if(e!==void 0)return String.fromCodePoint(e.cp);const t=n.length>0?w[n[0]]:void 0;return t!==void 0?String.fromCodePoint(t):"\u25C6"}u(U,"iconForPath");function p(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)?n:void 0}u(p,"plainObject");function T(n){const e=p(p(n)?.details);if(e===void 0)return[];const t=e.crtrPreviews;return(Array.isArray(t)?t:[e.crtrPreview]).flatMap(s=>{const o=p(s);if(o===void 0||typeof o.path!="string")return[];const a=o.jsonl;return[{path:o.path,result:p(o.result),jsonl:Array.isArray(a)?a.flatMap(i=>{const h=p(i);return h===void 0?[]:[h]}):void 0,error:p(o.error)}]})}u(T,"crtrPreviewRecords");const P=4;function d(n){return n.result}u(d,"record");function f(n,e){const t=n[e];return typeof t=="string"&&t!==""?t:void 0}u(f,"stringField");function x(n,e){return typeof n[e]=="boolean"?n[e]:void 0}u(x,"booleanField");function l(n,e){return typeof n[e]=="number"&&Number.isFinite(n[e])?n[e]:void 0}u(l,"numberField");function A(n,e){const t=n[e];return Array.isArray(t)&&t.every(r=>r!==null&&typeof r=="object"&&!Array.isArray(r))?t:void 0}u(A,"arrayField");function D(n){const e=n.replace(/[\\/]+$/,""),t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t===-1?e:e.slice(t+1)}u(D,"basename");function S(n,e){return n.length>e?`${n.slice(0,e).trimEnd()}\u2026`:n}u(S,"truncateLine");function $(n,e,t=5){const r=n.map(a=>f(a,e));if(r.some(a=>a===void 0))return;const s=r.slice(0,t),o=r.length-s.length;return o>0?`${s.join(", ")}, \u2026 ${o} more`:s.join(", ")}u($,"topNames");function j(n){const e=n.error;if(e===void 0)return null;const t=f(e,"error"),r=f(e,"message");return t===void 0||r===void 0?null:[{text:t,tone:"error"},{text:S(r,160),tone:"muted"}]}u(j,"summarizeError");function C(n){const e=d(n);if(e===void 0)return null;const t=f(e,"deleted")??f(e,"remote");if(t!==void 0)return[{text:t.trim().split(`
2
+ `)[0]??"",tone:"warning"}];const r=f(e,"object");if(r===void 0)return null;const s=r.split(`
3
+ `).filter(o=>o.trim()!==""&&!o.startsWith("<auto-loaded-context")&&!o.startsWith("</auto-loaded-context"));return s.length===0?null:[{text:s[0]},...s.slice(1,P).map(o=>({text:o,tone:"muted"}))]}u(C,"summarizeCanvasRead");function _(n,e=!1){return t=>{const r=d(t),s=r===void 0?void 0:l(r,"count")??l(r,"total");return s===void 0?null:s===0&&e?[{text:`PASS \xB7 no ${n}`,tone:"success"}]:[{text:`${s} ${n}`,tone:s===0?"muted":"plain"}]}}u(_,"summarizeCount");function c(n,e="items"){return t=>{const r=d(t);if(r===void 0)return null;const s=A(r,e),o=l(r,"total")??s?.length;if(s===void 0||o===void 0)return null;const a=[{text:`${o} ${n}`,tone:o===0?"muted":"plain"}],i=$(s,"name");return i!==void 0&&i!==""&&a.push({text:i,tone:"muted"}),a}}u(c,"summarizeArray");function O(n){const t=d(n)?.counts;if(t===null||typeof t!="object"||Array.isArray(t))return null;const r=Object.entries(t);if(r.some(([,a])=>typeof a!="number"))return null;const s=r.reduce((a,[,i])=>a+i,0);if(s===0)return[{text:"PASS \xB7 no pending asks",tone:"success"}];const o=r.filter(([,a])=>a>0).sort((a,i)=>i[1]-a[1])[0];return o===void 0?null:[{text:`${s} asks`,tone:"warning"},{text:`hottest: ${o[0]} (${o[1]})`,tone:"muted"}]}u(O,"summarizeAttentionMap");function m(n,e,t){return r=>{const s=d(r);if(s===void 0)return null;const o=x(s,n);if(o===void 0)return null;const a=l(s,"pid")??l(s,"existing_pid");return[{text:o?`${e}${a===void 0?"":` \xB7 pid ${a}`}`:t,tone:o?"success":"muted"}]}}u(m,"summarizeDaemon");function z(n){const e=d(n);if(e===void 0||f(e,"page_id")===void 0)return null;const t=x(e,"reply");return t===void 0?null:[{text:t?"page sent \u2192 waiting on human":"announcement sent",tone:t?"accent":"success"}]}u(z,"summarizeHumanSend");function E(n){const e=d(n);if(e===void 0)return null;const t=x(e,"resolved"),r=f(e,"job_id");return t===void 0||r===void 0?null:[{text:`${t?"resolved":"not resolved"} ${r}`,tone:t?"success":"warning"}]}u(E,"summarizeHumanResolve");function y(n){const e=d(n);if(e===void 0)return null;const t=f(e,"status");return t===void 0?null:[{text:t,tone:["done","success","submitted","filed"].includes(t)?"success":t==="failed"?"error":"plain"}]}u(y,"summarizeStatus");function F(n){const e=n.jsonl;if(e===void 0)return null;const t=e.filter(r=>f(r,"name")!==void 0&&l(r,"projects_count")!==void 0);return t.length===0&&e.length>0?null:[{text:`${t.length} profile${t.length===1?"":"s"}`},...t.slice(0,5).map(r=>({text:`${f(r,"name")} \xB7 ${l(r,"projects_count")} projects`,tone:"muted"}))]}u(F,"summarizeProfileList");const I=[{path:"canvas read",run:C},{path:"canvas list",run:c("objects")},{path:"canvas search",run:c("hits")},{path:"canvas attention count",run:_("pending asks",!0)},{path:"canvas attention list",run:c("pending asks")},{path:"canvas attention map",run:O},{path:"human send",run:z},{path:"human list",run:c("pending")},{path:"human resolve",run:E},{path:"pkg plugin list",run:c("plugins")},{path:"pkg market list",run:c("marketplaces")},{path:"pkg market browse",run:c("plugins")},{path:"canvas dashboard",run:c("nodes","rows")},{path:"node inspect list",run:c("nodes","nodes")},{path:"sys daemon start",run:m("started","started","already running")},{path:"sys daemon status",run:m("running","running","not running")},{path:"sys daemon stop",run:m("stopped","stopped","was not running")},{path:"sys update",run:y},{path:"sys feedback",run:y},{path:"profile list",run:F}];function V(n,e=[]){const t=j(n);return t!==null?t:I.find(({path:s})=>s===n.path)?.run(n,e)??null}u(V,"summarizePath");export{R as HELP_ICON,k as LEAF_ICON_CP,I as SUMMARIZERS,g as SUPPRESS_OUTPUT_LEAVES,H as TOOL_ICON,T as crtrPreviewRecords,U as iconForPath,V as summarizePath,N as suppressOutputForLeaf,M as suppressOutputForPath};
@@ -1,8 +1,9 @@
1
1
  import type { ProfileManifest } from '../../types.js';
2
- import type { ProfileProject, ProfileProjectMemory } from '../../api/dto/profiles.js';
2
+ import type { DeliveryLimits, ProfileProject, ProfileProjectMemory } from '../../api/dto/profiles.js';
3
3
  export declare const ROOT_PROFILE_ID = "root-00000000";
4
4
  export declare function profileMemoryDir(profileId: string): string;
5
5
  export declare function assertProfileProjects(entries: unknown): asserts entries is ProfileProject[];
6
+ export declare function assertDeliveryLimits(value: unknown): asserts value is DeliveryLimits;
6
7
  export interface ProfileEntry {
7
8
  profileId: string;
8
9
  manifest: ProfileManifest;
@@ -104,12 +105,11 @@ export declare function updateProfileMetadata(profileId: string, set: Record<str
104
105
  * over a bad profile id (mirrors `readProfileEnvVars`). */
105
106
  export declare function readProfileMetadata(profileId: string | null): Record<string, string>;
106
107
  export declare function renameProfile(profileId: string, name: string): ProfileEntry;
107
- /** Upsert: a new path appends, an existing one keeps its position and takes
108
- * the supplied memory value. Every caller names a memory value — a profile
109
- * relationship never acquires one by default. */
110
- export declare function addProfileProject(profileId: string, dir: string, opts: {
111
- memory: ProfileProjectMemory;
112
- }): ProfileEntry;
108
+ /** A new path appends; a path already listed keeps its position. */
109
+ export declare function addProfileProject(profileId: string, dir: string): ProfileEntry;
110
+ /** Set one owner's automatic delivery limit. `content` is the uncapped level,
111
+ * so it removes the owner's entry instead of storing it. */
112
+ export declare function setProfileDeliveryLimit(profileId: string, owner: string, level: ProfileProjectMemory): ProfileEntry;
113
113
  export declare function removeProfileProject(profileId: string, dir: string): ProfileEntry;
114
114
  export declare function deleteProfile(profileId: string): void;
115
115
  export {};