@crouton-kit/crouter 0.3.31 → 0.3.33

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 (443) hide show
  1. package/README.md +8 -0
  2. package/dist/build-root.js +1 -0
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +2 -2
  4. package/dist/builtin-memory/crouter-development/personas/base-prompt.md +2 -2
  5. package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +5 -5
  6. package/dist/builtin-memory/crouter-development/personas.md +3 -4
  7. package/dist/builtin-memory/crouter-development/plugins.md +18 -18
  8. package/dist/builtin-memory/design.md +4 -1
  9. package/dist/builtin-memory/development.md +4 -1
  10. package/dist/builtin-memory/internal/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/nodes-and-canvas.md +6 -6
  12. package/dist/builtin-memory/internal/storage-tiers.md +5 -5
  13. package/dist/builtin-memory/planning.md +4 -1
  14. package/dist/builtin-memory/product.md +80 -0
  15. package/dist/builtin-memory/spec.md +4 -1
  16. package/dist/builtin-personas/advisor/PERSONA.md +10 -0
  17. package/dist/builtin-personas/design/PERSONA.md +2 -2
  18. package/dist/builtin-personas/design/orchestrator.md +3 -3
  19. package/dist/builtin-personas/developer/PERSONA.md +1 -1
  20. package/dist/builtin-personas/developer/orchestrator.md +2 -2
  21. package/dist/builtin-personas/explore/PERSONA.md +3 -3
  22. package/dist/builtin-personas/explore/orchestrator.md +4 -2
  23. package/dist/builtin-personas/general/PERSONA.md +1 -1
  24. package/dist/builtin-personas/general/orchestrator.md +1 -1
  25. package/dist/builtin-personas/orchestration-kernel.md +7 -14
  26. package/dist/builtin-personas/plan/PERSONA.md +1 -1
  27. package/dist/builtin-personas/plan/orchestrator.md +2 -2
  28. package/dist/builtin-personas/plan/reviewers/architecture-fit/PERSONA.md +1 -1
  29. package/dist/builtin-personas/plan/reviewers/code-smells/PERSONA.md +1 -1
  30. package/dist/builtin-personas/plan/reviewers/pattern-consistency/PERSONA.md +1 -1
  31. package/dist/builtin-personas/plan/reviewers/requirements-coverage/PERSONA.md +1 -1
  32. package/dist/builtin-personas/plan/reviewers/security/PERSONA.md +1 -1
  33. package/dist/builtin-personas/product/PERSONA.md +18 -0
  34. package/dist/builtin-personas/product/orchestrator.md +14 -0
  35. package/dist/builtin-personas/product/teardown/PERSONA.md +13 -0
  36. package/dist/builtin-personas/review/PERSONA.md +1 -1
  37. package/dist/builtin-personas/review/orchestrator.md +1 -1
  38. package/dist/builtin-personas/runtime-base.md +5 -0
  39. package/dist/builtin-personas/spec/PERSONA.md +1 -1
  40. package/dist/builtin-personas/spec/orchestrator.md +2 -2
  41. package/dist/builtin-personas/spec/requirements/PERSONA.md +1 -1
  42. package/dist/builtin-views/canvas/core.mjs +82 -1
  43. package/dist/builtin-views/canvas/tui.mjs +9 -5
  44. package/dist/builtin-views/canvas/web.jsx +3 -2
  45. package/dist/builtin-views/chat/core.mjs +725 -0
  46. package/dist/builtin-views/chat/text.mjs +101 -0
  47. package/dist/builtin-views/chat/tui.mjs +368 -0
  48. package/dist/builtin-views/chat/web.jsx +367 -0
  49. package/dist/builtin-views/prompt-review/core.mjs +863 -0
  50. package/dist/builtin-views/prompt-review/text.mjs +15 -0
  51. package/dist/builtin-views/prompt-review/tui.mjs +196 -0
  52. package/dist/builtin-views/prompt-review/web.jsx +484 -0
  53. package/dist/builtin-views/settings/core.mjs +397 -0
  54. package/dist/builtin-views/settings/text.mjs +40 -0
  55. package/dist/builtin-views/settings/tui.mjs +95 -0
  56. package/dist/builtin-views/settings/web.jsx +167 -0
  57. package/dist/cli.js +16 -3
  58. package/dist/clients/attach/__tests__/autocomplete-and-bash-mode.test.js +96 -0
  59. package/dist/clients/attach/__tests__/bash-bang-routing.test.js +58 -0
  60. package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.d.ts +1 -0
  61. package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.js +56 -0
  62. package/dist/clients/attach/__tests__/titled-editor.test.js +22 -1
  63. package/dist/clients/attach/attach-cmd.d.ts +18 -0
  64. package/dist/clients/attach/attach-cmd.js +1723 -795
  65. package/dist/clients/attach/canvas-panels.js +2 -2
  66. package/dist/clients/attach/chat-view.d.ts +10 -0
  67. package/dist/clients/attach/chat-view.js +23 -0
  68. package/dist/clients/attach/config-load.d.ts +8 -4
  69. package/dist/clients/attach/config-load.js +2 -0
  70. package/dist/clients/attach/extension-dialogs.d.ts +2 -3
  71. package/dist/clients/attach/extension-dialogs.js +7 -9
  72. package/dist/clients/attach/graph-overlay.js +3 -2
  73. package/dist/clients/attach/input-controller.d.ts +4 -3
  74. package/dist/clients/attach/input-controller.js +24 -3
  75. package/dist/clients/attach/slash-commands.d.ts +7 -7
  76. package/dist/clients/attach/slash-commands.js +38 -14
  77. package/dist/clients/attach/titled-editor.js +18 -14
  78. package/dist/clients/attach/view-socket.d.ts +2 -1
  79. package/dist/clients/attach/view-socket.js +27 -8
  80. package/dist/clients/web/__tests__/source-cache.test.d.ts +1 -0
  81. package/dist/clients/web/__tests__/source-cache.test.js +32 -0
  82. package/dist/clients/web/dev-server.js +1 -0
  83. package/dist/clients/web/events.js +9 -11
  84. package/dist/clients/web/server.d.ts +4 -3
  85. package/dist/clients/web/server.js +138 -31
  86. package/dist/clients/web/source-cache.d.ts +10 -0
  87. package/dist/clients/web/source-cache.js +57 -0
  88. package/dist/clients/web/web-cmd.js +28 -9
  89. package/dist/commands/__tests__/human.test.js +30 -28
  90. package/dist/commands/canvas-history/search.js +1 -1
  91. package/dist/commands/canvas-history.js +5 -8
  92. package/dist/commands/canvas-issue.d.ts +2 -0
  93. package/dist/commands/canvas-issue.js +148 -0
  94. package/dist/commands/canvas-prune.js +19 -0
  95. package/dist/commands/canvas-rebuild-index.d.ts +2 -0
  96. package/dist/commands/canvas-rebuild-index.js +57 -0
  97. package/dist/commands/canvas-snapshot.d.ts +2 -0
  98. package/dist/commands/canvas-snapshot.js +48 -0
  99. package/dist/commands/canvas-tmux-spread.d.ts +2 -0
  100. package/dist/commands/canvas-tmux-spread.js +188 -0
  101. package/dist/commands/canvas.d.ts +1 -0
  102. package/dist/commands/canvas.js +16 -1
  103. package/dist/commands/chord.js +143 -48
  104. package/dist/commands/daemon.js +3 -3
  105. package/dist/commands/human/prompts.d.ts +0 -1
  106. package/dist/commands/human/prompts.js +39 -54
  107. package/dist/commands/human/queue.d.ts +12 -1
  108. package/dist/commands/human/queue.js +468 -73
  109. package/dist/commands/human/shared.d.ts +3 -4
  110. package/dist/commands/human/shared.js +3 -3
  111. package/dist/commands/human.js +11 -10
  112. package/dist/commands/memory/find.js +3 -2
  113. package/dist/commands/memory/list.js +4 -3
  114. package/dist/commands/memory/read.js +3 -3
  115. package/dist/commands/memory/shared.d.ts +1 -4
  116. package/dist/commands/memory/shared.js +6 -9
  117. package/dist/commands/memory/write.js +3 -3
  118. package/dist/commands/memory.js +4 -7
  119. package/dist/commands/node-context.d.ts +2 -0
  120. package/dist/commands/node-context.js +172 -0
  121. package/dist/commands/node-snapshot.d.ts +2 -0
  122. package/dist/commands/node-snapshot.js +123 -0
  123. package/dist/commands/node.js +228 -52
  124. package/dist/commands/pkg/plugin-inspect.js +6 -6
  125. package/dist/commands/pkg/plugin-manage.js +1 -1
  126. package/dist/commands/pkg/plugin.js +2 -2
  127. package/dist/commands/pkg.js +2 -2
  128. package/dist/commands/push.d.ts +2 -0
  129. package/dist/commands/push.js +79 -11
  130. package/dist/commands/revive.js +74 -1
  131. package/dist/commands/search/answer.d.ts +1 -0
  132. package/dist/commands/search/answer.js +50 -0
  133. package/dist/commands/search/contents.d.ts +1 -0
  134. package/dist/commands/search/contents.js +96 -0
  135. package/dist/commands/search/exa.d.ts +53 -0
  136. package/dist/commands/search/exa.js +155 -0
  137. package/dist/commands/search/puremd.d.ts +11 -0
  138. package/dist/commands/search/puremd.js +53 -0
  139. package/dist/commands/search/web.d.ts +1 -0
  140. package/dist/commands/search/web.js +65 -0
  141. package/dist/commands/search.d.ts +2 -0
  142. package/dist/commands/search.js +24 -0
  143. package/dist/commands/sys/__tests__/sync-import.test.d.ts +1 -0
  144. package/dist/commands/sys/__tests__/sync-import.test.js +72 -0
  145. package/dist/commands/sys/config.js +59 -10
  146. package/dist/commands/sys/doctor.js +56 -4
  147. package/dist/commands/sys/prompt-review.d.ts +1 -0
  148. package/dist/commands/sys/prompt-review.js +178 -0
  149. package/dist/commands/sys/promptstudio.d.ts +2 -0
  150. package/dist/commands/sys/promptstudio.js +65 -0
  151. package/dist/commands/sys/settings.d.ts +2 -0
  152. package/dist/commands/sys/settings.js +16 -0
  153. package/dist/commands/sys/sync.js +311 -159
  154. package/dist/commands/sys/sysprompt.d.ts +1 -0
  155. package/dist/commands/sys/sysprompt.js +86 -0
  156. package/dist/commands/sys.js +9 -5
  157. package/dist/commands/view-new.js +2 -2
  158. package/dist/core/__tests__/artifact-paths.test.d.ts +1 -0
  159. package/dist/core/__tests__/artifact-paths.test.js +44 -0
  160. package/dist/core/__tests__/broker-preflight.test.d.ts +1 -0
  161. package/dist/core/__tests__/broker-preflight.test.js +85 -0
  162. package/dist/core/__tests__/broker-sdk-wiring.test.js +15 -0
  163. package/dist/core/__tests__/canvas.test.js +37 -1
  164. package/dist/core/__tests__/chat-view-reconnect.test.d.ts +1 -0
  165. package/dist/core/__tests__/chat-view-reconnect.test.js +70 -0
  166. package/dist/core/__tests__/child-death-wake.test.js +11 -2
  167. package/dist/core/__tests__/close.test.js +39 -1
  168. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +1 -0
  169. package/dist/core/__tests__/connection-reconnect-resume.test.js +37 -0
  170. package/dist/core/__tests__/context-intro.test.js +48 -14
  171. package/dist/core/__tests__/daemon-boot.test.js +182 -9
  172. package/dist/core/__tests__/editor-label.test.d.ts +1 -0
  173. package/dist/core/__tests__/editor-label.test.js +26 -0
  174. package/dist/core/__tests__/fault-marker.test.d.ts +1 -0
  175. package/dist/core/__tests__/fault-marker.test.js +112 -0
  176. package/dist/core/__tests__/fault-retry-rewind.test.d.ts +1 -0
  177. package/dist/core/__tests__/fault-retry-rewind.test.js +123 -0
  178. package/dist/core/__tests__/fixtures/fake-engine.d.ts +30 -4
  179. package/dist/core/__tests__/fixtures/fake-engine.js +156 -17
  180. package/dist/core/__tests__/fixtures/fake-pi-host.js +10 -1
  181. package/dist/core/__tests__/full/human-new-window-regression.test.js +1 -1
  182. package/dist/core/__tests__/helpers/harness.d.ts +1 -1
  183. package/dist/core/__tests__/helpers/harness.js +9 -3
  184. package/dist/core/__tests__/human-stranded-deliver.test.js +38 -1
  185. package/dist/core/__tests__/human-surface-target.test.js +1 -1
  186. package/dist/core/__tests__/kickoff.test.js +18 -19
  187. package/dist/core/__tests__/memory-resolver.test.js +12 -1
  188. package/dist/core/__tests__/migration.test.js +49 -14
  189. package/dist/core/__tests__/model-ladders.test.d.ts +1 -0
  190. package/dist/core/__tests__/model-ladders.test.js +160 -0
  191. package/dist/core/__tests__/node-env.test.d.ts +1 -0
  192. package/dist/core/__tests__/node-env.test.js +26 -0
  193. package/dist/core/__tests__/push-final-guard.test.js +7 -1
  194. package/dist/core/__tests__/relaunch-root.test.js +9 -9
  195. package/dist/core/__tests__/revive.test.js +36 -6
  196. package/dist/core/__tests__/spawn-root.test.js +24 -1
  197. package/dist/core/__tests__/stop-guard.test.js +10 -0
  198. package/dist/core/__tests__/stranded-relaunch.test.d.ts +1 -0
  199. package/dist/core/__tests__/stranded-relaunch.test.js +72 -0
  200. package/dist/core/__tests__/tmux-surface.test.js +5 -1
  201. package/dist/core/__tests__/unknown-path.test.js +19 -19
  202. package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +1 -0
  203. package/dist/core/__tests__/yield-ensures-daemon.test.js +54 -0
  204. package/dist/core/artifact.d.ts +2 -33
  205. package/dist/core/artifact.js +27 -87
  206. package/dist/core/bootstrap.js +2 -0
  207. package/dist/core/canvas/browse/__tests__/model.test.js +35 -1
  208. package/dist/core/canvas/browse/app.js +87 -17
  209. package/dist/core/canvas/browse/model.d.ts +10 -1
  210. package/dist/core/canvas/browse/model.js +37 -1
  211. package/dist/core/canvas/browse/render.js +35 -33
  212. package/dist/core/canvas/canvas.d.ts +7 -0
  213. package/dist/core/canvas/canvas.js +54 -5
  214. package/dist/core/canvas/db.js +35 -8
  215. package/dist/core/canvas/labels.d.ts +6 -8
  216. package/dist/core/canvas/labels.js +8 -11
  217. package/dist/core/canvas/nav-model.d.ts +5 -4
  218. package/dist/core/canvas/nav-model.js +31 -17
  219. package/dist/core/canvas/paths.d.ts +18 -1
  220. package/dist/core/canvas/paths.js +37 -2
  221. package/dist/core/canvas/render.d.ts +25 -0
  222. package/dist/core/canvas/render.js +96 -13
  223. package/dist/core/canvas/status-glyph.d.ts +35 -0
  224. package/dist/core/canvas/status-glyph.js +104 -0
  225. package/dist/core/canvas/types.d.ts +2 -2
  226. package/dist/core/config.js +114 -16
  227. package/dist/core/fault-classifier.d.ts +41 -0
  228. package/dist/core/fault-classifier.js +110 -0
  229. package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +1 -0
  230. package/dist/core/feed/__tests__/empty-node-guard.test.js +45 -0
  231. package/dist/core/feed/feed.js +8 -0
  232. package/dist/core/feed/inbox.d.ts +15 -0
  233. package/dist/core/feed/inbox.js +40 -14
  234. package/dist/core/frontmatter.d.ts +1 -11
  235. package/dist/core/frontmatter.js +1 -55
  236. package/dist/core/hearth/config.d.ts +2 -0
  237. package/dist/core/hearth/config.js +75 -0
  238. package/dist/core/hearth/guest-env.d.ts +2 -0
  239. package/dist/core/hearth/guest-env.js +11 -0
  240. package/dist/core/hearth/index.d.ts +5 -0
  241. package/dist/core/hearth/index.js +5 -0
  242. package/dist/core/hearth/provider.d.ts +21 -0
  243. package/dist/core/hearth/provider.js +10 -0
  244. package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +10 -0
  245. package/dist/core/hearth/providers/blaxel-bootstrap.js +39 -0
  246. package/dist/core/hearth/providers/blaxel-home.d.ts +11 -0
  247. package/dist/core/hearth/providers/blaxel-home.js +126 -0
  248. package/dist/core/hearth/providers/blaxel.d.ts +26 -0
  249. package/dist/core/hearth/providers/blaxel.js +208 -0
  250. package/dist/core/hearth/providers/types.d.ts +72 -0
  251. package/dist/core/hearth/providers/types.js +1 -0
  252. package/dist/core/hearth/registry.d.ts +15 -0
  253. package/dist/core/hearth/registry.js +179 -0
  254. package/dist/core/hearth/types.d.ts +121 -0
  255. package/dist/core/hearth/types.js +1 -0
  256. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +1 -0
  257. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +79 -0
  258. package/dist/core/{skill-sync → host-exports}/builtins.d.ts +21 -13
  259. package/dist/core/host-exports/builtins.js +68 -0
  260. package/dist/core/{skill-sync → host-exports}/export.d.ts +9 -6
  261. package/dist/core/{skill-sync → host-exports}/export.js +37 -14
  262. package/dist/core/io.js +1 -1
  263. package/dist/core/log.d.ts +9 -0
  264. package/dist/core/log.js +113 -0
  265. package/dist/core/memory-resolver.d.ts +8 -8
  266. package/dist/core/memory-resolver.js +15 -28
  267. package/dist/core/personas/index.d.ts +4 -4
  268. package/dist/core/personas/index.js +2 -2
  269. package/dist/core/personas/loader.d.ts +51 -0
  270. package/dist/core/personas/loader.js +54 -50
  271. package/dist/core/personas/resolve.d.ts +43 -27
  272. package/dist/core/personas/resolve.js +336 -94
  273. package/dist/core/runtime/auth-reload.d.ts +7 -0
  274. package/dist/core/runtime/auth-reload.js +69 -0
  275. package/dist/core/runtime/bearings.d.ts +35 -15
  276. package/dist/core/runtime/bearings.js +305 -44
  277. package/dist/core/runtime/branded-host.d.ts +4 -2
  278. package/dist/core/runtime/branded-host.js +66 -4
  279. package/dist/core/runtime/broker-protocol.d.ts +38 -3
  280. package/dist/core/runtime/broker.js +343 -18
  281. package/dist/core/runtime/close.js +37 -29
  282. package/dist/core/runtime/connectivity.d.ts +12 -0
  283. package/dist/core/runtime/connectivity.js +73 -0
  284. package/dist/core/runtime/fault-recovery-nudge.d.ts +2 -0
  285. package/dist/core/runtime/fault-recovery-nudge.js +2 -0
  286. package/dist/core/runtime/fault-recovery.d.ts +23 -0
  287. package/dist/core/runtime/fault-recovery.js +74 -0
  288. package/dist/core/runtime/fault.d.ts +25 -0
  289. package/dist/core/runtime/fault.js +176 -0
  290. package/dist/core/runtime/front-door.d.ts +1 -1
  291. package/dist/core/runtime/front-door.js +2 -2
  292. package/dist/core/runtime/host.d.ts +10 -0
  293. package/dist/core/runtime/host.js +71 -9
  294. package/dist/core/runtime/kickoff.js +31 -45
  295. package/dist/core/runtime/launch.d.ts +32 -18
  296. package/dist/core/runtime/launch.js +148 -43
  297. package/dist/core/runtime/model-swap.d.ts +18 -0
  298. package/dist/core/runtime/model-swap.js +95 -0
  299. package/dist/core/runtime/naming.d.ts +7 -0
  300. package/dist/core/runtime/naming.js +61 -9
  301. package/dist/core/runtime/nodes.js +6 -1
  302. package/dist/core/runtime/persona.js +16 -17
  303. package/dist/core/runtime/placement.d.ts +36 -31
  304. package/dist/core/runtime/placement.js +149 -64
  305. package/dist/core/runtime/promote.d.ts +2 -0
  306. package/dist/core/runtime/promote.js +23 -3
  307. package/dist/core/runtime/recycle.js +6 -4
  308. package/dist/core/runtime/reset.d.ts +5 -2
  309. package/dist/core/runtime/reset.js +2 -2
  310. package/dist/core/runtime/revive.d.ts +4 -0
  311. package/dist/core/runtime/revive.js +27 -9
  312. package/dist/core/runtime/roadmap.d.ts +1 -1
  313. package/dist/core/runtime/roadmap.js +1 -1
  314. package/dist/core/runtime/spawn.d.ts +2 -2
  315. package/dist/core/runtime/spawn.js +30 -6
  316. package/dist/core/runtime/stop-guard.js +6 -1
  317. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  318. package/dist/core/runtime/tmux-chrome.js +1 -1
  319. package/dist/core/runtime/tmux.d.ts +29 -6
  320. package/dist/core/runtime/tmux.js +134 -80
  321. package/dist/core/runtime/view-socket-client.d.ts +46 -0
  322. package/dist/core/runtime/view-socket-client.js +203 -0
  323. package/dist/core/substrate/index.d.ts +1 -1
  324. package/dist/core/substrate/index.js +1 -1
  325. package/dist/core/substrate/on-read.js +16 -4
  326. package/dist/core/substrate/render.d.ts +10 -13
  327. package/dist/core/substrate/render.js +56 -51
  328. package/dist/core/tui/host.js +83 -18
  329. package/dist/core/view/__tests__/transport-cache.test.d.ts +1 -0
  330. package/dist/core/view/__tests__/transport-cache.test.js +62 -0
  331. package/dist/core/view/contract.d.ts +20 -0
  332. package/dist/core/view/stream-local.d.ts +3 -0
  333. package/dist/core/view/stream-local.js +184 -0
  334. package/dist/core/view/transport-cache.d.ts +8 -0
  335. package/dist/core/view/transport-cache.js +38 -0
  336. package/dist/core/view/transport-local.js +4 -0
  337. package/dist/core/view/transport.d.ts +7 -1
  338. package/dist/daemon/crtrd.d.ts +3 -19
  339. package/dist/daemon/crtrd.js +139 -178
  340. package/dist/daemon/manage.d.ts +18 -1
  341. package/dist/daemon/manage.js +54 -9
  342. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.d.ts +1 -0
  343. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.js +289 -0
  344. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.d.ts +1 -0
  345. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.js +34 -0
  346. package/dist/hearth/wake-proxy/__tests__/guest-source.test.d.ts +1 -0
  347. package/dist/hearth/wake-proxy/__tests__/guest-source.test.js +203 -0
  348. package/dist/hearth/wake-proxy/__tests__/hardening.test.d.ts +1 -0
  349. package/dist/hearth/wake-proxy/__tests__/hardening.test.js +59 -0
  350. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.d.ts +1 -0
  351. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.js +372 -0
  352. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.d.ts +1 -0
  353. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.js +258 -0
  354. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.d.ts +1 -0
  355. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.js +437 -0
  356. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.d.ts +1 -0
  357. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.js +455 -0
  358. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.d.ts +1 -0
  359. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.js +15 -0
  360. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.d.ts +1 -0
  361. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.js +141 -0
  362. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.d.ts +1 -0
  363. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.js +143 -0
  364. package/dist/hearth/wake-proxy/anthropic-oauth.d.ts +58 -0
  365. package/dist/hearth/wake-proxy/anthropic-oauth.js +189 -0
  366. package/dist/hearth/wake-proxy/auth.d.ts +22 -0
  367. package/dist/hearth/wake-proxy/auth.js +128 -0
  368. package/dist/hearth/wake-proxy/config.d.ts +2 -0
  369. package/dist/hearth/wake-proxy/config.js +151 -0
  370. package/dist/hearth/wake-proxy/guest-source.d.ts +14 -0
  371. package/dist/hearth/wake-proxy/guest-source.js +130 -0
  372. package/dist/hearth/wake-proxy/hearth-status.d.ts +44 -0
  373. package/dist/hearth/wake-proxy/hearth-status.js +267 -0
  374. package/dist/hearth/wake-proxy/home.d.ts +67 -0
  375. package/dist/hearth/wake-proxy/home.js +297 -0
  376. package/dist/hearth/wake-proxy/main.d.ts +1 -0
  377. package/dist/hearth/wake-proxy/main.js +134 -0
  378. package/dist/hearth/wake-proxy/model-auth.d.ts +13 -0
  379. package/dist/hearth/wake-proxy/model-auth.js +345 -0
  380. package/dist/hearth/wake-proxy/proxy.d.ts +35 -0
  381. package/dist/hearth/wake-proxy/proxy.js +716 -0
  382. package/dist/hearth/wake-proxy/public-source-gate.d.ts +9 -0
  383. package/dist/hearth/wake-proxy/public-source-gate.js +409 -0
  384. package/dist/hearth/wake-proxy/redact.d.ts +1 -0
  385. package/dist/hearth/wake-proxy/redact.js +17 -0
  386. package/dist/hearth/wake-proxy/server.d.ts +11 -0
  387. package/dist/hearth/wake-proxy/server.js +142 -0
  388. package/dist/hearth/wake-proxy/state.d.ts +18 -0
  389. package/dist/hearth/wake-proxy/state.js +342 -0
  390. package/dist/hearth/wake-proxy/types.d.ts +76 -0
  391. package/dist/hearth/wake-proxy/types.js +1 -0
  392. package/dist/index.js +3 -2
  393. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +6 -5
  394. package/dist/pi-extensions/canvas-context-intro.js +7 -7
  395. package/dist/pi-extensions/canvas-doc-substrate.js +19 -22
  396. package/dist/pi-extensions/canvas-nav.js +15 -8
  397. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  398. package/dist/pi-extensions/canvas-stophook.js +78 -11
  399. package/dist/types.d.ts +39 -20
  400. package/dist/types.js +38 -13
  401. package/dist/web/runtime.js +141 -42
  402. package/dist/web/transport-http.js +7 -5
  403. package/dist/web/transport-stream.d.ts +3 -0
  404. package/dist/web/transport-stream.js +204 -0
  405. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  406. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  407. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  408. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  409. package/dist/web-client/assets/fraunces-latin-ext-wght-normal-Ca2vKHc0.woff2 +0 -0
  410. package/dist/web-client/assets/fraunces-latin-wght-normal-ukD16Tqj.woff2 +0 -0
  411. package/dist/web-client/assets/fraunces-vietnamese-wght-normal-CnvboYUG.woff2 +0 -0
  412. package/dist/web-client/assets/index-BZUxTkv5.css +2 -0
  413. package/dist/web-client/assets/index-D36PNBj4.js +80 -0
  414. package/dist/web-client/assets/instrument-sans-latin-ext-wght-normal-B5bTHO_g.woff2 +0 -0
  415. package/dist/web-client/assets/instrument-sans-latin-wght-normal-BbzFLZTg.woff2 +0 -0
  416. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  417. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  418. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  419. package/dist/web-client/index.html +3 -2
  420. package/package.json +32 -10
  421. package/dist/core/__tests__/error-stall-recycle.test.js +0 -141
  422. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +0 -57
  423. package/dist/core/skill-sync/builtins.js +0 -112
  424. package/dist/core/skill-sync/claude-plugins.d.ts +0 -23
  425. package/dist/core/skill-sync/claude-plugins.js +0 -71
  426. package/dist/core/skill-sync/engine.d.ts +0 -42
  427. package/dist/core/skill-sync/engine.js +0 -633
  428. package/dist/core/skill-sync/manifest.d.ts +0 -64
  429. package/dist/core/skill-sync/manifest.js +0 -181
  430. package/dist/core/skill-sync/profile.d.ts +0 -76
  431. package/dist/core/skill-sync/profile.js +0 -173
  432. package/dist/core/skill-sync/snapshot.d.ts +0 -57
  433. package/dist/core/skill-sync/snapshot.js +0 -120
  434. package/dist/pi-extensions/canvas-commands.d.ts +0 -37
  435. package/dist/pi-extensions/canvas-commands.js +0 -113
  436. package/dist/pi-extensions/canvas-resume.d.ts +0 -21
  437. package/dist/pi-extensions/canvas-resume.js +0 -83
  438. package/dist/pi-extensions/canvas-view.d.ts +0 -21
  439. package/dist/pi-extensions/canvas-view.js +0 -76
  440. package/dist/web-client/assets/index-BUvQb4hR.css +0 -2
  441. package/dist/web-client/assets/index-ClLQXYAE.js +0 -10
  442. /package/dist/{core/__tests__/error-stall-recycle.test.d.ts → clients/attach/__tests__/autocomplete-and-bash-mode.test.d.ts} +0 -0
  443. /package/dist/{core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts → clients/attach/__tests__/bash-bang-routing.test.d.ts} +0 -0
@@ -1,134 +1,376 @@
1
1
  /**
2
2
  * Persona resolver — composes base + orchestrator personas into a
3
3
  * ResolvedPersona ready for use when spawning a canvas node.
4
- *
5
- * Composition rules:
6
- * mode==='base'
7
- * → load <kind>/PERSONA.md; if missing fall back to general defaults.
8
- *
9
- * mode==='orchestrator'
10
- * → prefer <kind>/orchestrator.md (which must embed the kernel via
11
- * @include orchestration-kernel.md — inlined by the loader).
12
- * If no orchestrator.md exists for this kind, compose:
13
- * <kind>/PERSONA.md body + '\n\n' + kernel body
14
- * If even the PERSONA.md is missing, fall back to general defaults + kernel.
15
- *
16
- * Frontmatter from whichever file is the primary source (orchestrator.md >
17
- * PERSONA.md) supplies model/skills/extensions/tools. Lifecycle and spine position
18
- * are INPUTS (the caller decides them — root/child, terminal/resident), not
19
- * derived here; they select the lifecycle/spine protocol fragments spliced
20
- * ahead of the persona body.
21
4
  */
22
- import { loadPersona, loadKernel, loadRuntimeBase, loadSpineFragment, loadLifecycleFragment, loadWaitingFragment, subPersonasFor } from './loader.js';
5
+ import { getNode } from '../canvas/index.js';
6
+ import { renderKnowledgeBlock, renderPreferencesSection } from '../substrate/render.js';
7
+ import { loadPersona, loadPersonaSource, loadKernelSource, loadRuntimeBaseSource, loadSpineFragmentSource, loadLifecycleFragmentSource, loadWaitingFragmentSource, loadScopedText, subPersonasFor, } from './loader.js';
23
8
  // ---------------------------------------------------------------------------
24
9
  // Helpers
25
10
  // ---------------------------------------------------------------------------
26
11
  function toStringArray(v) {
27
12
  if (!Array.isArray(v))
28
13
  return [];
29
- // yaml.parse coerces scalars to native types; the persona prompt needs strings,
30
- // so coerce each scalar element (dropping nested objects/arrays/null) — this
31
- // mirrors the prior hand-rolled parser, which returned every scalar as a string.
32
14
  return v.filter((x) => x != null && typeof x !== 'object').map((x) => String(x));
33
15
  }
34
16
  function toOptionalString(v) {
35
17
  if (typeof v === 'string')
36
18
  return v;
37
- // Preserve the legacy parser's string-typed contract for native scalars
38
- // (e.g. `model: 4` must compose as "4", not be dropped as a non-string).
39
19
  if (typeof v === 'number' || typeof v === 'boolean')
40
20
  return String(v);
41
21
  return undefined;
42
22
  }
43
- /** The bare-minimum system prompt used when no persona file is found at all. */
44
23
  function fallbackBasePrompt(kind) {
45
24
  return `You are a ${kind} agent. Complete the task you have been given.`;
46
25
  }
47
- /** Compose the runtime protocol that precedes every persona body: the
48
- * lifecycle-neutral base (identity/delegate/ask/promote), then the spine
49
- * fragment (report-up vs. silent, keyed on whether the node has a manager),
50
- * then the lifecycle fragment (finish-with-`push final` vs. dormant/wake). The
51
- * kind×mode persona body follows after a rule. Empty fragments drop out. */
52
- /** Render the "sub-personas you may spawn" menu for a kind that has any
53
- * available to it. Returns '' when none are. Data-driven: one line per
54
- * sub-persona, its spawn string + its `whenToUse`. A sub-persona surfaces here
55
- * for a kind when its `availableTo` includes that kind (default: its own
56
- * top-level ancestor) or is the wildcard. */
26
+ function approxTokens(text) {
27
+ return Math.ceil(text.length / 4);
28
+ }
29
+ function makeLayer(part) {
30
+ return {
31
+ ...part,
32
+ chars: part.text.length,
33
+ tokens: approxTokens(part.text),
34
+ };
35
+ }
36
+ function trimBlock(text) {
37
+ return text.trim();
38
+ }
39
+ function includeTargets(rawBody) {
40
+ const targets = [];
41
+ const re = /^@include\s+(\S+)\s*$/gm;
42
+ for (const match of rawBody.matchAll(re)) {
43
+ targets.push(match[1]);
44
+ }
45
+ return targets;
46
+ }
47
+ function addSource(list, seen, source) {
48
+ if (source === null)
49
+ return;
50
+ const key = `${source.scope}:${source.path}`;
51
+ if (seen.has(key))
52
+ return;
53
+ seen.add(key);
54
+ list.push(source);
55
+ }
56
+ function resolveSourceRef(path, label) {
57
+ const loaded = loadScopedText(path);
58
+ if (!loaded)
59
+ return null;
60
+ return { id: label, label, path: loaded.sourcePath, scope: loaded.scope };
61
+ }
62
+ function collectPersonaSources(primary, fallbackLabel) {
63
+ const sources = [];
64
+ const seen = new Set();
65
+ if (primary !== null) {
66
+ addSource(sources, seen, {
67
+ id: fallbackLabel,
68
+ label: fallbackLabel,
69
+ path: primary.sourcePath,
70
+ scope: primary.scope,
71
+ });
72
+ for (const target of includeTargets(primary.rawBody)) {
73
+ addSource(sources, seen, resolveSourceRef(target, `included: ${target}`));
74
+ }
75
+ }
76
+ return sources;
77
+ }
78
+ function basePersonaLayer(kind, mode) {
79
+ const source = loadPersonaSource(kind, mode);
80
+ if (source !== null) {
81
+ const label = mode === 'base' ? 'Persona body' : 'Orchestrator body';
82
+ return {
83
+ layer: makeLayer({
84
+ id: 'persona-body',
85
+ label,
86
+ group: 'persona',
87
+ source: source.source,
88
+ sourcePath: source.sourcePath,
89
+ scope: source.scope,
90
+ included: true,
91
+ condition: null,
92
+ text: source.body || fallbackBasePrompt(kind),
93
+ }),
94
+ sources: collectPersonaSources(source, label),
95
+ };
96
+ }
97
+ if (mode === 'orchestrator') {
98
+ const base = loadPersonaSource(kind, 'base');
99
+ const kernel = loadKernelSource();
100
+ const body = `${base?.body || fallbackBasePrompt(kind)}${kernel ? `\n\n${kernel.text}` : ''}`;
101
+ const layer = makeLayer({
102
+ id: 'persona-body',
103
+ label: 'Orchestrator body',
104
+ group: 'persona',
105
+ source: base?.sourcePath !== undefined ? base.source : 'generated: base persona + kernel',
106
+ sourcePath: base?.sourcePath ?? null,
107
+ scope: base?.scope ?? 'generated',
108
+ included: true,
109
+ condition: null,
110
+ text: body,
111
+ });
112
+ const sources = [];
113
+ const seen = new Set();
114
+ if (base !== null) {
115
+ addSource(sources, seen, { id: 'persona-body', label: 'Persona body', path: base.sourcePath, scope: base.scope });
116
+ for (const target of includeTargets(base.rawBody)) {
117
+ addSource(sources, seen, resolveSourceRef(target, `included: ${target}`));
118
+ }
119
+ }
120
+ if (kernel !== null) {
121
+ addSource(sources, seen, { id: 'kernel', label: 'Kernel', path: kernel.sourcePath, scope: kernel.scope });
122
+ }
123
+ return { layer, sources };
124
+ }
125
+ const layer = makeLayer({
126
+ id: 'persona-body',
127
+ label: 'Persona body',
128
+ group: 'persona',
129
+ source: 'generated: fallback persona',
130
+ sourcePath: null,
131
+ scope: 'generated',
132
+ included: true,
133
+ condition: null,
134
+ text: fallbackBasePrompt(kind),
135
+ });
136
+ return { layer, sources: [] };
137
+ }
138
+ function protocolLayers(lifecycle, hasManager) {
139
+ const runtime = loadRuntimeBaseSource();
140
+ const wait = loadWaitingFragmentSource();
141
+ const spineHas = loadSpineFragmentSource(true);
142
+ const spineNo = loadSpineFragmentSource(false);
143
+ const lifecycleTerminal = loadLifecycleFragmentSource('terminal');
144
+ const lifecycleResident = loadLifecycleFragmentSource('resident');
145
+ return [
146
+ makeLayer({
147
+ id: 'runtime-base',
148
+ label: 'Runtime base',
149
+ group: 'protocol',
150
+ source: 'personas/runtime-base.md',
151
+ sourcePath: runtime?.sourcePath ?? null,
152
+ scope: runtime?.scope ?? 'generated',
153
+ included: true,
154
+ condition: null,
155
+ text: trimBlock(runtime?.text ?? ''),
156
+ }),
157
+ makeLayer({
158
+ id: 'spine-has-manager',
159
+ label: 'Has manager',
160
+ group: 'protocol',
161
+ source: 'personas/spine/has-manager.md',
162
+ sourcePath: spineHas?.sourcePath ?? null,
163
+ scope: spineHas?.scope ?? 'generated',
164
+ included: hasManager,
165
+ condition: hasManager ? null : 'hasManager == false',
166
+ text: trimBlock(spineHas?.text ?? ''),
167
+ }),
168
+ makeLayer({
169
+ id: 'spine-no-manager',
170
+ label: 'No manager',
171
+ group: 'protocol',
172
+ source: 'personas/spine/no-manager.md',
173
+ sourcePath: spineNo?.sourcePath ?? null,
174
+ scope: spineNo?.scope ?? 'generated',
175
+ included: !hasManager,
176
+ condition: hasManager ? 'hasManager == true' : null,
177
+ text: trimBlock(spineNo?.text ?? ''),
178
+ }),
179
+ makeLayer({
180
+ id: 'lifecycle-terminal',
181
+ label: 'Terminal lifecycle',
182
+ group: 'protocol',
183
+ source: 'personas/lifecycle/terminal.md',
184
+ sourcePath: lifecycleTerminal?.sourcePath ?? null,
185
+ scope: lifecycleTerminal?.scope ?? 'generated',
186
+ included: lifecycle === 'terminal',
187
+ condition: lifecycle === 'terminal' ? null : 'lifecycle == resident',
188
+ text: trimBlock(lifecycleTerminal?.text ?? ''),
189
+ }),
190
+ makeLayer({
191
+ id: 'lifecycle-resident',
192
+ label: 'Resident lifecycle',
193
+ group: 'protocol',
194
+ source: 'personas/lifecycle/resident.md',
195
+ sourcePath: lifecycleResident?.sourcePath ?? null,
196
+ scope: lifecycleResident?.scope ?? 'generated',
197
+ included: lifecycle === 'resident',
198
+ condition: lifecycle === 'resident' ? null : 'lifecycle == terminal',
199
+ text: trimBlock(lifecycleResident?.text ?? ''),
200
+ }),
201
+ makeLayer({
202
+ id: 'waiting',
203
+ label: 'Waiting',
204
+ group: 'protocol',
205
+ source: 'personas/waiting.md',
206
+ sourcePath: wait?.sourcePath ?? null,
207
+ scope: wait?.scope ?? 'generated',
208
+ included: true,
209
+ condition: null,
210
+ text: trimBlock(wait?.text ?? ''),
211
+ }),
212
+ makeLayer({
213
+ id: 'separator',
214
+ label: 'Separator',
215
+ group: 'protocol',
216
+ source: 'generated: separator',
217
+ sourcePath: null,
218
+ scope: 'generated',
219
+ included: true,
220
+ condition: null,
221
+ text: '---',
222
+ }),
223
+ ];
224
+ }
57
225
  function renderSubPersonaMenu(kind) {
58
226
  const subs = subPersonasFor(kind);
59
227
  if (subs.length === 0)
60
- return '';
61
- const lines = subs.map((s) => `- \`${s.kind}\` — ${s.whenToUse}`);
62
- return [
228
+ return { layer: null, sources: [] };
229
+ const lines = [
63
230
  '## Sub-personas you may spawn',
64
231
  '',
65
- `These specialist sub-personas are available to the ${kind} kind. Spawn one with \`crtr node new --kind <sub> "<scope>"\`, giving it only its scope, never your suspicions: a reviewer handed a hint anchors on it instead of finding problems independently.`,
232
+ `These specialist sub-personas are available to the ${kind} kind. Spawn one with \`crtr node new --kind <sub> "<scope>"\`, and treat it as its own scope instead of dragging unrelated context into it.`,
66
233
  '',
67
- ...lines,
68
- ].join('\n');
234
+ ];
235
+ const sources = [];
236
+ const seen = new Set();
237
+ for (const sub of subs) {
238
+ const src = loadPersonaSource(sub.kind, 'base');
239
+ if (src !== null) {
240
+ addSource(sources, seen, { id: sub.kind, label: sub.kind, path: src.sourcePath, scope: src.scope });
241
+ lines.push(`- \`${sub.kind}\` — ${sub.whenToUse} (${src.sourcePath})`);
242
+ }
243
+ else {
244
+ lines.push(`- \`${sub.kind}\` — ${sub.whenToUse}`);
245
+ }
246
+ }
247
+ return {
248
+ layer: makeLayer({
249
+ id: 'subpersona-menu',
250
+ label: 'Sub-persona menu',
251
+ group: 'generated',
252
+ source: 'generated: sub-persona menu',
253
+ sourcePath: null,
254
+ scope: 'generated',
255
+ included: true,
256
+ condition: null,
257
+ text: lines.join('\n'),
258
+ }),
259
+ sources,
260
+ };
69
261
  }
70
- function composeProtocol(personaPrompt, kind, lifecycle, hasManager) {
262
+ function coreLayers(kind, mode, opts) {
263
+ const protocol = protocolLayers(opts.lifecycle, opts.hasManager);
264
+ const body = basePersonaLayer(kind, mode);
71
265
  const menu = renderSubPersonaMenu(kind);
72
- const body = menu ? `${personaPrompt}\n\n${menu}` : personaPrompt;
73
- const protocol = [
74
- loadRuntimeBase(),
75
- loadSpineFragment(hasManager),
76
- loadLifecycleFragment(lifecycle),
77
- loadWaitingFragment(),
78
- ]
79
- .filter((s) => s.length > 0)
80
- .join('\n\n');
81
- return protocol ? `${protocol}\n\n---\n\n${body}` : body;
266
+ const layers = [...protocol, body.layer];
267
+ if (menu.layer !== null)
268
+ layers.push(menu.layer);
269
+ const sources = [];
270
+ const seen = new Set();
271
+ for (const layer of protocol) {
272
+ if (layer.sourcePath === null)
273
+ continue;
274
+ addSource(sources, seen, { id: layer.id, label: layer.label, path: layer.sourcePath, scope: layer.scope });
275
+ }
276
+ for (const source of body.sources)
277
+ addSource(sources, seen, source);
278
+ for (const source of menu.sources)
279
+ addSource(sources, seen, source);
280
+ return { layers, sources };
82
281
  }
83
- export function resolve(kind, mode, opts) {
84
- if (mode === 'base') {
85
- const persona = loadPersona(kind, 'base');
86
- if (!persona) {
87
- // No persona file for this kind — use minimal defaults.
88
- return {
89
- systemPrompt: composeProtocol(fallbackBasePrompt(kind), kind, opts.lifecycle, opts.hasManager),
90
- extensions: [],
91
- skills: [],
92
- lifecycle: opts.lifecycle,
93
- };
94
- }
95
- const fm = persona.frontmatter ?? {};
96
- return {
97
- systemPrompt: composeProtocol(persona.body || fallbackBasePrompt(kind), kind, opts.lifecycle, opts.hasManager),
98
- extensions: toStringArray(fm['extensions']),
99
- skills: toStringArray(fm['skills']),
100
- model: toOptionalString(fm['model']),
101
- lifecycle: opts.lifecycle,
102
- tools: fm['tools'] !== undefined ? toStringArray(fm['tools']) : undefined,
103
- };
282
+ function joinIncluded(layers) {
283
+ return layers.filter((layer) => layer.included && layer.text.length > 0).map((layer) => layer.text).join('\n\n');
284
+ }
285
+ function spliceRuntimeSubstrate(systemPrompt, nodeId) {
286
+ const pref = renderPreferencesSection(nodeId).trim();
287
+ const blocks = [];
288
+ const layers = [];
289
+ if (pref !== '') {
290
+ const text = pref;
291
+ blocks.push(text);
292
+ layers.push(makeLayer({
293
+ id: 'memory-preference',
294
+ label: 'Memory usage guidance + preferences',
295
+ group: 'substrate',
296
+ source: 'runtime-spliced',
297
+ sourcePath: null,
298
+ scope: 'runtime',
299
+ included: true,
300
+ condition: null,
301
+ text,
302
+ }));
104
303
  }
105
- // mode === 'orchestrator'
106
- const orchestratorPersona = loadPersona(kind, 'orchestrator');
107
- if (orchestratorPersona) {
108
- // Orchestrator file exists; @include was already inlined by the loader.
109
- const fm = orchestratorPersona.frontmatter ?? {};
110
- return {
111
- systemPrompt: composeProtocol(orchestratorPersona.body || fallbackBasePrompt(kind), kind, opts.lifecycle, opts.hasManager),
112
- extensions: toStringArray(fm['extensions']),
113
- skills: toStringArray(fm['skills']),
114
- model: toOptionalString(fm['model']),
115
- lifecycle: opts.lifecycle,
116
- tools: fm['tools'] !== undefined ? toStringArray(fm['tools']) : undefined,
117
- };
304
+ const knowledge = renderKnowledgeBlock(nodeId).trim();
305
+ if (knowledge !== '') {
306
+ layers.push(makeLayer({
307
+ id: 'memory-knowledge',
308
+ label: 'Memory (knowledge) context message, not system prompt',
309
+ group: 'substrate',
310
+ source: 'runtime-spliced',
311
+ sourcePath: null,
312
+ scope: 'runtime',
313
+ included: false,
314
+ condition: 'session_start context message, not the system prompt',
315
+ text: knowledge,
316
+ }));
118
317
  }
119
- // No orchestrator.md for this kind — compose base + bare kernel.
120
- const kernel = loadKernel();
121
- const basePersona = loadPersona(kind, 'base');
122
- const baseBody = basePersona?.body || fallbackBasePrompt(kind);
123
- const fm = basePersona?.frontmatter ?? {};
124
- // Append the kernel to the base body (with separator if kernel is non-empty).
125
- const systemPrompt = kernel ? `${baseBody}\n\n${kernel}` : baseBody;
318
+ if (blocks.length === 0)
319
+ return { prompt: systemPrompt, layers };
320
+ const insert = blocks.join('\n\n');
321
+ const anchor = '\n\nGuidelines:';
322
+ const idx = systemPrompt.indexOf(anchor);
323
+ if (idx === -1)
324
+ return { prompt: `${systemPrompt}\n\n${insert}`, layers };
325
+ return { prompt: `${systemPrompt.slice(0, idx)}\n\n${insert}${systemPrompt.slice(idx)}`, layers };
326
+ }
327
+ function collectLayers(kind, mode, opts, nodeId) {
328
+ const core = coreLayers(kind, mode, opts);
329
+ const assembledCore = joinIncluded(core.layers);
330
+ const node = nodeId !== undefined ? getNode(nodeId) : null;
331
+ const config = {
332
+ kind,
333
+ mode,
334
+ lifecycle: opts.lifecycle,
335
+ hasManager: opts.hasManager,
336
+ node: node !== null ? node.node_id : null,
337
+ };
338
+ const substrate = node !== null ? spliceRuntimeSubstrate(assembledCore, node.node_id) : { prompt: assembledCore, layers: [] };
339
+ const layers = [...core.layers, ...substrate.layers];
340
+ const sources = [];
341
+ const seen = new Set();
342
+ for (const source of core.sources)
343
+ addSource(sources, seen, source);
344
+ const included = layers.filter((layer) => layer.included).reduce((acc, layer) => ({ tokens: acc.tokens + layer.tokens, chars: acc.chars + layer.chars }), { tokens: 0, chars: 0 });
345
+ return {
346
+ config,
347
+ layers,
348
+ assembled: substrate.prompt,
349
+ total: included,
350
+ sources,
351
+ };
352
+ }
353
+ // ---------------------------------------------------------------------------
354
+ // Public API
355
+ // ---------------------------------------------------------------------------
356
+ /**
357
+ * Resolve a fully composed persona for the given `kind` and `mode`.
358
+ */
359
+ export function resolve(kind, mode, opts) {
360
+ const persona = mode === 'base' ? loadPersona(kind, 'base') : loadPersona(kind, 'orchestrator') ?? loadPersona(kind, 'base');
361
+ const fm = persona?.frontmatter ?? {};
362
+ const systemPrompt = joinIncluded(coreLayers(kind, mode, opts).layers);
126
363
  return {
127
- systemPrompt: composeProtocol(systemPrompt, kind, opts.lifecycle, opts.hasManager),
364
+ systemPrompt,
128
365
  extensions: toStringArray(fm['extensions']),
129
- skills: toStringArray(fm['skills']),
130
366
  model: toOptionalString(fm['model']),
131
367
  lifecycle: opts.lifecycle,
132
368
  tools: fm['tools'] !== undefined ? toStringArray(fm['tools']) : undefined,
133
369
  };
134
370
  }
371
+ export function resolveLayers(kind, mode, opts) {
372
+ return coreLayers(kind, mode, opts).layers;
373
+ }
374
+ export function resolvePromptReview(kind, mode, opts, nodeId) {
375
+ return collectLayers(kind, mode, opts, nodeId);
376
+ }
@@ -0,0 +1,7 @@
1
+ /** Reload a LIVE node's credentials over its view.sock. Connects as an OBSERVER
2
+ * (hello only — NO request_control, so an attached human keeps control through
3
+ * the fan; the broker's reload_auth handler is open to any client), sends
4
+ * `reload_auth`, and resolves on its ack. Rejects on the broker's `error` frame,
5
+ * connect failure, a premature close, or timeout — the caller (the daemon fan)
6
+ * isolates each broker so one failure never aborts the rest. */
7
+ export declare function reloadAuthLive(nodeId: string): Promise<void>;
@@ -0,0 +1,69 @@
1
+ // auth-reload.ts — fan a live credential reload to a node's broker over its
2
+ // view.sock, the headless sibling of the viewer's own `reload_auth` frame.
3
+ //
4
+ // Every broker reads the SAME shared `~/.pi/agent/auth.json`. When the user
5
+ // `/login`s (anywhere), the broker that performed it self-reloads — but every
6
+ // OTHER live broker keeps its stale in-memory credentials until told. The
7
+ // daemon watches auth.json's mtime and fans this RPC to each live broker so the
8
+ // whole canvas follows one account switch with no per-broker re-login.
9
+ //
10
+ // connect → hello → reload_auth → await ack. NO request_control: the broker's
11
+ // reload_auth handler is open to any client (it's an idempotent local re-read
12
+ // that doesn't steer the conversation), so the fan must NOT claim controller —
13
+ // request_control ALWAYS preempts, which would silently demote any human
14
+ // attached-and-driving a node every time /login fans canvas-wide.
15
+ import { randomUUID } from 'node:crypto';
16
+ import { ViewSocketClient } from './view-socket-client.js';
17
+ /** How long to wait for the broker's `reload_auth` ack before giving up. The
18
+ * reload is an instant local file read + registry refresh, and the daemon's
19
+ * supervision loop awaits this on a real change — so the timeout is kept tight
20
+ * to cap the worst-case stall if a broker connects but never acks. */
21
+ const ACK_TIMEOUT_MS = 3_000;
22
+ /** Reload a LIVE node's credentials over its view.sock. Connects as an OBSERVER
23
+ * (hello only — NO request_control, so an attached human keeps control through
24
+ * the fan; the broker's reload_auth handler is open to any client), sends
25
+ * `reload_auth`, and resolves on its ack. Rejects on the broker's `error` frame,
26
+ * connect failure, a premature close, or timeout — the caller (the daemon fan)
27
+ * isolates each broker so one failure never aborts the rest. */
28
+ export function reloadAuthLive(nodeId) {
29
+ return new Promise((resolve, reject) => {
30
+ const client = new ViewSocketClient(nodeId);
31
+ const clientId = randomUUID();
32
+ let settled = false;
33
+ const timer = setTimeout(() => finish(() => reject(new Error(`timed out after ${ACK_TIMEOUT_MS}ms waiting for the broker to ack the auth reload`))), ACK_TIMEOUT_MS);
34
+ if (typeof timer.unref === 'function')
35
+ timer.unref();
36
+ function finish(act) {
37
+ if (settled)
38
+ return;
39
+ settled = true;
40
+ clearTimeout(timer);
41
+ try {
42
+ client.close();
43
+ }
44
+ catch {
45
+ /* best-effort */
46
+ }
47
+ act();
48
+ }
49
+ client.on('error', (err) => finish(() => reject(err)));
50
+ client.on('close', () => finish(() => reject(new Error('broker connection closed before it acked the auth reload'))));
51
+ client.on('connect', () => {
52
+ // Hello as OBSERVER — reload_auth is open to any client, and an observer
53
+ // hello never touches controllerId, so a human driving this broker keeps
54
+ // control through the fan. (A `controller` hello also only takes control
55
+ // when none is held, which is safe; observer is the more honest signal.)
56
+ client.send({ type: 'hello', role: 'observer', client_id: clientId });
57
+ client.send({ type: 'reload_auth' });
58
+ });
59
+ client.on('frame', (frame) => {
60
+ if (frame.type === 'ack' && frame.for === 'reload_auth' && frame.ok) {
61
+ finish(() => resolve());
62
+ }
63
+ else if (frame.type === 'error') {
64
+ finish(() => reject(new Error(frame.message)));
65
+ }
66
+ });
67
+ client.connect();
68
+ });
69
+ }
@@ -1,23 +1,36 @@
1
1
  import { type WakeKind, type Wakeup } from '../canvas/index.js';
2
- /** Base framing present for every node. No path baked in: the caller carries
3
- * the dir in the `<crtr-context dir="…">` attribute. */
4
- export declare const BASE_CONTEXT_NOTE: string;
2
+ /** The `<project_context>` block for the files discovered from `cwd`, plus the
3
+ * cwd/git environment snapshot that now rides at the end of the wrapper.
4
+ * Always emits the wrapper because the environment snapshot is always present
5
+ * even when no project instructions exist. Exported for testing. */
6
+ export declare function buildProjectContextBlock(cwd: string): string;
7
+ /** The context-directory note — names the path INLINE (no XML attribute, so it
8
+ * never scopes a sibling block) and frames the dir as durable, shared scratch.
9
+ * Present for every node, rendered as the `## Your context directory`
10
+ * subsection of <crtr-bearings>. */
11
+ export declare function contextDirNote(nodeId: string): string;
5
12
  /** Orchestrator-only framing: a resident orchestrator survives refresh cycles,
6
13
  * so its context dir is also where a future cycle of itself resumes the work.
7
14
  * Used inside the bearings block AND in the promotion guidance dump, so a
8
15
  * promoted node gets the same note a born-orchestrator gets. */
9
16
  export declare function orchestratorContextNote(nodeId: string): string;
17
+ /** The graph mini-map: the ancestry trunk (root first), then this node marked
18
+ * `● you`, then its immediate children. Returns '' for a lone root with no
19
+ * children (nothing to map). Exported for testing. */
20
+ export declare function buildGraphMap(nodeId: string): string;
10
21
  /** The IDENTITY assertion that opens every boot intro — the load-bearing fix
11
22
  * for the `--fork-from` impersonation bug. A fork copies the SOURCE node's
12
23
  * entire first-person conversation into its own session, so without an explicit
13
24
  * re-assertion the forked agent reads that copied narrative as its own and
14
25
  * impersonates the source (it kept "monitoring itself" as a phantom child).
15
- * This block names the node unambiguously. ONLY when the node IS a fork does it
16
- * additionally name the source AND disown the copied first-person narrative as
17
- * inherited reference material a non-fork node's bearings are its first session
18
- * entry, so there is no earlier narrative to disown (emitting a disown line there
19
- * is dead weight that reads as a contradiction with no referent). Always the FIRST
20
- * thing the node reads. Exported for testing. */
26
+ * These lines name the node unambiguously and lead the <crtr-bearings> block
27
+ * (no wrapper of their own identity is the first prose the model reads). ONLY
28
+ * when the node IS a fork do they additionally name the source AND disown the
29
+ * copied first-person narrative as inherited reference material a non-fork
30
+ * node's bearings are its first session entry, so there is no earlier narrative
31
+ * to disown (emitting a disown line there is dead weight that reads as a
32
+ * contradiction with no referent). Also prepended to a fork's kickoff prompt in
33
+ * spawn.ts. Exported for testing. */
21
34
  export declare function buildIdentityAssertion(nodeId: string): string;
22
35
  /** Why a node woke or was born, as carried from the fired wakeup row to the
23
36
  * injection seam. `ownerName` is the armer's resolved display name when it
@@ -52,10 +65,17 @@ export declare function wakeOriginFrom(w: Wakeup): WakeOrigin;
52
65
  * agent cannot cheaply turn into an elapsed delta). Rendered for 'spawn' and
53
66
  * 'bare'; other kinds self-mark elsewhere. */
54
67
  export declare function buildWakeBearings(origin: WakeOrigin): string;
55
- /** The full boot intro: the IDENTITY assertion (always first, so it overrides
56
- * any copied-in persona) followed by the `<crtr-context>` bearings block. Base
57
- * framing rides for EVERY node; the across-cycles context-dir note is added
58
- * ONLY for an orchestrator (by mode) the one node whose dir a future cycle
59
- * resumes from. The `<knowledge>` block carries the substrate knowledge docs
60
- * + node-local docs. */
68
+ /** The full boot intro, three top-level sections:
69
+ *
70
+ * 1. `<crtr-bearings>` the orienting facts about THIS node: the identity
71
+ * assertion (always first, so it overrides any copied-in persona), then a
72
+ * `## Your place in the canvas` graph map and a `## Your context directory`
73
+ * note. The across-cycles context-dir framing is added ONLY for an
74
+ * orchestrator (by mode) — the one node whose dir a future cycle resumes
75
+ * from.
76
+ * 2. `<memory kind="knowledge">` — the consultable catalog, a SIBLING of the
77
+ * bearings (never nested under the context dir). Dropped when empty.
78
+ * 3. `<project_context>` — the AGENTS.md/CLAUDE.md instructions + the cwd/git
79
+ * environment snapshot, moved OUT of the system prompt (pi's copy is
80
+ * suppressed via noContextFiles in broker.ts) so it rides this message. */
61
81
  export declare function buildContextBearings(nodeId: string): string;