@north-light/crouter 0.3.352 → 0.3.354

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 (616) 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 +133 -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 +167 -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 +9 -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/04-orchestration-kernel.md +7 -7
  25. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
  27. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +2 -2
  28. package/dist/builtin-memory/crouter-concepts/INDEX.md +2 -2
  29. package/dist/builtin-memory/crouter-concepts/lifecycle-and-wakes.md +1 -1
  30. package/dist/builtin-memory/crouter-concepts/memory.md +15 -15
  31. package/dist/builtin-memory/crouter-concepts/nodes-and-the-canvas.md +1 -1
  32. package/dist/builtin-memory/crouter-concepts/profiles-kinds-and-modes.md +5 -5
  33. package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +1 -1
  34. package/dist/builtin-memory/crouter-concepts/why-a-daemon.md +1 -1
  35. package/dist/builtin-memory/crouter-sdk/INDEX.md +2 -2
  36. package/dist/builtin-memory/crouter-sdk/README.md +5 -6
  37. package/dist/builtin-memory/crouter-sdk/errors.md +0 -13
  38. package/dist/builtin-memory/crouter-sdk/guides/README.md +0 -1
  39. package/dist/builtin-memory/crouter-sdk/guides/event-driven-assistant.md +2 -2
  40. package/dist/builtin-memory/crouter-sdk/nodes.md +0 -2
  41. package/dist/builtin-memory/crouter-sdk/resources.md +0 -1
  42. package/dist/builtin-memory/explore/exploration-doc.md +4 -4
  43. package/dist/builtin-memory/insights/capture.md +6 -6
  44. package/dist/builtin-memory/insights/init.md +14 -14
  45. package/dist/builtin-memory/internal/INDEX.md +4 -4
  46. package/dist/builtin-memory/internal/agent-shaping.md +20 -20
  47. package/dist/builtin-memory/internal/examples/imessage-assistant.md +2 -2
  48. package/dist/builtin-memory/internal/marketplaces.md +2 -2
  49. package/dist/builtin-memory/internal/memory-loading.md +31 -30
  50. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  51. package/dist/builtin-memory/internal/plugins.md +16 -14
  52. package/dist/builtin-memory/internal/storage-tiers.md +4 -4
  53. package/dist/builtin-memory/memory-read-orientation.md +1 -1
  54. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +32 -40
  55. package/dist/clients/attach/input/controller.js +1 -1
  56. package/dist/clients/attach/input/ref-autocomplete.js +1 -1
  57. package/dist/clients/attach/input/titled-editor.js +1 -1
  58. package/dist/clients/attach/render/chat-view.js +1 -1
  59. package/dist/clients/attach/render/crtr-output.d.ts +1 -2
  60. package/dist/clients/attach/render/crtr-output.js +17 -17
  61. package/dist/clients/attach/render/group-activity.d.ts +8 -8
  62. package/dist/clients/attach/render/group-activity.js +2 -2
  63. package/dist/clients/attach/render/group-recap.js +1 -1
  64. package/dist/clients/attach/render/tool-calls.d.ts +1 -1
  65. package/dist/clients/attach/session/profile-files.js +1 -1
  66. package/dist/clients/attach/slash/dispatch.js +1 -1
  67. package/dist/clients/attach/viewer.js +806 -1553
  68. package/dist/commands/api-client.d.ts +2 -0
  69. package/dist/commands/api-client.js +3 -3
  70. package/dist/commands/canvas/edges.d.ts +2 -0
  71. package/dist/commands/canvas/edges.js +2 -0
  72. package/dist/commands/canvas/list.d.ts +4 -0
  73. package/dist/commands/canvas/list.js +3 -0
  74. package/dist/commands/canvas/read.d.ts +8 -0
  75. package/dist/commands/canvas/read.js +5 -0
  76. package/dist/commands/canvas/search.d.ts +2 -0
  77. package/dist/commands/canvas/search.js +3 -0
  78. package/dist/commands/canvas/unwatch.d.ts +2 -0
  79. package/dist/commands/canvas/unwatch.js +1 -0
  80. package/dist/commands/canvas/watch.d.ts +3 -0
  81. package/dist/commands/canvas/watch.js +1 -0
  82. package/dist/commands/canvas-analytics.js +1 -1
  83. package/dist/commands/canvas-history/grep.js +4 -4
  84. package/dist/commands/canvas-history/read.js +2 -2
  85. package/dist/commands/canvas-history/search.js +7 -7
  86. package/dist/commands/canvas-history/shared.d.ts +0 -1
  87. package/dist/commands/canvas-history/shared.js +1 -1
  88. package/dist/commands/canvas-history/stats.js +2 -2
  89. package/dist/commands/canvas-history.js +1 -1
  90. package/dist/commands/canvas.js +1 -1
  91. package/dist/commands/doc/delete.d.ts +2 -0
  92. package/dist/commands/doc/delete.js +1 -0
  93. package/dist/commands/doc/edit.d.ts +2 -0
  94. package/dist/commands/doc/edit.js +1 -0
  95. package/dist/commands/doc/history.d.ts +2 -0
  96. package/dist/commands/doc/history.js +2 -0
  97. package/dist/commands/doc/lint.d.ts +2 -0
  98. package/dist/commands/doc/lint.js +2 -0
  99. package/dist/commands/doc/list.d.ts +2 -0
  100. package/dist/commands/doc/list.js +1 -0
  101. package/dist/commands/doc/move.d.ts +2 -0
  102. package/dist/commands/doc/move.js +1 -0
  103. package/dist/commands/doc/read.d.ts +2 -0
  104. package/dist/commands/doc/read.js +1 -0
  105. package/dist/commands/doc/shared.d.ts +25 -0
  106. package/dist/commands/doc/shared.js +2 -0
  107. package/dist/commands/doc/write.d.ts +2 -0
  108. package/dist/commands/doc/write.js +1 -0
  109. package/dist/commands/{memory.d.ts → doc.d.ts} +1 -1
  110. package/dist/commands/doc.js +1 -0
  111. package/dist/commands/human/review.js +1 -1
  112. package/dist/commands/node/bash.js +2 -2
  113. package/dist/commands/node/create.js +1 -1
  114. package/dist/commands/node/inspect.js +10 -10
  115. package/dist/commands/node/lifecycle.js +2 -2
  116. package/dist/commands/node/outcome.js +1 -1
  117. package/dist/commands/node/subscription.js +1 -1
  118. package/dist/commands/node-context.js +2 -2
  119. package/dist/commands/pkg/browse/catalog.js +1 -1
  120. package/dist/commands/pkg/browse/doc-view.js +1 -1
  121. package/dist/commands/pkg/browse/model.d.ts +9 -17
  122. package/dist/commands/pkg/plugin-inspect.js +1 -1
  123. package/dist/commands/pkg/plugin-manage.d.ts +4 -8
  124. package/dist/commands/pkg/plugin-manage.js +15 -17
  125. package/dist/commands/profile/list.js +1 -1
  126. package/dist/commands/profile/new.js +1 -1
  127. package/dist/commands/profile/project.js +1 -1
  128. package/dist/commands/profile/show.js +1 -1
  129. package/dist/commands/push.js +3 -3
  130. package/dist/commands/sys/config.js +1 -1
  131. package/dist/commands/sys/context/admin/actions.d.ts +18 -43
  132. package/dist/commands/sys/context/admin/actions.js +1 -2
  133. package/dist/commands/sys/context/admin/detail-panel.d.ts +17 -25
  134. package/dist/commands/sys/context/admin/detail-panel.js +2 -1
  135. package/dist/commands/sys/context/admin/docs-panel.d.ts +7 -6
  136. package/dist/commands/sys/context/admin/docs-panel.js +1 -1
  137. package/dist/commands/sys/context/admin/list-view.d.ts +12 -12
  138. package/dist/commands/sys/context/admin/list-view.js +1 -1
  139. package/dist/commands/sys/context/admin/model.d.ts +96 -69
  140. package/dist/commands/sys/context/admin/model.js +1 -1
  141. package/dist/commands/sys/context/admin/rail-panel.d.ts +7 -5
  142. package/dist/commands/sys/context/admin/rail-panel.js +1 -1
  143. package/dist/commands/sys/context/admin/read-view.d.ts +10 -14
  144. package/dist/commands/sys/context/admin/read-view.js +1 -2
  145. package/dist/commands/sys/context/admin/shell.d.ts +26 -31
  146. package/dist/commands/sys/context/admin/shell.js +1 -1
  147. package/dist/commands/sys/context/admin.js +2 -2
  148. package/dist/commands/sys/context/doc.js +2 -3
  149. package/dist/commands/sys/context/expose.js +2 -2
  150. package/dist/commands/sys/context/prompt-review.js +4 -4
  151. package/dist/commands/sys/context/resolve.d.ts +92 -65
  152. package/dist/commands/sys/context/resolve.js +7 -9
  153. package/dist/commands/sys/context.js +1 -1
  154. package/dist/commands/sys/doctor.js +1 -1
  155. package/dist/commands/sys/migrate.js +1 -1
  156. package/dist/commands/sys/panels/profiles-panel.d.ts +3 -1
  157. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  158. package/dist/commands/sys/sync-deps.d.ts +6 -11
  159. package/dist/commands/sys/sync-deps.js +7 -8
  160. package/dist/commands/sys/sync-project-guidance.js +5 -4
  161. package/dist/commands/sys/sync-shared.d.ts +41 -4
  162. package/dist/commands/sys/sync-shared.js +1 -1
  163. package/dist/commands/sys/sync-skills.js +2 -2
  164. package/dist/commands/sys/sync.js +1 -1
  165. package/dist/core/bash-job-supervisor.d.ts +2 -3
  166. package/dist/core/bash-job-supervisor.js +3 -3
  167. package/dist/core/bash-jobs.d.ts +0 -5
  168. package/dist/core/bash-jobs.js +7 -7
  169. package/dist/core/bootstrap.js +2 -2
  170. package/dist/core/canvas/canvas.d.ts +6 -50
  171. package/dist/core/canvas/canvas.js +16 -21
  172. package/dist/core/canvas/db.d.ts +4 -1
  173. package/dist/core/canvas/db.js +2 -2
  174. package/dist/core/canvas/history.d.ts +11 -39
  175. package/dist/core/canvas/history.js +9 -20
  176. package/dist/core/canvas/install-id.d.ts +2 -2
  177. package/dist/core/canvas/install-id.js +1 -1
  178. package/dist/core/canvas/memory-reads.d.ts +5 -0
  179. package/dist/core/canvas/memory-reads.js +1 -1
  180. package/dist/core/canvas/migrations.js +215 -41
  181. package/dist/core/canvas/node-agent-paths.js +1 -1
  182. package/dist/core/canvas/node-tokens.js +1 -1
  183. package/dist/core/canvas/paths.d.ts +0 -4
  184. package/dist/core/canvas/paths.js +1 -1
  185. package/dist/core/canvas/remote-canvas-source.d.ts +0 -1
  186. package/dist/core/canvas/remote-canvas-source.js +1 -1
  187. package/dist/core/canvas/render-source.d.ts +9 -6
  188. package/dist/core/canvas/render-source.js +6 -6
  189. package/dist/core/canvas/sessions.js +2 -2
  190. package/dist/core/canvas/source.d.ts +6 -0
  191. package/dist/core/canvas/tree.d.ts +29 -0
  192. package/dist/core/canvas/tree.js +12 -0
  193. package/dist/core/canvas/types.d.ts +0 -20
  194. package/dist/core/command-plugins/bundle.js +1 -1
  195. package/dist/core/config.d.ts +1 -1
  196. package/dist/core/conversation-store/listener.js +4 -2
  197. package/dist/core/feed/feed.d.ts +9 -7
  198. package/dist/core/feed/feed.js +3 -7
  199. package/dist/core/feed/inbox.d.ts +3 -5
  200. package/dist/core/feed/inbox.js +1 -10
  201. package/dist/core/feed/messages.d.ts +33 -6
  202. package/dist/core/feed/messages.js +10 -7
  203. package/dist/core/feed/reports.d.ts +10 -0
  204. package/dist/core/feed/reports.js +2 -0
  205. package/dist/core/grants/remove.js +1 -1
  206. package/dist/core/graph/access.d.ts +24 -0
  207. package/dist/core/graph/access.js +8 -0
  208. package/dist/core/graph/bodies.d.ts +6 -0
  209. package/dist/core/graph/bodies.js +1 -0
  210. package/dist/core/graph/deletion.d.ts +9 -0
  211. package/dist/core/graph/deletion.js +5 -0
  212. package/dist/core/graph/diff.d.ts +4 -0
  213. package/dist/core/graph/diff.js +4 -0
  214. package/dist/core/graph/documents.d.ts +160 -0
  215. package/dist/core/graph/documents.js +7 -0
  216. package/dist/core/graph/edges.d.ts +24 -0
  217. package/dist/core/graph/edges.js +1 -0
  218. package/dist/core/graph/events.d.ts +26 -0
  219. package/dist/core/graph/events.js +6 -0
  220. package/dist/core/graph/exposures.d.ts +53 -0
  221. package/dist/core/graph/exposures.js +4 -0
  222. package/dist/core/graph/jobs.d.ts +31 -0
  223. package/dist/core/graph/jobs.js +2 -0
  224. package/dist/core/graph/names.d.ts +28 -0
  225. package/dist/core/graph/names.js +3 -0
  226. package/dist/core/graph/objects.d.ts +55 -0
  227. package/dist/core/graph/objects.js +9 -0
  228. package/dist/core/graph/package-docs.d.ts +31 -0
  229. package/dist/core/graph/package-docs.js +5 -0
  230. package/dist/core/graph/package-files.d.ts +20 -0
  231. package/dist/core/graph/package-files.js +2 -0
  232. package/dist/core/graph/reader.d.ts +21 -0
  233. package/dist/core/graph/reader.js +3 -0
  234. package/dist/core/graph/repo-sync/exchange.d.ts +34 -0
  235. package/dist/core/graph/repo-sync/exchange.js +2 -0
  236. package/dist/core/graph/repo-sync/identity.d.ts +30 -0
  237. package/dist/core/graph/repo-sync/identity.js +1 -0
  238. package/dist/core/graph/repo-sync/index.d.ts +4 -0
  239. package/dist/core/graph/repo-sync/index.js +1 -0
  240. package/dist/core/graph/repo-sync/mirror.d.ts +30 -0
  241. package/dist/core/graph/repo-sync/mirror.js +6 -0
  242. package/dist/core/graph/repo-sync/ref-format.d.ts +76 -0
  243. package/dist/core/graph/repo-sync/ref-format.js +2 -0
  244. package/dist/core/graph/repo-sync/repos.d.ts +17 -0
  245. package/dist/core/graph/repo-sync/repos.js +3 -0
  246. package/dist/core/graph/repo-sync/sync.d.ts +42 -0
  247. package/dist/core/graph/repo-sync/sync.js +2 -0
  248. package/dist/core/graph/rules.d.ts +26 -0
  249. package/dist/core/graph/rules.js +3 -0
  250. package/dist/core/graph/spaces/app.d.ts +3 -0
  251. package/dist/core/graph/spaces/app.js +1 -0
  252. package/dist/core/graph/spaces/index.d.ts +19 -0
  253. package/dist/core/graph/spaces/index.js +1 -0
  254. package/dist/core/graph/spaces/person.d.ts +5 -0
  255. package/dist/core/graph/spaces/person.js +2 -0
  256. package/dist/core/graph/spaces/repo.d.ts +4 -0
  257. package/dist/core/graph/spaces/repo.js +1 -0
  258. package/dist/core/graph/types.d.ts +75 -0
  259. package/dist/core/graph/types.js +1 -0
  260. package/dist/core/graph/watches.d.ts +62 -0
  261. package/dist/core/graph/watches.js +18 -0
  262. package/dist/core/human/feedback-companion.js +1 -1
  263. package/dist/core/human/requests.d.ts +3 -1
  264. package/dist/core/human/requests.js +6 -6
  265. package/dist/core/inspector/model.js +2 -2
  266. package/dist/core/io.js +5 -5
  267. package/dist/core/layout-migrate/index.d.ts +24 -1
  268. package/dist/core/layout-migrate/index.js +4 -4
  269. package/dist/core/layout-migrate/paths.d.ts +4 -0
  270. package/dist/core/layout-migrate/paths.js +1 -1
  271. package/dist/core/layout-migrate/stored-paths.d.ts +7 -0
  272. package/dist/core/layout-migrate/stored-paths.js +11 -11
  273. package/dist/core/layout-migrate/stores.d.ts +19 -6
  274. package/dist/core/layout-migrate/stores.js +3 -4
  275. package/dist/core/manifest.d.ts +0 -2
  276. package/dist/core/manifest.js +1 -1
  277. package/dist/core/{memory/extensions.d.ts → plugin-extensions.d.ts} +9 -10
  278. package/dist/core/plugin-extensions.js +1 -0
  279. package/dist/core/preview-registry.d.ts +1 -1
  280. package/dist/core/preview-registry.js +3 -2
  281. package/dist/core/profiles/manifest.d.ts +7 -7
  282. package/dist/core/profiles/manifest.js +1 -1
  283. package/dist/core/profiles/select.js +3 -3
  284. package/dist/core/review/birth.js +1 -1
  285. package/dist/core/review/companion.js +1 -1
  286. package/dist/core/review/stage.d.ts +12 -1
  287. package/dist/core/review/stage.js +1 -1
  288. package/dist/core/review/store.d.ts +2 -0
  289. package/dist/core/review/store.js +1 -1
  290. package/dist/core/review/types.d.ts +7 -1
  291. package/dist/core/runs/events.js +1 -1
  292. package/dist/core/runs/operations.js +5 -5
  293. package/dist/core/runs/questions.js +2 -2
  294. package/dist/core/runtime/bearings-render.d.ts +13 -7
  295. package/dist/core/runtime/bearings-render.js +12 -12
  296. package/dist/core/runtime/bearings.d.ts +8 -18
  297. package/dist/core/runtime/bearings.js +7 -7
  298. package/dist/core/runtime/broker/daemon-ops.d.ts +7 -12
  299. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  300. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  301. package/dist/core/runtime/broker/fault-retry.js +1 -1
  302. package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
  303. package/dist/core/runtime/broker/frame-memory-refs.d.ts +7 -2
  304. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  305. package/dist/core/runtime/broker/inbox.d.ts +1 -4
  306. package/dist/core/runtime/broker/inbox.js +1 -10
  307. package/dist/core/runtime/broker/rebind.js +1 -1
  308. package/dist/core/runtime/broker/retry-card-elision.d.ts +7 -0
  309. package/dist/core/runtime/broker/retry-card-elision.js +1 -0
  310. package/dist/core/runtime/broker-extension-render.d.ts +0 -13
  311. package/dist/core/runtime/broker-extension-render.js +2 -4
  312. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  313. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  314. package/dist/core/runtime/broker.js +1 -1
  315. package/dist/core/runtime/close.d.ts +9 -4
  316. package/dist/core/runtime/close.js +1 -1
  317. package/dist/core/runtime/deliver-live.js +1 -1
  318. package/dist/core/runtime/kickoff.js +17 -19
  319. package/dist/core/runtime/launch-target.d.ts +7 -0
  320. package/dist/core/runtime/launch-target.js +1 -1
  321. package/dist/core/runtime/ledger.d.ts +10 -0
  322. package/dist/core/runtime/ledger.js +3 -0
  323. package/dist/core/runtime/lifecycle.js +2 -2
  324. package/dist/core/runtime/nodes.d.ts +10 -2
  325. package/dist/core/runtime/nodes.js +1 -1
  326. package/dist/core/runtime/outcome-document.d.ts +2 -2
  327. package/dist/core/runtime/outcome-document.js +1 -1
  328. package/dist/core/runtime/persona.js +2 -2
  329. package/dist/core/runtime/placement.js +1 -1
  330. package/dist/core/runtime/promote.d.ts +2 -2
  331. package/dist/core/runtime/promote.js +1 -1
  332. package/dist/core/runtime/prospective-inventory-cli.js +2 -2
  333. package/dist/core/runtime/recycle.js +1 -1
  334. package/dist/core/runtime/reopen.js +1 -1
  335. package/dist/core/runtime/revive.js +2 -2
  336. package/dist/core/runtime/roadmap.d.ts +17 -9
  337. package/dist/core/runtime/roadmap.js +4 -4
  338. package/dist/core/runtime/spawn-env.js +1 -1
  339. package/dist/core/runtime/spawn.d.ts +5 -3
  340. package/dist/core/runtime/spawn.js +2 -2
  341. package/dist/core/runtime/structured-output.d.ts +3 -1
  342. package/dist/core/runtime/structured-output.js +4 -4
  343. package/dist/core/scope.d.ts +1 -32
  344. package/dist/core/scope.js +1 -1
  345. package/dist/core/scoped-state/db.js +2 -1
  346. package/dist/core/scoped-state/migrate.js +2 -2
  347. package/dist/core/scoped-state/profiles.d.ts +11 -0
  348. package/dist/core/scoped-state/profiles.js +1 -1
  349. package/dist/core/scoped-state/schema.d.ts +1 -1
  350. package/dist/core/scoped-state/schema.js +7 -5
  351. package/dist/core/spaces/permissions.d.ts +0 -14
  352. package/dist/core/spaces/permissions.js +1 -1
  353. package/dist/core/spaces/stop.d.ts +13 -0
  354. package/dist/core/spaces/stop.js +2 -2
  355. package/dist/core/storage/tables.d.ts +1 -1
  356. package/dist/core/substrate/delivery/corpus.d.ts +21 -0
  357. package/dist/core/substrate/delivery/corpus.js +3 -0
  358. package/dist/core/substrate/delivery/deliver.d.ts +76 -0
  359. package/dist/core/substrate/delivery/deliver.js +6 -0
  360. package/dist/core/substrate/delivery/listings.d.ts +27 -0
  361. package/dist/core/substrate/delivery/listings.js +4 -0
  362. package/dist/core/substrate/delivery/match.d.ts +28 -0
  363. package/dist/core/substrate/delivery/match.js +1 -0
  364. package/dist/core/substrate/delivery/plan.d.ts +67 -0
  365. package/dist/core/substrate/delivery/plan.js +3 -0
  366. package/dist/core/substrate/delivery/render-boot.d.ts +20 -0
  367. package/dist/core/substrate/delivery/render-boot.js +54 -0
  368. package/dist/core/substrate/delivery/render-event.d.ts +47 -0
  369. package/dist/core/substrate/delivery/render-event.js +6 -0
  370. package/dist/core/substrate/delivery/sub-persona-menu.d.ts +2 -0
  371. package/dist/core/substrate/delivery/sub-persona-menu.js +6 -0
  372. package/dist/core/substrate/delivery/types.d.ts +30 -0
  373. package/dist/core/substrate/delivery/types.js +0 -0
  374. package/dist/core/substrate/gate-explain.d.ts +0 -13
  375. package/dist/core/substrate/gate-explain.js +1 -1
  376. package/dist/core/substrate/schema.d.ts +11 -139
  377. package/dist/core/substrate/schema.js +1 -1
  378. package/dist/core/substrate/subject-fields.d.ts +3 -0
  379. package/dist/core/substrate/subject.d.ts +2 -1
  380. package/dist/core/substrate/subject.js +1 -1
  381. package/dist/daemon/api/app-listener.js +11 -11
  382. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  383. package/dist/daemon/api/handlers/bash-jobs.js +1 -2
  384. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  385. package/dist/daemon/api/handlers/canvas.js +5 -5
  386. package/dist/daemon/api/handlers/daemon.js +1 -1
  387. package/dist/daemon/api/handlers/delivery.d.ts +2 -0
  388. package/dist/daemon/api/handlers/delivery.js +1 -0
  389. package/dist/daemon/api/handlers/{memory.d.ts → docs.d.ts} +1 -1
  390. package/dist/daemon/api/handlers/docs.js +1 -0
  391. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  392. package/dist/daemon/api/handlers/messages.js +2 -2
  393. package/dist/daemon/api/handlers/modelauth.d.ts +3 -0
  394. package/dist/daemon/api/handlers/modelauth.js +1 -1
  395. package/dist/daemon/api/handlers/node-records.js +2 -2
  396. package/dist/daemon/api/handlers/nodes.js +1 -1
  397. package/dist/daemon/api/handlers/objects.d.ts +2 -0
  398. package/dist/daemon/api/handlers/objects.js +5 -0
  399. package/dist/daemon/api/handlers/package-docs.d.ts +2 -0
  400. package/dist/daemon/api/handlers/package-docs.js +1 -0
  401. package/dist/daemon/api/handlers/profiles.js +1 -1
  402. package/dist/daemon/api/handlers/reports.d.ts +2 -2
  403. package/dist/daemon/api/handlers/reports.js +4 -4
  404. package/dist/daemon/api/handlers/reviews.js +1 -1
  405. package/dist/daemon/api/handlers/vendor-status.d.ts +8 -0
  406. package/dist/daemon/api/handlers/vendor-status.js +1 -0
  407. package/dist/daemon/api/map.d.ts +2 -2
  408. package/dist/daemon/api/map.js +2 -2
  409. package/dist/daemon/api/operations.d.ts +1 -1
  410. package/dist/daemon/api/operations.js +1 -1
  411. package/dist/daemon/api/principal.d.ts +5 -0
  412. package/dist/daemon/api/principal.js +1 -1
  413. package/dist/daemon/api/reader.d.ts +17 -0
  414. package/dist/daemon/api/reader.js +1 -0
  415. package/dist/daemon/api/server.js +1 -1
  416. package/dist/daemon/control.d.ts +2 -3
  417. package/dist/daemon/crtrd.js +8 -6
  418. package/dist/daemon/fleet.js +4 -4
  419. package/dist/daemon/reconcilers/bash-deadline.d.ts +11 -1
  420. package/dist/daemon/reconcilers/bash-deadline.js +2 -1
  421. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  422. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  423. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  424. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  425. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -0
  426. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  427. package/dist/daemon/review/deliver.js +2 -2
  428. package/dist/daemon/review/finish.js +1 -1
  429. package/dist/hook-authoring.d.ts +0 -1
  430. package/dist/hook-authoring.js +3 -3
  431. package/dist/migrations/004-canvas-documents/apply.d.ts +10 -0
  432. package/dist/migrations/004-canvas-documents/apply.js +1 -0
  433. package/dist/migrations/004-canvas-documents/fields.d.ts +24 -0
  434. package/dist/migrations/004-canvas-documents/fields.js +2 -0
  435. package/dist/migrations/004-canvas-documents/index.d.ts +16 -0
  436. package/dist/migrations/004-canvas-documents/index.js +2 -0
  437. package/dist/migrations/004-canvas-documents/legacy/discover.d.ts +16 -0
  438. package/dist/migrations/004-canvas-documents/legacy/discover.js +1 -0
  439. package/dist/migrations/004-canvas-documents/legacy/history.d.ts +5 -0
  440. package/dist/migrations/004-canvas-documents/legacy/history.js +2 -0
  441. package/dist/migrations/004-canvas-documents/legacy/nested.d.ts +7 -0
  442. package/dist/migrations/004-canvas-documents/legacy/nested.js +1 -0
  443. package/dist/migrations/004-canvas-documents/legacy/parse.d.ts +14 -0
  444. package/dist/migrations/004-canvas-documents/legacy/parse.js +1 -0
  445. package/dist/migrations/004-canvas-documents/legacy/types.d.ts +91 -0
  446. package/dist/migrations/004-canvas-documents/legacy/types.js +0 -0
  447. package/dist/migrations/004-canvas-documents/legacy-edges.d.ts +6 -0
  448. package/dist/migrations/004-canvas-documents/legacy-edges.js +18 -0
  449. package/dist/migrations/004-canvas-documents/plan.d.ts +102 -0
  450. package/dist/migrations/004-canvas-documents/plan.js +3 -0
  451. package/dist/migrations/004-canvas-documents/pointers.d.ts +23 -0
  452. package/dist/migrations/004-canvas-documents/pointers.js +4 -0
  453. package/dist/migrations/activation.d.ts +9 -18
  454. package/dist/migrations/activation.js +2 -2
  455. package/dist/pi-extensions/broker-local.d.ts +2 -2
  456. package/dist/pi-extensions/broker-local.js +2 -2
  457. package/dist/pi-extensions/canvas-bash-valve.js +5 -4
  458. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  459. package/dist/pi-extensions/canvas-doc-substrate.d.ts +0 -1
  460. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  461. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  462. package/dist/pi-extensions/canvas-passive-context.js +1 -1
  463. package/dist/pi-extensions/canvas-recap.js +2 -2
  464. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  465. package/dist/pi-extensions/canvas-stophook.js +1 -1
  466. package/dist/prompts/review.js +3 -3
  467. package/dist/shared/env.d.ts +5 -0
  468. package/dist/shared/env.js +1 -1
  469. package/dist/shared/generated-context.js +2 -10
  470. package/dist/shared/inbox-entry-body.d.ts +22 -0
  471. package/dist/shared/inbox-entry-body.js +10 -0
  472. package/dist/{core/memory → shared}/inline-ref-guidance.d.ts +2 -2
  473. package/dist/shared/inline-ref-guidance.js +2 -0
  474. package/dist/types.d.ts +3 -1
  475. package/docs/cli/memory-and-preferences.md +12 -14
  476. package/docs/concepts/README.md +1 -1
  477. package/docs/concepts/lifecycle-and-wakes.md +1 -1
  478. package/docs/concepts/memory.md +15 -15
  479. package/docs/concepts/nodes-and-the-canvas.md +1 -1
  480. package/docs/concepts/profiles-kinds-and-modes.md +5 -5
  481. package/docs/concepts/scopes-and-trust.md +1 -1
  482. package/docs/concepts/why-a-daemon.md +1 -1
  483. package/docs/sdk/README.md +5 -6
  484. package/docs/sdk/errors.md +0 -13
  485. package/docs/sdk/guides/README.md +0 -1
  486. package/docs/sdk/nodes.md +0 -2
  487. package/docs/sdk/resources.md +0 -1
  488. package/package.json +2 -2
  489. package/packages/crouter-identity/package.json +1 -1
  490. package/runtime.lock.json +11 -11
  491. package/dist/api/dto/memory.d.ts +0 -171
  492. package/dist/api/dto/memory.js +0 -1
  493. package/dist/builtin-memory/crouter-sdk/guides/app-memory.md +0 -73
  494. package/dist/builtin-memory/crouter-sdk/memory.md +0 -87
  495. package/dist/commands/broker-permissions.d.ts +0 -2
  496. package/dist/commands/broker-permissions.js +0 -1
  497. package/dist/commands/memory/client.d.ts +0 -11
  498. package/dist/commands/memory/client.js +0 -1
  499. package/dist/commands/memory/delete.d.ts +0 -1
  500. package/dist/commands/memory/delete.js +0 -1
  501. package/dist/commands/memory/edit.d.ts +0 -1
  502. package/dist/commands/memory/edit.js +0 -21
  503. package/dist/commands/memory/find.d.ts +0 -1
  504. package/dist/commands/memory/find.js +0 -1
  505. package/dist/commands/memory/history.d.ts +0 -1
  506. package/dist/commands/memory/history.js +0 -5
  507. package/dist/commands/memory/lint.d.ts +0 -1
  508. package/dist/commands/memory/lint.js +0 -1
  509. package/dist/commands/memory/list.d.ts +0 -1
  510. package/dist/commands/memory/list.js +0 -1
  511. package/dist/commands/memory/move.d.ts +0 -1
  512. package/dist/commands/memory/move.js +0 -1
  513. package/dist/commands/memory/origin.d.ts +0 -1
  514. package/dist/commands/memory/origin.js +0 -1
  515. package/dist/commands/memory/read.d.ts +0 -1
  516. package/dist/commands/memory/read.js +0 -6
  517. package/dist/commands/memory/shared.d.ts +0 -22
  518. package/dist/commands/memory/shared.js +0 -1
  519. package/dist/commands/memory/write.d.ts +0 -1
  520. package/dist/commands/memory/write.js +0 -13
  521. package/dist/commands/memory.js +0 -1
  522. package/dist/commands/node-inspect-artifacts.d.ts +0 -1
  523. package/dist/commands/node-inspect-artifacts.js +0 -8
  524. package/dist/core/help/memory-extensions.d.ts +0 -3
  525. package/dist/core/help/memory-extensions.js +0 -2
  526. package/dist/core/memory/cli-selector.d.ts +0 -13
  527. package/dist/core/memory/cli-selector.js +0 -1
  528. package/dist/core/memory/doc-link-grammar.d.ts +0 -20
  529. package/dist/core/memory/doc-link-grammar.js +0 -2
  530. package/dist/core/memory/extensions.js +0 -1
  531. package/dist/core/memory/history.d.ts +0 -87
  532. package/dist/core/memory/history.js +0 -6
  533. package/dist/core/memory/identity.d.ts +0 -65
  534. package/dist/core/memory/identity.js +0 -1
  535. package/dist/core/memory/inline-ref-guidance.js +0 -2
  536. package/dist/core/memory/inline-ref-inventory.d.ts +0 -9
  537. package/dist/core/memory/inline-ref-inventory.js +0 -1
  538. package/dist/core/memory/lint.d.ts +0 -163
  539. package/dist/core/memory/lint.js +0 -2
  540. package/dist/core/memory/mutation-domain.d.ts +0 -113
  541. package/dist/core/memory/mutation-domain.js +0 -12
  542. package/dist/core/memory/mutations.d.ts +0 -74
  543. package/dist/core/memory/mutations.js +0 -1
  544. package/dist/core/memory/project-namespace.d.ts +0 -31
  545. package/dist/core/memory/project-namespace.js +0 -2
  546. package/dist/core/memory/repository-association.d.ts +0 -31
  547. package/dist/core/memory/repository-association.js +0 -1
  548. package/dist/core/memory/service.d.ts +0 -145
  549. package/dist/core/memory/service.js +0 -2
  550. package/dist/core/memory/tree.d.ts +0 -39
  551. package/dist/core/memory/tree.js +0 -1
  552. package/dist/core/memory-resolver.d.ts +0 -280
  553. package/dist/core/memory-resolver.js +0 -2
  554. package/dist/core/nested-stores.d.ts +0 -18
  555. package/dist/core/nested-stores.js +0 -1
  556. package/dist/core/runtime/memory.d.ts +0 -3
  557. package/dist/core/runtime/memory.js +0 -1
  558. package/dist/core/substrate/frontmatter-validation.d.ts +0 -11
  559. package/dist/core/substrate/frontmatter-validation.js +0 -1
  560. package/dist/core/substrate/gate.d.ts +0 -16
  561. package/dist/core/substrate/gate.js +0 -1
  562. package/dist/core/substrate/index.d.ts +0 -18
  563. package/dist/core/substrate/index.js +0 -1
  564. package/dist/core/substrate/injected-store.d.ts +0 -75
  565. package/dist/core/substrate/injected-store.js +0 -2
  566. package/dist/core/substrate/listings.d.ts +0 -28
  567. package/dist/core/substrate/listings.js +0 -1
  568. package/dist/core/substrate/memory-events.d.ts +0 -6
  569. package/dist/core/substrate/memory-events.js +0 -1
  570. package/dist/core/substrate/on-read-node.d.ts +0 -6
  571. package/dist/core/substrate/on-read-node.js +0 -1
  572. package/dist/core/substrate/on-read.d.ts +0 -101
  573. package/dist/core/substrate/on-read.js +0 -9
  574. package/dist/core/substrate/plan.d.ts +0 -94
  575. package/dist/core/substrate/plan.js +0 -1
  576. package/dist/core/substrate/render-node.d.ts +0 -12
  577. package/dist/core/substrate/render-node.js +0 -1
  578. package/dist/core/substrate/render.d.ts +0 -41
  579. package/dist/core/substrate/render.js +0 -65
  580. package/dist/core/substrate/session-cache.d.ts +0 -27
  581. package/dist/core/substrate/session-cache.js +0 -1
  582. package/dist/core/substrate/surface-match.d.ts +0 -73
  583. package/dist/core/substrate/surface-match.js +0 -1
  584. package/dist/daemon/api/handlers/memory.js +0 -5
  585. package/dist/migrations/001-surfaces-frontmatter.d.ts +0 -2
  586. package/dist/migrations/001-surfaces-frontmatter.js +0 -1
  587. package/dist/migrations/002-profile-project-memory.d.ts +0 -2
  588. package/dist/migrations/002-profile-project-memory.js +0 -1
  589. package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +0 -26
  590. package/dist/migrations/003-repository-root-memory-identity/front-door.js +0 -11
  591. package/dist/migrations/003-repository-root-memory-identity/index.d.ts +0 -2
  592. package/dist/migrations/003-repository-root-memory-identity/index.js +0 -5
  593. package/dist/migrations/003-repository-root-memory-identity/references.d.ts +0 -95
  594. package/dist/migrations/003-repository-root-memory-identity/references.js +0 -5
  595. package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +0 -39
  596. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +0 -3
  597. package/dist/migrations/convergent.d.ts +0 -43
  598. package/dist/migrations/convergent.js +0 -2
  599. package/dist/migrations/corpus.d.ts +0 -75
  600. package/dist/migrations/corpus.js +0 -3
  601. package/dist/migrations/frontmatter-splice.d.ts +0 -15
  602. package/dist/migrations/frontmatter-splice.js +0 -8
  603. package/dist/migrations/profile-manifests.d.ts +0 -30
  604. package/dist/migrations/profile-manifests.js +0 -2
  605. package/dist/migrations/registry.d.ts +0 -7
  606. package/dist/migrations/registry.js +0 -1
  607. package/dist/migrations/runner.d.ts +0 -43
  608. package/dist/migrations/runner.js +0 -1
  609. package/dist/migrations/types.d.ts +0 -211
  610. package/dist/shared/birth-announcement.d.ts +0 -12
  611. package/dist/shared/birth-announcement.js +0 -1
  612. package/docs/sdk/guides/app-memory.md +0 -22
  613. package/docs/sdk/memory.md +0 -85
  614. /package/dist/{migrations/types.js → api/dto/delivery.js} +0 -0
  615. /package/dist/{core/memory → shared}/inline-ref-grammar.d.ts +0 -0
  616. /package/dist/{core/memory → shared}/inline-ref-grammar.js +0 -0
@@ -1 +1 @@
1
- var h=Object.defineProperty;var u=(n,t)=>h(n,"name",{value:t,configurable:!0});import{defineLeaf as m}from"../../core/command.js";import{general as f,usage as y}from"../../core/errors.js";import{resolve as w}from"node:path";import{pathExists as g}from"../../core/fs-utils.js";import{cliClient as v,rethrowAsCliError as b}from"../api-client.js";import{layoutNeedsMigration as _}from"../../core/layout.js";import{migrateLayout as k}from"../../core/layout-migrate/index.js";const $=m({name:"migrate",description:"migrate an old runtime layout offline, then converge profile and memory formats",whenToUse:"after a crtr update whose release notes name a state migration, when profiles stop resolving on a home that predates the update, or when old-format docs resurface (a restore, a sync, a hand-authored file). Convergent and idempotent: re-running over current state changes nothing, so use --dry-run first only when you want to review the rewrite.",help:{name:"sys migrate",summary:"move an old runtime layout offline before running daemon-owned profile and memory migrations",guide:"A layout migration requires the daemon to be stopped and runs in this process. It moves runtime files, rewrites stored paths, and writes the layout version last, then stops. Start the daemon and run `crtr sys migrate` again: the daemon then runs profile and memory migrations. Discovery decides what is migrated: the profiles and the projects they name, the ancestors of this directory, every nested store below any project root it reaches (a node's recorded cwd included), every installed plugin (disabled included), the node stores holding documents, and builtin as read-only input. A store outside that frontier is invisible to the run \u2014 add it with --dir; discovery_roots reports the frontier the run actually searched. A migration that changes a canonical identity plans across the whole corpus at once and applies in two phases, every reference rewrite before any identity rewrite, so one blocker writes nothing anywhere.",params:[{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Plan and report every rewrite without writing any file."},{kind:"flag",name:"dir",type:"path",required:!1,repeatable:!0,constraint:"Project directory (the one containing `.crouter/`, not the memory dir) to add to discovery, once per occurrence. For a store no profile names and this directory does not sit under. The path must exist."}],output:[{name:"layout_moved",type:"number",required:!1,constraint:"Old-layout paths moved or stored paths rewritten on this run; present when the layout migration ran."},{name:"layout_absent_credentials",type:"string[]",required:!1,constraint:"Old credential files the layout migration looked for and did not find (or, under --dry-run, will not find); present when the layout migration ran. An absent file is legitimate when the old home never held that credential."},{name:"profiles",type:"number",required:!1,constraint:"Profile manifests scanned after the layout migration completed."},{name:"stores",type:"number",required:!1,constraint:"Memory stores discovered, deduped by realpath. Builtin is counted: it is read-only corpus input."},{name:"changed",type:"number",required:!1,constraint:"Files rewritten (or, under --dry-run, that would be) \u2014 manifests, per-store documents, and corpus phases together."},{name:"applied",type:"object[]",required:!1,constraint:"One row per migration that changed files: {store, lane, migration, files}, lane one of profile-manifest, convergent, corpus. Empty when the state is already current."},{name:"skipped",type:"object[]",required:!1,constraint:"Files left untouched because they could not be parsed \u2014 a doc whose frontmatter is not valid YAML, or a manifest that is not valid JSON: {store, relPath, error}. Fix the file, then re-run."},{name:"blockers",type:"object[]",required:!1,constraint:"Why the corpus lane may not write: {kind, message, store?, target?, path?, name?, paths?}. kind is inaccessible-root, inaccessible-target, parse-failure, namespace, association, front-door, divergent-reference, unsafe-route, collision, package-owned-corpus, or verification. A non-empty list with a corpus migration registered fails the run, and `received` carries this whole report plus {corpus_phase, wrote} \u2014 corpus_phase is not-started (the corpus is untouched), planned (--dry-run), or written (both phases landed and verification then failed, so `wrote` is the inventory on disk)."},{name:"discovery_roots",type:"object[]",required:!1,constraint:"The frontier searched: {reason, root, boundary, detail?}. reason is user, profile, profile-project, cwd-ancestor, descendant, node, plugin, builtin, or explicit-dir; boundary is store, ancestors, descendants, plugins, or nodes."},{name:"discovered_stores",type:"object[]",required:!1,constraint:"One row per physical store: {store, scope, namespace, mount_status, writable, reasons, targets, docs}. reasons holds every way the store was reached; targets the target ids that mount it; docs its parseable document count."},{name:"discovered_targets",type:"object[]",required:!1,constraint:"One row per resolution view: {id, kind, origin, cwd, profile_id, node_id, stores}. stores lists store keys in that target's precedence order."},{name:"repository_namespaces",type:"object[]",required:!1,constraint:"Repository-root namespace decisions this run makes: {repository_root, repository_key, declaration_path, namespace, source, action}. A nested store inherits this declaration; its reported effective prefix is not a declaration."},{name:"store_prefixes",type:"object[]",required:!1,constraint:"Effective prefix facts for each project store: {store_root, owner_dir, repository_root, owner_relative_path, old_prefix, old_rule, effective_prefix, nested_declaration_action, front_door_action}. A nonempty owner_relative_path always reports front_door_action `none`; a nested effective_prefix is derived, not a declaration."},{name:"renames",type:"object[]",required:!1,constraint:"Canonical identity changes: {store_root, path, from, to}."},{name:"references",type:"object[]",required:!1,constraint:"Rewritten pointers at a changed identity: {store_root, path, kind, from, to}, kind link or memory-read."},{name:"dryRun",type:"boolean",required:!0,constraint:"True when nothing was written (preview only)."},{name:"resumed",type:"boolean",required:!1,constraint:"True only when this repair resumed the blocked daemon startup."},{name:"resume_error",type:"string",required:!1,constraint:"Present when corpus repair succeeded but normal daemon startup then failed."}],outputKind:"object",effects:["With an old layout and no layout version, refuses while a daemon answers, moves the runtime records, rewrites stored paths and writes the layout version last, then stops; the next run, with the daemon started, runs the daemon-owned state migration.","After layout migration is complete, the daemon that owns this canvas runs the migration. Rewrites old-format `profile.json` manifests in place (atomic, under the same per-profile lock `profile project add/remove` take). A manifest whose structure cannot be converted fails the whole run \u2014 no project setting is ever guessed.","Rewrites old-format memory documents in place (atomic per-file writes) across every writable discovered store: profiles, profile-owned projects, this directory's ancestors, nested descendant stores, installed plugin stores, and node stores. Builtin docs are package-owned and never touched.","Applies corpus-wide identity changes in two ordered phases across every writable store, after the global plan comes back blocker-free; a post-write pass re-reads the corpus from disk and verifies it.","Under --dry-run: read-only, writes nothing."]},run:u(async n=>{const t=n.dryRun===!0,d=(n.dir??[]).map(r=>w(r)),i=d.filter(r=>!g(r));if(i.length>0)throw y(`--dir path does not exist: ${i.join(", ")}`,{received:i,field:"dir",next:"Pass the project directory that contains `.crouter/`, or omit --dir to migrate the discovered frontier only."});const o=_()?await k(t):null;if(t&&o!==null)return{layout_moved:o.moved,layout_absent_credentials:o.absentCredentials,dryRun:t,follow_up:"Preview only \u2014 re-run without --dry-run to migrate the layout."};if(o!==null)return{layout_moved:o.moved,layout_absent_credentials:o.absentCredentials,dryRun:t,follow_up:"Layout migrated. Start the daemon, then run `crtr sys migrate` again against it (in a container, `docker compose exec`) to converge profile and memory formats."};let e;try{e=await v().migrateState({dry_run:t,dirs:d})}catch(r){b(r)}if(e.blocked){const r=e.blockers,c=e.applied.filter(s=>s.lane!=="corpus").flatMap(s=>s.files),a=e.corpus_phase,l=e.wrote,p=t?"\u2014 this was a --dry-run; nothing was written":a==="written"?`after both write phases \u2014 ${l.corpus_consumers.length} reference and ${l.corpus_identities.length} identity rewrite(s) are on disk and are NOT rolled back`:c.length>0?`before any corpus write \u2014 the corpus is unchanged, but ${c.length} earlier manifest/document rewrite(s) are already on disk`:"\u2014 nothing was written";throw f(`corpus migration ${a==="written"?"verification failed with":"blocked by"} ${r.length} finding(s) ${p}`,{received:e,next:a==="written"?"Resolve every verification finding against the files listed in received.wrote.corpus_identities and .corpus_consumers, then re-run `crtr sys migrate` \u2014 the lane converges from file truth.":"Resolve every blocker, then re-run `crtr sys migrate` \u2014 the earlier lanes are convergent and re-running them is a no-op."})}return{...e,follow_up:e.skipped.length>0?"Some files could not be parsed and were left untouched \u2014 fix each named file, then re-run `crtr sys migrate`.":e.changed===0?"State already current \u2014 nothing to rewrite.":t?"Preview only \u2014 re-run without --dry-run to write these changes.":void 0}},"run")});export{$ as sysMigrateLeaf};
1
+ var s=Object.defineProperty;var n=(o,e)=>s(o,"name",{value:e,configurable:!0});import{defineLeaf as i}from"../../core/command.js";import{general as d}from"../../core/errors.js";import{cliClient as l,rethrowAsCliError as u}from"../api-client.js";import{layoutNeedsMigration as m}from"../../core/layout.js";import{migrateLayout as h}from"../../core/layout-migrate/index.js";const v=i({name:"migrate",description:"migrate an old runtime layout offline, then import the legacy memory stores into the canvas",whenToUse:"when the daemon reports startup `blocked` by the canvas import, or after moving from a release that kept memory as markdown stores. Run --dry-run first to see the plan and what it resolves; a write run on an imported home does nothing.",help:{name:"sys migrate",summary:"move an old runtime layout offline, then plan or run the daemon-owned canvas import",guide:"A layout migration requires the daemon to be stopped, runs in this process, and stops after writing the layout version; start the daemon and run `crtr sys migrate` again. The daemon then plans the canvas import: every legacy store (the user store, each profile store, every repository `.crouter/memory` reached from a profile project or a node's cwd, node context folders and reports) becomes documents with their revision history, owned by the person, a profile, a repo, or a node. Both stages resolve leftovers and clashes themselves (a folder with no node row is set aside, two repos with one namespace get distinct handles, an unparseable file imports as its raw text, and so on) and list each in `layout_resolutions` and `resolutions`, on the dry run too. The daemon runs the import itself at startup; only a blocker (the store migrations of a skipped release never ran) makes it write nothing and hold startup in `blocked`. The import writes in one transaction and resumes startup. The markdown files are left on disk and are never read again.",params:[{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Plan and report without writing. On an imported home, returns the recorded report with pending false."}],output:[{name:"layout_moved",type:"number",required:!1,constraint:"Old-layout paths moved or stored paths rewritten on this run; present when the layout migration ran."},{name:"layout_resolutions",type:"string[]",required:!1,constraint:"One line per leftover the layout migration resolved (or, under --dry-run, will resolve): set-aside folders, moved profile files, closed worktree rows, cleared transcript paths."},{name:"layout_absent_credentials",type:"string[]",required:!1,constraint:"Old credential files the layout migration looked for and did not find (or, under --dry-run, will not find); present when the layout migration ran. An absent file is legitimate when the old home never held that credential."},{name:"stores",type:"object[]",required:!1,constraint:"Every store root found: {root, owner, docs, skipped?}; skipped is duplicate-worktree for a second checkout of an imported repo."},{name:"counts",type:"object",required:!1,constraint:"Planned (or written) totals: documents.<kind>, documents.owner.<person|profile|repo|node>, revisions, documents.rewritten, owners, stores, profile-limits, and informational counts. Empty on a write run over an imported home."},{name:"rewrites",type:"object[]",required:!1,constraint:"Pointer rewrites in head bodies: {path, from, to}."},{name:"dropped_fields",type:"object[]",required:!1,constraint:"Frontmatter fields with no canvas equivalent: {path, field}."},{name:"skipped",type:"object[]",required:!1,constraint:"Files or roots not imported, with the reason: {path, reason}."},{name:"resolutions",type:"object[]",required:!1,constraint:"Clashes the import resolved itself: {kind, message, paths}; kind is invalid-source, invalid-history, name-clash, repo-handle, profile-handle, repo-identity, or delivery-limit."},{name:"blockers",type:"object[]",required:!1,constraint:"{kind, message, paths}; kind is marker (the store migrations of a skipped release never ran). A blocker makes the command fail with this whole report in `received`; nothing is written."},{name:"dryRun",type:"boolean",required:!0,constraint:"True when nothing was written."},{name:"pending",type:"boolean",required:!1,constraint:"True while this home has not been imported."},{name:"resumed",type:"boolean",required:!1,constraint:"True only when this run resumed a blocked daemon startup."},{name:"resume_error",type:"string",required:!1,constraint:"Present when the import succeeded but normal daemon startup then failed."}],outputKind:"object",effects:["With an old layout and no layout version, refuses while a daemon answers, moves the runtime records, sets aside leftovers under runtime/set-aside/, rewrites stored paths and writes the layout version last, then stops; the next run, with the daemon started, plans or runs the canvas import.","Without --dry-run and with no blockers: stores revision bodies, converts profile project memory caps into profile delivery limits, and writes owners, documents, revisions, links, and the authoring nodes' watches in one canvas transaction, recorded so it runs once.","Under --dry-run: read-only, writes nothing."]},run:n(async o=>{const e=o.dryRun===!0,t=m()?await h(e):null;if(e&&t!==null)return{layout_resolutions:t.resolutions,layout_absent_credentials:t.absentCredentials,dryRun:e,follow_up:"Preview only \u2014 re-run without --dry-run to migrate the layout; the canvas import is planned after it."};if(t!==null)return{layout_moved:t.moved,layout_resolutions:t.resolutions,layout_absent_credentials:t.absentCredentials,dryRun:e,follow_up:"Layout migrated. Start the daemon (in a container, `docker compose exec`), then run `crtr sys migrate --dry-run` against it to plan the canvas import."};let r;try{r=await l().migrateState({dry_run:e})}catch(a){u(a)}if(r.blockers.length>0)throw d(`canvas import blocked by ${r.blockers.length} finding(s) \u2014 nothing was written`,{received:r,next:"Do what received.blockers[].message says, then run `crtr sys migrate` again."});return{...r,follow_up:r.pending?"Preview only \u2014 re-run without --dry-run to import.":e?"Already imported \u2014 this is the recorded report.":void 0}},"run")});export{v as sysMigrateLeaf};
@@ -4,6 +4,7 @@ export declare class ProfilesPanel implements SetupPanel {
4
4
  private readonly onChange;
5
5
  private readonly nameInput;
6
6
  private readonly dirInput;
7
+ private readonly limitInput;
7
8
  private entries;
8
9
  private listIndex;
9
10
  private dirIndex;
@@ -48,7 +49,8 @@ export declare class ProfilesPanel implements SetupPanel {
48
49
  private togglePin;
49
50
  private submitName;
50
51
  private submitDir;
51
- private cycleMemory;
52
+ /** `<owner handle> <level>` sets one entry of the profile's `delivery_limits`. */
53
+ private submitLimit;
52
54
  private askRemoveDir;
53
55
  private removeDir;
54
56
  private togglePause;
@@ -1 +1 @@
1
- var L=Object.defineProperty;var g=(m,e)=>L(m,"name",{value:e,configurable:!0});import{envNodeId as R}from"../../../shared/env.js";import{Input as C,matchesKey as I,truncateToWidth as u}from"@earendil-works/pi-tui";import{basename as O}from"node:path";import{PROFILE_PROJECT_MEMORY_VALUES as v}from"../../../api/dto/profiles.js";import{cliClient as E}from"../../api-client.js";import{clearDefaultProfile as N,defaultProfileDirs as F,getDefaultProfileId as S,setDefaultProfileId as H}from"../../../core/profiles/default-binding.js";import{ROOT_PROFILE_ID as P,addProfileProject as w,createProfile as V,listProfiles as A,pauseProfile as U,removeProfileProject as W,renameProfile as B,resumeProfile as J}from"../../../core/profiles/manifest.js";import{tildify as l}from"../../../core/fs-utils.js";import{profileCoversCwd as M}from"../../../core/profiles/select.js";import{padAnsi as h,theme as o,visibleRange as _,wrapText as j}from"../../../core/tui/panel.js";function D(m){if(m===null)return"never used";const e=Date.parse(m);if(Number.isNaN(e))return"used recently";const t=Math.max(0,Math.floor((Date.now()-e)/1e3));if(t<60)return"used just now";const n=Math.floor(t/60);if(n<60)return`used ${n}m ago`;const i=Math.floor(n/60);if(i<24)return`used ${i}h ago`;const s=Math.floor(i/24);if(s<30)return`used ${s}d ago`;const r=Math.floor(s/30);return r<12?`used ${r}mo ago`:`used ${Math.floor(r/12)}y ago`}g(D,"relativeUsed");function T(m){return m instanceof Error?m.message:String(m)}g(T,"messageOf");class ie{static{g(this,"ProfilesPanel")}cwd;onChange;nameInput=new C;dirInput=new C;entries=[];listIndex=0;dirIndex=0;mode="list";openId=null;notice;noticeTone="success";mutating=!1;constructor(e,t){this.cwd=e,this.onChange=t,this.nameInput.onSubmit=()=>{this.submitName(),this.onChange()},this.nameInput.onEscape=()=>{this.mode=this.openId!==null?"detail":"list",this.leaveField(),this.onChange()},this.dirInput.onSubmit=()=>{this.submitDir(),this.onChange()},this.dirInput.onEscape=()=>{this.mode="detail",this.leaveField(),this.onChange()},this.reload()}badge(){return String(this.entries.length)}ownsInput(e){return this.mode==="list"?!1:this.mode==="detail"?I(e,"escape")||I(e,"left"):!0}reload(){const e=g(i=>i.profileId===P?2:M(i,this.cwd)?0:1,"rank"),t=g(i=>i.manifest.last_used_at??"","used");this.entries=A().sort((i,s)=>{const r=e(i)-e(s);if(r!==0)return r;const d=t(s).localeCompare(t(i));return d!==0?d:i.manifest.name.localeCompare(s.manifest.name)}),this.listIndex>=this.entries.length&&(this.listIndex=Math.max(0,this.entries.length-1));const n=this.open();n===null?(this.mode!=="list"&&(this.mode="list"),this.openId=null):this.dirIndex>=n.manifest.projects.length&&(this.dirIndex=Math.max(0,n.manifest.projects.length-1))}selected(){return this.entries[this.listIndex]??null}open(){return this.openId===null?null:this.entries.find(e=>e.profileId===this.openId)??null}currentDir(){return this.open()?.manifest.projects[this.dirIndex]??null}pinnedHere(){return S(this.cwd)}say(e,t="success"){this.notice=e,this.noticeTone=t}attempt(e,t){try{e(),this.reload(),this.say(t)}catch(n){this.say(T(n),"warning")}}handleInput(e,t){const n=this.route(e,t);return n&&this.onChange(),n}route(e,t){switch(this.mode){case"new-name":case"rename":return this.routeText(this.nameInput,e);case"add-dir":return this.routeText(this.dirInput,e);case"confirm-delete":return this.routeConfirm(e,()=>{this.deleteOpen()});case"confirm-remove-dir":return this.routeConfirm(e,()=>this.removeDir());case"detail":return this.routeDetail(e,t);case"list":return this.routeList(e,t)}}routeText(e,t){return e.handleInput(t),!0}routeConfirm(e,t){const n=e.toLowerCase();return n==="y"?t():(n==="n"||I(e,"escape")||I(e,"return"))&&(this.mode=this.openId!==null?"detail":"list",this.say("Cancelled.")),!0}routeList(e,t){if(t?.("crtr.setup.list-down",e)===!0)return this.move(1),!0;if(t?.("crtr.setup.list-up",e)===!0)return this.move(-1),!0;if(t?.("crtr.setup.advance",e)===!0){const n=this.selected();return n!==null&&(this.openId=n.profileId,this.dirIndex=0,this.mode="detail",this.notice=void 0),!0}switch(e.toLowerCase()){case"a":return this.addCwdTo(this.selected());case"d":return this.togglePin();case"n":return this.mode="new-name",this.edit(this.nameInput,O(this.cwd)||"profile"),!0;case"x":return this.askDelete();default:return!1}}routeDetail(e,t){const n=this.open();if(n===null)return this.mode="list",!0;if(I(e,"escape")||I(e,"left"))return this.mode="list",this.notice=void 0,!0;if(t?.("crtr.setup.list-down",e)===!0)return this.moveDir(1),!0;if(t?.("crtr.setup.list-up",e)===!0)return this.moveDir(-1),!0;switch(e.toLowerCase()){case"a":return this.mode="add-dir",this.edit(this.dirInput,this.cwd),!0;case"m":return this.cycleMemory();case"x":return this.askRemoveDir();case"r":return this.mode="rename",this.edit(this.nameInput,n.manifest.name),!0;case"p":return this.togglePause();default:return!1}}edit(e,t){e.setValue(t),e.handleInput(""),e.focused=!0,this.notice=void 0}leaveField(){this.nameInput.focused=!1,this.dirInput.focused=!1}move(e){this.entries.length!==0&&(this.listIndex=(this.listIndex+e+this.entries.length)%this.entries.length,this.notice=void 0)}moveDir(e){const t=this.open()?.manifest.projects.length??0;t!==0&&(this.dirIndex=(this.dirIndex+e+t)%t,this.notice=void 0)}addCwdTo(e){return e===null||this.attempt(()=>w(e.profileId,this.cwd,{memory:"content"}),`${l(this.cwd)} now belongs to "${e.manifest.name}".`),!0}togglePin(){const e=this.selected();return e===null||(this.pinnedHere()===e.profileId?(N(this.cwd),this.say(`${l(this.cwd)} no longer defaults to any profile.`)):(H(this.cwd,e.profileId),this.say(`${l(this.cwd)} now starts as "${e.manifest.name}" without asking.`)),this.onChange()),!0}submitName(){const e=this.nameInput.getValue().trim(),t=this.mode==="new-name";if(this.mode=t?"list":"detail",this.leaveField(),e===""){this.say("A profile name cannot be empty.","warning");return}if(t){let i=null;this.attempt(()=>{i=V(e,[{path:this.cwd,memory:"content"}]).profileId},`Created "${e}", owning ${l(this.cwd)}.`);const s=this.entries.findIndex(r=>r.profileId===i);s>=0&&(this.listIndex=s);return}const n=this.open();n!==null&&this.attempt(()=>B(n.profileId,e),`Renamed to "${e}".`)}submitDir(){const e=this.dirInput.getValue().trim(),t=this.open();if(this.mode="detail",this.leaveField(),t!==null){if(e===""){this.say("Type the directory to add.","warning");return}this.attempt(()=>w(t.profileId,e,{memory:"content"}),`${l(e)} added to "${t.manifest.name}".`)}}cycleMemory(){const e=this.open(),t=this.currentDir();if(e===null||t===null)return!0;const n=v[(v.indexOf(t.memory)+1)%v.length];return this.attempt(()=>w(e.profileId,t.path,{memory:n}),`${l(t.path)} discloses up to "${n}".`),!0}askRemoveDir(){return this.currentDir()===null?(this.say("This profile owns no directories.","warning"),!0):(this.mode="confirm-remove-dir",this.notice=void 0,!0)}removeDir(){const e=this.open(),t=this.currentDir();this.mode="detail",!(e===null||t===null)&&this.attempt(()=>W(e.profileId,t.path),`${l(t.path)} removed from "${e.manifest.name}".`)}togglePause(){const e=this.open();if(e===null)return!0;const t=e.manifest.paused_at!==null;return this.attempt(()=>t?J(e.profileId):U(e.profileId),t?`"${e.manifest.name}" is active again.`:`"${e.manifest.name}" is paused \u2014 no new nodes start under it.`),!0}askDelete(){const e=this.selected();return e===null?!0:e.profileId===P?(this.say("The root profile is the fallback identity for uncovered directories and cannot be deleted.","warning"),!0):(this.openId=e.profileId,this.mode="confirm-delete",this.notice=void 0,!0)}async deleteOpen(){const e=this.open();if(this.mode="list",!(e===null||this.mutating)){this.mutating=!0,this.say(`Deleting "${e.manifest.name}"\u2026`),this.onChange();try{const t=await E().deleteProfile(e.profileId,{force:!0,caller_node_id:R()??null});this.openId=null,this.reload(),this.say(`Deleted "${t.name}" \u2014 ${t.nodes} nodes, ${t.crons} crons, ${t.default_pins} pins.`)}catch(t){this.say(T(t),"warning")}finally{this.mutating=!1,this.onChange()}}}footerHint(){switch(this.mode){case"new-name":return"type a name \xB7 enter create \xB7 esc cancel";case"rename":return"type a name \xB7 enter save \xB7 esc cancel";case"add-dir":return"type a directory \xB7 enter add \xB7 esc cancel";case"confirm-delete":case"confirm-remove-dir":return"y confirm \xB7 n cancel";case"detail":return"\u2191\u2193 dir \xB7 a add \xB7 m memory \xB7 x remove \xB7 r rename \xB7 p pause \xB7 esc back";case"list":return"\u2191\u2193 move \xB7 enter open \xB7 a add this dir \xB7 d pin here \xB7 n new \xB7 x delete"}}render(e,t){const i=this.mode==="list"||this.mode==="new-name"||this.mode==="confirm-delete"?this.renderList(e,t):this.renderDetail(e,t);if(this.notice!==void 0){i.push("");for(const s of j(this.notice,e))i.push(u(o.fg(this.noticeTone,s),e))}return i}header(e,t,n){const i=o.fg("accent",o.bold(t)),s=o.fg("dim",n);return u(`${i} ${s}`,e)}renderList(e,t){const n=[this.header(e,"Profiles",`${this.entries.length} profile${this.entries.length===1?"":"s"}`),u(o.fg("dim",`Identities your sessions run under. Here: ${l(this.cwd)}`),e),""];if(this.mode==="new-name")return[...n,...this.field(e,"New profile name",this.nameInput)];if(this.mode==="confirm-delete")return[...n,...this.deletePrompt(e)];if(this.entries.length===0)return n.push(u(o.fg("dim"," No profiles yet \u2014 press n to create one here."),e)),n;const i=this.pinnedHere(),s=Math.min(22,Math.max(...this.entries.map(f=>f.manifest.name.length))),r=Math.max(1,t-8),d=_(this.entries.length,this.listIndex,r);for(let f=d.start;f<d.end;f+=1){const c=this.entries[f],y=c.manifest.projects.length,$=y===0?"\u2014":`${y} dir${y===1?"":"s"}`,a=[];M(c,this.cwd)&&a.push("covers here"),i===c.profileId&&a.push("pinned"),c.manifest.paused_at!==null&&a.push("paused");const p=`${h(c.manifest.name,s)} ${h($,8)} ${h(D(c.manifest.last_used_at),14)} ${a.join(" \xB7 ")}`;f===this.listIndex?n.push(o.bg("selectedBg",h(`\u25B8 ${p}`,e))):n.push(u(` ${h(c.manifest.name,s)} ${o.fg("dim",`${h($,8)} ${h(D(c.manifest.last_used_at),14)}`)} ${o.fg("muted",a.join(" \xB7 "))}`,e))}return(d.start>0||d.end<this.entries.length)&&n.push(u(o.fg("dim",` ${this.listIndex+1}/${this.entries.length}`),e)),n}renderDetail(e,t){const n=this.open();if(n===null)return this.renderList(e,t);const i=n.manifest,s=[`app ${i.grantee??"app:terminal"}`,`kind ${i.default_kind??"general"}`,D(i.last_used_at),...i.paused_at!==null?["paused"]:[]],r=[this.header(e,i.name,n.profileId),u(o.fg("dim",s.join(" \xB7 ")),e),""];if(this.mode==="rename")return[...r,...this.field(e,"Rename profile",this.nameInput)];if(this.mode==="add-dir")return[...r,...this.field(e,"Directory to add to this profile",this.dirInput)];const d=i.projects;if(d.length===0)return r.push(u(o.fg("dim"," Owns no directories \u2014 press a to add one."),e)),r;const f=new Set(F(n.profileId)),c=Math.min(Math.max(20,e-26),Math.max(...d.map(a=>l(a.path).length))),y=Math.max(1,t-8),$=_(d.length,this.dirIndex,y);for(let a=$.start;a<$.end;a+=1){const p=d[a],x=[];f.has(p.path)&&x.push("pinned"),p.path===this.cwd&&x.push("\u2190 here");const b=h(l(p.path),c),k=`${b} ${h(p.memory,8)} ${x.join(" \xB7 ")}`;a===this.dirIndex?r.push(o.bg("selectedBg",h(`\u25B8 ${k}`,e))):r.push(u(` ${b} ${o.fg("success",h(p.memory,8))} ${o.fg("muted",x.join(" \xB7 "))}`,e))}if(this.mode==="confirm-remove-dir"){const a=this.currentDir();r.push(""),r.push(u(o.fg("warning",`Remove ${a!==null?l(a.path):"this directory"} from "${i.name}"? Its files are untouched. y / n`),e))}return r}field(e,t,n){return[u(o.fg("accent",t),e),u(` ${n.render(Math.max(8,e-2))[0]??""}`,e)]}deletePrompt(e){const n=this.open()?.manifest.name??"",i=[];for(const s of j(`Delete "${n}" and everything it owns \u2014 every node, cron, inbox ticket and review under it, plus its memory store and directory pins? This cannot be undone.`,e))i.push(u(o.fg("warning",s),e));return i.push(""),i.push(u(o.fg("dim"," y delete n cancel"),e)),i}}export{ie as ProfilesPanel};
1
+ var R=Object.defineProperty;var g=(m,e)=>R(m,"name",{value:e,configurable:!0});import{envNodeId as O}from"../../../shared/env.js";import{Input as x,matchesKey as I,truncateToWidth as a}from"@earendil-works/pi-tui";import{basename as E}from"node:path";import{PROFILE_PROJECT_MEMORY_VALUES as C}from"../../../api/dto/profiles.js";import{cliClient as F}from"../../api-client.js";import{clearDefaultProfile as N,defaultProfileDirs as S,getDefaultProfileId as H,setDefaultProfileId as V}from"../../../core/profiles/default-binding.js";import{ROOT_PROFILE_ID as P,addProfileProject as _,createProfile as A,listProfiles as U,pauseProfile as W,removeProfileProject as B,setProfileDeliveryLimit as J,renameProfile as K,resumeProfile as Y}from"../../../core/profiles/manifest.js";import{tildify as c}from"../../../core/fs-utils.js";import{profileCoversCwd as j}from"../../../core/profiles/select.js";import{padAnsi as f,theme as o,visibleRange as M,wrapText as T}from"../../../core/tui/panel.js";function b(m){if(m===null)return"never used";const e=Date.parse(m);if(Number.isNaN(e))return"used recently";const t=Math.max(0,Math.floor((Date.now()-e)/1e3));if(t<60)return"used just now";const i=Math.floor(t/60);if(i<60)return`used ${i}m ago`;const n=Math.floor(i/60);if(n<24)return`used ${n}h ago`;const r=Math.floor(n/24);if(r<30)return`used ${r}d ago`;const s=Math.floor(r/30);return s<12?`used ${s}mo ago`:`used ${Math.floor(s/12)}y ago`}g(b,"relativeUsed");function L(m){return m instanceof Error?m.message:String(m)}g(L,"messageOf");class re{static{g(this,"ProfilesPanel")}cwd;onChange;nameInput=new x;dirInput=new x;limitInput=new x;entries=[];listIndex=0;dirIndex=0;mode="list";openId=null;notice;noticeTone="success";mutating=!1;constructor(e,t){this.cwd=e,this.onChange=t,this.nameInput.onSubmit=()=>{this.submitName(),this.onChange()},this.nameInput.onEscape=()=>{this.mode=this.openId!==null?"detail":"list",this.leaveField(),this.onChange()},this.dirInput.onSubmit=()=>{this.submitDir(),this.onChange()},this.dirInput.onEscape=()=>{this.mode="detail",this.leaveField(),this.onChange()},this.limitInput.onSubmit=()=>{this.submitLimit(),this.onChange()},this.limitInput.onEscape=()=>{this.mode="detail",this.leaveField(),this.onChange()},this.reload()}badge(){return String(this.entries.length)}ownsInput(e){return this.mode==="list"?!1:this.mode==="detail"?I(e,"escape")||I(e,"left"):!0}reload(){const e=g(n=>n.profileId===P?2:j(n,this.cwd)?0:1,"rank"),t=g(n=>n.manifest.last_used_at??"","used");this.entries=U().sort((n,r)=>{const s=e(n)-e(r);if(s!==0)return s;const d=t(r).localeCompare(t(n));return d!==0?d:n.manifest.name.localeCompare(r.manifest.name)}),this.listIndex>=this.entries.length&&(this.listIndex=Math.max(0,this.entries.length-1));const i=this.open();i===null?(this.mode!=="list"&&(this.mode="list"),this.openId=null):this.dirIndex>=i.manifest.projects.length&&(this.dirIndex=Math.max(0,i.manifest.projects.length-1))}selected(){return this.entries[this.listIndex]??null}open(){return this.openId===null?null:this.entries.find(e=>e.profileId===this.openId)??null}currentDir(){return this.open()?.manifest.projects[this.dirIndex]??null}pinnedHere(){return H(this.cwd)}say(e,t="success"){this.notice=e,this.noticeTone=t}attempt(e,t){try{e(),this.reload(),this.say(t)}catch(i){this.say(L(i),"warning")}}handleInput(e,t){const i=this.route(e,t);return i&&this.onChange(),i}route(e,t){switch(this.mode){case"new-name":case"rename":return this.routeText(this.nameInput,e);case"add-dir":return this.routeText(this.dirInput,e);case"set-limit":return this.routeText(this.limitInput,e);case"confirm-delete":return this.routeConfirm(e,()=>{this.deleteOpen()});case"confirm-remove-dir":return this.routeConfirm(e,()=>this.removeDir());case"detail":return this.routeDetail(e,t);case"list":return this.routeList(e,t)}}routeText(e,t){return e.handleInput(t),!0}routeConfirm(e,t){const i=e.toLowerCase();return i==="y"?t():(i==="n"||I(e,"escape")||I(e,"return"))&&(this.mode=this.openId!==null?"detail":"list",this.say("Cancelled.")),!0}routeList(e,t){if(t?.("crtr.setup.list-down",e)===!0)return this.move(1),!0;if(t?.("crtr.setup.list-up",e)===!0)return this.move(-1),!0;if(t?.("crtr.setup.advance",e)===!0){const i=this.selected();return i!==null&&(this.openId=i.profileId,this.dirIndex=0,this.mode="detail",this.notice=void 0),!0}switch(e.toLowerCase()){case"a":return this.addCwdTo(this.selected());case"d":return this.togglePin();case"n":return this.mode="new-name",this.edit(this.nameInput,E(this.cwd)||"profile"),!0;case"x":return this.askDelete();default:return!1}}routeDetail(e,t){const i=this.open();if(i===null)return this.mode="list",!0;if(I(e,"escape")||I(e,"left"))return this.mode="list",this.notice=void 0,!0;if(t?.("crtr.setup.list-down",e)===!0)return this.moveDir(1),!0;if(t?.("crtr.setup.list-up",e)===!0)return this.moveDir(-1),!0;switch(e.toLowerCase()){case"a":return this.mode="add-dir",this.edit(this.dirInput,this.cwd),!0;case"l":return this.mode="set-limit",this.edit(this.limitInput,""),!0;case"x":return this.askRemoveDir();case"r":return this.mode="rename",this.edit(this.nameInput,i.manifest.name),!0;case"p":return this.togglePause();default:return!1}}edit(e,t){e.setValue(t),e.handleInput(""),e.focused=!0,this.notice=void 0}leaveField(){this.nameInput.focused=!1,this.dirInput.focused=!1,this.limitInput.focused=!1}move(e){this.entries.length!==0&&(this.listIndex=(this.listIndex+e+this.entries.length)%this.entries.length,this.notice=void 0)}moveDir(e){const t=this.open()?.manifest.projects.length??0;t!==0&&(this.dirIndex=(this.dirIndex+e+t)%t,this.notice=void 0)}addCwdTo(e){return e===null||this.attempt(()=>_(e.profileId,this.cwd),`${c(this.cwd)} now belongs to "${e.manifest.name}".`),!0}togglePin(){const e=this.selected();return e===null||(this.pinnedHere()===e.profileId?(N(this.cwd),this.say(`${c(this.cwd)} no longer defaults to any profile.`)):(V(this.cwd,e.profileId),this.say(`${c(this.cwd)} now starts as "${e.manifest.name}" without asking.`)),this.onChange()),!0}submitName(){const e=this.nameInput.getValue().trim(),t=this.mode==="new-name";if(this.mode=t?"list":"detail",this.leaveField(),e===""){this.say("A profile name cannot be empty.","warning");return}if(t){let n=null;this.attempt(()=>{n=A(e,[{path:this.cwd}]).profileId},`Created "${e}", owning ${c(this.cwd)}.`);const r=this.entries.findIndex(s=>s.profileId===n);r>=0&&(this.listIndex=r);return}const i=this.open();i!==null&&this.attempt(()=>K(i.profileId,e),`Renamed to "${e}".`)}submitDir(){const e=this.dirInput.getValue().trim(),t=this.open();if(this.mode="detail",this.leaveField(),t!==null){if(e===""){this.say("Type the directory to add.","warning");return}this.attempt(()=>_(t.profileId,e),`${c(e)} added to "${t.manifest.name}".`)}}submitLimit(){const e=this.limitInput.getValue().trim().split(/\s+/),t=this.open();if(this.mode="detail",this.leaveField(),t===null)return;const[i,n]=e;if(e.length!==2||i===void 0||n===void 0||!C.includes(n)){this.say(`Type an owner handle and a level (${C.join(", ")}), e.g. "crouter preview".`,"warning");return}this.attempt(()=>J(t.profileId,i,n),n==="content"?`${i} is no longer limited.`:`${i} is delivered automatically up to "${n}".`)}askRemoveDir(){return this.currentDir()===null?(this.say("This profile owns no directories.","warning"),!0):(this.mode="confirm-remove-dir",this.notice=void 0,!0)}removeDir(){const e=this.open(),t=this.currentDir();this.mode="detail",!(e===null||t===null)&&this.attempt(()=>B(e.profileId,t.path),`${c(t.path)} removed from "${e.manifest.name}".`)}togglePause(){const e=this.open();if(e===null)return!0;const t=e.manifest.paused_at!==null;return this.attempt(()=>t?Y(e.profileId):W(e.profileId),t?`"${e.manifest.name}" is active again.`:`"${e.manifest.name}" is paused \u2014 no new nodes start under it.`),!0}askDelete(){const e=this.selected();return e===null?!0:e.profileId===P?(this.say("The root profile is the fallback identity for uncovered directories and cannot be deleted.","warning"),!0):(this.openId=e.profileId,this.mode="confirm-delete",this.notice=void 0,!0)}async deleteOpen(){const e=this.open();if(this.mode="list",!(e===null||this.mutating)){this.mutating=!0,this.say(`Deleting "${e.manifest.name}"\u2026`),this.onChange();try{const t=await F().deleteProfile(e.profileId,{force:!0,caller_node_id:O()??null});this.openId=null,this.reload(),this.say(`Deleted "${t.name}" \u2014 ${t.nodes} nodes, ${t.crons} crons, ${t.default_pins} pins.`)}catch(t){this.say(L(t),"warning")}finally{this.mutating=!1,this.onChange()}}}footerHint(){switch(this.mode){case"new-name":return"type a name \xB7 enter create \xB7 esc cancel";case"rename":return"type a name \xB7 enter save \xB7 esc cancel";case"add-dir":return"type a directory \xB7 enter add \xB7 esc cancel";case"set-limit":return"type <owner> <level> \xB7 enter save \xB7 esc cancel";case"confirm-delete":case"confirm-remove-dir":return"y confirm \xB7 n cancel";case"detail":return"\u2191\u2193 dir \xB7 a add \xB7 l limit \xB7 x remove \xB7 r rename \xB7 p pause \xB7 esc back";case"list":return"\u2191\u2193 move \xB7 enter open \xB7 a add this dir \xB7 d pin here \xB7 n new \xB7 x delete"}}render(e,t){const n=this.mode==="list"||this.mode==="new-name"||this.mode==="confirm-delete"?this.renderList(e,t):this.renderDetail(e,t);if(this.notice!==void 0){n.push("");for(const r of T(this.notice,e))n.push(a(o.fg(this.noticeTone,r),e))}return n}header(e,t,i){const n=o.fg("accent",o.bold(t)),r=o.fg("dim",i);return a(`${n} ${r}`,e)}renderList(e,t){const i=[this.header(e,"Profiles",`${this.entries.length} profile${this.entries.length===1?"":"s"}`),a(o.fg("dim",`Identities your sessions run under. Here: ${c(this.cwd)}`),e),""];if(this.mode==="new-name")return[...i,...this.field(e,"New profile name",this.nameInput)];if(this.mode==="confirm-delete")return[...i,...this.deletePrompt(e)];if(this.entries.length===0)return i.push(a(o.fg("dim"," No profiles yet \u2014 press n to create one here."),e)),i;const n=this.pinnedHere(),r=Math.min(22,Math.max(...this.entries.map(u=>u.manifest.name.length))),s=Math.max(1,t-8),d=M(this.entries.length,this.listIndex,s);for(let u=d.start;u<d.end;u+=1){const h=this.entries[u],$=h.manifest.projects.length,v=$===0?"\u2014":`${$} dir${$===1?"":"s"}`,p=[];j(h,this.cwd)&&p.push("covers here"),n===h.profileId&&p.push("pinned"),h.manifest.paused_at!==null&&p.push("paused");const l=`${f(h.manifest.name,r)} ${f(v,8)} ${f(b(h.manifest.last_used_at),14)} ${p.join(" \xB7 ")}`;u===this.listIndex?i.push(o.bg("selectedBg",f(`\u25B8 ${l}`,e))):i.push(a(` ${f(h.manifest.name,r)} ${o.fg("dim",`${f(v,8)} ${f(b(h.manifest.last_used_at),14)}`)} ${o.fg("muted",p.join(" \xB7 "))}`,e))}return(d.start>0||d.end<this.entries.length)&&i.push(a(o.fg("dim",` ${this.listIndex+1}/${this.entries.length}`),e)),i}renderDetail(e,t){const i=this.open();if(i===null)return this.renderList(e,t);const n=i.manifest,r=[`app ${n.grantee??"app:terminal"}`,`kind ${n.default_kind??"general"}`,b(n.last_used_at),...n.paused_at!==null?["paused"]:[]],s=[this.header(e,n.name,i.profileId),a(o.fg("dim",r.join(" \xB7 ")),e),""];if(this.mode==="rename")return[...s,...this.field(e,"Rename profile",this.nameInput)];if(this.mode==="add-dir")return[...s,...this.field(e,"Directory to add to this profile",this.dirInput)];if(this.mode==="set-limit")return[...s,...this.field(e,"Delivery limit: owner handle and level (content removes it)",this.limitInput)];const d=Object.entries(n.delivery_limits??{});d.length>0&&(s.push(a(o.fg("dim",`limits ${d.map(([l,y])=>`${l} ${y}`).join(" \xB7 ")}`),e)),s.push(""));const u=n.projects;if(u.length===0)return s.push(a(o.fg("dim"," Owns no directories \u2014 press a to add one."),e)),s;const h=new Set(S(i.profileId)),$=Math.min(Math.max(20,e-16),Math.max(...u.map(l=>c(l.path).length))),v=Math.max(1,t-8),p=M(u.length,this.dirIndex,v);for(let l=p.start;l<p.end;l+=1){const y=u[l],w=[];h.has(y.path)&&w.push("pinned"),y.path===this.cwd&&w.push("\u2190 here");const D=f(c(y.path),$),k=`${D} ${w.join(" \xB7 ")}`;l===this.dirIndex?s.push(o.bg("selectedBg",f(`\u25B8 ${k}`,e))):s.push(a(` ${D} ${o.fg("muted",w.join(" \xB7 "))}`,e))}if(this.mode==="confirm-remove-dir"){const l=this.currentDir();s.push(""),s.push(a(o.fg("warning",`Remove ${l!==null?c(l.path):"this directory"} from "${n.name}"? Its files are untouched. y / n`),e))}return s}field(e,t,i){return[a(o.fg("accent",t),e),a(` ${i.render(Math.max(8,e-2))[0]??""}`,e)]}deletePrompt(e){const i=this.open()?.manifest.name??"",n=[];for(const r of T(`Delete "${i}" and everything it owns \u2014 every node, cron, inbox ticket and review under it, plus its memory store and directory pins? This cannot be undone.`,e))n.push(a(o.fg("warning",r),e));return n.push(""),n.push(a(o.fg("dim"," y delete n cancel"),e)),n}}export{re as ProfilesPanel};
@@ -1,21 +1,16 @@
1
- /** Marker value written to the generated top INDEX's `generated-by` field —
2
- * the wipe guard: `deps` only ever deletes a deps/ dir whose INDEX carries
3
- * this marker. */
1
+ import type { CrtrClient } from '../../api/index.js';
4
2
  export declare const DEPS_GENERATED_MARKER = "crtr sys sync deps";
5
- /** Row shape structurally compatible with sync.ts's ImportResult. */
6
3
  interface DepsRow {
7
4
  source: string;
8
- target: string;
9
- /** Full canonical name the vendored doc answers at (`<namespace>/deps/...`),
10
- * except on an `excluded` row, which names the excluded package selector. */
5
+ /** Full name of the vendored document (`<repo>/deps/...`), except on an
6
+ * `excluded` row, which names the excluded package selector. */
11
7
  name: string;
12
- scope: 'project';
13
- status: 'imported' | 'would-import' | 'skipped' | 'excluded';
8
+ status: 'imported' | 'unchanged' | 'would-import' | 'deleted' | 'would-delete' | 'skipped' | 'excluded';
14
9
  reason?: string;
15
10
  }
16
- export declare function runDepsSync(opts: {
11
+ export declare function runDepsSync(client: CrtrClient, opts: {
17
12
  sourceArg?: string;
18
13
  dryRun: boolean;
19
- }): DepsRow[];
14
+ }): Promise<DepsRow[]>;
20
15
  export declare const sysSyncDepsLeaf: import("../../core/command.js").LeafDef;
21
16
  export {};
@@ -1,15 +1,14 @@
1
- var ce=Object.defineProperty;var u=(s,n)=>ce(s,"name",{value:n,configurable:!0});import{copyFileSync as de,mkdirSync as ae,readdirSync as le,rmSync as pe}from"node:fs";import{basename as ue,dirname as S,join as m,relative as P,resolve as H,sep as z}from"node:path";import{defineLeaf as me}from"../../core/command.js";import{usage as A}from"../../core/errors.js";import{parseFrontmatterGeneric as J}from"../../core/frontmatter.js";import{pathExists as N,readJsonIfExists as U,readText as I,walkFiles as Q,writeText as W}from"../../core/fs-utils.js";import{composeCanonicalName as ge}from"../../core/memory/identity.js";import{openProjectMemoryStore as fe}from"../../core/memory-resolver.js";import{requireMountedStore as he,serializeMemoryDoc as C}from"../../core/memory/mutation-domain.js";import{routeFromDescription as ke,scalarString as ye}from"./sync-shared.js";import{isRecord as L}from"../../shared/predicates.js";const T="crtr sys sync deps";function y(s){throw A(`--deps: invalid package.json crtr.sync.deps.exclude: ${s}`)}u(y,"invalidDepsConfig");function be(s){const n=U(m(s,"package.json"));L(n)||y("package.json must contain an object");const o=n.crtr;if(o===void 0)return[];L(o)||y("crtr must be an object");const a=o.sync;if(a===void 0)return[];L(a)||y("crtr.sync must be an object");const r=a.deps;if(r===void 0)return[];L(r)||y("crtr.sync.deps must be an object");const l=r.exclude;if(l===void 0)return[];Array.isArray(l)||y("exclude must be an array of {package, version, skill} selectors");const g=new Set;return l.map(($,i)=>{L($)||y(`exclude[${i}] must be an object with exactly package, version, and skill`),Object.keys($).sort().join(",")!=="package,skill,version"&&y(`exclude[${i}] must contain exactly package, version, and skill`);const f=$.package,x=$.version,h=$.skill;(typeof f!="string"||!$e.test(f))&&y(`exclude[${i}].package must be one exact npm package name`),(typeof x!="string"||!we.test(x))&&y(`exclude[${i}].version must be one exact installed semver version`),(typeof h!="string"||h===""||h!=="."&&(h.startsWith("/")||h.split("/").some(R=>R===""||R==="."||R==="..")||/[\\*?[\]{}]/.test(h)))&&y(`exclude[${i}].skill must be one exact POSIX path relative to the package skills/ directory (use . for a root SKILL.md)`);const w={package:f,version:x,skill:h},D=`${f}\0${x}\0${h}`;return g.has(D)&&y(`exclude[${i}] duplicates ${f}@${x} skill ${h}`),g.add(D),w})}u(be,"readDepsExclusions");const $e=/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/,Y="(?:0|[1-9]\\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)",we=new RegExp(`^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-${Y}(?:\\.${Y})*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$`);function _(s,n,o){return`${s}\0${n}\0${o}`}u(_,"exclusionKey");function ve(s,n,o){return s.has(_(n.pkg,n.version,o))}u(ve,"isExcluded");function je(s){if(s!==void 0)return H(s);let n=H(process.cwd());for(;;){if(N(m(n,"package.json")))return n;const o=S(n);if(o===n)throw A("--deps: no package.json found from cwd upward; run inside a Node project or pass --source <project-dir>");n=o}}u(je,"depsProjectDir");function xe(s){const n=[];for(const a of ee(s))if(!a.startsWith("."))if(a.startsWith("@"))for(const r of ee(m(s,a)))n.push(m(s,a,r));else n.push(m(s,a));const o=[];for(const a of n.sort()){const r=m(a,"skills");if(!N(r))continue;const l=U(m(a,"package.json"));o.push({pkg:l?.name??P(s,a).split(z).join("/"),version:l?.version??"",skillsRoot:r})}return o}u(xe,"skillsPackages");function ee(s){try{return le(s)}catch{return[]}}u(ee,"listDirNames");function Re(s,n){return n.find(o=>s===o||s.startsWith(`${o}${z}`))}u(Re,"owningBundle");function se(s,n=220){const o=s.replace(/\s+/g," ").trim(),a=o.split(/(?<=[.!?])\s+/)[0]??o,r=a.length>=30?a:o;if(r.length<=n)return r;const l=r.slice(0,n),g=l.lastIndexOf(" ");return`${l.slice(0,g>80?g:n).trimEnd()}\u2026`}u(se,"condenseDescription");const Ee=["name","description","type","keywords","kind","when-and-why-to-read","short-form","unlisted","surfaces","gate","rationale"];function ne(s){const n={...s};for(const o of Ee)delete n[o];return n}u(ne,"passthroughFm");function Se(s){const n=s.match(/^#{1,6}\s+(.+)$/m);return n?n[1].trim():void 0}u(Se,"firstHeading");function De(s){const n=je(s.sourceArg),o=m(n,"node_modules");if(!N(o))throw A(`sys sync deps: ${o} does not exist; install dependencies first (npm ci / npm install), then re-run`);const a=he(fe(n)),r=m(a.storeRoot,"deps"),l=ge(a.namespace,"deps"),g=be(n),$=new Set(g.map(e=>_(e.package,e.version,e.skill))),i=new Map(g.map(e=>[_(e.package,e.version,e.skill),0])),j=new Map,f=[],x=xe(o),h=[];for(const e of x){const t=[],c=new Set;for(const d of Q(e.skillsRoot,p=>p==="SKILL.md",p=>p==="node_modules"||p===".git")){const p=S(d);t.push(p);const k=S(P(e.skillsRoot,d).split(z).join("/"));if(!ve($,e,k))continue;const v=_(e.pkg,e.version,k);i.set(v,(i.get(v)??0)+1),c.add(p),f.push({source:d,target:"\u2014",name:`${e.pkg}@${e.version}:${k}`,scope:"project",status:"excluded",reason:"matched package.json crtr.sync.deps.exclude"})}h.push({...e,bundleRoots:t.sort((d,p)=>p.length-d.length),excludedBundleRoots:c})}for(const e of g){const t=_(e.package,e.version,e.skill),c=i.get(t);if(c!==1)throw A(`--deps: package.json crtr.sync.deps.exclude selector ${e.package}@${e.version}:${e.skill} ${c===0?"does not match an installed dependency skill bundle":`matches ${c} installed dependency skill bundles`}; update or remove the selector before syncing`)}for(const e of h){const t=e.bundleRoots??[],c=e.excludedBundleRoots??new Set;for(const d of Q(e.skillsRoot,()=>!0,p=>p==="node_modules"||p===".git")){const p=Re(d,t);if(p===void 0||c.has(p))continue;const k=P(e.skillsRoot,d).split(z).join("/");let v,b;if(ue(d)==="SKILL.md"){const Z=S(k),q=Z==="."?e.pkg.split("/").pop()??e.pkg:Z;b=`${q}/INDEX.md`;let X={},K="";try{const V=J(I(d));X=V.data??{},K=V.body}catch{K=I(d)}v={kind:"skill",sourceAbs:d,pkg:e.pkg,version:e.version,bundleRel:q,fm:X,body:K,description:ye(X.description)??""}}else k.toLowerCase().endsWith(".md")?(b=k,v={kind:"sidecar-md",sourceAbs:d,pkg:e.pkg,version:e.version}):(b=k,v={kind:"asset",sourceAbs:d,pkg:e.pkg});if(b==="INDEX.md")continue;const E=j.get(b);if(E){v.kind==="skill"&&f.push({source:d,target:m(r,...b.split("/")),name:`${l}/${S(b)}`,scope:"project",status:"skipped",reason:`collides with same-named bundle from ${E.pkg}`});continue}j.set(b,v)}}const w=[...j.entries()].filter(e=>e[1].kind==="skill"),D=w.map(([,e])=>e.bundleRel).sort((e,t)=>t.length-e.length),R=new Map;for(const[e,t]of j){if(t.kind==="skill")continue;const c=D.find(d=>e.startsWith(`${d}/`));c&&R.set(c,(R.get(c)??0)+1)}const B=new Set(w.map(([,e])=>`${e.pkg}@${e.version}`)),G=s.dryRun?"would-import":"imported";for(const[e,t]of w){const c=R.get(t.bundleRel)??0;f.push({source:t.sourceAbs,target:m(r,...e.split("/")),name:`${l}/${t.bundleRel}`,scope:"project",status:G,...c>0?{reason:`+${c} sidecar file${c===1?"":"s"}`}:{}})}if(f.push({source:o,target:m(r,"INDEX.md"),name:l,scope:"project",status:G,reason:`generated catalog of ${w.length} docs from ${B.size} package${B.size===1?"":"s"}`}),s.dryRun)return f;if(N(r)){const e=m(r,"INDEX.md");if(!(N(e)&&I(e).includes(T)))throw A(`--deps: ${r} exists but its INDEX.md does not carry the "${T}" marker; it may be hand-authored \u2014 move or delete it manually before vendoring dependency docs there`);pe(r,{recursive:!0,force:!0})}for(const[e,t]of j){const c=m(r,...e.split("/"));if(t.kind==="skill"){const d={kind:"knowledge",privacy:"public","when-and-why-to-read":ke(t.description,"knowledge"),"short-form":t.description!==""?se(t.description):`Vendored agent doc shipped by ${t.pkg}.`,surfaces:[{on:"boot",at:"name"}],"source-package":`${t.pkg}@${t.version}`,...ne(t.fm)};W(c,C(d,t.body))}else if(t.kind==="sidecar-md"){let d={},p;try{const E=J(I(t.sourceAbs));d=E.data??{},p=E.body}catch{p=I(t.sourceAbs)}const k=D.find(E=>e.startsWith(`${E}/`)),b={kind:"knowledge",privacy:"public","when-and-why-to-read":`When ${k?`${l}/${k}`:`a ${l} document`} links to this file, this knowledge should be read because it carries the linked supporting reference.`,"short-form":Se(p)??`Supporting reference vendored from ${t.pkg}.`,surfaces:[{on:"boot",at:"name"}],"source-package":`${t.pkg}@${t.version}`,...ne(d)};W(c,C(b,p))}else ae(S(c),{recursive:!0}),de(t.sourceAbs,c)}const O=[...new Set(w.map(([,e])=>e.pkg))],te=O.slice(0,6).join(", ")+(O.length>6?", \u2026":""),F=new Map;for(const[,e]of w){const t=`${e.pkg}@${e.version}`,c=F.get(t)??{version:e.version,lines:[]},d=e.description!==""?` \u2014 ${se(e.description,180)}`:"";c.lines.push(`- \`${l}/${e.bundleRel}\`${d}`),F.set(t,c)}const oe=[...F.entries()].map(([e,{lines:t}])=>`## ${e}
1
+ var le=Object.defineProperty;var p=(s,n)=>le(s,"name",{value:n,configurable:!0});import{dirname as W,join as w,relative as F,resolve as X,sep as z}from"node:path";import{defineLeaf as pe}from"../../core/command.js";import{usage as D}from"../../core/errors.js";import{parseFrontmatterGeneric as Q}from"../../core/frontmatter.js";import{pathExists as M,readJsonIfExists as Y,readText as I,walkFiles as ee}from"../../core/fs-utils.js";import{cliClient as ue}from"../api-client.js";import{normalizedName as ne,putDoc as se,repoOwner as me,routeFromDescription as he,scalarString as fe,writeFailure as te}from"./sync-shared.js";import{isRecord as E}from"../../shared/predicates.js";import{readdirSync as ge}from"node:fs";const L="crtr sys sync deps";function f(s){throw D(`--deps: invalid package.json crtr.sync.deps.exclude: ${s}`)}p(f,"invalidDepsConfig");function ke(s){const n=Y(w(s,"package.json"));E(n)||f("package.json must contain an object");const o=n.crtr;if(o===void 0)return[];E(o)||f("crtr must be an object");const r=o.sync;if(r===void 0)return[];E(r)||f("crtr.sync must be an object");const t=r.deps;if(t===void 0)return[];E(t)||f("crtr.sync.deps must be an object");const i=t.exclude;if(i===void 0)return[];Array.isArray(i)||f("exclude must be an array of {package, version, skill} selectors");const m=new Set;return i.map((k,g)=>{E(k)||f(`exclude[${g}] must be an object with exactly package, version, and skill`),Object.keys(k).sort().join(",")!=="package,skill,version"&&f(`exclude[${g}] must contain exactly package, version, and skill`);const u=k.package,v=k.version,h=k.skill;(typeof u!="string"||!ye.test(u))&&f(`exclude[${g}].package must be one exact npm package name`),(typeof v!="string"||!$e.test(v))&&f(`exclude[${g}].version must be one exact installed semver version`),(typeof h!="string"||h===""||h!=="."&&(h.startsWith("/")||h.split("/").some(x=>x===""||x==="."||x==="..")||/[\\*?[\]{}]/.test(h)))&&f(`exclude[${g}].skill must be one exact POSIX path relative to the package skills/ directory (use . for a root SKILL.md)`);const $={package:u,version:v,skill:h},S=`${u}\0${v}\0${h}`;return m.has(S)&&f(`exclude[${g}] duplicates ${u}@${v} skill ${h}`),m.add(S),$})}p(ke,"readDepsExclusions");const ye=/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/,oe="(?:0|[1-9]\\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)",$e=new RegExp(`^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-${oe}(?:\\.${oe})*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$`);function _(s,n,o){return`${s}\0${n}\0${o}`}p(_,"exclusionKey");function be(s,n,o){return s.has(_(n.pkg,n.version,o))}p(be,"isExcluded");function we(s){if(s!==void 0)return X(s);let n=X(process.cwd());for(;;){if(M(w(n,"package.json")))return n;const o=W(n);if(o===n)throw D("--deps: no package.json found from cwd upward; run inside a Node project or pass --source <project-dir>");n=o}}p(we,"depsProjectDir");function ve(s){const n=[];for(const r of re(s))if(!r.startsWith("."))if(r.startsWith("@"))for(const t of re(w(s,r)))n.push(w(s,r,t));else n.push(w(s,r));const o=[];for(const r of n.sort()){const t=w(r,"skills");if(!M(t))continue;const i=Y(w(r,"package.json"));o.push({pkg:i?.name??F(s,r).split(z).join("/"),version:i?.version??"",skillsRoot:t})}return o}p(ve,"skillsPackages");function re(s){try{return ge(s)}catch{return[]}}p(re,"listDirNames");function xe(s,n){return n.find(o=>s===o||s.startsWith(`${o}${z}`))}p(xe,"owningBundle");function de(s,n=220){const o=s.replace(/\s+/g," ").trim(),r=o.split(/(?<=[.!?])\s+/)[0]??o,t=r.length>=30?r:o;if(t.length<=n)return t;const i=t.slice(0,n),m=i.lastIndexOf(" ");return`${i.slice(0,m>80?m:n).trimEnd()}\u2026`}p(de,"condenseDescription");function je(s){const n=s.match(/^#{1,6}\s+(.+)$/m);return n?n[1].trim():void 0}p(je,"firstHeading");async function Re(s,n){const o=we(n.sourceArg),r=w(o,"node_modules");if(!M(r))throw D(`sys sync deps: ${r} does not exist; install dependencies first (npm ci / npm install), then re-run`);const t=await me(s,o),i=[...t.existing].filter(e=>e.startsWith("deps/"));if(i.length>0||t.existing.has("deps")){const e=t.existing.has("deps")?await s.objects.read(`${t.handle}/deps`):null;if(!(e!==null&&e.state==="object"&&e.type==="document"&&e.bodies.some(c=>c.includes(L))))throw D(`--deps: repo ${t.handle} already has documents named deps/\u2026 but its \`deps\` document does not carry the "${L}" marker; they may be hand-written \u2014 move or delete them (\`crtr doc move\` / \`crtr doc delete\`) before vendoring dependency docs there`)}const m=ke(o),k=new Set(m.map(e=>_(e.package,e.version,e.skill))),g=new Map(m.map(e=>[_(e.package,e.version,e.skill),0])),y=new Map,u=[],v=ve(r),h=[];for(const e of v){const d=[],c=new Set;for(const a of ee(e.skillsRoot,l=>l==="SKILL.md",l=>l==="node_modules"||l===".git")){const l=W(a);d.push(l);const b=W(F(e.skillsRoot,a).split(z).join("/"));if(!be(k,e,b))continue;const j=_(e.pkg,e.version,b);g.set(j,(g.get(j)??0)+1),c.add(l),u.push({source:a,name:`${e.pkg}@${e.version}:${b}`,status:"excluded",reason:"matched package.json crtr.sync.deps.exclude"})}h.push({...e,bundleRoots:d.sort((a,l)=>l.length-a.length),excludedBundleRoots:c})}for(const e of m){const d=_(e.package,e.version,e.skill),c=g.get(d);if(c!==1)throw D(`--deps: package.json crtr.sync.deps.exclude selector ${e.package}@${e.version}:${e.skill} ${c===0?"does not match an installed dependency skill bundle":`matches ${c} installed dependency skill bundles`}; update or remove the selector before syncing`)}for(const e of h){const d=e.bundleRoots??[],c=e.excludedBundleRoots??new Set;for(const a of ee(e.skillsRoot,l=>l.toLowerCase().endsWith(".md"),l=>l==="node_modules"||l===".git")){const l=xe(a,d);if(l===void 0||c.has(l))continue;const b=F(e.skillsRoot,a).split(z).join("/");let j,R;if(b==="SKILL.md"||b.endsWith("/SKILL.md")){const V=W(b),H=ne(V==="."?e.pkg.split("/").pop()??e.pkg:V);R=H;let J={},P="";try{const U=Q(I(a));J=U.data??{},P=U.body}catch{P=I(a)}j={kind:"skill",sourceAbs:a,pkg:e.pkg,version:e.version,bundleRel:H,body:P,description:fe(J.description)??""}}else R=ne(b),j={kind:"sidecar-md",sourceAbs:a,pkg:e.pkg,version:e.version};if(R==="")continue;const q=y.get(R);if(q){j.kind==="skill"&&u.push({source:a,name:`${t.handle}/deps/${R}`,status:"skipped",reason:`collides with same-named document from ${q.pkg}`});continue}y.set(R,j)}}const $=[...y.entries()].filter(e=>e[1].kind==="skill"),S=$.map(([,e])=>e.bundleRel).sort((e,d)=>d.length-e.length),x=new Map;for(const[e,d]of y){if(d.kind==="skill")continue;const c=S.find(a=>e.startsWith(`${a}/`));c&&x.set(c,(x.get(c)??0)+1)}const C=new Set($.map(([,e])=>`${e.pkg}@${e.version}`)),O=`generated catalog of ${$.length} docs from ${C.size} package${C.size===1?"":"s"}`,B=p((e,d)=>{if(d.kind!=="skill")return;const c=x.get(d.bundleRel)??0;return c>0?`+${c} sidecar doc${c===1?"":"s"}`:void 0},"reasonFor"),G=i.filter(e=>!y.has(e.slice(5)));if(n.dryRun){for(const[e,d]of y){const c=B(e,d);u.push({source:d.sourceAbs,name:`${t.handle}/deps/${e}`,status:"would-import",...c?{reason:c}:{}})}for(const e of G)u.push({source:"\u2014",name:`${t.handle}/${e}`,status:"would-delete",reason:"no dependency ships it any more"});return u.push({source:r,name:`${t.handle}/deps`,status:"would-import",reason:O}),u}const T="regenerated by crtr sys sync deps";for(const[e,d]of y){const c=d.kind==="skill"?Se(e,d):Ae(e,d,S,t.handle);try{const a=await se(s,t,c,T),l=B(e,d);u.push({source:d.sourceAbs,name:a.name,status:a.changed?"imported":"unchanged",...l?{reason:l}:{}})}catch(a){u.push({source:d.sourceAbs,name:`${t.handle}/deps/${e}`,status:"skipped",reason:te(a)})}}for(const e of G)await s.docs.delete(`${t.handle}/${e}`),u.push({source:"\u2014",name:`${t.handle}/${e}`,status:"deleted",reason:"no dependency ships it any more"});const A=`${t.handle}/deps`,Z=[...new Set($.map(([,e])=>e.pkg))],ce=Z.slice(0,6).join(", ")+(Z.length>6?", \u2026":""),N=new Map;for(const[,e]of $){const d=`${e.pkg}@${e.version}`,c=N.get(d)??[],a=e.description!==""?` \u2014 ${de(e.description,180)}`:"";c.push(`- [[${A}/${e.bundleRel}]]${a}`),N.set(d,c)}const ie=[...N.entries()].map(([e,d])=>`## ${e}
2
2
 
3
- ${t.sort().join(`
3
+ ${d.sort().join(`
4
4
  `)}`).join(`
5
5
 
6
- `),M=w.length===0,re={kind:"knowledge",privacy:"public","when-and-why-to-read":M?"When deciding whether dependency-shipped agent docs are available in this project, this catalog should be read because no dependency guides are currently vendored.":`When writing code against this project's dependencies (${te}), this catalog should be read because those packages ship their own authoritative agent guides, vendored below and readable with \`crtr memory read ${l}/<name>\`.`,"short-form":M?"No dependency-shipped agent docs are currently vendored.":"Generated catalog of the agent docs shipped inside this project's npm dependencies.",surfaces:[{on:"boot",at:"preview"}],"generated-by":T},ie=M?`# Dependency-shipped agent docs (generated)
6
+ `),K=$.length===0,ae={name:"deps",kind:"knowledge",preview:K?"When deciding whether dependency-shipped agent docs are available in this project, read this because no dependency guides are currently vendored.":`When writing code against this project's dependencies (${ce}), read this because those packages ship their own agent guides, vendored as documents readable with \`crtr canvas read ${A}/<name>\`.`,summary:K?"No dependency-shipped agent docs are currently vendored.":"Generated catalog of the agent docs shipped inside this project's npm dependencies.",rules:[{on:"boot",deliver:"preview"}],body:K?`# Dependency-shipped agent docs (generated)
7
7
 
8
- No dependency agent docs are currently vendored. \`crtr sys sync deps\` found no included Agent Skill bundles.
8
+ No dependency agent docs are currently vendored. \`${L}\` found no included Agent Skill bundles.
9
9
  `:`# Dependency-shipped agent docs (generated)
10
10
 
11
- Generated by \`crtr sys sync deps\` from the Agent Skill bundles inside this project's node_modules. Do not hand-edit: the whole \`deps/\` directory is wiped and regenerated on every run \u2014 re-run after dependencies change. Read any entry with \`crtr memory read ${l}/<name>\`.
11
+ Generated by \`${L}\` from the Agent Skill bundles inside this project's node_modules. Do not hand-edit: every \`${A}/\u2026\` document is rewritten on every run \u2014 re-run after dependencies change. Read any entry with \`crtr canvas read ${A}/<name>\`.
12
12
 
13
- `+oe;return W(m(r,"INDEX.md"),C(re,ie)),W(m(r,".gitignore"),`*
14
- `),f}u(De,"runDepsSync");function Ae(s){const n=s.filter(i=>i.status==="imported").length,o=s.filter(i=>i.status==="would-import").length,a=s.filter(i=>i.status==="skipped").length,r=s.filter(i=>i.status==="excluded").length,l=o>0?`crtr sys sync deps \u2014 dry run: ${o} would import, ${a} skipped, ${r} excluded`:`crtr sys sync deps \u2014 ${n} imported, ${a} skipped, ${r} excluded`,g=s.map(i=>{const j=i.reason?` (${i.reason})`:"";return`| ${i.status} | ${i.scope}/${i.name||"\u2014"} | ${i.target} | ${i.source}${j} |`}),$=g.length===0?["No sync candidates."]:["| status | memory doc | target | source |","| --- | --- | --- | --- |",...g];return[l,"",...$].join(`
15
- `)}u(Ae,"renderDepsSummary");const Te=me({name:"deps",description:"vendor Agent Skill bundles shipped inside npm dependencies as derived crouter memory docs",whenToUse:"vendoring Agent Skill bundles shipped inside a project's installed npm dependencies (node_modules/<pkg>/skills/**/SKILL.md) into that project's own .crouter/memory/deps/ as derived, regenerated-per-run memory docs, so agents get first-party dependency guidance without touching node_modules directly.",help:{name:"sys sync deps",summary:"vendor npm-dependency Agent Skill bundles into <project>/.crouter/memory/deps/ (wholly derived, regenerated every run)",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"The project directory whose dependencies to vendor. Default: the nearest ancestor of cwd with a package.json. node_modules must already be installed there, and its repository-root `.crouter/memory/INDEX.md` must declare a `namespace:`."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Report what would be vendored without writing anything."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,target,name,scope,status,reason?}; status is one of imported, would-import, skipped, excluded. `name` is the full canonical name the vendored doc answers at (`<namespace>/deps/<bundle>`), except on an excluded row, which names the `<package>@<version>:<skill>` selector. An excluded row is a dependency bundle rejected before its files enter the vendoring planner."}],outputKind:"object",effects:["Wipes and regenerates <project>/.crouter/memory/deps/ from installed dependency skills, except bundles selected by exact {package,version,skill} entries in package.json crtr.sync.deps.exclude. Each included SKILL.md becomes a system-name/file-none deps/<bundle>/INDEX.md answering at <namespace>/deps/<bundle> (relative sidecar links keep resolving), Markdown sidecar docs are vendored alongside at the same rungs, other sidecar assets are copied verbatim, and a system-preview/file-none deps/INDEX.md catalog answering at <namespace>/deps plus a self-ignoring .gitignore are written. Excluded bundles and their sidecars do not enter the catalog.","Refuses a project store whose repository root declares no namespace, naming `crtr sys migrate --dir <repositoryRoot>` as the remedy; it never declares one itself.","With --dry-run: read-only; writes nothing."]},run:u(async s=>{const n=s.source,o=s.dryRun??!1;return{results:De({sourceArg:n,dryRun:o})}},"run"),render:u(s=>Ae(s.results),"render")});export{T as DEPS_GENERATED_MARKER,De as runDepsSync,Te as sysSyncDepsLeaf};
13
+ `+ie};try{const e=await se(s,t,ae,T);u.push({source:r,name:e.name,status:e.changed?"imported":"unchanged",reason:O})}catch(e){u.push({source:r,name:A,status:"skipped",reason:te(e)})}return u}p(Re,"runDepsSync");function Se(s,n){return{name:`deps/${s}`,kind:"knowledge",preview:he(n.description,"knowledge"),summary:n.description!==""?de(n.description):`Vendored agent doc shipped by ${n.pkg}@${n.version}.`,rules:[{on:"boot",deliver:"name"}],body:n.body}}p(Se,"skillDoc");function Ae(s,n,o,r){let t;try{t=Q(I(n.sourceAbs)).body}catch{t=I(n.sourceAbs)}const i=o.find(k=>s.startsWith(`${k}/`)),m=i?`${r}/deps/${i}`:`a ${r}/deps document`;return{name:`deps/${s}`,kind:"knowledge",preview:`When ${m} links to this file, read this because it carries the linked supporting reference.`,summary:je(t)??`Supporting reference vendored from ${n.pkg}@${n.version}.`,rules:[{on:"boot",deliver:"name"}],body:t}}p(Ae,"sidecarDoc");function De(s){const n=p(i=>s.filter(m=>m.status===i).length,"count"),o=n("would-import")>0?`crtr sys sync deps \u2014 dry run: ${n("would-import")} would import, ${n("would-delete")} would delete, ${n("skipped")} skipped, ${n("excluded")} excluded`:`crtr sys sync deps \u2014 ${n("imported")} imported, ${n("unchanged")} unchanged, ${n("deleted")} deleted, ${n("skipped")} skipped, ${n("excluded")} excluded`,r=s.map(i=>{const m=i.reason?` (${i.reason})`:"";return`| ${i.status} | ${i.name||"\u2014"} | ${i.source}${m} |`}),t=r.length===0?["No sync candidates."]:["| status | document | source |","| --- | --- | --- |",...r];return[o,"",...t].join(`
14
+ `)}p(De,"renderDepsSummary");const Me=pe({name:"deps",description:"vendor Agent Skill bundles shipped inside npm dependencies as documents owned by the project's repo",whenToUse:"vendoring Agent Skill bundles shipped inside a project's installed npm dependencies (node_modules/<pkg>/skills/**/SKILL.md) as documents owned by that project's repo, named under `deps/` and rewritten on every run, so agents get first-party dependency guidance without touching node_modules directly.",help:{name:"sys sync deps",summary:"vendor npm-dependency Agent Skill bundles as the repo's `deps/\u2026` documents (rewritten every run)",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"The project directory whose dependencies to vendor. Default: the nearest ancestor of cwd with a package.json. node_modules must already be installed there, and the directory must be inside a repo."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Report what would be vendored without writing anything."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,name,status,reason?}; status is one of imported, unchanged, would-import, deleted, would-delete, skipped, excluded. `name` is the document's full name (`<repo>/deps/<bundle>`), except on an excluded row, which names the `<package>@<version>:<skill>` selector. An excluded row is a dependency bundle rejected before its files are planned."}],outputKind:"object",effects:["Writes the repo's documents from installed dependency skills, except bundles selected by exact {package,version,skill} entries in package.json crtr.sync.deps.exclude: each included SKILL.md becomes `<repo>/deps/<bundle>` and each Markdown sidecar `<repo>/deps/<bundle>/<path>`, both with a boot rule at name; the `<repo>/deps` catalog carries a boot rule at preview. Other sidecar files are not vendored. Repo documents sync to everyone working in the repo.","Deletes `<repo>/deps/\u2026` documents no installed dependency ships any more.",`Refuses when \`<repo>/deps/\u2026\` documents exist and \`<repo>/deps\` does not carry the "${L}" marker.`,"With --dry-run: read-only; writes nothing."]},run:p(async s=>{const n=s.source,o=s.dryRun??!1;return{results:await Re(ue(),{sourceArg:n,dryRun:o})}},"run"),render:p(s=>De(s.results),"render")});export{L as DEPS_GENERATED_MARKER,Re as runDepsSync,Me as sysSyncDepsLeaf};
@@ -1,4 +1,5 @@
1
- var F=Object.defineProperty;var p=(e,t)=>F(e,"name",{value:t,configurable:!0});import{envProfileId as O}from"../../shared/env.js";import{existsSync as j,readdirSync as W,statSync as E}from"node:fs";import{basename as _,join as g,resolve as b}from"node:path";import{defineLeaf as z}from"../../core/command.js";import{parseFrontmatterGeneric as D}from"../../core/frontmatter.js";import{usage as w}from"../../core/errors.js";import{pathExists as N,readText as $,realpathOrSelf as y,walkFiles as A,writeText as U}from"../../core/fs-utils.js";import{loadProfileManifest as q}from"../../core/profiles/manifest.js";import{CRTR_DIR_NAME as k}from"../../types.js";import{memoryFilePath as J,serializeMemoryDoc as X}from"../../core/memory/mutation-domain.js";import{normalizedName as B,routeFromDescription as K,scalarString as x}from"./sync-shared.js";import{deriveProjectNamespace as H}from"../../core/memory/project-namespace.js";import{associateRepository as C}from"../../core/memory/repository-association.js";import{openProjectMemoryStore as P}from"../../core/memory-resolver.js";import{composeCanonicalName as T,localNameFromPath as Q,resolveLocalName as V,validateExplicitLocalName as Y}from"../../core/memory/identity.js";const Z=new Set(["node_modules",".git",".venv","venv","dist","build",".next",".cache",".yalc",".sisyphus",k]),ee=["AGENTS.md","CLAUDE.md"];function te(e){if(e!==void 0)return[b(e)];const t=[b(process.cwd())],o=O();if(o!==void 0&&o!=="")try{const{manifest:a}=q(o);for(const r of a.projects){const n=b(r.path);t.includes(n)||t.push(n)}}catch{}return t}p(te,"projectDocRoots");function oe(e){const t=[];if(!j(e)||!E(e).isDirectory())return t;const o=b(e),a=[o];for(;a.length>0;){const r=a.pop();for(const i of ee){const u=g(r,i);if(j(u)&&E(u).isFile()){t.push({kind:"agents",path:u,sourceDir:r,walkRoot:o});break}}const n=g(r,".claude","rules");if(j(n))for(const i of A(n,u=>u.endsWith(".md")))t.push({kind:"rule",path:i,sourceDir:r,walkRoot:o});let c;try{c=W(r,{withFileTypes:!0})}catch{continue}for(const i of c)i.isDirectory()&&!Z.has(i.name)&&a.push(g(r,i.name))}return t}p(oe,"collectProjectDocCandidates");function S(e){for(const t of e.split(`
2
- `)){const o=t.replace(/^#+\s*/,"").replace(/\s+/g," ").trim();if(o!=="")return o.length>200?`${o.slice(0,197)}...`:o}return"Migrated project guidance."}p(S,"synthesizeShortForm");function L(e){const t=[];let o=0,a="";for(const r of e){if(r==="{"?o+=1:r==="}"&&(o=Math.max(0,o-1)),r===","&&o===0){t.push(a),a="";continue}a+=r}return t.push(a),t.map(r=>r.trim()).filter(r=>r!=="")}p(L,"splitTopLevelCommas");function re(e){return typeof e=="string"?L(e):Array.isArray(e)?e.filter(t=>typeof t=="string").flatMap(L):[]}p(re,"normalizeRulePaths");function ne(e,t,o,a){const r=C(e);let n;if(r.ok)n=r.association.repositoryRoot;else if(r.ok===!1&&r.code==="no-project-root")n=y(t);else{const s=r.ok===!1?r.reason:"unknown repository association failure";throw w(`cannot associate project guidance at ${e}: ${s}`,{next:`Run \`crtr sys migrate --dir ${e}\`.`})}n=y(n);const c=a.get(n);if(c!==void 0)return c;const i=P(n);if(i.mountStatus==="ready"){const d={namespace:i.repositoryNamespace??i.namespace,repositoryRoot:n,initialize:!1};return a.set(n,d),d}const u=g(n,k,"memory");if((N(u)?A(u,s=>s.endsWith(".md")):[]).length>0)throw w(`project memory store at ${u} is undeclared or invalid`,{next:`Run \`crtr sys migrate --dir ${n}\`.`});const f=H({ownerDir:n,rootBody:o.get(n)});if(f.ok===!1)throw w(`cannot initialize project memory store at ${u}: ${f.reason}`,{next:`Run \`crtr sys migrate --dir ${n}\`.`});const h={namespace:f.namespace,repositoryRoot:n,initialize:!0};return a.set(n,h),h}p(ne,"resolveRepositoryNamespace");function se(){return[{on:"workspace-open",at:"content"},{on:"read",match:"./**",at:"content"}]}p(se,"frontDoorSurfaces");function ae(e){const t=e.trim();return!t.includes("/")||t.startsWith("/")||t.startsWith("**")||t.startsWith("./")?t:`./${t}`}p(ae,"anchorReadGlob");function ie(e,t){const o=D($(e.path)),a=y(e.sourceDir)===t.repositoryRoot;return M(e,t.namespace,o.body,a,o.data??{})}p(ie,"prepareAgentsCandidate");function ce(e){return Array.isArray(e.surfaces)?e.surfaces.filter(t=>{if(t===null||typeof t!="object"||Array.isArray(t))return!1;const o=t;if(o.on!=="read"||!["name","preview","content"].includes(String(o.at)))return!1;const a=o.match,r=typeof a=="string"?a.trim()!=="":Array.isArray(a)&&a.length>0&&a.every(c=>typeof c=="string"&&c.trim()!==""),n=o["match-frontmatter"];return r||n!==null&&typeof n=="object"&&!Array.isArray(n)}):[]}p(ce,"sourceReadRoute");function M(e,t,o,a,r={}){if(!a){const c=ce(r),i=x(r["when-and-why-to-read"])?.trim(),u={kind:"knowledge",privacy:"public","when-and-why-to-read":i!==void 0&&i!==""?i:`When working under ${t}, this knowledge should be read because it carries the nested project guidance.`,"short-form":S(o),...c.length>0?{surfaces:c}:{}};return{candidate:e,name:"",target:g(e.sourceDir,k,"memory","INDEX.md"),frontmatter:u,body:o}}const n={kind:"knowledge",privacy:"public",namespace:t,"when-and-why-to-read":`When working in ${t}, this knowledge should be read because it is the project's operating guide.`,"short-form":S(o),surfaces:se()};return{candidate:e,name:t,target:g(e.sourceDir,k,"memory","INDEX.md"),frontmatter:n,body:o}}p(M,"prepareRootCandidate");function ue(e,t){const o=C(e.sourceDir);if(!o.ok)throw w(`cannot associate rule guidance at ${e.path}: ${o.reason}`,{next:`Run \`crtr sys migrate --dir ${e.sourceDir}\`.`});const a=T(t.namespace,o.association.ownerRelativePath),r=$(e.path),n=D(r),c=n.data??{},i=B(_(e.path)),u=Q(`${i}.md`),l=V(c,u),f=Y(l,a);if(f.ok===!1)throw w(`invalid local rule name in ${e.path}: ${f.reason}`);const h=x(c.description)??"",s=T(a,l),d={kind:"knowledge",privacy:"public",name:l,"when-and-why-to-read":h!==""?K(h,"knowledge"):`When working under ${a}, this knowledge should be read because it is migrated project rule guidance.`,"short-form":h!==""?h.replace(/\s+/g," ").trim():S(n.body)},m=re(c.paths).map(ae);return d.surfaces=m.length>0?[{on:"read",match:m.length===1?m[0]:m,at:"content"}]:[{on:"read",match:"./**",at:"content"}],{candidate:e,name:s,target:J(g(e.sourceDir,k,"memory"),l),frontmatter:d,body:n.body}}p(ue,"prepareRuleCandidate");function I(e,t){if(N(e.target)&&!t.overwrite)return{source:e.candidate.path,target:e.target,name:e.name,scope:"project",status:"skipped",reason:"target memory doc already exists; re-run with --overwrite to replace it"};if(!t.dryRun){const o=N(e.target)?D($(e.target)).data?.privacy??"private":"public";U(e.target,X({...e.frontmatter,privacy:o},e.body))}return{source:e.candidate.path,target:e.target,name:e.name,scope:"project",status:t.dryRun?"would-import":"imported"}}p(I,"convertProjectDoc");function de(e,t){if(e.kind!=="agents")return;let o;try{o=D($(e.path)).data?.namespace}catch{return}if(o===void 0)return;const a=y(e.sourceDir)===t.repositoryRoot,r=g(t.repositoryRoot,k,"memory","INDEX.md");if(!a)throw w(`project guidance at ${e.path} declares a namespace, but ${r} is the only declaration for this repository`,{next:`Run \`crtr sys migrate --dir ${t.repositoryRoot}\`.`});if(o!==t.namespace)throw w(`project guidance namespace ${JSON.stringify(o)} conflicts with the declared store namespace ${JSON.stringify(t.namespace)}`,{next:`Run \`crtr sys migrate --dir ${t.repositoryRoot}\` for a repository-wide identity change.`})}p(de,"validateAuthoredNamespace");function pe(e){const t=e.filter(i=>i.status==="imported").length,o=e.filter(i=>i.status==="would-import").length,a=e.filter(i=>i.status==="skipped").length,r=o>0?`crtr sys sync project-guidance \u2014 dry run: ${o} would import, ${a} skipped`:`crtr sys sync project-guidance \u2014 ${t} imported, ${a} skipped`,n=e.map(i=>{const u=i.reason?` (${i.reason})`:"";return`| ${i.status} | ${i.scope}/${i.name||"\u2014"} | ${i.target} | ${i.source}${u} |`}),c=n.length===0?["No sync candidates."]:["| status | memory doc | target | source |","| --- | --- | --- | --- |",...n];return[r,"",...c].join(`
3
- `)}p(pe,"renderSummary");const Ee=z({name:"project-guidance",description:"migrate repository guidance into repository-root and nested crouter memory docs",whenToUse:"migrating repository CLAUDE.md/AGENTS.md/.claude/rules into the crouter memory-doc model: one-way copy into the repository root's or nested store's .crouter/memory/. Only the repository-root guide becomes the workspace front door; nested guides and rules keep read routes. Never exports memory docs back to these source files.",help:{name:"sys sync project-guidance",summary:"one-way migration: CLAUDE.md/AGENTS.md/.claude/rules \u2192 repository-root and nested crouter memory docs",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"The root to walk recursively for CLAUDE.md/AGENTS.md/.claude/rules files. Default: cwd plus every project in the current profile's purview (when one is selected)."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Show what would be migrated without writing memory docs."},{kind:"flag",name:"overwrite",type:"bool",required:!1,constraint:"Replace an existing target memory doc. Default: skip existing docs to avoid clobbering user-authored memory."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,target,name,scope,status,reason?}; status is one of imported, skipped, would-import."}],outputKind:"object",effects:["Copies the repository-root CLAUDE.md/AGENTS.md into the repository-root .crouter/memory/INDEX.md with the namespace declaration and workspace front-door surfaces. Copies nested guides into nested .crouter/memory/INDEX.md files without namespace, name, or workspace-open metadata. Copies each .claude/rules/*.md into its nested store with a local name and a content read entry over the source paths (\u2018./\u2019-anchored when repo-relative), or a plain read route when no paths are declared. Originals are left untouched.","Skips existing memory docs unless --overwrite is present.","With --dry-run: read-only; writes nothing."]},run:p(async e=>{const t=e.source,o=e.dryRun??!1,a=e.overwrite??!1,r=[],n=new Set,c=[];for(const s of te(t))for(const d of oe(s))n.has(d.path)||(n.add(d.path),c.push(d));const i=new Map;for(const s of c)if(s.kind==="agents")try{i.set(y(s.sourceDir),D($(s.path)).body)}catch{i.set(y(s.sourceDir),void 0)}const u=new Map,l=new Map;for(const s of c){const d=ne(s.sourceDir,s.walkRoot,i,u);l.set(s.path,d),de(s,d)}const f=[];for(const s of c){const d=l.get(s.path);try{const m=s.kind==="agents"?ie(s,d):ue(s,d);f.push({candidate:s,prepared:m})}catch(m){const R=(m instanceof Error?m.message:String(m)).split(`
4
- `)[0];r.push({source:s.path,target:"",name:"",scope:"project",status:"skipped",reason:`unparseable source frontmatter: ${R} \u2014 fix the source file and re-run`})}}for(const s of u.values()){if(c.some(v=>v.kind==="agents"&&l.get(v.path)?.repositoryRoot===s.repositoryRoot&&y(v.sourceDir)===s.repositoryRoot)||P(s.repositoryRoot).mountStatus==="ready")continue;const m=c.find(v=>l.get(v.path)?.repositoryRoot===s.repositoryRoot);if(m===void 0)continue;const R={...m,kind:"agents",sourceDir:s.repositoryRoot},G=M(R,s.namespace,"Migrated project guidance.",!0);r.push(I(G,{dryRun:o,overwrite:a}))}const h=[...f].sort((s,d)=>{const m=y(s.candidate.sourceDir)===l.get(s.candidate.path).repositoryRoot,R=y(d.candidate.sourceDir)===l.get(d.candidate.path).repositoryRoot;return Number(R)-Number(m)});for(const{prepared:s}of h)r.push(I(s,{dryRun:o,overwrite:a}));return{results:r}},"run"),render:p(e=>pe(e.results),"render")});export{Ee as sysSyncProjectGuidanceLeaf};
1
+ var N=Object.defineProperty;var c=(r,t)=>N(r,"name",{value:t,configurable:!0});import{envProfileId as x}from"../../shared/env.js";import{existsSync as y,readdirSync as T,statSync as v}from"node:fs";import{basename as L,join as g,relative as F,resolve as f}from"node:path";import{defineLeaf as W}from"../../core/command.js";import{parseFrontmatterGeneric as $}from"../../core/frontmatter.js";import{readText as D,realpathOrSelf as S,walkFiles as G}from"../../core/fs-utils.js";import{identifyCheckout as M}from"../../core/graph/repo-sync/identity.js";import{loadProfileManifest as O}from"../../core/profiles/manifest.js";import{CRTR_DIR_NAME as P}from"../../types.js";import{cliClient as _}from"../api-client.js";import{normalizedName as j,putDoc as U,repoOwner as I,routeFromDescription as q,rulesFromLegacyFrontmatter as z,scalarString as w,writeFailure as J}from"./sync-shared.js";const K=new Set(["node_modules",".git",".venv","venv","dist","build",".next",".cache",".yalc",".sisyphus",P]),B=["AGENTS.md","CLAUDE.md"];function H(r){if(r!==void 0)return[f(r)];const t=[f(process.cwd())],e=x();if(e!==void 0&&e!=="")try{const{manifest:s}=O(e);for(const o of s.projects){const n=f(o.path);t.includes(n)||t.push(n)}}catch{}return t}c(H,"projectDocRoots");function Q(r){const t=[];if(!y(r)||!v(r).isDirectory())return t;const e=f(r),s=[e];for(;s.length>0;){const o=s.pop();for(const a of B){const d=g(o,a);if(y(d)&&v(d).isFile()){t.push({kind:"agents",path:d,sourceDir:o,walkRoot:e});break}}const n=g(o,".claude","rules");if(y(n))for(const a of G(n,d=>d.endsWith(".md")))t.push({kind:"rule",path:a,sourceDir:o,walkRoot:e});let i;try{i=T(o,{withFileTypes:!0})}catch{continue}for(const a of i)a.isDirectory()&&!K.has(a.name)&&s.push(g(o,a.name))}return t}c(Q,"collectProjectDocCandidates");function me(r){for(const t of r.split(`
2
+ `)){const e=t.replace(/^#+\s*/,"").replace(/\s+/g," ").trim();if(e!=="")return e.length>200?`${e.slice(0,197)}...`:e}return"Migrated project guidance."}c(me,"synthesizeShortForm");function E(r){const t=[];let e=0,s="";for(const o of r){if(o==="{"?e+=1:o==="}"&&(e=Math.max(0,e-1)),o===","&&e===0){t.push(s),s="";continue}s+=o}return t.push(s),t.map(o=>o.trim()).filter(o=>o!=="")}c(E,"splitTopLevelCommas");function V(r){return typeof r=="string"?E(r):Array.isArray(r)?r.filter(t=>typeof t=="string").flatMap(E):[]}c(V,"normalizeRulePaths");function R(r,t){let e=r.trim();return e.includes("/")&&!e.startsWith("/")&&!e.startsWith("**")&&!e.startsWith("./")&&(e=`./${e}`),!e.startsWith("./")||t===""?e:`./${t}/${e.slice(2)}`}c(R,"anchorReadGlob");function k(r){for(const t of r.split(`
3
+ `)){const e=t.replace(/^#+\s*/,"").replace(/\s+/g," ").trim();if(e!=="")return e.length>200?`${e.slice(0,197)}...`:e}return"Migrated project guidance."}c(k,"firstNonEmptyLine");function C(r,t){return j(F(S(r.cwd),S(t)))}c(C,"folderName");function X(r,t){const e=$(D(r.path)),s=e.data??{},o=C(t,r.sourceDir);if(o==="")return{candidate:r,owner:t,doc:{name:"index",kind:"knowledge",preview:`When working in ${t.handle}, read this because it is the project's operating guide.`,summary:k(e.body),rules:[{on:"workspace-open",deliver:"content"},{on:"file-read",match:["./**"],deliver:"content"}],body:e.body}};const n=z(s).filter(a=>a.on==="file-read"),i=w(s["when-and-why-to-read"])?.trim();return{candidate:r,owner:t,doc:{name:o,kind:"knowledge",preview:i!==void 0&&i!==""?i:`When working under ${o} in ${t.handle}, read this because it carries that folder's guidance.`,summary:k(e.body),rules:n.length>0?n.map(a=>a.match?{...a,match:a.match.map(d=>R(d,o))}:a):[{on:"file-read",match:[`./${o}/**`],deliver:"content"}],body:e.body}}}c(X,"prepareAgents");function Y(r,t){const e=$(D(r.path)),s=e.data??{},o=C(t,r.sourceDir),n=w(s.name),i=j(n!==void 0&&n.trim()!==""?n:L(r.path)),a=o===""?i:`${o}/${i}`,d=w(s.description)??"",p=V(s.paths).map(l=>R(l,o)),u={on:"file-read",match:p.length>0?p:[o===""?"./**":`./${o}/**`],deliver:"content"};return{candidate:r,owner:t,doc:{name:a,kind:"knowledge",preview:d!==""?q(d,"knowledge"):`When working under ${o===""?t.handle:`${o} in ${t.handle}`}, read this because it is migrated project rule guidance.`,summary:d!==""?d.replace(/\s+/g," ").trim():k(e.body),rules:[u],body:e.body}}}c(Y,"prepareRule");async function Z(r,t,e){const{owner:s,doc:o}=t,n={source:t.candidate.path,name:`${s.handle}/${o.name}`};if(s.existing.has(o.name)&&!e.overwrite)return{...n,status:"skipped",reason:"a document with this name already exists; re-run with --overwrite to replace it"};if(e.dryRun)return{...n,status:"would-import"};try{const i=await U(r,s,o,"migrated by crtr sys sync project-guidance");return{...n,name:i.name,status:i.changed?"imported":"unchanged"}}catch(i){return{...n,status:"skipped",reason:J(i)}}}c(Z,"convertProjectDoc");function ee(r){const t=c(n=>r.filter(i=>i.status===n).length,"count"),e=t("would-import")>0?`crtr sys sync project-guidance \u2014 dry run: ${t("would-import")} would import, ${t("skipped")} skipped`:`crtr sys sync project-guidance \u2014 ${t("imported")} imported, ${t("unchanged")} unchanged, ${t("skipped")} skipped`,s=r.map(n=>{const i=n.reason?` (${n.reason})`:"";return`| ${n.status} | ${n.name||"\u2014"} | ${n.source}${i} |`}),o=s.length===0?["No sync candidates."]:["| status | document | source |","| --- | --- | --- |",...s];return[e,"",...o].join(`
4
+ `)}c(ee,"renderSummary");const fe=W({name:"project-guidance",description:"migrate repository guidance into documents owned by the repo",whenToUse:"migrating a repository's CLAUDE.md/AGENTS.md/.claude/rules into documents owned by that repo: one-way copy. Only the repository-root guide becomes the workspace front door (`<repo>/index`); nested guides and rules load when files under their folder are read. Never exports documents back to these source files.",help:{name:"sys sync project-guidance",summary:"one-way migration: CLAUDE.md/AGENTS.md/.claude/rules \u2192 documents owned by the repo",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"The root to walk recursively for CLAUDE.md/AGENTS.md/.claude/rules files. Default: cwd plus every project in the current profile's purview (when one is selected)."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Show what would be migrated without writing documents."},{kind:"flag",name:"overwrite",type:"bool",required:!1,constraint:"Replace the body and fields of an existing document of the same name (a new revision). Default: skip it."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,name,status,reason?}; status is one of imported, unchanged, skipped, would-import. `name` is the document's full name."}],outputKind:"object",effects:["Copies the repository-root CLAUDE.md/AGENTS.md into `<repo>/index` with a workspace-open rule and a file-read rule over the whole repo, both at content. Copies a nested guide into `<repo>/<folder>` with a file-read rule over that folder. Copies each .claude/rules/*.md into `<repo>/<folder>/<rule name>` with a file-read rule over its `paths` (placed under the folder when relative), or over the folder when it declares none. Originals are left untouched; a source outside any repo is skipped. Repo documents sync to everyone working in the repo.","Skips existing documents unless --overwrite is present.","With --dry-run: read-only; writes nothing."]},run:c(async r=>{const t=r.source,e=r.dryRun??!1,s=r.overwrite??!1,o=_(),n=[],i=new Set,a=new Map,d=[];for(const p of H(t))for(const u of Q(p)){if(i.has(u.path))continue;i.add(u.path);const l=M(u.sourceDir);if(!l.ok){n.push({source:u.path,name:"",status:"skipped",reason:`not inside a repo: ${l.reason}`});continue}let m=a.get(l.root);m===void 0&&(m=I(o,l.root),a.set(l.root,m));const b=await m;try{d.push(u.kind==="agents"?X(u,b):Y(u,b))}catch(h){const A=(h instanceof Error?h.message:String(h)).split(`
5
+ `)[0];n.push({source:u.path,name:"",status:"skipped",reason:`unparseable source frontmatter: ${A} \u2014 fix the source file and re-run`})}}for(const p of d)n.push(await Z(o,p,{dryRun:e,overwrite:s}));return{results:n}},"run"),render:c(r=>ee(r.results),"render")});export{fe as sysSyncProjectGuidanceLeaf};
@@ -1,7 +1,44 @@
1
+ import { type CrtrClient } from '../../api/index.js';
2
+ import type { DeliveryRuleDTO, DocKindName } from '../../api/dto/docs.js';
3
+ import type { PrivacyName } from '../../api/dto/objects.js';
1
4
  export declare function scalarString(value: unknown): string | undefined;
2
5
  export declare function routeFromDescription(description: string, kind: string): string;
3
- /** Slugify a raw name/path segment into a memory-doc-safe identity: lowercase,
4
- * `.md` stripped, path separators normalized to `/`, each segment reduced to
5
- * `[a-z0-9._-]`. Shared by the skills lane (bundle names) and the
6
- * project-guidance lane (project/subdir labels). */
6
+ /** Slugify a raw name/path into a document name: lowercase, `.md` stripped,
7
+ * path separators normalized to `/`, each segment reduced to `[a-z0-9_-]`. */
7
8
  export declare function normalizedName(raw: string): string;
9
+ /** A document a sync lane converts, in `/v1/docs` terms. */
10
+ export interface SyncDoc {
11
+ name: string;
12
+ body: string;
13
+ preview: string;
14
+ summary?: string;
15
+ kind: DocKindName;
16
+ privacy?: PrivacyName;
17
+ rules: DeliveryRuleDTO[];
18
+ }
19
+ /** Legacy `surfaces`/`gate`/`slash` frontmatter as `/v1/docs` rules. */
20
+ export declare function rulesFromLegacyFrontmatter(fm: Record<string, unknown>): DeliveryRuleDTO[];
21
+ /** Where a lane's documents go: the repo enclosing `cwd`, or the person. */
22
+ export interface SyncOwner {
23
+ owner: 'repo' | 'user';
24
+ /** Sent with every write so `--owner repo` resolves this repo. */
25
+ cwd: string;
26
+ /** The owner's handle; for an owner not yet on the canvas, the handle it is expected to get. */
27
+ handle: string;
28
+ /** Local names of the owner's existing documents. */
29
+ existing: Set<string>;
30
+ }
31
+ /** The repo enclosing `dir`. Throws when `dir` is in no repo. */
32
+ export declare function repoOwner(client: CrtrClient, dir: string): Promise<SyncOwner>;
33
+ /** The person on this runtime. */
34
+ export declare function userOwner(client: CrtrClient): Promise<SyncOwner>;
35
+ /** Write `doc` as a new document, or replace an existing one's body and fields
36
+ * (read first, as every edit requires). Answers the document's full name and
37
+ * whether anything changed. The first write under an owner that was not yet
38
+ * on the canvas corrects `owner.handle` from the name the daemon answers. */
39
+ export declare function putDoc(client: CrtrClient, owner: SyncOwner, doc: SyncDoc, rationale: string): Promise<{
40
+ name: string;
41
+ changed: boolean;
42
+ }>;
43
+ /** One line for a failed write, for a lane's `skipped` row. */
44
+ export declare function writeFailure(err: unknown): string;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var r=(s,e)=>a(s,"name",{value:e,configurable:!0});function p(s){if(typeof s=="string")return s;if(typeof s=="number"||typeof s=="boolean")return String(s)}r(p,"scalarString");function i(s){let e=s.replace(/\s+/g," ").trim();return e=e.replace(/^[,;:.\s]+/,"").replace(/[,;:.\s]+$/,""),/^[A-Z][a-z]/.test(e)&&(e=e.charAt(0).toLowerCase()+e.slice(1)),e}r(i,"cleanClause");const u=/\b(?:use\s+this\s+skill\s+when|use\s+this\s+when|this\s+skill\s+should\s+be\s+used\s+when|used\s+when|use\s+when)\b\s*/i;function d(s,e){const t=s.replace(/\s+/g," ").trim();if(t==="")return`When this migrated ${e} applies, this ${e} should be read.`;const n=t.match(u);if(n&&n.index!==void 0){const o=i(t.slice(0,n.index)),c=i(t.slice(n.index+n[0].length));if(c!==""){let l=`When ${c}, this ${e} should be read`;return o!==""&&(l+=` because ${o}`),`${l}.`}}return`When ${i(t)}, this ${e} should be read.`}r(d,"routeFromDescription");function f(s){return s.replace(/\\/g,"/").replace(/\.md$/i,"").split("/").map(t=>t.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")).filter(Boolean).join("/")}r(f,"normalizedName");export{f as normalizedName,d as routeFromDescription,p as scalarString};
1
+ var l=Object.defineProperty;var s=(n,e)=>l(n,"name",{value:e,configurable:!0});import{ApiError as f}from"../../api/index.js";import{identifyCheckout as h}from"../../core/graph/repo-sync/identity.js";import{rulesFromFrontmatter as p}from"../../core/graph/rules.js";import{usage as w}from"../../core/errors.js";function _(n){if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n)}s(_,"scalarString");function c(n){let e=n.replace(/\s+/g," ").trim();return e=e.replace(/^[,;:.\s]+/,"").replace(/[,;:.\s]+$/,""),/^[A-Z][a-z]/.test(e)&&(e=e.charAt(0).toLowerCase()+e.slice(1)),e}s(c,"cleanClause");const g=/\b(?:use\s+this\s+skill\s+when|use\s+this\s+when|this\s+skill\s+should\s+be\s+used\s+when|used\s+when|use\s+when)\b\s*/i;function S(n,e){const t=n.replace(/\s+/g," ").trim();if(t==="")return`When this migrated ${e} applies, this ${e} should be read.`;const r=t.match(g);if(r&&r.index!==void 0){const a=c(t.slice(0,r.index)),o=c(t.slice(r.index+r[0].length));if(o!==""){let i=`When ${o}, this ${e} should be read`;return a!==""&&(i+=` because ${a}`),`${i}.`}}return`When ${c(t)}, this ${e} should be read.`}s(S,"routeFromDescription");function v(n){return n.replace(/\\/g,"/").replace(/\.md$/i,"").split("/").map(t=>t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")).filter(Boolean).join("/")}s(v,"normalizedName");function C(n){return p(n).map(e=>({on:e.on,deliver:e.deliver,...e.match!==void 0?{match:e.match}:{},...e.matchFrontmatter!==void 0?{match_frontmatter:e.matchFrontmatter}:{},...e.if!==void 0?{if:e.if}:{}}))}s(C,"rulesFromLegacyFrontmatter");async function m(n,e,t){let r;do{const a=await n.objects.list({type:e,limit:100,...r?{cursor:r}:{}});for(const o of a.items){const i=await n.objects.read(o.id);if(i.state==="object"&&"identity"in i&&i.identity.external_id===t)return i.handle}r=a.next_cursor??void 0}while(r);return null}s(m,"ownerByIdentity");async function d(n,e){const t=new Set;let r;do{const a=await n.objects.list({type:"document",owner:e,limit:100,...r?{cursor:r}:{}});for(const o of a.items)t.add(o.name);r=a.next_cursor??void 0}while(r);return t}s(d,"documentNames");async function E(n,e){const t=h(e);if(!t.ok)throw w(`${e} is not inside a repo: ${t.reason}`);const r=await m(n,"repo",t.externalId);return{owner:"repo",cwd:t.root,handle:r??t.handleHint,existing:r?await d(n,r):new Set}}s(E,"repoOwner");async function W(n){const e=await m(n,"person","user:local");return{owner:"user",cwd:process.cwd(),handle:e??"user",existing:e?await d(n,e):new Set}}s(W,"userOwner");async function k(n,e,t,r){const a={preview:t.preview,...t.summary!==void 0&&t.summary!==""?{summary:t.summary}:{},...t.privacy!==void 0?{privacy:t.privacy}:{},rules:t.rules};if(!e.existing.has(t.name)){const u=await n.docs.write({name:t.name,body:t.body,kind:t.kind,owner:e.owner,cwd:e.cwd,...a});return e.handle=u.name.slice(0,u.name.length-t.name.length-1),e.existing.add(t.name),{name:u.name,changed:!0}}const o=`${e.handle}/${t.name}`,i=await n.objects.read(o);return i.state==="object"&&i.type==="document"&&i.bodies.length===1&&i.bodies[0]===t.body&&i.object.preview===t.preview?{name:o,changed:!1}:{name:(await n.docs.edit(o,{body:t.body,rationale:r,...a})).name,changed:!0}}s(k,"putDoc");function z(n){if(n instanceof f)return n.message;throw n}s(z,"writeFailure");export{v as normalizedName,k as putDoc,E as repoOwner,S as routeFromDescription,C as rulesFromLegacyFrontmatter,_ as scalarString,W as userOwner,z as writeFailure};
@@ -1,2 +1,2 @@
1
- var C=Object.defineProperty;var s=(e,o)=>C(e,"name",{value:o,configurable:!0});import{existsSync as L}from"node:fs";import{homedir as N}from"node:os";import{basename as $,dirname as h,join as g,relative as q,resolve as y,sep as T}from"node:path";import{defineLeaf as D}from"../../core/command.js";import{usage as v}from"../../core/errors.js";import{parseFrontmatterGeneric as j}from"../../core/frontmatter.js";import{pathExists as R,readJsonIfExists as M,readText as x,walkFiles as O,writeJson as P,writeText as W}from"../../core/fs-utils.js";import{composeCanonicalName as J}from"../../core/memory/identity.js";import{findProjectScopeRoot as G}from"../../core/scope.js";import{runtimeRoot as z}from"../../core/layout.js";import{piAgentDir as H}from"../../core/runtime/package-health.js";import{CRTR_DIR_NAME as U}from"../../types.js";import{memoryFilePath as B,requireMountedStore as X,serializeMemoryDoc as Y}from"../../core/memory/mutation-domain.js";import{resolveWriteSelector as Q}from"../../core/memory/cli-selector.js";import{normalizedName as K,routeFromDescription as V,scalarString as A}from"./sync-shared.js";const Z="<!-- crtr-boot-skill v",I="SKILL.md",w="skill-import-ignore.json",ee=new Set(["node_modules",".git",".venv","venv","dist","build",".next",".cache",".yalc",".sisyphus",U]);function te(){const e=G();return e?h(e):null}s(te,"projectDir");function k(){return g(z(),w)}s(k,"ignoreFilePath");function oe(){const e=[{label:"claude-user",root:g(N(),".claude","skills"),defaultScope:"user"},{label:"pi-user",root:g(H(),"skills"),defaultScope:"user"}],o=te();return o&&(e.push({label:"claude-project",root:g(o,".claude","skills"),defaultScope:"project"}),e.push({label:"pi-project",root:g(o,".pi","agent","skills"),defaultScope:"project"})),e}s(oe,"defaultSourceRoots");function re(e,o){if(e===void 0)return oe();const r=y(e);if(o!==void 0&&o!=="user"&&o!=="project")throw v(`invalid --scope: ${o} (expected user|project)`);return[{label:"source",root:r,defaultScope:o??"user"}]}s(re,"sourceRootsFromArg");function ne(e){const o=e.root;if(!L(o))return[];const r=y(o),t=[];if($(r)===I)return t.push({path:r,root:h(r),source:e.label,defaultScope:e.defaultScope}),t;const i=g(r,I);if(L(i))return t.push({path:i,root:h(r),source:e.label,defaultScope:e.defaultScope}),t;for(const a of O(r,c=>c===I,c=>ee.has(c)))t.push({path:a,root:r,source:e.label,defaultScope:e.defaultScope});return t}s(ne,"collectCandidates");function se(e,o){const r=A(o?.name);if(r&&r.trim()!=="")return K(r);const t=q(e.root,h(e.path)).split(T).join("/");return K(t||$(h(e.path)))}s(se,"nameForCandidate");function ie(){const e=new Map;return o=>{const r=e.get(o);if(r!==void 0)return r;const{memoryDir:t,store:i}=Q({scope:o});X(i);const a={memoryDir:t,namespace:i.namespace};return e.set(o,a),a}}s(ie,"storeResolver");function ae(){let e;try{e=M(k())}catch(r){throw v(`invalid JSON in ${k()}: ${r instanceof Error?r.message:String(r)}`)}if(e===null)return{version:1,ignored:[]};if(typeof e!="object"||e===null||e.version!==1||!Array.isArray(e.ignored))throw v(`malformed ${k()}: expected {"version":1,"ignored":[...]}`);const o=[];for(const r of e.ignored){if(typeof r!="object"||r===null)continue;const t=r;typeof t.source=="string"&&typeof t.name=="string"&&(t.scope==="user"||t.scope==="project")&&typeof t.ignoredAt=="string"&&o.push({source:y(t.source),name:t.name,scope:t.scope,ignoredAt:t.ignoredAt})}return{version:1,ignored:o}}s(ae,"readIgnoreState");function ce(e){P(k(),e)}s(ce,"writeIgnoreState");function F(e,o){const r=y(e.candidate.path);return o.ignored.some(t=>t.source===r||t.scope===e.scope&&t.name===e.name)}s(F,"isIgnored");function le(e,o){return F(e,o)?!1:(o.ignored.push({source:y(e.candidate.path),name:e.name,scope:e.scope,ignoredAt:new Date().toISOString()}),o.ignored.sort((r,t)=>`${r.scope}/${r.name}`.localeCompare(`${t.scope}/${t.name}`)),!0)}s(le,"rememberIgnored");function _(e,o,r){return{source:e.path,target:"",name:"",scope:o,status:"skipped",reason:r}}s(_,"skipResult");function de(e,o,r){const t=x(e.path),i=r??e.defaultScope;if(t.includes(Z))return _(e,i,"legacy generated crtr boot skill is pruned by host exports, not imported");const a=j(t),c=a.data??{},u=c.kind==="preference"?"preference":"knowledge",d=se(e,c);if(d==="")return _(e,i,"could not derive memory document name");const m=o(i),n=B(m.memoryDir,d),p=J(m.namespace,d);return{candidate:e,raw:t,parsed:a,sourceFm:c,kind:u,name:p,scope:i,target:n}}s(de,"prepareCandidate");function ue(e,o){if(R(e.target)&&!o.overwrite)return{source:e.candidate.path,target:e.target,name:e.name,scope:e.scope,status:"skipped",reason:"target memory doc already exists; re-run with --overwrite to replace it"};const r=A(e.sourceFm.description)??"",t={...e.sourceFm};return delete t.name,delete t.description,delete t.type,delete t.keywords,delete t["system-prompt-visibility"],delete t["file-read-visibility"],delete t["applies-to"],delete t["read-when"],t.kind=e.kind,(typeof t["when-and-why-to-read"]!="string"||t["when-and-why-to-read"].trim()==="")&&(t["when-and-why-to-read"]=V(r,e.kind)),(typeof t["short-form"]!="string"||t["short-form"].trim()==="")&&(t["short-form"]=r.replace(/\s+/g," ").trim()),Array.isArray(t.surfaces)||(t.surfaces=[{on:"boot",at:"preview"}]),o.dryRun||(t.privacy=R(e.target)?j(x(e.target)).data?.privacy??"private":t.privacy??"public",W(e.target,Y(t,e.parsed.body))),{source:e.candidate.path,target:e.target,name:e.name,scope:e.scope,status:o.dryRun?"would-import":"imported"}}s(ue,"convertPrepared");function E(e,o,r){return{source:e.candidate.path,target:e.target,name:e.name,scope:e.scope,status:r?"would-ignore":"ignored",reason:o}}s(E,"ignoreResult");function me(e,o){const r=e.filter(n=>n.status==="imported").length,t=e.filter(n=>n.status==="would-import").length,i=e.filter(n=>n.status==="skipped").length,a=e.filter(n=>n.status==="ignored").length,c=e.filter(n=>n.status==="would-ignore").length;let u;o?u=`crtr sys sync skills \u2014 ${c>0?`${c} would ignore`:`${a} ignored`}, ${i} skipped`:t>0?u=`crtr sys sync skills \u2014 dry run: ${t} would import, ${i} skipped, ${a} ignored`:u=`crtr sys sync skills \u2014 ${r} imported, ${i} skipped, ${a} ignored`;const d=e.map(n=>{const p=n.target||"\u2014",f=n.reason?` (${n.reason})`:"";return`| ${n.status} | ${n.scope}/${n.name||"\u2014"} | ${p} | ${n.source}${f} |`}),m=d.length===0?["No sync candidates."]:["| status | memory doc | target | source |","| --- | --- | --- | --- |",...d];return[u,"",...m].join(`
2
- `)}s(me,"renderSummary");const Ke=D({name:"skills",description:"import host Agent Skill (SKILL.md) bundles as crouter memory docs",whenToUse:"migrating legacy host-native Agent Skill bundles (SKILL.md \u2014 Claude/pi user or project skill roots, or an explicit bundle/root via --source) into the crouter memory-doc model. One-way: crouter never re-exports memory docs back to SKILL.md, and stops reading the originals unconditionally once migrated.",help:{name:"sys sync skills",summary:"one-way import: host SKILL.md bundles \u2192 crouter memory docs",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"A SKILL.md file, a single skill bundle dir containing SKILL.md, or a skills root to scan recursively. Default: the user/project Claude and pi skill roots that exist."},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Target memory scope for the selected sources. Default: user for user host roots and project for project host roots; an explicit value applies to every selected source. `project` writes into the nearest project store walking up from cwd, which must already declare its `namespace:` \u2014 this lane imports documents into a store, never the declaration itself."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Show what would be imported without writing memory docs."},{kind:"flag",name:"overwrite",type:"bool",required:!1,constraint:"Replace an existing target memory doc. Default: skip existing docs to avoid clobbering user-authored memory."},{kind:"flag",name:"ignore",type:"bool",required:!1,constraint:`Permanently ignore every selected SKILL.md source by recording it in ~/.crouter/${w}. Honors --source/--scope; with no --source, ignores every currently discovered default host skill candidate.`},{kind:"flag",name:"include-ignored",type:"bool",required:!1,constraint:"Include ignored candidates in the report without making sync read-only. Pair with --dry-run to audit the full candidate set without importing non-ignored skills."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,target,name,scope,status,reason?}; status is one of imported, skipped, would-import, ignored, would-ignore. `name` is the full canonical name the imported doc answers at \u2014 a user import\u2019s bundle name, a project import\u2019s `<namespace>/<bundle name>`."}],outputKind:"object",effects:["Writes memory/<bundle name>.md in the selected crouter scope with substrate frontmatter and the SKILL.md body. The file stays store-local; a project import answers at `<namespace>/<bundle name>`.","Refuses a project store that declares no namespace, naming the `crtr sys migrate --dir` (legacy store) or `crtr memory write <namespace> --dir` (empty store) remedy; it never declares one itself.","Skips existing memory docs unless --overwrite is present.","Skips marker-bearing generated crtr boot skills; host exports prune those legacy artifacts instead.",`With --ignore: writes ~/.crouter/${w} and does not import the selected sources.`,"With --dry-run: read-only; writes nothing."]},run:s(async e=>{const o=e.source,r=e.scope,t=e.dryRun??!1,i=e.overwrite??!1,a=e.ignore??!1,c=e.includeIgnored??!1,u=re(o,r),d=new Set,m=[];for(const b of u)for(const l of ne(b))d.has(l.path)||(d.add(l.path),m.push(l));const n=ie(),p=ae(),f=[];let S=!1;for(const b of m){const l=de(b,n,r);if("status"in l){f.push(l);continue}if(a){t||(S=le(l,p)||S),f.push(E(l,t?"would record permanent ignore":`recorded in ~/.crouter/${w}`,t));continue}if(F(l,p)){c&&f.push(E(l,`matched ~/.crouter/${w}`,!1));continue}f.push(ue(l,{dryRun:t,overwrite:i}))}return S&&ce(p),{results:f,ignoreFile:k(),ignoreMode:a}},"run"),render:s(e=>me(e.results,e.ignoreMode===!0),"render")});export{Ke as sysSyncSkillsLeaf};
1
+ var _=Object.defineProperty;var i=(e,o)=>_(e,"name",{value:o,configurable:!0});import{existsSync as j}from"node:fs";import{homedir as C}from"node:os";import{basename as R,dirname as k,join as f,relative as E,resolve as h,sep as N}from"node:path";import{defineLeaf as O}from"../../core/command.js";import{usage as L}from"../../core/errors.js";import{parseFrontmatterGeneric as q}from"../../core/frontmatter.js";import{readJsonIfExists as P,readText as D,walkFiles as M,writeJson as T}from"../../core/fs-utils.js";import{identifyCheckout as J}from"../../core/graph/repo-sync/identity.js";import{runtimeRoot as W}from"../../core/layout.js";import{piAgentDir as G}from"../../core/runtime/package-health.js";import{CRTR_DIR_NAME as H}from"../../types.js";import{cliClient as U}from"../api-client.js";import{normalizedName as x,putDoc as z,repoOwner as B,routeFromDescription as V,rulesFromLegacyFrontmatter as X,scalarString as S,userOwner as Y,writeFailure as Q}from"./sync-shared.js";const Z="<!-- crtr-boot-skill v",$="SKILL.md",y="skill-import-ignore.json",ee=new Set(["node_modules",".git",".venv","venv","dist","build",".next",".cache",".yalc",".sisyphus",H]);function oe(){const e=J(process.cwd());return e.ok?e.root:null}i(oe,"projectDir");function w(){return f(W(),y)}i(w,"ignoreFilePath");function te(){const e=[{label:"claude-user",root:f(C(),".claude","skills"),defaultScope:"user"},{label:"pi-user",root:f(G(),"skills"),defaultScope:"user"}],o=oe();return o&&(e.push({label:"claude-project",root:f(o,".claude","skills"),defaultScope:"project"}),e.push({label:"pi-project",root:f(o,".pi","agent","skills"),defaultScope:"project"})),e}i(te,"defaultSourceRoots");function re(e,o){if(e===void 0)return te();const r=h(e);if(o!==void 0&&o!=="user"&&o!=="project")throw L(`invalid --scope: ${o} (expected user|project)`);return[{label:"source",root:r,defaultScope:o??"user"}]}i(re,"sourceRootsFromArg");function ne(e){const o=e.root;if(!j(o))return[];const r=h(o),t=[];if(R(r)===$)return t.push({path:r,root:k(r),source:e.label,defaultScope:e.defaultScope}),t;const n=f(r,$);if(j(n))return t.push({path:n,root:k(r),source:e.label,defaultScope:e.defaultScope}),t;for(const a of M(r,c=>c===$,c=>ee.has(c)))t.push({path:a,root:r,source:e.label,defaultScope:e.defaultScope});return t}i(ne,"collectCandidates");function se(e,o){const r=S(o?.name);if(r&&r.trim()!=="")return x(r);const t=E(e.root,k(e.path)).split(N).join("/");return x(t||R(k(e.path)))}i(se,"nameForCandidate");function ie(e){const o=new Map;return r=>{let t=o.get(r);return t===void 0&&(t=r==="user"?Y(e):B(e,process.cwd()),o.set(r,t)),t}}i(ie,"ownerResolver");function ce(){let e;try{e=P(w())}catch(r){throw L(`invalid JSON in ${w()}: ${r instanceof Error?r.message:String(r)}`)}if(e===null)return{version:1,ignored:[]};if(typeof e!="object"||e===null||e.version!==1||!Array.isArray(e.ignored))throw L(`malformed ${w()}: expected {"version":1,"ignored":[...]}`);const o=[];for(const r of e.ignored){if(typeof r!="object"||r===null)continue;const t=r;typeof t.source=="string"&&typeof t.name=="string"&&(t.scope==="user"||t.scope==="project")&&typeof t.ignoredAt=="string"&&o.push({source:h(t.source),name:t.name,scope:t.scope,ignoredAt:t.ignoredAt})}return{version:1,ignored:o}}i(ce,"readIgnoreState");function ae(e){T(w(),e)}i(ae,"writeIgnoreState");function F(e,o){const r=h(e.candidate.path);return o.ignored.some(t=>t.source===r||t.scope===e.scope&&t.name===e.name)}i(F,"isIgnored");function ue(e,o){return F(e,o)?!1:(o.ignored.push({source:h(e.candidate.path),name:e.name,scope:e.scope,ignoredAt:new Date().toISOString()}),o.ignored.sort((r,t)=>`${r.scope}/${r.name}`.localeCompare(`${t.scope}/${t.name}`)),!0)}i(ue,"rememberIgnored");function K(e,o,r){return{source:e.path,name:"",scope:o,status:"skipped",reason:r}}i(K,"skipResult");async function de(e,o,r){const t=D(e.path),n=r??e.defaultScope;if(t.includes(Z))return K(e,n,"legacy generated crtr boot skill is pruned by host exports, not imported");const a=q(t),c=a.data??{},u=c.kind==="preference"?"preference":"knowledge",d=se(e,c);if(d==="")return K(e,n,"could not derive a document name");const p=await o(n);return{candidate:e,raw:t,parsed:a,sourceFm:c,kind:u,localName:d,name:`${p.handle}/${d}`,scope:n,owner:p}}i(de,"prepareCandidate");const le=["public","friends","private"];async function pe(e,o,r){const t={source:o.candidate.path,name:o.name,scope:o.scope};if(o.owner.existing.has(o.localName)&&!r.overwrite)return{...t,status:"skipped",reason:"a document with this name already exists; re-run with --overwrite to replace it"};if(r.dryRun)return{...t,status:"would-import"};const n=o.sourceFm,a=S(n.description)??"",c=S(n["when-and-why-to-read"])?.trim(),u=S(n["short-form"])?.trim(),d=X(n),p=le.find(m=>m===n.privacy),s={name:o.localName,kind:o.kind,preview:(c!==void 0&&c!==""?c:V(a,o.kind)).replace(/\s+/g," "),summary:u!==void 0&&u!==""?u:a.replace(/\s+/g," ").trim(),...p!==void 0?{privacy:p}:{},rules:Array.isArray(n.surfaces)?d:[{on:"boot",deliver:"preview"}],body:o.parsed.body};try{const m=await z(e,o.owner,s,"imported by crtr sys sync skills");return{...t,name:m.name,status:m.changed?"imported":"unchanged"}}catch(m){return{...t,status:"skipped",reason:Q(m)}}}i(pe,"convertPrepared");function A(e,o,r){return{source:e.candidate.path,name:e.name,scope:e.scope,status:r?"would-ignore":"ignored",reason:o}}i(A,"ignoreResult");function me(e,o){const r=e.filter(s=>s.status==="imported").length,t=e.filter(s=>s.status==="would-import").length,n=e.filter(s=>s.status==="skipped").length,a=e.filter(s=>s.status==="ignored").length,c=e.filter(s=>s.status==="would-ignore").length;let u;o?u=`crtr sys sync skills \u2014 ${c>0?`${c} would ignore`:`${a} ignored`}, ${n} skipped`:t>0?u=`crtr sys sync skills \u2014 dry run: ${t} would import, ${n} skipped, ${a} ignored`:u=`crtr sys sync skills \u2014 ${r} imported, ${n} skipped, ${a} ignored`;const d=e.map(s=>{const m=s.reason?` (${s.reason})`:"";return`| ${s.status} | ${s.name||"\u2014"} | ${s.source}${m} |`}),p=d.length===0?["No sync candidates."]:["| status | document | source |","| --- | --- | --- |",...d];return[u,"",...p].join(`
2
+ `)}i(me,"renderSummary");const xe=O({name:"skills",description:"import host Agent Skill (SKILL.md) bundles as documents",whenToUse:"migrating legacy host-native Agent Skill bundles (SKILL.md \u2014 Claude/pi user or project skill roots, or an explicit bundle/root via --source) into documents. One-way: crouter never re-exports documents back to SKILL.md, and stops reading the originals unconditionally once migrated.",help:{name:"sys sync skills",summary:"one-way import: host SKILL.md bundles \u2192 documents owned by you or the repo",params:[{kind:"flag",name:"source",type:"string",required:!1,constraint:"A SKILL.md file, a single skill bundle dir containing SKILL.md, or a skills root to scan recursively. Default: the user/project Claude and pi skill roots that exist."},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Owner of the imported documents. `user` \u2014 you, the person; `project` \u2014 the repo of the working directory (a repo owns only public documents). Default: user for user host roots and project for project host roots; an explicit value applies to every selected source."},{kind:"flag",name:"dry-run",type:"bool",required:!1,constraint:"Show what would be imported without writing documents."},{kind:"flag",name:"overwrite",type:"bool",required:!1,constraint:"Replace the body and fields of an existing document of the same name (a new revision). Default: skip it."},{kind:"flag",name:"ignore",type:"bool",required:!1,constraint:`Permanently ignore every selected SKILL.md source by recording it in ~/.crouter/${y}. Honors --source/--scope; with no --source, ignores every currently discovered default host skill candidate.`},{kind:"flag",name:"include-ignored",type:"bool",required:!1,constraint:"Include ignored candidates in the report without making sync read-only. Pair with --dry-run to audit the full candidate set without importing non-ignored skills."}],output:[{name:"results",type:"object[]",required:!0,constraint:"Each: {source,target,name,scope,status,reason?}; status is one of imported, unchanged, skipped, would-import, ignored, would-ignore. `name` is the document's full name, `<owner handle>/<bundle name>`."}],outputKind:"object",effects:["Writes the document `<owner handle>/<bundle name>` with the SKILL.md body; its preview comes from the skill description, and it carries a boot rule at preview unless the source declares its own `surfaces`.","Skips existing documents unless --overwrite is present.","Skips marker-bearing generated crtr boot skills; host exports prune those legacy artifacts instead.",`With --ignore: writes ~/.crouter/${y} and does not import the selected sources.`,"With --dry-run: read-only; writes nothing."]},run:i(async e=>{const o=e.source,r=e.scope,t=e.dryRun??!1,n=e.overwrite??!1,a=e.ignore??!1,c=e.includeIgnored??!1,u=re(o,r),d=new Set,p=[];for(const I of u)for(const l of ne(I))d.has(l.path)||(d.add(l.path),p.push(l));const s=U(),m=ie(s),b=ce(),g=[];let v=!1;for(const I of p){const l=await de(I,m,r);if("status"in l){g.push(l);continue}if(a){t||(v=ue(l,b)||v),g.push(A(l,t?"would record permanent ignore":`recorded in ~/.crouter/${y}`,t));continue}if(F(l,b)){c&&g.push(A(l,`matched ~/.crouter/${y}`,!1));continue}g.push(await pe(s,l,{dryRun:t,overwrite:n}))}return v&&ae(b),{results:g,ignoreFile:w(),ignoreMode:a}},"run"),render:i(e=>me(e.results,e.ignoreMode===!0),"render")});export{xe as sysSyncSkillsLeaf};
@@ -1 +1 @@
1
- import{defineBranch as e}from"../../core/command.js";import{sysSyncSkillsLeaf as r}from"./sync-skills.js";import{sysSyncProjectGuidanceLeaf as o}from"./sync-project-guidance.js";import{sysSyncDepsLeaf as n}from"./sync-deps.js";const d=e({name:"sync",description:"migrate non-crouter guidance surfaces into crouter memory docs",whenToUse:"importing or migrating an external guidance source \u2014 host Agent Skill bundles, project CLAUDE.md/AGENTS.md/.claude/rules, or npm-dependency-shipped Agent Skill bundles \u2014 into the crouter memory-doc model",help:{name:"sys sync",summary:"migrate external guidance sources into crouter memory docs",model:"Three independent one-way conversion lanes, none of which ever export memory docs back to their source: skills imports host-native SKILL.md bundles into a scope-root memory dir; project-guidance migrates a project's own CLAUDE.md/AGENTS.md/.claude/rules into that same directory's OWN .crouter/memory/; deps vendors Agent Skill bundles shipped inside installed npm dependencies into the owning project's .crouter/memory/deps/ as wholly derived, regenerated-per-run docs."},children:[r,o,n]});export{d as sysSyncBranch};
1
+ import{defineBranch as e}from"../../core/command.js";import{sysSyncSkillsLeaf as n}from"./sync-skills.js";import{sysSyncProjectGuidanceLeaf as o}from"./sync-project-guidance.js";import{sysSyncDepsLeaf as s}from"./sync-deps.js";const c=e({name:"sync",description:"migrate non-crouter guidance surfaces into documents",whenToUse:"importing or migrating an external guidance source \u2014 host Agent Skill bundles, project CLAUDE.md/AGENTS.md/.claude/rules, or npm-dependency-shipped Agent Skill bundles \u2014 into documents",help:{name:"sys sync",summary:"migrate external guidance sources into documents",model:"Three independent one-way conversion lanes, none of which ever export documents back to their source: skills imports host-native SKILL.md bundles as documents owned by you or by the working directory's repo; project-guidance migrates a repo's own CLAUDE.md/AGENTS.md/.claude/rules into documents owned by that repo; deps vendors Agent Skill bundles shipped inside installed npm dependencies as the repo's `deps/\u2026` documents, rewritten on every run."},children:[n,o,s]});export{c as sysSyncBranch};
@@ -1,6 +1,5 @@
1
1
  export declare const MAX_BACKGROUND_BASH_LOG_BYTES: number;
2
2
  export declare const BACKGROUND_BASH_LOG_TRUNCATION_MARKER = "\n[background bash job output truncated at 10 MiB; remaining output discarded]\n";
3
- /** File-backed command supervisor. The daemon receives completed Linux jobs
4
- * from the durable file state; on a Mac the existing CLI completion notice
5
- * remains the owner of delivery. $12 selects that direct Mac path. */
3
+ /** File-backed command supervisor. It writes the exit code to job.exit and, for a foreground
4
+ * command, claims job.done; the daemon reads job.exit of a backgrounded job and publishes `exited`. */
6
5
  export declare const BASH_JOB_SUPERVISOR_SCRIPT: string;
@@ -1,4 +1,4 @@
1
- const t=10485760,e=`
1
+ const t=10485760,n=`
2
2
  [background bash job output truncated at 10 MiB; remaining output discarded]
3
- `,n=['const fs = require("node:fs");',"const cap = 10485760;",`const marker = Buffer.from(${JSON.stringify(e)});`,"const prefixCap = cap - marker.length;",'const fd = fs.openSync(process.argv[1], "w");',"let written = 0;","let truncated = false;",'process.stdin.on("data", (chunk) => {'," if (truncated) return;"," const available = prefixCap - written;"," if (available > 0) {"," const prefix = chunk.subarray(0, available);"," fs.writeSync(fd, prefix);"," written += prefix.length;"," if (prefix.length === chunk.length) return;"," }"," fs.writeSync(fd, marker);"," truncated = true;","});",'process.stdin.on("end", () => fs.closeSync(fd));'].join(" "),r=["SECONDS=0","n=$(command -v nice)",'${n:+"$n" -n "${10}"} "${9}" "$1" 2>&1 | "${11}" -e '+JSON.stringify(n)+' "$2"',"ec=${PIPESTATUS[0]}","d=$SECONDS",'echo "$ec" > "$3"','if [ "$d" -lt 60 ]; then',' el="${d}s"','elif [ "$d" -lt 3600 ]; then',' el="$((d / 60))m $(printf "%02d" "$((d % 60))")s"',"else",' el="$((d / 3600))h $(printf "%02d" "$((d / 60 % 60))")m"',"fi",'if mv "$4" "$5" 2>/dev/null; then'," :",'elif [ -f "$6" ] && [ "${12}" = direct ]; then',' crtr node message send "Background bash job $7 finished (exit $ec) after $el. Log: $2 Command: $1" --to "$8" --tier urgent || true',"fi"].join(`
4
- `);export{e as BACKGROUND_BASH_LOG_TRUNCATION_MARKER,r as BASH_JOB_SUPERVISOR_SCRIPT,t as MAX_BACKGROUND_BASH_LOG_BYTES};
3
+ `,e=['const fs = require("node:fs");',"const cap = 10485760;",`const marker = Buffer.from(${JSON.stringify(n)});`,"const prefixCap = cap - marker.length;",'const fd = fs.openSync(process.argv[1], "w");',"let written = 0;","let truncated = false;",'process.stdin.on("data", (chunk) => {'," if (truncated) return;"," const available = prefixCap - written;"," if (available > 0) {"," const prefix = chunk.subarray(0, available);"," fs.writeSync(fd, prefix);"," written += prefix.length;"," if (prefix.length === chunk.length) return;"," }"," fs.writeSync(fd, marker);"," truncated = true;","});",'process.stdin.on("end", () => fs.closeSync(fd));'].join(" "),r=["n=$(command -v nice)",'${n:+"$n" -n "$7"} "$6" "$1" 2>&1 | "$8" -e '+JSON.stringify(e)+' "$2"','echo "${PIPESTATUS[0]}" > "$3"','mv "$4" "$5" 2>/dev/null || true'].join(`
4
+ `);export{n as BACKGROUND_BASH_LOG_TRUNCATION_MARKER,r as BASH_JOB_SUPERVISOR_SCRIPT,t as MAX_BACKGROUND_BASH_LOG_BYTES};
@@ -152,11 +152,6 @@ export declare function activeBackgroundBashJobs(contextDir: string, includeFore
152
152
  /** Every live background job for this node whose auto-cancel deadline has
153
153
  * passed at `now`. The daemon's deadline lane stops exactly these. A job with
154
154
  * no deadline (deliberate handoff, or one the node claimed) never appears. */
155
- export declare function completedBackgroundBashJobs(contextDir: string): Array<{
156
- jobId: string;
157
- exitCode: number;
158
- startedAtMs: number;
159
- }>;
160
155
  export declare function expiredAutoBackgroundBashJobs(contextDir: string, now: number): BashJobStatus[];
161
156
  /** Credit every armed auto-cancel deadline for an interval the node was not
162
157
  * permitted to run. A profile pause stops the owning node, so without this the