@north-light/crouter 0.3.348 → 0.3.350

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 (634) hide show
  1. package/bin/crtr-launcher +4 -0
  2. package/bin/runtime-generation-manifest.mjs +12 -2
  3. package/dist/api/client.d.ts +50 -7
  4. package/dist/api/client.js +2 -2
  5. package/dist/api/command-manifest/schema.js +1 -1
  6. package/dist/api/dto/analytics.d.ts +184 -0
  7. package/dist/api/dto/analytics.js +0 -0
  8. package/dist/api/dto/broker-ops.d.ts +43 -1
  9. package/dist/api/dto/config.d.ts +11 -0
  10. package/dist/api/dto/grants.d.ts +14 -0
  11. package/dist/api/dto/grants.js +0 -0
  12. package/dist/api/dto/human-requests.d.ts +14 -0
  13. package/dist/api/dto/memory.d.ts +6 -0
  14. package/dist/api/dto/modelauth.d.ts +35 -0
  15. package/dist/api/dto/node-records.d.ts +35 -0
  16. package/dist/api/dto/node-records.js +0 -0
  17. package/dist/api/dto/nodes.d.ts +5 -0
  18. package/dist/api/dto/profiles.d.ts +38 -3
  19. package/dist/api/dto/worktree.d.ts +11 -0
  20. package/dist/api/errors.d.ts +23 -1
  21. package/dist/api/errors.js +1 -1
  22. package/dist/api/index.d.ts +2 -0
  23. package/dist/api/index.js +1 -1
  24. package/dist/api/node-transport.js +1 -1
  25. package/dist/api/routes.d.ts +22 -0
  26. package/dist/api/routes.js +1 -1
  27. package/dist/build-root.d.ts +6 -1
  28. package/dist/build-root.js +1 -1
  29. package/dist/builtin-memory/crouter-sdk/client.md +34 -0
  30. package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
  31. package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
  32. package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
  37. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
  38. package/dist/cli.js +9 -8
  39. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  40. package/dist/clients/attach/chrome/roster.js +1 -1
  41. package/dist/clients/attach/config.js +1 -1
  42. package/dist/clients/attach/overlays/auth.js +2 -2
  43. package/dist/clients/attach/overlays/graph.js +1 -1
  44. package/dist/clients/attach/render/tool-calls.js +3 -3
  45. package/dist/clients/attach/session/connection.js +1 -1
  46. package/dist/clients/attach/session/profile-files.js +1 -1
  47. package/dist/clients/attach/viewer.js +1569 -816
  48. package/dist/commands/api-client.js +3 -3
  49. package/dist/commands/broker-permissions.d.ts +2 -0
  50. package/dist/commands/broker-permissions.js +1 -0
  51. package/dist/commands/canvas-analytics/chart.d.ts +52 -0
  52. package/dist/commands/canvas-analytics/chart.js +1 -0
  53. package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
  54. package/dist/commands/canvas-analytics/drilldown.js +1 -0
  55. package/dist/commands/canvas-analytics/format.d.ts +29 -0
  56. package/dist/commands/canvas-analytics/format.js +1 -0
  57. package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
  58. package/dist/commands/canvas-analytics/graph-detail.js +2 -0
  59. package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
  60. package/dist/commands/canvas-analytics/graphs.js +1 -0
  61. package/dist/commands/canvas-analytics/memory.d.ts +2 -0
  62. package/dist/commands/canvas-analytics/memory.js +1 -0
  63. package/dist/commands/canvas-analytics/overview.d.ts +2 -0
  64. package/dist/commands/canvas-analytics/overview.js +1 -0
  65. package/dist/commands/canvas-analytics/shell.d.ts +60 -0
  66. package/dist/commands/canvas-analytics/shell.js +2 -0
  67. package/dist/commands/canvas-analytics/time.d.ts +2 -0
  68. package/dist/commands/canvas-analytics/time.js +1 -0
  69. package/dist/commands/canvas-analytics/usage.d.ts +2 -0
  70. package/dist/commands/canvas-analytics/usage.js +1 -0
  71. package/dist/commands/canvas-analytics/view.d.ts +85 -0
  72. package/dist/commands/canvas-analytics/view.js +1 -0
  73. package/dist/commands/canvas-analytics.d.ts +2 -0
  74. package/dist/commands/canvas-analytics.js +1 -0
  75. package/dist/commands/canvas-prune.js +1 -1
  76. package/dist/commands/canvas.js +1 -1
  77. package/dist/commands/cron.js +5 -5
  78. package/dist/commands/human/components.d.ts +2 -0
  79. package/dist/commands/human/components.js +2 -2
  80. package/dist/commands/human/prompts.js +1 -1
  81. package/dist/commands/human/queue.js +1 -1
  82. package/dist/commands/memory/client.d.ts +11 -0
  83. package/dist/commands/memory/client.js +1 -0
  84. package/dist/commands/memory/delete.js +1 -1
  85. package/dist/commands/memory/edit.js +3 -3
  86. package/dist/commands/memory/find.js +1 -1
  87. package/dist/commands/memory/history.js +4 -4
  88. package/dist/commands/memory/lint.js +1 -1
  89. package/dist/commands/memory/list.d.ts +0 -2
  90. package/dist/commands/memory/list.js +1 -1
  91. package/dist/commands/memory/move.js +1 -1
  92. package/dist/commands/memory/origin.js +1 -1
  93. package/dist/commands/memory/read.d.ts +0 -5
  94. package/dist/commands/memory/read.js +3 -3
  95. package/dist/commands/memory/shared.d.ts +0 -178
  96. package/dist/commands/memory/shared.js +1 -12
  97. package/dist/commands/memory/write.js +5 -5
  98. package/dist/commands/node/bash.js +5 -5
  99. package/dist/commands/node/create.d.ts +0 -17
  100. package/dist/commands/node/create.js +2 -3
  101. package/dist/commands/node/inspect.js +6 -6
  102. package/dist/commands/node/lifecycle.js +2 -2
  103. package/dist/commands/node-context.js +2 -2
  104. package/dist/commands/node-inspect-artifacts.js +6 -6
  105. package/dist/commands/pkg/browse/catalog.js +1 -1
  106. package/dist/commands/pkg/browse/model.d.ts +1 -1
  107. package/dist/commands/pkg/market-manage.js +1 -1
  108. package/dist/commands/pkg/plugin-manage.js +10 -10
  109. package/dist/commands/profile/daemon-profiles.d.ts +13 -0
  110. package/dist/commands/profile/daemon-profiles.js +4 -0
  111. package/dist/commands/profile/delete.js +1 -1
  112. package/dist/commands/profile/env.d.ts +6 -0
  113. package/dist/commands/profile/env.js +2 -2
  114. package/dist/commands/profile/kind.js +1 -2
  115. package/dist/commands/profile/list.js +1 -1
  116. package/dist/commands/profile/meta.js +1 -1
  117. package/dist/commands/profile/new.js +1 -1
  118. package/dist/commands/profile/pause.js +1 -1
  119. package/dist/commands/profile/project.js +1 -1
  120. package/dist/commands/profile/rename.js +1 -1
  121. package/dist/commands/profile/show.js +1 -1
  122. package/dist/commands/profile.js +1 -1
  123. package/dist/commands/push.js +3 -3
  124. package/dist/commands/surface-inspect.js +1 -1
  125. package/dist/commands/sys/branch.js +1 -1
  126. package/dist/commands/sys/config.js +1 -1
  127. package/dist/commands/sys/connect.js +3 -3
  128. package/dist/commands/sys/context/admin/actions.js +1 -1
  129. package/dist/commands/sys/context/admin/model.d.ts +1 -0
  130. package/dist/commands/sys/context/admin/model.js +1 -1
  131. package/dist/commands/sys/context/admin.js +1 -1
  132. package/dist/commands/sys/context/expose.js +2 -1
  133. package/dist/commands/sys/context/prompt-review.js +2 -2
  134. package/dist/commands/sys/context/resolve.js +7 -7
  135. package/dist/commands/sys/context/sysprompt.js +1 -1
  136. package/dist/commands/sys/join.d.ts +1 -0
  137. package/dist/commands/sys/join.js +1 -0
  138. package/dist/commands/sys/migrate.js +1 -1
  139. package/dist/commands/sys/panels/models-panel.js +1 -1
  140. package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
  141. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  142. package/dist/commands/sys/provider-login.js +6 -6
  143. package/dist/commands/sys/setup-core.d.ts +1 -1
  144. package/dist/commands/sys/setup-core.js +6 -6
  145. package/dist/commands/sys/setup-settings-runner.js +1 -1
  146. package/dist/commands/sys/setup.js +1 -1
  147. package/dist/commands/sys/spaces.d.ts +1 -0
  148. package/dist/commands/sys/spaces.js +2 -0
  149. package/dist/commands/sys/sync-deps.js +2 -2
  150. package/dist/commands/sys/sync-project-guidance.js +4 -4
  151. package/dist/commands/sys/sync-skills.js +2 -2
  152. package/dist/commands/sys/worktrees.d.ts +1 -0
  153. package/dist/commands/sys/worktrees.js +1 -1
  154. package/dist/commands/sys.js +1 -1
  155. package/dist/core/auth-file.js +2 -2
  156. package/dist/core/bash-job-supervisor.d.ts +6 -0
  157. package/dist/core/bash-job-supervisor.js +4 -0
  158. package/dist/core/bash-jobs.d.ts +13 -6
  159. package/dist/core/bash-jobs.js +8 -7
  160. package/dist/core/broker-client/transport-relay.d.ts +6 -3
  161. package/dist/core/broker-client/transport-relay.js +1 -1
  162. package/dist/core/broker-client/transport-socket.d.ts +6 -1
  163. package/dist/core/broker-client/transport-socket.js +1 -1
  164. package/dist/core/canvas/canvas.d.ts +39 -18
  165. package/dist/core/canvas/canvas.js +21 -20
  166. package/dist/core/canvas/context-strip.d.ts +20 -0
  167. package/dist/core/canvas/context-strip.js +5 -0
  168. package/dist/core/canvas/crons.d.ts +12 -20
  169. package/dist/core/canvas/crons.js +15 -13
  170. package/dist/core/canvas/db.js +2 -2
  171. package/dist/core/canvas/deliveries.d.ts +4 -1
  172. package/dist/core/canvas/deliveries.js +1 -1
  173. package/dist/core/canvas/executions.js +1 -1
  174. package/dist/core/canvas/history.d.ts +2 -1
  175. package/dist/core/canvas/history.js +17 -18
  176. package/dist/core/canvas/memory-reads.d.ts +19 -0
  177. package/dist/core/canvas/memory-reads.js +1 -0
  178. package/dist/core/canvas/migrations.d.ts +0 -4
  179. package/dist/core/canvas/migrations.js +99 -32
  180. package/dist/core/canvas/nav-render.js +1 -1
  181. package/dist/core/canvas/node-agent-paths.d.ts +8 -0
  182. package/dist/core/canvas/node-agent-paths.js +1 -0
  183. package/dist/core/canvas/node-recap.d.ts +2 -2
  184. package/dist/core/canvas/node-recap.js +2 -2
  185. package/dist/core/canvas/node-tokens.d.ts +24 -0
  186. package/dist/core/canvas/node-tokens.js +5 -0
  187. package/dist/core/canvas/paths.d.ts +16 -19
  188. package/dist/core/canvas/paths.js +1 -1
  189. package/dist/core/canvas/render-source.d.ts +2 -2
  190. package/dist/core/canvas/render-source.js +6 -9
  191. package/dist/core/canvas/sessions.d.ts +18 -0
  192. package/dist/core/canvas/sessions.js +4 -1
  193. package/dist/core/canvas/types.d.ts +22 -6
  194. package/dist/core/command-hooks/compose.js +1 -1
  195. package/dist/core/command-hooks/discovery.d.ts +15 -1
  196. package/dist/core/command-hooks/discovery.js +1 -1
  197. package/dist/core/command-hooks/help.d.ts +2 -2
  198. package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
  199. package/dist/core/command-hooks/lifecycle-create.js +1 -1
  200. package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
  201. package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
  202. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
  203. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  204. package/dist/core/command-hooks/transport/plan.d.ts +3 -0
  205. package/dist/core/command-hooks/transport/plan.js +1 -0
  206. package/dist/core/command-plugins/discovery.js +1 -1
  207. package/dist/core/command-plugins/transport/http-invoke.js +2 -2
  208. package/dist/core/command.d.ts +6 -2
  209. package/dist/core/command.js +6 -6
  210. package/dist/core/config.d.ts +8 -5
  211. package/dist/core/config.js +1 -1
  212. package/dist/core/conversation-store/client-worker.d.ts +1 -0
  213. package/dist/core/conversation-store/client-worker.js +1 -0
  214. package/dist/core/conversation-store/client.d.ts +2 -0
  215. package/dist/core/conversation-store/client.js +2 -0
  216. package/dist/core/conversation-store/file-store.d.ts +37 -0
  217. package/dist/core/conversation-store/file-store.js +9 -0
  218. package/dist/core/conversation-store/index.d.ts +50 -0
  219. package/dist/core/conversation-store/index.js +1 -0
  220. package/dist/core/conversation-store/listener.d.ts +4 -0
  221. package/dist/core/conversation-store/listener.js +3 -0
  222. package/dist/core/conversation-store/patch.d.ts +1 -0
  223. package/dist/core/conversation-store/patch.js +1 -0
  224. package/dist/core/directory/join.d.ts +27 -0
  225. package/dist/core/directory/join.js +1 -0
  226. package/dist/core/disk-usage.d.ts +4 -0
  227. package/dist/core/disk-usage.js +1 -0
  228. package/dist/core/events/emit.d.ts +2 -0
  229. package/dist/core/events/emit.js +3 -1
  230. package/dist/core/feed/feed.js +4 -4
  231. package/dist/core/feed/messages.d.ts +3 -0
  232. package/dist/core/feed/messages.js +6 -6
  233. package/dist/core/fs-utils.d.ts +2 -0
  234. package/dist/core/fs-utils.js +3 -3
  235. package/dist/core/grants/local.d.ts +4 -0
  236. package/dist/core/grants/local.js +1 -0
  237. package/dist/core/grants/mirror.d.ts +44 -0
  238. package/dist/core/grants/mirror.js +4 -0
  239. package/dist/core/grants/on-sync.d.ts +22 -0
  240. package/dist/core/grants/on-sync.js +1 -0
  241. package/dist/core/grants/remove.d.ts +7 -0
  242. package/dist/core/grants/remove.js +1 -0
  243. package/dist/core/grants/sandboxes.d.ts +7 -0
  244. package/dist/core/grants/sandboxes.js +1 -0
  245. package/dist/core/grants/sync.d.ts +12 -0
  246. package/dist/core/grants/sync.js +1 -0
  247. package/dist/core/help/memory-extensions.d.ts +3 -0
  248. package/dist/core/help/memory-extensions.js +2 -0
  249. package/dist/core/help.d.ts +14 -0
  250. package/dist/core/help.js +7 -7
  251. package/dist/core/host-exports/builtins.js +3 -3
  252. package/dist/core/host-exports/export.js +3 -3
  253. package/dist/core/human/action-binding.d.ts +2 -0
  254. package/dist/core/human/action-binding.js +1 -1
  255. package/dist/core/human/feedback-companion.d.ts +0 -1
  256. package/dist/core/human/feedback-companion.js +1 -1
  257. package/dist/core/human/page-schema.d.ts +1 -1
  258. package/dist/core/inspector/core.d.ts +2 -0
  259. package/dist/core/inspector/core.js +1 -1
  260. package/dist/core/inspector/tui.js +2 -2
  261. package/dist/core/installed-plugins.js +1 -1
  262. package/dist/core/io.js +6 -6
  263. package/dist/core/keybindings/catalog.d.ts +1 -1
  264. package/dist/core/keybindings/catalog.js +1 -1
  265. package/dist/core/layout-migrate/index.d.ts +15 -0
  266. package/dist/core/layout-migrate/index.js +4 -0
  267. package/dist/core/layout-migrate/paths.d.ts +26 -0
  268. package/dist/core/layout-migrate/paths.js +1 -0
  269. package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
  270. package/dist/core/layout-migrate/stored-paths.js +11 -0
  271. package/dist/core/layout-migrate/stores.d.ts +17 -0
  272. package/dist/core/layout-migrate/stores.js +4 -0
  273. package/dist/core/layout.d.ts +26 -0
  274. package/dist/core/layout.js +2 -0
  275. package/dist/core/llm/run.d.ts +60 -0
  276. package/dist/core/llm/run.js +4 -0
  277. package/dist/core/memory/cli-selector.d.ts +13 -0
  278. package/dist/core/memory/cli-selector.js +1 -0
  279. package/dist/core/memory/history.d.ts +5 -4
  280. package/dist/core/memory/history.js +6 -6
  281. package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
  282. package/dist/core/memory/inline-ref-inventory.js +1 -1
  283. package/dist/core/memory/lint.js +2 -2
  284. package/dist/core/memory/mutation-domain.d.ts +2 -2
  285. package/dist/core/memory/mutation-domain.js +8 -7
  286. package/dist/core/memory/mutations.js +1 -1
  287. package/dist/core/memory/service.d.ts +5 -0
  288. package/dist/core/memory/service.js +2 -2
  289. package/dist/core/memory-resolver.d.ts +11 -7
  290. package/dist/core/memory-resolver.js +2 -2
  291. package/dist/core/model-auth/daemon-login.d.ts +13 -0
  292. package/dist/core/model-auth/daemon-login.js +1 -0
  293. package/dist/core/model-auth/flows.d.ts +45 -0
  294. package/dist/core/model-auth/flows.js +1 -0
  295. package/dist/core/model-auth/handoff-jti.d.ts +4 -0
  296. package/dist/core/model-auth/handoff-jti.js +1 -0
  297. package/dist/core/model-routes.js +1 -1
  298. package/dist/core/nested-stores.d.ts +2 -1
  299. package/dist/core/nested-stores.js +1 -2
  300. package/dist/core/preview-registry.js +2 -2
  301. package/dist/core/profiles/env-store.js +2 -2
  302. package/dist/core/profiles/manifest.d.ts +16 -5
  303. package/dist/core/profiles/manifest.js +1 -1
  304. package/dist/core/provider-management.js +1 -1
  305. package/dist/core/review/birth.js +1 -1
  306. package/dist/core/review/companion.d.ts +0 -2
  307. package/dist/core/review/companion.js +1 -1
  308. package/dist/core/review/fork.js +2 -2
  309. package/dist/core/review/realize.js +1 -1
  310. package/dist/core/review/stage.d.ts +1 -1
  311. package/dist/core/review/stage.js +1 -1
  312. package/dist/core/review/types.d.ts +1 -1
  313. package/dist/core/runs/events.d.ts +34 -0
  314. package/dist/core/runs/events.js +1 -0
  315. package/dist/core/runs/operations.d.ts +43 -0
  316. package/dist/core/runs/operations.js +12 -0
  317. package/dist/core/runtime/bearings-render.d.ts +2 -2
  318. package/dist/core/runtime/bearings-render.js +11 -11
  319. package/dist/core/runtime/bearings.js +2 -2
  320. package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
  321. package/dist/core/runtime/broker/cli-relay.js +1 -0
  322. package/dist/core/runtime/broker/client-registry.d.ts +0 -5
  323. package/dist/core/runtime/broker/client-registry.js +1 -1
  324. package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
  325. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  326. package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
  327. package/dist/core/runtime/broker/engine-drive.js +1 -1
  328. package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
  329. package/dist/core/runtime/broker/fault-retry.js +1 -1
  330. package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
  331. package/dist/core/runtime/broker/frame-dispatch.js +1 -1
  332. package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
  333. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  334. package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
  335. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  336. package/dist/core/runtime/broker/frame-read.js +1 -1
  337. package/dist/core/runtime/broker/frame-session.js +1 -1
  338. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
  339. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  340. package/dist/core/runtime/broker/inbox.d.ts +1 -2
  341. package/dist/core/runtime/broker/inbox.js +7 -10
  342. package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
  343. package/dist/core/runtime/broker/model-adapter.js +2 -0
  344. package/dist/core/runtime/broker/node-token.d.ts +3 -0
  345. package/dist/core/runtime/broker/node-token.js +1 -0
  346. package/dist/core/runtime/broker/read-ops.js +1 -1
  347. package/dist/core/runtime/broker/rebind.d.ts +2 -0
  348. package/dist/core/runtime/broker/rebind.js +1 -1
  349. package/dist/core/runtime/broker/tool-groups.js +1 -1
  350. package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
  351. package/dist/core/runtime/broker/turn-ignition.js +1 -1
  352. package/dist/core/runtime/broker-cli.js +3 -3
  353. package/dist/core/runtime/broker-extension-render.d.ts +2 -5
  354. package/dist/core/runtime/broker-extension-render.js +4 -4
  355. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  356. package/dist/core/runtime/broker-protocol.d.ts +7 -8
  357. package/dist/core/runtime/broker.js +1 -1
  358. package/dist/core/runtime/canvas-extensions.d.ts +1 -0
  359. package/dist/core/runtime/canvas-extensions.js +1 -1
  360. package/dist/core/runtime/close.d.ts +9 -0
  361. package/dist/core/runtime/close.js +1 -1
  362. package/dist/core/runtime/deliver-live.js +1 -1
  363. package/dist/core/runtime/fleet.d.ts +1 -1
  364. package/dist/core/runtime/front-door-login.js +1 -1
  365. package/dist/core/runtime/front-door.js +2 -2
  366. package/dist/core/runtime/headless-pi.d.ts +1 -1
  367. package/dist/core/runtime/headless-pi.js +1 -1
  368. package/dist/core/runtime/host.d.ts +1 -1
  369. package/dist/core/runtime/host.js +3 -1
  370. package/dist/core/runtime/invocation.d.ts +3 -0
  371. package/dist/core/runtime/kickoff.d.ts +1 -0
  372. package/dist/core/runtime/kickoff.js +16 -16
  373. package/dist/core/runtime/launch-target.d.ts +1 -1
  374. package/dist/core/runtime/launch-target.js +1 -1
  375. package/dist/core/runtime/launch.d.ts +10 -35
  376. package/dist/core/runtime/launch.js +1 -1
  377. package/dist/core/runtime/lifecycle.js +2 -2
  378. package/dist/core/runtime/memory.d.ts +1 -1
  379. package/dist/core/runtime/memory.js +1 -1
  380. package/dist/core/runtime/model-registry.js +1 -1
  381. package/dist/core/runtime/model-swap.d.ts +17 -19
  382. package/dist/core/runtime/model-swap.js +1 -1
  383. package/dist/core/runtime/node-read.js +3 -2
  384. package/dist/core/runtime/nodes.d.ts +7 -0
  385. package/dist/core/runtime/nodes.js +1 -1
  386. package/dist/core/runtime/outcome-document.js +1 -1
  387. package/dist/core/runtime/package-health.js +2 -2
  388. package/dist/core/runtime/persona.js +2 -2
  389. package/dist/core/runtime/pi-vendored.js +1 -1
  390. package/dist/core/runtime/placement-tmux.d.ts +1 -1
  391. package/dist/core/runtime/placement-tmux.js +1 -1
  392. package/dist/core/runtime/placement.js +1 -1
  393. package/dist/core/runtime/promote.js +1 -1
  394. package/dist/core/runtime/provider-credential-gate.js +2 -2
  395. package/dist/core/runtime/recovery-hold.d.ts +2 -0
  396. package/dist/core/runtime/recovery-hold.js +1 -0
  397. package/dist/core/runtime/recycle.js +1 -1
  398. package/dist/core/runtime/reopen.js +1 -1
  399. package/dist/core/runtime/reset.js +1 -1
  400. package/dist/core/runtime/revive.d.ts +1 -1
  401. package/dist/core/runtime/revive.js +2 -3
  402. package/dist/core/runtime/roadmap.js +4 -4
  403. package/dist/core/runtime/run-command.d.ts +6 -0
  404. package/dist/core/runtime/run-command.js +1 -1
  405. package/dist/core/runtime/session-branch.d.ts +2 -8
  406. package/dist/core/runtime/session-branch.js +1 -1
  407. package/dist/core/runtime/session-list-cache.d.ts +6 -22
  408. package/dist/core/runtime/session-list-cache.js +1 -1
  409. package/dist/core/runtime/situational-context.js +2 -2
  410. package/dist/core/runtime/spawn-env.d.ts +6 -6
  411. package/dist/core/runtime/spawn-env.js +1 -1
  412. package/dist/core/runtime/spawn.d.ts +5 -0
  413. package/dist/core/runtime/spawn.js +2 -2
  414. package/dist/core/runtime/stop-guard.js +2 -2
  415. package/dist/core/runtime/stop-signals.d.ts +2 -2
  416. package/dist/core/runtime/stop-signals.js +1 -1
  417. package/dist/core/runtime/structured-output.d.ts +10 -4
  418. package/dist/core/runtime/structured-output.js +4 -4
  419. package/dist/core/runtime/tmux-bindings.js +3 -3
  420. package/dist/core/runtime/tmux-driver.d.ts +4 -0
  421. package/dist/core/runtime/tmux-driver.js +7 -7
  422. package/dist/core/runtime/view-socket.d.ts +9 -2
  423. package/dist/core/runtime/view-socket.js +1 -1
  424. package/dist/core/runtime/warm-pool.js +1 -1
  425. package/dist/core/scope.d.ts +3 -2
  426. package/dist/core/scope.js +1 -1
  427. package/dist/core/scoped-state/db.js +1 -1
  428. package/dist/core/scoped-state/migrate.js +3 -3
  429. package/dist/core/scoped-state/profiles.d.ts +2 -1
  430. package/dist/core/scoped-state/profiles.js +1 -1
  431. package/dist/core/scoped-state/schema.d.ts +2 -1
  432. package/dist/core/scoped-state/schema.js +4 -4
  433. package/dist/core/scopes.d.ts +2 -2
  434. package/dist/core/scopes.js +1 -1
  435. package/dist/core/secrets.d.ts +1 -0
  436. package/dist/core/secrets.js +2 -2
  437. package/dist/core/spaces/mounts.d.ts +32 -0
  438. package/dist/core/spaces/mounts.js +1 -0
  439. package/dist/core/spaces/open-beneath.d.ts +71 -0
  440. package/dist/core/spaces/open-beneath.js +1 -0
  441. package/dist/core/spaces/permissions.d.ts +46 -0
  442. package/dist/core/spaces/permissions.js +1 -0
  443. package/dist/core/spaces/process.d.ts +27 -0
  444. package/dist/core/spaces/process.js +1 -0
  445. package/dist/core/spaces/space.d.ts +8 -0
  446. package/dist/core/spaces/space.js +2 -0
  447. package/dist/core/spaces/stop.d.ts +8 -0
  448. package/dist/core/spaces/stop.js +2 -0
  449. package/dist/core/spaces/users.d.ts +19 -0
  450. package/dist/core/spaces/users.js +1 -0
  451. package/dist/core/subscription-state.d.ts +2 -0
  452. package/dist/core/subscription-state.js +3 -3
  453. package/dist/core/substrate/frontmatter-validation.js +1 -1
  454. package/dist/core/substrate/injected-store.d.ts +28 -3
  455. package/dist/core/substrate/injected-store.js +2 -1
  456. package/dist/core/substrate/listings.js +1 -1
  457. package/dist/core/substrate/memory-events.d.ts +6 -0
  458. package/dist/core/substrate/memory-events.js +1 -0
  459. package/dist/core/substrate/on-read-node.js +1 -1
  460. package/dist/core/substrate/on-read.d.ts +6 -6
  461. package/dist/core/substrate/on-read.js +5 -5
  462. package/dist/core/substrate/plan.js +1 -1
  463. package/dist/core/substrate/render-node.js +1 -1
  464. package/dist/core/substrate/render.d.ts +4 -3
  465. package/dist/core/substrate/render.js +38 -38
  466. package/dist/core/substrate/schema.d.ts +6 -0
  467. package/dist/core/substrate/schema.js +1 -1
  468. package/dist/core/tui/panel.js +1 -1
  469. package/dist/core/user-settings.d.ts +12 -0
  470. package/dist/core/user-settings.js +1 -1
  471. package/dist/core/worktree-mutation-async.js +5 -5
  472. package/dist/core/worktree-quarantine.js +1 -1
  473. package/dist/core/worktree-remove.d.ts +15 -0
  474. package/dist/core/worktree-remove.js +1 -0
  475. package/dist/core/worktree-sweep.js +6 -6
  476. package/dist/daemon/analytics/compute.d.ts +37 -0
  477. package/dist/daemon/analytics/compute.js +1 -0
  478. package/dist/daemon/analytics/scan-worker.d.ts +1 -0
  479. package/dist/daemon/analytics/scan-worker.js +2 -0
  480. package/dist/daemon/analytics/scan.d.ts +37 -0
  481. package/dist/daemon/analytics/scan.js +1 -0
  482. package/dist/daemon/api/app-listener.d.ts +11 -0
  483. package/dist/daemon/api/app-listener.js +21 -0
  484. package/dist/daemon/api/bridge.js +5 -5
  485. package/dist/daemon/api/handlers/analytics.d.ts +2 -0
  486. package/dist/daemon/api/handlers/analytics.js +1 -0
  487. package/dist/daemon/api/handlers/attach.js +1 -1
  488. package/dist/daemon/api/handlers/bash-jobs.js +2 -2
  489. package/dist/daemon/api/handlers/bash.js +1 -1
  490. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  491. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  492. package/dist/daemon/api/handlers/canvas.js +6 -6
  493. package/dist/daemon/api/handlers/crons.js +1 -1
  494. package/dist/daemon/api/handlers/files.d.ts +1 -1
  495. package/dist/daemon/api/handlers/files.js +1 -1
  496. package/dist/daemon/api/handlers/health.js +2 -2
  497. package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
  498. package/dist/daemon/api/handlers/hook-exec.js +1 -0
  499. package/dist/daemon/api/handlers/human-requests.js +1 -1
  500. package/dist/daemon/api/handlers/inbox.js +1 -1
  501. package/dist/daemon/api/handlers/llm.d.ts +2 -0
  502. package/dist/daemon/api/handlers/llm.js +3 -0
  503. package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
  504. package/dist/daemon/api/handlers/memory-reads.js +1 -0
  505. package/dist/daemon/api/handlers/memory.js +5 -1
  506. package/dist/daemon/api/handlers/messages.js +2 -2
  507. package/dist/daemon/api/handlers/modelauth.js +1 -1
  508. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  509. package/dist/daemon/api/handlers/node-records.d.ts +2 -0
  510. package/dist/daemon/api/handlers/node-records.js +3 -0
  511. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  512. package/dist/daemon/api/handlers/nodes.js +1 -1
  513. package/dist/daemon/api/handlers/profiles.d.ts +4 -1
  514. package/dist/daemon/api/handlers/profiles.js +1 -1
  515. package/dist/daemon/api/handlers/reports.js +5 -3
  516. package/dist/daemon/api/handlers/reviews.d.ts +1 -1
  517. package/dist/daemon/api/handlers/reviews.js +1 -1
  518. package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
  519. package/dist/daemon/api/handlers/run-routes.js +1 -0
  520. package/dist/daemon/api/handlers/runs.d.ts +9 -0
  521. package/dist/daemon/api/handlers/runs.js +1 -0
  522. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  523. package/dist/daemon/api/handlers/worktree.js +1 -1
  524. package/dist/daemon/api/map.d.ts +10 -4
  525. package/dist/daemon/api/map.js +2 -2
  526. package/dist/daemon/api/operations.d.ts +18 -0
  527. package/dist/daemon/api/operations.js +1 -0
  528. package/dist/daemon/api/principal.d.ts +42 -0
  529. package/dist/daemon/api/principal.js +1 -0
  530. package/dist/daemon/api/router.d.ts +27 -3
  531. package/dist/daemon/api/router.js +1 -1
  532. package/dist/daemon/api/server.d.ts +4 -0
  533. package/dist/daemon/api/server.js +1 -1
  534. package/dist/daemon/api/vendor-signin.d.ts +7 -0
  535. package/dist/daemon/api/vendor-signin.js +77 -0
  536. package/dist/daemon/api/viewer-presence.d.ts +3 -0
  537. package/dist/daemon/api/viewer-presence.js +1 -0
  538. package/dist/daemon/cron/armed-context.d.ts +4 -0
  539. package/dist/daemon/cron/armed-context.js +1 -1
  540. package/dist/daemon/cron/escalation.js +3 -3
  541. package/dist/daemon/cron/lease-recovery.js +1 -1
  542. package/dist/daemon/cron/sinks.js +2 -2
  543. package/dist/daemon/cron-run.d.ts +5 -5
  544. package/dist/daemon/cron-run.js +1 -1
  545. package/dist/daemon/crtrd-cli.js +1 -1
  546. package/dist/daemon/crtrd.js +8 -7
  547. package/dist/daemon/delivery/run-delivery.d.ts +4 -0
  548. package/dist/daemon/delivery/run-delivery.js +1 -1
  549. package/dist/daemon/fleet.d.ts +1 -1
  550. package/dist/daemon/fleet.js +6 -6
  551. package/dist/daemon/http-dispatcher.d.ts +1 -0
  552. package/dist/daemon/http-dispatcher.js +1 -0
  553. package/dist/daemon/human/finish.js +7 -7
  554. package/dist/daemon/joined-owner.d.ts +5 -0
  555. package/dist/daemon/joined-owner.js +1 -0
  556. package/dist/daemon/manage.js +2 -2
  557. package/dist/daemon/messaging/node-message.js +1 -1
  558. package/dist/daemon/park-activity.js +1 -1
  559. package/dist/daemon/reconcilers/bash-deadline.js +1 -1
  560. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  561. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  562. package/dist/daemon/reconcilers/delivery-lane.js +1 -1
  563. package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
  564. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  565. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  566. package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
  567. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  568. package/dist/daemon/runs/append-section.d.ts +6 -0
  569. package/dist/daemon/runs/append-section.js +2 -0
  570. package/dist/daemon/runs/observer.d.ts +5 -0
  571. package/dist/daemon/runs/observer.js +4 -0
  572. package/dist/launcher/bwrap.d.ts +4 -0
  573. package/dist/launcher/bwrap.js +2 -0
  574. package/dist/launcher/client.d.ts +2 -0
  575. package/dist/launcher/client.js +3 -0
  576. package/dist/launcher/main.d.ts +1 -0
  577. package/dist/launcher/main.js +3 -0
  578. package/dist/launcher/netrule.d.ts +1 -0
  579. package/dist/launcher/netrule.js +1 -0
  580. package/dist/launcher/seccomp.d.ts +1 -0
  581. package/dist/launcher/seccomp.js +1 -0
  582. package/dist/launcher/spec.d.ts +88 -0
  583. package/dist/launcher/spec.js +1 -0
  584. package/dist/launcher/users.d.ts +18 -0
  585. package/dist/launcher/users.js +7 -0
  586. package/dist/launcher/validate.d.ts +22 -0
  587. package/dist/launcher/validate.js +1 -0
  588. package/dist/migrations/corpus.js +3 -3
  589. package/dist/migrations/runner.js +1 -1
  590. package/dist/native/linux/addon.node +0 -0
  591. package/dist/native/linux.d.ts +29 -0
  592. package/dist/native/linux.js +1 -0
  593. package/dist/pi-extensions/broker-local.js +2 -2
  594. package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
  595. package/dist/pi-extensions/canvas-bash-valve.js +4 -7
  596. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
  597. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  598. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  599. package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
  600. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
  601. package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
  602. package/dist/pi-extensions/canvas-passive-context.js +11 -11
  603. package/dist/pi-extensions/canvas-recap.js +6 -6
  604. package/dist/pi-extensions/canvas-stophook.js +1 -1
  605. package/dist/pi-extensions/canvas-structured-output.js +4 -4
  606. package/dist/pi-extensions/canvas-tool-guide.js +1 -1
  607. package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
  608. package/dist/pi-extensions/system-prompt-entry.js +1 -0
  609. package/dist/shared/env.d.ts +5 -1
  610. package/dist/shared/env.js +1 -1
  611. package/dist/shared/strip-cd-prefix.d.ts +1 -0
  612. package/dist/shared/strip-cd-prefix.js +1 -0
  613. package/dist/types.d.ts +31 -15
  614. package/docs/cli/memory-and-preferences.md +3 -1
  615. package/docs/sdk/client.md +34 -0
  616. package/docs/sdk/errors.md +2 -0
  617. package/docs/sdk/memory.md +2 -2
  618. package/docs/sdk/streaming.md +21 -0
  619. package/package.json +19 -4
  620. package/packages/crouter-identity/dist/index.d.ts +54 -0
  621. package/packages/crouter-identity/dist/index.js +166 -0
  622. package/packages/crouter-identity/package.json +33 -0
  623. package/runtime.lock.json +44 -8
  624. package/scripts/build-native-linux.mjs +16 -0
  625. package/scripts/install-runtime.mjs +9 -7
  626. package/scripts/lib/isolation-env.mjs +42 -0
  627. package/scripts/runtime-smoke.mjs +49 -0
  628. package/src/native/linux/addon.c +249 -0
  629. package/dist/core/profiles/state-block.d.ts +0 -4
  630. package/dist/core/profiles/state-block.js +0 -3
  631. package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
  632. package/dist/core/runtime/broker/auth-reload.js +0 -1
  633. package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
  634. package/dist/core/substrate/cli-context-delivery.js +0 -1
@@ -1 +1 @@
1
- var f=Object.defineProperty;var u=(r,i)=>f(r,"name",{value:i,configurable:!0});import{defineLeaf as y}from"../../core/command.js";import{CrtrError as g,notFound as w}from"../../core/errors.js";import{loadMemoryStoreView as _,resolveMemoryCandidates as v}from"../../core/memory-resolver.js";import{ApiError as b}from"../../api/index.js";import{cliClient as q}from"../api-client.js";import{contextDir as l}from"../../core/canvas/paths.js";import{requireMountedStore as k,requireUnambiguousDoc as x,resolveReadSelector as R,selectorParam as p}from"./shared.js";const I=y({name:"origin",description:"deref a memory document back to the node + conversation that created it",whenToUse:"you are looking at a stored memory and want to know WHERE it came from \u2014 which node authored it, in what conversation, when, and in which project. Reads the `origin` provenance block the runtime stamps at creation and derefs the node pointer to its live session conversation, context dir, and current state. Docs hand-authored or created before provenance capture carry no origin \u2014 the command says so rather than guessing.",help:{name:"memory origin",summary:"resolve a doc name to its creation provenance and deref the originating node",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical memory name (a project document includes its namespace). Resolved exactly across the selected target view; a same-store physical collision is refused."},p("scope-read"),p("dir"),p("profile")],output:[{name:"name",type:"string",required:!0,constraint:"Resolved document name."},{name:"path",type:"string",required:!0,constraint:"Absolute path to the document on disk."},{name:"scope",type:"string",required:!0,constraint:"Scope whose ordered store view supplied the document."},{name:"local_name",type:"string",required:!0,constraint:"Store-local identity, before project namespace composition."},{name:"store_root",type:"string",required:!0,constraint:"Absolute memory store root containing the document."},{name:"physical_relative_path",type:"string",required:!0,constraint:"Store-relative physical markdown path; sidecars preserve this shape."},{name:"representation",type:"string",required:!0,constraint:"Physical representation: leaf-file or directory-index."},{name:"origin_recorded",type:"boolean",required:!0,constraint:"true when the doc carries an `origin` provenance block; false for hand-authored or pre-provenance docs."},{name:"created",type:"string",required:!1,constraint:"ISO timestamp the doc was created. Absent when origin_recorded is false."},{name:"cwd",type:"string",required:!1,constraint:"Working directory the authoring conversation ran in."},{name:"node",type:"string",required:!1,constraint:"Node id that authored the doc, or null when written by the user at the CLI (no node)."},{name:"node_present",type:"boolean",required:!1,constraint:"true when that node still exists on the canvas (deref below is live); false when it has been pruned."},{name:"node_kind",type:"string",required:!1,constraint:"Kind of the authoring node (only when node_present)."},{name:"node_mode",type:"string",required:!1,constraint:"Mode of the authoring node (only when node_present)."},{name:"node_status",type:"string",required:!1,constraint:"Current lifecycle status of the authoring node (only when node_present)."},{name:"node_description",type:"string",required:!1,constraint:"The authoring node\u2019s description (only when node_present)."},{name:"session_file",type:"string",required:!1,constraint:"Absolute path to the originating conversation\u2019s pi session .jsonl (only when node_present and a session was captured) \u2014 read it to see the conversation that produced the doc."},{name:"context_dir",type:"string",required:!1,constraint:"Absolute path to the authoring node\u2019s context dir (its shared document store)."},{name:"follow_up",type:"string",required:!0,constraint:"Concrete next commands to inspect the origin."}],outputKind:"object",effects:["None. Read-only."]},run:u(async r=>{const i=r.name,a=R({scope:r.scope,dir:r.dir,profile:r.profile});a.store!==null&&k(a.store);let d;try{d=a.store!==null?_(a.store,!0).candidates(i):v(i,{includeDescendants:!0,...a.scope?{scope:a.scope}:{}})}catch(n){if(!(n instanceof g&&n.code==="not_found"))throw n;d=null}if(d===null)throw w(`memory document not found: ${i}`,{memory:i,next:"Run `crtr memory find <query>` to discover documents, or `crtr memory list` to browse the inventory."});const e=x(d),s=e.frontmatter?.origin;if(s===void 0||typeof s!="object")return{name:e.name,path:e.path,scope:e.scope,local_name:e.localName,store_root:e.root,physical_relative_path:e.physicalRelativePath,representation:e.representation,origin_recorded:!1,follow_up:"No provenance recorded \u2014 this doc was hand-authored or created before provenance capture. Read its body with `crtr memory read "+e.name+"`."};const c=u(n=>typeof n=="string"?n:null,"str"),t=c(s.node);let o=null;if(t!==null)try{o=await q().getNode(t)}catch(n){if(!(n instanceof b&&n.status===404))throw n}const h=c(o?.pi_session_file),m=o!==null?`Read the originating conversation at \`${h??"(no session captured)"}\`, browse its shared docs at \`${l(t)}\`, or attach live with \`crtr surface attach ${t}\`.`:t!==null?`The authoring node \`${t}\` has been pruned from the canvas; its context dir may persist at \`${l(t)}\`.`:"Authored by the user at the CLI \u2014 no node conversation to deref.";return{name:e.name,path:e.path,scope:e.scope,local_name:e.localName,store_root:e.root,physical_relative_path:e.physicalRelativePath,representation:e.representation,origin_recorded:!0,created:c(s.created)??void 0,cwd:c(s.cwd)??void 0,node:t??void 0,node_present:t!==null?o!==null:void 0,node_kind:o?.kind??void 0,node_mode:o?.mode??void 0,node_status:o?.status??void 0,node_description:o?.description??void 0,session_file:h??void 0,context_dir:t!==null?l(t):void 0,follow_up:m}},"run")});export{I as originLeaf};
1
+ var f=Object.defineProperty;var d=(a,s)=>f(a,"name",{value:s,configurable:!0});import{defineLeaf as y}from"../../core/command.js";import{memoryQuery as g,memoryRequest as _,memorySelection as w}from"./client.js";import{ApiError as u}from"../../api/index.js";import{cliClient as h}from"../api-client.js";import{conversationIdFromPath as v}from"../../core/conversation-store/index.js";import{selectorParam as c}from"./shared.js";const I=y({name:"origin",description:"deref a memory document back to the node + conversation that created it",whenToUse:"you are looking at a stored memory and want to know WHERE it came from \u2014 which node authored it, in what conversation, when, and in which project. Reads the `origin` provenance block the runtime stamps at creation and derefs the node pointer to its live session conversation, context dir, and current state. Docs hand-authored or created before provenance capture carry no origin \u2014 the command says so rather than guessing.",help:{name:"memory origin",summary:"resolve a doc name to its creation provenance and deref the originating node",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical memory name (a project document includes its namespace). Resolved exactly across the selected target view; a same-store physical collision is refused."},c("scope-read"),c("dir"),c("profile")],output:[{name:"name",type:"string",required:!0,constraint:"Resolved document name."},{name:"path",type:"string",required:!0,constraint:"Absolute path to the document on disk."},{name:"scope",type:"string",required:!0,constraint:"Scope whose ordered store view supplied the document."},{name:"local_name",type:"string",required:!0,constraint:"Store-local identity, before project namespace composition."},{name:"store_root",type:"string",required:!0,constraint:"Absolute memory store root containing the document."},{name:"physical_relative_path",type:"string",required:!0,constraint:"Store-relative physical markdown path; sidecars preserve this shape."},{name:"representation",type:"string",required:!0,constraint:"Physical representation: leaf-file or directory-index."},{name:"origin_recorded",type:"boolean",required:!0,constraint:"true when the doc carries an `origin` provenance block; false for hand-authored or pre-provenance docs."},{name:"created",type:"string",required:!1,constraint:"ISO timestamp the doc was created. Absent when origin_recorded is false."},{name:"cwd",type:"string",required:!1,constraint:"Working directory the authoring conversation ran in."},{name:"node",type:"string",required:!1,constraint:"Node id that authored the doc, or null when written by the user at the CLI (no node)."},{name:"node_present",type:"boolean",required:!1,constraint:"true when that node still exists on the canvas (deref below is live); false when it has been pruned."},{name:"node_kind",type:"string",required:!1,constraint:"Kind of the authoring node (only when node_present)."},{name:"node_mode",type:"string",required:!1,constraint:"Mode of the authoring node (only when node_present)."},{name:"node_status",type:"string",required:!1,constraint:"Current lifecycle status of the authoring node (only when node_present)."},{name:"node_description",type:"string",required:!1,constraint:"The authoring node\u2019s description (only when node_present)."},{name:"session_file",type:"string",required:!1,constraint:"Store path of the originating conversation when the node and conversation still exist. Use `crtr node transcript` to read it."},{name:"context_dir",type:"string",required:!1,constraint:"Absolute path to the authoring node\u2019s context dir (its shared document store)."},{name:"follow_up",type:"string",required:!0,constraint:"Concrete next commands to inspect the origin."}],outputKind:"object",effects:["None. Read-only."]},run:d(async a=>{const s=a.name,e=await _("GET",`/v1/memory/resolve?${g({...w(a),mode:"cli",name:s})}`),r=e.origin;if(r===null||typeof r!="object")return{name:e.name,path:e.path,scope:e.scope,local_name:e.local_name,store_root:e.store_root,physical_relative_path:e.physical_relative_path,representation:e.representation,origin_recorded:!1,follow_up:"No provenance recorded \u2014 this doc was hand-authored or created before provenance capture. Read its body with `crtr memory read "+e.name+"`."};const i=d(n=>typeof n=="string"?n:null,"str"),o=i(r.node);let t=null;if(o!==null)try{t=await h().getNode(o)}catch(n){if(!(n instanceof u&&n.status===404))throw n}const l=v(i(t?.pi_session_file)??"");let p=null;if(l!==null)try{p=(await h().getMemoryOriginConversation(l)).session_file}catch(n){if(!(n instanceof u&&n.status===404))throw n}const m=t!==null?`Read the originating conversation with \`crtr node transcript ${o}\`, browse its shared docs at \`${t.paths.context_dir}\`, or attach live with \`crtr surface attach ${o}\`.`:o!==null?`The authoring node \`${o}\` has been pruned from the canvas; its app and context path are no longer available from the daemon.`:"Authored by the user at the CLI \u2014 no node conversation to deref.";return{name:e.name,path:e.path,scope:e.scope,local_name:e.local_name,store_root:e.store_root,physical_relative_path:e.physical_relative_path,representation:e.representation,origin_recorded:!0,created:i(r.created)??void 0,cwd:i(r.cwd)??void 0,node:o??void 0,node_present:o!==null?t!==null:void 0,node_kind:t?.kind??void 0,node_mode:t?.mode??void 0,node_status:t?.status??void 0,node_description:t?.description??void 0,session_file:p??void 0,context_dir:t?.paths.context_dir,follow_up:m}},"run")});export{I as originLeaf};
@@ -1,6 +1 @@
1
- import { createMemoryDocSnapshot, readMemoryDocContent, resolveMemoryDocs } from '../../core/memory-resolver.js';
2
- export { createMemoryDocSnapshot, readMemoryDocContent, resolveMemoryDocs };
3
- /** One physical document sharing a canonical identity, as the path-aware
4
- * surfaces report it. `--dir <its project>` is how a non-winner is reached. */
5
- export { candidateLocation as candidateRow } from '../../core/memory/service.js';
6
1
  export declare const readLeaf: import("../../core/command.js").LeafDef;
@@ -1,6 +1,6 @@
1
- var D=Object.defineProperty;var a=(t,i)=>D(t,"name",{value:i,configurable:!0});import{envNodeId as E}from"../../shared/env.js";import{diag as v}from"../../core/io.js";import{defineLeaf as S}from"../../core/command.js";import{memoryExtensionEffectiveCatalog as N,projectEffectiveMemoryExtensions as M}from"../../core/memory/extensions.js";import{ambientMemoryTarget as P,createMemoryDocSnapshot as C,memoryStoresInPrecedence as I,readMemoryDocContent as L,resolveMemoryDocs as B}from"../../core/memory-resolver.js";import{candidateLocation as F,readDoc as T}from"../../core/memory/service.js";import{expandShellBlocks as K,hasShellBlocks as U,makeNodeShellRunner as O}from"../../core/runtime/shell-expansion.js";import{registerDocumentExposure as Y,registerExposure as X}from"../../core/substrate/injected-store.js";import{renderCliContextDelivery as x}from"../../core/substrate/cli-context-delivery.js";import{dirDedupKey as $,renderDirListing as W}from"../../core/substrate/listings.js";import{contentReadAttachments as z}from"../../core/substrate/on-read.js";import{renderResult as G}from"../../core/render.js";import{effectiveDocKind as H}from"../../core/substrate/schema.js";import{MEMORY_KINDS as J,resolveReadSelector as Q,selectorParam as q}from"./shared.js";import{candidateLocation as fe}from"../../core/memory/service.js";const V=S({name:"read",description:"load a memory document body by name",whenToUse:"a task in front of you matches a stored document and you already know its canonical name \u2014 read it before improvising. Resolution is exact and takes the full canonical name (a project document is `<namespace>/<local name>`); among documents sharing one name the winner is the nearest scope (node > project stack > profile > user > builtin). A directory name is a valid target too: it answers with that directory\u2019s own document, when it has one, together with its immediate listing, and walking directories is the sanctioned browse move. You name the document by its crtr identifier, never a file path \u2014 do not cat or find the markdown off disk. Reach for `crtr memory find` first when you do not yet know which document applies.",help:{name:"memory read",summary:"resolve an exact canonical name to its document body (frontmatter stripped unless --frontmatter), plus the directory listing when that name has members",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical memory name \u2014 a project document is `<namespace>/<local name>`, every other store\u2019s local names are already canonical, where a nested store's namespace includes its path under the repository root. Resolution is exact: a file path, a bare leaf, a `<scope>/<name>` spelling, and a trailing `/INDEX` all fail. A name that carries members returns its listing alongside its body; a name that is only a directory returns the listing alone."},{kind:"flag",name:"kind",type:"enum",choices:[...J],required:!1,constraint:"Narrows resolution when the name is ambiguous across kinds."},{kind:"flag",name:"frontmatter",type:"bool",required:!1,constraint:"When present, includes the YAML frontmatter in the returned body. Off by default \u2014 only the body is returned."},q("scope-read"),q("dir",{},"Reads that store alone: the name resolves against its documents only, and the listing shows its members only.")],output:[{name:"name",type:"string",required:!0,constraint:"Resolved canonical document name, or the directory name on a directory read."},{name:"local_name",type:"string",required:!1,constraint:"Store-local identity, before the store namespace composed the canonical name. Absent on a directory read."},{name:"kind",type:"string",required:!1,constraint:"Resolved kind: knowledge or preference. Absent on a directory read."},{name:"scope",type:"string",required:!1,constraint:"Scope the document was resolved from: node, project, profile, user, or builtin. Absent on a directory read."},{name:"path",type:"string",required:!1,constraint:"Absolute path to the document on disk. Revise it with `crtr memory edit`, never by editing this file \u2014 an edit records why the change happened and lands in the doc\u2019s revision history. Absent on a directory read."},{name:"store_root",type:"string",required:!1,constraint:"Absolute memory store root the document loaded from. Absent on a directory read."},{name:"physical_relative_path",type:"string",required:!1,constraint:"Store-relative physical markdown path, ordering prefixes and any `INDEX.md` kept. Absent on a directory read."},{name:"representation",type:"string",required:!1,constraint:"Physical representation of this identity: leaf-file or directory-index. Absent on a directory read."},{name:"candidates",type:"object[]",required:!1,constraint:"Present only when several physical documents share this canonical name: one row per candidate in source order, {winner, scope, store_root, physical_relative_path, path}. The winner is what this read returned; reach a non-winning one with `--dir <its project>`."},{name:"content",type:"string",required:!1,constraint:"Document body. Frontmatter stripped unless --frontmatter is set. A document may embed shell as `!`cmd`` or a ```! fenced block; each runs once per read, in the current working directory, and is replaced by its output. Read `path` off disk when you need the literal unexecuted text. May be preceded by one `<auto-loaded-context>` block carrying the doc\u2019s neighborhood listings and any docs routed to this read. Absent on a directory read."},{name:"listing",type:"string[]",required:!1,constraint:"Present when the name has members \u2014 a directory document returns its body AND this listing, a bare directory returns the listing alone: one `[[name]]: <when-and-why>` line per member doc, one bare `[[name]]` per subdirectory. Follow any line with `crtr memory read <name>`."},{name:"extensions",type:"object",required:!1,constraint:"Effective valid plugin-owned metadata, keyed by plugin namespace then field. Includes enabled declaration defaults without writing them to frontmatter; disabled and unresolved namespaces are omitted. Present only on a document read."},{name:"links",type:"string[]",required:!1,constraint:"Canonical names this document links to via `[[name]]` that resolve in the current corpus \u2014 further reading, loaded only on demand with `crtr memory read <name>`. A directory link returns that directory\u2019s listing. Omitted when the body carries no resolvable links."},{name:"follow_up",type:"string",required:!1,constraint:"Present whenever the read returned a listing or resolvable body links."}],outputKind:"object",effects:["Reads the document. A document that embeds shell (`!`cmd`` or a ```! block) runs those commands once, in the current working directory.","Records a content delivery for this node: a document whose profile project caps automatic boot and workspace-open disclosure below content is still returned whole here, and unsolicited channels stay quiet about it afterwards."]},run:a(async t=>{const i=t.name,c=t.kind,A=t.frontmatter,s=Q({scope:t.scope,dir:t.dir}),l=P();s.store===null&&I(l,s.scope,!0,!0);const n=T({target:l,scope:s.scope,store:s.store,name:i,kind:c,frontmatter:A}),f=E()||void 0;if(n.kind==="directory"){const o=await x({nodeId:f,allowUnavailableSubject:!0,render:a((u,r)=>{const p=W(n.listingByName,n.name,r,!1);return X(r,$(n.name),"preview"),{name:n.name,listing:p,follow_up:"Each line is readable with `crtr memory read <name>` \u2014 a `[[name]]: <line>` entry is a doc, a bare `[[name]]` is a subdirectory whose read browses deeper. Browse the whole inventory with `crtr memory list`."}},"render")});return o.diagnostic!==void 0&&v(o.diagnostic),o.result}const{doc:e,candidates:w,content:m,links:d,listingByName:R}=n,_=H(e),b=U(m)?await K(m,O({cwd:process.cwd()})):m,h=await x({nodeId:f,allowUnavailableSubject:!0,render:a((o,u)=>{Y(u,e.path,e.body,"content");const r=z(e,{subject:o,target:u,byName:R,memoryTarget:l,listings:"blocks",explicit:!0}),p=r.blocks.length===0?b:`<auto-loaded-context>
2
- ${r.blocks.join(`
1
+ var c=Object.defineProperty;var r=(e,t)=>c(e,"name",{value:t,configurable:!0});import{defineLeaf as l}from"../../core/command.js";import{expandShellBlocks as m,hasShellBlocks as h,makeNodeShellRunner as u}from"../../core/runtime/shell-expansion.js";import{renderResult as y}from"../../core/render.js";import{memoryQuery as p,memoryRequest as f,memorySelection as b}from"./client.js";import{MEMORY_KINDS as w,selectorParam as i}from"./shared.js";const g=l({name:"read",description:"load a memory document body by name",whenToUse:"a task in front of you matches a stored document and you already know its canonical name \u2014 read it before improvising. Resolution is exact and takes the full canonical name (a project document is `<namespace>/<local name>`); among documents sharing one name the winner is the nearest scope (node > project stack > profile > user > builtin). A directory name is a valid target too: it answers with that directory\u2019s own document, when it has one, together with its immediate listing, and walking directories is the sanctioned browse move. You name the document by its crtr identifier, never a file path \u2014 do not cat or find the markdown off disk. Reach for `crtr memory find` first when you do not yet know which document applies.",help:{name:"memory read",summary:"resolve an exact canonical name to its document body (frontmatter stripped unless --frontmatter), plus the directory listing when that name has members",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical memory name \u2014 a project document is `<namespace>/<local name>`, every other store\u2019s local names are already canonical, where a nested store's namespace includes its path under the repository root. Resolution is exact: a file path, a bare leaf, a `<scope>/<name>` spelling, and a trailing `/INDEX` all fail. A name that carries members returns its listing alongside its body; a name that is only a directory returns the listing alone."},{kind:"flag",name:"kind",type:"enum",choices:[...w],required:!1,constraint:"Narrows resolution when the name is ambiguous across kinds."},{kind:"flag",name:"frontmatter",type:"bool",required:!1,constraint:"When present, includes the YAML frontmatter in the returned body. Off by default \u2014 only the body is returned."},i("scope-read"),i("dir",{},"Reads that store alone: the name resolves against its documents only, and the listing shows its members only.")],output:[{name:"name",type:"string",required:!0,constraint:"Resolved canonical document name, or the directory name on a directory read."},{name:"local_name",type:"string",required:!1,constraint:"Store-local identity, before the store namespace composed the canonical name. Absent on a directory read."},{name:"kind",type:"string",required:!1,constraint:"Resolved kind: knowledge or preference. Absent on a directory read."},{name:"privacy",type:"string",required:!1,constraint:"App access level: public, friends, or private. Missing legacy frontmatter resolves to private. Absent on a directory read."},{name:"scope",type:"string",required:!1,constraint:"Scope the document was resolved from: node, project, profile, user, or builtin. Absent on a directory read."},{name:"path",type:"string",required:!1,constraint:"Absolute path to the document on disk. Revise it with `crtr memory edit`, never by editing this file \u2014 an edit records why the change happened and lands in the doc\u2019s revision history. Absent on a directory read."},{name:"store_root",type:"string",required:!1,constraint:"Absolute memory store root the document loaded from. Absent on a directory read."},{name:"physical_relative_path",type:"string",required:!1,constraint:"Store-relative physical markdown path, ordering prefixes and any `INDEX.md` kept. Absent on a directory read."},{name:"representation",type:"string",required:!1,constraint:"Physical representation of this identity: leaf-file or directory-index. Absent on a directory read."},{name:"candidates",type:"object[]",required:!1,constraint:"Present only when several physical documents share this canonical name: one row per candidate in source order, {winner, scope, store_root, physical_relative_path, path}. The winner is what this read returned; reach a non-winning one with `--dir <its project>`."},{name:"content",type:"string",required:!1,constraint:"Document body. Frontmatter stripped unless --frontmatter is set. A document may embed shell as `!`cmd`` or a ```! fenced block; each runs once per read, in the current working directory, and is replaced by its output. Read `path` off disk when you need the literal unexecuted text. May be preceded by one `<auto-loaded-context>` block carrying the doc\u2019s neighborhood listings and any docs routed to this read. Absent on a directory read."},{name:"listing",type:"string[]",required:!1,constraint:"Present when the name has members \u2014 a directory document returns its body AND this listing, a bare directory returns the listing alone: one `[[name]]: <when-and-why>` line per member doc, one bare `[[name]]` per subdirectory. Follow any line with `crtr memory read <name>`."},{name:"extensions",type:"object",required:!1,constraint:"Effective valid plugin-owned metadata, keyed by plugin namespace then field. Includes enabled declaration defaults without writing them to frontmatter; disabled and unresolved namespaces are omitted. Present only on a document read."},{name:"links",type:"string[]",required:!1,constraint:"Canonical names this document links to via `[[name]]` that resolve in the current corpus \u2014 further reading, loaded only on demand with `crtr memory read <name>`. A directory link returns that directory\u2019s listing. Omitted when the body carries no resolvable links."},{name:"follow_up",type:"string",required:!1,constraint:"Present whenever the read returned a listing or resolvable body links."}],outputKind:"object",effects:["Reads the document. A document that embeds shell (`!`cmd`` or a ```! block) runs those commands once, in the current working directory.","Records a content delivery for this node: a document whose profile project caps automatic boot and workspace-open disclosure below content is still returned whole here, and unsolicited channels stay quiet about it afterwards."]},run:r(async e=>{const t=await f("GET",`/v1/memory/docs/${encodeURIComponent(e.name)}?${p({...b(e),mode:"cli",kind:e.kind,frontmatter:e.frontmatter})}`);if(typeof t.content!="string")return t;const n=t.content,o=h(n)?await m(n,u({cwd:process.cwd()})):n,{attachment_blocks:s,...d}=t,a=s;return{...d,content:a.length===0?o:`<auto-loaded-context>
2
+ ${a.join(`
3
3
  `)}
4
4
  </auto-loaded-context>
5
5
 
6
- ${b}`,y=r.listing,g=y!==void 0&&y.length>0,k=g?d.length>0?"Each `[[name]]` line in `listing` is one of this directory\u2019s immediate members, and the `[[name]]` links in the body are further reading \u2014 follow either with `crtr memory read <name>` only when the task needs that depth.":"Each `[[name]]` line in `listing` is one of this directory\u2019s immediate members, readable with `crtr memory read <name>` \u2014 follow one only when the task needs that depth.":d.length>0?"The `[[name]]` links in the body are further reading \u2014 follow one with `crtr memory read <name>` only when the task needs that depth.":null;return{name:e.name,local_name:e.localName,kind:_,scope:e.scope,path:e.path,store_root:e.root,physical_relative_path:e.physicalRelativePath,representation:e.representation,...w.length>1?{candidates:w.map(j=>F(j,e))}:{},content:p,...g?{listing:y}:{},extensions:M(e.frontmatter?.extensions,N(e)),...d.length>0?{links:d}:{},...k===null?{}:{follow_up:k}}},"render")});return h.diagnostic!==void 0&&v(h.diagnostic),h.result},"run"),render:a(t=>{const{extensions:i,...c}=t;return G(c,V.help)},"render")});export{fe as candidateRow,C as createMemoryDocSnapshot,V as readLeaf,L as readMemoryDocContent,B as resolveMemoryDocs};
6
+ ${o}`}},"run"),render:r(e=>{const{extensions:t,...n}=e;return y(n,g.help)},"render")});export{g as readLeaf};
@@ -1,189 +1,11 @@
1
1
  import { type FlagParam } from '../../core/help.js';
2
- import { type MemoryCandidateSet, type MemoryDoc, type MemoryScope, type MemoryStoreDescriptor } from '../../core/memory-resolver.js';
3
- import { type DocRepresentation } from '../../core/memory/identity.js';
4
- export { memoryScopeRank as scopeRank, requireCanonicalName, requireLocalNameInStore, requireMountedStore } from '../../core/memory/service.js';
5
- import { type MemoryExtensionCatalog } from '../../core/memory/extensions.js';
6
- import type { MemoryExtensionScalar } from '../../types.js';
7
2
  export declare const MEMORY_KINDS: readonly ["knowledge", "preference"];
8
3
  export declare const MEMORY_READ_SCOPES: readonly ["user", "project", "profile", "node", "builtin"];
9
4
  export declare const MEMORY_WRITE_SCOPES: readonly ["user", "project", "profile", "node"];
10
- export declare const MEMORY_SCOPES: readonly ["user", "project", "profile", "node"];
11
- export declare function registerMemoryListingExposure(identity: string): void;
12
- /** The raw selector flags a memory leaf accepts. */
13
- export interface MemorySelectorInput {
14
- scope?: string | undefined;
15
- dir?: string | undefined;
16
- profile?: string | undefined;
17
- }
18
- export interface MemoryReadSelector {
19
- /** Source-stack filter for a target view, absent when unfiltered. */
20
- scope?: MemoryScope;
21
- /** The one exact store `--dir` selected, or null for a target view. Returned
22
- * whatever its mount status: lint inspects a store the runtime refuses to
23
- * mount, everything else calls `requireMountedStore` first. */
24
- store: MemoryStoreDescriptor | null;
25
- }
26
- export interface MemoryWriteSelector {
27
- scope: MemoryScope;
28
- /** Absolute `<root>/memory` dir the document is written under. */
29
- memoryDir: string;
30
- /** The store its canonical name composes under. */
31
- store: MemoryStoreDescriptor;
32
- }
33
- /** Resolve the read selection: a scope filter, or the exact store `--dir`
34
- * names. */
35
- export declare function resolveReadSelector(input: MemorySelectorInput): MemoryReadSelector;
36
- /** Resolve the one store a mutation writes to. Default: project when a project
37
- * scope exists for the cwd, else user. An explicit `--scope project` with no
38
- * project scope yet scaffolds one (`ensureProjectScopeRoot`). `--scope
39
- * profile` is NEVER a default — it requires a selected profile, from
40
- * `--profile <id-or-name>` or else the process's `CRTR_PROFILE_ID`, resolved
41
- * through the centralized `loadProfileManifest` (never a raw path join).
42
- * `--scope node` targets the this-node store
43
- * (`nodes/<CRTR_NODE_ID>/context/memory/`) and requires a running node. */
44
- export declare function resolveWriteSelector(input: MemorySelectorInput): MemoryWriteSelector;
45
- /** The scope + memory dir a write lands in. Retained for the leaves that still
46
- * place documents by path alone; they cut over to `resolveWriteSelector` and
47
- * `planNewDocumentPlacement` in their own phases. */
48
- export declare function resolveWriteTarget(scopeArg: string | undefined, profileArg?: string, dirArg?: string): {
49
- scope: MemoryScope;
50
- memoryDir: string;
51
- };
52
- /** Refuse a project store the runtime will not resolve through. A project
53
- * repository-root store carries the identity every canonical name in it composes under, so
54
- * without a valid declaration no name can be validated, stripped, or placed;
55
- * user, profile, and node stores have no declaration and always pass, even
56
- * before their directory exists. */
57
- /** Normalize and validate a full canonical name: ordering prefixes are
58
- * physical-path-only, a trailing `INDEX` is never an address, and the segment
59
- * charset is fixed. */
60
- /** The store-local name a full canonical name has inside one exact store, or a
61
- * usage error when it falls outside that store's namespace. `''` names the
62
- * store's own root document — a project store answers at its namespace. */
63
- export interface MemoryPlacement {
64
- store: MemoryStoreDescriptor;
65
- /** Full canonical name — the address the document answers at. */
66
- canonicalName: string;
67
- /** Store-local name, `''` for the store's own root document. */
68
- localName: string;
69
- representation: DocRepresentation;
70
- /** Store-relative markdown path. */
71
- physicalRelativePath: string;
72
- /** Absolute path of the `.md` file. */
73
- path: string;
74
- }
75
- /** Where a NEW document (a `write`, a `move` destination) physically lands in
76
- * one exact store, after proving the canonical identity is free.
77
- *
78
- * Both physical forms carry the same identity, so occupancy is checked against
79
- * the loaded identities AND both `<local>.md` and `<local>/INDEX.md` — a file
80
- * whose explicit `name:` points elsewhere still owns its path. The chosen form
81
- * is `<local>/INDEX.md` when the canonical directory already has descendants
82
- * in this store (the document fronts a directory that exists), else
83
- * `<local>.md`; descendants created later never relocate it, because either
84
- * form validly owns the identity. Pass `storeDocs` when the caller already
85
- * loaded the store, and `source` when planning a move, whose own identity and
86
- * file are being vacated. */
87
- export declare function planNewDocumentPlacement(store: MemoryStoreDescriptor, rawName: string, storeDocs?: readonly MemoryDoc[], source?: MemoryDoc): MemoryPlacement;
88
- /** The document a mutation acts on, refusing an identity two files in ONE
89
- * store both own. Reads stay answerable (`<name>/INDEX.md` deterministically
90
- * wins), but a mutation would silently pick one of two files, so it stops with
91
- * both paths. Candidates in OTHER stores are ordinary alternates — precedence
92
- * picked the winner and `--dir` reaches the rest. */
93
- export declare function requireUnambiguousDoc(set: MemoryCandidateSet): MemoryDoc;
94
- /** Move and delete are the only mutation recovery path for a same-store
95
- * collision. The exact-store winner remains the ordinary target; only the
96
- * selected store's candidates are ordered by their physical path. */
97
- export interface MutationDocSelection {
98
- doc: MemoryDoc;
99
- collisionPaths: readonly string[];
100
- }
101
- export declare function selectMutationDoc(set: MemoryCandidateSet): MutationDocSelection;
102
- /** Remove a just-removed file's now-empty parent directories up to (never
103
- * including) its store root, so removing the last entry under an `area/`
104
- * prefix does not orphan an empty directory. `pathSegments` counts the
105
- * PHYSICAL store-relative path (`doc.physicalRelativePath.split('/').length`),
106
- * never the canonical name, which carries the store's namespace on top of it —
107
- * the same count addresses a `.history/<path>.jsonl` sidecar. Stops at the
108
- * first non-empty ancestor. */
109
- export declare function pruneEmptyParents(filePath: string, pathSegments: number): void;
110
- /** Map a STORE-LOCAL name (`topic`, `area/topic`, `INDEX`) to its file path
111
- * under a memory dir, guarding against traversal/absolute escapes. Physical
112
- * mapping only: it composes no namespace and collapses no `INDEX`, so a
113
- * canonical name reaches it through `planNewDocumentPlacement`. */
114
- export declare function memoryFilePath(memoryDir: string, name: string): string;
115
- export declare function coerceGate(raw: string): Record<string, unknown>;
116
- /** Coerce one `--surface` value into a validated surfaces entry. Strict where
117
- * the runtime parser is tolerant: a flag that would be silently dropped or
118
- * trimmed at render time is an authoring mistake and fails HERE. The entry is
119
- * returned in canonical key order with a single glob kept as a bare string,
120
- * so the stored YAML stays as compact as the flag that authored it. */
121
- export declare function coerceSurface(raw: string): Record<string, unknown>;
122
- /** Provenance for a doc at the moment it is created: when, where, and which
123
- * node's conversation authored it. Read from the env the runtime injects into
124
- * every node's pi process (CRTR_NODE_ID/KIND/MODE/NODE_CWD); when invoked
125
- * outside a node (a human at the CLI) only `created` + `cwd` are recorded.
126
- * Stamped ONCE at create and preserved verbatim on every later update —
127
- * `crtr memory origin <name>` derefs the `node` pointer back to the live node
128
- * (its session conversation, context dir, current state). */
129
- export declare function historyActorFromEnvironment(): {
130
- cwd: string;
131
- node?: string;
132
- };
133
- export declare function buildOrigin(): Record<string, unknown>;
134
- /** Serialize a substrate frontmatter record + body into a complete `.md`
135
- * document. Frontmatter is emitted as a `---` fenced YAML block (the `yaml`
136
- * package — the same one the parser uses — so nested gate maps and surfaces
137
- * entry lists round-trip), in canonical field order with preserved extras last. */
138
- export declare function serializeMemoryDoc(frontmatter: Record<string, unknown>, body: string): string;
139
- /** Everything after the closing frontmatter fence, byte for byte — leading blank
140
- * lines and indentation intact. Source without a fence is all body. */
141
- export declare function literalBodySegment(source: string): string;
142
- /** Serialize a document WITHOUT touching the body. `bodySegment` is everything
143
- * after the closing frontmatter fence (leading blank line included), emitted
144
- * byte for byte. This is the revision path: `edit` saves what it was given, so
145
- * an unchanged doc round-trips identically and a supplied body reaches disk
146
- * untransformed. Creation uses `serializeMemoryDoc`, which normalizes a first
147
- * body into the canonical shape. */
148
- export declare function serializeMemoryDocLiteral(frontmatter: Record<string, unknown>, bodySegment: string): string;
149
- export interface RequestedExtensionSet {
150
- path: string;
151
- namespace: string;
152
- field: string;
153
- value: MemoryExtensionScalar;
154
- }
155
- interface RequestedExtensionPath {
156
- path: string;
157
- namespace: string;
158
- field: string;
159
- }
160
- /** Resolve declarations at the same scope and path a document will use. The
161
- * catalog intentionally includes disabled plugins: they still authorize typed
162
- * edits to values that stay inert until their plugin is enabled again. */
163
- export declare function memoryExtensionCatalogForDoc(doc: Pick<MemoryDoc, 'scope' | 'path'>): MemoryExtensionCatalog;
164
- /** A bounded declaration catalog for the two authoring leaves. The manifest is
165
- * the source for both the type and operation-specific guidance. */
166
- export declare function memoryExtensionFieldCatalogHelp(operation: 'write' | 'edit'): string | null;
167
- /** Parse every requested extension mutation before the caller constructs any
168
- * frontmatter. Set values are deliberately declaration-typed rather than YAML. */
169
- export declare function parseRequestedExtensionChanges(setRaw: readonly string[] | undefined, unsetRaw: readonly string[] | undefined, catalog: MemoryExtensionCatalog): {
170
- sets: RequestedExtensionSet[];
171
- unsets: RequestedExtensionPath[];
172
- };
173
- /** Apply only requested extension paths. Existing unknown namespaces remain
174
- * untouched; an unset prunes the empty namespace and empty root mapping. */
175
- export declare function applyExtensionChanges(frontmatter: Record<string, unknown>, sets: readonly RequestedExtensionSet[], unsets: readonly RequestedExtensionPath[]): void;
176
- /** The frontmatter-overlay flags, keyed by flag name, carrying the prose true
177
- * on BOTH leaves. `write` appends its creation clauses with `withConstraint`;
178
- * neither leaf restates the other's rules. */
179
- /** The selector flags, keyed by flag name, carrying the prose true on every
180
- * leaf that accepts them. A leaf appends its own clause with `selectorParam`;
181
- * none of them restates the shared rules. */
182
5
  export declare const SELECTOR_PARAMS: Record<string, FlagParam>;
183
6
  /** One selector flag, with leaf-specific prose appended to the shared
184
7
  * constraint and any leaf-specific schema override applied. */
185
8
  export declare function selectorParam(name: string, overrides?: Partial<FlagParam>, extraConstraint?: string): FlagParam;
186
- export declare function coerceLintIgnore(raw: unknown): string | string[] | undefined;
187
9
  export declare const FRONTMATTER_OVERLAY_PARAMS: Record<string, FlagParam>;
188
10
  /** One overlay flag, with leaf-specific prose appended to the shared
189
11
  * constraint and any leaf-specific schema override applied. */
@@ -1,12 +1 @@
1
- var J=Object.defineProperty;var a=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envNodeId as $,envProfileId as U}from"../../shared/env.js";import{existsSync as R,readdirSync as Y,realpathSync as W,rmdirSync as V,statSync as B}from"node:fs";import{dirname as g,join as y,resolve as G}from"node:path";import{stringify as S,parse as k}from"yaml";import{stateBlock as H}from"../../core/help.js";import{loadStoreMemoryDocs as X,openProjectMemoryStore as b}from"../../core/memory-resolver.js";import{physicalRelativePathFor as j}from"../../core/memory/identity.js";import{requireCanonicalName as z,requireLocalNameInStore as K}from"../../core/memory/service.js";import{memoryScopeRank as ut,requireCanonicalName as yt,requireLocalNameInStore as gt,requireMountedStore as wt}from"../../core/memory/service.js";import{pathExists as O,realpathOrSelf as x}from"../../core/fs-utils.js";import{usage as c}from"../../core/errors.js";import{memoryExtensionValidationCatalog as Q}from"../../core/memory/extensions.js";import{CRTR_DIR_NAME as Z}from"../../types.js";import{NEUTRAL_PROJECT_MEMORY as ee,scopeMemoryDir as N,projectScopeRoot as A,ensureProjectScopeRoot as te,resetScopeCache as ne}from"../../core/scope.js";import{loadProfileManifest as re,resolveProfileOperand as D,profileMemoryDir as _}from"../../core/profiles/manifest.js";import{memoryDir as oe}from"../../core/runtime/memory.js";import{SURFACE_EVENTS as I,SURFACE_RUNGS as C}from"../../core/substrate/schema.js";import{SUPPRESSIBLE_RULES as v}from"../../core/substrate/frontmatter-validation.js";import{exposureTarget as ie,loadContextExposureState as se,registerExposure as ae,saveContextExposureState as ce}from"../../core/substrate/injected-store.js";const de=["knowledge","preference"],q=["user","project","profile","node","builtin"],E=["user","project","profile","node"],Fe=E;function Je(e){const r=$();if(r===void 0||r==="")return;const t=se(r);ae(ie(t,"transcript"),e,"content"),ce(r,t)}a(Je,"registerMemoryListingExposure");function T(e){if(e.scope!==void 0&&e.scope!=="")throw c(`--dir selects the project store itself and cannot combine with --scope ${e.scope}`,{received:`--dir ${e.dir} --scope ${e.scope}`,next:"Drop --scope: --dir already pins the exact project store."});if(e.profile!==void 0&&e.profile!=="")throw c("--profile only applies to --scope profile; --dir selects a project store",{received:e.profile,next:"Drop --profile when using --dir."})}a(T,"rejectDirConflicts");function P(e){const r=G(e);if(!R(r)||!B(r).isDirectory())throw c(`--dir does not exist or is not a directory: ${e}`,{received:e,next:"Pass an existing project directory."});try{return W(r)}catch{return r}}a(P,"ownerDirFromArg");function M(e,r){if(!(e===void 0||e==="")){if(!r.includes(e))throw c(`invalid --scope: ${e} (expected ${r.join("|")})`);return e}}a(M,"parseScope");function w(e,r){return{scope:e,storeRoot:r,namespace:"",mountStatus:O(r)?"ready":"absent",projectMemory:ee}}a(w,"nativeStoreDescriptor");function Ue(e){if(e.dir!==void 0&&e.dir!=="")return T(e),{store:b(P(e.dir))};if(e.profile!==void 0&&e.profile!==""&&e.scope!=="profile")throw c(`--profile only applies to --scope profile (received scope: ${e.scope??"none"})`,{received:e.profile,next:"Drop --profile, or pass --scope profile to target a specific profile store."});const r=M(e.scope,q);if(e.profile!==void 0&&e.profile!==""){const{profileId:t}=D(e.profile);return{scope:"profile",store:w("profile",_(t))}}return{...r===void 0?{}:{scope:r},store:null}}a(Ue,"resolveReadSelector");function le(e){if(e.dir!==void 0&&e.dir!==""){T(e);const o=P(e.dir);return ne(),{scope:"project",memoryDir:y(o,Z,"memory"),store:b(o)}}const t=M(e.scope,E)??(A()!==null?"project":"user");if(e.profile!==void 0&&e.profile!==""&&t!=="profile")throw c(`--profile only applies to --scope profile (resolved scope: ${t})`,{received:e.profile,next:"Drop --profile, or pass --scope profile to target a specific profile store."});if(t==="node"){const o=$()||"";if(o==="")throw c("node scope requires a running node (CRTR_NODE_ID unset); rerun inside a node");const i=oe(o);return{scope:t,memoryDir:i,store:w(t,i)}}if(t==="profile"){const o=e.profile!==void 0&&e.profile!=="",i=o?e.profile:U()||"";if(i==="")throw c("profile scope requires a selected profile; rerun inside a profiled node or pass --profile");const{profileId:s}=o?D(i):re(i),l=_(s);return{scope:t,memoryDir:l,store:w(t,l)}}let n=N(t);if(!n&&t==="project"&&(n=y(te(),"memory")),!n)throw c(`no ${t} scope available for writing memory documents`);return t==="project"?{scope:t,memoryDir:n,store:b(g(g(n)))}:{scope:t,memoryDir:n,store:w(t,n)}}a(le,"resolveWriteSelector");function Ye(e,r,t){const{scope:n,memoryDir:o}=le({scope:e,profile:r,dir:t});return{scope:n,memoryDir:o}}a(Ye,"resolveWriteTarget");function We(e,r,t,n){const o=K(e,r),i=z(r),s=t??X(e,!0),l=n===void 0?null:x(n.path),d=s.find(u=>u.name===i&&x(u.path)!==l);if(d!==void 0)throw c(`${i} already exists in ${e.storeRoot}`,{memory:i,path:d.path,next:`Revise it with \`crtr memory edit ${i}\`, which records the change, or move it with \`crtr memory move\`.`});const p=(o===""?["directory-index"]:["directory-index","leaf-file"]).map(u=>y(e.storeRoot,j(o,u))).filter(u=>O(u)&&x(u)!==l);if(p.length>0)throw c(`${i} cannot be created: ${p.join(" and ")} already exists`,{memory:i,path:p.join(", "),next:"Both `<name>.md` and `<name>/INDEX.md` carry that identity. Read the existing file, then edit, move, or delete it."});const f=o===""||s.some(u=>u.localName.startsWith(`${o}/`))?"directory-index":"leaf-file",h=j(o,f);return{store:e,canonicalName:i,localName:o,representation:f,physicalRelativePath:h,path:y(e.storeRoot,h)}}a(We,"planNewDocumentPlacement");function Ve(e){const r=e.winner,t=e.candidates.filter(n=>n.store.storeRoot===r.store.storeRoot);if(t.length>1)throw c(`${e.name} is owned by ${t.length} files in one store: ${t.map(n=>n.path).join(" and ")}`,{memory:e.name,path:t.map(n=>n.path).join(", "),next:`Recover the collision with \`crtr memory move ${e.name} --to <new-free-name>\`; it selects the first physical path in stable lexical order. Do not remove files by hand; \`crtr memory lint\` reports every such collision.`});return r}a(Ve,"requireUnambiguousDoc");function Be(e){const t=[...e.candidates.filter(n=>n.store.storeRoot===e.winner.store.storeRoot)].sort((n,o)=>{const i=n.physicalRelativePath.localeCompare(o.physicalRelativePath);return i!==0?i:n.path.localeCompare(o.path)});return{doc:t[0]??e.winner,collisionPaths:t.length>1?t.map(n=>n.path):[]}}a(Be,"selectMutationDoc");function Ge(e,r){let t=e;for(let o=0;o<r;o+=1)t=g(t);let n=g(e);for(;n!==t&&n.startsWith(t)&&R(n)&&Y(n).length===0;)V(n),n=g(n)}a(Ge,"pruneEmptyParents");function He(e,r){const t=r.split("/").filter(n=>n.length>0);if(t.length===0)throw c("memory document name required");if(t.some(n=>n==="."||n===".."))throw c(`invalid memory document name: ${r}`);return y(e,...t)+".md"}a(He,"memoryFilePath");function me(e){const r=k(e);return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:`expected an object, got ${JSON.stringify(r)}`}a(me,"parseYamlObject");function Xe(e){const r=me(e);if(typeof r=="string")throw c(`--gate must be a YAML/JSON object (field\u2192matcher map): ${r}. Example: --gate '{kind: design}' or --gate '{orchestration.depth: {gte: 2}}'`);return r}a(Xe,"coerceGate");const pe=new Set(["on","match","match-frontmatter","gate","at"]);function ze(e){const r=k(e);if(r===null||typeof r!="object"||Array.isArray(r))throw c(`--surface must be a YAML/JSON object entry {on, at, match?, match-frontmatter?, gate?}, got ${JSON.stringify(r)}. Example: --surface '{on: read, match: "src/**", at: content}'`);const t=r;for(const d of Object.keys(t))if(!pe.has(d))throw c(`--surface: unknown key \`${d}\` (an entry carries only on, match, match-frontmatter, gate, at)`);const n=t.on;if(typeof n!="string"||!I.includes(n))throw c(`--surface: invalid \`on\`: ${JSON.stringify(n)} (expected ${I.join("|")})`);const o=t.at;if(typeof o!="string"||!C.includes(o))throw c(`--surface: invalid \`at\`: ${JSON.stringify(o)} (expected ${C.join("|")})`);let i;if(t.match!==void 0){if(n==="boot"||n==="workspace-open")throw c(`--surface: \`match\` is meaningless on \`${n}\` \u2014 the entry's presence is the match; drop it`);if(typeof t.match=="string"){const d=t.match.trim();if(d==="")throw c("--surface: `match` must be a non-empty glob or a non-empty glob list");i=d}else if(Array.isArray(t.match)){const d=t.match.map(m=>typeof m=="string"?m.trim():"");if(d.length===0||d.some(m=>m===""))throw c("--surface: `match` must be a non-empty glob or a non-empty glob list");i=d.length===1?d[0]:d}else throw c(`--surface: invalid \`match\`: ${JSON.stringify(t.match)} (expected a glob string or list)`)}const s=t["match-frontmatter"];if(s!==void 0){if(n!=="read")throw c("--surface: `match-frontmatter` is a `read`-event predicate only");if(s===null||typeof s!="object"||Array.isArray(s))throw c(`--surface: invalid \`match-frontmatter\`: ${JSON.stringify(s)} (expected a field\u2192matcher object)`)}if((n==="read"||n==="memory-read"||n==="command"||n==="pre-command")&&i===void 0&&s===void 0)throw c(`--surface: a \`${n}\` entry requires \`match\`${n==="read"?" or `match-frontmatter`":""}`);const l=t.gate;if(l!==void 0&&(l===null||typeof l!="object"||Array.isArray(l)))throw c(`--surface: invalid \`gate\`: ${JSON.stringify(l)} (expected a field\u2192matcher object)`);return{on:n,...i!==void 0?{match:i}:{},...s!==void 0?{"match-frontmatter":s}:{},...l!==void 0?{gate:l}:{},at:o}}a(ze,"coerceSurface");const L=["kind","when-and-why-to-read","short-form","unlisted","surfaces","gate","slash","rationale","lint-ignore","last-updated","origin"];function fe(){const e=process.env;return{cwd:e.CRTR_NODE_CWD??process.cwd(),...e.CRTR_NODE_ID?{node:e.CRTR_NODE_ID}:{}}}a(fe,"historyActorFromEnvironment");function Ke(){const e=fe();return{created:new Date().toISOString(),cwd:e.cwd,...e.node===void 0?{}:{node:e.node}}}a(Ke,"buildOrigin");function Qe(e,r){const t={};for(const i of L)e[i]!==void 0&&(t[i]=e[i]);for(const i of Object.keys(e))!(i in t)&&e[i]!==void 0&&(t[i]=e[i]);const n=S(t).replace(/\n+$/,""),o=r.replace(/^\n+/,"").replace(/\s+$/,"");return`---
2
- ${n}
3
- ---
4
-
5
- ${o}
6
- `}a(Qe,"serializeMemoryDoc");const he=/^---[ \t]*\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;function Ze(e){const r=e.match(he);return r?e.slice(r[0].length):e}a(Ze,"literalBodySegment");function et(e,r){const t={};for(const o of L)e[o]!==void 0&&(t[o]=e[o]);for(const o of Object.keys(e))!(o in t)&&e[o]!==void 0&&(t[o]=e[o]);return`---
7
- ${S(t).replace(/\n+$/,"")}
8
- ---
9
- ${r}`}a(et,"serializeMemoryDocLiteral");function ue(e){return Q(e)}a(ue,"memoryExtensionCatalogForDoc");function ye(e){return e.type!=="enum"?e.type:`enum (${e.values.join("|")})`}a(ye,"declarationValueDescription");function ge(e){return typeof e=="string"?JSON.stringify(e):String(e)}a(ge,"extensionHelpValue");function tt(e){const r=A()===null?"user":"project",t=N(r);if(t===null)return null;const n=ue({scope:r,path:y(t,".extension-help.md")}),o=Object.entries(n).flatMap(([l,d])=>Object.entries(d).map(([m,p])=>({namespace:l,field:m,declaration:p}))).sort((l,d)=>`${l.namespace}.${l.field}`.localeCompare(`${d.namespace}.${d.field}`));if(o.length===0)return null;const i=50,s=o.slice(0,i).map(({namespace:l,field:d,declaration:m})=>{const p=m.default===void 0?"":`; default ${ge(m.default)}`,f=e==="write"?m.write_help:m.edit_help;return`- \`extensions.${l}.${d}\` \u2014 ${ye(m)}${p}. ${f}`});return o.length>i&&s.push(`- ${o.length-i} additional declared fields omitted from help.`),H("memory-extension-fields",{count:o.length},s.join(`
10
- `))}a(tt,"memoryExtensionFieldCatalogHelp");function F(e,r){const t=/^extensions\.([^.]+)\.([^.]+)$/.exec(e);return t===null?`${r} requires the full path extensions.<plugin>.<field>: ${e}`:{path:e,namespace:t[1],field:t[2]}}a(F,"parseExtensionPath");function we(e,r,t){if(t.type==="boolean")return r==="true"?!0:r==="false"?!1:`${e} expects boolean true or false, received ${JSON.stringify(r)}`;if(t.type==="number"){if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(r))return`${e} expects finite numeric syntax, received ${JSON.stringify(r)}`;const n=Number(r);return Number.isFinite(n)?n:`${e} expects a finite number, received ${JSON.stringify(r)}`}return t.type==="enum"&&!t.values.includes(r)?`${e} expects one of ${t.values.join("|")}, received ${JSON.stringify(r)}`:r}a(we,"parseExtensionValue");function nt(e,r,t){const n=[],o=[],i=[],s=new Set,l=new Set;for(const d of e??[]){const m=d.indexOf("=");if(m<0){n.push(`--extension requires extensions.<plugin>.<field>=VALUE: ${d}`);continue}const p=F(d.slice(0,m),"--extension");if(typeof p=="string"){n.push(p);continue}if(s.has(p.path)){n.push(`duplicate --extension path: ${p.path}`);continue}s.add(p.path);const f=t[p.namespace]?.[p.field];if(f===void 0){n.push(`${p.path} is not declared by an installed plugin`);continue}const h=we(p.path,d.slice(m+1),f);if(typeof h=="string"&&f.type!=="string"&&f.type!=="enum"){n.push(h);continue}if(typeof h=="string"&&f.type==="enum"&&!f.values.includes(h)){n.push(`${p.path} expects one of ${f.values.join("|")}, received ${JSON.stringify(h)}`);continue}o.push({...p,value:h})}for(const d of r??[]){const m=F(d,"--unset-extension");if(typeof m=="string"){n.push(m);continue}if(l.has(m.path)){n.push(`duplicate --unset-extension path: ${m.path}`);continue}if(l.add(m.path),t[m.namespace]?.[m.field]===void 0){n.push(`${m.path} is not declared by an installed plugin`);continue}i.push(m)}for(const d of s)l.has(d)&&n.push(`${d} was requested in both --extension and --unset-extension`);if(n.length>0)throw c(`invalid plugin memory extension request:
11
- - ${n.join(`
12
- - `)}`,{received:[...e??[],...r??[]].join(", "),next:"Run `crtr memory write -h` or `crtr memory edit -h` for the installed field catalog and value syntax."});return{sets:o,unsets:i}}a(nt,"parseRequestedExtensionChanges");function rt(e,r,t){if(r.length===0&&t.length===0)return;const n=e.extensions;if(n!==void 0&&(n===null||typeof n!="object"||Array.isArray(n)))throw c("existing extensions frontmatter must be a mapping before extension fields can be changed",{received:JSON.stringify(n),next:"Repair the extensions mapping, or make a core-field-only edit that preserves it unchanged."});const o={...n??{}};for(const i of r){const s=o[i.namespace];if(s!==void 0&&(s===null||typeof s!="object"||Array.isArray(s)))throw c(`existing ${`extensions.${i.namespace}`} frontmatter must be a mapping before ${i.path} can change`,{received:JSON.stringify(s),next:"Repair the namespace mapping, or make a core-field-only edit that preserves it unchanged."});o[i.namespace]={...s??{},[i.field]:i.value}}for(const i of t){const s=o[i.namespace];if(s===void 0)continue;if(s===null||typeof s!="object"||Array.isArray(s))throw c(`existing ${`extensions.${i.namespace}`} frontmatter must be a mapping before ${i.path} can change`,{received:JSON.stringify(s),next:"Repair the namespace mapping, or make a core-field-only edit that preserves it unchanged."});const l={...s};delete l[i.field],Object.keys(l).length===0?delete o[i.namespace]:o[i.namespace]=l}Object.keys(o).length===0?delete e.extensions:e.extensions=o}a(rt,"applyExtensionChanges");const be={"scope-read":{kind:"flag",name:"scope",type:"enum",choices:[...q],required:!1,constraint:"Restrict resolution to one source class. A source filter only: the name stays the full canonical name, and project scope keeps its nearest-first precedence. Conflicts with --dir, which selects one exact store instead."},"scope-write":{kind:"flag",name:"scope",type:"enum",choices:[...E],required:!1,constraint:"Store to write to (package-shipped documents and installed-plugin documents are managed outside this command, so neither is writable). Default: project when cwd sits in a project, else user. `project` resolves to the NEAREST ancestor `.crouter/` walking up from cwd \u2014 in a nested workspace that can be a parent\u2019s store, not the dir you are standing in; pass --dir to pin the exact project. `profile` requires a selected profile (CRTR_PROFILE_ID) or an explicit --profile. `node` writes the this-node store (`nodes/<CRTR_NODE_ID>/context/memory/`), the nearest scope, seen only by this running node. Conflicts with --dir."},dir:{kind:"flag",name:"dir",type:"string",required:!1,constraint:"Exact project directory to operate in \u2014 selects `<dir>/.crouter/memory/` by realpath, regardless of cwd, ancestor stores, or which store a target view would pick. THE way to reach one specific project store: another project in your profile\u2019s purview, a store shadowed by an ancestor, or a non-winning duplicate such as a linked worktree that declares the same namespace as its main checkout. The name is still the FULL canonical name \u2014 the repository namespace plus that store\u2019s path under the repository root, plus the store-local name. It selects the store itself, so it conflicts with any explicit --scope and with --profile."},profile:{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target, for --scope profile. Names that profile\u2019s store exactly, whichever profile this process runs under. Default: the process CRTR_PROFILE_ID (the node\u2019s selected profile). Resolved through the same profile lookup as `crtr profile show`. Rejected (usage error) unless --scope profile is also selected \u2014 never silently ignored for another scope \u2014 and rejected with --dir."}};function ot(e,r={},t){const n=be[e];if(n===void 0)throw new Error(`unknown selector param: ${e}`);const o=t===void 0?n.constraint:`${n.constraint} ${t}`;return{...n,...r,constraint:o}}a(ot,"selectorParam");function it(e){if(e===void 0)return;const r=Array.isArray(e)?e:[e];if(r.length===0||r.some(t=>typeof t!="string"||!v.includes(t)))throw c(`invalid lint-ignore: ${JSON.stringify(e)} (suppressible rules: ${v.map(t=>`\`${t}\``).join(", ")})`);return r.length===1?r[0]:r}a(it,"coerceLintIgnore");const xe={kind:{kind:"flag",name:"kind",type:"enum",choices:[...de],required:!1,constraint:"Document kind."},"when-and-why-to-read":{kind:"flag",name:"when-and-why-to-read",type:"string",required:!1,constraint:'ONE routing sentence: "When <circumstance>, this <kind> should be read because <broader downstream payoff>." WHY is the reader\u2019s payoff \u2014 the consequence they secure for their task by reading \u2014 NEVER the doc summary, its rule, or that rule reworded as an outcome (a benefit-shaped restatement still fails). Rendered verbatim as the preview.'},"short-form":{kind:"flag",name:"short-form",type:"string",required:!1,constraint:"Frontmatter short-form \u2014 a very abbreviated version of the content, the hook shown in `crtr memory list`."},unlisted:{kind:"flag",name:"unlisted",type:"bool",required:!1,default:!1,constraint:"Suppress this doc from directory listings. Suppression only \u2014 explicit reads, [[links]], and surfaces entries still work."},surface:{kind:"flag",name:"surface",type:"string",required:!1,repeatable:!0,constraint:"One routing entry per occurrence, as a YAML/JSON object `{on, at, match?, match-frontmatter?, gate?}`; the flag set replaces the document\u2019s whole surfaces list. `on` is boot|workspace-open|read|memory-read|command|pre-command; `at` is name|preview|content. `match` holds the event\u2019s globs \u2014 required on read/memory-read/command/pre-command (a read entry may carry `match-frontmatter`, a predicate over the read file\u2019s own frontmatter, instead), meaningless on boot/workspace-open. Optional entry `gate` is a node-config predicate using the same vocabulary as the document gate; its event constraints and gate both match before it participates. A `./`-anchored glob is relative: for `read` to the store\u2019s owning repo dir, for `memory-read` to this doc\u2019s routing anchor \u2014 its own canonical name when the doc is its directory\u2019s document (`<dir>/INDEX.md`), otherwise the canonical directory it sits in. Participating entries fold to their highest `at`; there is no cross-entry deny precedence."},gate:{kind:"flag",name:"gate",type:"string",required:!1,constraint:"Frontmatter gate \u2014 YAML/JSON object predicate over node config using the same field/matcher vocabulary described in the guide."},"lint-ignore":{kind:"flag",name:"lint-ignore",type:"enum",choices:[...v],required:!1,repeatable:!0,constraint:"Suppress one authoring lint rule for this document. Repeat for a list; valid rules: length, broad-memory-read, orphan."},slash:{kind:"flag",name:"slash",type:"bool",required:!1,default:!1,constraint:"Presence flags this doc invocable as a pi slash command (`/<name>`, `/` in a nested name rendered as `:`) \u2014 the doc body becomes the command\u2019s injected prompt. Default false: most docs are consulted, not invoked."}};function st(e,r={},t){const n=xe[e];if(n===void 0)throw new Error(`unknown frontmatter overlay param: ${e}`);const o=t===void 0?n.constraint:`${n.constraint} ${t}`;return{...n,...r,constraint:o}}a(st,"overlayParam");const at="Frontmatter rationale \u2014 the observed agent failure that made this doc necessary. Maintainer-facing only: never ships in any delivered surface (boot render, on-read injection, `memory read` content), visible only via `memory read --frontmatter`. Omitting the flag preserves an existing rationale unchanged.",ct='Every doc appears in its directory\u2019s listing by default (suppress with --unlisted); everything beyond the listing is explicit `surfaces` routing \u2014 entries declaring WHEN the doc delivers and how much. Events: `boot` delivers in the boot catalog every agent sees; `workspace-open` delivers in first-message context when cwd/profile mounts the doc\u2019s project store (project stores only); `read` fires when the agent reads a matching file (globs vs the file\u2019s absolute path and basename, `./`-anchored globs vs its path relative to the store\u2019s owning repo dir, `match-frontmatter` predicates over the read file\u2019s own YAML frontmatter); `memory-read` fires when another memory doc\u2019s full body is delivered, including an explicit read (globs vs that doc\u2019s canonical name, `./` anchored to this doc\u2019s routing anchor \u2014 its own canonical name when it is its directory\u2019s document, otherwise the canonical directory it sits in); `command` fires when a matching shell command runs (globs vs each shell segment of the command line \u2014 split on `&&`/`||`/`;`/`|`/newlines outside quotes, leading `VAR=value` assignments dropped \u2014 where `*` spans whole whitespace-separated tokens and never part of one, `?` is one character inside a token, and quoted argument text is opaque, so `*git commit*` fires for `cd x && git commit -m "\u2026"` but not for `git commit-tree` or an `echo` that merely mentions it); `pre-command` fires BEFORE a matching bash command runs (same matching): when the memory has not been read yet, the command does not execute \u2014 the memory comes back as the tool result instead, and the agent re-issues the command, which then runs. Use it to guarantee a memory is seen before a sensitive action is taken. Requires `match`. An entry may also carry `gate`, a node-config predicate using the same vocabulary as the document-level `gate`: event constraints and entry gate both must match, then all participating entries fold to the highest `at` (`content` > `preview` > `name`), with no cross-entry deny precedence. The document-level `gate` remains the hard eligibility check: when it fails, no automatic surface can deliver the document. `at` sets how much delivers: `name` the bare tag, `preview` the routing line, `content` the whole body. Explicit `memory read` and listings remain deliberate access and ignore gates/rungs; only companion docs routed by their `memory-read` entries use entry gates. Each entry is paid by every future agent it fires on, so default down: no surfaces at all is correct for reference depth reached through listings and [[links]], and when a doc fits in a single sentence, deliver `content` directly \u2014 a `preview` routing line would run longer than the doc itself. Sentence-length `content` docs are correct; never pad a memory to be more verbose than the rule or fact it carries.',dt='The routing line (--when-and-why-to-read) is the only text an agent reads before deciding to load the doc. The test for its when-clause: it names an observable circumstance in the reader\u2019s current work, not the doc\u2019s topic reworded as an activity. If the WHEN can be inferred from the title alone, it is not a real trigger. Bad on a todo list: "When planning or prioritizing work across this profile." Good: "When the user mentions something from their todos, or asks what is still outstanding across this profile." The test for its because-clause: if it can be derived by paraphrasing the doc\u2019s advice, it is a restatement, not a payoff \u2014 a real payoff names a consequence in the reader\u2019s world that the document itself never asserts. Bad: "because only genuine first principles belong in taste memory." Bad: "because keeping the test loop fast and free of speculative tests protects the development pace" \u2014 the doc\u2019s rule as an outcome, derivable straight from its advice. Good: "because identifying throughlines in user taste lets future decisions be made faster and with less re-litigation." Someone mid-task who has not read the doc must be able to decide from this line alone whether the read is worth it. If you cannot name the concrete situation that triggers it, you do not yet understand the memory \u2014 ask the user one sharp question instead of improvising.',lt="Document gates, surface-entry gates, and match-frontmatter share the same predicate language: a field map is AND-ed across fields; dotted fields resolve nested values; field matchers may be scalar, array, or object. Scalar matchers do exact equality, with arrays matching any element. Array matchers do membership or intersection. Object matchers accept `eq`, `ne`, `in`, `nin`, `exists`, `contains`, `containsAll`, `containsAny`, `matches`, `imatches`, `gt`, `gte`, `lt`, and `lte`. Combinators are `all`, `any`, and `not`; sibling field matchers next to them are AND-ed in. An empty condition is inert. An unknown op never matches.",mt="Link related docs with `[[canonical/name]]`. A doc link in any body is a first-class cross-reference to another memory document by its exact canonical name \u2014 the same identifier `crtr memory read` takes, namespace included for a project document. A bare directory name is a valid link too: following it returns that directory\u2019s own document when it has one, plus the directory listing. Links are pointers, never transclusion: the linked body is loaded only when a reader follows it, so a link costs nothing until needed. `crtr memory lint` fails on a link that resolves to no document or directory, and `crtr memory read` lists a doc\u2019s resolvable links alongside its body. There is no alias, label, or old-name form \u2014 a renamed target needs its links rewritten.",pt="A document has exactly one address: its canonical name, the store\u2019s namespace composed with the document\u2019s store-local name. A repository declares its namespace once, as `namespace:` on the root `INDEX.md` of `<repository root>/.crouter/memory/`; a store nested inside that repository composes under the repository namespace plus its own directory path relative to the repository root, and declares nothing itself. An installed plugin\u2019s store mounts under the plugin\u2019s own name; user, profile, node, and builtin stores have no namespace, so their local names are already canonical. A local doc `unit-tests` in a store that declares `namespace: acme/core` therefore answers only at `acme/core/unit-tests`, and the store\u2019s root document answers at `acme/core`; a store at `packages/api/.crouter/memory/` in a repository declaring `namespace: acme` answers under `acme/packages/api`. A non-root explicit `name:` in frontmatter is store-LOCAL \u2014 it never carries the namespace, and composition is unconditional, so a name that merely looks prefixed is prefixed again. The namespace itself is immutable through the memory commands: `crtr memory write <namespace> --dir <repository root>` declares it once in an empty repository-root store, `crtr sys migrate --dir <repository root>` converts a legacy one, and nothing else rewrites it. A trailing `INDEX` is never part of an address in any store: `area/INDEX.md` is the document attached to directory `area`, so it answers at `area` and reading `area` returns that body together with the directory\u2019s immediate listing. Resolution is exact \u2014 a file path, a bare leaf, a `<scope>/<name>` spelling, and a trailing `/INDEX` all fail \u2014 so run `crtr memory find <leaf>` when you do not know the canonical name.";export{at as DOC_RATIONALE_CONSTRAINT,xe as FRONTMATTER_OVERLAY_PARAMS,pt as GUIDE_CANONICAL_NAMES,mt as GUIDE_DOC_LINKS,lt as GUIDE_PREDICATE_VOCABULARY,dt as GUIDE_ROUTING_LINE,ct as GUIDE_SURFACES,de as MEMORY_KINDS,q as MEMORY_READ_SCOPES,Fe as MEMORY_SCOPES,E as MEMORY_WRITE_SCOPES,be as SELECTOR_PARAMS,rt as applyExtensionChanges,Ke as buildOrigin,Xe as coerceGate,it as coerceLintIgnore,ze as coerceSurface,fe as historyActorFromEnvironment,Ze as literalBodySegment,ue as memoryExtensionCatalogForDoc,tt as memoryExtensionFieldCatalogHelp,He as memoryFilePath,st as overlayParam,nt as parseRequestedExtensionChanges,We as planNewDocumentPlacement,Ge as pruneEmptyParents,Je as registerMemoryListingExposure,yt as requireCanonicalName,gt as requireLocalNameInStore,wt as requireMountedStore,Ve as requireUnambiguousDoc,Ue as resolveReadSelector,le as resolveWriteSelector,Ye as resolveWriteTarget,ut as scopeRank,Be as selectMutationDoc,ot as selectorParam,Qe as serializeMemoryDoc,et as serializeMemoryDocLiteral};
1
+ var s=Object.defineProperty;var o=(t,r)=>s(t,"name",{value:r,configurable:!0});import{PRIVACY_LEVELS as i}from"../../core/substrate/schema.js";import{SUPPRESSIBLE_RULES as c}from"../../core/substrate/frontmatter-validation.js";const d=["knowledge","preference"],l=["user","project","profile","node","builtin"],h=["user","project","profile","node"],m={"scope-read":{kind:"flag",name:"scope",type:"enum",choices:[...l],required:!1,constraint:"Restrict resolution to one source class. A source filter only: the name stays the full canonical name, and project scope keeps its nearest-first precedence. Conflicts with --dir, which selects one exact store instead."},"scope-write":{kind:"flag",name:"scope",type:"enum",choices:[...h],required:!1,constraint:"Store to write to (package-shipped documents and installed-plugin documents are managed outside this command, so neither is writable). Default: project when cwd sits in a project, else user. `project` resolves to the NEAREST ancestor `.crouter/` walking up from cwd \u2014 in a nested workspace that can be a parent\u2019s store, not the dir you are standing in; pass --dir to pin the exact project. `profile` requires a selected profile (CRTR_PROFILE_ID) or an explicit --profile. `node` writes the this-node store (`nodes/<CRTR_NODE_ID>/context/memory/`), the nearest scope, seen only by this running node. Conflicts with --dir."},dir:{kind:"flag",name:"dir",type:"string",required:!1,constraint:"Exact project directory to operate in \u2014 selects `<dir>/.crouter/memory/` by realpath, regardless of cwd, ancestor stores, or which store a target view would pick. THE way to reach one specific project store: another project in your profile\u2019s purview, a store shadowed by an ancestor, or a non-winning duplicate such as a linked worktree that declares the same namespace as its main checkout. The name is still the FULL canonical name \u2014 the repository namespace plus that store\u2019s path under the repository root, plus the store-local name. It selects the store itself, so it conflicts with any explicit --scope and with --profile."},profile:{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target, for --scope profile. Names that profile\u2019s store exactly, whichever profile this process runs under. Default: the process CRTR_PROFILE_ID (the node\u2019s selected profile). Resolved through the same profile lookup as `crtr profile show`. Rejected (usage error) unless --scope profile is also selected \u2014 never silently ignored for another scope \u2014 and rejected with --dir."}};function y(t,r={},n){const e=m[t];if(e===void 0)throw new Error(`unknown selector param: ${t}`);const a=n===void 0?e.constraint:`${e.constraint} ${n}`;return{...e,...r,constraint:a}}o(y,"selectorParam");const u={kind:{kind:"flag",name:"kind",type:"enum",choices:[...d],required:!1,constraint:"Document kind."},privacy:{kind:"flag",name:"privacy",type:"enum",choices:[...i],required:!1,constraint:"App access level. Write defaults to public and persists it; edit preserves the current level unless set. A legacy document without the field is read as private."},"when-and-why-to-read":{kind:"flag",name:"when-and-why-to-read",type:"string",required:!1,constraint:'ONE routing sentence: "When <circumstance>, this <kind> should be read because <broader downstream payoff>." WHY is the reader\u2019s payoff \u2014 the consequence they secure for their task by reading \u2014 NEVER the doc summary, its rule, or that rule reworded as an outcome (a benefit-shaped restatement still fails). Rendered verbatim as the preview.'},"short-form":{kind:"flag",name:"short-form",type:"string",required:!1,constraint:"Frontmatter short-form \u2014 a very abbreviated version of the content, the hook shown in `crtr memory list`."},unlisted:{kind:"flag",name:"unlisted",type:"bool",required:!1,default:!1,constraint:"Suppress this doc from directory listings. Suppression only \u2014 explicit reads, [[links]], and surfaces entries still work."},surface:{kind:"flag",name:"surface",type:"string",required:!1,repeatable:!0,constraint:"One routing entry per occurrence, as a YAML/JSON object `{on, at, match?, match-frontmatter?, gate?}`; the flag set replaces the document\u2019s whole surfaces list. `on` is boot|workspace-open|read|memory-read|command|pre-command; `at` is name|preview|content. `match` holds the event\u2019s globs \u2014 required on read/memory-read/command/pre-command (a read entry may carry `match-frontmatter`, a predicate over the read file\u2019s own frontmatter, instead), meaningless on boot/workspace-open. Optional entry `gate` is a node-config predicate using the same vocabulary as the document gate; its event constraints and gate both match before it participates. A `./`-anchored glob is relative: for `read` to the store\u2019s owning repo dir, for `memory-read` to this doc\u2019s routing anchor \u2014 its own canonical name when the doc is its directory\u2019s document (`<dir>/INDEX.md`), otherwise the canonical directory it sits in. Participating entries fold to their highest `at`; there is no cross-entry deny precedence."},gate:{kind:"flag",name:"gate",type:"string",required:!1,constraint:"Frontmatter gate \u2014 YAML/JSON object predicate over node config using the same field/matcher vocabulary described in the guide."},"lint-ignore":{kind:"flag",name:"lint-ignore",type:"enum",choices:[...c],required:!1,repeatable:!0,constraint:"Suppress one authoring lint rule for this document. Repeat for a list; valid rules: length, broad-memory-read, orphan."},slash:{kind:"flag",name:"slash",type:"bool",required:!1,default:!1,constraint:"Presence flags this doc invocable as a pi slash command (`/<name>`, `/` in a nested name rendered as `:`) \u2014 the doc body becomes the command\u2019s injected prompt. Default false: most docs are consulted, not invoked."}};function w(t,r={},n){const e=u[t];if(e===void 0)throw new Error(`unknown frontmatter overlay param: ${t}`);const a=n===void 0?e.constraint:`${e.constraint} ${n}`;return{...e,...r,constraint:a}}o(w,"overlayParam");const b="Frontmatter rationale \u2014 the observed agent failure that made this doc necessary. Maintainer-facing only: never ships in any delivered surface (boot render, on-read injection, `memory read` content), visible only via `memory read --frontmatter`. Omitting the flag preserves an existing rationale unchanged.",v='Every doc appears in its directory\u2019s listing by default (suppress with --unlisted); everything beyond the listing is explicit `surfaces` routing \u2014 entries declaring WHEN the doc delivers and how much. Events: `boot` delivers in the boot catalog every agent sees; `workspace-open` delivers in first-message context when cwd/profile mounts the doc\u2019s project store (project stores only); `read` fires when the agent reads a matching file (globs vs the file\u2019s absolute path and basename, `./`-anchored globs vs its path relative to the store\u2019s owning repo dir, `match-frontmatter` predicates over the read file\u2019s own YAML frontmatter); `memory-read` fires when another memory doc\u2019s full body is delivered, including an explicit read (globs vs that doc\u2019s canonical name, `./` anchored to this doc\u2019s routing anchor \u2014 its own canonical name when it is its directory\u2019s document, otherwise the canonical directory it sits in); `command` fires when a matching shell command runs (globs vs each shell segment of the command line \u2014 split on `&&`/`||`/`;`/`|`/newlines outside quotes, leading `VAR=value` assignments dropped \u2014 where `*` spans whole whitespace-separated tokens and never part of one, `?` is one character inside a token, and quoted argument text is opaque, so `*git commit*` fires for `cd x && git commit -m "\u2026"` but not for `git commit-tree` or an `echo` that merely mentions it); `pre-command` fires BEFORE a matching bash command runs (same matching): when the memory has not been read yet, the command does not execute \u2014 the memory comes back as the tool result instead, and the agent re-issues the command, which then runs. Use it to guarantee a memory is seen before a sensitive action is taken. Requires `match`. An entry may also carry `gate`, a node-config predicate using the same vocabulary as the document-level `gate`: event constraints and entry gate both must match, then all participating entries fold to the highest `at` (`content` > `preview` > `name`), with no cross-entry deny precedence. The document-level `gate` remains the hard eligibility check: when it fails, no automatic surface can deliver the document. `at` sets how much delivers: `name` the bare tag, `preview` the routing line, `content` the whole body. Explicit `memory read` and listings remain deliberate access and ignore gates/rungs; only companion docs routed by their `memory-read` entries use entry gates. Each entry is paid by every future agent it fires on, so default down: no surfaces at all is correct for reference depth reached through listings and [[links]], and when a doc fits in a single sentence, deliver `content` directly \u2014 a `preview` routing line would run longer than the doc itself. Sentence-length `content` docs are correct; never pad a memory to be more verbose than the rule or fact it carries.',k='The routing line (--when-and-why-to-read) is the only text an agent reads before deciding to load the doc. The test for its when-clause: it names an observable circumstance in the reader\u2019s current work, not the doc\u2019s topic reworded as an activity. If the WHEN can be inferred from the title alone, it is not a real trigger. Bad on a todo list: "When planning or prioritizing work across this profile." Good: "When the user mentions something from their todos, or asks what is still outstanding across this profile." The test for its because-clause: if it can be derived by paraphrasing the doc\u2019s advice, it is a restatement, not a payoff \u2014 a real payoff names a consequence in the reader\u2019s world that the document itself never asserts. Bad: "because only genuine first principles belong in taste memory." Bad: "because keeping the test loop fast and free of speculative tests protects the development pace" \u2014 the doc\u2019s rule as an outcome, derivable straight from its advice. Good: "because identifying throughlines in user taste lets future decisions be made faster and with less re-litigation." Someone mid-task who has not read the doc must be able to decide from this line alone whether the read is worth it. If you cannot name the concrete situation that triggers it, you do not yet understand the memory \u2014 ask the user one sharp question instead of improvising.',E="Document gates, surface-entry gates, and match-frontmatter share the same predicate language: a field map is AND-ed across fields; dotted fields resolve nested values; field matchers may be scalar, array, or object. Scalar matchers do exact equality, with arrays matching any element. Array matchers do membership or intersection. Object matchers accept `eq`, `ne`, `in`, `nin`, `exists`, `contains`, `containsAll`, `containsAny`, `matches`, `imatches`, `gt`, `gte`, `lt`, and `lte`. Combinators are `all`, `any`, and `not`; sibling field matchers next to them are AND-ed in. An empty condition is inert. An unknown op never matches.",A="Link related docs with `[[canonical/name]]`. A doc link in any body is a first-class cross-reference to another memory document by its exact canonical name \u2014 the same identifier `crtr memory read` takes, namespace included for a project document. A bare directory name is a valid link too: following it returns that directory\u2019s own document when it has one, plus the directory listing. Links are pointers, never transclusion: the linked body is loaded only when a reader follows it, so a link costs nothing until needed. `crtr memory lint` fails on a link that resolves to no document or directory, and `crtr memory read` lists a doc\u2019s resolvable links alongside its body. There is no alias, label, or old-name form \u2014 a renamed target needs its links rewritten.",R="A document has exactly one address: its canonical name, the store\u2019s namespace composed with the document\u2019s store-local name. A repository declares its namespace once, as `namespace:` on the root `INDEX.md` of `<repository root>/.crouter/memory/`; a store nested inside that repository composes under the repository namespace plus its own directory path relative to the repository root, and declares nothing itself. An installed plugin\u2019s store mounts under the plugin\u2019s own name; user, profile, node, and builtin stores have no namespace, so their local names are already canonical. A local doc `unit-tests` in a store that declares `namespace: acme/core` therefore answers only at `acme/core/unit-tests`, and the store\u2019s root document answers at `acme/core`; a store at `packages/api/.crouter/memory/` in a repository declaring `namespace: acme` answers under `acme/packages/api`. A non-root explicit `name:` in frontmatter is store-LOCAL \u2014 it never carries the namespace, and composition is unconditional, so a name that merely looks prefixed is prefixed again. The namespace itself is immutable through the memory commands: `crtr memory write <namespace> --dir <repository root>` declares it once in an empty repository-root store, `crtr sys migrate --dir <repository root>` converts a legacy one, and nothing else rewrites it. A trailing `INDEX` is never part of an address in any store: `area/INDEX.md` is the document attached to directory `area`, so it answers at `area` and reading `area` returns that body together with the directory\u2019s immediate listing. Resolution is exact \u2014 a file path, a bare leaf, a `<scope>/<name>` spelling, and a trailing `/INDEX` all fail \u2014 so run `crtr memory find <leaf>` when you do not know the canonical name.";export{b as DOC_RATIONALE_CONSTRAINT,u as FRONTMATTER_OVERLAY_PARAMS,R as GUIDE_CANONICAL_NAMES,A as GUIDE_DOC_LINKS,E as GUIDE_PREDICATE_VOCABULARY,k as GUIDE_ROUTING_LINE,v as GUIDE_SURFACES,d as MEMORY_KINDS,l as MEMORY_READ_SCOPES,h as MEMORY_WRITE_SCOPES,m as SELECTOR_PARAMS,w as overlayParam,y as selectorParam};
@@ -1,13 +1,13 @@
1
- var a=Object.defineProperty;var o=(t,r)=>a(t,"name",{value:r,configurable:!0});import{defineLeaf as s}from"../../core/command.js";import{createDoc as d}from"../../core/memory/mutations.js";import{ambientMemoryTarget as c}from"../../core/memory-resolver.js";import{DOC_RATIONALE_CONSTRAINT as h,GUIDE_CANONICAL_NAMES as l,GUIDE_DOC_LINKS as m,GUIDE_PREDICATE_VOCABULARY as u,GUIDE_ROUTING_LINE as p,GUIDE_SURFACES as f,buildOrigin as y,historyActorFromEnvironment as g,memoryExtensionFieldCatalogHelp as w,overlayParam as e,resolveWriteSelector as b,selectorParam as n}from"./shared.js";const T=s({name:"write",description:"create a memory document",whenToUse:"you are recording a new knowledge document or preference that does not exist yet. Creation only \u2014 a name already taken at the resolved scope is an error, because revising a stored document goes through `crtr memory edit`, which requires a rationale and records the revision.",help:{name:"memory write",summary:"create a memory document at the resolved store from frontmatter flags + a stdin body",guide:`Every frontmatter flag decides who sees this doc, when, and at what context cost. Each rung up is paid by every future agent at every boot or read, so default each rung down.
1
+ var a=Object.defineProperty;var r=(t,o)=>a(t,"name",{value:o,configurable:!0});import{defineLeaf as s}from"../../core/command.js";import{memoryExtensionHelp as d,memoryRequest as c,memorySelection as h}from"./client.js";import{DOC_RATIONALE_CONSTRAINT as l,GUIDE_CANONICAL_NAMES as u,GUIDE_DOC_LINKS as m,GUIDE_PREDICATE_VOCABULARY as p,GUIDE_ROUTING_LINE as f,GUIDE_SURFACES as y,overlayParam as e,selectorParam as n}from"./shared.js";const g=s({name:"write",description:"create a memory document",whenToUse:"you are recording a new knowledge document or preference that does not exist yet. Creation only \u2014 a name already taken at the resolved scope is an error, because revising a stored document goes through `crtr memory edit`, which requires a rationale and records the revision.",help:{name:"memory write",summary:"create a memory document at the resolved store from frontmatter flags + a stdin body",guide:`Every frontmatter flag decides who sees this doc, when, and at what context cost. Each rung up is paid by every future agent at every boot or read, so default each rung down.
2
2
 
3
3
  Pick the kind. knowledge is consulted for facts or procedures; preference directs behavior. The kind choice is about how the doc is used, not about how long it is.
4
4
 
5
5
  Store reusable current truth, not session notes. Useful memories are non-obvious procedures, gotchas, durable preferences, and cross-repo conventions. Do not store chat summaries, implementation history, or facts already recorded in the repo.
6
6
 
7
- `+f+'\n\nChoose the scope. `project` is for facts any agent in one repo needs. `user` is for person-wide facts and preferences that should follow the user everywhere. `profile` is for the profile\u2019s bundle of dirs: cross-repo conventions, how the pieces relate, or the user\u2019s stance toward that body of work. `node` is scratch memory only this running node sees; it rides into this node\u2019s knowledge block and dies with the node. When unsure, choose the narrowest scope that will still reach the next agent who needs it.\n\nA workspace front door is an ordinary doc carrying the entry pair {on: workspace-open, at: content} plus {on: read, match: "./**", at: content}: it enters first-message context when cwd/profile mounts its project store and fires on any file read beneath the store\u2019s owning dir. Target the exact project with --dir. Keep only the project constraints, key commands, architecture orientation, and conventions that differ from defaults. `crtr memory lint` requires this front door on the repository-root guide for a repository managed by the selected profile; nested stores may carry ordinary guides without a missing-door finding.\n\nChoose the hook \u2014 boot vs read. A boot entry rides the boot catalog every agent sees; a read entry fires only when a matching file is actually read. Put code-specific knowledge in the owning project store, give it the narrowest real file glob, and keep it off boot when the file read is the useful trigger. Knowledge about a person or process usually has no file boundary, so skip read entries and route it through boot instead.\n\nWrite the routing line (--when-and-why-to-read) first, before storing anything. '+p+`
7
+ `+y+'\n\nChoose the scope. `project` is for facts any agent in one repo needs. `user` is for person-wide facts and preferences that should follow the user everywhere. `profile` is for the profile\u2019s bundle of dirs: cross-repo conventions, how the pieces relate, or the user\u2019s stance toward that body of work. `node` is scratch memory only this running node sees; it rides into this node\u2019s knowledge block and dies with the node. When unsure, choose the narrowest scope that will still reach the next agent who needs it.\n\nA workspace front door is an ordinary doc carrying the entry pair {on: workspace-open, at: content} plus {on: read, match: "./**", at: content}: it enters first-message context when cwd/profile mounts its project store and fires on any file read beneath the store\u2019s owning dir. Target the exact project with --dir. Keep only the project constraints, key commands, architecture orientation, and conventions that differ from defaults. `crtr memory lint` requires this front door on the repository-root guide for a repository managed by the selected profile; nested stores may carry ordinary guides without a missing-door finding.\n\nChoose the hook \u2014 boot vs read. A boot entry rides the boot catalog every agent sees; a read entry fires only when a matching file is actually read. Put code-specific knowledge in the owning project store, give it the narrowest real file glob, and keep it off boot when the file read is the useful trigger. Knowledge about a person or process usually has no file boundary, so skip read entries and route it through boot instead.\n\nWrite the routing line (--when-and-why-to-read) first, before storing anything. '+f+`
8
8
 
9
- `+u+`
9
+ `+p+`
10
10
 
11
- `+l+`
11
+ `+u+`
12
12
 
13
- `+m+"\n\nWhen a doc grows long or information-rich, nest it into a graph instead of letting it become a scroll. The main doc at the topic\u2019s path keeps the high-level, most load-bearing information, most important first; depth splits into reference docs under the topic\u2019s directory (`area/topic/...`), each pointed at with a `[[link]]`. Split by subject: a leaf earns its link by covering a different subject a task might need on its own; a leaf of offloaded \u201Cfurther evidence\u201D, examples, or references is never followed, so supporting material either sits in the main doc next to the point it supports or gets cut. The main doc is the entry point a reader can act from alone; a reference leaf is loaded only when the task needs that depth. Give reference leaves no surfaces at all \u2014 the directory listing and the link from the main doc are how they are found, so any routing entry just double-charges every boot or read for depth the graph already routes. State each fact once. Keep facts that affect action or judgment, including constraints, exceptions, numbers, and exact names. Remove known context, inferable conclusions, filler transitions, and examples that resolve no ambiguity. `crtr memory lint` caps body length by delivery rung and its findings carry the split guidance.\n\nA directory needs no index doc: reading a directory name returns its listing \u2014 each member\u2019s routing line \u2014 so never author a doc that merely lists, fronts, or paraphrases its siblings. Write a directory-level doc only for synthesis: an operating guide or the cluster\u2019s mechanics, ordering, conditions, and relationships, content no single member can carry. Guided entrance into a topic is an ordinary member doc, found through the listing like any other.\n\nFind before write. Prefer slightly expanding an existing document with `crtr memory edit`, nesting genuinely separate depth under its topic, and updating the existing `when-and-why-to-read` (plus its INDEX router when present) over creating another similar memory. A new document earns its own identity only when it has a distinct read trigger and a coherent body whose merge into the existing document would make it harder to route or use. Group related docs with path names (area/topic). Provenance is stamped here and preserved by every later revision.\n\nThis leaf validates the document it just wrote and reports any finding; a silent result means it is clean, so there is nothing to run afterwards. The check is scoped to this one document \u2014 `crtr memory lint` remains the corpus-wide sweep, and only it catches store-level faults such as a canonical collision or a missing workspace front door.\n\n--rationale is the gap this doc exists to close \u2014 the observed agent failure that prompted it, captured from user signal (a correction, a mistake you watched happen) rather than inferred from the doc\u2019s own content. If the rationale is guessable from reading the doc, it is not the real one \u2014 a guessable gap is one agents do not actually fall into. Omit the flag when you have no observed gap to record.\n\nRevise an existing doc with `crtr memory edit`.",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical identity. Project writes require `<namespace>/<local name>`; writing the namespace itself targets the repository-root document. A trailing `/INDEX` is invalid because directory documents answer at the directory name. The identity must be free in the selected exact store."},e("kind",{required:!0}),e("when-and-why-to-read",{required:!0}),e("short-form"),e("unlisted"),e("surface"),e("gate"),e("lint-ignore"),e("slash"),{kind:"flag",name:"rationale",type:"string",required:!1,constraint:h},{kind:"flag",name:"extension",type:"string",required:!1,repeatable:!0,constraint:"Set one declared plugin field as `extensions.<plugin>.<field>=VALUE`. The path is required in full; booleans accept only true or false, numbers require finite numeric syntax, and strings/enums preserve the literal text after the first =. Every requested field validates before the document is written."},n("scope-write"),n("dir"),n("profile"),{kind:"stdin",name:"body",required:!0,constraint:"Document body (markdown, no frontmatter). Piped on stdin only \u2014 this leaf already claims the one positional for NAME, so a second bare argv token is rejected, not silently accepted as the body."}],output:[{name:"name",type:"string",required:!0,constraint:"The full canonical document name written \u2014 the resolved identity, which composes a namespace onto the name you passed when the store declares one."},{name:"scope",type:"string",required:!0,constraint:"Scope the document was written to: user, project, profile, or node. The selector rules decide this, so it is the one placement fact the invocation does not already state."},{name:"path",type:"string",required:!0,constraint:"Absolute path to the written document."},{name:"findings",type:"object[]",required:!1,constraint:"Authoring problems in the document just written, each {severity, rule, message}. ABSENT when the document is clean, which is the normal case \u2014 a silent result means it validated. Covers every rule that reads one document: yaml, schema, extension, length, short-preview, local-name, namespace-placement, root-name, nested-store-boot, broad-memory-read, and a workspace front door on a non-root doc. Reference rules (dangling-link, memory-read-route) run only when the document actually carries a `[[link]]` or a memory-read route. The document is written either way: a finding reports what to revise with `crtr memory edit`, it does not mean the write failed."}],outputKind:"object",dynamicState:o(()=>w("write"),"dynamicState"),effects:["Creates the selected physical memory document with the given frontmatter fields + stdin body, and opens its mirrored `.history` sidecar with a `create` record. An empty repository-root store is initialized at its root namespace only when the ordinary workspace front door surfaces are supplied."]},run:o(async t=>{const r=t.dir,i=b({scope:t.scope,profile:t.profile,dir:r});return d({target:c(),...i,isExplicitProjectStore:r!==void 0,origin:y(),history:g(),fields:t})},"run")});export{T as writeLeaf};
13
+ `+m+"\n\nWhen a doc grows long or information-rich, nest it into a graph instead of letting it become a scroll. The main doc at the topic\u2019s path keeps the high-level, most load-bearing information, most important first; depth splits into reference docs under the topic\u2019s directory (`area/topic/...`), each pointed at with a `[[link]]`. Split by subject: a leaf earns its link by covering a different subject a task might need on its own; a leaf of offloaded \u201Cfurther evidence\u201D, examples, or references is never followed, so supporting material either sits in the main doc next to the point it supports or gets cut. The main doc is the entry point a reader can act from alone; a reference leaf is loaded only when the task needs that depth. Give reference leaves no surfaces at all \u2014 the directory listing and the link from the main doc are how they are found, so any routing entry just double-charges every boot or read for depth the graph already routes. State each fact once. Keep facts that affect action or judgment, including constraints, exceptions, numbers, and exact names. Remove known context, inferable conclusions, filler transitions, and examples that resolve no ambiguity. `crtr memory lint` caps body length by delivery rung and its findings carry the split guidance.\n\nA directory needs no index doc: reading a directory name returns its listing \u2014 each member\u2019s routing line \u2014 so never author a doc that merely lists, fronts, or paraphrases its siblings. Write a directory-level doc only for synthesis: an operating guide or the cluster\u2019s mechanics, ordering, conditions, and relationships, content no single member can carry. Guided entrance into a topic is an ordinary member doc, found through the listing like any other.\n\nFind before write. Prefer slightly expanding an existing document with `crtr memory edit`, nesting genuinely separate depth under its topic, and updating the existing `when-and-why-to-read` (plus its INDEX router when present) over creating another similar memory. A new document earns its own identity only when it has a distinct read trigger and a coherent body whose merge into the existing document would make it harder to route or use. Group related docs with path names (area/topic). Provenance is stamped here and preserved by every later revision.\n\nThis leaf validates the document it just wrote and reports any finding; a silent result means it is clean, so there is nothing to run afterwards. The check is scoped to this one document \u2014 `crtr memory lint` remains the corpus-wide sweep, and only it catches store-level faults such as a canonical collision or a missing workspace front door.\n\n--rationale is the gap this doc exists to close \u2014 the observed agent failure that prompted it, captured from user signal (a correction, a mistake you watched happen) rather than inferred from the doc\u2019s own content. If the rationale is guessable from reading the doc, it is not the real one \u2014 a guessable gap is one agents do not actually fall into. Omit the flag when you have no observed gap to record.\n\nRevise an existing doc with `crtr memory edit`.",params:[{kind:"positional",name:"name",required:!0,constraint:"Full canonical identity. Project writes require `<namespace>/<local name>`; writing the namespace itself targets the repository-root document. A trailing `/INDEX` is invalid because directory documents answer at the directory name. The identity must be free in the selected exact store."},e("kind",{required:!0}),e("privacy",{default:"public"}),e("when-and-why-to-read",{required:!0}),e("short-form"),e("unlisted"),e("surface"),e("gate"),e("lint-ignore"),e("slash"),{kind:"flag",name:"rationale",type:"string",required:!1,constraint:l},{kind:"flag",name:"extension",type:"string",required:!1,repeatable:!0,constraint:"Set one declared plugin field as `extensions.<plugin>.<field>=VALUE`. The path is required in full; booleans accept only true or false, numbers require finite numeric syntax, and strings/enums preserve the literal text after the first =. Every requested field validates before the document is written."},n("scope-write"),n("dir"),n("profile"),{kind:"stdin",name:"body",required:!0,constraint:"Document body (markdown, no frontmatter). Piped on stdin only \u2014 this leaf already claims the one positional for NAME, so a second bare argv token is rejected, not silently accepted as the body."}],output:[{name:"name",type:"string",required:!0,constraint:"The full canonical document name written \u2014 the resolved identity, which composes a namespace onto the name you passed when the store declares one."},{name:"scope",type:"string",required:!0,constraint:"Scope the document was written to: user, project, profile, or node. The selector rules decide this, so it is the one placement fact the invocation does not already state."},{name:"path",type:"string",required:!0,constraint:"Absolute path to the written document."},{name:"findings",type:"object[]",required:!1,constraint:"Authoring problems in the document just written, each {severity, rule, message}. ABSENT when the document is clean, which is the normal case \u2014 a silent result means it validated. Covers every rule that reads one document: yaml, schema, extension, length, short-preview, local-name, namespace-placement, root-name, nested-store-boot, broad-memory-read, and a workspace front door on a non-root doc. Reference rules (dangling-link, memory-read-route) run only when the document actually carries a `[[link]]` or a memory-read route. The document is written either way: a finding reports what to revise with `crtr memory edit`, it does not mean the write failed."}],outputKind:"object",effects:["Creates the selected physical memory document with the given frontmatter fields + stdin body, and opens its mirrored `.history` sidecar with a `create` record. An empty repository-root store is initialized at its root namespace only when the ordinary workspace front door surfaces are supplied."]},effectiveHelp:r(async()=>{const t=await d("write");return{...g.help,dynamicState:r(()=>t,"dynamicState")}},"effectiveHelp"),run:r(async t=>{const{scope:o,dir:w,profile:b,...i}=t;return c("POST","/v1/memory/docs",{...h(t),mode:"cli",fields:i})},"run")});export{g as writeLeaf};
@@ -1,5 +1,5 @@
1
- var k=Object.defineProperty;var i=(n,t)=>k(n,"name",{value:t,configurable:!0});import{envNodeId as j}from"../../shared/env.js";import{defineBranch as y,defineLeaf as h}from"../../core/command.js";import{InputError as d}from"../../core/io.js";import{contextDir as c}from"../../core/canvas/paths.js";import{existsSync as m}from"node:fs";import{activeBackgroundBashJobs as x,backgroundRunningBashJobs as $,bashJobCommandLine as v,bashJobPaths as f,clearJobDeadline as I,formatBashElapsed as w,isSafeBashJobId as _,jobStartedAtMs as D,readJobPgid as T,stopBackgroundBashJob as M,tailJobLog as q,writeJobDeadlineMs as N}from"../../core/bash-jobs.js";import{parseDurationMs as L}from"../../core/wake.js";import{cliClient as B,getNodeOrNull as u}from"../api-client.js";import{nodeInPane as E}from"../surface/node/placement.js";function b(n,t){const e=n.pane??process.env.TMUX_PANE;let o=n.node;if((o===void 0||o==="")&&(o=E(e)),(o===void 0||o==="")&&(o=j()),o===void 0||o==="")throw new d({error:"no_node",message:t,next:"Run from inside a node, pass --node <id>, or --pane <pane>."});return{id:o,pane:e}}i(b,"resolveBashTarget");const S=h({name:"background",description:"hand the focused node\u2019s running bash command to its background job system",whenToUse:"the tmux prefix menu invokes this when a foreground bash command should stop blocking the agent immediately but keep running as a file-backed background job",tier:"hidden",help:{name:"node bash background",summary:"hand every running foreground bash command for one node to its file-backed background job system",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node whose running bash command to background. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE. The prefix menu passes this for you."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The target node."},{name:"jobs",type:"object[]",required:!0,constraint:"Per handed-off job {job_id, elapsed_ms} \u2014 the foreground elapsed time in milliseconds at the moment of handoff."}],outputKind:"object",effects:["Signals every foreground bash command currently running for the node to return from its tool call immediately while its detached supervisor keeps the command running.","Each handed-off command retains its log under the node context jobs directory and sends the node an urgent inbox message when it exits, which steers the node mid-turn."]},run:i(async n=>{const{id:t}=b(n,"no node found for the bash handoff");if(await u(t)===null)throw new d({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const e=$(c(t)),o=Date.now(),r=e.map(s=>({job_id:s.jobId,elapsed_ms:o-(D(s.jobId)??o)}));return{node_id:t,jobs:r}},"run"),render:i(n=>{const t=n.jobs;if(t.length===0)return`No foreground bash command is running for ${n.node_id}.`;const e=Math.max(...t.map(o=>o.elapsed_ms));return`Handed ${t.length} bash command(s) to the background job system for ${n.node_id} \xB7 ran ${w(e)} in the foreground.`},"render")}),R=h({name:"list",description:"list a node\u2019s live background bash jobs",whenToUse:"the Inspector\u2019s jobs section reads this to show what a node handed off to the background",tier:"hidden",help:{name:"node bash list",summary:"read every still-running background bash job owned by one node",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node whose background jobs to list. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."},{kind:"flag",name:"tail",type:"int",required:!1,default:0,constraint:"Include this many trailing log lines per job (0 = none)."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The target node."},{name:"jobs",type:"object[]",required:!0,constraint:"Oldest-first {job_id, command, purpose, started_at, elapsed_ms, deadline_at, log_path, pgid, log_tail} for every live background job; purpose is a human-readable label or null; deadline_at is the auto-cancel time or null for a job that runs to completion."}],outputKind:"object",effects:["Reads the node context jobs directory. Changes nothing."]},run:i(async n=>{const{id:t}=b(n,"no node found for the bash job list"),e=await u(t);if(e===null)throw new d({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=Date.now(),r=Math.max(0,Math.trunc(Number(n.tail??0))),s=c(e.node_id),l=x(s).map(a=>({job_id:a.jobId,command:a.command,purpose:a.purpose,started_at:new Date(a.startedAtMs).toISOString(),elapsed_ms:o-a.startedAtMs,deadline_at:a.deadlineAtMs===null?null:new Date(a.deadlineAtMs).toISOString(),log_path:a.logPath,pgid:T(s,a.jobId)??null,log_tail:q(a.logPath,r)}));return{node_id:e.node_id,jobs:l}},"run"),render:i(n=>{const t=n.jobs;return t.length===0?`No background bash jobs for ${n.node_id}.`:t.map(e=>`${e.job_id} \xB7 ${w(e.elapsed_ms)} \xB7 ${v(e.command)}${e.purpose===null?"":`
2
- purpose: ${e.purpose}`}${e.deadline_at===null?"":`
3
- cancels at: ${e.deadline_at}`}
4
- log: ${e.log_path}`).join(`
5
- `)},"render")}),U=h({name:"kill",description:"stop one of a node\u2019s background bash jobs",whenToUse:"the user watching the Inspector or the attach cockpit\u2019s bash row wants a long-running background job to stop now, or an agent is abandoning work it backgrounded",tier:"hidden",help:{name:"node bash kill",summary:"best-effort stop a background bash job and tell the owning node it was canceled",params:[{kind:"positional",name:"job",required:!0,constraint:"Job id, as reported by node bash list."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node owning the job. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The owning node."},{name:"signaled",type:"boolean",required:!0,constraint:"True when at least one observed supervisor-tree process received SIGTERM."}],outputKind:"object",effects:["Snapshots the supervisor\u2019s observable process tree, sends SIGTERM then SIGKILL to those processes, and cannot stop a descendant that detached and reparented before the snapshot.","Records the job\u2019s exit so it stops showing as live, and sends the owning node an urgent inbox message saying the job was stopped \u2014 which steers that node mid-turn."]},run:i(async n=>{const{id:t}=b(n,"no node found for the bash job"),e=await u(t);if(e===null)throw new d({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=n.job;if(!_(o))throw new d({error:"invalid_job_id",message:`invalid background job id: ${o}`,next:"Use a job id reported by `crtr node bash list`."});const r=c(e.node_id),s=f(r,o),l=await M(r,o);if(l.kind==="missing")throw new d({error:"not_found",message:`no background job ${o} for ${e.node_id}`,next:"List live jobs with `crtr node bash list`."});if(l.kind==="retired")throw new d({error:"not_found",message:`background job ${o} for ${e.node_id} is no longer running`,next:`It finished or was already stopped, so nothing was signaled. Log: ${l.logPath}`});if(l.kind==="not-stoppable")throw new d({error:"not_stoppable",message:`job ${o} recorded no trusted process identity`,next:`It started before crtr persisted its supervisor identity. Stop it by hand, then it will disappear from the list. Log: ${s.jobLog}`});return await B().sendMessage(e.node_id,{body:`Background bash job ${o} was stopped by the user before it finished. Log: ${s.jobLog} Command: ${s.cmdSh}`,tier:"urgent"}),{node_id:e.node_id,signaled:l.signaled}},"run"),render:i(n=>`Canceled a background bash job for ${n.node_id}${n.signaled===!0?"":" (no observed job process was still running)"}.`,"render")}),J=h({name:"extend",description:"claim an auto-backgrounded bash job so the daemon does not cancel it at its deadline",whenToUse:"a command the valve auto-backgrounded is worth keeping past its cancel deadline \u2014 give it more time with --for, or let it run to completion with --keep",tier:"hidden",help:{name:"node bash extend",summary:"move or clear the auto-cancel deadline on one of a node\u2019s live background bash jobs",params:[{kind:"positional",name:"job",required:!0,constraint:"Job id, as reported by node bash list or the auto-background notice."},{kind:"flag",name:"for",type:"string",required:!1,constraint:"New window from now before the job is canceled, as a duration (e.g. 90s, 10m, 1h30m). Mutually exclusive with --keep; give exactly one."},{kind:"flag",name:"keep",type:"bool",required:!1,constraint:"Remove the deadline entirely so the job runs to completion. Mutually exclusive with --for; give exactly one."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node owning the job. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The owning node."},{name:"deadline_at",type:"string",required:!1,constraint:"The job\u2019s new auto-cancel time (ISO), or absent when --keep cleared the deadline so the job runs to completion."}],outputKind:"object",effects:["Rewrites or removes the job\u2019s deadline file. The daemon\u2019s deadline lane reads it on its next scan. Signals nothing."]},run:i(async n=>{const{id:t}=b(n,"no node found for the bash job"),e=await u(t);if(e===null)throw new d({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=n.job;if(!_(o))throw new d({error:"invalid_job_id",message:`invalid background job id: ${o}`,next:"Use a job id reported by `crtr node bash list`."});const r=n.for,s=n.keep===!0;if(s===(r!==void 0&&r!==""))throw new d({error:"invalid_args",message:"give exactly one of --for <duration> or --keep",next:"Extend by a window with --for 10m, or drop the deadline with --keep."});const l=c(e.node_id),a=f(l,o);if(!m(a.dir))throw new d({error:"not_found",message:`no background job ${o} for ${e.node_id}`,next:"List live jobs with `crtr node bash list`."});if(!m(a.jobBg)||m(a.jobExit))throw new d({error:"not_running",message:`background job ${o} for ${e.node_id} is no longer running`,next:`It finished or was stopped, so there is no deadline to change. Log: ${a.jobLog}`});if(s)return I(a),{node_id:e.node_id};const g=L(r);if(g===null||g<=0)throw new d({error:"invalid_duration",message:`not a duration: ${r}`,next:"Use a value like 90s, 10m, or 1h30m."});const p=Date.now()+g;return N(a,p),{node_id:e.node_id,deadline_at:new Date(p).toISOString()}},"run"),render:i(n=>n.deadline_at===void 0?`Cleared the deadline \u2014 the background job will run to completion for ${n.node_id}.`:`Background job for ${n.node_id} will be canceled at ${n.deadline_at} unless extended again.`,"render")}),Q=y({name:"bash",description:"control file-backed bash jobs owned by a node",whenToUse:"a running bash command must be handed off, listed, stopped, or its auto-cancel deadline changed \u2014 the tmux prefix menu backgrounds, the Inspector\u2019s jobs section lists and cancels",tier:"hidden",help:{name:"node bash",summary:"control file-backed bash jobs owned by a node"},children:[S,R,U,J]});export{Q as nodeBash};
1
+ var w=Object.defineProperty;var r=(e,t)=>w(e,"name",{value:t,configurable:!0});import{envNodeId as _}from"../../shared/env.js";import{defineBranch as k,defineLeaf as c}from"../../core/command.js";import{InputError as s}from"../../core/io.js";import{existsSync as m}from"node:fs";import{activeBackgroundBashJobs as j,backgroundRunningBashJobs as y,bashJobCommandLine as x,bashJobPaths as v,clearJobDeadline as $,formatBashElapsed as g,isSafeBashJobId as f,jobStartedAtMs as I,readJobPgid as D,tailJobLog as T,writeJobDeadlineMs as M}from"../../core/bash-jobs.js";import{parseDurationMs as q}from"../../core/wake.js";import{cliClient as N,getNodeOrNull as h}from"../api-client.js";import{nodeInPane as E}from"../surface/node/placement.js";function u(e,t){const n=e.pane??process.env.TMUX_PANE;let o=e.node;if((o===void 0||o==="")&&(o=E(n)),(o===void 0||o==="")&&(o=_()),o===void 0||o==="")throw new s({error:"no_node",message:t,next:"Run from inside a node, pass --node <id>, or --pane <pane>."});return{id:o,pane:n}}r(u,"resolveBashTarget");const B=c({name:"background",description:"hand the focused node\u2019s running bash command to its background job system",whenToUse:"the tmux prefix menu invokes this when a foreground bash command should stop blocking the agent immediately but keep running as a file-backed background job",tier:"hidden",help:{name:"node bash background",summary:"hand every running foreground bash command for one node to its file-backed background job system",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node whose running bash command to background. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE. The prefix menu passes this for you."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The target node."},{name:"jobs",type:"object[]",required:!0,constraint:"Per handed-off job {job_id, elapsed_ms} \u2014 the foreground elapsed time in milliseconds at the moment of handoff."}],outputKind:"object",effects:["Signals every foreground bash command currently running for the node to return from its tool call immediately while its detached supervisor keeps the command running.","Each handed-off command retains its log under the node context jobs directory and sends the node an urgent inbox message when it exits, which steers the node mid-turn."]},run:r(async e=>{const{id:t}=u(e,"no node found for the bash handoff"),n=await h(t);if(n===null)throw new s({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=y(n.paths.context_dir),d=Date.now(),i=o.map(l=>({job_id:l.jobId,elapsed_ms:d-(I(l.jobId)??d)}));return{node_id:t,jobs:i}},"run"),render:r(e=>{const t=e.jobs;if(t.length===0)return`No foreground bash command is running for ${e.node_id}.`;const n=Math.max(...t.map(o=>o.elapsed_ms));return`Handed ${t.length} bash command(s) to the background job system for ${e.node_id} \xB7 ran ${g(n)} in the foreground.`},"render")}),R=c({name:"list",description:"list a node\u2019s live background bash jobs",whenToUse:"the Inspector\u2019s jobs section reads this to show what a node handed off to the background",tier:"hidden",help:{name:"node bash list",summary:"read every still-running background bash job owned by one node",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node whose background jobs to list. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."},{kind:"flag",name:"tail",type:"int",required:!1,default:0,constraint:"Include this many trailing log lines per job (0 = none)."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The target node."},{name:"jobs",type:"object[]",required:!0,constraint:"Oldest-first {job_id, command, purpose, started_at, elapsed_ms, deadline_at, log_path, pgid, log_tail} for every live background job; purpose is a human-readable label or null; deadline_at is the auto-cancel time or null for a job that runs to completion."}],outputKind:"object",effects:["Reads the node context jobs directory. Changes nothing."]},run:r(async e=>{const{id:t}=u(e,"no node found for the bash job list"),n=await h(t);if(n===null)throw new s({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=Date.now(),d=Math.max(0,Math.trunc(Number(e.tail??0))),i=n.paths.context_dir,l=j(i).map(a=>({job_id:a.jobId,command:a.command,purpose:a.purpose,started_at:new Date(a.startedAtMs).toISOString(),elapsed_ms:o-a.startedAtMs,deadline_at:a.deadlineAtMs===null?null:new Date(a.deadlineAtMs).toISOString(),log_path:a.logPath,pgid:D(i,a.jobId)??null,log_tail:T(a.logPath,d)}));return{node_id:n.node_id,jobs:l}},"run"),render:r(e=>{const t=e.jobs;return t.length===0?`No background bash jobs for ${e.node_id}.`:t.map(n=>`${n.job_id} \xB7 ${g(n.elapsed_ms)} \xB7 ${x(n.command)}${n.purpose===null?"":`
2
+ purpose: ${n.purpose}`}${n.deadline_at===null?"":`
3
+ cancels at: ${n.deadline_at}`}
4
+ log: ${n.log_path}`).join(`
5
+ `)},"render")}),S=c({name:"kill",description:"stop one of a node\u2019s background bash jobs",whenToUse:"the user watching the Inspector or the attach cockpit\u2019s bash row wants a long-running background job to stop now, or an agent is abandoning work it backgrounded",tier:"hidden",help:{name:"node bash kill",summary:"best-effort stop a background bash job and tell the owning node it was canceled",params:[{kind:"positional",name:"job",required:!0,constraint:"Job id, as reported by node bash list."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node owning the job. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The owning node."},{name:"signaled",type:"boolean",required:!0,constraint:"True when at least one observed supervisor-tree process received SIGTERM."}],outputKind:"object",effects:["Snapshots the supervisor\u2019s observable process tree, sends SIGTERM then SIGKILL to those processes, and cannot stop a descendant that detached and reparented before the snapshot.","Records the job\u2019s exit so it stops showing as live, and sends the owning node an urgent inbox message saying the job was stopped \u2014 which steers that node mid-turn."]},run:r(async e=>{const{id:t}=u(e,"no node found for the bash job"),n=await h(t);if(n===null)throw new s({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=e.job;if(!f(o))throw new s({error:"invalid_job_id",message:`invalid background job id: ${o}`,next:"Use a job id reported by `crtr node bash list`."});const d=await N().stopBashJob(n.node_id,o);return{node_id:n.node_id,signaled:d.signaled}},"run"),render:r(e=>`Canceled a background bash job for ${e.node_id}${e.signaled===!0?"":" (no observed job process was still running)"}.`,"render")}),L=c({name:"extend",description:"claim an auto-backgrounded bash job so the daemon does not cancel it at its deadline",whenToUse:"a command the valve auto-backgrounded is worth keeping past its cancel deadline \u2014 give it more time with --for, or let it run to completion with --keep",tier:"hidden",help:{name:"node bash extend",summary:"move or clear the auto-cancel deadline on one of a node\u2019s live background bash jobs",params:[{kind:"positional",name:"job",required:!0,constraint:"Job id, as reported by node bash list or the auto-background notice."},{kind:"flag",name:"for",type:"string",required:!1,constraint:"New window from now before the job is canceled, as a duration (e.g. 90s, 10m, 1h30m). Mutually exclusive with --keep; give exactly one."},{kind:"flag",name:"keep",type:"bool",required:!1,constraint:"Remove the deadline entirely so the job runs to completion. Mutually exclusive with --for; give exactly one."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Node owning the job. Defaults to the node in --pane, else the caller (CRTR_NODE_ID)."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the target node, when --node is omitted. Defaults to $TMUX_PANE."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The owning node."},{name:"deadline_at",type:"string",required:!1,constraint:"The job\u2019s new auto-cancel time (ISO), or absent when --keep cleared the deadline so the job runs to completion."}],outputKind:"object",effects:["Rewrites or removes the job\u2019s deadline file. The daemon\u2019s deadline lane reads it on its next scan. Signals nothing."]},run:r(async e=>{const{id:t}=u(e,"no node found for the bash job"),n=await h(t);if(n===null)throw new s({error:"not_found",message:`no node: ${t}`,next:"List nodes with `crtr node inspect list`."});const o=e.job;if(!f(o))throw new s({error:"invalid_job_id",message:`invalid background job id: ${o}`,next:"Use a job id reported by `crtr node bash list`."});const d=e.for,i=e.keep===!0;if(i===(d!==void 0&&d!==""))throw new s({error:"invalid_args",message:"give exactly one of --for <duration> or --keep",next:"Extend by a window with --for 10m, or drop the deadline with --keep."});const l=n.paths.context_dir,a=v(l,o);if(!m(a.dir))throw new s({error:"not_found",message:`no background job ${o} for ${n.node_id}`,next:"List live jobs with `crtr node bash list`."});if(!m(a.jobBg)||m(a.jobExit))throw new s({error:"not_running",message:`background job ${o} for ${n.node_id} is no longer running`,next:`It finished or was stopped, so there is no deadline to change. Log: ${a.jobLog}`});if(i)return $(a),{node_id:n.node_id};const b=q(d);if(b===null||b<=0)throw new s({error:"invalid_duration",message:`not a duration: ${d}`,next:"Use a value like 90s, 10m, or 1h30m."});const p=Date.now()+b;return M(a,p),{node_id:n.node_id,deadline_at:new Date(p).toISOString()}},"run"),render:r(e=>e.deadline_at===void 0?`Cleared the deadline \u2014 the background job will run to completion for ${e.node_id}.`:`Background job for ${e.node_id} will be canceled at ${e.deadline_at} unless extended again.`,"render")}),H=k({name:"bash",description:"control file-backed bash jobs owned by a node",whenToUse:"a running bash command must be handed off, listed, stopped, or its auto-cancel deadline changed \u2014 the tmux prefix menu backgrounds, the Inspector\u2019s jobs section lists and cancels",tier:"hidden",help:{name:"node bash",summary:"control file-backed bash jobs owned by a node"},children:[B,R,S,L]});export{H as nodeBash};
@@ -3,21 +3,4 @@
3
3
  * YIELD_NUDGE_THRESHOLD, steer it to yield now and let its fresh revive handle
4
4
  * the child's result. */
5
5
  export declare function childFollowUp(spawnerId: string | undefined): Promise<string>;
6
- /** Validate a `--kind` against the installed personas; throws a listing InputError. */
7
- export declare function assertKind(kind: string): void;
8
- /** A live `<kinds count=N>` state element — one `<kind> — <whenToUse>` line per
9
- * installed top-level persona kind (project > user > builtin), lazily built so
10
- * it reflects the caller's cwd/project scope. Appended to `node new -h` and
11
- * `node promote -h` so custom kinds appear in help. Soft-fails via the renderer.
12
- *
13
- * Keep this block cheap and caller-agnostic: help should not depend on the
14
- * running node's current persona env, which can lag after polymorph. Sub-kinds
15
- * (e.g. `audit/security`) are OMITTED here — `KindConfig.availableTo`
16
- * defaults to the sub-kind's own top-level ancestor, and this generic block has
17
- * no single ancestor to check against, so only an explicit `availableTo: ['*']`
18
- * sub-kind (universally available) earns a place in this list. A direct launch
19
- * by full sub-kind string is always valid regardless (visibility-only
20
- * filtering) — discover the roster for a specific kind via
21
- * `crtr sys context prompt-review --list --kind <kind>`. */
22
- export declare function kindsStateBlock(): string;
23
6
  export declare const nodeNew: import("../../core/command.js").LeafDef;