@crouton-kit/crouter 0.3.28 → 0.3.30

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 (324) hide show
  1. package/dist/build-root.d.ts +15 -7
  2. package/dist/build-root.js +48 -34
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +7 -6
  4. package/dist/builtin-memory/crouter-development/personas/base-prompt.md +1 -1
  5. package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +1 -1
  6. package/dist/builtin-memory/crouter-development/personas.md +1 -1
  7. package/dist/builtin-memory/crouter-development/plugins.md +20 -18
  8. package/dist/builtin-memory/design.md +1 -1
  9. package/dist/builtin-memory/development.md +1 -1
  10. package/dist/builtin-memory/internal/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/examples/INDEX.md +1 -1
  12. package/dist/builtin-memory/internal/examples/imessage-assistant.md +2 -2
  13. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  14. package/dist/builtin-memory/internal/storage-tiers.md +1 -1
  15. package/dist/builtin-memory/planning.md +1 -1
  16. package/dist/builtin-memory/spec.md +6 -4
  17. package/dist/builtin-personas/orchestration-kernel.md +4 -5
  18. package/dist/builtin-personas/runtime-base.md +5 -4
  19. package/dist/builtin-personas/spec/PERSONA.md +8 -4
  20. package/dist/builtin-personas/spec/orchestrator.md +5 -3
  21. package/dist/builtin-personas/spec/requirements/PERSONA.md +10 -0
  22. package/dist/builtin-views/canvas/core.mjs +586 -0
  23. package/dist/builtin-views/canvas/text.mjs +58 -0
  24. package/dist/builtin-views/canvas/tui.mjs +165 -0
  25. package/dist/builtin-views/canvas/web.jsx +120 -0
  26. package/dist/builtin-views/git-pr/core.mjs +673 -0
  27. package/dist/builtin-views/git-pr/text.mjs +84 -0
  28. package/dist/builtin-views/git-pr/tui.mjs +302 -0
  29. package/dist/builtin-views/git-pr/web.jsx +216 -0
  30. package/dist/builtin-views/inbox/_lib/render.mjs +1 -3
  31. package/dist/builtin-views/inbox/core.mjs +1273 -0
  32. package/dist/builtin-views/inbox/text.mjs +73 -0
  33. package/dist/builtin-views/inbox/tui.mjs +312 -0
  34. package/dist/builtin-views/inbox/web.jsx +188 -0
  35. package/dist/builtin-views/linkedin/core.mjs +906 -0
  36. package/dist/builtin-views/linkedin/text.mjs +69 -0
  37. package/dist/builtin-views/linkedin/tui.mjs +427 -0
  38. package/dist/builtin-views/linkedin/web.jsx +206 -0
  39. package/dist/builtin-views/workspace-sidebar/core.mjs +621 -0
  40. package/dist/builtin-views/workspace-sidebar/text.mjs +53 -0
  41. package/dist/builtin-views/workspace-sidebar/tui.mjs +142 -0
  42. package/dist/builtin-views/workspace-sidebar/web.jsx +109 -0
  43. package/dist/cli.js +22 -17
  44. package/dist/clients/attach/__tests__/action-parity.test.js +48 -0
  45. package/dist/clients/attach/__tests__/clipboard-image.test.js +76 -0
  46. package/dist/clients/attach/__tests__/editor-newline.test.js +57 -0
  47. package/dist/clients/attach/__tests__/git-info.test.js +31 -0
  48. package/dist/clients/attach/__tests__/onrequest-wired.test.js +20 -0
  49. package/dist/clients/attach/__tests__/slash-quit-copy.test.js +42 -0
  50. package/dist/clients/attach/__tests__/titled-editor.test.js +39 -0
  51. package/dist/clients/attach/attach-cmd.js +282 -46
  52. package/dist/clients/attach/auth-pickers.d.ts +9 -0
  53. package/dist/clients/attach/auth-pickers.js +194 -0
  54. package/dist/clients/attach/canvas-panels.d.ts +4 -2
  55. package/dist/clients/attach/canvas-panels.js +45 -17
  56. package/dist/clients/attach/chat-view.d.ts +27 -2
  57. package/dist/clients/attach/chat-view.js +98 -9
  58. package/dist/clients/attach/clipboard-image.d.ts +47 -8
  59. package/dist/clients/attach/clipboard-image.js +150 -26
  60. package/dist/clients/attach/clipboard-text.d.ts +3 -0
  61. package/dist/clients/attach/clipboard-text.js +39 -0
  62. package/dist/clients/attach/config-load.d.ts +54 -7
  63. package/dist/clients/attach/config-load.js +99 -3
  64. package/dist/clients/attach/context-message.d.ts +12 -0
  65. package/dist/clients/attach/context-message.js +72 -0
  66. package/dist/clients/attach/git-info.d.ts +20 -0
  67. package/dist/clients/attach/git-info.js +44 -0
  68. package/dist/clients/attach/graph-overlay.d.ts +13 -4
  69. package/dist/clients/attach/graph-overlay.js +59 -19
  70. package/dist/clients/attach/input-controller.d.ts +75 -13
  71. package/dist/clients/attach/input-controller.js +305 -67
  72. package/dist/clients/attach/pickers.d.ts +58 -0
  73. package/dist/clients/attach/pickers.js +171 -0
  74. package/dist/clients/attach/slash-commands.d.ts +22 -0
  75. package/dist/clients/attach/slash-commands.js +91 -25
  76. package/dist/clients/attach/titled-editor.d.ts +33 -0
  77. package/dist/clients/attach/titled-editor.js +84 -0
  78. package/dist/clients/attach/view-socket.d.ts +18 -1
  79. package/dist/clients/attach/view-socket.js +70 -1
  80. package/dist/clients/web/dev-server.d.ts +7 -0
  81. package/dist/clients/web/dev-server.js +59 -0
  82. package/dist/clients/web/events.d.ts +14 -0
  83. package/dist/clients/web/events.js +151 -0
  84. package/dist/clients/web/server.d.ts +18 -0
  85. package/dist/clients/web/server.js +450 -0
  86. package/dist/clients/web/web-cmd.d.ts +2 -0
  87. package/dist/clients/web/web-cmd.js +120 -0
  88. package/dist/commands/canvas.js +1 -2
  89. package/dist/commands/chord.js +4 -25
  90. package/dist/commands/dashboard.js +5 -1
  91. package/dist/commands/memory/__tests__/lint-schema.test.js +6 -6
  92. package/dist/commands/memory/lint.js +14 -2
  93. package/dist/commands/memory/read.js +2 -2
  94. package/dist/commands/memory/shared.d.ts +7 -1
  95. package/dist/commands/memory/shared.js +18 -3
  96. package/dist/commands/memory/write.js +8 -4
  97. package/dist/commands/memory.js +4 -4
  98. package/dist/commands/node.d.ts +1 -1
  99. package/dist/commands/node.js +64 -65
  100. package/dist/commands/pkg.js +1 -2
  101. package/dist/commands/revive.js +11 -3
  102. package/dist/commands/sys/sync.d.ts +1 -0
  103. package/dist/commands/sys/sync.js +187 -0
  104. package/dist/commands/sys.js +3 -2
  105. package/dist/commands/view-cycle.js +2 -2
  106. package/dist/commands/view-list.js +8 -8
  107. package/dist/commands/view-new.js +21 -17
  108. package/dist/commands/view-pick.js +1 -1
  109. package/dist/commands/view-run.js +35 -14
  110. package/dist/commands/view.js +8 -6
  111. package/dist/commands/workspace.d.ts +2 -0
  112. package/dist/commands/workspace.js +161 -0
  113. package/dist/core/__tests__/broker-double-spawn.test.d.ts +1 -0
  114. package/dist/core/__tests__/broker-double-spawn.test.js +143 -0
  115. package/dist/core/__tests__/broker-fork-seam.test.d.ts +1 -0
  116. package/dist/core/__tests__/broker-fork-seam.test.js +102 -0
  117. package/dist/core/__tests__/broker-sdk-wiring.test.js +2 -0
  118. package/dist/core/__tests__/child-death-wake.test.js +56 -111
  119. package/dist/core/__tests__/close.test.js +14 -20
  120. package/dist/core/__tests__/context-intro.test.js +19 -19
  121. package/dist/core/__tests__/daemon-boot.test.js +30 -23
  122. package/dist/core/__tests__/draw-style.test.js +1 -1
  123. package/dist/core/__tests__/error-stall-recycle.test.d.ts +1 -0
  124. package/dist/core/__tests__/error-stall-recycle.test.js +141 -0
  125. package/dist/core/__tests__/fixtures/fake-engine.d.ts +17 -1
  126. package/dist/core/__tests__/fixtures/fake-engine.js +22 -2
  127. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  128. package/dist/core/__tests__/focuses.test.js +25 -13
  129. package/dist/core/__tests__/fork.test.js +22 -5
  130. package/dist/core/__tests__/full/broker-control-preempt.test.d.ts +1 -0
  131. package/dist/core/__tests__/full/broker-control-preempt.test.js +61 -0
  132. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +1 -0
  133. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +57 -0
  134. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +1 -0
  135. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +80 -0
  136. package/dist/core/__tests__/full/broker-pane-resolution.test.js +90 -0
  137. package/dist/core/__tests__/full/cascade-close.test.js +22 -8
  138. package/dist/core/__tests__/full/detach-focus.test.js +66 -169
  139. package/dist/core/__tests__/helpers/harness.d.ts +6 -9
  140. package/dist/core/__tests__/helpers/harness.js +19 -36
  141. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +1 -0
  142. package/dist/core/__tests__/human-node-not-supervised.test.js +83 -0
  143. package/dist/core/__tests__/lifecycle.test.js +1 -19
  144. package/dist/core/__tests__/listing-completeness.test.js +2 -2
  145. package/dist/core/__tests__/live-mutation-verbs.test.js +5 -5
  146. package/dist/core/__tests__/memory-resolver.test.js +1 -1
  147. package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -2
  148. package/dist/core/__tests__/refresh-stall-recycle.test.d.ts +1 -0
  149. package/dist/core/__tests__/refresh-stall-recycle.test.js +88 -0
  150. package/dist/core/__tests__/relaunch-root.test.d.ts +1 -0
  151. package/dist/core/__tests__/relaunch-root.test.js +114 -0
  152. package/dist/core/__tests__/reset.test.js +19 -79
  153. package/dist/core/__tests__/steer-note.test.js +9 -7
  154. package/dist/core/__tests__/tmux-surface.test.js +13 -7
  155. package/dist/core/bootstrap.d.ts +0 -3
  156. package/dist/core/bootstrap.js +1 -143
  157. package/dist/core/canvas/browse/__tests__/model.test.js +86 -1
  158. package/dist/core/canvas/browse/__tests__/render.test.js +2 -1
  159. package/dist/core/canvas/browse/app.js +131 -8
  160. package/dist/core/canvas/browse/model.d.ts +23 -5
  161. package/dist/core/canvas/browse/model.js +68 -13
  162. package/dist/core/canvas/browse/render.d.ts +7 -1
  163. package/dist/core/canvas/browse/render.js +178 -47
  164. package/dist/core/canvas/canvas.js +1 -1
  165. package/dist/core/canvas/focuses.d.ts +4 -4
  166. package/dist/core/canvas/focuses.js +7 -7
  167. package/dist/core/canvas/nav-model.js +8 -7
  168. package/dist/core/canvas/render.d.ts +68 -9
  169. package/dist/core/canvas/render.js +195 -61
  170. package/dist/core/canvas/types.d.ts +16 -23
  171. package/dist/core/config.js +1 -4
  172. package/dist/core/memory-resolver.js +43 -5
  173. package/dist/core/runtime/bearings.d.ts +1 -1
  174. package/dist/core/runtime/bearings.js +8 -8
  175. package/dist/core/runtime/branded-host.d.ts +16 -0
  176. package/dist/core/runtime/branded-host.js +127 -0
  177. package/dist/core/runtime/broker-protocol.d.ts +212 -6
  178. package/dist/core/runtime/broker.d.ts +4 -1
  179. package/dist/core/runtime/broker.js +494 -58
  180. package/dist/core/runtime/close.d.ts +12 -2
  181. package/dist/core/runtime/close.js +37 -16
  182. package/dist/core/runtime/front-door.js +6 -14
  183. package/dist/core/runtime/host.d.ts +14 -34
  184. package/dist/core/runtime/host.js +14 -50
  185. package/dist/core/runtime/launch.d.ts +12 -9
  186. package/dist/core/runtime/launch.js +27 -15
  187. package/dist/core/runtime/lifecycle.d.ts +1 -1
  188. package/dist/core/runtime/lifecycle.js +15 -19
  189. package/dist/core/runtime/nodes.d.ts +0 -55
  190. package/dist/core/runtime/nodes.js +6 -74
  191. package/dist/core/runtime/placement.d.ts +91 -335
  192. package/dist/core/runtime/placement.js +291 -858
  193. package/dist/core/runtime/promote.d.ts +2 -0
  194. package/dist/core/runtime/promote.js +24 -6
  195. package/dist/core/runtime/recap.d.ts +8 -0
  196. package/dist/core/runtime/recap.js +107 -0
  197. package/dist/core/runtime/recycle.js +25 -61
  198. package/dist/core/runtime/reset.d.ts +43 -37
  199. package/dist/core/runtime/reset.js +131 -218
  200. package/dist/core/runtime/revive.d.ts +9 -29
  201. package/dist/core/runtime/revive.js +40 -139
  202. package/dist/core/runtime/spawn.d.ts +15 -16
  203. package/dist/core/runtime/spawn.js +165 -194
  204. package/dist/core/runtime/surface-bg.d.ts +11 -0
  205. package/dist/core/runtime/surface-bg.js +68 -0
  206. package/dist/core/runtime/tmux.d.ts +15 -52
  207. package/dist/core/runtime/tmux.js +35 -99
  208. package/dist/core/scope.d.ts +1 -2
  209. package/dist/core/scope.js +1 -5
  210. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts +1 -0
  211. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +57 -0
  212. package/dist/core/skill-sync/builtins.d.ts +42 -0
  213. package/dist/core/skill-sync/builtins.js +112 -0
  214. package/dist/core/skill-sync/claude-plugins.d.ts +23 -0
  215. package/dist/core/skill-sync/claude-plugins.js +71 -0
  216. package/dist/core/skill-sync/engine.d.ts +42 -0
  217. package/dist/core/skill-sync/engine.js +633 -0
  218. package/dist/core/skill-sync/export.d.ts +23 -0
  219. package/dist/core/skill-sync/export.js +86 -0
  220. package/dist/core/skill-sync/manifest.d.ts +64 -0
  221. package/dist/core/skill-sync/manifest.js +181 -0
  222. package/dist/core/skill-sync/profile.d.ts +76 -0
  223. package/dist/core/skill-sync/profile.js +173 -0
  224. package/dist/core/skill-sync/snapshot.d.ts +57 -0
  225. package/dist/core/skill-sync/snapshot.js +120 -0
  226. package/dist/core/substrate/index.d.ts +1 -1
  227. package/dist/core/substrate/index.js +1 -1
  228. package/dist/core/substrate/injected-store.js +3 -3
  229. package/dist/core/substrate/on-read.js +68 -6
  230. package/dist/core/substrate/render.d.ts +8 -11
  231. package/dist/core/substrate/render.js +29 -43
  232. package/dist/core/substrate/schema.d.ts +10 -3
  233. package/dist/core/substrate/schema.js +6 -3
  234. package/dist/core/tui/host.d.ts +12 -4
  235. package/dist/core/tui/host.js +280 -149
  236. package/dist/core/view/bridge.d.ts +10 -0
  237. package/dist/core/view/bridge.js +31 -0
  238. package/dist/core/view/chrome.d.ts +9 -0
  239. package/dist/core/view/chrome.js +22 -0
  240. package/dist/core/view/contract.d.ts +171 -0
  241. package/dist/core/view/contract.js +23 -0
  242. package/dist/core/view/loader.d.ts +31 -0
  243. package/dist/core/view/loader.js +188 -0
  244. package/dist/core/view/transport-local.d.ts +7 -0
  245. package/dist/core/view/transport-local.js +70 -0
  246. package/dist/core/view/transport.d.ts +4 -0
  247. package/dist/core/view/transport.js +15 -0
  248. package/dist/daemon/crtrd.d.ts +38 -27
  249. package/dist/daemon/crtrd.js +303 -376
  250. package/dist/daemon/manage.js +6 -1
  251. package/dist/index.js +1 -1
  252. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +28 -20
  253. package/dist/pi-extensions/canvas-context-intro.js +4 -4
  254. package/dist/pi-extensions/canvas-doc-substrate.js +16 -16
  255. package/dist/pi-extensions/canvas-nav.js +5 -0
  256. package/dist/pi-extensions/canvas-recap.d.ts +37 -0
  257. package/dist/pi-extensions/canvas-recap.js +236 -0
  258. package/dist/pi-extensions/canvas-resume.js +2 -1
  259. package/dist/pi-extensions/canvas-stophook.d.ts +14 -12
  260. package/dist/pi-extensions/canvas-stophook.js +87 -101
  261. package/dist/pi-extensions/canvas-view.js +2 -1
  262. package/dist/pi-extensions/widget-order-bus.d.ts +6 -0
  263. package/dist/pi-extensions/widget-order-bus.js +34 -0
  264. package/dist/prompts/view.d.ts +2 -2
  265. package/dist/prompts/view.js +145 -73
  266. package/dist/types.d.ts +1 -6
  267. package/dist/types.js +1 -3
  268. package/dist/web/ViewChrome.d.ts +7 -0
  269. package/dist/web/ViewChrome.js +28 -0
  270. package/dist/web/ViewPane.d.ts +39 -0
  271. package/dist/web/ViewPane.js +48 -0
  272. package/dist/web/index.d.ts +6 -0
  273. package/dist/web/index.js +16 -0
  274. package/dist/web/runtime.d.ts +39 -0
  275. package/dist/web/runtime.js +133 -0
  276. package/dist/web/states.d.ts +24 -0
  277. package/dist/web/states.js +24 -0
  278. package/dist/web/transport-http.d.ts +5 -0
  279. package/dist/web/transport-http.js +28 -0
  280. package/dist/web-client/assets/index-BUvQb4hR.css +2 -0
  281. package/dist/web-client/assets/index-ClLQXYAE.js +10 -0
  282. package/dist/web-client/index.html +13 -0
  283. package/package.json +20 -6
  284. package/dist/builtin-views/canvas/client.mjs +0 -303
  285. package/dist/builtin-views/canvas/view.mjs +0 -576
  286. package/dist/builtin-views/git-pr/client.mjs +0 -440
  287. package/dist/builtin-views/git-pr/view.mjs +0 -675
  288. package/dist/builtin-views/inbox/sources/gmail.mjs +0 -965
  289. package/dist/builtin-views/inbox/sources/linkedin.mjs +0 -427
  290. package/dist/builtin-views/inbox/view.mjs +0 -889
  291. package/dist/builtin-views/linkedin/client.mjs +0 -610
  292. package/dist/builtin-views/linkedin/view.mjs +0 -1171
  293. package/dist/commands/pkg/bridge.d.ts +0 -1
  294. package/dist/commands/pkg/bridge.js +0 -137
  295. package/dist/commands/skill/author.d.ts +0 -3
  296. package/dist/commands/skill/author.js +0 -140
  297. package/dist/commands/skill/shared.d.ts +0 -3
  298. package/dist/commands/skill/shared.js +0 -19
  299. package/dist/commands/skill.d.ts +0 -2
  300. package/dist/commands/skill.js +0 -21
  301. package/dist/commands/tmux-spread.d.ts +0 -2
  302. package/dist/commands/tmux-spread.js +0 -144
  303. package/dist/core/__tests__/full/daemon-liveness-pane.full.test.js +0 -292
  304. package/dist/core/__tests__/full/placement-focus.test.js +0 -309
  305. package/dist/core/__tests__/full/placement-reconcile.test.js +0 -212
  306. package/dist/core/__tests__/full/placement-revive.test.js +0 -238
  307. package/dist/core/__tests__/full/placement-teardown.test.js +0 -297
  308. package/dist/core/__tests__/home-session.test.js +0 -186
  309. package/dist/core/__tests__/relaunch.test.js +0 -335
  310. package/dist/core/bridge-map.d.ts +0 -19
  311. package/dist/core/bridge-map.js +0 -73
  312. package/dist/core/tui/contract.d.ts +0 -83
  313. package/dist/core/tui/contract.js +0 -8
  314. package/dist/core/tui/loader.d.ts +0 -16
  315. package/dist/core/tui/loader.js +0 -94
  316. package/dist/prompts/skill.d.ts +0 -2
  317. package/dist/prompts/skill.js +0 -650
  318. /package/dist/{core/__tests__/full/daemon-liveness-pane.full.test.d.ts → clients/attach/__tests__/action-parity.test.d.ts} +0 -0
  319. /package/dist/{core/__tests__/full/placement-focus.test.d.ts → clients/attach/__tests__/clipboard-image.test.d.ts} +0 -0
  320. /package/dist/{core/__tests__/full/placement-reconcile.test.d.ts → clients/attach/__tests__/editor-newline.test.d.ts} +0 -0
  321. /package/dist/{core/__tests__/full/placement-revive.test.d.ts → clients/attach/__tests__/git-info.test.d.ts} +0 -0
  322. /package/dist/{core/__tests__/full/placement-teardown.test.d.ts → clients/attach/__tests__/onrequest-wired.test.d.ts} +0 -0
  323. /package/dist/{core/__tests__/home-session.test.d.ts → clients/attach/__tests__/slash-quit-copy.test.d.ts} +0 -0
  324. /package/dist/{core/__tests__/relaunch.test.d.ts → clients/attach/__tests__/titled-editor.test.d.ts} +0 -0
@@ -8,7 +8,7 @@
8
8
  import { defineLeaf } from '../core/command.js';
9
9
  import { InputError } from '../core/io.js';
10
10
  import { getNode, listNodes } from '../core/canvas/index.js';
11
- import { renderTree, renderForest, dashboardRows, dashboardRowsAll } from '../core/canvas/render.js';
11
+ import { renderTree, renderForest, dashboardRows, dashboardRowsAll, enrichRows } from '../core/canvas/render.js';
12
12
  // ---------------------------------------------------------------------------
13
13
  // dashboard show — the main leaf
14
14
  // ---------------------------------------------------------------------------
@@ -57,7 +57,11 @@ export const dashboardLeaf = defineLeaf({
57
57
  }
58
58
  // Full forest: all nodes on the canvas.
59
59
  const allNodes = listNodes();
60
+ // dashboardRowsAll is the cheap-boot builder: ctx_tokens/asks are 0 and `name`
61
+ // is the handle only until enriched. The JSON consumer wants the real values,
62
+ // so fold the deferred fields in before emitting (the rendered TREE is unaffected).
60
63
  const rows = dashboardRowsAll();
64
+ enrichRows(rows);
61
65
  return {
62
66
  tree: renderForest(),
63
67
  nodes: allNodes.length,
@@ -11,22 +11,22 @@ import { lintSubstrateSchema } from '../lint.js';
11
11
  const ROUTING = 'When you are X, this reference should be read because Y';
12
12
  const RUNGS = { 'system-prompt-visibility': 'name', 'file-read-visibility': 'none' };
13
13
  test('lint rejects a doc still carrying the retired `when` key', () => {
14
- const err = lintSubstrateSchema({ kind: 'reference', when: 'when X' });
14
+ const err = lintSubstrateSchema({ kind: 'knowledge', when: 'when X' });
15
15
  assert.ok(err !== null, 'old-shape `when` must produce a finding');
16
16
  assert.match(err, /when-and-why-to-read/, 'the message points at the new field');
17
17
  });
18
18
  test('lint rejects a doc still carrying the retired `why` key', () => {
19
- const err = lintSubstrateSchema({ kind: 'reference', why: 'because Y' });
19
+ const err = lintSubstrateSchema({ kind: 'knowledge', why: 'because Y' });
20
20
  assert.ok(err !== null, 'old-shape `why` must produce a finding');
21
21
  assert.match(err, /when-and-why-to-read/, 'the message points at the new field');
22
22
  });
23
23
  test('lint rejects a substrate doc missing the merged routing field', () => {
24
- const err = lintSubstrateSchema({ kind: 'reference' });
24
+ const err = lintSubstrateSchema({ kind: 'knowledge' });
25
25
  assert.ok(err !== null, 'a substrate doc must carry when-and-why-to-read');
26
26
  assert.match(err, /when-and-why-to-read/);
27
27
  });
28
28
  test('lint accepts the merged new-shape frontmatter', () => {
29
- assert.equal(lintSubstrateSchema({ kind: 'reference', 'when-and-why-to-read': ROUTING, ...RUNGS }), null);
29
+ assert.equal(lintSubstrateSchema({ kind: 'knowledge', 'when-and-why-to-read': ROUTING, ...RUNGS }), null);
30
30
  });
31
31
  // Visibility is a required, case-by-case authoring call — there is no kind
32
32
  // default. lint must reject a doc that omits either rung (the runtime parser
@@ -34,7 +34,7 @@ test('lint accepts the merged new-shape frontmatter', () => {
34
34
  // gate exists to catch at authoring time).
35
35
  test('lint rejects a substrate doc missing system-prompt-visibility', () => {
36
36
  const err = lintSubstrateSchema({
37
- kind: 'reference',
37
+ kind: 'knowledge',
38
38
  'when-and-why-to-read': ROUTING,
39
39
  'file-read-visibility': 'none',
40
40
  });
@@ -43,7 +43,7 @@ test('lint rejects a substrate doc missing system-prompt-visibility', () => {
43
43
  });
44
44
  test('lint rejects a substrate doc missing file-read-visibility', () => {
45
45
  const err = lintSubstrateSchema({
46
- kind: 'reference',
46
+ kind: 'knowledge',
47
47
  'when-and-why-to-read': ROUTING,
48
48
  'system-prompt-visibility': 'name',
49
49
  });
@@ -24,9 +24,9 @@ const RUNG_FIELDS = ['system-prompt-visibility', 'file-read-visibility'];
24
24
  * silent tolerance this lint exists to catch at authoring time. */
25
25
  export function lintSubstrateSchema(fm) {
26
26
  if (fm === null)
27
- return 'missing frontmatter: a memory store doc requires `kind: skill|reference|preference`';
27
+ return 'missing frontmatter: a memory store doc requires `kind: knowledge|preference`';
28
28
  if (!isDocKind(fm.kind)) {
29
- return `invalid kind: ${JSON.stringify(fm.kind)} (expected skill|reference|preference)`;
29
+ return `invalid kind: ${JSON.stringify(fm.kind)} (expected knowledge|preference)`;
30
30
  }
31
31
  // The retired `when`/`why` pair was merged into one read-routing field. The
32
32
  // hard cut is enforced HERE: an old-shape doc must fail, never be silently
@@ -56,6 +56,18 @@ export function lintSubstrateSchema(fm) {
56
56
  !(Array.isArray(appliesTo) && appliesTo.every((g) => typeof g === 'string'))) {
57
57
  return `invalid applies-to: ${JSON.stringify(appliesTo)} (expected a glob or glob list)`;
58
58
  }
59
+ // read-when (Stream A on-read frontmatter trigger): same well-formed-object
60
+ // contract as gate — a non-object is inert (never fires), so catch it here.
61
+ const readWhen = fm['read-when'];
62
+ if (readWhen !== undefined && (readWhen === null || typeof readWhen !== 'object' || Array.isArray(readWhen))) {
63
+ return `invalid read-when: ${JSON.stringify(readWhen)} (expected a field→matcher object)`;
64
+ }
65
+ // A dead on-read trigger: an explicit applies-to/read-when with nothing to
66
+ // surface (file-read-visibility none) can never fire — flag it loudly rather
67
+ // than store a silent no-op.
68
+ if (fm['file-read-visibility'] === 'none' && (appliesTo !== undefined || readWhen !== undefined)) {
69
+ return 'dead on-read trigger: applies-to/read-when is set but file-read-visibility is `none` — raise the rung or drop the trigger';
70
+ }
59
71
  return null;
60
72
  }
61
73
  /** Strict-parse one file; push a finding on a YAML error, then run the
@@ -18,7 +18,7 @@ export const readLeaf = defineLeaf({
18
18
  ],
19
19
  output: [
20
20
  { name: 'name', type: 'string', required: true, constraint: 'Resolved document name.' },
21
- { name: 'kind', type: 'string', required: true, constraint: 'Resolved kind: skill, reference, or preference.' },
21
+ { name: 'kind', type: 'string', required: true, constraint: 'Resolved kind: knowledge or preference.' },
22
22
  { name: 'scope', type: 'string', required: true, constraint: 'Scope the document was resolved from: project, user, or builtin.' },
23
23
  { name: 'path', type: 'string', required: true, constraint: 'Absolute path to the document on disk.' },
24
24
  { name: 'content', type: 'string', required: true, constraint: 'Document body. Frontmatter stripped unless --frontmatter is set.' },
@@ -48,7 +48,7 @@ export const readLeaf = defineLeaf({
48
48
  ? sub.kind
49
49
  : typeof doc.frontmatter?.['kind'] === 'string'
50
50
  ? doc.frontmatter['kind']
51
- : 'reference';
51
+ : 'knowledge';
52
52
  // --kind asserts the resolved kind; a mismatch falls through to not-found.
53
53
  if (kindFilter === undefined || kind === kindFilter) {
54
54
  const content = includeFrontmatter ? readText(doc.path) : doc.body;
@@ -1,5 +1,5 @@
1
1
  import type { Scope } from '../../types.js';
2
- export declare const MEMORY_KINDS: readonly ["skill", "reference", "preference"];
2
+ export declare const MEMORY_KINDS: readonly ["knowledge", "preference"];
3
3
  export declare const VISIBILITY_RUNGS: readonly ["none", "name", "preview", "content"];
4
4
  export declare const MEMORY_SCOPES: readonly ["user", "project"];
5
5
  /** Scope sort weight matching resolution precedence (project > user > builtin).
@@ -17,6 +17,12 @@ export declare function resolveWriteTarget(scopeArg: string | undefined): {
17
17
  * memory dir, guarding against traversal/absolute escapes. */
18
18
  export declare function memoryFilePath(memoryDir: string, name: string): string;
19
19
  export declare function coerceGate(raw: string): Record<string, unknown>;
20
+ /** Coerce a `--read-when` string into a predicate tree. Like `--gate`, the
21
+ * read-when field MUST be a YAML/JSON object (the field→matcher map the schema
22
+ * expects, evaluated against a read file's own frontmatter). A scalar/array
23
+ * read-when is inert (never matches), so passing one is always a mistake and is
24
+ * caught at authoring time rather than stored. */
25
+ export declare function coerceReadWhen(raw: string): Record<string, unknown>;
20
26
  /** Coerce a `--applies-to` string to the schema's glob form: a comma-separated
21
27
  * list becomes an array, a single glob stays a string. */
22
28
  export declare function coerceAppliesTo(raw: string): unknown;
@@ -7,9 +7,10 @@ import { join } from 'node:path';
7
7
  import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
8
8
  import { usage } from '../../core/errors.js';
9
9
  import { scopeMemoryDir, projectScopeRoot, ensureProjectScopeRoot, } from '../../core/scope.js';
10
- // The three memory kinds — procedural (skill), referential (reference),
11
- // preferential (preference). Used as the `--kind` enum choices everywhere.
12
- export const MEMORY_KINDS = ['skill', 'reference', 'preference'];
10
+ // The two memory kinds — knowledge (consult: procedural playbooks + factual
11
+ // references merged) vs preference (behave: standing directives). Used as the
12
+ // `--kind` enum choices everywhere.
13
+ export const MEMORY_KINDS = ['knowledge', 'preference'];
13
14
  // Visibility rungs — how much of a document surfaces (none → name → preview →
14
15
  // content). Shared by --system-prompt-visibility and --file-read-visibility.
15
16
  export const VISIBILITY_RUNGS = ['none', 'name', 'preview', 'content'];
@@ -76,6 +77,19 @@ export function coerceGate(raw) {
76
77
  }
77
78
  return result;
78
79
  }
80
+ /** Coerce a `--read-when` string into a predicate tree. Like `--gate`, the
81
+ * read-when field MUST be a YAML/JSON object (the field→matcher map the schema
82
+ * expects, evaluated against a read file's own frontmatter). A scalar/array
83
+ * read-when is inert (never matches), so passing one is always a mistake and is
84
+ * caught at authoring time rather than stored. */
85
+ export function coerceReadWhen(raw) {
86
+ const result = parseYamlObject(raw);
87
+ if (typeof result === 'string') {
88
+ throw usage(`--read-when must be a YAML/JSON object (field→matcher map over a read file's frontmatter): ${result}. ` +
89
+ `Example: --read-when '{tags: {contains: security}}'`);
90
+ }
91
+ return result;
92
+ }
79
93
  /** Coerce a `--applies-to` string to the schema's glob form: a comma-separated
80
94
  * list becomes an array, a single glob stays a string. */
81
95
  export function coerceAppliesTo(raw) {
@@ -97,6 +111,7 @@ const FRONTMATTER_ORDER = [
97
111
  'file-read-visibility',
98
112
  'gate',
99
113
  'applies-to',
114
+ 'read-when',
100
115
  ];
101
116
  /** Serialize a substrate frontmatter record + body into a complete `.md`
102
117
  * document. Frontmatter is emitted as a `---` fenced YAML block (the `yaml`
@@ -2,18 +2,18 @@ import { defineLeaf } from '../../core/command.js';
2
2
  import { usage } from '../../core/errors.js';
3
3
  import { parseFrontmatterGeneric } from '../../core/frontmatter.js';
4
4
  import { readText, writeText, pathExists } from '../../core/fs-utils.js';
5
- import { MEMORY_KINDS, MEMORY_SCOPES, VISIBILITY_RUNGS, resolveWriteTarget, memoryFilePath, coerceGate, coerceAppliesTo, serializeMemoryDoc, } from './shared.js';
5
+ import { MEMORY_KINDS, MEMORY_SCOPES, VISIBILITY_RUNGS, resolveWriteTarget, memoryFilePath, coerceGate, coerceAppliesTo, coerceReadWhen, serializeMemoryDoc, } from './shared.js';
6
6
  export const writeLeaf = defineLeaf({
7
7
  name: 'write',
8
8
  description: 'create or update a memory document',
9
- whenToUse: 'you are recording a new skill, reference, or preference — or revising one that already exists. Writes memory/<name>.md at the resolved scope from the frontmatter flags plus a body piped on stdin. Identity is path-derived: if <name> already exists at the scope it is updated in place, otherwise it is created.',
9
+ whenToUse: 'you are recording a new knowledge document or preference — or revising one that already exists. Writes memory/<name>.md at the resolved scope from the frontmatter flags plus a body piped on stdin. Identity is path-derived: if <name> already exists at the scope it is updated in place, otherwise it is created.',
10
10
  help: {
11
11
  name: 'memory write',
12
12
  summary: 'create or update memory/<name>.md at the resolved scope from frontmatter flags + a stdin body',
13
13
  guide: 'The body is the easy part; the craft is ROUTING — every frontmatter flag decides who sees this doc, when, and at what context cost. Each rung up is paid by every future agent at every boot or read, forever, so default each rung DOWN.\n\n' +
14
- 'Pick the kind. skill = how to DO something (a repeatable procedure/playbook); reference = what is TRUE or how something WORKS (a fact about the user, a system\u2019s behavior, code docs); preference = how to BEHAVE (a directive, a standing correction). The test that splits the close pair: does it DIRECT behavior ("always lint after authoring" \u2192 preference) or INFORM the world-model ("Silas likes chicken", "the daemon never reloads dist/" \u2192 reference)? A correction yields a preference, a learned fact a reference, a repeatable procedure a skill.\n\n' +
14
+ 'Pick the kind. knowledge = anything you CONSULT \u2014 how to DO something (a repeatable procedure/playbook) OR what is TRUE / how something WORKS (a fact about the user, a system\u2019s behavior, code docs); preference = how to BEHAVE (a directive, a standing correction). The test that splits them: does it DIRECT behavior ("always lint after authoring" \u2192 preference) or INFORM what you know ("Silas likes chicken", "the daemon never reloads dist/" \u2192 knowledge)? A correction yields a preference; a learned fact or a repeatable procedure yields knowledge.\n\n' +
15
15
  'Set the rungs \u2014 BOTH --system-prompt-visibility (boot) and --file-read-visibility (on-read) are REQUIRED on create. There is no default: the right rung is a case-by-case call, never a function of kind. The ladder, lowest to highest: `none` for niche docs almost nothing should pull into context; `name` for the common case \u2014 references and skills that are relatively uncommon but an agent (or the user, by name) may reach for; `preview` for docs important enough that their routing line is worth its token cost every session (preferences usually land here); `content` (full body injected) for a doc that would be `preview` except its body is already so short you may as well inline it whole. `content` is rare \u2014 when a `content` doc grows past a bullet or two, downgrade it to `preview`. Each axis is independent: usually one carries a real rung and the other is `none` (see the hook paragraph next).\n\n' +
16
- 'Choose the hook \u2014 boot vs file-read. There are exactly two moments a doc can surface. Behavior and procedure (preferences, skills) are relevant whatever file is open \u2192 surface at boot. Knowledge about code (references) belongs NEXT TO the code: put the file in that directory\u2019s .crouter/memory/ and it fires positionally when files there are read, costing nothing at boot. The exception that matters: a reference about a PERSON or PROCESS has no code directory to anchor to, so on-read triggering is meaningless \u2014 set --system-prompt-visibility preview so its routing line surfaces at boot instead.\n\n' +
16
+ 'Choose the hook \u2014 boot vs file-read. There are exactly two moments a doc can surface. Behavior (preferences) and how-to procedure are relevant whatever file is open \u2192 surface at boot. Knowledge about code belongs NEXT TO the code: put the file in that directory\u2019s .crouter/memory/ and it fires positionally when files there are read, costing nothing at boot. The exception that matters: a knowledge doc about a PERSON or PROCESS has no code directory to anchor to, so on-read triggering is meaningless \u2014 set --system-prompt-visibility preview so its routing line surfaces at boot instead.\n\n' +
17
17
  'Write the routing line (--when-and-why-to-read) FIRST, before storing anything: "When <circumstance the agent is in>, this <kind> should be read because <what the read buys>." The test: can a stranger mid-task decide from that one line alone whether to spend the read? If you cannot name the concrete situation that triggers it, you do not yet understand the memory \u2014 ask the user ONE sharp question instead of improvising. ("Remember I like chicken" routes cleanly \u2192 food/meal decisions; "be careful with the API" does not \u2192 which API, careful how, against what failure?) And NEVER paraphrase the advice in the routing line \u2014 a preview that gives away the gist makes every future agent skip the real read. BAD: "\u2026because it carries the placement policy \u2014 -h first, memory only for dev-mode material." GOOD: "\u2026because it carries the standing placement policy."\n\n' +
18
18
  'Find before write. `crtr memory find <topic>` first; grow ONE doc per recurring circumstance rather than minting near-duplicates \u2014 extend `food-preferences`, do not create `likes-chicken`. Group related docs with path names (area/topic). Do not store what is already recorded (code structure, git history, CLAUDE.md) or what only matters to this conversation.\n\n' +
19
19
  'Body: write for a STRANGER \u2014 a future session that shares none of this conversation. State current truth, not the history of getting there (no "as discussed"). Keep the reasoning behind a rule and cut everything else; dense beats complete, since every line costs a mid-task reader.\n\n' +
@@ -27,6 +27,7 @@ export const writeLeaf = defineLeaf({
27
27
  { kind: 'flag', name: 'file-read-visibility', type: 'enum', choices: [...VISIBILITY_RUNGS], required: false, constraint: 'Rung controlling how much of this document surfaces when it is read off disk. Required when creating — there is no kind default; pick a rung explicitly.' },
28
28
  { kind: 'flag', name: 'gate', type: 'string', required: false, constraint: 'Frontmatter gate — expression/condition that determines when this document applies.' },
29
29
  { kind: 'flag', name: 'applies-to', type: 'string', required: false, constraint: 'Frontmatter applies-to — glob/path scope the document applies to.' },
30
+ { kind: 'flag', name: 'read-when', type: 'string', required: false, constraint: 'Frontmatter read-when — a condition (field→matcher object) over a READ FILE’s own frontmatter that surfaces this doc on-read (a native rule). Same predicate vocabulary as --gate. Example: \'{tags: {contains: security}}\'.' },
30
31
  { kind: 'flag', name: 'scope', type: 'enum', choices: [...MEMORY_SCOPES], required: false, constraint: 'Target scope. Default: project when inside a project, else user.' },
31
32
  { kind: 'stdin', name: 'body', required: true, constraint: 'Document body (markdown, no frontmatter). Piped on stdin, or passed as the bare positional after <name>.' },
32
33
  ],
@@ -86,6 +87,9 @@ export const writeLeaf = defineLeaf({
86
87
  if (input['appliesTo'] !== undefined) {
87
88
  frontmatter['applies-to'] = coerceAppliesTo(input['appliesTo']);
88
89
  }
90
+ if (input['readWhen'] !== undefined) {
91
+ frontmatter['read-when'] = coerceReadWhen(input['readWhen']);
92
+ }
89
93
  writeText(path, serializeMemoryDoc(frontmatter, body));
90
94
  return {
91
95
  name,
@@ -1,4 +1,4 @@
1
- // `crtr memory` subtree — the document substrate (skills, references,
1
+ // `crtr memory` subtree — the document substrate (knowledge and
2
2
  // preferences) accessed via the CLI. Four flat leaves: list, read, find, write.
3
3
  // SKELETON ONLY (task B1): the `-h` contracts here are final; the leaf handlers
4
4
  // are stubs that B2 fills in. Mirrors `skill.ts` minus the loaded-skills
@@ -13,13 +13,13 @@ export function registerMemory() {
13
13
  return defineBranch({
14
14
  name: 'memory',
15
15
  rootEntry: {
16
- concept: 'a memory document you read on demand — a skill, reference, or preference',
16
+ concept: 'a memory document you read on demand — knowledge or a preference',
17
17
  desc: 'list, read, search, and write memory documents',
18
- useWhen: 'a task matches a stored skill, reference, or preference — read it before improvising. `crtr memory read <name>` loads one by name; `crtr memory list` browses the inventory; `crtr memory find` searches by topic when you do not yet know the name. Names are path-derived crtr identifiers, not file paths — never cat or find the markdown off disk.',
18
+ useWhen: 'a task matches stored knowledge or a preference — read it before improvising. `crtr memory read <name>` loads one by name; `crtr memory list` browses the inventory; `crtr memory find` searches by topic when you do not yet know the name. Names are path-derived crtr identifiers, not file paths — never cat or find the markdown off disk.',
19
19
  },
20
20
  help: {
21
21
  name: 'memory',
22
- summary: 'list, read, search, and write memory documents — skills, references, preferences',
22
+ summary: 'list, read, search, and write memory documents — knowledge and preferences',
23
23
  model: '`list` for a human inventory of what is stored — one line per document, the only surface that shows short-form. `read` (leaf) loads one document body by name, resolved project > user > builtin with leaf-name fallback; --frontmatter keeps the YAML header. `find` when you do not yet know which document applies — it ranks by relevance over name/when/why/short-form, --body to also weigh bodies, --grep for an exact regex over bodies. `write` creates or updates memory/<name>.md at a scope from frontmatter flags + a body piped on stdin. `lint` strict-parses the whole bounded corpus and fails on any invalid frontmatter — run it after authoring. A directory may carry an `INDEX.md` with the same frontmatter schema as any doc; the dir then renders as one entry at the INDEX\'s rung, and that rung is a ceiling for its whole subtree (`none` hides the dir) — when a doc mysteriously is not surfacing, check its ancestors\' INDEX rungs and its gate. Append `-h` at any leaf for its full schema, and `crtr memory write -h` for the authoring guide.',
24
24
  },
25
25
  children: [listLeaf, readLeaf, findLeaf, writeLeaf, lintLeaf],
@@ -7,7 +7,7 @@ export declare function childFollowUp(spawnerId: string | undefined): string;
7
7
  /** The live node "in front of you" in a tmux pane, HOST-AGNOSTIC. Defaults to
8
8
  * $TMUX_PANE / the caller's current pane when `pane` is omitted — shared by
9
9
  * `node recycle` / `node demote` / `node lifecycle` / `node close` / `node
10
- * cycle`, and the `canvas chord` / `canvas tmux-spread` leaves.
10
+ * cycle`, and the `canvas chord` leaf.
11
11
  *
12
12
  * Two resolutions, tried in order:
13
13
  * 1. VIEWER pane (broker host): a `crtr attach` viewer self-tags its pane with