@north-light/crouter 0.3.349 → 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 (629) 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/dto/analytics.d.ts +184 -0
  6. package/dist/api/dto/analytics.js +0 -0
  7. package/dist/api/dto/broker-ops.d.ts +43 -1
  8. package/dist/api/dto/config.d.ts +11 -0
  9. package/dist/api/dto/grants.d.ts +14 -0
  10. package/dist/api/dto/grants.js +0 -0
  11. package/dist/api/dto/human-requests.d.ts +14 -0
  12. package/dist/api/dto/memory.d.ts +6 -0
  13. package/dist/api/dto/modelauth.d.ts +35 -0
  14. package/dist/api/dto/node-records.d.ts +35 -0
  15. package/dist/api/dto/node-records.js +0 -0
  16. package/dist/api/dto/nodes.d.ts +5 -0
  17. package/dist/api/dto/profiles.d.ts +38 -3
  18. package/dist/api/dto/worktree.d.ts +11 -0
  19. package/dist/api/errors.d.ts +23 -1
  20. package/dist/api/errors.js +1 -1
  21. package/dist/api/index.d.ts +2 -0
  22. package/dist/api/index.js +1 -1
  23. package/dist/api/node-transport.js +1 -1
  24. package/dist/api/routes.d.ts +22 -0
  25. package/dist/api/routes.js +1 -1
  26. package/dist/build-root.d.ts +6 -1
  27. package/dist/build-root.js +1 -1
  28. package/dist/builtin-memory/crouter-sdk/client.md +34 -0
  29. package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
  30. package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
  31. package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
  32. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
  37. package/dist/cli.js +9 -8
  38. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  39. package/dist/clients/attach/chrome/roster.js +1 -1
  40. package/dist/clients/attach/config.js +1 -1
  41. package/dist/clients/attach/overlays/auth.js +2 -2
  42. package/dist/clients/attach/overlays/graph.js +1 -1
  43. package/dist/clients/attach/render/tool-calls.js +3 -3
  44. package/dist/clients/attach/session/connection.js +1 -1
  45. package/dist/clients/attach/session/profile-files.js +1 -1
  46. package/dist/clients/attach/viewer.js +1569 -816
  47. package/dist/commands/api-client.js +3 -3
  48. package/dist/commands/broker-permissions.d.ts +2 -0
  49. package/dist/commands/broker-permissions.js +1 -0
  50. package/dist/commands/canvas-analytics/chart.d.ts +52 -0
  51. package/dist/commands/canvas-analytics/chart.js +1 -0
  52. package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
  53. package/dist/commands/canvas-analytics/drilldown.js +1 -0
  54. package/dist/commands/canvas-analytics/format.d.ts +29 -0
  55. package/dist/commands/canvas-analytics/format.js +1 -0
  56. package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
  57. package/dist/commands/canvas-analytics/graph-detail.js +2 -0
  58. package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
  59. package/dist/commands/canvas-analytics/graphs.js +1 -0
  60. package/dist/commands/canvas-analytics/memory.d.ts +2 -0
  61. package/dist/commands/canvas-analytics/memory.js +1 -0
  62. package/dist/commands/canvas-analytics/overview.d.ts +2 -0
  63. package/dist/commands/canvas-analytics/overview.js +1 -0
  64. package/dist/commands/canvas-analytics/shell.d.ts +60 -0
  65. package/dist/commands/canvas-analytics/shell.js +2 -0
  66. package/dist/commands/canvas-analytics/time.d.ts +2 -0
  67. package/dist/commands/canvas-analytics/time.js +1 -0
  68. package/dist/commands/canvas-analytics/usage.d.ts +2 -0
  69. package/dist/commands/canvas-analytics/usage.js +1 -0
  70. package/dist/commands/canvas-analytics/view.d.ts +85 -0
  71. package/dist/commands/canvas-analytics/view.js +1 -0
  72. package/dist/commands/canvas-analytics.d.ts +2 -0
  73. package/dist/commands/canvas-analytics.js +1 -0
  74. package/dist/commands/canvas-prune.js +1 -1
  75. package/dist/commands/canvas.js +1 -1
  76. package/dist/commands/cron.js +5 -5
  77. package/dist/commands/human/components.d.ts +2 -0
  78. package/dist/commands/human/components.js +2 -2
  79. package/dist/commands/human/prompts.js +1 -1
  80. package/dist/commands/human/queue.js +1 -1
  81. package/dist/commands/memory/client.d.ts +11 -0
  82. package/dist/commands/memory/client.js +1 -0
  83. package/dist/commands/memory/delete.js +1 -1
  84. package/dist/commands/memory/edit.js +3 -3
  85. package/dist/commands/memory/find.js +1 -1
  86. package/dist/commands/memory/history.js +4 -4
  87. package/dist/commands/memory/lint.js +1 -1
  88. package/dist/commands/memory/list.d.ts +0 -2
  89. package/dist/commands/memory/list.js +1 -1
  90. package/dist/commands/memory/move.js +1 -1
  91. package/dist/commands/memory/origin.js +1 -1
  92. package/dist/commands/memory/read.d.ts +0 -5
  93. package/dist/commands/memory/read.js +3 -3
  94. package/dist/commands/memory/shared.d.ts +0 -178
  95. package/dist/commands/memory/shared.js +1 -12
  96. package/dist/commands/memory/write.js +5 -5
  97. package/dist/commands/node/bash.js +5 -5
  98. package/dist/commands/node/create.d.ts +0 -17
  99. package/dist/commands/node/create.js +2 -3
  100. package/dist/commands/node/inspect.js +6 -6
  101. package/dist/commands/node/lifecycle.js +2 -2
  102. package/dist/commands/node-context.js +2 -2
  103. package/dist/commands/node-inspect-artifacts.js +6 -6
  104. package/dist/commands/pkg/browse/catalog.js +1 -1
  105. package/dist/commands/pkg/browse/model.d.ts +1 -1
  106. package/dist/commands/pkg/market-manage.js +1 -1
  107. package/dist/commands/pkg/plugin-manage.js +10 -10
  108. package/dist/commands/profile/daemon-profiles.d.ts +13 -0
  109. package/dist/commands/profile/daemon-profiles.js +4 -0
  110. package/dist/commands/profile/delete.js +1 -1
  111. package/dist/commands/profile/env.d.ts +6 -0
  112. package/dist/commands/profile/env.js +2 -2
  113. package/dist/commands/profile/kind.js +1 -2
  114. package/dist/commands/profile/list.js +1 -1
  115. package/dist/commands/profile/meta.js +1 -1
  116. package/dist/commands/profile/new.js +1 -1
  117. package/dist/commands/profile/pause.js +1 -1
  118. package/dist/commands/profile/project.js +1 -1
  119. package/dist/commands/profile/rename.js +1 -1
  120. package/dist/commands/profile/show.js +1 -1
  121. package/dist/commands/profile.js +1 -1
  122. package/dist/commands/push.js +3 -3
  123. package/dist/commands/surface-inspect.js +1 -1
  124. package/dist/commands/sys/branch.js +1 -1
  125. package/dist/commands/sys/config.js +1 -1
  126. package/dist/commands/sys/connect.js +3 -3
  127. package/dist/commands/sys/context/admin/actions.js +1 -1
  128. package/dist/commands/sys/context/admin/model.d.ts +1 -0
  129. package/dist/commands/sys/context/admin/model.js +1 -1
  130. package/dist/commands/sys/context/admin.js +1 -1
  131. package/dist/commands/sys/context/expose.js +2 -1
  132. package/dist/commands/sys/context/prompt-review.js +2 -2
  133. package/dist/commands/sys/context/resolve.js +7 -7
  134. package/dist/commands/sys/context/sysprompt.js +1 -1
  135. package/dist/commands/sys/join.d.ts +1 -0
  136. package/dist/commands/sys/join.js +1 -0
  137. package/dist/commands/sys/migrate.js +1 -1
  138. package/dist/commands/sys/panels/models-panel.js +1 -1
  139. package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
  140. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  141. package/dist/commands/sys/provider-login.js +6 -6
  142. package/dist/commands/sys/setup-core.d.ts +1 -1
  143. package/dist/commands/sys/setup-core.js +6 -6
  144. package/dist/commands/sys/setup-settings-runner.js +1 -1
  145. package/dist/commands/sys/setup.js +1 -1
  146. package/dist/commands/sys/spaces.d.ts +1 -0
  147. package/dist/commands/sys/spaces.js +2 -0
  148. package/dist/commands/sys/sync-deps.js +2 -2
  149. package/dist/commands/sys/sync-project-guidance.js +4 -4
  150. package/dist/commands/sys/sync-skills.js +2 -2
  151. package/dist/commands/sys/worktrees.d.ts +1 -0
  152. package/dist/commands/sys/worktrees.js +1 -1
  153. package/dist/commands/sys.js +1 -1
  154. package/dist/core/auth-file.js +2 -2
  155. package/dist/core/bash-job-supervisor.d.ts +6 -0
  156. package/dist/core/bash-job-supervisor.js +4 -0
  157. package/dist/core/bash-jobs.d.ts +13 -6
  158. package/dist/core/bash-jobs.js +8 -7
  159. package/dist/core/broker-client/transport-relay.d.ts +6 -3
  160. package/dist/core/broker-client/transport-relay.js +1 -1
  161. package/dist/core/broker-client/transport-socket.d.ts +6 -1
  162. package/dist/core/broker-client/transport-socket.js +1 -1
  163. package/dist/core/canvas/canvas.d.ts +39 -18
  164. package/dist/core/canvas/canvas.js +21 -20
  165. package/dist/core/canvas/context-strip.d.ts +20 -0
  166. package/dist/core/canvas/context-strip.js +5 -0
  167. package/dist/core/canvas/crons.d.ts +12 -20
  168. package/dist/core/canvas/crons.js +15 -13
  169. package/dist/core/canvas/db.js +2 -2
  170. package/dist/core/canvas/deliveries.d.ts +4 -1
  171. package/dist/core/canvas/deliveries.js +1 -1
  172. package/dist/core/canvas/executions.js +1 -1
  173. package/dist/core/canvas/history.d.ts +2 -1
  174. package/dist/core/canvas/history.js +17 -18
  175. package/dist/core/canvas/memory-reads.d.ts +19 -0
  176. package/dist/core/canvas/memory-reads.js +1 -0
  177. package/dist/core/canvas/migrations.d.ts +0 -4
  178. package/dist/core/canvas/migrations.js +99 -32
  179. package/dist/core/canvas/nav-render.js +1 -1
  180. package/dist/core/canvas/node-agent-paths.d.ts +8 -0
  181. package/dist/core/canvas/node-agent-paths.js +1 -0
  182. package/dist/core/canvas/node-recap.d.ts +2 -2
  183. package/dist/core/canvas/node-recap.js +2 -2
  184. package/dist/core/canvas/node-tokens.d.ts +24 -0
  185. package/dist/core/canvas/node-tokens.js +5 -0
  186. package/dist/core/canvas/paths.d.ts +16 -19
  187. package/dist/core/canvas/paths.js +1 -1
  188. package/dist/core/canvas/render-source.d.ts +2 -2
  189. package/dist/core/canvas/render-source.js +6 -9
  190. package/dist/core/canvas/sessions.d.ts +18 -0
  191. package/dist/core/canvas/sessions.js +4 -1
  192. package/dist/core/canvas/types.d.ts +22 -6
  193. package/dist/core/command-hooks/compose.js +1 -1
  194. package/dist/core/command-hooks/discovery.d.ts +15 -1
  195. package/dist/core/command-hooks/discovery.js +1 -1
  196. package/dist/core/command-hooks/help.d.ts +2 -2
  197. package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
  198. package/dist/core/command-hooks/lifecycle-create.js +1 -1
  199. package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
  200. package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
  201. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
  202. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  203. package/dist/core/command-hooks/transport/plan.d.ts +3 -0
  204. package/dist/core/command-hooks/transport/plan.js +1 -0
  205. package/dist/core/command-plugins/discovery.js +1 -1
  206. package/dist/core/command.d.ts +6 -2
  207. package/dist/core/command.js +6 -6
  208. package/dist/core/config.d.ts +8 -5
  209. package/dist/core/config.js +1 -1
  210. package/dist/core/conversation-store/client-worker.d.ts +1 -0
  211. package/dist/core/conversation-store/client-worker.js +1 -0
  212. package/dist/core/conversation-store/client.d.ts +2 -0
  213. package/dist/core/conversation-store/client.js +2 -0
  214. package/dist/core/conversation-store/file-store.d.ts +37 -0
  215. package/dist/core/conversation-store/file-store.js +9 -0
  216. package/dist/core/conversation-store/index.d.ts +50 -0
  217. package/dist/core/conversation-store/index.js +1 -0
  218. package/dist/core/conversation-store/listener.d.ts +4 -0
  219. package/dist/core/conversation-store/listener.js +3 -0
  220. package/dist/core/conversation-store/patch.d.ts +1 -0
  221. package/dist/core/conversation-store/patch.js +1 -0
  222. package/dist/core/directory/join.d.ts +27 -0
  223. package/dist/core/directory/join.js +1 -0
  224. package/dist/core/disk-usage.d.ts +4 -0
  225. package/dist/core/disk-usage.js +1 -0
  226. package/dist/core/events/emit.d.ts +2 -0
  227. package/dist/core/events/emit.js +3 -1
  228. package/dist/core/feed/feed.js +4 -4
  229. package/dist/core/feed/messages.d.ts +3 -0
  230. package/dist/core/feed/messages.js +6 -6
  231. package/dist/core/fs-utils.d.ts +2 -0
  232. package/dist/core/fs-utils.js +3 -3
  233. package/dist/core/grants/local.d.ts +4 -0
  234. package/dist/core/grants/local.js +1 -0
  235. package/dist/core/grants/mirror.d.ts +44 -0
  236. package/dist/core/grants/mirror.js +4 -0
  237. package/dist/core/grants/on-sync.d.ts +22 -0
  238. package/dist/core/grants/on-sync.js +1 -0
  239. package/dist/core/grants/remove.d.ts +7 -0
  240. package/dist/core/grants/remove.js +1 -0
  241. package/dist/core/grants/sandboxes.d.ts +7 -0
  242. package/dist/core/grants/sandboxes.js +1 -0
  243. package/dist/core/grants/sync.d.ts +12 -0
  244. package/dist/core/grants/sync.js +1 -0
  245. package/dist/core/help/memory-extensions.d.ts +3 -0
  246. package/dist/core/help/memory-extensions.js +2 -0
  247. package/dist/core/help.d.ts +14 -0
  248. package/dist/core/help.js +7 -7
  249. package/dist/core/host-exports/builtins.js +3 -3
  250. package/dist/core/host-exports/export.js +3 -3
  251. package/dist/core/human/action-binding.d.ts +2 -0
  252. package/dist/core/human/action-binding.js +1 -1
  253. package/dist/core/human/feedback-companion.d.ts +0 -1
  254. package/dist/core/human/feedback-companion.js +1 -1
  255. package/dist/core/human/page-schema.d.ts +1 -1
  256. package/dist/core/inspector/core.d.ts +2 -0
  257. package/dist/core/inspector/core.js +1 -1
  258. package/dist/core/inspector/tui.js +2 -2
  259. package/dist/core/installed-plugins.js +1 -1
  260. package/dist/core/io.js +6 -6
  261. package/dist/core/keybindings/catalog.d.ts +1 -1
  262. package/dist/core/keybindings/catalog.js +1 -1
  263. package/dist/core/layout-migrate/index.d.ts +15 -0
  264. package/dist/core/layout-migrate/index.js +4 -0
  265. package/dist/core/layout-migrate/paths.d.ts +26 -0
  266. package/dist/core/layout-migrate/paths.js +1 -0
  267. package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
  268. package/dist/core/layout-migrate/stored-paths.js +11 -0
  269. package/dist/core/layout-migrate/stores.d.ts +17 -0
  270. package/dist/core/layout-migrate/stores.js +4 -0
  271. package/dist/core/layout.d.ts +26 -0
  272. package/dist/core/layout.js +2 -0
  273. package/dist/core/llm/run.d.ts +60 -0
  274. package/dist/core/llm/run.js +4 -0
  275. package/dist/core/memory/cli-selector.d.ts +13 -0
  276. package/dist/core/memory/cli-selector.js +1 -0
  277. package/dist/core/memory/history.d.ts +5 -4
  278. package/dist/core/memory/history.js +6 -6
  279. package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
  280. package/dist/core/memory/inline-ref-inventory.js +1 -1
  281. package/dist/core/memory/lint.js +2 -2
  282. package/dist/core/memory/mutation-domain.d.ts +2 -2
  283. package/dist/core/memory/mutation-domain.js +8 -7
  284. package/dist/core/memory/mutations.js +1 -1
  285. package/dist/core/memory/service.d.ts +5 -0
  286. package/dist/core/memory/service.js +2 -2
  287. package/dist/core/memory-resolver.d.ts +11 -7
  288. package/dist/core/memory-resolver.js +2 -2
  289. package/dist/core/model-auth/daemon-login.d.ts +13 -0
  290. package/dist/core/model-auth/daemon-login.js +1 -0
  291. package/dist/core/model-auth/flows.d.ts +45 -0
  292. package/dist/core/model-auth/flows.js +1 -0
  293. package/dist/core/model-auth/handoff-jti.d.ts +4 -0
  294. package/dist/core/model-auth/handoff-jti.js +1 -0
  295. package/dist/core/model-routes.js +1 -1
  296. package/dist/core/nested-stores.d.ts +2 -1
  297. package/dist/core/nested-stores.js +1 -2
  298. package/dist/core/preview-registry.js +2 -2
  299. package/dist/core/profiles/env-store.js +2 -2
  300. package/dist/core/profiles/manifest.d.ts +16 -5
  301. package/dist/core/profiles/manifest.js +1 -1
  302. package/dist/core/provider-management.js +1 -1
  303. package/dist/core/review/birth.js +1 -1
  304. package/dist/core/review/companion.d.ts +0 -2
  305. package/dist/core/review/companion.js +1 -1
  306. package/dist/core/review/fork.js +2 -2
  307. package/dist/core/review/realize.js +1 -1
  308. package/dist/core/review/stage.d.ts +1 -1
  309. package/dist/core/review/stage.js +1 -1
  310. package/dist/core/review/types.d.ts +1 -1
  311. package/dist/core/runs/events.d.ts +34 -0
  312. package/dist/core/runs/events.js +1 -0
  313. package/dist/core/runs/operations.d.ts +43 -0
  314. package/dist/core/runs/operations.js +12 -0
  315. package/dist/core/runtime/bearings-render.d.ts +2 -2
  316. package/dist/core/runtime/bearings-render.js +11 -11
  317. package/dist/core/runtime/bearings.js +2 -2
  318. package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
  319. package/dist/core/runtime/broker/cli-relay.js +1 -0
  320. package/dist/core/runtime/broker/client-registry.d.ts +0 -5
  321. package/dist/core/runtime/broker/client-registry.js +1 -1
  322. package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
  323. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  324. package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
  325. package/dist/core/runtime/broker/engine-drive.js +1 -1
  326. package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
  327. package/dist/core/runtime/broker/fault-retry.js +1 -1
  328. package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
  329. package/dist/core/runtime/broker/frame-dispatch.js +1 -1
  330. package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
  331. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  332. package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
  333. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  334. package/dist/core/runtime/broker/frame-read.js +1 -1
  335. package/dist/core/runtime/broker/frame-session.js +1 -1
  336. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
  337. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  338. package/dist/core/runtime/broker/inbox.d.ts +1 -2
  339. package/dist/core/runtime/broker/inbox.js +7 -10
  340. package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
  341. package/dist/core/runtime/broker/model-adapter.js +2 -0
  342. package/dist/core/runtime/broker/node-token.d.ts +3 -0
  343. package/dist/core/runtime/broker/node-token.js +1 -0
  344. package/dist/core/runtime/broker/read-ops.js +1 -1
  345. package/dist/core/runtime/broker/rebind.d.ts +2 -0
  346. package/dist/core/runtime/broker/rebind.js +1 -1
  347. package/dist/core/runtime/broker/tool-groups.js +1 -1
  348. package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
  349. package/dist/core/runtime/broker/turn-ignition.js +1 -1
  350. package/dist/core/runtime/broker-cli.js +3 -3
  351. package/dist/core/runtime/broker-extension-render.d.ts +2 -5
  352. package/dist/core/runtime/broker-extension-render.js +4 -4
  353. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  354. package/dist/core/runtime/broker-protocol.d.ts +7 -8
  355. package/dist/core/runtime/broker.js +1 -1
  356. package/dist/core/runtime/canvas-extensions.d.ts +1 -0
  357. package/dist/core/runtime/canvas-extensions.js +1 -1
  358. package/dist/core/runtime/close.d.ts +9 -0
  359. package/dist/core/runtime/close.js +1 -1
  360. package/dist/core/runtime/deliver-live.js +1 -1
  361. package/dist/core/runtime/fleet.d.ts +1 -1
  362. package/dist/core/runtime/front-door-login.js +1 -1
  363. package/dist/core/runtime/front-door.js +2 -2
  364. package/dist/core/runtime/headless-pi.d.ts +1 -1
  365. package/dist/core/runtime/headless-pi.js +1 -1
  366. package/dist/core/runtime/host.d.ts +1 -1
  367. package/dist/core/runtime/host.js +3 -1
  368. package/dist/core/runtime/invocation.d.ts +3 -0
  369. package/dist/core/runtime/kickoff.d.ts +1 -0
  370. package/dist/core/runtime/kickoff.js +16 -16
  371. package/dist/core/runtime/launch-target.d.ts +1 -1
  372. package/dist/core/runtime/launch-target.js +1 -1
  373. package/dist/core/runtime/launch.d.ts +10 -35
  374. package/dist/core/runtime/launch.js +1 -1
  375. package/dist/core/runtime/lifecycle.js +2 -2
  376. package/dist/core/runtime/memory.d.ts +1 -1
  377. package/dist/core/runtime/memory.js +1 -1
  378. package/dist/core/runtime/model-registry.js +1 -1
  379. package/dist/core/runtime/model-swap.d.ts +17 -19
  380. package/dist/core/runtime/model-swap.js +1 -1
  381. package/dist/core/runtime/node-read.js +3 -2
  382. package/dist/core/runtime/nodes.d.ts +7 -0
  383. package/dist/core/runtime/nodes.js +1 -1
  384. package/dist/core/runtime/outcome-document.js +1 -1
  385. package/dist/core/runtime/package-health.js +2 -2
  386. package/dist/core/runtime/persona.js +2 -2
  387. package/dist/core/runtime/pi-vendored.js +1 -1
  388. package/dist/core/runtime/placement-tmux.d.ts +1 -1
  389. package/dist/core/runtime/placement-tmux.js +1 -1
  390. package/dist/core/runtime/placement.js +1 -1
  391. package/dist/core/runtime/promote.js +1 -1
  392. package/dist/core/runtime/provider-credential-gate.js +2 -2
  393. package/dist/core/runtime/recovery-hold.d.ts +2 -0
  394. package/dist/core/runtime/recovery-hold.js +1 -0
  395. package/dist/core/runtime/recycle.js +1 -1
  396. package/dist/core/runtime/reopen.js +1 -1
  397. package/dist/core/runtime/reset.js +1 -1
  398. package/dist/core/runtime/revive.d.ts +1 -1
  399. package/dist/core/runtime/revive.js +2 -3
  400. package/dist/core/runtime/roadmap.js +4 -4
  401. package/dist/core/runtime/run-command.d.ts +6 -0
  402. package/dist/core/runtime/run-command.js +1 -1
  403. package/dist/core/runtime/session-branch.d.ts +2 -8
  404. package/dist/core/runtime/session-branch.js +1 -1
  405. package/dist/core/runtime/session-list-cache.d.ts +6 -22
  406. package/dist/core/runtime/session-list-cache.js +1 -1
  407. package/dist/core/runtime/situational-context.js +2 -2
  408. package/dist/core/runtime/spawn-env.d.ts +6 -6
  409. package/dist/core/runtime/spawn-env.js +1 -1
  410. package/dist/core/runtime/spawn.d.ts +5 -0
  411. package/dist/core/runtime/spawn.js +2 -2
  412. package/dist/core/runtime/stop-guard.js +2 -2
  413. package/dist/core/runtime/stop-signals.d.ts +2 -2
  414. package/dist/core/runtime/stop-signals.js +1 -1
  415. package/dist/core/runtime/structured-output.d.ts +10 -4
  416. package/dist/core/runtime/structured-output.js +4 -4
  417. package/dist/core/runtime/tmux-bindings.js +3 -3
  418. package/dist/core/runtime/tmux-driver.d.ts +4 -0
  419. package/dist/core/runtime/tmux-driver.js +7 -7
  420. package/dist/core/runtime/view-socket.d.ts +9 -2
  421. package/dist/core/runtime/view-socket.js +1 -1
  422. package/dist/core/runtime/warm-pool.js +1 -1
  423. package/dist/core/scope.d.ts +3 -2
  424. package/dist/core/scope.js +1 -1
  425. package/dist/core/scoped-state/db.js +1 -1
  426. package/dist/core/scoped-state/migrate.js +3 -3
  427. package/dist/core/scoped-state/profiles.d.ts +2 -1
  428. package/dist/core/scoped-state/profiles.js +1 -1
  429. package/dist/core/scoped-state/schema.d.ts +2 -1
  430. package/dist/core/scoped-state/schema.js +4 -4
  431. package/dist/core/scopes.d.ts +2 -2
  432. package/dist/core/scopes.js +1 -1
  433. package/dist/core/secrets.d.ts +1 -0
  434. package/dist/core/secrets.js +2 -2
  435. package/dist/core/spaces/mounts.d.ts +32 -0
  436. package/dist/core/spaces/mounts.js +1 -0
  437. package/dist/core/spaces/open-beneath.d.ts +71 -0
  438. package/dist/core/spaces/open-beneath.js +1 -0
  439. package/dist/core/spaces/permissions.d.ts +46 -0
  440. package/dist/core/spaces/permissions.js +1 -0
  441. package/dist/core/spaces/process.d.ts +27 -0
  442. package/dist/core/spaces/process.js +1 -0
  443. package/dist/core/spaces/space.d.ts +8 -0
  444. package/dist/core/spaces/space.js +2 -0
  445. package/dist/core/spaces/stop.d.ts +8 -0
  446. package/dist/core/spaces/stop.js +2 -0
  447. package/dist/core/spaces/users.d.ts +19 -0
  448. package/dist/core/spaces/users.js +1 -0
  449. package/dist/core/subscription-state.d.ts +2 -0
  450. package/dist/core/subscription-state.js +3 -3
  451. package/dist/core/substrate/frontmatter-validation.js +1 -1
  452. package/dist/core/substrate/injected-store.d.ts +28 -3
  453. package/dist/core/substrate/injected-store.js +2 -1
  454. package/dist/core/substrate/listings.js +1 -1
  455. package/dist/core/substrate/memory-events.d.ts +6 -0
  456. package/dist/core/substrate/memory-events.js +1 -0
  457. package/dist/core/substrate/on-read-node.js +1 -1
  458. package/dist/core/substrate/on-read.d.ts +6 -6
  459. package/dist/core/substrate/on-read.js +5 -5
  460. package/dist/core/substrate/plan.js +1 -1
  461. package/dist/core/substrate/render-node.js +1 -1
  462. package/dist/core/substrate/render.d.ts +4 -3
  463. package/dist/core/substrate/render.js +38 -38
  464. package/dist/core/substrate/schema.d.ts +6 -0
  465. package/dist/core/substrate/schema.js +1 -1
  466. package/dist/core/tui/panel.js +1 -1
  467. package/dist/core/user-settings.d.ts +12 -0
  468. package/dist/core/user-settings.js +1 -1
  469. package/dist/core/worktree-mutation-async.js +5 -5
  470. package/dist/core/worktree-quarantine.js +1 -1
  471. package/dist/core/worktree-remove.d.ts +15 -0
  472. package/dist/core/worktree-remove.js +1 -0
  473. package/dist/core/worktree-sweep.js +6 -6
  474. package/dist/daemon/analytics/compute.d.ts +37 -0
  475. package/dist/daemon/analytics/compute.js +1 -0
  476. package/dist/daemon/analytics/scan-worker.d.ts +1 -0
  477. package/dist/daemon/analytics/scan-worker.js +2 -0
  478. package/dist/daemon/analytics/scan.d.ts +37 -0
  479. package/dist/daemon/analytics/scan.js +1 -0
  480. package/dist/daemon/api/app-listener.d.ts +11 -0
  481. package/dist/daemon/api/app-listener.js +21 -0
  482. package/dist/daemon/api/bridge.js +5 -5
  483. package/dist/daemon/api/handlers/analytics.d.ts +2 -0
  484. package/dist/daemon/api/handlers/analytics.js +1 -0
  485. package/dist/daemon/api/handlers/attach.js +1 -1
  486. package/dist/daemon/api/handlers/bash-jobs.js +2 -2
  487. package/dist/daemon/api/handlers/bash.js +1 -1
  488. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  489. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  490. package/dist/daemon/api/handlers/canvas.js +6 -6
  491. package/dist/daemon/api/handlers/crons.js +1 -1
  492. package/dist/daemon/api/handlers/files.d.ts +1 -1
  493. package/dist/daemon/api/handlers/files.js +1 -1
  494. package/dist/daemon/api/handlers/health.js +2 -2
  495. package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
  496. package/dist/daemon/api/handlers/hook-exec.js +1 -0
  497. package/dist/daemon/api/handlers/human-requests.js +1 -1
  498. package/dist/daemon/api/handlers/inbox.js +1 -1
  499. package/dist/daemon/api/handlers/llm.d.ts +2 -0
  500. package/dist/daemon/api/handlers/llm.js +3 -0
  501. package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
  502. package/dist/daemon/api/handlers/memory-reads.js +1 -0
  503. package/dist/daemon/api/handlers/memory.js +5 -1
  504. package/dist/daemon/api/handlers/messages.js +2 -2
  505. package/dist/daemon/api/handlers/modelauth.js +1 -1
  506. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  507. package/dist/daemon/api/handlers/node-records.d.ts +2 -0
  508. package/dist/daemon/api/handlers/node-records.js +3 -0
  509. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  510. package/dist/daemon/api/handlers/nodes.js +1 -1
  511. package/dist/daemon/api/handlers/profiles.d.ts +4 -1
  512. package/dist/daemon/api/handlers/profiles.js +1 -1
  513. package/dist/daemon/api/handlers/reports.js +5 -3
  514. package/dist/daemon/api/handlers/reviews.d.ts +1 -1
  515. package/dist/daemon/api/handlers/reviews.js +1 -1
  516. package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
  517. package/dist/daemon/api/handlers/run-routes.js +1 -0
  518. package/dist/daemon/api/handlers/runs.d.ts +9 -0
  519. package/dist/daemon/api/handlers/runs.js +1 -0
  520. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  521. package/dist/daemon/api/handlers/worktree.js +1 -1
  522. package/dist/daemon/api/map.d.ts +10 -4
  523. package/dist/daemon/api/map.js +2 -2
  524. package/dist/daemon/api/operations.d.ts +18 -0
  525. package/dist/daemon/api/operations.js +1 -0
  526. package/dist/daemon/api/principal.d.ts +42 -0
  527. package/dist/daemon/api/principal.js +1 -0
  528. package/dist/daemon/api/router.d.ts +27 -3
  529. package/dist/daemon/api/router.js +1 -1
  530. package/dist/daemon/api/server.d.ts +4 -0
  531. package/dist/daemon/api/server.js +1 -1
  532. package/dist/daemon/api/vendor-signin.d.ts +7 -0
  533. package/dist/daemon/api/vendor-signin.js +77 -0
  534. package/dist/daemon/api/viewer-presence.d.ts +3 -0
  535. package/dist/daemon/api/viewer-presence.js +1 -0
  536. package/dist/daemon/cron/armed-context.d.ts +4 -0
  537. package/dist/daemon/cron/armed-context.js +1 -1
  538. package/dist/daemon/cron/escalation.js +3 -3
  539. package/dist/daemon/cron/lease-recovery.js +1 -1
  540. package/dist/daemon/cron/sinks.js +2 -2
  541. package/dist/daemon/cron-run.d.ts +5 -5
  542. package/dist/daemon/cron-run.js +1 -1
  543. package/dist/daemon/crtrd.js +8 -7
  544. package/dist/daemon/delivery/run-delivery.d.ts +4 -0
  545. package/dist/daemon/delivery/run-delivery.js +1 -1
  546. package/dist/daemon/fleet.d.ts +1 -1
  547. package/dist/daemon/fleet.js +6 -6
  548. package/dist/daemon/human/finish.js +7 -7
  549. package/dist/daemon/joined-owner.d.ts +5 -0
  550. package/dist/daemon/joined-owner.js +1 -0
  551. package/dist/daemon/manage.js +2 -2
  552. package/dist/daemon/messaging/node-message.js +1 -1
  553. package/dist/daemon/park-activity.js +1 -1
  554. package/dist/daemon/reconcilers/bash-deadline.js +1 -1
  555. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  556. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  557. package/dist/daemon/reconcilers/delivery-lane.js +1 -1
  558. package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
  559. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  560. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  561. package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
  562. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  563. package/dist/daemon/runs/append-section.d.ts +6 -0
  564. package/dist/daemon/runs/append-section.js +2 -0
  565. package/dist/daemon/runs/observer.d.ts +5 -0
  566. package/dist/daemon/runs/observer.js +4 -0
  567. package/dist/launcher/bwrap.d.ts +4 -0
  568. package/dist/launcher/bwrap.js +2 -0
  569. package/dist/launcher/client.d.ts +2 -0
  570. package/dist/launcher/client.js +3 -0
  571. package/dist/launcher/main.d.ts +1 -0
  572. package/dist/launcher/main.js +3 -0
  573. package/dist/launcher/netrule.d.ts +1 -0
  574. package/dist/launcher/netrule.js +1 -0
  575. package/dist/launcher/seccomp.d.ts +1 -0
  576. package/dist/launcher/seccomp.js +1 -0
  577. package/dist/launcher/spec.d.ts +88 -0
  578. package/dist/launcher/spec.js +1 -0
  579. package/dist/launcher/users.d.ts +18 -0
  580. package/dist/launcher/users.js +7 -0
  581. package/dist/launcher/validate.d.ts +22 -0
  582. package/dist/launcher/validate.js +1 -0
  583. package/dist/migrations/corpus.js +3 -3
  584. package/dist/migrations/runner.js +1 -1
  585. package/dist/native/linux/addon.node +0 -0
  586. package/dist/native/linux.d.ts +29 -0
  587. package/dist/native/linux.js +1 -0
  588. package/dist/pi-extensions/broker-local.js +2 -2
  589. package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
  590. package/dist/pi-extensions/canvas-bash-valve.js +4 -7
  591. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
  592. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  593. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  594. package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
  595. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
  596. package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
  597. package/dist/pi-extensions/canvas-passive-context.js +11 -11
  598. package/dist/pi-extensions/canvas-recap.js +6 -6
  599. package/dist/pi-extensions/canvas-stophook.js +1 -1
  600. package/dist/pi-extensions/canvas-structured-output.js +4 -4
  601. package/dist/pi-extensions/canvas-tool-guide.js +1 -1
  602. package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
  603. package/dist/pi-extensions/system-prompt-entry.js +1 -0
  604. package/dist/shared/env.d.ts +5 -1
  605. package/dist/shared/env.js +1 -1
  606. package/dist/shared/strip-cd-prefix.d.ts +1 -0
  607. package/dist/shared/strip-cd-prefix.js +1 -0
  608. package/dist/types.d.ts +31 -15
  609. package/docs/cli/memory-and-preferences.md +3 -1
  610. package/docs/sdk/client.md +34 -0
  611. package/docs/sdk/errors.md +2 -0
  612. package/docs/sdk/memory.md +2 -2
  613. package/docs/sdk/streaming.md +21 -0
  614. package/package.json +18 -4
  615. package/packages/crouter-identity/dist/index.d.ts +54 -0
  616. package/packages/crouter-identity/dist/index.js +166 -0
  617. package/packages/crouter-identity/package.json +33 -0
  618. package/runtime.lock.json +34 -8
  619. package/scripts/build-native-linux.mjs +16 -0
  620. package/scripts/install-runtime.mjs +9 -7
  621. package/scripts/lib/isolation-env.mjs +42 -0
  622. package/scripts/runtime-smoke.mjs +49 -0
  623. package/src/native/linux/addon.c +249 -0
  624. package/dist/core/profiles/state-block.d.ts +0 -4
  625. package/dist/core/profiles/state-block.js +0 -3
  626. package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
  627. package/dist/core/runtime/broker/auth-reload.js +0 -1
  628. package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
  629. package/dist/core/substrate/cli-context-delivery.js +0 -1
@@ -1,9 +1,9 @@
1
- var y=Object.defineProperty;var i=(e,r)=>y(e,"name",{value:r,configurable:!0});import{envNodeId as b}from"../shared/env.js";import{defineBranch as _,defineLeaf as u}from"../core/command.js";import{InputError as d,readStdinRaw as c}from"../core/io.js";import{ApiError as k}from"../api/index.js";import{cliClient as h,rethrowAsCliError as l}from"./api-client.js";import{markStopSignal as p}from"../core/runtime/stop-signals.js";function f(){const e=b();if(e===void 0||e.trim()==="")throw new d({error:"no_node_context",message:"CRTR_NODE_ID is not set \u2014 push runs inside a canvas node.",next:"Run push from a node process spawned by the runtime."});return e.trim()}i(f,"requireCallerNode");const m={update:"report progress to subscribers",final:"finish: write the canonical result, mark the node done, close its window"},v={update:"you have progress worth surfacing to your managers while work remains in flight. Use normal delivery unless it can wait for their next real wake (--tier deferred) or needs immediate attention (--tier urgent); use push final only when the work is actually done.",final:"the work this node was spawned to do is complete and you are ready to hand back the canonical result \u2014 this writes that result, marks the node done, and closes its window, so it is the LAST thing you do here, not a progress note. Use push update while work is still in flight, and do not reach for final on a node working directly with the user: it has no manager to report up to and would close mid-conversation (the guard blocks it unless you pass --force after the user confirms)."};function q(){return u({name:"result",description:"answer a pending structured-output request with the required JSON result, or decline it",whenToUse:'your system prompt names a pending structured-output request you must answer. The value is validated against the required schema server-side; a mismatch rejects with field errors and records nothing, so fix and rerun. When the schema cannot be honestly satisfied (blocked, unavailable, bad input), pass `--decline "<reason>" --code <token>` (plus `--retryable` when the same request could succeed later) instead of inventing a value; your requester names the code tokens it accepts. For a terminal request either path IS how the node finishes \u2014 never call `crtr push final` alongside it.',help:{name:"push result",summary:"answer a pending structured-output request",params:[{kind:"stdin",name:"value",required:!1,constraint:"The JSON result. Pipe it from a single-quoted heredoc (`<<'EOF'`) to preserve literal bytes. Required unless `--decline` is passed."},{kind:"flag",name:"decline",type:"string",required:!1,constraint:"Decline instead of answering: one plain sentence on why the schema cannot be honestly satisfied (blocked, unavailable, bad input). Requires `--code`. Records a failure outcome with reason `declined` carrying the reason, code, and retryable flag, and clears the request; for a terminal request this finishes the node."},{kind:"flag",name:"code",type:"string",required:!1,constraint:"With `--decline`: one whitespace-free token (\u2264 64 chars) naming the decline class. crouter carries it verbatim; the requester validates it against the tokens it documented for you."},{kind:"flag",name:"retryable",type:"bool",required:!1,default:!1,constraint:"With `--decline`: the same request could succeed if issued again later (a transient block). Omit when the decline is final for this input."}],output:[{name:"mode",type:"string",required:!0,constraint:"Which request this answered: `terminal` finished the node; `oneoff` left it working."},{name:"result_path",type:"string",required:!0,constraint:"Absolute path of the recorded artifact: the result JSON, or the declined marker when `--decline` was passed."},{name:"declined",type:"object",required:!1,constraint:"Present only when the request was declined: { reason, code, retryable } as recorded."},{name:"report_path",type:"string",required:!0,constraint:"Absolute path of the report pushed alongside the result."},{name:"notified",type:"string[]",required:!0,constraint:"Subscriber node ids that received an inbox pointer."},{name:"transitioned",type:"object",required:!1,constraint:"Present only for a terminal request that flipped the node \u2014 { from, to } lifecycle-status transition applied server-side."}],outputKind:"object",effects:["Validates the value against the pending schema server-side; a mismatch records nothing and the request stays pending.","Writes the accepted result to nodes/<nodeId>/context/result.json (or the decline to context/declined.json) and clears the pending request.","A terminal decline records a `failure` outcome with reason `declined` whose `declined` field carries { reason, code, retryable }; the requester sees no value.","Pushes the mode-matched report: final for a terminal request (the node finishes \u2014 same effects as `push final`), update for a one-off request (the node keeps working)."]},run:i(async e=>{const r=f(),s=typeof e.decline=="string"?e.decline.trim():"",o=typeof e.code=="string"?e.code.trim():"";let a;if(s!==""){if(o==="")throw new d({error:"missing_decline_code",message:"a decline needs a code",field:"code",next:"Pass `--code <token>` \u2014 the whitespace-free token your requester documented for this decline class."});a={decline:s,code:o,retryable:e.retryable===!0}}else{if(o!==""||e.retryable===!0)throw new d({error:"decline_flags_without_decline",message:"--code and --retryable only apply with --decline",next:'Pass `--decline "<reason>"` alongside them, or drop them and submit the JSON result.'});let t=typeof e.value=="string"?e.value.trim():"";if(t===""&&(t=(await c()).trim()),t==="")throw new d({error:"missing_value",message:"no result value",field:"value",next:'Pass the JSON result as an argument or on stdin, or `--decline "<reason>" --code <token>` when the schema cannot be honestly satisfied.'});let n;try{n=JSON.parse(t)}catch(g){throw new d({error:"bad_result_json",message:`the result is not valid JSON: ${g.message}`,field:"value",next:"Pass one valid JSON value matching the requested schema."})}a={value:n}}try{const t=await h().submitResult(r,a);return t.mode==="terminal"&&p(r,"pushedFinal"),{mode:t.mode,result_path:t.result_path,report_path:t.report_path,notified:t.notified,...t.declined===void 0?{}:{declined:t.declined},...t.transitioned!==void 0?{transitioned:t.transitioned}:{},...t.worktree_auto_dropped===!0?{worktree_auto_dropped:!0,worktree_auto_dropped_path:t.worktree_auto_dropped_path}:{}}}catch(t){l(t)}},"run"),render:i(e=>{const r=e.declined,s=e.mode==="terminal"?`${r?"Decline recorded":"Result recorded"} \u2014 node finished; its engine shuts down on next stop. Nothing more to do here: STOP your turn immediately. Reply with just "Done." and nothing else.`:`${r?"One-off request declined":"One-off result recorded"} and pushed \u2014 the structured-output gate is cleared; continue working normally.`,o=r===void 0?"":`
1
+ var g=Object.defineProperty;var i=(e,r)=>g(e,"name",{value:r,configurable:!0});import{envNodeId as y}from"../shared/env.js";import{defineBranch as b,defineLeaf as u}from"../core/command.js";import{InputError as d,readStdinRaw as c}from"../core/io.js";import{ApiError as _}from"../api/index.js";import{cliClient as h,rethrowAsCliError as l}from"./api-client.js";function p(){const e=y();if(e===void 0||e.trim()==="")throw new d({error:"no_node_context",message:"CRTR_NODE_ID is not set \u2014 push runs inside a canvas node.",next:"Run push from a node process spawned by the runtime."});return e.trim()}i(p,"requireCallerNode");const f={update:"report progress to subscribers",final:"finish: write the canonical result, mark the node done, close its window"},k={update:"you have progress worth surfacing to your managers while work remains in flight. Use normal delivery unless it can wait for their next real wake (--tier deferred) or needs immediate attention (--tier urgent); use push final only when the work is actually done.",final:"the work this node was spawned to do is complete and you are ready to hand back the canonical result \u2014 this writes that result, marks the node done, and closes its window, so it is the LAST thing you do here, not a progress note. Use push update while work is still in flight, and do not reach for final on a node working directly with the user: it has no manager to report up to and would close mid-conversation (the guard blocks it unless you pass --force after the user confirms)."};function v(){return u({name:"result",description:"answer a pending structured-output request with the required JSON result, or decline it",whenToUse:'your system prompt names a pending structured-output request you must answer. The value is validated against the required schema server-side; a mismatch rejects with field errors and records nothing, so fix and rerun. When the schema cannot be honestly satisfied (blocked, unavailable, bad input), pass `--decline "<reason>" --code <token>` (plus `--retryable` when the same request could succeed later) instead of inventing a value; your requester names the code tokens it accepts. For a terminal request either path IS how the node finishes \u2014 never call `crtr push final` alongside it.',help:{name:"push result",summary:"answer a pending structured-output request",params:[{kind:"stdin",name:"value",required:!1,constraint:"The JSON result. Pipe it from a single-quoted heredoc (`<<'EOF'`) to preserve literal bytes. Required unless `--decline` is passed."},{kind:"flag",name:"decline",type:"string",required:!1,constraint:"Decline instead of answering: one plain sentence on why the schema cannot be honestly satisfied (blocked, unavailable, bad input). Requires `--code`. Records a failure outcome with reason `declined` carrying the reason, code, and retryable flag, and clears the request; for a terminal request this finishes the node."},{kind:"flag",name:"code",type:"string",required:!1,constraint:"With `--decline`: one whitespace-free token (\u2264 64 chars) naming the decline class. crouter carries it verbatim; the requester validates it against the tokens it documented for you."},{kind:"flag",name:"retryable",type:"bool",required:!1,default:!1,constraint:"With `--decline`: the same request could succeed if issued again later (a transient block). Omit when the decline is final for this input."}],output:[{name:"mode",type:"string",required:!0,constraint:"Which request this answered: `terminal` finished the node; `oneoff` left it working."},{name:"result_path",type:"string",required:!0,constraint:"Absolute path of the recorded artifact: the result JSON, or the declined marker when `--decline` was passed."},{name:"declined",type:"object",required:!1,constraint:"Present only when the request was declined: { reason, code, retryable } as recorded."},{name:"report_path",type:"string",required:!0,constraint:"Absolute path of the report pushed alongside the result."},{name:"notified",type:"string[]",required:!0,constraint:"Subscriber node ids that received an inbox pointer."},{name:"transitioned",type:"object",required:!1,constraint:"Present only for a terminal request that flipped the node \u2014 { from, to } lifecycle-status transition applied server-side."}],outputKind:"object",effects:["Validates the value against the pending schema server-side; a mismatch records nothing and the request stays pending.","Writes the accepted result to nodes/<nodeId>/context/result.json (or the decline to context/declined.json) and clears the pending request.","A terminal decline records a `failure` outcome with reason `declined` whose `declined` field carries { reason, code, retryable }; the requester sees no value.","Pushes the mode-matched report: final for a terminal request (the node finishes \u2014 same effects as `push final`), update for a one-off request (the node keeps working)."]},run:i(async e=>{const r=p(),s=typeof e.decline=="string"?e.decline.trim():"",o=typeof e.code=="string"?e.code.trim():"";let a;if(s!==""){if(o==="")throw new d({error:"missing_decline_code",message:"a decline needs a code",field:"code",next:"Pass `--code <token>` \u2014 the whitespace-free token your requester documented for this decline class."});a={decline:s,code:o,retryable:e.retryable===!0}}else{if(o!==""||e.retryable===!0)throw new d({error:"decline_flags_without_decline",message:"--code and --retryable only apply with --decline",next:'Pass `--decline "<reason>"` alongside them, or drop them and submit the JSON result.'});let t=typeof e.value=="string"?e.value.trim():"";if(t===""&&(t=(await c()).trim()),t==="")throw new d({error:"missing_value",message:"no result value",field:"value",next:'Pass the JSON result as an argument or on stdin, or `--decline "<reason>" --code <token>` when the schema cannot be honestly satisfied.'});let n;try{n=JSON.parse(t)}catch(w){throw new d({error:"bad_result_json",message:`the result is not valid JSON: ${w.message}`,field:"value",next:"Pass one valid JSON value matching the requested schema."})}a={value:n}}try{const t=await h().submitResult(r,a);return{mode:t.mode,result_path:t.result_path,report_path:t.report_path,notified:t.notified,...t.declined===void 0?{}:{declined:t.declined},...t.transitioned!==void 0?{transitioned:t.transitioned}:{},...t.worktree_auto_dropped===!0?{worktree_auto_dropped:!0,worktree_auto_dropped_path:t.worktree_auto_dropped_path}:{}}}catch(t){l(t)}},"run"),render:i(e=>{const r=e.declined,s=e.mode==="terminal"?`${r?"Decline recorded":"Result recorded"} \u2014 node finished; its engine shuts down on next stop. Nothing more to do here: STOP your turn immediately. Reply with just "Done." and nothing else.`:`${r?"One-off request declined":"One-off result recorded"} and pushed \u2014 the structured-output gate is cleared; continue working normally.`,o=r===void 0?"":`
2
2
  - code: ${r.code} (${r.retryable?"retryable":"not retryable"})`;return`${s}
3
3
 
4
4
  - ${r?"declined":"result"}: ${e.result_path}${o}
5
- - report: ${e.report_path}`},"render")})}i(q,"makeResultLeaf");function w(e){return u({name:e,description:m[e],whenToUse:v[e],help:{name:`push ${e}`,summary:m[e],params:[{kind:"stdin",name:"body",required:!0,constraint:"Report body (markdown). Pipe it from a single-quoted heredoc (`<<'EOF'`) to preserve literal bytes."},...e==="update"?[{kind:"flag",name:"tier",type:"enum",choices:["deferred","normal","urgent"],required:!1,default:"normal",constraint:"Delivery urgency: deferred holds for the receiver\u2019s next non-deferred wake; normal wakes normally; urgent steers a live receiver and wakes an idle receiver."}]:[{kind:"flag",name:"force",type:"bool",required:!1,default:!1,constraint:"Override the guard that blocks `push final` on a node the user is attending (a resident with no one to report up to). Only pass this after the user explicitly confirms they want this node finished."}]],output:[{name:"report_path",type:"string",required:!0,constraint:"Absolute path of the written report."},{name:"notified",type:"string[]",required:!0,constraint:"Subscriber node ids that received an inbox pointer."},...e==="final"?[{name:"transitioned",type:"object",required:!1,constraint:"Present only for a final that flipped the node \u2014 { from, to } lifecycle-status transition applied server-side."},{name:"worktree_auto_dropped",type:"boolean",required:!1,constraint:"Present only when the server closed this node\u2019s managed-worktree record without requiring `node worktree close`; cleanup of an existing checkout remains pending (see worktree_auto_dropped_path)."},{name:"worktree_auto_dropped_path",type:"string",required:!1,constraint:"Present only alongside worktree_auto_dropped: the closed worktree path; an existing checkout remains until pending cleanup."}]:[]],outputKind:"object",effects:["Writes nodes/<nodeId>/reports/<ts>-<kind>.md (server-side).","Appends one inbox pointer per subscriber.",...e==="final"?["Marks the node done (status + intent) server-side; its engine shuts down on next stop.","When this node owns a clean managed worktree already contained in its local base, the server closes its record with cleanup pending instead of blocking on `node worktree close`. A clean worktree whose exact tip exists on any branch on origin may also finalize while retaining its branch and checkout; uncommitted changes or a tip absent from origin still block with open_managed_worktree."]:[]]},run:i(async r=>{const s=f();let o=typeof r.body=="string"?r.body.trim():"";if(o===""&&(o=(await c()).trim()),o==="")throw new d({error:"missing_body",message:"no report body",field:"body",next:"Pass the body as an argument or on stdin."});const a=h();if(e==="final"&&r.force!==!0){let t=null;try{t=await a.getNode(s)}catch(n){n instanceof k&&n.status===404||l(n)}if(t!==null&&t.lifecycle==="resident"&&t.edges.subscribers.length===0)throw new d({error:"no_final_recipient",message:"This node is working directly with the user \u2014 it has no manager to submit a final result to. `push final` would end the conversation mid-stream.",next:'You almost certainly do NOT need to finish here \u2014 just keep working with the user. If the user has explicitly asked you to finish and close this node, confirm with them first, then rerun with `crtr push final --force "<result>"`.'})}try{const t=r.tier,n=await a.pushReport(s,{tier:e,body:o,...t===void 0?{}:{delivery_tier:t}});return e==="final"&&p(s,"pushedFinal"),{report_path:n.report_path,notified:n.notified,...n.transitioned!==void 0?{transitioned:n.transitioned}:{},...n.worktree_auto_dropped===!0?{worktree_auto_dropped:!0,worktree_auto_dropped_path:n.worktree_auto_dropped_path}:{}}}catch(t){l(t)}},"run"),render:i(r=>{const s=Array.isArray(r.notified)?r.notified.length:0,o=e==="final"?'Result recorded \u2014 node finished; its engine shuts down on next stop. Nothing more to do here: STOP your turn immediately. Reply with just "Done." and nothing else.':`Progress report fanned to ${s} subscriber(s).`,a=r.worktree_auto_dropped===!0?`
5
+ - report: ${e.report_path}`},"render")})}i(v,"makeResultLeaf");function m(e){return u({name:e,description:f[e],whenToUse:k[e],help:{name:`push ${e}`,summary:f[e],params:[{kind:"stdin",name:"body",required:!0,constraint:"Report body (markdown). Pipe it from a single-quoted heredoc (`<<'EOF'`) to preserve literal bytes."},...e==="update"?[{kind:"flag",name:"tier",type:"enum",choices:["deferred","normal","urgent"],required:!1,default:"normal",constraint:"Delivery urgency: deferred holds for the receiver\u2019s next non-deferred wake; normal wakes normally; urgent steers a live receiver and wakes an idle receiver."}]:[{kind:"flag",name:"force",type:"bool",required:!1,default:!1,constraint:"Override the guard that blocks `push final` on a node the user is attending (a resident with no one to report up to). Only pass this after the user explicitly confirms they want this node finished."}]],output:[{name:"report_path",type:"string",required:!0,constraint:"Absolute path of the written report."},{name:"notified",type:"string[]",required:!0,constraint:"Subscriber node ids that received an inbox pointer."},...e==="final"?[{name:"transitioned",type:"object",required:!1,constraint:"Present only for a final that flipped the node \u2014 { from, to } lifecycle-status transition applied server-side."},{name:"worktree_auto_dropped",type:"boolean",required:!1,constraint:"Present only when the server closed this node\u2019s managed-worktree record without requiring `node worktree close`; cleanup of an existing checkout remains pending (see worktree_auto_dropped_path)."},{name:"worktree_auto_dropped_path",type:"string",required:!1,constraint:"Present only alongside worktree_auto_dropped: the closed worktree path; an existing checkout remains until pending cleanup."}]:[]],outputKind:"object",effects:["Writes nodes/<nodeId>/reports/<ts>-<kind>.md (server-side).","Appends one inbox pointer per subscriber.",...e==="final"?["Marks the node done (status + intent) server-side; its engine shuts down on next stop.","When this node owns a clean managed worktree already contained in its local base, the server closes its record with cleanup pending instead of blocking on `node worktree close`. A clean worktree whose exact tip exists on any branch on origin may also finalize while retaining its branch and checkout; uncommitted changes or a tip absent from origin still block with open_managed_worktree."]:[]]},run:i(async r=>{const s=p();let o=typeof r.body=="string"?r.body.trim():"";if(o===""&&(o=(await c()).trim()),o==="")throw new d({error:"missing_body",message:"no report body",field:"body",next:"Pass the body as an argument or on stdin."});const a=h();if(e==="final"&&r.force!==!0){let t=null;try{t=await a.getNode(s)}catch(n){n instanceof _&&n.status===404||l(n)}if(t!==null&&t.lifecycle==="resident"&&t.edges.subscribers.length===0)throw new d({error:"no_final_recipient",message:"This node is working directly with the user \u2014 it has no manager to submit a final result to. `push final` would end the conversation mid-stream.",next:'You almost certainly do NOT need to finish here \u2014 just keep working with the user. If the user has explicitly asked you to finish and close this node, confirm with them first, then rerun with `crtr push final --force "<result>"`.'})}try{const t=r.tier,n=await a.pushReport(s,{tier:e,body:o,...t===void 0?{}:{delivery_tier:t}});return{report_path:n.report_path,notified:n.notified,...n.transitioned!==void 0?{transitioned:n.transitioned}:{},...n.worktree_auto_dropped===!0?{worktree_auto_dropped:!0,worktree_auto_dropped_path:n.worktree_auto_dropped_path}:{}}}catch(t){l(t)}},"run"),render:i(r=>{const s=Array.isArray(r.notified)?r.notified.length:0,o=e==="final"?'Result recorded \u2014 node finished; its engine shuts down on next stop. Nothing more to do here: STOP your turn immediately. Reply with just "Done." and nothing else.':`Progress report fanned to ${s} subscriber(s).`,a=r.worktree_auto_dropped===!0?`
6
6
 
7
7
  Closed a clean managed-worktree record at ${String(r.worktree_auto_dropped_path)} \u2014 nothing to land; cleanup remains pending if the checkout still exists.`:"";return`${o}
8
8
 
9
- - report: ${r.report_path}${a}`},"render")})}i(w,"makePushLeaf");function A(){return _({name:"push",rootEntry:{concept:"the one verb up the graph \u2014 a node reports to whoever subscribes to it",desc:"push an update or final report to your subscribers",useWhen:"sharing progress, raising an alert, or finishing your work"},help:{name:"push",summary:"push a report to your subscribers",model:"A push writes a markdown report to the node's reports/ history and fans a lightweight pointer to every subscriber's inbox. Delivery inlines reports under 1,000 characters; each report ref is read with `crtr canvas history read <ref>`. Nothing is pushed automatically \u2014 the feed contains only what a node pushes explicitly, so push whenever you want a manager to see something. Pipe markdown via a single-quoted heredoc so it reaches the report literally. `push final` is how ANY node finishes: write the canonical result, mark done, close the window."},children:[w("update"),w("final"),q()]})}i(A,"registerPush");export{A as registerPush};
9
+ - report: ${r.report_path}${a}`},"render")})}i(m,"makePushLeaf");function R(){return b({name:"push",rootEntry:{concept:"the one verb up the graph \u2014 a node reports to whoever subscribes to it",desc:"push an update or final report to your subscribers",useWhen:"sharing progress, raising an alert, or finishing your work"},help:{name:"push",summary:"push a report to your subscribers",model:"A push writes a markdown report to the node's reports/ history and fans a lightweight pointer to every subscriber's inbox. Delivery inlines reports under 1,000 characters; each report ref is read with `crtr canvas history read <ref>`. Nothing is pushed automatically \u2014 the feed contains only what a node pushes explicitly, so push whenever you want a manager to see something. Pipe markdown via a single-quoted heredoc so it reaches the report literally. `push final` is how ANY node finishes: write the canonical result, mark done, close the window."},children:[m("update"),m("final"),v()]})}i(R,"registerPush");export{R as registerPush};
@@ -1 +1 @@
1
- var s=Object.defineProperty;var o=(e,t)=>s(e,"name",{value:t,configurable:!0});import{defineLeaf as i}from"../core/command.js";import{InputError as a}from"../core/io.js";import{inspectorCore as c}from"../core/inspector/core.js";import{inspectorText as p}from"../core/inspector/text.js";import{inspectorTui as d}from"../core/inspector/tui.js";import{inTmux as u}from"../core/runtime/placement-tmux.js";import{runInspector as m}from"../core/inspector/host.js";const x=i({name:"inspect",description:"host the native Inspector for one node",whenToUse:"you want a live native screen for a node\u2019s overview, raw record, owner-scoped crons, and live background bash jobs. Use node inspect show for the underlying one-shot data read instead.",help:{name:"surface inspect",summary:"host the native Inspector in this pane (the attach viewer opens it as a tmux popup)",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id or resolvable reference to inspect."},{kind:"flag",name:"section",type:"enum",choices:["overview","schedule","jobs","raw"],required:!1,default:"overview",constraint:"Section focused when the Inspector opens."}],output:[],outputKind:"object",effects:["Reads node, cron, and background bash job data through crtr subprocesses and crtrd. Takes over the hosting pane (or popup) until it quits."]},run:o(async e=>{const t=e.node,n=e.section??"overview",r=o(()=>m(c,d,p,{options:{target:t,section:n}}),"host");if(!process.stdin.isTTY||!process.stdout.isTTY){await r();return}if(!u())throw new a({error:"not_in_tmux",message:"Inspector is tmux-only for interactive use.",next:"Run it inside tmux, or pipe `crtr surface inspect <node>` for a static snapshot."});await r()},"run"),render:o(()=>"","render")});export{x as surfaceInspectLeaf};
1
+ var a=Object.defineProperty;var o=(e,t)=>a(e,"name",{value:t,configurable:!0});import{defineLeaf as i}from"../core/command.js";import{InputError as c}from"../core/io.js";import{inspectorCore as p}from"../core/inspector/core.js";import{inspectorText as d}from"../core/inspector/text.js";import{inspectorTui as u}from"../core/inspector/tui.js";import{inTmux as f}from"../core/runtime/placement-tmux.js";import{runInspector as m}from"../core/inspector/host.js";const x=i({name:"inspect",description:"host the native Inspector for one node",whenToUse:"you want a live native screen for a node\u2019s overview, raw record, owner-scoped crons, and live background bash jobs. Use node inspect show for the underlying one-shot data read instead.",help:{name:"surface inspect",summary:"host the native Inspector in this pane (the attach viewer opens it as a tmux popup)",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id or resolvable reference to inspect."},{kind:"flag",name:"section",type:"enum",choices:["overview","schedule","jobs","raw"],required:!1,default:"overview",constraint:"Section focused when the Inspector opens."},{kind:"flag",name:"read-only",type:"bool",required:!1,constraint:"Offer no cron cancel or job stop, so the Inspector cannot change canvas state."}],output:[],outputKind:"object",effects:["Reads node, cron, and background bash job data through crtr subprocesses and crtrd. Takes over the hosting pane (or popup) until it quits."]},run:o(async e=>{const t=e.node,r=e.section??"overview",s=e.readOnly===!0?"true":"false",n=o(()=>m(p,u,d,{options:{target:t,section:r,readOnly:s}}),"host");if(!process.stdin.isTTY||!process.stdout.isTTY){await n();return}if(!f())throw new c({error:"not_in_tmux",message:"Inspector is tmux-only for interactive use.",next:"Run it inside tmux, or pipe `crtr surface inspect <node>` for a static snapshot."});await n()},"run"),render:o(()=>"","render")});export{x as surfaceInspectLeaf};
@@ -1 +1 @@
1
- var s=Object.defineProperty;var e=(n,t)=>s(n,"name",{value:t,configurable:!0});import{defineBranch as o}from"../../core/command.js";const r={concept:"crtr configuration, diagnostics, and self-management",desc:"settings, config, connect, setup, tutorial, doctor, context, sync, migrate, update, version, feedback, logs, support, daemon",useWhen:"managing the crtr installation, inspecting diagnostics, or operating the crtrd supervisor process"},a={name:"sys",summary:"crtr system configuration, settings, diagnostics, and self-management",model:"Configuration and settings own durable behavior; diagnostics and support observe it. Setup, migration, sync, and update change installed or generated state, while daemon control owns the supervisor lifecycle."};function d(n){return o({name:"sys",rootEntry:r,help:{...a},children:n})}e(d,"defineSysBranch");export{d as defineSysBranch};
1
+ var o=Object.defineProperty;var t=(e,n)=>o(e,"name",{value:n,configurable:!0});import{defineBranch as r}from"../../core/command.js";const s={concept:"crtr configuration, diagnostics, and self-management",desc:"settings, config, connect, setup, tutorial, doctor, context, sync, migrate, join, update, version, feedback, logs, support, daemon",useWhen:"managing the crtr installation, inspecting diagnostics, operating the crtrd supervisor process, or registering a hosted runtime with its directory before first boot"},i={name:"sys",summary:"crtr system configuration, settings, diagnostics, and self-management",model:"Configuration and settings own durable behavior; diagnostics and support observe it. Setup, migration, sync, and update change installed or generated state, and join registers a stopped runtime with its directory from an enrollment token, while daemon control owns the supervisor lifecycle."};function d(e){return r({name:"sys",rootEntry:s,help:{...i},children:e})}t(d,"defineSysBranch");export{d as defineSysBranch};
@@ -1 +1 @@
1
- var S=Object.defineProperty;var i=(t,e)=>S(t,"name",{value:e,configurable:!0});import{defineBranch as j,defineLeaf as u}from"../../core/command.js";import{InvalidRawSettingsError as T,readConfig as f,readRawSettingsForTarget as q,replaceRawSettingsForTarget as L,updateConfig as R,persistModelLadders as P,configPath as N}from"../../core/config.js";import{usage as o,notFound as g}from"../../core/errors.js";import{requireScopeRoot as _}from"../../core/scope.js";import{resolveScope as h}from"./shared.js";import{resolveProfileOperand as O}from"../../core/profiles/manifest.js";import{SettingsRevisionConflictError as E}from"../../core/scoped-state/settings.js";import{InputError as l}from"../../core/io.js";import{SCOPE_CONFIG_KEYS as C,USER_SETTINGS as U,findUserSetting as m}from"../../core/user-settings.js";const $=C.join(", "),J=U.map(t=>`${t.key} (${t.valueConstraint})`).join(", "),M=new Set(["anthropic","openai"]),I=new Set(["ultra","strong","medium","light"]);function y(t){return M.has(t)}i(y,"isModelProvider");function x(t){return I.has(t)}i(x,"isModelStrength");function w(t,e){const n=e.split(".");let r=t;for(const s of n){if(r===null||typeof r!="object")return;r=r[s]}return r}i(w,"getNestedValue");function A(t){return t==="true"?!0:t==="false"?!1:/^-?\d+$/.test(t)?parseInt(t,10):t}i(A,"parseConfigValue");function b(t,e){if(t.split(".",1)[0]==="brokerThresholds"&&e!=="user")throw o("brokerThresholds are available only in user scope")}i(b,"assertUserScopeBrokerThresholds");function v(t,e){if(t.split(".",1)[0]==="lifecycle"&&e!=="user")throw o("lifecycle settings are available only in user scope")}i(v,"assertUserScopeLifecycle");function F(t,e){if(t==="working_gerunds"&&e!=="user")throw o("working_gerunds is available only in user scope")}i(F,"assertWorkingGerundsScope");function K(t,e){if(t==="whip_messages"&&e!=="user")throw o("whip_messages are available only in user scope")}i(K,"assertWhipMessagesScope");function D(t,e){if(m(t)!==void 0&&e!=="user")throw o(`${t} is available only in user scope`)}i(D,"assertUserSettingScope");function G(t,e){const n=t.split(".");if(n[0]!=="modelLadders")return null;if(n.length===2&&n[1]==="defaultProvider"){if(!y(e))throw o("modelLadders.defaultProvider must be anthropic or openai");return{defaultProvider:e}}if(n.length===3){const r=n[1],s=n[2];if(!y(r))throw o("modelLadders provider must be anthropic or openai");if(!x(s))throw o("modelLadders strength must be ultra, strong, medium, or light");if(e.trim()==="")throw o(`modelLadders.${r}.${s} cannot be empty`);return{[r]:{[s]:e}}}throw o(`unsupported key path for set: ${t}`)}i(G,"modelLadderPatch");function k(t){const e=t.scope;if(e==="project")throw o("project settings remain a JSON file; use `crtr sys config set` or `crtr sys config path --scope project`.");const n=t.profile;if(e==="user"){if(n!==void 0)throw o("--profile is available only with --scope profile.");return{scope:"user"}}if(n===void 0)throw o("--profile is required with --scope profile.");return{scope:"profile",profileId:O(n).profileId}}i(k,"rawSettingsTarget");function Q(t){let e;try{e=JSON.parse(t)}catch{throw new l({error:"invalid_request",message:"stdin must be valid JSON",field:"stdin",next:"Pipe one complete JSON object on stdin."})}if(e===null||typeof e!="object"||Array.isArray(e))throw new l({error:"invalid_request",message:"stdin must be a JSON object",field:"stdin",next:"Pipe one complete JSON object on stdin."});return e}i(Q,"parseRawSettings");function W(t,e,n,r){const s=e.split("."),c=s[0];if(e==="working_gerunds"||e==="whip_messages"){let a;try{a=JSON.parse(n)}catch{throw o(`${e} must be a JSON array of non-empty strings`)}if(!Array.isArray(a)||a.length===0||!a.every(d=>typeof d=="string"&&d.trim()!==""))throw o(`${e} must be a non-empty JSON array of non-empty strings`);t[e]=a.map(d=>d.trim());return}if(c==="keybindings")throw o("keybindings are edited only through `crtr sys settings`");if(c==="modelLadders")throw o("modelLadders keys are written through persistModelLadders, not this path");const p=m(e);if(p!==void 0){const a=p.setFromString(t,n);if(a!==null)throw o(a);return}if(c==="brokerThresholds"){if(s.length!==2||s[1]!=="warning"&&s[1]!=="automaticReviveCap")throw o("brokerThresholds key must be warning or automaticReviveCap");if(typeof r!="number"||!Number.isFinite(r)||r<1)throw o(`brokerThresholds.${s[1]} must be an integer >= 1`);const a=Math.floor(r);if(s[1]==="warning"&&a>t.brokerThresholds.automaticReviveCap)throw o("brokerThresholds.warning must be <= brokerThresholds.automaticReviveCap");if(s[1]==="automaticReviveCap"&&a<t.brokerThresholds.warning)throw o("brokerThresholds.automaticReviveCap must be >= brokerThresholds.warning");t.brokerThresholds[s[1]]=a;return}if(c==="lifecycle"){if(s.length!==2||s[1]!=="unattendedParkMs")throw o("lifecycle key must be unattendedParkMs");if(typeof r!="number"||!Number.isFinite(r)||r<1)throw o("lifecycle.unattendedParkMs must be an integer >= 1");t.lifecycle.unattendedParkMs=Math.floor(r);return}throw o(`unsupported key path for set: ${e}`)}i(W,"setNestedValue");const B=u({name:"get",description:"read a config value by key",whenToUse:"you want to inspect one config value \u2014 including the whole user keybindings object \u2014 optionally from a specific scope. Use sys settings to edit keybindings and sys config set for supported scalar settings.",help:{name:"sys config get",summary:"read a config value by dotted key",params:[{kind:"positional",name:"key",type:"string",required:!0,constraint:`Dotted key path. Top-level keys: ${$}. brokerThresholds and lifecycle are user-only; keybindings is readable only as the whole user-scope object and editable only through sys settings.`},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Scope to read from. Default: user."}],output:[{name:"key",type:"string",required:!0,constraint:"Echo of input key."},{name:"value",type:"unknown",required:!0,constraint:"The resolved value. Type depends on the key."},{name:"scope",type:"string",required:!0,constraint:"Scope the value was read from."}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>{const e=t.key,n=h(t.scope);if(b(e,n),v(e,n),e.startsWith("keybindings.")||e==="keybindings"&&n!=="user")throw g("keybindings are available only as the whole user-scope object");const r=f(n),s=w(r,e);if(s===void 0)throw g(`config key not found: ${e}`);return{key:e,value:s,scope:n}},"run")}),H=u({name:"set",description:"write a config value by key",whenToUse:"you want to change a supported crtr setting in user or project scope. Use sys settings instead for keybindings, and sys config get to inspect values.",help:{name:"sys config set",summary:"write a config value by dotted key",params:[{kind:"positional",name:"key",type:"string",required:!0,constraint:`Dotted key path. User-scope scalar settings: ${J}. Also supported: working_gerunds and whip_messages (non-empty JSON string arrays), brokerThresholds.warning and brokerThresholds.automaticReviveCap (user scope; integer >= 1), lifecycle.unattendedParkMs (user scope; integer ms >= 1), modelLadders.defaultProvider, and modelLadders.<anthropic|openai>.<ultra|strong|medium|light>. Keybindings are edited only through sys settings. For arbitrary raw user or profile documents, use sys config get-raw and set-raw.`},{kind:"flag",name:"value",type:"string",required:!0,constraint:"value VALUE \u2014 string, required. working_gerunds and whip_messages accept JSON arrays; other values are stored as-is if quoted and coerced to number or boolean when unambiguous."},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Scope to write to. Default: user. Project scope is supported only for modelLadders."}],output:[{name:"value",type:"unknown",required:!0,constraint:"Resolved value as written after parsing and setting-specific coercion."},{name:"scope",type:"string",required:!0,constraint:"Scope the value was written to."}],outputKind:"object",effects:["Writes the updated value through the target scope\u2019s configuration storage."]},run:i(async t=>{const e=t.key,n=t.value,r=h(t.scope);b(e,r),v(e,r),F(e,r),K(e,r),D(e,r);const s=A(n),c=G(e,n),p=c!==null?(P(_(r),c),f(r)):R(r,d=>W(d,e,n,s));return{value:w(p,e),scope:r}},"run")}),V=u({name:"get-raw",description:"read one raw SQL-backed settings document and revision",whenToUse:"you need the exact stored user or profile settings document before replacing it with set-raw.",help:{name:"sys config get-raw",summary:"read one raw user or profile settings document",params:[{kind:"flag",name:"scope",type:"enum",choices:["user","profile","project"],required:!0,constraint:"SQL-backed target: user or profile. project is rejected because its settings remain a JSON file."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target. Required with --scope profile; rejected with --scope user or project."}],output:[{name:"revision",type:"string",required:!0,constraint:"Opaque revision token for set-raw. absent means the settings row does not exist."},{name:"settings",type:"object | null",required:!0,constraint:"Exact stored settings document, or null when no row exists."}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>q(k(t)),"run")}),z=u({name:"set-raw",description:"replace one raw SQL-backed settings document at a revision",whenToUse:"you have a complete user or profile settings document from get-raw and must replace it without losing a concurrent change.",help:{name:"sys config set-raw",summary:"atomically replace one raw user or profile settings document",params:[{kind:"flag",name:"scope",type:"enum",choices:["user","profile","project"],required:!0,constraint:"SQL-backed target: user or profile. project is rejected because its settings remain a JSON file."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target. Required with --scope profile; rejected with --scope user or project."},{kind:"flag",name:"if-revision",type:"string",required:!0,constraint:"Revision returned by get-raw. Required; use absent only when get-raw reported no settings row."},{kind:"stdin",name:"settings",required:!0,allowPositional:!1,constraint:"One complete JSON object. It replaces the document exactly; values are not normalized or merged."}],output:[{name:"revision",type:"string",required:!0,constraint:"Revision token of the stored document after this operation."},{name:"changed",type:"boolean",required:!0,constraint:"Whether the stored document changed."}],outputKind:"object",effects:["Atomically replaces the SQL-backed settings document only when --if-revision matches its current revision."]},run:i(async t=>{const e=k(t),n=Q(t.settings);try{return L(e,n,t.ifRevision)}catch(r){throw r instanceof E?new l({error:"settings_revision_conflict",message:"settings changed since the supplied revision",field:"if_revision",next:"Run `crtr sys config get-raw` again, reapply the intended transformation, and retry with its revision."}):r instanceof T?new l({error:"invalid_settings",message:r.message,field:"stdin",next:"Correct the document so crouter can merge it into resolved settings, then retry with a fresh revision."}):r}},"run")}),Y=u({name:"path",description:"print the project config.json path",whenToUse:"you need the project config.json path for inspection or backup. User and profile settings use get-raw and set-raw instead.",help:{name:"sys config path",summary:"print the project config.json path",params:[{kind:"flag",name:"scope",type:"enum",choices:["project","user","profile"],required:!1,constraint:"Project is the only path-backed settings scope. user and profile are rejected because they use SQL-backed get-raw and set-raw. Default: project."}],output:[{name:"paths",type:"object[]",required:!0,constraint:'One {scope: "project", path} entry when the current project has a config file; otherwise empty.'}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>{const e=t.scope;if(e==="user"||e==="profile")throw o(`${e} settings are SQL-backed; use \`crtr sys config get-raw --scope ${e}\` instead.`);const n=N("project");return{paths:n===null?[]:[{scope:"project",path:n}]}},"run")}),ce=j({name:"config",description:"read and write configuration",whenToUse:"inspecting crtr settings, changing supported scalar values, replacing complete raw user or profile settings documents, or locating a project config.json. Keybinding changes belong in sys settings.",help:{name:"sys config",summary:"read and write crtr configuration, including model ladders and raw SQL-backed user/profile settings",model:"get and set resolve individual settings. get-raw and set-raw read and replace complete user or profile documents with a revision precondition. path applies only to project config.json."},children:[B,H,V,z,Y]});export{ce as configBranch};
1
+ var j=Object.defineProperty;var i=(t,e)=>j(t,"name",{value:e,configurable:!0});import{defineBranch as T,defineLeaf as u}from"../../core/command.js";import{requirePersonCli as p}from"../broker-permissions.js";import{InvalidRawSettingsError as q,readConfig as g,readRawSettingsForTarget as L,replaceRawSettingsForTarget as R,updateConfig as P,persistModelLadders as N,configPath as _}from"../../core/config.js";import{usage as o,notFound as h}from"../../core/errors.js";import{requireScopeRoot as O}from"../../core/scope.js";import{resolveScope as m}from"./shared.js";import{resolveProfileOperand as C}from"../../core/profiles/manifest.js";import{SettingsRevisionConflictError as E}from"../../core/scoped-state/settings.js";import{InputError as f}from"../../core/io.js";import{SCOPE_CONFIG_KEYS as U,USER_SETTINGS as $,findUserSetting as y}from"../../core/user-settings.js";const J=U.join(", "),M=$.map(t=>`${t.key} (${t.valueConstraint})`).join(", "),I=new Set(["anthropic","openai"]),x=new Set(["ultra","strong","medium","light"]);function w(t){return I.has(t)}i(w,"isModelProvider");function A(t){return x.has(t)}i(A,"isModelStrength");function b(t,e){const n=e.split(".");let r=t;for(const s of n){if(r===null||typeof r!="object")return;r=r[s]}return r}i(b,"getNestedValue");function F(t){return t==="true"?!0:t==="false"?!1:/^-?\d+$/.test(t)?parseInt(t,10):t}i(F,"parseConfigValue");function v(t,e){if(t.split(".",1)[0]==="brokerThresholds"&&e!=="user")throw o("brokerThresholds are available only in user scope")}i(v,"assertUserScopeBrokerThresholds");function k(t,e){if(t.split(".",1)[0]==="lifecycle"&&e!=="user")throw o("lifecycle settings are available only in user scope")}i(k,"assertUserScopeLifecycle");function K(t,e){if(t==="working_gerunds"&&e!=="user")throw o("working_gerunds is available only in user scope")}i(K,"assertWorkingGerundsScope");function D(t,e){if(t==="whip_messages"&&e!=="user")throw o("whip_messages are available only in user scope")}i(D,"assertWhipMessagesScope");function G(t,e){if(y(t)!==void 0&&e!=="user")throw o(`${t} is available only in user scope`)}i(G,"assertUserSettingScope");function Q(t,e){const n=t.split(".");if(n[0]!=="modelLadders")return null;if(n.length===2&&n[1]==="defaultProvider"){if(!w(e))throw o("modelLadders.defaultProvider must be anthropic or openai");return{defaultProvider:e}}if(n.length===3){const r=n[1],s=n[2];if(!w(r))throw o("modelLadders provider must be anthropic or openai");if(!A(s))throw o("modelLadders strength must be ultra, strong, medium, or light");if(e.trim()==="")throw o(`modelLadders.${r}.${s} cannot be empty`);return{[r]:{[s]:e}}}throw o(`unsupported key path for set: ${t}`)}i(Q,"modelLadderPatch");function S(t){const e=t.scope;if(e==="project")throw o("project settings remain a JSON file; use `crtr sys config set` or `crtr sys config path --scope project`.");const n=t.profile;if(e==="user"){if(n!==void 0)throw o("--profile is available only with --scope profile.");return{scope:"user"}}if(n===void 0)throw o("--profile is required with --scope profile.");return{scope:"profile",profileId:C(n).profileId}}i(S,"rawSettingsTarget");function W(t){let e;try{e=JSON.parse(t)}catch{throw new f({error:"invalid_request",message:"stdin must be valid JSON",field:"stdin",next:"Pipe one complete JSON object on stdin."})}if(e===null||typeof e!="object"||Array.isArray(e))throw new f({error:"invalid_request",message:"stdin must be a JSON object",field:"stdin",next:"Pipe one complete JSON object on stdin."});return e}i(W,"parseRawSettings");function B(t,e,n,r){const s=e.split("."),c=s[0];if(e==="working_gerunds"||e==="whip_messages"){let a;try{a=JSON.parse(n)}catch{throw o(`${e} must be a JSON array of non-empty strings`)}if(!Array.isArray(a)||a.length===0||!a.every(d=>typeof d=="string"&&d.trim()!==""))throw o(`${e} must be a non-empty JSON array of non-empty strings`);t[e]=a.map(d=>d.trim());return}if(c==="keybindings")throw o("keybindings are edited only through `crtr sys settings`");if(c==="modelLadders")throw o("modelLadders keys are written through persistModelLadders, not this path");const l=y(e);if(l!==void 0){const a=l.setFromString(t,n);if(a!==null)throw o(a);return}if(c==="brokerThresholds"){if(s.length!==2||s[1]!=="warning"&&s[1]!=="automaticReviveCap")throw o("brokerThresholds key must be warning or automaticReviveCap");if(typeof r!="number"||!Number.isFinite(r)||r<1)throw o(`brokerThresholds.${s[1]} must be an integer >= 1`);const a=Math.floor(r);if(s[1]==="warning"&&a>t.brokerThresholds.automaticReviveCap)throw o("brokerThresholds.warning must be <= brokerThresholds.automaticReviveCap");if(s[1]==="automaticReviveCap"&&a<t.brokerThresholds.warning)throw o("brokerThresholds.automaticReviveCap must be >= brokerThresholds.warning");t.brokerThresholds[s[1]]=a;return}if(c==="lifecycle"){if(s.length!==2||s[1]!=="unattendedParkMs")throw o("lifecycle key must be unattendedParkMs");if(typeof r!="number"||!Number.isFinite(r)||r<1)throw o("lifecycle.unattendedParkMs must be an integer >= 1");t.lifecycle.unattendedParkMs=Math.floor(r);return}throw o(`unsupported key path for set: ${e}`)}i(B,"setNestedValue");const H=u({name:"get",description:"read a config value by key",whenToUse:"you want to inspect one config value \u2014 including the whole user keybindings object \u2014 optionally from a specific scope. Use sys settings to edit keybindings and sys config set for supported scalar settings.",help:{name:"sys config get",summary:"read a config value by dotted key",params:[{kind:"positional",name:"key",type:"string",required:!0,constraint:`Dotted key path. Top-level keys: ${J}. brokerThresholds and lifecycle are user-only; keybindings is readable only as the whole user-scope object and editable only through sys settings.`},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Scope to read from. Default: user."}],output:[{name:"key",type:"string",required:!0,constraint:"Echo of input key."},{name:"value",type:"unknown",required:!0,constraint:"The resolved value. Type depends on the key."},{name:"scope",type:"string",required:!0,constraint:"Scope the value was read from."}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>{p();const e=t.key,n=m(t.scope);if(v(e,n),k(e,n),e.startsWith("keybindings.")||e==="keybindings"&&n!=="user")throw h("keybindings are available only as the whole user-scope object");const r=g(n),s=b(r,e);if(s===void 0)throw h(`config key not found: ${e}`);return{key:e,value:s,scope:n}},"run")}),V=u({name:"set",description:"write a config value by key",whenToUse:"you want to change a supported crtr setting in user or project scope. Use sys settings instead for keybindings, and sys config get to inspect values.",help:{name:"sys config set",summary:"write a config value by dotted key",params:[{kind:"positional",name:"key",type:"string",required:!0,constraint:`Dotted key path. User-scope scalar settings: ${M}. Also supported: working_gerunds and whip_messages (non-empty JSON string arrays), brokerThresholds.warning and brokerThresholds.automaticReviveCap (user scope; integer >= 1), lifecycle.unattendedParkMs (user scope; integer ms >= 1), modelLadders.defaultProvider, and modelLadders.<anthropic|openai>.<ultra|strong|medium|light>. Keybindings are edited only through sys settings. For arbitrary raw user or profile documents, use sys config get-raw and set-raw.`},{kind:"flag",name:"value",type:"string",required:!0,constraint:"value VALUE \u2014 string, required. working_gerunds and whip_messages accept JSON arrays; other values are stored as-is if quoted and coerced to number or boolean when unambiguous."},{kind:"flag",name:"scope",type:"enum",choices:["user","project"],required:!1,constraint:"Scope to write to. Default: user. Project scope is supported only for modelLadders."}],output:[{name:"value",type:"unknown",required:!0,constraint:"Resolved value as written after parsing and setting-specific coercion."},{name:"scope",type:"string",required:!0,constraint:"Scope the value was written to."}],outputKind:"object",effects:["Writes the updated value through the target scope\u2019s configuration storage."]},run:i(async t=>{p();const e=t.key,n=t.value,r=m(t.scope);v(e,r),k(e,r),K(e,r),D(e,r),G(e,r);const s=F(n),c=Q(e,n),l=c!==null?(N(O(r),c),g(r)):P(r,d=>B(d,e,n,s));return{value:b(l,e),scope:r}},"run")}),z=u({name:"get-raw",description:"read one raw SQL-backed settings document and revision",whenToUse:"you need the exact stored user or profile settings document before replacing it with set-raw.",help:{name:"sys config get-raw",summary:"read one raw user or profile settings document",params:[{kind:"flag",name:"scope",type:"enum",choices:["user","profile","project"],required:!0,constraint:"SQL-backed target: user or profile. project is rejected because its settings remain a JSON file."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target. Required with --scope profile; rejected with --scope user or project."}],output:[{name:"revision",type:"string",required:!0,constraint:"Opaque revision token for set-raw. absent means the settings row does not exist."},{name:"settings",type:"object | null",required:!0,constraint:"Exact stored settings document, or null when no row exists."}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>(p(),L(S(t))),"run")}),Y=u({name:"set-raw",description:"replace one raw SQL-backed settings document at a revision",whenToUse:"you have a complete user or profile settings document from get-raw and must replace it without losing a concurrent change.",help:{name:"sys config set-raw",summary:"atomically replace one raw user or profile settings document",params:[{kind:"flag",name:"scope",type:"enum",choices:["user","profile","project"],required:!0,constraint:"SQL-backed target: user or profile. project is rejected because its settings remain a JSON file."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id or name to target. Required with --scope profile; rejected with --scope user or project."},{kind:"flag",name:"if-revision",type:"string",required:!0,constraint:"Revision returned by get-raw. Required; use absent only when get-raw reported no settings row."},{kind:"stdin",name:"settings",required:!0,allowPositional:!1,constraint:"One complete JSON object. It replaces the document exactly; values are not normalized or merged."}],output:[{name:"revision",type:"string",required:!0,constraint:"Revision token of the stored document after this operation."},{name:"changed",type:"boolean",required:!0,constraint:"Whether the stored document changed."}],outputKind:"object",effects:["Atomically replaces the SQL-backed settings document only when --if-revision matches its current revision."]},run:i(async t=>{p();const e=S(t),n=W(t.settings);try{return R(e,n,t.ifRevision)}catch(r){throw r instanceof E?new f({error:"settings_revision_conflict",message:"settings changed since the supplied revision",field:"if_revision",next:"Run `crtr sys config get-raw` again, reapply the intended transformation, and retry with its revision."}):r instanceof q?new f({error:"invalid_settings",message:r.message,field:"stdin",next:"Correct the document so crouter can merge it into resolved settings, then retry with a fresh revision."}):r}},"run")}),X=u({name:"path",description:"print the project config.json path",whenToUse:"you need the project config.json path for inspection or backup. User and profile settings use get-raw and set-raw instead.",help:{name:"sys config path",summary:"print the project config.json path",params:[{kind:"flag",name:"scope",type:"enum",choices:["project","user","profile"],required:!1,constraint:"Project is the only path-backed settings scope. user and profile are rejected because they use SQL-backed get-raw and set-raw. Default: project."}],output:[{name:"paths",type:"object[]",required:!0,constraint:'One {scope: "project", path} entry when the current project has a config file; otherwise empty.'}],outputKind:"object",effects:["None. Read-only."]},run:i(async t=>{p();const e=t.scope;if(e==="user"||e==="profile")throw o(`${e} settings are SQL-backed; use \`crtr sys config get-raw --scope ${e}\` instead.`);const n=_("project");return{paths:n===null?[]:[{scope:"project",path:n}]}},"run")}),ue=T({name:"config",description:"read and write configuration",whenToUse:"inspecting crtr settings, changing supported scalar values, replacing complete raw user or profile settings documents, or locating a project config.json. Keybinding changes belong in sys settings.",help:{name:"sys config",summary:"read and write crtr configuration, including model ladders and raw SQL-backed user/profile settings",model:"get and set resolve individual settings. get-raw and set-raw read and replace complete user or profile documents with a revision precondition. path applies only to project config.json."},children:[H,V,z,Y,X]});export{ue as configBranch};
@@ -1,3 +1,3 @@
1
- var _=Object.defineProperty;var o=(e,t)=>_(e,"name",{value:t,configurable:!0});import{randomBytes as $}from"node:crypto";import x from"node:path";import{defineLeaf as R}from"../../core/command.js";import{readConfig as w,updateConfig as g}from"../../core/config.js";import{emit as S,InputError as d,isJsonOutput as A}from"../../core/io.js";import{renderResult as L}from"../../core/render.js";import{addScopedApiToken as E,getApiToken as y,setApiToken as I}from"../../core/secrets.js";import{SCOPE_VOCABULARY as k,validateScopes as O}from"../../core/scopes.js";import{envCrtrdTcp as D,envCrtrdToken as b,envNodeId as N}from"../../shared/env.js";import{shellQuote as c}from"../../shared/shell-quote.js";import{cliClient as v}from"../api-client.js";const q="127.0.0.1:8787",T=3e4,M=100;function C(){return $(32).toString("hex")}o(C,"token");function U(e){if(e===void 0)return;const t=String(e).split(",").map(n=>n.trim()).filter(n=>n!=="");if(t.length===0)throw new d({error:"empty_scopes",message:"--scopes names no scope",received:e,field:"scopes",next:`Pass a comma-separated list from ${k.join(", ")}, or prefix:operand; omit the flag for the owner token.`});return O(t)}o(U,"parseScopes");function j(e){A()?S(e):process.stdout.write(L(e,H.help)+`
2
- `)}o(j,"printCredentials");function W(e){const t=e.lastIndexOf(":");return t===-1||Number(e.slice(t+1))!==0?e:`${e.slice(0,t+1)}8787`}o(W,"fixedTcpPort");async function B(){const e=v(),t=Date.now()+T;let n;for(;Date.now()<t;){try{const r=await e.status();if(r.listeners.tcp!==null)return r}catch(r){n=r}await new Promise(r=>setTimeout(r,M))}throw new d({error:"listener_unavailable",message:`the successor did not expose a TCP listener within ${T}ms${n instanceof Error?`: ${n.message}`:""}`,next:"Run `crtr sys daemon status` to inspect the daemon, then retry `crtr sys connect`."})}o(B,"awaitTcpListener");async function P(e,t){const n=await e.getModelAuthReadiness(t);if(n.credential==="ready")return;process.stderr.write(`Logging in to ${n.provider} for ${n.model}.
3
- `);const{loginProvider:r,openProviderLoginRuntime:f,terminalAuthInteraction:i}=await import("./provider-login.js");await r(await f(),n.provider,i());const s=await e.getModelAuthReadiness(t);if(s.credential!=="ready")throw new d({error:"provider_login_incomplete",message:`provider ${s.provider} credential is ${s.credential} after login`,next:`Run \`${F(t)}\` again and complete the provider login.`})}o(P,"ensureProviderCredential");function F(e){return["crtr sys connect",e.profile===void 0?void 0:`--profile ${c(e.profile)}`,e.cwd===void 0?void 0:`--cwd ${c(e.cwd)}`,e.kind===void 0?void 0:`--kind ${c(e.kind)}`,e.model===void 0?void 0:`--model ${c(e.model)}`].filter(t=>t!==void 0).join(" ")}o(F,"connectCommand");const H=R({name:"connect",description:"enable browser access to this daemon",whenToUse:"an application needs a browser-reachable daemon URL and bearer token; this enables the local TCP listener and reports the credentials to paste into that application. Add --scopes when that application should hold less than the owner.",help:{name:"sys connect",summary:"enable authenticated browser access and log in to the selected model provider when needed; a handover reports browser credentials before it begins",params:[{kind:"flag",name:"scopes",type:"string",required:!1,constraint:`Comma-separated list from ${k.join(", ")}, or prefix:operand. Mints a NEW bearer token whose list is the ceiling for every scope-gated daemon operation it performs and every node it creates; owner-only operations (daemon restart, attach, broker internals) refuse it. Omit for the owner token, which has no ceiling.`},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile setting selecting the provider a root launch with these settings would use."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Directory setting selecting the provider a root launch with these settings would use. Default: this directory."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Node kind setting selecting the provider a root launch with these settings would use."},{kind:"flag",name:"model",type:"string",required:!1,constraint:"Model setting selecting the provider a root launch with these settings would use."}],output:[{name:"base_url",type:"string",required:!0,constraint:"The HTTP URL configured for the TCP listener."},{name:"token",type:"string",required:!0,constraint:"The bearer token accepted by that listener: the owner token, or with --scopes the newly minted scoped token. Paste it only into the application that needs daemon access."}],outputKind:"object",effects:["Stores a missing listener address in user settings and a missing owner bearer token in the 0600 user secrets store.","With --scopes, appends a new scoped token to that secrets store; there is no revoke verb yet, so removing one means editing the store by hand.","When the listener is not already up with both settings present, or a scoped token was minted (the daemon reads tokens only at boot), asks the daemon to hand over to a successor.","After the listener is available, resolves the provider selected by these params (default: this directory) and runs its existing OAuth login flow when that provider has no usable credential."]},run:o(async e=>{const t={profile:e.profile,cwd:x.resolve(e.cwd??process.cwd()),kind:e.kind,model:e.model},n=U(e.scopes),r=N(),i=w("user").api.tcp,s=y("user"),a=v(),h=await a.status();i===""?g("user",u=>{u.api.tcp=q}):Number(i.slice(i.lastIndexOf(":")+1))===0&&g("user",u=>{u.api.tcp=W(i)});const l=D()??w("user").api.tcp;if(Number(l.slice(l.lastIndexOf(":")+1))===0)throw new d({error:"dynamic_tcp_port",message:"CRTRD_TCP must use a fixed port for `crtr sys connect`",next:"Set CRTRD_TCP to a host and fixed port, then run `crtr sys connect` again."});if(n===void 0&&i!==""&&s!==void 0&&h.listeners.tcp!==null)return await P(a,t),{base_url:`http://${h.listeners.tcp}`,token:b()??s};s===void 0&&I(C(),"user");const m=b()??y("user");if(m===void 0)throw new Error("TCP listener cannot start without a bearer token");let p=m;n!==void 0&&(p=C(),E({token:p,scopes:n,created:new Date().toISOString()},"user")),j({base_url:`http://${l}`,token:p}),await a.restartDaemon(),await B(),await P(a,t),r!==void 0&&await a.sendMessage(r,{body:"Browser access is ready.",tier:"urgent",from:r})},"run")});export{H as sysConnectLeaf};
1
+ var x=Object.defineProperty;var i=(e,n)=>x(e,"name",{value:n,configurable:!0});import{randomBytes as P}from"node:crypto";import R from"node:path";import{defineLeaf as A}from"../../core/command.js";import{readConfig as k,updateConfig as y}from"../../core/config.js";import{emit as S,InputError as s,isJsonOutput as E}from"../../core/io.js";import{renderResult as L}from"../../core/render.js";import{addScopedApiToken as q,getApiToken as b,setApiToken as I}from"../../core/secrets.js";import{ENFORCED as c}from"@north-light/crouter-identity";import{envCrtrdTcp as D,envCrtrdToken as v,envNodeId as N}from"../../shared/env.js";import{shellQuote as p}from"../../shared/shell-quote.js";import{cliClient as T}from"../api-client.js";const O="127.0.0.1:8787",$=3e4,M=100;function C(){return P(32).toString("hex")}i(C,"token");function j(e){if(e===void 0)return;const n=String(e).split(",").map(t=>t.trim()).filter(t=>t!=="");if(n.length===0)throw new s({error:"empty_scopes",message:"--scopes names no scope",received:e,field:"scopes",next:`Pass a comma-separated list from ${[...c].join(", ")}; omit the flag for the owner token.`});for(const t of n)if(!c.has(t))throw new s({error:"invalid_scope",message:`invalid scope: ${t}`,field:"scopes",received:t,next:`Use one of ${[...c].join(", ")}.`});return n}i(j,"parseScopes");function U(e){E()?S(e):process.stdout.write(L(e,F.help)+`
2
+ `)}i(U,"printCredentials");function W(e){const n=e.lastIndexOf(":");return n===-1||Number(e.slice(n+1))!==0?e:`${e.slice(0,n+1)}8787`}i(W,"fixedTcpPort");async function z(){const e=T(),n=Date.now()+$;let t;for(;Date.now()<n;){try{const r=await e.status();if(r.listeners.tcp!==null)return r}catch(r){t=r}await new Promise(r=>setTimeout(r,M))}throw new s({error:"listener_unavailable",message:`the successor did not expose a TCP listener within ${$}ms${t instanceof Error?`: ${t.message}`:""}`,next:"Run `crtr sys daemon status` to inspect the daemon, then retry `crtr sys connect`."})}i(z,"awaitTcpListener");async function _(e,n){const t=await e.getModelAuthReadiness(n);if(t.credential==="ready")return;process.stderr.write(`Logging in to ${t.provider} for ${t.model}.
3
+ `);const{loginProvider:r,openProviderLoginRuntime:a,terminalAuthInteraction:m}=await import("./provider-login.js");await r(await a(),t.provider,m());const o=await e.getModelAuthReadiness(n);if(o.credential!=="ready")throw new s({error:"provider_login_incomplete",message:`provider ${o.provider} credential is ${o.credential} after login`,next:`Run \`${B(n)}\` again and complete the provider login.`})}i(_,"ensureProviderCredential");function B(e){return["crtr sys connect",e.profile===void 0?void 0:`--profile ${p(e.profile)}`,e.cwd===void 0?void 0:`--cwd ${p(e.cwd)}`,e.kind===void 0?void 0:`--kind ${p(e.kind)}`,e.model===void 0?void 0:`--model ${p(e.model)}`].filter(n=>n!==void 0).join(" ")}i(B,"connectCommand");const F=A({name:"connect",description:"enable browser access to this daemon",whenToUse:"an application needs a browser-reachable daemon URL and bearer token; this enables the local TCP listener and reports the credentials to paste into that application. Add --app and --scopes to mint an app token instead of the owner token.",help:{name:"sys connect",summary:"enable authenticated browser access and log in to the selected model provider when needed; a handover reports browser credentials before it begins",params:[{kind:"flag",name:"app",type:"string",required:!1,constraint:"App id for the new scoped token (without the app: prefix). Required with --scopes; omit both for the owner token."},{kind:"flag",name:"scopes",type:"string",required:!1,constraint:`Comma-separated list from ${[...c].join(", ")}. Requires --app; mints a NEW app bearer with this resolved scope set. Omit both flags for the owner token.`},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile setting selecting the provider a root launch with these settings would use."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Directory setting selecting the provider a root launch with these settings would use. Default: this directory."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Node kind setting selecting the provider a root launch with these settings would use."},{kind:"flag",name:"model",type:"string",required:!1,constraint:"Model setting selecting the provider a root launch with these settings would use."}],output:[{name:"base_url",type:"string",required:!0,constraint:"The HTTP URL configured for the TCP listener."},{name:"token",type:"string",required:!0,constraint:"The bearer token accepted by that listener: the owner token, or with --scopes the newly minted scoped token. Paste it only into the application that needs daemon access."}],outputKind:"object",effects:["Stores a missing listener address in user settings and a missing owner bearer token in the 0600 user secrets store.","With --scopes, appends a new scoped token to that secrets store; there is no revoke verb yet, so removing one means editing the store by hand.","When the listener is not already up with both settings present, or a scoped token was minted (the daemon reads tokens only at boot), asks the daemon to hand over to a successor.","After the listener is available, resolves the provider selected by these params (default: this directory) and runs its existing OAuth login flow when that provider has no usable credential."]},run:i(async e=>{const n={profile:e.profile,cwd:R.resolve(e.cwd??process.cwd()),kind:e.kind,model:e.model},t=j(e.scopes),r=e.app;if(t===void 0!=(r===void 0)||r!==void 0&&!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(String(r)))throw new s({error:"invalid_app",message:"--app must name an app id and is required exactly when --scopes is set",field:"app",received:r,next:"Pass --app with an app id and --scopes together, or omit both for the owner token."});const a=N(),o=k("user").api.tcp,l=b("user"),d=T(),w=await d.status();o===""?y("user",h=>{h.api.tcp=O}):Number(o.slice(o.lastIndexOf(":")+1))===0&&y("user",h=>{h.api.tcp=W(o)});const f=D()??k("user").api.tcp;if(Number(f.slice(f.lastIndexOf(":")+1))===0)throw new s({error:"dynamic_tcp_port",message:"CRTRD_TCP must use a fixed port for `crtr sys connect`",next:"Set CRTRD_TCP to a host and fixed port, then run `crtr sys connect` again."});if(t===void 0&&o!==""&&l!==void 0&&w.listeners.tcp!==null)return await _(d,n),{base_url:`http://${w.listeners.tcp}`,token:v()??l};l===void 0&&I(C(),"user");const g=v()??b("user");if(g===void 0)throw new Error("TCP listener cannot start without a bearer token");let u=g;t!==void 0&&(u=C(),q({token:u,grantee:`app:${String(r)}`,scopes:t,created:new Date().toISOString()},"user")),U({base_url:`http://${f}`,token:u}),await d.restartDaemon(),await z(),await _(d,n),a!==void 0&&await d.sendMessage(a,{body:"Browser access is ready.",tier:"urgent",from:a})},"run")});export{F as sysConnectLeaf};
@@ -1,2 +1,2 @@
1
- var h=Object.defineProperty;var a=(e,n)=>h(e,"name",{value:n,configurable:!0});import{dirname as d}from"node:path";import{editLeaf as p}from"../../../memory/edit.js";import{literalBodySegment as g}from"../../../memory/shared.js";import{moveLeaf as y}from"../../../memory/move.js";import{addProfileProject as $,loadProfileManifest as w}from"../../../../core/profiles/manifest.js";import{findProjectScopeRoots as k}from"../../../../core/scope.js";import{readText as x,realpathOrSelf as l}from"../../../../core/fs-utils.js";import{parseSubstrateFrontmatter as R}from"../../../../core/substrate/schema.js";import{surfaceEntryToFlag as b}from"./model.js";const A="editor";function f(e,n){if(e.doc.plugin!==void 0)return{refusal:`${e.name} belongs to the plugin \u201C${e.doc.plugin}\u201D and is read-only here \u2014 override it with \`crtr memory write ${e.name}\`.`};if(e.scope==="builtin")return{refusal:`${e.name} is a builtin document and is read-only here \u2014 override it with \`crtr memory write ${e.name}\`.`};if(e.scope==="project"){const t=e.source.store.ownerDir;return t===void 0?{refusal:`${e.name} resolves from a project store with no owning directory, which this page cannot address \u2014 edit it with \`crtr memory edit ${e.name} --dir <dir>\`.`}:{selector:{dir:t}}}return e.scope==="profile"?{selector:n===null?{scope:"profile"}:{scope:"profile",profile:n}}:e.scope==="user"||e.scope==="node"?{selector:{scope:e.scope}}:{refusal:`${e.name} resolves from the ${e.scope} scope, which this page cannot address.`}}a(f,"storeAddress");function F(e,n){const t=f(e,n);return"refusal"in t?t.refusal:null}a(F,"readOnlyReason");function m(e){return{ok:!1,message:e instanceof Error?e.message:String(e)}}a(m,"failure");async function i(e,n,t,r){const o=f(e,n);if("refusal"in o)return{ok:!1,message:o.refusal};const s=t.surfaces,u=[...t.unset??[]];s!==void 0&&s.length===0&&!u.includes("surfaces")&&u.push("surfaces");try{return await p.run({name:e.name,rationale:A,...o.selector,...s!==void 0&&s.length>0?{surface:s.map(b)}:{},...t.body===void 0?{}:{body:t.body},...t.gate===void 0?{}:{gate:t.gate},...t.unlisted===void 0?{}:{unlisted:!0},...t.slash===void 0?{}:{slash:!0},...t.whenAndWhyToRead===void 0?{}:{whenAndWhyToRead:t.whenAndWhyToRead},...t.shortForm===void 0?{}:{shortForm:t.shortForm},...u.length>0?{unset:u}:{}}),{ok:!0,message:r,name:e.name}}catch(c){return m(c)}}a(i,"runEdit");function G(e,n,t,r){const o=F(e,n)??j(e);return o!==null?Promise.resolve({ok:!1,message:o}):i(e,n,{surfaces:t},r)}a(G,"writeSurfaces");function j(e){const n=e.source.frontmatter?.surfaces;if(n==null)return null;const t=`a write replaces the whole list, so fix ${e.storePath} first`;if(!Array.isArray(n))return`The \`surfaces\` field of ${e.name} is not a list of entries \u2014 ${t}.`;for(const[r,o]of n.entries()){const s=S(e.kind,o);if(s!==null)return`Entry ${r+1} of ${e.name} ${s} \u2014 ${t}.`}return null}a(j,"unwritableSurfaces");const v={on:"on",at:"at",match:"match","match-frontmatter":"matchFrontmatter",gate:"gate"};function S(e,n){if(n===null||typeof n!="object"||Array.isArray(n))return"is not an entry object";const t=n,r=R({kind:e,surfaces:[t]})?.surfaces[0];if(r===void 0)return`(on ${JSON.stringify(t.on??null)}) is malformed and the parser drops it`;for(const o of Object.keys(t)){if(t[o]===void 0)continue;const s=v[o];if(s===void 0)return`carries an unknown key \`${o}\``;if(r[s]===void 0)return`carries a \`${o}\` the parser drops`}return null}a(S,"entryLoss");function J(e){const n=g(x(e.storePath));return n.startsWith(`
1
+ var h=Object.defineProperty;var a=(e,n)=>h(e,"name",{value:n,configurable:!0});import{dirname as d}from"node:path";import{editLeaf as p}from"../../../memory/edit.js";import{literalBodySegment as g}from"../../../../core/memory/mutation-domain.js";import{moveLeaf as y}from"../../../memory/move.js";import{addProfileProject as $,loadProfileManifest as w}from"../../../../core/profiles/manifest.js";import{findProjectScopeRoots as k}from"../../../../core/scope.js";import{readText as x,realpathOrSelf as l}from"../../../../core/fs-utils.js";import{parseSubstrateFrontmatter as R}from"../../../../core/substrate/schema.js";import{surfaceEntryToFlag as b}from"./model.js";const A="editor";function f(e,n){if(e.doc.plugin!==void 0)return{refusal:`${e.name} belongs to the plugin \u201C${e.doc.plugin}\u201D and is read-only here \u2014 override it with \`crtr memory write ${e.name}\`.`};if(e.scope==="builtin")return{refusal:`${e.name} is a builtin document and is read-only here \u2014 override it with \`crtr memory write ${e.name}\`.`};if(e.scope==="project"){const t=e.source.store.ownerDir;return t===void 0?{refusal:`${e.name} resolves from a project store with no owning directory, which this page cannot address \u2014 edit it with \`crtr memory edit ${e.name} --dir <dir>\`.`}:{selector:{dir:t}}}return e.scope==="profile"?{selector:n===null?{scope:"profile"}:{scope:"profile",profile:n}}:e.scope==="user"||e.scope==="node"?{selector:{scope:e.scope}}:{refusal:`${e.name} resolves from the ${e.scope} scope, which this page cannot address.`}}a(f,"storeAddress");function F(e,n){const t=f(e,n);return"refusal"in t?t.refusal:null}a(F,"readOnlyReason");function m(e){return{ok:!1,message:e instanceof Error?e.message:String(e)}}a(m,"failure");async function i(e,n,t,r){const o=f(e,n);if("refusal"in o)return{ok:!1,message:o.refusal};const s=t.surfaces,u=[...t.unset??[]];s!==void 0&&s.length===0&&!u.includes("surfaces")&&u.push("surfaces");try{return await p.run({name:e.name,rationale:A,...o.selector,...s!==void 0&&s.length>0?{surface:s.map(b)}:{},...t.body===void 0?{}:{body:t.body},...t.gate===void 0?{}:{gate:t.gate},...t.unlisted===void 0?{}:{unlisted:!0},...t.slash===void 0?{}:{slash:!0},...t.whenAndWhyToRead===void 0?{}:{whenAndWhyToRead:t.whenAndWhyToRead},...t.shortForm===void 0?{}:{shortForm:t.shortForm},...u.length>0?{unset:u}:{}}),{ok:!0,message:r,name:e.name}}catch(c){return m(c)}}a(i,"runEdit");function G(e,n,t,r){const o=F(e,n)??j(e);return o!==null?Promise.resolve({ok:!1,message:o}):i(e,n,{surfaces:t},r)}a(G,"writeSurfaces");function j(e){const n=e.source.frontmatter?.surfaces;if(n==null)return null;const t=`a write replaces the whole list, so fix ${e.storePath} first`;if(!Array.isArray(n))return`The \`surfaces\` field of ${e.name} is not a list of entries \u2014 ${t}.`;for(const[r,o]of n.entries()){const s=S(e.kind,o);if(s!==null)return`Entry ${r+1} of ${e.name} ${s} \u2014 ${t}.`}return null}a(j,"unwritableSurfaces");const v={on:"on",at:"at",match:"match","match-frontmatter":"matchFrontmatter",gate:"gate"};function S(e,n){if(n===null||typeof n!="object"||Array.isArray(n))return"is not an entry object";const t=n,r=R({kind:e,surfaces:[t]})?.surfaces[0];if(r===void 0)return`(on ${JSON.stringify(t.on??null)}) is malformed and the parser drops it`;for(const o of Object.keys(t)){if(t[o]===void 0)continue;const s=v[o];if(s===void 0)return`carries an unknown key \`${o}\``;if(r[s]===void 0)return`carries a \`${o}\` the parser drops`}return null}a(S,"entryLoss");function J(e){const n=g(x(e.storePath));return n.startsWith(`
2
2
  `)?n.slice(1):n}a(J,"readBody");function M(e,n,t){return t.trim()===""?Promise.resolve({ok:!1,message:`An empty body is not an edit \u2014 remove ${e.name} with \`crtr memory delete\` instead.`}):i(e,n,{body:t},`Rewrote the body of ${e.name}.`)}a(M,"writeBody");function Y(e,n,t){const r=t.trim();return r===""?i(e,n,{unset:["gate"]},`Cleared the gate on ${e.name}.`):i(e,n,{gate:r},`Gated ${e.name} on ${r}.`)}a(Y,"writeGate");function _(e,n,t){return(t==="unlisted"?e.doc.unlisted:e.doc.slash)?i(e,n,{unset:[t]},`${e.name} is no longer ${t}.`):i(e,n,t==="unlisted"?{unlisted:!0}:{slash:!0},`${e.name} is now ${t}.`)}a(_,"toggleFlag");function z(e,n,t){const r=t.trim();return r===""?Promise.resolve({ok:!1,message:"A routing line cannot be empty \u2014 it is the document\u2019s contract."}):i(e,n,{whenAndWhyToRead:r},`Rewrote the routing line on ${e.name}.`)}a(z,"writeRoutingLine");function H(e,n,t){const r=t.trim();return r===""?i(e,n,{unset:["short-form"]},`Cleared the short form on ${e.name}.`):i(e,n,{shortForm:r},`Rewrote the short form on ${e.name}.`)}a(H,"writeShortForm");async function K(e,n,t){const r=t.trim();if(r==="")return{ok:!1,message:"Type the new canonical name."};const o=f(e,n);if("refusal"in o)return{ok:!1,message:o.refusal};try{const s=await y.run({name:e.name,to:r,...o.selector}),u=typeof s?.name=="string"?s.name:r;return{ok:!0,message:`${e.name} now answers to ${u}.`,name:u}}catch(s){return m(s)}}a(K,"moveDoc");function Q(e,n){if(n===null||e.scope!=="project")return null;const t=l(d(e.source.store.storeRoot));let r;try{r=w(n).manifest}catch{return null}for(const o of r.projects)if(k(o.path,null).some(s=>l(s)===t))return{path:o.path,memory:o.memory};return null}a(Q,"capOwnerFor");function U(e,n,t){try{return $(e,n,{memory:t}),{ok:!0,message:`${n} discloses up to "${t}".`,change:{path:n,memory:t}}}catch(r){return m(r)}}a(U,"writeCap");export{Q as capOwnerFor,K as moveDoc,J as readBody,F as readOnlyReason,_ as toggleFlag,M as writeBody,U as writeCap,Y as writeGate,z as writeRoutingLine,H as writeShortForm,G as writeSurfaces};
@@ -13,6 +13,7 @@ export interface Snapshot {
13
13
  profileId: string | null;
14
14
  cwd: string;
15
15
  nodeId: string | null;
16
+ grantee?: string;
16
17
  depth: number;
17
18
  event: SurfaceEvent;
18
19
  /** `read` payload — the file that was read. */
@@ -1 +1 @@
1
- var l=Object.defineProperty;var n=(t,e)=>l(t,"name",{value:e,configurable:!0});import{resolve as p}from"node:path";import{realpathOrSelf as g}from"../../../../core/fs-utils.js";import{planDelivery as w}from"../../../../core/substrate/plan.js";import{assembleEventAccounting as x,effectivePlan as F}from"../resolve.js";import{RUNGS as o,SURFACE_EVENTS as R,previewLine as S,rungRank as s}from"../../../../core/substrate/schema.js";import{effectiveScopes as N,scopeForCwd as $,profileNameFor as v}from"../../../../core/substrate/subject-fields.js";import{resolveMemoryDocForTarget as O}from"../../../../core/memory-resolver.js";function b(t){return{kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,hasManager:t.hasManager,cwd:t.cwd,scope:$(t.cwd),orchestration:{depth:t.depth},profile:v(t.profileId),scopes:N(null)}}n(b,"subjectOf");function m(t){return{cwd:t.cwd,profileId:t.profileId,nodeId:t.nodeId}}n(m,"targetOf");function A(t){return t==="read"?"file":t==="memory-read"?"docName":t==="command"||t==="pre-command"?"command":null}n(A,"payloadAxisFor");class J{static{n(this,"PlanSet")}snapshot;plans=new Map;warming;constructor(e){this.snapshot=e}setSnapshot(e){this.snapshot=e,this.invalidate()}invalidate(){this.plans.clear(),this.warming!==void 0&&(clearTimeout(this.warming),this.warming=void 0)}dispose(){this.warming!==void 0&&clearTimeout(this.warming),this.warming=void 0}plan(e){const i=this.plans.get(e);if(i!==void 0)return i;const a=b(this.snapshot),u=m(this.snapshot),r=this.payload(e),c=w(a,u,e,r),h=x({subject:a,target:u,nodeMissing:!1},e,r),f=F(c,h.accounting.deliveries,r);return this.plans.set(e,f),f}peek(e){return this.plans.get(e)}warm(e){if(this.warming!==void 0)return;const i=R.find(a=>!this.plans.has(a));i!==void 0&&(this.warming=setTimeout(()=>{this.warming=void 0,this.plan(i),e(),this.warm(e)},0))}payload(e){return e==="read"?this.snapshot.file===""?{}:{absoluteFile:p(this.snapshot.cwd,this.snapshot.file)}:e==="memory-read"?this.snapshot.docName===""?{}:{resolvedCanonicalName:this.snapshot.docName,resolvedDocPath:k(this.snapshot.docName,m(this.snapshot))}:e==="command"||e==="pre-command"?this.snapshot.command===""?{}:{command:this.snapshot.command}:{}}}function k(t,e){try{return g(O(t,e).path)}catch{return""}}n(k,"resolvedDocRealpath");function P(t){return t===void 0?"silent":t.docGate.pass?t.shadowedBy!==null?"shadowed":t.finalRung!=="none"?s(t.finalRung)<s(t.authoredRung)?"capped":"delivers":t.authoredRung!=="none"?"capped":t.entryGate!==null&&!t.entryGate.pass?"gated":"silent":"gated"}n(P,"deliveryStateOf");function L(t,e){return e==="gated"?{text:"gated",tone:"muted"}:e==="shadowed"?{text:"shadowed",tone:"muted"}:t===void 0||t.finalRung==="none"?{text:"",tone:"muted"}:{text:t.finalRung,tone:e==="capped"?"warning":"success"}}n(L,"stateLabel");function U(t,e){const i=(s(t)+e+o.length)%o.length;return o[i]}n(U,"nextRung");function _(t){const e=t.match===void 0||t.match.length===0?void 0:t.match.length===1?t.match[0]:t.match;return JSON.stringify({on:t.on,...e===void 0?{}:{match:e},...t.matchFrontmatter===void 0?{}:{"match-frontmatter":t.matchFrontmatter},...t.gate===void 0?{}:{gate:t.gate},at:t.at})}n(_,"surfaceEntryToFlag");function B(t){const e=[t.on];return t.match!==void 0&&t.match.length>0&&e.push(t.match.join(" | ")),t.matchFrontmatter!==void 0&&e.push(`fm ${JSON.stringify(t.matchFrontmatter)}`),t.gate!==void 0&&e.push(`gate ${JSON.stringify(t.gate)}`),`${e.join(" ")} \u2192 ${t.at}`}n(B,"describeSurfaceEntry");function V(t,e,i){return`${t} ${t===1?e:i}`}n(V,"plural");function M(t){const e=t.name.length,i=S(t.doc).length;return{none:0,name:d(e),preview:d(e+i),content:d(t.doc.body.length)}}n(M,"rungCostsOf");function q(t){return t===void 0?0:M(t)[t.finalRung]}n(q,"deliveredCost");function d(t){return Math.ceil(t/4)}n(d,"tokens");function z(t){return t<=0?"":t<1e3?`~${t}`:t<1e4?`~${(t/1e3).toFixed(1)}k`:`~${Math.round(t/1e3)}k`}n(z,"formatCost");export{J as PlanSet,q as deliveredCost,P as deliveryStateOf,B as describeSurfaceEntry,z as formatCost,U as nextRung,A as payloadAxisFor,V as plural,M as rungCostsOf,L as stateLabel,b as subjectOf,_ as surfaceEntryToFlag,m as targetOf};
1
+ var l=Object.defineProperty;var n=(e,t)=>l(e,"name",{value:t,configurable:!0});import{resolve as p}from"node:path";import{realpathOrSelf as g}from"../../../../core/fs-utils.js";import{planDelivery as w}from"../../../../core/substrate/plan.js";import{assembleEventAccounting as x,effectivePlan as F}from"../resolve.js";import{RUNGS as o,SURFACE_EVENTS as R,previewLine as S,rungRank as s}from"../../../../core/substrate/schema.js";import{effectiveScopes as N,scopeForCwd as $,profileNameFor as v}from"../../../../core/substrate/subject-fields.js";import{resolveMemoryDocForTarget as O}from"../../../../core/memory-resolver.js";function b(e){return{kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,hasManager:e.hasManager,cwd:e.cwd,scope:$(e.cwd),orchestration:{depth:e.depth},profile:v(e.profileId),scopes:N(null)}}n(b,"subjectOf");function m(e){return{cwd:e.cwd,profileId:e.profileId,nodeId:e.nodeId,grantee:e.grantee}}n(m,"targetOf");function A(e){return e==="read"?"file":e==="memory-read"?"docName":e==="command"||e==="pre-command"?"command":null}n(A,"payloadAxisFor");class J{static{n(this,"PlanSet")}snapshot;plans=new Map;warming;constructor(t){this.snapshot=t}setSnapshot(t){this.snapshot=t,this.invalidate()}invalidate(){this.plans.clear(),this.warming!==void 0&&(clearTimeout(this.warming),this.warming=void 0)}dispose(){this.warming!==void 0&&clearTimeout(this.warming),this.warming=void 0}plan(t){const i=this.plans.get(t);if(i!==void 0)return i;const a=b(this.snapshot),u=m(this.snapshot),r=this.payload(t),c=w(a,u,t,r),h=x({subject:a,target:u,nodeMissing:!1},t,r),f=F(c,h.accounting.deliveries,r);return this.plans.set(t,f),f}peek(t){return this.plans.get(t)}warm(t){if(this.warming!==void 0)return;const i=R.find(a=>!this.plans.has(a));i!==void 0&&(this.warming=setTimeout(()=>{this.warming=void 0,this.plan(i),t(),this.warm(t)},0))}payload(t){return t==="read"?this.snapshot.file===""?{}:{absoluteFile:p(this.snapshot.cwd,this.snapshot.file)}:t==="memory-read"?this.snapshot.docName===""?{}:{resolvedCanonicalName:this.snapshot.docName,resolvedDocPath:k(this.snapshot.docName,m(this.snapshot))}:t==="command"||t==="pre-command"?this.snapshot.command===""?{}:{command:this.snapshot.command}:{}}}function k(e,t){try{return g(O(e,t).path)}catch{return""}}n(k,"resolvedDocRealpath");function P(e){return e===void 0?"silent":e.docGate.pass?e.shadowedBy!==null?"shadowed":e.finalRung!=="none"?s(e.finalRung)<s(e.authoredRung)?"capped":"delivers":e.authoredRung!=="none"?"capped":e.entryGate!==null&&!e.entryGate.pass?"gated":"silent":"gated"}n(P,"deliveryStateOf");function L(e,t){return t==="gated"?{text:"gated",tone:"muted"}:t==="shadowed"?{text:"shadowed",tone:"muted"}:e===void 0||e.finalRung==="none"?{text:"",tone:"muted"}:{text:e.finalRung,tone:t==="capped"?"warning":"success"}}n(L,"stateLabel");function U(e,t){const i=(s(e)+t+o.length)%o.length;return o[i]}n(U,"nextRung");function _(e){const t=e.match===void 0||e.match.length===0?void 0:e.match.length===1?e.match[0]:e.match;return JSON.stringify({on:e.on,...t===void 0?{}:{match:t},...e.matchFrontmatter===void 0?{}:{"match-frontmatter":e.matchFrontmatter},...e.gate===void 0?{}:{gate:e.gate},at:e.at})}n(_,"surfaceEntryToFlag");function B(e){const t=[e.on];return e.match!==void 0&&e.match.length>0&&t.push(e.match.join(" | ")),e.matchFrontmatter!==void 0&&t.push(`fm ${JSON.stringify(e.matchFrontmatter)}`),e.gate!==void 0&&t.push(`gate ${JSON.stringify(e.gate)}`),`${t.join(" ")} \u2192 ${e.at}`}n(B,"describeSurfaceEntry");function V(e,t,i){return`${e} ${e===1?t:i}`}n(V,"plural");function M(e){const t=e.name.length,i=S(e.doc).length;return{none:0,name:d(t),preview:d(t+i),content:d(e.doc.body.length)}}n(M,"rungCostsOf");function q(e){return e===void 0?0:M(e)[e.finalRung]}n(q,"deliveredCost");function d(e){return Math.ceil(e/4)}n(d,"tokens");function z(e){return e<=0?"":e<1e3?`~${e}`:e<1e4?`~${(e/1e3).toFixed(1)}k`:`~${Math.round(e/1e3)}k`}n(z,"formatCost");export{J as PlanSet,q as deliveredCost,P as deliveryStateOf,B as describeSurfaceEntry,z as formatCost,U as nextRung,A as payloadAxisFor,V as plural,M as rungCostsOf,L as stateLabel,b as subjectOf,_ as surfaceEntryToFlag,m as targetOf};
@@ -1,2 +1,2 @@
1
- var f=Object.defineProperty;var i=(t,e)=>f(t,"name",{value:e,configurable:!0});import{resolve as p}from"node:path";import{defineLeaf as h}from"../../../core/command.js";import{InputError as u}from"../../../core/io.js";import{ApiError as g}from"../../../api/index.js";import{cliClient as y}from"../../api-client.js";import{SURFACE_EVENTS as w}from"../../../core/substrate/schema.js";import{ambientMemoryTarget as v}from"../../../core/memory-resolver.js";import{getDefaultProfileId as b}from"../../../core/profiles/default-binding.js";import{resolveProfileOperand as k}from"../../../core/profiles/manifest.js";const P=h({name:"admin",description:"browse and edit the context surface interactively",whenToUse:"you are shaping what agents load rather than answering one question about it \u2014 comparing snapshots, sweeping which documents fire where, and editing surfaces, gates, or caps in place",help:{name:"sys context admin",summary:"interactive browser and editor for the memory context surface",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Open with the snapshot derived from this live node instead of the defaults."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Opening node kind. Defaults to the --node value, else `general`."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,constraint:"Opening node mode. Defaults to `base`."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id whose memory store and project-memory caps apply. Defaults to the selected profile."},{kind:"flag",name:"cwd",type:"path",required:!1,constraint:"Directory the project stores resolve from. Defaults to the current directory."},{kind:"flag",name:"event",type:"enum",choices:[...w],required:!1,constraint:"Opening event for the detail panel. Defaults to `boot`."}],output:[{name:"edited",type:"array",required:!1,constraint:"Canonical names of the documents changed during the session; absent when nothing was changed."},{name:"cap_changes",type:"array",required:!1,constraint:"Profile project-memory caps changed during the session, each as store path and new rung; absent when none were."}],outputKind:"object",effects:["Interactive: requires a TTY.","Edits memory documents through `memory edit` / `memory move` with rationale `editor` when you choose an edit action.","Writes profile project-memory caps to the profile manifest when you change one."]},run:i(async t=>{if(!process.stdout.isTTY)throw new u({error:"not_a_tty",message:"sys context admin is interactive and needs a TTY",next:"Run it in a terminal, or use `crtr sys context resolve` and `crtr sys context doc` for scriptable reads."});const e=await c(t.node?.trim()??""),n=v(),o=t.profile?.trim(),r=t.cwd?.trim(),s=r===void 0||r===""?e?.cwd??n.cwd:p(r),l={kind:t.kind?.trim()||e?.kind||"general",mode:t.mode??e?.mode??"base",lifecycle:e?.lifecycle??"terminal",hasManager:e?.parent!=null,profileId:o===void 0||o===""?e?.profile_id??n.profileId??b(s):k(o).profileId,cwd:s,nodeId:e?.node_id??null,depth:e===null?0:await x(e),event:t.event??"boot",file:"",docName:"",command:""},{runContextAdmin:m}=await import("./admin/shell.js"),a=await m(l);return a===void 0?{}:{...a.edited.length>0?{edited:a.edited}:{},...a.capChanges.length>0?{cap_changes:a.capChanges.map(d=>({path:d.path,memory:d.memory}))}:{}}},"run"),render:i(t=>{const e=t.edited??[],n=t.cap_changes??[];return e.length===0&&n.length===0?"Closed the context admin with nothing changed.":[...e.map(r=>`- edited ${r}`),...n.map(r=>`- ceiling ${r.path} \u2192 ${r.memory}`)].join(`
1
+ var f=Object.defineProperty;var i=(t,e)=>f(t,"name",{value:e,configurable:!0});import{resolve as p}from"node:path";import{defineLeaf as h}from"../../../core/command.js";import{InputError as u}from"../../../core/io.js";import{ApiError as g}from"../../../api/index.js";import{cliClient as y}from"../../api-client.js";import{SURFACE_EVENTS as w}from"../../../core/substrate/schema.js";import{ambientMemoryTarget as v}from"../../../core/memory-resolver.js";import{getDefaultProfileId as b}from"../../../core/profiles/default-binding.js";import{resolveProfileOperand as k}from"../../../core/profiles/manifest.js";const P=h({name:"admin",description:"browse and edit the context surface interactively",whenToUse:"you are shaping what agents load rather than answering one question about it \u2014 comparing snapshots, sweeping which documents fire where, and editing surfaces, gates, or caps in place",help:{name:"sys context admin",summary:"interactive browser and editor for the memory context surface",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Open with the snapshot derived from this live node instead of the defaults."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Opening node kind. Defaults to the --node value, else `general`."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,constraint:"Opening node mode. Defaults to `base`."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id whose memory store and project-memory caps apply. Defaults to the selected profile."},{kind:"flag",name:"cwd",type:"path",required:!1,constraint:"Directory the project stores resolve from. Defaults to the current directory."},{kind:"flag",name:"event",type:"enum",choices:[...w],required:!1,constraint:"Opening event for the detail panel. Defaults to `boot`."}],output:[{name:"edited",type:"array",required:!1,constraint:"Canonical names of the documents changed during the session; absent when nothing was changed."},{name:"cap_changes",type:"array",required:!1,constraint:"Profile project-memory caps changed during the session, each as store path and new rung; absent when none were."}],outputKind:"object",effects:["Interactive: requires a TTY.","Edits memory documents through `memory edit` / `memory move` with rationale `editor` when you choose an edit action.","Writes profile project-memory caps to the profile manifest when you change one."]},run:i(async t=>{if(!process.stdout.isTTY)throw new u({error:"not_a_tty",message:"sys context admin is interactive and needs a TTY",next:"Run it in a terminal, or use `crtr sys context resolve` and `crtr sys context doc` for scriptable reads."});const e=await c(t.node?.trim()??""),n=v(),o=t.profile?.trim(),r=t.cwd?.trim(),s=r===void 0||r===""?e?.cwd??n.cwd:p(r),l={kind:t.kind?.trim()||e?.kind||"general",mode:t.mode??e?.mode??"base",lifecycle:e?.lifecycle??"terminal",hasManager:e?.parent!=null,profileId:o===void 0||o===""?e?.profile_id??n.profileId??b(s):k(o).profileId,cwd:s,nodeId:e?.node_id??null,grantee:e?.grantee??n.grantee,depth:e===null?0:await x(e),event:t.event??"boot",file:"",docName:"",command:""},{runContextAdmin:m}=await import("./admin/shell.js"),a=await m(l);return a===void 0?{}:{...a.edited.length>0?{edited:a.edited}:{},...a.capChanges.length>0?{cap_changes:a.capChanges.map(d=>({path:d.path,memory:d.memory}))}:{}}},"run"),render:i(t=>{const e=t.edited??[],n=t.cap_changes??[];return e.length===0&&n.length===0?"Closed the context admin with nothing changed.":[...e.map(r=>`- edited ${r}`),...n.map(r=>`- ceiling ${r.path} \u2192 ${r.memory}`)].join(`
2
2
  `)},"render")});async function c(t){if(t==="")return null;try{return await y().getNode(t)}catch(e){if(e instanceof g&&e.status===404)return null;throw e}}i(c,"fetchNodeOrNull");async function x(t){const e=new Set([t.node_id]);let n=t.parent,o=0;for(;n!=null&&!e.has(n);){e.add(n),o+=1;const r=await c(n);if(r===null)break;n=r.parent}return o}i(x,"spineDepth");export{P as adminLeaf};
@@ -1 +1,2 @@
1
- var d=Object.defineProperty;var a=(n,e)=>d(n,"name",{value:e,configurable:!0});import{accessSync as l,realpathSync as c,statSync as u,constants as m}from"node:fs";import{resolve as p}from"node:path";import{defineLeaf as f}from"../../../core/command.js";import{diag as h}from"../../../core/io.js";import{expandTilde as y}from"../../../core/fs-utils.js";import{renderAutoLoadedContext as g,renderOnReadDocBlocksForSubject as b}from"../../../core/substrate/on-read.js";import{renderCliContextDelivery as x}from"../../../core/substrate/cli-context-delivery.js";import{envNodeId as w}from"../../../shared/env.js";function R(n){const e=[],r=new Set;for(const o of n)try{const t=c(p(y(o)));if(l(t,m.R_OK),!u(t).isFile()||r.has(t))continue;r.add(t),e.push(t)}catch{}return e}a(R,"readableRegularFiles");const F=f({name:"expose",description:"attach read-routed memory to file content a local command displays",whenToUse:"a local command has successfully rendered file contents and must place the matching Read-routed memory in that same output",help:{name:"sys context expose",summary:"return read-routed memory for files displayed by a command",params:[{kind:"flag",name:"file",type:"path",required:!0,repeatable:!0,constraint:"Files whose contents the caller displays. Relative paths resolve against this process\u2019s cwd; leading ~ expands as for Read. Symlinks resolve to their target. Missing, unreadable, and non-file paths contribute nothing."}],output:[{name:"content",type:"string",required:!1,constraint:"One <auto-loaded-context> block. Absent when nothing new matches or CRTR_NODE_ID is unset. Prose output is the block alone, without a field label or acknowledgement."}],outputKind:"object",effects:["Records the returned memory documents at their matched rungs in this node\u2019s transcript exposure ledger. Inherits node identity from CRTR_NODE_ID; does not start the daemon. The caller must include the returned block in the same output as the displayed files; this is not a preview operation."]},run:a(async n=>{const e=w()?.trim();if(e===void 0||e==="")return{};const r=R(n.file);if(r.length===0)return{};const o=await x({nodeId:e,render:a((t,s)=>{if(t===null)throw new Error("context subject unexpectedly unavailable");return g(r.flatMap(i=>b(t,i,s)))},"render")});return o.diagnostic!==void 0&&h(o.diagnostic),o.result===""?{}:{content:o.result}},"run"),render:a(n=>n.content??"","render")});export{F as exposeLeaf};
1
+ var i=Object.defineProperty;var a=(t,e)=>i(t,"name",{value:e,configurable:!0});import{accessSync as c,constants as d,realpathSync as l,statSync as m}from"node:fs";import{resolve as u}from"node:path";import{defineLeaf as p}from"../../../core/command.js";import{expandTilde as h}from"../../../core/fs-utils.js";import{brokerContextEvent as f,commitBrokerContext as y}from"../../../core/runtime/broker/daemon-ops.js";import{envNodeId as g}from"../../../shared/env.js";function w(t){const e=[],o=new Set;for(const s of t)try{const n=l(u(h(s)));if(c(n,d.R_OK),!m(n).isFile()||o.has(n))continue;o.add(n),e.push(n)}catch{}return e}a(w,"readableRegularFiles");const S=p({name:"expose",description:"attach read-routed memory to file content a local command displays",whenToUse:"a local command has successfully rendered file contents and must place the matching Read-routed memory in that same output",help:{name:"sys context expose",summary:"return read-routed memory for files displayed by a command",params:[{kind:"flag",name:"file",type:"path",required:!0,repeatable:!0,constraint:"Files whose contents the caller displays. Relative paths resolve against this process\u2019s cwd; leading ~ expands as for Read. Symlinks resolve to their target. Missing, unreadable, and non-file paths contribute nothing."}],output:[{name:"content",type:"string",required:!1,constraint:"Read-routed <auto-loaded-context> blocks, one per displayed file with new matches. Absent when nothing new matches or CRTR_NODE_ID is unset. Prose output is the blocks alone, without a field label or acknowledgement."}],outputKind:"object",effects:["crtrd records the returned memory documents at their matched rungs in this node\u2019s transcript exposure ledger. Inherits node identity from CRTR_NODE_ID. The caller must include the returned blocks in the same output as the displayed files; this is not a preview operation."]},run:a(async t=>{const e=g()?.trim();if(e===void 0||e==="")return{};const o=w(t.file);if(o.length===0)return{};const s=[];for(const n of o){const r=await f(e,"read",n);r.content!==""&&(await y(e,r.snapshot,r.loads),s.push(r.content))}return s.length===0?{}:{content:s.join(`
2
+ `)}},"run"),render:a(t=>t.content??"","render")});export{S as exposeLeaf};
@@ -1,4 +1,4 @@
1
- var S=Object.defineProperty;var s=(n,e)=>S(n,"name",{value:e,configurable:!0});import{mkdirSync as q,writeFileSync as P}from"node:fs";import{join as k}from"node:path";import{defineLeaf as j}from"../../../core/command.js";import{InputError as l,readStdinRaw as M}from"../../../core/io.js";import{userScopeRoot as L}from"../../../core/scope.js";import{ApiError as O}from"../../../api/index.js";import{cliClient as _}from"../../api-client.js";import{readMergedLaunchConfig as D,subKindsAvailableTo as R}from"../../../core/config.js";import{LAUNCH_SYSTEM_PROMPT as p}from"../../../core/runtime/launch-prompt.js";import{renderPreferencesForSubject as T,renderKnowledgeForSubject as C}from"../../../core/substrate/render.js";import{effectiveScopes as N,scopeForCwd as U,profileNameFor as A}from"../../../core/substrate/subject-fields.js";function F(n,e){return e!==void 0?e:n==="orchestrator"?"resident":"terminal"}s(F,"resolveLifecycle");function I(n){try{return JSON.parse(n)}catch(e){throw new l({error:"invalid_json",message:`stdin is not valid JSON: ${String(e)}`,field:"stdin",next:"Pass the comments deck JSON on stdin."})}}s(I,"readJson");function $(n,e,r){if(n===void 0)return r;if(n===!0||n===!1)return n;if(typeof n!="string")throw new l({error:"invalid_field",message:`${e} must be true or false`,field:e,next:`Use true or false for ${e}.`});const t=n.trim().toLowerCase();if(t==="true")return!0;if(t==="false")return!1;throw new l({error:"invalid_field",message:`${e} must be true or false`,field:e,next:`Use true or false for ${e}.`})}s($,"parseBool");function K(n){return typeof n=="string"&&n.trim()!==""?n:null}s(K,"optionalString");function u(n){return Math.ceil(n.length/4)}s(u,"approxTokens");function E(){const n=D().kinds;return Object.entries(n).filter(([e])=>!e.includes("/")).map(([e,r])=>({kind:e,whenToUse:r.whenToUse})).sort((e,r)=>e.kind.localeCompare(r.kind))}s(E,"topLevelKinds");function J(n){return R(n)}s(J,"subKindsFor");function W(){const n=E(),e={};for(const{kind:r}of n)e[r]=J(r);return{kinds:n,modes:["base","orchestrator"],lifecycles:["terminal","resident"],subPersonas:e}}s(W,"reviewList");async function x(n){if(n===null)return null;try{return await _().getNode(n)}catch(e){if(e instanceof O&&e.status===404)return null;throw e}}s(x,"fetchNodeOrNull");async function z(n){let e=n;const r=new Set;let t=0;for(;e!==null&&!r.has(e);){r.add(e);const i=await x(e);if(i===null||i.parent==null)break;e=i.parent,t++}return t}s(z,"spineDepthViaApi");async function B(n,e,r,t,i){const a=i?.cwd??process.cwd();return{kind:n,mode:e,lifecycle:r,hasManager:t,cwd:a,scope:U(a),orchestration:{depth:i!==null?await z(i.node_id):0},profile:A(i?.profile_id),scopes:N(i?.scopes)}}s(B,"buildReviewSubject");function G(n,e){const t=n.indexOf(`
1
+ var S=Object.defineProperty;var s=(n,e)=>S(n,"name",{value:e,configurable:!0});import{mkdirSync as q,writeFileSync as P}from"node:fs";import{join as k}from"node:path";import{defineLeaf as j}from"../../../core/command.js";import{InputError as l,readStdinRaw as M}from"../../../core/io.js";import{userScopeRoot as L}from"../../../core/scope.js";import{ApiError as O}from"../../../api/index.js";import{cliClient as _}from"../../api-client.js";import{readMergedLaunchConfig as D,subKindsAvailableTo as R}from"../../../core/config.js";import{LAUNCH_SYSTEM_PROMPT as p}from"../../../core/runtime/launch-prompt.js";import{renderPreferencesForSubject as T,renderKnowledgeForSubject as C}from"../../../core/substrate/render.js";import{effectiveScopes as N,scopeForCwd as U,profileNameFor as A}from"../../../core/substrate/subject-fields.js";function F(n,e){return e!==void 0?e:n==="orchestrator"?"resident":"terminal"}s(F,"resolveLifecycle");function I(n){try{return JSON.parse(n)}catch(e){throw new l({error:"invalid_json",message:`stdin is not valid JSON: ${String(e)}`,field:"stdin",next:"Pass the comments deck JSON on stdin."})}}s(I,"readJson");function $(n,e,r){if(n===void 0)return r;if(n===!0||n===!1)return n;if(typeof n!="string")throw new l({error:"invalid_field",message:`${e} must be true or false`,field:e,next:`Use true or false for ${e}.`});const t=n.trim().toLowerCase();if(t==="true")return!0;if(t==="false")return!1;throw new l({error:"invalid_field",message:`${e} must be true or false`,field:e,next:`Use true or false for ${e}.`})}s($,"parseBool");function K(n){return typeof n=="string"&&n.trim()!==""?n:null}s(K,"optionalString");function u(n){return Math.ceil(n.length/4)}s(u,"approxTokens");function E(){const n=D().kinds;return Object.entries(n).filter(([e])=>!e.includes("/")).map(([e,r])=>({kind:e,whenToUse:r.whenToUse})).sort((e,r)=>e.kind.localeCompare(r.kind))}s(E,"topLevelKinds");function J(n){return R(n)}s(J,"subKindsFor");function W(){const n=E(),e={};for(const{kind:r}of n)e[r]=J(r);return{kinds:n,modes:["base","orchestrator"],lifecycles:["terminal","resident"],subPersonas:e}}s(W,"reviewList");async function x(n){if(n===null)return null;try{return await _().getNode(n)}catch(e){if(e instanceof O&&e.status===404)return null;throw e}}s(x,"fetchNodeOrNull");async function z(n){let e=n;const r=new Set;let t=0;for(;e!==null&&!r.has(e);){r.add(e);const i=await x(e);if(i===null||i.parent==null)break;e=i.parent,t++}return t}s(z,"spineDepthViaApi");async function B(n,e,r,t,i){const c=i?.cwd??process.cwd();return{kind:n,mode:e,lifecycle:r,hasManager:t,cwd:c,scope:U(c),orchestration:{depth:i!==null?await z(i.node_id):0},profile:A(i?.profile_id),scopes:N(i?.scopes)}}s(B,"buildReviewSubject");function G(n,e){const t=n.indexOf(`
2
2
 
3
3
  Guidelines:`);return t===-1?`${n}
4
4
 
@@ -8,4 +8,4 @@ ${e}${n.slice(t)}`}s(G,"spliceIntoScaffold");function H(){const n=k(L(),"prompt-
8
8
  `).join(`
9
9
  > `)),e.push(t.body),e.push("");e[e.length-1]===""&&e.pop()}e.push(""),e.push("## Prompt sources (edit these)");const r=new Set;for(const t of n.sources){const i=`${t.scope}:${t.path}`;r.has(i)||(r.add(i),e.push(`- ${t.label} \u2014 \`${t.path}\` (${t.scope})`))}return e.push(""),e.push("These are review comments on an assembled system prompt; edit the listed source files to address them."),e.join(`
10
10
  `)+`
11
- `}s(V,"renderExportDeck");function Y(n){const e=H();return P(e,V(n),"utf8"),{path:e}}s(Y,"exportReview");async function Q(n){const e=n.kind,r=n.mode??"base",t=F(r,n.lifecycle),i=$(n.hasManager,"hasManager",!0),a=K(n.node);if(e===void 0||e.trim()==="")throw new l({error:"missing_parameter",message:"kind is required",field:"kind",next:"Pass --kind <kind> or use --list."});const c=await x(a),h=await B(e,r,t,i,c),{block:v,contentDocs:g,tree:d}=T(h),f=[{id:"launch-scaffold",label:"Launch scaffold",group:"generated",source:"generated: launch scaffold",sourcePath:null,scope:"generated",included:!0,condition:null,text:p,tokens:u(p),chars:p.length},...g.map(o=>({id:o.name,label:o.name,group:"substrate",source:`memory: ${o.name}`,sourcePath:o.path,scope:o.scope,included:!0,condition:null,text:o.body,tokens:u(o.body),chars:o.body.length}))];if(d!==""&&f.push({id:"preference-catalog",label:"Preference catalog (routing entries)",group:"substrate",source:"generated: preference catalog",sourcePath:null,scope:"generated",included:!0,condition:null,text:d,tokens:u(d),chars:d.length}),c!==null){const o=C(h,c.node_id);o!==""&&f.push({id:"memory-knowledge",label:"Memory (knowledge) \u2014 context message, not system prompt",group:"substrate",source:"runtime-spliced",sourcePath:null,scope:"runtime",included:!1,condition:"session_start context message, not the system prompt",text:o,tokens:u(o),chars:o.length})}const m=G(p,v),y=[],b=new Set;for(const o of g){const w=`${o.scope}:${o.path}`;b.has(w)||(b.add(w),y.push({id:o.name,label:o.name,path:o.path,scope:o.scope}))}return{config:{kind:e,mode:r,lifecycle:t,hasManager:i,node:c?.node_id??null},layers:f,assembled:m,total:{tokens:u(m),chars:m.length},sources:y}}s(Q,"resolveDeck");const ue=j({name:"prompt-review",description:"inspect an assembled prompt and export review notes",whenToUse:"you want to inspect a composed persona prompt for a kind/mode combo, compare the space around it, or export review notes back to source files",help:{name:"sys context prompt-review",summary:"inspect an assembled prompt and export review notes",params:[{kind:"positional",name:"action",type:"string",required:!1,constraint:"Optional subcommand: export. Omit for the assembled prompt contract."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Persona kind to inspect. Required unless --list or export."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,default:"base",constraint:"Persona mode. Default: base."},{kind:"flag",name:"lifecycle",type:"enum",choices:["terminal","resident"],required:!1,constraint:"Lifecycle axis. Default: base -> terminal, orchestrator -> resident."},{kind:"flag",name:"has-manager",type:"string",required:!1,default:"true",constraint:"Whether the node reports to a manager. Use true or false. Default: true."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Optional node id. When the node exists, runtime substrate layers are appended."},{kind:"flag",name:"list",type:"bool",required:!1,constraint:"List the available kinds, modes, lifecycles, and sub-personas."}],output:[{name:"config",type:"object",required:!1,constraint:"Resolved config: {kind, mode, lifecycle, hasManager, node}."},{name:"layers",type:"object[]",required:!1,constraint:"Ordered prompt layers, including excluded alternatives and provenance."},{name:"assembled",type:"string",required:!1,constraint:"The assembled prompt string."},{name:"total",type:"object",required:!1,constraint:"Approximate token/char totals for included layers."},{name:"sources",type:"object[]",required:!1,constraint:"De-duplicated source files referenced by the prompt."},{name:"kinds",type:"object[]",required:!1,constraint:"Available kinds for --list."},{name:"modes",type:"string[]",required:!1,constraint:"Mode choices for --list."},{name:"lifecycles",type:"string[]",required:!1,constraint:"Lifecycle choices for --list."},{name:"subPersonas",type:"object",required:!1,constraint:"Available sub-personas keyed by kind for --list."},{name:"path",type:"string",required:!1,constraint:"Written markdown path for export."}],outputKind:"object",effects:["Read-only inspection, or writes a review markdown file under `~/.crouter/prompt-reviews/`."]},run:s(async n=>{const e=n.action,r=n.list===!0,t=$(n.hasManager,"hasManager",!0);if(e!==void 0&&e!=="export")throw new l({error:"unknown_action",message:`unknown action: ${e}`,field:"action",next:"Use `export` or omit the positional action."});if(e==="export"){const a=await M(),c=I(a);return Y(c)}return r?W():await Q({...n,hasManager:t})},"run")});export{ue as promptReviewLeaf};
11
+ `}s(V,"renderExportDeck");function Y(n){const e=H();return P(e,V(n),"utf8"),{path:e}}s(Y,"exportReview");async function Q(n){const e=n.kind,r=n.mode??"base",t=F(r,n.lifecycle),i=$(n.hasManager,"hasManager",!0),c=K(n.node);if(e===void 0||e.trim()==="")throw new l({error:"missing_parameter",message:"kind is required",field:"kind",next:"Pass --kind <kind> or use --list."});const a=await x(c),h=await B(e,r,t,i,a),{block:v,contentDocs:g,tree:d}=T(h),f=[{id:"launch-scaffold",label:"Launch scaffold",group:"generated",source:"generated: launch scaffold",sourcePath:null,scope:"generated",included:!0,condition:null,text:p,tokens:u(p),chars:p.length},...g.map(o=>({id:o.name,label:o.name,group:"substrate",source:`memory: ${o.name}`,sourcePath:o.path,scope:o.scope,included:!0,condition:null,text:o.body,tokens:u(o.body),chars:o.body.length}))];if(d!==""&&f.push({id:"preference-catalog",label:"Preference catalog (routing entries)",group:"substrate",source:"generated: preference catalog",sourcePath:null,scope:"generated",included:!0,condition:null,text:d,tokens:u(d),chars:d.length}),a!==null){const o=C(h,a.node_id,void 0,void 0,a.grantee);o!==""&&f.push({id:"memory-knowledge",label:"Memory (knowledge) \u2014 context message, not system prompt",group:"substrate",source:"runtime-spliced",sourcePath:null,scope:"runtime",included:!1,condition:"session_start context message, not the system prompt",text:o,tokens:u(o),chars:o.length})}const m=G(p,v),y=[],b=new Set;for(const o of g){const w=`${o.scope}:${o.path}`;b.has(w)||(b.add(w),y.push({id:o.name,label:o.name,path:o.path,scope:o.scope}))}return{config:{kind:e,mode:r,lifecycle:t,hasManager:i,node:a?.node_id??null},layers:f,assembled:m,total:{tokens:u(m),chars:m.length},sources:y}}s(Q,"resolveDeck");const ue=j({name:"prompt-review",description:"inspect an assembled prompt and export review notes",whenToUse:"you want to inspect a composed persona prompt for a kind/mode combo, compare the space around it, or export review notes back to source files",help:{name:"sys context prompt-review",summary:"inspect an assembled prompt and export review notes",params:[{kind:"positional",name:"action",type:"string",required:!1,constraint:"Optional subcommand: export. Omit for the assembled prompt contract."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Persona kind to inspect. Required unless --list or export."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,default:"base",constraint:"Persona mode. Default: base."},{kind:"flag",name:"lifecycle",type:"enum",choices:["terminal","resident"],required:!1,constraint:"Lifecycle axis. Default: base -> terminal, orchestrator -> resident."},{kind:"flag",name:"has-manager",type:"string",required:!1,default:"true",constraint:"Whether the node reports to a manager. Use true or false. Default: true."},{kind:"flag",name:"node",type:"string",required:!1,constraint:"Optional node id. When the node exists, runtime substrate layers are appended."},{kind:"flag",name:"list",type:"bool",required:!1,constraint:"List the available kinds, modes, lifecycles, and sub-personas."}],output:[{name:"config",type:"object",required:!1,constraint:"Resolved config: {kind, mode, lifecycle, hasManager, node}."},{name:"layers",type:"object[]",required:!1,constraint:"Ordered prompt layers, including excluded alternatives and provenance."},{name:"assembled",type:"string",required:!1,constraint:"The assembled prompt string."},{name:"total",type:"object",required:!1,constraint:"Approximate token/char totals for included layers."},{name:"sources",type:"object[]",required:!1,constraint:"De-duplicated source files referenced by the prompt."},{name:"kinds",type:"object[]",required:!1,constraint:"Available kinds for --list."},{name:"modes",type:"string[]",required:!1,constraint:"Mode choices for --list."},{name:"lifecycles",type:"string[]",required:!1,constraint:"Lifecycle choices for --list."},{name:"subPersonas",type:"object",required:!1,constraint:"Available sub-personas keyed by kind for --list."},{name:"path",type:"string",required:!1,constraint:"Written markdown path for export."}],outputKind:"object",effects:["Read-only inspection, or writes a review markdown file under `~/.crouter/prompt-reviews/`."]},run:s(async n=>{const e=n.action,r=n.list===!0,t=$(n.hasManager,"hasManager",!0);if(e!==void 0&&e!=="export")throw new l({error:"unknown_action",message:`unknown action: ${e}`,field:"action",next:"Use `export` or omit the positional action."});if(e==="export"){const c=await M(),a=I(c);return Y(a)}return r?W():await Q({...n,hasManager:t})},"run")});export{ue as promptReviewLeaf};
@@ -1,10 +1,10 @@
1
- var R=Object.defineProperty;var d=(e,n)=>R(e,"name",{value:n,configurable:!0});import{existsSync as $}from"node:fs";import{resolve as h}from"node:path";import{defineLeaf as S}from"../../../core/command.js";import{InputError as I}from"../../../core/io.js";import{ApiError as g}from"../../../api/index.js";import{cliClient as y}from"../../api-client.js";import{envNodeId as D,envProfileId as q}from"../../../shared/env.js";import{realpathOrSelf as u}from"../../../core/fs-utils.js";import{ambientMemoryTarget as C,resolveMemoryDocForTarget as N}from"../../../core/memory-resolver.js";import{planDelivery as v}from"../../../core/substrate/plan.js";import{explainRecordGate as m,formatClause as E}from"../../../core/substrate/gate-explain.js";import{emptyContextExposureState as F,exposureTarget as P}from"../../../core/substrate/injected-store.js";import{renderPreferencesForSubject as T,renderKnowledgeForSubject as O}from"../../../core/substrate/render.js";import{deliveryAccounting as M,memoryReadDocBlocks as B,renderOnCommandDocsForSubject as G,renderOnReadDocsForSubject as A,renderPreCommandDocsForSubject as L,renderWorkspaceOpenDocsForSubject as W}from"../../../core/substrate/on-read.js";import{clearSessionCache as w}from"../../../core/substrate/session-cache.js";import{parseSubstrateDoc as K,rungAtLeast as b,SURFACE_EVENTS as _}from"../../../core/substrate/schema.js";import{effectiveScopes as U,scopeForCwd as V,profileNameFor as z}from"../../../core/substrate/subject-fields.js";import{resetScopeCache as x}from"../../../core/scope.js";import{getDefaultProfileId as H}from"../../../core/profiles/default-binding.js";const Te=S({name:"resolve",description:"resolve what a configuration snapshot loads for one surface event",whenToUse:"you are asking what a node (or a hypothetical configuration) actually receives \u2014 at boot, on opening a workspace, on reading a file, on a memory read, or around a command",help:{name:"sys context resolve",summary:"resolve the documents a configuration snapshot loads for one surface event",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Resolve for this live node \u2014 derives kind, mode, lifecycle, has-manager, profile, and cwd from it. A node id that does not exist degrades to a synthetic subject and says so."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Node kind of the synthetic subject. Defaults to the --node value, else `general`."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,constraint:"Node mode of the synthetic subject. Defaults to `base`."},{kind:"flag",name:"lifecycle",type:"enum",choices:["terminal","resident"],required:!1,constraint:"Node lifecycle of the synthetic subject. Defaults to `terminal` for base, `resident` for orchestrator."},{kind:"flag",name:"has-manager",type:"enum",choices:["true","false"],required:!1,constraint:"Treat the subject as having a manager (a subscriber above it). Defaults to the --node value, else true."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id whose memory store and project-memory caps apply. Defaults to the selected profile."},{kind:"flag",name:"cwd",type:"path",required:!1,constraint:"Directory the project stores resolve from. Defaults to the current directory."},{kind:"flag",name:"event",type:"enum",choices:[..._],required:!1,constraint:"The surface event to resolve. Defaults to `boot`. Ignored when --all-events is set."},{kind:"flag",name:"all-events",type:"bool",required:!1,constraint:"Resolve every surface event instead of one, and report each plan separately."},{kind:"flag",name:"file",type:"path",required:!1,constraint:"Payload for `--event read`: the file that was read. Without it, no read entry matches."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Payload for `--event memory-read`: the exact canonical name the read resolved to."},{kind:"flag",name:"command",type:"string",required:!1,constraint:"Payload for `--event command` / `--event pre-command`: the command string."},{kind:"flag",name:"granularity",type:"enum",choices:["summary","docs","assembled"],required:!1,constraint:"`summary` folds to per-rung counts; `docs` reports one row per document; `assembled` returns the real rendered text by calling the event\u2019s renderer. Defaults to `docs`. `--all` applies only at `docs` granularity; with `assembled` it is reported as ignored."},{kind:"flag",name:"all",type:"bool",required:!1,constraint:"At `docs` granularity, include every considered document, not just the ones that deliver \u2014 shadowed, gated-out, and capped-to-none documents with the reason each was excluded. Ignored at `summary` and `assembled` granularity."}],output:[{name:"event",type:"string",required:!1,constraint:"The resolved event. Absent with --all-events, where every entry in `plans` carries its own."},{name:"subject",type:"object",required:!0,constraint:"The configuration snapshot used: kind, mode, lifecycle, hasManager, profile, scope."},{name:"target",type:"object",required:!0,constraint:"Store resolution inputs: cwd, profileId, nodeId."},{name:"docs",type:"array",required:!1,constraint:"One entry per document, at `docs`/`all` granularity: name, kind, scope, store_path, authored_rung, project_memory_cap, capped_rung, final_rung, winner, shadowed_by, doc_gate, entry_gate, matched_entry, delivery_cause when the renderer raised it through a content attachment, and excluded when --all includes a non-delivering document."},{name:"counts",type:"object",required:!1,constraint:"At `summary` granularity: {considered, delivered: {content, preview, name}, delivered_total, excluded: {<reason>: count}}."},{name:"all_ignored",type:"boolean",required:!1,constraint:"Present only when --all is supplied with --granularity assembled; true means assembled text is unchanged because --all applies only to docs granularity."},{name:"assembled",type:"string",required:!1,constraint:"At `assembled` granularity: the exact text the node would receive for this event."},{name:"plans",type:"array",required:!1,constraint:"With --all-events: one plan result per surface event, each shaped as above."},{name:"node_missing",type:"boolean",required:!1,constraint:"Present when --node named a node that does not exist and a synthetic subject was used instead."}],outputKind:"object",effects:["None. Read-only."]},run:d(async e=>{const n=await J(e),o=e.granularity??"docs",t=e.all===!0,a=e.allEvents===!0?[..._]:[e.event??"boot"],s={file:l(e.file),readName:l(e.name),command:l(e.command)},r=a.map(c=>ne(n,c,Q(c,s,n.target),o,t)),i={subject:X(n.subject),target:n.target,...n.nodeMissing?{node_missing:!0}:{},...o==="assembled"&&t?{all_ignored:!0}:{}};return a.length===1?{...i,...r[0]}:{...i,plans:r}},"run"),render:d(e=>ue(e),"render")});async function J(e){const n=l(e.node),o=await Z(n),t=o===null?null:await ee(o.node_id),a=e.mode??t?.mode??"base",s=e.lifecycle??t?.lifecycle??(a==="orchestrator"?"resident":"terminal"),r=Y(l(e.cwd)??t?.cwd??process.cwd()),i=l(e.profile)??o?.profile_id??C().profileId??H(r),c=l(e.hasManager);return{subject:{kind:l(e.kind)??t?.kind??"general",mode:a,lifecycle:s,hasManager:c===null?t?.hasManager??!0:c==="true",cwd:r,scope:V(r),orchestration:{depth:t?.orchestration.depth??0},profile:z(i),scopes:t?.scopes??U(null)},target:{cwd:r,profileId:i,nodeId:o?.node_id??null},nodeMissing:n!==null&&o===null}}d(J,"buildSnapshot");function Q(e,n,o){return e==="read"?n.file===null?{}:{absoluteFile:h(n.file)}:e==="memory-read"?n.readName===null?{}:{resolvedCanonicalName:n.readName,resolvedDocPath:le(n.readName,o)}:e==="command"||e==="pre-command"?n.command===null?{}:{command:n.command}:{}}d(Q,"payloadFor");function X(e){return{kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,hasManager:e.hasManager,scope:e.scope,profile:e.profile,depth:e.orchestration.depth}}d(X,"subjectSummary");function Y(e){const n=h(e);if(!$(n))throw new I({error:"invalid_field",message:`cwd does not exist: ${n}`,field:"cwd",next:"Pass --cwd a directory that exists, or omit it to use the current directory."});return u(n)}d(Y,"resolveCwd");function l(e){return typeof e=="string"&&e.trim()!==""?e:null}d(l,"optionalString");async function Z(e){if(e===null)return null;try{return await y().getNode(e)}catch(n){if(n instanceof g&&n.status===404)return null;throw n}}d(Z,"fetchNodeOrNull");async function ee(e){try{return await y().nodeSubject(e)}catch(n){if(n instanceof g&&n.status===404)return null;throw n}}d(ee,"fetchSubjectOrNull");function ne(e,n,o,t,a){const s=ie(e,n,o);if(t==="assembled")return{event:n,assembled:s.assembled};const r=te(v(e.subject,e.target,n,o),s.accounting.deliveries,o);if(t==="summary")return{event:n,counts:se(r)};const i=r.docs.filter(c=>a||p(c)).map(c=>re(c,a,r.subject));return{event:n,docs:i}}d(ne,"planSection");function te(e,n,o={}){const t=new Set,a=e.docs.map(s=>{t.add(u(s.doc.path));const r=n.get(u(s.doc.path));if(r===void 0||!b(r.rung,s.finalRung))return s;const i=r.rung!==s.finalRung;return{...s,...i?{winner:!0,shadowedBy:null}:{},finalRung:r.rung,...i&&r.cause!==void 0?{deliveryCause:r.cause}:{}}});for(const s of n.values()){if(s.source===void 0||t.has(u(s.source.path)))continue;const r=K(s.source);if(r===null)continue;const i=v(e.subject,e.target,e.event,o,[{doc:r,source:s.source}]).docs[0];i!==void 0&&a.push({...i,winner:!0,shadowedBy:null,finalRung:s.rung,...s.cause===void 0?{}:{deliveryCause:s.cause}})}return{...e,docs:a}}d(te,"effectivePlan");function p(e){return e.winner&&b(e.finalRung,"name")}d(p,"delivers");function re(e,n,o){const t={name:e.name,kind:e.kind,scope:e.scope,store_path:e.storePath,authored_rung:e.authoredRung,project_memory_cap:e.projectMemoryCap,capped_rung:e.cappedRung,final_rung:e.finalRung,winner:e.winner,shadowed_by:e.shadowedBy===null?null:`${e.shadowedBy.scope}:${e.shadowedBy.path}`,doc_gate:j(e.docGate,m(e,"doc",o)),entry_gate:e.entryGate===null?null:j(e.entryGate,m(e,"entry",o)),matched_entry:oe(e.matchedEntry),...e.deliveryCause===void 0?{}:{delivery_cause:e.deliveryCause}};return n&&!p(e)&&(t.excluded=ae(e,o)),t}d(re,"docRow");function j(e,n){return e.pass?"pass":`fail: ${k(e.reason,n)}`}d(j,"gateText");function k(e,n){return n.length===0?e:n.map(E).join("; ")}d(k,"gateReason");function oe(e){if(e===null)return null;const n=[`at=${e.at}`];return e.match!==void 0&&n.push(`match=${e.match.join(",")}`),e.matchFrontmatter!==void 0&&n.push("match-frontmatter"),e.gate!==void 0&&n.push("gate"),n.join(" ")}d(oe,"entryText");function ae(e,n){return e.docGate.pass?e.shadowedBy!==null?`shadowed by ${e.shadowedBy.scope}:${e.shadowedBy.path}`:e.authoredEntries.length===0?"no surface entry for this event":e.matchedEntry===null?e.entryGate!==null&&!e.entryGate.pass?`entry gate: ${k(e.entryGate.reason,m(e,"entry",n))}`:"no authored entry matched this event\u2019s payload":e.cappedRung==="none"?`capped to none by the profile\u2019s project-memory setting (authored ${e.authoredRung})`:`resolved to rung none (authored ${e.authoredRung})`:"document gate"}d(ae,"exclusionReason");function se(e){const n={content:0,preview:0,name:0},o={};for(const t of e.docs){if(p(t)){n[t.finalRung]=(n[t.finalRung]??0)+1;continue}const a=de(t);o[a]=(o[a]??0)+1}return{considered:e.docs.length,delivered:n,delivered_total:n.content+n.preview+n.name,excluded:o}}d(se,"countsOf");function de(e){return e.docGate.pass?e.shadowedBy!==null?"shadowed":e.authoredEntries.length===0?"no_entry":e.matchedEntry===null?e.entryGate!==null&&!e.entryGate.pass?"entry_gate":"no_match":e.cappedRung==="none"?"capped":"rung_none":"document_gate"}d(de,"exclusionBucket");function ie(e,n,o){const t={cwd:process.cwd(),profileId:q(),nodeId:D()},a=M();w(),x();try{return process.chdir(e.target.cwd),f("CRTR_PROFILE_ID",e.target.profileId??void 0),f("CRTR_NODE_ID",e.target.nodeId??void 0),{assembled:ce(e,n,o,a),accounting:a}}finally{process.chdir(t.cwd),f("CRTR_PROFILE_ID",t.profileId),f("CRTR_NODE_ID",t.nodeId),w(),x()}}d(ie,"assembleEventAccounting");function f(e,n){n===void 0?delete process.env[e]:process.env[e]=n}d(f,"setEnv");function ce(e,n,o,t){const{subject:a,target:s}=e;switch(n){case"boot":{const{block:r}=T(a,void 0,t),i=s.nodeId===null?"":O(a,s.nodeId,void 0,t);return i===""?r:`${r}
1
+ var k=Object.defineProperty;var d=(e,n)=>k(e,"name",{value:n,configurable:!0});import{existsSync as $}from"node:fs";import{resolve as h}from"node:path";import{defineLeaf as S}from"../../../core/command.js";import{InputError as I}from"../../../core/io.js";import{ApiError as g}from"../../../api/index.js";import{cliClient as y}from"../../api-client.js";import{envGrantee as D,envNodeId as C,envProfileId as E}from"../../../shared/env.js";import{realpathOrSelf as f}from"../../../core/fs-utils.js";import{ambientMemoryTarget as N,resolveMemoryDocForTarget as q}from"../../../core/memory-resolver.js";import{planDelivery as v}from"../../../core/substrate/plan.js";import{explainRecordGate as m,formatClause as T}from"../../../core/substrate/gate-explain.js";import{emptyContextExposureState as F,exposureTarget as P}from"../../../core/substrate/injected-store.js";import{renderPreferencesForSubject as G,renderKnowledgeForSubject as O}from"../../../core/substrate/render.js";import{deliveryAccounting as M,memoryReadDocBlocks as A,renderOnCommandDocsForSubject as B,renderOnReadDocsForSubject as L,renderPreCommandDocsForSubject as W,renderWorkspaceOpenDocsForSubject as K}from"../../../core/substrate/on-read.js";import{clearSessionCache as w}from"../../../core/substrate/session-cache.js";import{parseSubstrateDoc as U,rungAtLeast as b,SURFACE_EVENTS as _}from"../../../core/substrate/schema.js";import{effectiveScopes as V,scopeForCwd as z,profileNameFor as H}from"../../../core/substrate/subject-fields.js";import{resetScopeCache as x}from"../../../core/scope.js";import{getDefaultProfileId as J}from"../../../core/profiles/default-binding.js";const Ge=S({name:"resolve",description:"resolve what a configuration snapshot loads for one surface event",whenToUse:"you are asking what a node (or a hypothetical configuration) actually receives \u2014 at boot, on opening a workspace, on reading a file, on a memory read, or around a command",help:{name:"sys context resolve",summary:"resolve the documents a configuration snapshot loads for one surface event",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Resolve for this live node \u2014 derives kind, mode, lifecycle, has-manager, profile, and cwd from it. A node id that does not exist degrades to a synthetic subject and says so."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Node kind of the synthetic subject. Defaults to the --node value, else `general`."},{kind:"flag",name:"mode",type:"enum",choices:["base","orchestrator"],required:!1,constraint:"Node mode of the synthetic subject. Defaults to `base`."},{kind:"flag",name:"lifecycle",type:"enum",choices:["terminal","resident"],required:!1,constraint:"Node lifecycle of the synthetic subject. Defaults to `terminal` for base, `resident` for orchestrator."},{kind:"flag",name:"has-manager",type:"enum",choices:["true","false"],required:!1,constraint:"Treat the subject as having a manager (a subscriber above it). Defaults to the --node value, else true."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Profile id whose memory store and project-memory caps apply. Defaults to the selected profile."},{kind:"flag",name:"cwd",type:"path",required:!1,constraint:"Directory the project stores resolve from. Defaults to the current directory."},{kind:"flag",name:"event",type:"enum",choices:[..._],required:!1,constraint:"The surface event to resolve. Defaults to `boot`. Ignored when --all-events is set."},{kind:"flag",name:"all-events",type:"bool",required:!1,constraint:"Resolve every surface event instead of one, and report each plan separately."},{kind:"flag",name:"file",type:"path",required:!1,constraint:"Payload for `--event read`: the file that was read. Without it, no read entry matches."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Payload for `--event memory-read`: the exact canonical name the read resolved to."},{kind:"flag",name:"command",type:"string",required:!1,constraint:"Payload for `--event command` / `--event pre-command`: the command string."},{kind:"flag",name:"granularity",type:"enum",choices:["summary","docs","assembled"],required:!1,constraint:"`summary` folds to per-rung counts; `docs` reports one row per document; `assembled` returns the real rendered text by calling the event\u2019s renderer. Defaults to `docs`. `--all` applies only at `docs` granularity; with `assembled` it is reported as ignored."},{kind:"flag",name:"all",type:"bool",required:!1,constraint:"At `docs` granularity, include every considered document, not just the ones that deliver \u2014 shadowed, gated-out, and capped-to-none documents with the reason each was excluded. Ignored at `summary` and `assembled` granularity."}],output:[{name:"event",type:"string",required:!1,constraint:"The resolved event. Absent with --all-events, where every entry in `plans` carries its own."},{name:"subject",type:"object",required:!0,constraint:"The configuration snapshot used: kind, mode, lifecycle, hasManager, profile, scope."},{name:"target",type:"object",required:!0,constraint:"Store resolution inputs: cwd, profileId, nodeId."},{name:"docs",type:"array",required:!1,constraint:"One entry per document, at `docs`/`all` granularity: name, kind, scope, store_path, authored_rung, project_memory_cap, capped_rung, final_rung, winner, shadowed_by, doc_gate, entry_gate, matched_entry, delivery_cause when the renderer raised it through a content attachment, and excluded when --all includes a non-delivering document."},{name:"counts",type:"object",required:!1,constraint:"At `summary` granularity: {considered, delivered: {content, preview, name}, delivered_total, excluded: {<reason>: count}}."},{name:"all_ignored",type:"boolean",required:!1,constraint:"Present only when --all is supplied with --granularity assembled; true means assembled text is unchanged because --all applies only to docs granularity."},{name:"assembled",type:"string",required:!1,constraint:"At `assembled` granularity: the exact text the node would receive for this event."},{name:"plans",type:"array",required:!1,constraint:"With --all-events: one plan result per surface event, each shaped as above."},{name:"node_missing",type:"boolean",required:!1,constraint:"Present when --node named a node that does not exist and a synthetic subject was used instead."}],outputKind:"object",effects:["None. Read-only."]},run:d(async e=>{const n=await Q(e),t=e.granularity??"docs",r=e.all===!0,s=e.allEvents===!0?[..._]:[e.event??"boot"],a={file:l(e.file),readName:l(e.name),command:l(e.command)},o=s.map(c=>te(n,c,X(c,a,n.target),t,r)),i={subject:Y(n.subject),target:n.target,...n.nodeMissing?{node_missing:!0}:{},...t==="assembled"&&r?{all_ignored:!0}:{}};return s.length===1?{...i,...o[0]}:{...i,plans:o}},"run"),render:d(e=>fe(e),"render")});async function Q(e){const n=l(e.node),t=await ee(n),r=t===null?null:await ne(t.node_id),s=e.mode??r?.mode??"base",a=e.lifecycle??r?.lifecycle??(s==="orchestrator"?"resident":"terminal"),o=Z(l(e.cwd)??r?.cwd??process.cwd()),i=l(e.profile)??t?.profile_id??N().profileId??J(o),c=l(e.hasManager);return{subject:{kind:l(e.kind)??r?.kind??"general",mode:s,lifecycle:a,hasManager:c===null?r?.hasManager??!0:c==="true",cwd:o,scope:z(o),orchestration:{depth:r?.orchestration.depth??0},profile:H(i),scopes:r?.scopes??V(null)},target:{cwd:o,profileId:i,nodeId:t?.node_id??null,...t===null?{}:{grantee:t.grantee}},nodeMissing:n!==null&&t===null}}d(Q,"buildSnapshot");function X(e,n,t){return e==="read"?n.file===null?{}:{absoluteFile:h(n.file)}:e==="memory-read"?n.readName===null?{}:{resolvedCanonicalName:n.readName,resolvedDocPath:ue(n.readName,t)}:e==="command"||e==="pre-command"?n.command===null?{}:{command:n.command}:{}}d(X,"payloadFor");function Y(e){return{kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,hasManager:e.hasManager,scope:e.scope,profile:e.profile,depth:e.orchestration.depth}}d(Y,"subjectSummary");function Z(e){const n=h(e);if(!$(n))throw new I({error:"invalid_field",message:`cwd does not exist: ${n}`,field:"cwd",next:"Pass --cwd a directory that exists, or omit it to use the current directory."});return f(n)}d(Z,"resolveCwd");function l(e){return typeof e=="string"&&e.trim()!==""?e:null}d(l,"optionalString");async function ee(e){if(e===null)return null;try{return await y().getNode(e)}catch(n){if(n instanceof g&&n.status===404)return null;throw n}}d(ee,"fetchNodeOrNull");async function ne(e){try{return await y().nodeSubject(e)}catch(n){if(n instanceof g&&n.status===404)return null;throw n}}d(ne,"fetchSubjectOrNull");function te(e,n,t,r,s){const a=ce(e,n,t);if(r==="assembled")return{event:n,assembled:a.assembled};const o=re(v(e.subject,e.target,n,t),a.accounting.deliveries,t);if(r==="summary")return{event:n,counts:de(o)};const i=o.docs.filter(c=>s||p(c)).map(c=>oe(c,s,o.subject));return{event:n,docs:i}}d(te,"planSection");function re(e,n,t={}){const r=new Set,s=e.docs.map(a=>{r.add(f(a.doc.path));const o=n.get(f(a.doc.path));if(o===void 0||!b(o.rung,a.finalRung))return a;const i=o.rung!==a.finalRung;return{...a,...i?{winner:!0,shadowedBy:null}:{},finalRung:o.rung,...i&&o.cause!==void 0?{deliveryCause:o.cause}:{}}});for(const a of n.values()){if(a.source===void 0||r.has(f(a.source.path)))continue;const o=U(a.source);if(o===null)continue;const i=v(e.subject,e.target,e.event,t,[{doc:o,source:a.source}]).docs[0];i!==void 0&&s.push({...i,winner:!0,shadowedBy:null,finalRung:a.rung,...a.cause===void 0?{}:{deliveryCause:a.cause}})}return{...e,docs:s}}d(re,"effectivePlan");function p(e){return e.winner&&b(e.finalRung,"name")}d(p,"delivers");function oe(e,n,t){const r={name:e.name,kind:e.kind,scope:e.scope,store_path:e.storePath,authored_rung:e.authoredRung,project_memory_cap:e.projectMemoryCap,capped_rung:e.cappedRung,final_rung:e.finalRung,winner:e.winner,shadowed_by:e.shadowedBy===null?null:`${e.shadowedBy.scope}:${e.shadowedBy.path}`,doc_gate:j(e.docGate,m(e,"doc",t)),entry_gate:e.entryGate===null?null:j(e.entryGate,m(e,"entry",t)),matched_entry:ae(e.matchedEntry),...e.deliveryCause===void 0?{}:{delivery_cause:e.deliveryCause}};return n&&!p(e)&&(r.excluded=se(e,t)),r}d(oe,"docRow");function j(e,n){return e.pass?"pass":`fail: ${R(e.reason,n)}`}d(j,"gateText");function R(e,n){return n.length===0?e:n.map(T).join("; ")}d(R,"gateReason");function ae(e){if(e===null)return null;const n=[`at=${e.at}`];return e.match!==void 0&&n.push(`match=${e.match.join(",")}`),e.matchFrontmatter!==void 0&&n.push("match-frontmatter"),e.gate!==void 0&&n.push("gate"),n.join(" ")}d(ae,"entryText");function se(e,n){return e.docGate.pass?e.shadowedBy!==null?`shadowed by ${e.shadowedBy.scope}:${e.shadowedBy.path}`:e.authoredEntries.length===0?"no surface entry for this event":e.matchedEntry===null?e.entryGate!==null&&!e.entryGate.pass?`entry gate: ${R(e.entryGate.reason,m(e,"entry",n))}`:"no authored entry matched this event\u2019s payload":e.cappedRung==="none"?`capped to none by the profile\u2019s project-memory setting (authored ${e.authoredRung})`:`resolved to rung none (authored ${e.authoredRung})`:"document gate"}d(se,"exclusionReason");function de(e){const n={content:0,preview:0,name:0},t={};for(const r of e.docs){if(p(r)){n[r.finalRung]=(n[r.finalRung]??0)+1;continue}const s=ie(r);t[s]=(t[s]??0)+1}return{considered:e.docs.length,delivered:n,delivered_total:n.content+n.preview+n.name,excluded:t}}d(de,"countsOf");function ie(e){return e.docGate.pass?e.shadowedBy!==null?"shadowed":e.authoredEntries.length===0?"no_entry":e.matchedEntry===null?e.entryGate!==null&&!e.entryGate.pass?"entry_gate":"no_match":e.cappedRung==="none"?"capped":"rung_none":"document_gate"}d(ie,"exclusionBucket");function ce(e,n,t){const r={cwd:process.cwd(),profileId:E(),nodeId:C(),grantee:D()},s=M();w(),x();try{return process.chdir(e.target.cwd),u("CRTR_PROFILE_ID",e.target.profileId??void 0),u("CRTR_NODE_ID",e.target.nodeId??void 0),u("CRTR_GRANTEE",e.target.grantee),{assembled:le(e,n,t,s),accounting:s}}finally{process.chdir(r.cwd),u("CRTR_PROFILE_ID",r.profileId),u("CRTR_NODE_ID",r.nodeId),u("CRTR_GRANTEE",r.grantee),w(),x()}}d(ce,"assembleEventAccounting");function u(e,n){n===void 0?delete process.env[e]:process.env[e]=n}d(u,"setEnv");function le(e,n,t,r){const{subject:s,target:a}=e;switch(n){case"boot":{const{block:o}=G(s,void 0,r),i=a.nodeId===null?"":O(s,a.nodeId,void 0,r,a.grantee);return i===""?o:`${o}
2
2
 
3
- ${i}`}case"workspace-open":return W(a,s.cwd,s.profileId,void 0,t);case"read":return o.absoluteFile===void 0?"":A(a,o.absoluteFile,void 0,t);case"memory-read":{const r=o.resolvedCanonicalName;if(r===void 0)return"";const i=B(o.resolvedDocPath??"",r,{subject:a,target:P(F(),"transcript"),listings:"blocks",accounting:t});return i.length===0?"":`<auto-loaded-context>
3
+ ${i}`}case"workspace-open":return K(s,a.cwd,a.profileId,void 0,r);case"read":return t.absoluteFile===void 0?"":L(s,t.absoluteFile,void 0,r);case"memory-read":{const o=t.resolvedCanonicalName;if(o===void 0)return"";const i=A(t.resolvedDocPath??"",o,{subject:s,target:P(F(),"transcript"),listings:"blocks",accounting:r});return i.length===0?"":`<auto-loaded-context>
4
4
  ${i.join(`
5
5
  `)}
6
- </auto-loaded-context>`}case"command":return o.command===void 0?"":G(a,o.command,void 0,t);case"pre-command":return o.command===void 0?"":L(a,o.command,void 0,t)}}d(ce,"renderEvent");function le(e,n){try{return u(N(e,n).path)}catch{return""}}d(le,"resolvedDocRealpath");function ue(e){const n=[];e.node_missing===!0&&n.push("The id passed to --node names no node; a synthetic subject was used instead.",""),n.push(`subject: ${fe(e.subject)}`),n.push(`target: cwd=${e.target.cwd} profile=${e.target.profileId??"(none)"} node=${e.target.nodeId??"(none)"}`),e.all_ignored===!0&&n.push("Note: --all applies only at docs granularity and was ignored for assembled output.");const o=e.plans??[{event:e.event,docs:e.docs,counts:e.counts,assembled:e.assembled}];for(const t of o)n.push("",`## ${t.event}`,"",me(t));return n.join(`
7
- `)}d(ue,"renderResolve");function fe(e){return["kind","mode","lifecycle","hasManager","scope","profile","depth"].map(n=>`${n}=${String(e[n])}`).join(" ")}d(fe,"describeSubject");function me(e){if(e.assembled!==void 0)return e.assembled===""?"Nothing is delivered for this event.":["```",e.assembled,"```"].join(`
8
- `);if(e.counts!==void 0)return pe(e.counts);const n=e.docs??[];if(n.length===0)return"No document delivers for this event.";const o=n.some(r=>r.excluded!==void 0),t=n.some(r=>r.delivery_cause!==void 0),a=["document","scope","kind","authored","cap","final","matched","gate",...t?["cause"]:[],...o?["excluded"]:[]],s=n.map(r=>[r.name,r.scope,r.kind,r.authored_rung,r.project_memory_cap??"\u2014",r.final_rung,r.matched_entry??"\u2014",r.doc_gate,...t?[r.delivery_cause??""]:[],...o?[r.excluded??""]:[]]);return[`${n.length} document${n.length===1?"":"s"}:`,"",`| ${a.join(" | ")} |`,`| ${a.map(()=>"---").join(" | ")} |`,...s.map(r=>`| ${r.map(he).join(" | ")} |`)].join(`
9
- `)}d(me,"renderSection");function pe(e){const n=e.delivered,o=e.excluded,t=Object.keys(o).length===0?"none":Object.entries(o).map(([a,s])=>`${a}=${s}`).join(" ");return[`- considered: ${String(e.considered)}`,`- delivered: ${String(e.delivered_total)} (content=${n.content} preview=${n.preview} name=${n.name})`,`- excluded: ${t}`].join(`
10
- `)}d(pe,"renderCounts");function he(e){return String(e).replace(/\|/g,"\\|").replace(/\n/g," ")}d(he,"cell");export{ie as assembleEventAccounting,J as buildSnapshot,he as cell,p as delivers,fe as describeSubject,re as docRow,te as effectivePlan,oe as entryText,ae as exclusionReason,j as gateText,l as optionalString,Q as payloadFor,Te as resolveLeaf,X as subjectSummary};
6
+ </auto-loaded-context>`}case"command":return t.command===void 0?"":B(s,t.command,void 0,r);case"pre-command":return t.command===void 0?"":W(s,t.command,void 0,r)}}d(le,"renderEvent");function ue(e,n){try{return f(q(e,n).path)}catch{return""}}d(ue,"resolvedDocRealpath");function fe(e){const n=[];e.node_missing===!0&&n.push("The id passed to --node names no node; a synthetic subject was used instead.",""),n.push(`subject: ${me(e.subject)}`),n.push(`target: cwd=${e.target.cwd} profile=${e.target.profileId??"(none)"} node=${e.target.nodeId??"(none)"}`),e.all_ignored===!0&&n.push("Note: --all applies only at docs granularity and was ignored for assembled output.");const t=e.plans??[{event:e.event,docs:e.docs,counts:e.counts,assembled:e.assembled}];for(const r of t)n.push("",`## ${r.event}`,"",pe(r));return n.join(`
7
+ `)}d(fe,"renderResolve");function me(e){return["kind","mode","lifecycle","hasManager","scope","profile","depth"].map(n=>`${n}=${String(e[n])}`).join(" ")}d(me,"describeSubject");function pe(e){if(e.assembled!==void 0)return e.assembled===""?"Nothing is delivered for this event.":["```",e.assembled,"```"].join(`
8
+ `);if(e.counts!==void 0)return he(e.counts);const n=e.docs??[];if(n.length===0)return"No document delivers for this event.";const t=n.some(o=>o.excluded!==void 0),r=n.some(o=>o.delivery_cause!==void 0),s=["document","scope","kind","authored","cap","final","matched","gate",...r?["cause"]:[],...t?["excluded"]:[]],a=n.map(o=>[o.name,o.scope,o.kind,o.authored_rung,o.project_memory_cap??"\u2014",o.final_rung,o.matched_entry??"\u2014",o.doc_gate,...r?[o.delivery_cause??""]:[],...t?[o.excluded??""]:[]]);return[`${n.length} document${n.length===1?"":"s"}:`,"",`| ${s.join(" | ")} |`,`| ${s.map(()=>"---").join(" | ")} |`,...a.map(o=>`| ${o.map(ge).join(" | ")} |`)].join(`
9
+ `)}d(pe,"renderSection");function he(e){const n=e.delivered,t=e.excluded,r=Object.keys(t).length===0?"none":Object.entries(t).map(([s,a])=>`${s}=${a}`).join(" ");return[`- considered: ${String(e.considered)}`,`- delivered: ${String(e.delivered_total)} (content=${n.content} preview=${n.preview} name=${n.name})`,`- excluded: ${r}`].join(`
10
+ `)}d(he,"renderCounts");function ge(e){return String(e).replace(/\|/g,"\\|").replace(/\n/g," ")}d(ge,"cell");export{ce as assembleEventAccounting,Q as buildSnapshot,ge as cell,p as delivers,me as describeSubject,oe as docRow,re as effectivePlan,ae as entryText,se as exclusionReason,j as gateText,l as optionalString,X as payloadFor,Ge as resolveLeaf,Y as subjectSummary};
@@ -1,4 +1,4 @@
1
- var l=Object.defineProperty;var i=(t,e)=>l(t,"name",{value:e,configurable:!0});import{envNodeId as f}from"../../../shared/env.js";import{existsSync as h,readFileSync as y,statSync as g,writeFileSync as x}from"node:fs";import{tmpdir as _}from"node:os";import{join as p}from"node:path";import{defineLeaf as b}from"../../../core/command.js";import{InputError as n}from"../../../core/io.js";import{jobDir as $}from"../../../core/canvas/paths.js";import{openNodeWindow as v}from"../../../core/runtime/placement-tmux.js";import{ApiError as q}from"../../../api/index.js";import{cliClient as c}from"../../api-client.js";import{shellQuote as k}from"../../../shared/shell-quote.js";const A=b({name:"sysprompt",description:"print a node's assembled system prompt",whenToUse:"you want to inspect a node's assembled system prompt headlessly, without paying conversation/context cost \u2014 the broker writes it to disk while live, and this command reads that artifact back as markdown.",help:{name:"sys context sysprompt",summary:"print a node's assembled system prompt",params:[{kind:"positional",name:"node",required:!1,constraint:"Node id. Defaults to the calling node (CRTR_NODE_ID)."},{kind:"flag",name:"window",type:"bool",required:!1,constraint:"Open the assembled prompt in a NEW tmux window in the session currently showing that node instead of printing to stdout."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The node whose prompt was read."},{name:"captured_at",type:"string",required:!0,constraint:"File mtime in ISO-8601 UTC."},{name:"chars",type:"number",required:!0,constraint:"Character count of the stored prompt."},{name:"prompt",type:"string",required:!0,constraint:"The assembled system prompt, exactly as pi built it."},{name:"session",type:"string",required:!1,constraint:"tmux session showing the node (only when --window is used)."},{name:"window",type:"string",required:!1,constraint:"tmux window opened for the prompt (only when --window is used)."}],outputKind:"object",effects:["Read-only: reads the node's job/system-prompt.md artifact, or opens it in a tmux window."],preview:{suppressOutput:!0}},run:i(async t=>{const e=t.node?.trim()||f();if(e===void 0||e==="")throw new n({error:"empty_node",message:"a node id is required",field:"node",next:"Pass a node id or run from inside a node."});try{await c().getNode(e)}catch(o){throw o instanceof q&&o.status===404?new n({error:"not_found",message:`no node: ${e}`,field:"node",next:"List nodes with `crtr node inspect list`."}):o}const s=p($(e),"system-prompt.md");if(!h(s))throw new n({error:"not_found",message:`system prompt not captured yet for ${e}`,field:"node",next:"Focus or revive the node once while its broker is live, then rerun `crtr sys context sysprompt <node>`."});const r=y(s,"utf8"),u=g(s).mtime.toISOString();if(t.window===!0){const o=await c().focusOf(e);if(o===null||o.session===null||o.session==="")throw new n({error:"not_focused",message:`node ${e} is not currently shown in tmux`,field:"node",next:`Focus the node first with \`crtr surface node focus ${e}\`, then rerun \`crtr sys context sysprompt --window ${e}\`.`});const d=p(_(),`crtr-sysprompt-${e}.md`);x(d,r,"utf8");const a=k(d),w=`if command -v bat >/dev/null 2>&1; then bat --language=markdown --color=always --paging=always --style=plain ${a}; else less -R ${a}; fi`,m=v({session:o.session,name:`sysprompt:${e}`,cwd:process.cwd(),env:{},command:w});if(m===null)throw new n({error:"window_open_failed",message:`tmux could not open a window for node ${e}`,field:"node",next:"Check the tmux server is reachable, then retry."});return{node_id:e,session:o.session,window:m.window}}return{node_id:e,captured_at:u,chars:r.length,prompt:r}},"run"),render:i(t=>"window"in t?`Opened system prompt for node ${t.node_id} in tmux session ${t.session} \u2014 window ${t.window}.`:`- node_id: ${t.node_id}
1
+ var l=Object.defineProperty;var i=(t,e)=>l(t,"name",{value:e,configurable:!0});import{envNodeId as f}from"../../../shared/env.js";import{existsSync as h,readFileSync as y,statSync as g,writeFileSync as x}from"node:fs";import{tmpdir as _}from"node:os";import{join as p}from"node:path";import{defineLeaf as b}from"../../../core/command.js";import{InputError as n}from"../../../core/io.js";import{nodeRunJobDir as $}from"../../../core/canvas/paths.js";import{openNodeWindow as v}from"../../../core/runtime/placement-tmux.js";import{ApiError as q}from"../../../api/index.js";import{cliClient as c}from"../../api-client.js";import{shellQuote as k}from"../../../shared/shell-quote.js";const A=b({name:"sysprompt",description:"print a node's assembled system prompt",whenToUse:"you want to inspect a node's assembled system prompt headlessly, without paying conversation/context cost \u2014 the broker writes it to disk while live, and this command reads that artifact back as markdown.",help:{name:"sys context sysprompt",summary:"print a node's assembled system prompt",params:[{kind:"positional",name:"node",required:!1,constraint:"Node id. Defaults to the calling node (CRTR_NODE_ID)."},{kind:"flag",name:"window",type:"bool",required:!1,constraint:"Open the assembled prompt in a NEW tmux window in the session currently showing that node instead of printing to stdout."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The node whose prompt was read."},{name:"captured_at",type:"string",required:!0,constraint:"File mtime in ISO-8601 UTC."},{name:"chars",type:"number",required:!0,constraint:"Character count of the stored prompt."},{name:"prompt",type:"string",required:!0,constraint:"The assembled system prompt, exactly as pi built it."},{name:"session",type:"string",required:!1,constraint:"tmux session showing the node (only when --window is used)."},{name:"window",type:"string",required:!1,constraint:"tmux window opened for the prompt (only when --window is used)."}],outputKind:"object",effects:["Read-only: reads the node's job/system-prompt.md artifact, or opens it in a tmux window."],preview:{suppressOutput:!0}},run:i(async t=>{const e=t.node?.trim()||f();if(e===void 0||e==="")throw new n({error:"empty_node",message:"a node id is required",field:"node",next:"Pass a node id or run from inside a node."});try{await c().getNode(e)}catch(o){throw o instanceof q&&o.status===404?new n({error:"not_found",message:`no node: ${e}`,field:"node",next:"List nodes with `crtr node inspect list`."}):o}const s=p($(e),"system-prompt.md");if(!h(s))throw new n({error:"not_found",message:`system prompt not captured yet for ${e}`,field:"node",next:"Focus or revive the node once while its broker is live, then rerun `crtr sys context sysprompt <node>`."});const r=y(s,"utf8"),u=g(s).mtime.toISOString();if(t.window===!0){const o=await c().focusOf(e);if(o===null||o.session===null||o.session==="")throw new n({error:"not_focused",message:`node ${e} is not currently shown in tmux`,field:"node",next:`Focus the node first with \`crtr surface node focus ${e}\`, then rerun \`crtr sys context sysprompt --window ${e}\`.`});const d=p(_(),`crtr-sysprompt-${e}.md`);x(d,r,"utf8");const a=k(d),w=`if command -v bat >/dev/null 2>&1; then bat --language=markdown --color=always --paging=always --style=plain ${a}; else less -R ${a}; fi`,m=v({session:o.session,name:`sysprompt:${e}`,cwd:process.cwd(),env:{},command:w});if(m===null)throw new n({error:"window_open_failed",message:`tmux could not open a window for node ${e}`,field:"node",next:"Check the tmux server is reachable, then retry."});return{node_id:e,session:o.session,window:m.window}}return{node_id:e,captured_at:u,chars:r.length,prompt:r}},"run"),render:i(t=>"window"in t?`Opened system prompt for node ${t.node_id} in tmux session ${t.session} \u2014 window ${t.window}.`:`- node_id: ${t.node_id}
2
2
  - captured_at: ${t.captured_at}
3
3
  - chars: ${t.chars}
4
4
 
@@ -0,0 +1 @@
1
+ export declare const sysJoinLeaf: import("../../core/command.js").LeafDef;
@@ -0,0 +1 @@
1
+ var r=Object.defineProperty;var t=(e,n)=>r(e,"name",{value:n,configurable:!0});import{defineLeaf as i}from"../../core/command.js";import{joinDirectory as s}from"../../core/directory/join.js";const u=i({name:"join",description:"register this runtime with its directory using an enrollment token, offline",whenToUse:"at a hosted runtime's first boot, before the daemon starts, with the enrollment token provisioning passed in. Not for a runtime that is already running: the daemon must be stopped.",help:{name:"sys join",summary:"exchange a directory enrollment token for a new runtime client key and record the returned identity",guide:"Generates a new ES256 client key, sends only its public key to `PUT <directory>/v1/runtimes/registration` with the token as bearer, and learns the runtime id, client id, issuer, owner and URL from the answer. Only after that answer does it write the key file, set the user settings `runtime.issuer` and `runtime.audience`, and rewrite `user:local` profile grantees to `app:terminal`. canvas.db belongs to the daemon: its next start rewrites `user:local` there, before it serves anything. Presenting the token of the stored successful registration again finishes those local writes without calling the directory. Any other token generates a new key and registers again.",params:[{kind:"flag",name:"directory",type:"string",required:!0,constraint:"Directory base URL (http or https) that minted the token."},{kind:"flag",name:"token",type:"string",required:!0,sensitive:!0,constraint:"Single-use enrollment token. Sensitive: never echoed in output or errors."}],output:[{name:"runtime",type:"string",required:!0,constraint:"Runtime principal from the directory, `runtime:<id>`."},{name:"client_id",type:"string",required:!0,constraint:"OAuth client id registered for the new key."},{name:"issuer",type:"string",required:!0,constraint:"Canonical issuer, written to `runtime.issuer`."},{name:"owner",type:"string",required:!0,constraint:"Owner principal, `user:<id>`, that replaces `user:local` subjects."},{name:"canvas_rewrite",type:"string",required:!0,constraint:"Always `next daemon start`: when canvas.db identity fields are rewritten."},{name:"url",type:"string",required:!0,constraint:"Runtime URL, written to `runtime.audience`."},{name:"registered",type:"boolean",required:!0,constraint:"False when the token matched the stored registration and the directory was not called."}],outputKind:"object",effects:["Refuses while a daemon answers on the API socket.","On a new token: calls the directory once; on success writes `<runtime>/secrets/runtime-client.json` (mode 0600) with the private key, registration and the token's SHA-256, replacing any earlier key file. A refused or failed call writes nothing.","Sets `runtime.issuer` and `runtime.audience` in user settings.","Rewrites `user:local` profile grantees to `app:terminal`.","At every later daemon start, before any listener: exact `user:local` subjects in canvas.db nodes and node_tokens become the owner (as do missing subjects on `app:terminal` nodes), `user:local` grantees in nodes, run_events, idempotency_keys and node_tokens become `app:terminal`, references to the unjoined runtime's `local:terminal` grant are cleared, and that local grant mirror is deleted so grant sync installs the directory's. Application grantees and free text are unchanged; a start with nothing left to rewrite changes no rows."]},run:t(async e=>({...await s(e.directory,e.token),canvas_rewrite:"next daemon start"}),"run")});export{u as sysJoinLeaf};