@north-light/crouter 0.3.226 → 0.3.228

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 (288) hide show
  1. package/dist/api/client.d.ts +5 -5
  2. package/dist/api/client.js +3 -3
  3. package/dist/api/dto/broker-ops.d.ts +8 -0
  4. package/dist/api/dto/memory.d.ts +8 -7
  5. package/dist/api/dto/memory.js +2 -2
  6. package/dist/builtin-memory/05-kinds/design/00-base.md +3 -4
  7. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +4 -3
  8. package/dist/builtin-memory/05-kinds/design/design-contract.md +3 -6
  9. package/dist/builtin-memory/05-kinds/plan/00-base.md +3 -4
  10. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +4 -5
  11. package/dist/builtin-memory/05-kinds/plan/plan-contract.md +5 -13
  12. package/dist/builtin-memory/design/guide.md +38 -16
  13. package/dist/builtin-memory/design/roadmap.md +4 -4
  14. package/dist/builtin-memory/insights/init.md +5 -5
  15. package/dist/builtin-memory/internal/INDEX.md +1 -1
  16. package/dist/builtin-memory/internal/examples/INDEX.md +1 -1
  17. package/dist/builtin-memory/internal/memory-loading.md +6 -6
  18. package/dist/builtin-memory/internal/plugins.md +1 -1
  19. package/dist/builtin-memory/plan/guide.md +53 -0
  20. package/dist/builtin-memory/plan/roadmap.md +10 -8
  21. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +50 -37
  22. package/dist/clients/attach/__tests__/pane-tag-successor.test.js +56 -0
  23. package/dist/clients/attach/__tests__/profile-files.test.js +21 -0
  24. package/dist/clients/attach/chrome/inbox-strip.js +11 -7
  25. package/dist/clients/attach/session/pane-tag.d.ts +28 -2
  26. package/dist/clients/attach/session/pane-tag.js +48 -22
  27. package/dist/clients/attach/session/profile-files.d.ts +6 -0
  28. package/dist/clients/attach/session/profile-files.js +44 -11
  29. package/dist/clients/attach/slash/dispatch.js +4 -7
  30. package/dist/clients/attach/viewer.js +588 -596
  31. package/dist/commands/__tests__/surface-reload-target.test.js +21 -0
  32. package/dist/commands/api-client.d.ts +3 -7
  33. package/dist/commands/api-client.js +7 -12
  34. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +292 -0
  35. package/dist/commands/memory/__tests__/repository-root-lint.test.js +146 -0
  36. package/dist/commands/memory/delete.js +51 -24
  37. package/dist/commands/memory/edit.js +50 -10
  38. package/dist/commands/memory/find.js +105 -56
  39. package/dist/commands/memory/history.js +51 -31
  40. package/dist/commands/memory/lint.d.ts +0 -9
  41. package/dist/commands/memory/lint.js +78 -322
  42. package/dist/commands/memory/list.d.ts +12 -4
  43. package/dist/commands/memory/list.js +64 -25
  44. package/dist/commands/memory/move.js +103 -73
  45. package/dist/commands/memory/origin.js +35 -5
  46. package/dist/commands/memory/read.d.ts +4 -0
  47. package/dist/commands/memory/read.js +132 -80
  48. package/dist/commands/memory/shared.d.ts +115 -25
  49. package/dist/commands/memory/shared.js +331 -74
  50. package/dist/commands/memory/write.js +72 -21
  51. package/dist/commands/memory.js +2 -2
  52. package/dist/commands/node/lifecycle.js +2 -2
  53. package/dist/commands/pkg/market-manage.js +25 -24
  54. package/dist/commands/pkg/plugin-manage.d.ts +22 -6
  55. package/dist/commands/pkg/plugin-manage.js +118 -25
  56. package/dist/commands/pkg/shared.d.ts +8 -0
  57. package/dist/commands/pkg/shared.js +23 -20
  58. package/dist/commands/surface-reload.d.ts +5 -0
  59. package/dist/commands/surface-reload.js +9 -1
  60. package/dist/commands/sys/__tests__/migrate.test.js +1140 -22
  61. package/dist/commands/sys/__tests__/sync-project-guidance.test.js +218 -0
  62. package/dist/commands/sys/migrate.js +126 -140
  63. package/dist/commands/sys/panels/profiles-panel.d.ts +66 -0
  64. package/dist/commands/sys/panels/profiles-panel.js +599 -0
  65. package/dist/commands/sys/settings-shell.d.ts +4 -2
  66. package/dist/commands/sys/settings-shell.js +35 -4
  67. package/dist/commands/sys/settings.js +21 -5
  68. package/dist/commands/sys/sync-deps.d.ts +2 -0
  69. package/dist/commands/sys/sync-deps.js +26 -15
  70. package/dist/commands/sys/sync-project-guidance.js +228 -145
  71. package/dist/commands/sys/sync-skills.js +28 -17
  72. package/dist/commands/sys/update.js +11 -3
  73. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +15 -2
  74. package/dist/core/__tests__/config-change-delta.test.js +106 -0
  75. package/dist/core/__tests__/context-intro.test.js +13 -9
  76. package/dist/core/__tests__/daemon-boot.test.js +22 -16
  77. package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +5 -1
  78. package/dist/core/__tests__/human-deliver.test.js +19 -0
  79. package/dist/core/__tests__/inline-memory-refs.test.js +50 -46
  80. package/dist/core/__tests__/{serial → integration}/broker-fork-seam.test.js +1 -1
  81. package/dist/core/__tests__/{serial → integration}/broker-sdk-wiring.test.js +1 -1
  82. package/dist/core/__tests__/{serial → integration}/broker-snapshot-history.test.js +1 -1
  83. package/dist/core/__tests__/{serial → integration}/command-plugins.test.js +94 -3
  84. package/dist/core/__tests__/{serial → integration}/deferred-no-wake.test.js +1 -1
  85. package/dist/core/__tests__/{serial → integration}/flagship-lifecycle.test.js +13 -27
  86. package/dist/core/__tests__/{serial → integration}/host-teardown-process-group.test.js +1 -1
  87. package/dist/core/__tests__/{serial → integration}/human-deliver-e2e.test.js +1 -1
  88. package/dist/core/__tests__/{live-mutation-verbs.test.js → integration/live-mutation-verbs.test.js} +22 -33
  89. package/dist/core/__tests__/{serial → integration}/live-mutation.test.js +21 -41
  90. package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +1 -0
  91. package/dist/core/__tests__/{serial → integration}/refresh-stall-recycle.test.js +1 -1
  92. package/dist/core/__tests__/integration/revive.test.d.ts +1 -0
  93. package/dist/core/__tests__/{serial → integration}/revive.test.js +38 -19
  94. package/dist/core/__tests__/integration/spawn-root.test.d.ts +1 -0
  95. package/dist/core/__tests__/{serial → integration}/spawn-root.test.js +104 -1
  96. package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +1 -0
  97. package/dist/core/__tests__/{serial → integration}/subscription-delivery.test.js +1 -1
  98. package/dist/core/__tests__/integration/tmux-surface.test.d.ts +1 -0
  99. package/dist/core/__tests__/{serial → integration}/tmux-surface.test.js +1 -1
  100. package/dist/core/__tests__/integration/worktree-land.test.d.ts +1 -0
  101. package/dist/core/__tests__/integration/worktree-land.test.js +400 -0
  102. package/dist/core/__tests__/integration/worktree-reap.test.d.ts +1 -0
  103. package/dist/core/__tests__/{serial/worktree.test.js → integration/worktree-reap.test.js} +6 -338
  104. package/dist/core/__tests__/kickoff.test.js +16 -5
  105. package/dist/core/__tests__/memory-resolver-precedence.test.js +122 -91
  106. package/dist/core/__tests__/nested-store-discovery.test.js +5 -3
  107. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
  108. package/dist/core/__tests__/on-read-dedup-resume.test.js +39 -27
  109. package/dist/core/__tests__/on-read-nested-store.test.js +19 -13
  110. package/dist/core/__tests__/profile-project-memory-delivery.test.js +138 -44
  111. package/dist/core/__tests__/repository-association.test.d.ts +1 -0
  112. package/dist/core/__tests__/repository-association.test.js +153 -0
  113. package/dist/core/__tests__/repository-root-identity.test.d.ts +1 -0
  114. package/dist/core/__tests__/repository-root-identity.test.js +219 -0
  115. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +27 -11
  116. package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +1 -0
  117. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +40 -0
  118. package/dist/core/canvas/canvas.d.ts +3 -0
  119. package/dist/core/canvas/canvas.js +30 -10
  120. package/dist/core/canvas/db.js +28 -1
  121. package/dist/core/canvas/paths.d.ts +4 -6
  122. package/dist/core/canvas/paths.js +8 -6
  123. package/dist/core/canvas/render-source.js +2 -2
  124. package/dist/core/canvas/types.d.ts +9 -13
  125. package/dist/core/exclusive-lock.d.ts +2 -0
  126. package/dist/core/exclusive-lock.js +21 -0
  127. package/dist/core/git.d.ts +0 -1
  128. package/dist/core/git.js +0 -3
  129. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +1 -0
  130. package/dist/core/human/feedback-companion.js +3 -0
  131. package/dist/core/human/scan.js +8 -1
  132. package/dist/core/keybindings/catalog.d.ts +2 -2
  133. package/dist/core/keybindings/catalog.js +2 -1
  134. package/dist/core/memory/doc-link-grammar.js +2 -2
  135. package/dist/core/memory/history.d.ts +24 -0
  136. package/dist/core/memory/history.js +66 -1
  137. package/dist/core/memory/identity.d.ts +65 -0
  138. package/dist/core/memory/identity.js +185 -0
  139. package/dist/core/memory/inline-ref-guidance.d.ts +1 -1
  140. package/dist/core/memory/inline-ref-guidance.js +1 -1
  141. package/dist/core/memory/inline-ref-inventory.d.ts +3 -10
  142. package/dist/core/memory/inline-ref-inventory.js +30 -62
  143. package/dist/core/memory/lint.d.ts +129 -0
  144. package/dist/core/memory/lint.js +517 -0
  145. package/dist/core/memory/project-namespace.d.ts +31 -0
  146. package/dist/core/memory/project-namespace.js +85 -0
  147. package/dist/core/memory/repository-association.d.ts +31 -0
  148. package/dist/core/memory/repository-association.js +129 -0
  149. package/dist/core/memory/tree.d.ts +39 -0
  150. package/dist/core/memory/tree.js +93 -0
  151. package/dist/core/memory-resolver.d.ts +193 -90
  152. package/dist/core/memory-resolver.js +461 -375
  153. package/dist/core/nested-stores.js +6 -13
  154. package/dist/core/profiles/select.d.ts +4 -1
  155. package/dist/core/profiles/select.js +108 -48
  156. package/dist/core/review/__tests__/capture-origin.test.js +2 -2
  157. package/dist/core/review/__tests__/stage-identity.test.js +2 -2
  158. package/dist/core/review/companion.js +11 -2
  159. package/dist/core/runtime/bearings.d.ts +2 -2
  160. package/dist/core/runtime/bearings.js +3 -3
  161. package/dist/core/runtime/broker/daemon-ops.d.ts +2 -2
  162. package/dist/core/runtime/broker/rebind.js +5 -0
  163. package/dist/core/runtime/broker-extension-render.d.ts +7 -3
  164. package/dist/core/runtime/broker-extension-render.js +10 -5
  165. package/dist/core/runtime/broker-persona-guidance.d.ts +19 -5
  166. package/dist/core/runtime/broker-persona-guidance.js +122 -27
  167. package/dist/core/runtime/deliver-live.d.ts +16 -4
  168. package/dist/core/runtime/deliver-live.js +29 -15
  169. package/dist/core/runtime/kickoff.d.ts +3 -3
  170. package/dist/core/runtime/kickoff.js +8 -16
  171. package/dist/core/runtime/lifecycle.js +2 -3
  172. package/dist/core/runtime/nodes.d.ts +3 -4
  173. package/dist/core/runtime/nodes.js +3 -4
  174. package/dist/core/runtime/persona.d.ts +8 -12
  175. package/dist/core/runtime/persona.js +24 -96
  176. package/dist/core/runtime/promote.d.ts +2 -2
  177. package/dist/core/runtime/promote.js +8 -21
  178. package/dist/core/runtime/revive.js +20 -17
  179. package/dist/core/runtime/spawn.js +18 -7
  180. package/dist/core/runtime/tmux-bindings.js +2 -3
  181. package/dist/core/runtime/warm-pool.js +3 -4
  182. package/dist/core/scope.js +2 -0
  183. package/dist/core/self-update.d.ts +0 -2
  184. package/dist/core/self-update.js +2 -35
  185. package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +1 -0
  186. package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +28 -0
  187. package/dist/core/substrate/index.d.ts +2 -2
  188. package/dist/core/substrate/index.js +1 -1
  189. package/dist/core/substrate/injected-store.d.ts +43 -27
  190. package/dist/core/substrate/injected-store.js +208 -104
  191. package/dist/core/substrate/listings.d.ts +19 -12
  192. package/dist/core/substrate/listings.js +75 -52
  193. package/dist/core/substrate/on-read-node.d.ts +4 -7
  194. package/dist/core/substrate/on-read-node.js +6 -8
  195. package/dist/core/substrate/on-read.d.ts +22 -25
  196. package/dist/core/substrate/on-read.js +103 -147
  197. package/dist/core/substrate/render-node.d.ts +4 -7
  198. package/dist/core/substrate/render-node.js +5 -7
  199. package/dist/core/substrate/render.d.ts +21 -3
  200. package/dist/core/substrate/render.js +291 -223
  201. package/dist/core/substrate/schema.d.ts +1 -13
  202. package/dist/core/substrate/schema.js +5 -40
  203. package/dist/core/substrate/session-cache.d.ts +14 -4
  204. package/dist/core/substrate/session-cache.js +40 -22
  205. package/dist/core/substrate/surface-match.d.ts +9 -7
  206. package/dist/core/substrate/surface-match.js +26 -25
  207. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +30 -0
  208. package/dist/daemon/__tests__/helpers/source-daemon.js +174 -0
  209. package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +1 -0
  210. package/dist/daemon/__tests__/integration/migration-startup.test.js +97 -0
  211. package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +37 -9
  212. package/dist/daemon/api/bridge.d.ts +35 -4
  213. package/dist/daemon/api/bridge.js +50 -8
  214. package/dist/daemon/api/handlers/broker-ops.js +21 -16
  215. package/dist/daemon/api/handlers/memory.js +2 -0
  216. package/dist/daemon/crtrd.js +2 -0
  217. package/dist/daemon/human/finish.js +8 -1
  218. package/dist/daemon/manage.d.ts +0 -1
  219. package/dist/daemon/manage.js +7 -16
  220. package/dist/daemon/startup-policy.d.ts +1 -0
  221. package/dist/daemon/startup-policy.js +1 -0
  222. package/dist/migrations/001-surfaces-frontmatter.js +21 -109
  223. package/dist/migrations/002-profile-project-memory.js +1 -0
  224. package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +26 -0
  225. package/dist/migrations/003-repository-root-memory-identity/front-door.js +231 -0
  226. package/dist/migrations/003-repository-root-memory-identity/index.d.ts +2 -0
  227. package/dist/migrations/003-repository-root-memory-identity/index.js +513 -0
  228. package/dist/migrations/003-repository-root-memory-identity/references.d.ts +95 -0
  229. package/dist/migrations/003-repository-root-memory-identity/references.js +469 -0
  230. package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +39 -0
  231. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +349 -0
  232. package/dist/migrations/__tests__/activation-concurrency.test.d.ts +1 -0
  233. package/dist/migrations/__tests__/activation-concurrency.test.js +145 -0
  234. package/dist/migrations/__tests__/activation.test.d.ts +1 -0
  235. package/dist/migrations/__tests__/activation.test.js +149 -0
  236. package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +1 -0
  237. package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +149 -0
  238. package/dist/migrations/activation.d.ts +16 -0
  239. package/dist/migrations/activation.js +78 -0
  240. package/dist/migrations/convergent.d.ts +14 -3
  241. package/dist/migrations/convergent.js +21 -10
  242. package/dist/migrations/corpus.d.ts +78 -0
  243. package/dist/migrations/corpus.js +497 -0
  244. package/dist/migrations/frontmatter-splice.d.ts +15 -0
  245. package/dist/migrations/frontmatter-splice.js +176 -0
  246. package/dist/migrations/registry.d.ts +6 -1
  247. package/dist/migrations/registry.js +7 -2
  248. package/dist/migrations/runner.d.ts +41 -0
  249. package/dist/migrations/runner.js +81 -0
  250. package/dist/migrations/types.d.ts +148 -9
  251. package/dist/migrations/types.js +9 -2
  252. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +225 -17
  253. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +11 -3
  254. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -5
  255. package/dist/pi-extensions/canvas-context-intro.js +50 -46
  256. package/dist/pi-extensions/canvas-doc-substrate.d.ts +1 -8
  257. package/dist/pi-extensions/canvas-doc-substrate.js +55 -122
  258. package/dist/pi-extensions/canvas-stophook.js +6 -13
  259. package/dist/shared/generated-context.d.ts +0 -3
  260. package/dist/shared/generated-context.js +0 -57
  261. package/dist/shared/tool-groups.js +2 -3
  262. package/package.json +5 -4
  263. package/runtime.lock.json +2 -2
  264. /package/dist/api/__tests__/{serial → integration}/client.test.d.ts +0 -0
  265. /package/dist/api/__tests__/{serial → integration}/client.test.js +0 -0
  266. /package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{serial → integration}/provider-rotation.test.ts +0 -0
  267. /package/dist/clients/{inbox/__tests__/serial/inbox-controller.test.d.ts → attach/__tests__/pane-tag-successor.test.d.ts} +0 -0
  268. /package/dist/clients/{inbox/__tests__/serial/mount-panel.test.d.ts → attach/__tests__/profile-files.test.d.ts} +0 -0
  269. /package/dist/{core/__tests__/live-mutation-verbs.test.d.ts → clients/inbox/__tests__/integration/inbox-controller.test.d.ts} +0 -0
  270. /package/dist/clients/inbox/__tests__/{serial → integration}/inbox-controller.test.js +0 -0
  271. /package/dist/{core/__tests__/serial/broker-fork-seam.test.d.ts → clients/inbox/__tests__/integration/mount-panel.test.d.ts} +0 -0
  272. /package/dist/clients/inbox/__tests__/{serial → integration}/mount-panel.test.js +0 -0
  273. /package/dist/{core/__tests__/serial/broker-sdk-wiring.test.d.ts → commands/__tests__/surface-reload-target.test.d.ts} +0 -0
  274. /package/dist/{core/__tests__/serial/broker-snapshot-history.test.d.ts → commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts} +0 -0
  275. /package/dist/{core/__tests__/serial/command-plugins.test.d.ts → commands/memory/__tests__/repository-root-lint.test.d.ts} +0 -0
  276. /package/dist/{core/__tests__/serial/deferred-no-wake.test.d.ts → commands/sys/__tests__/sync-project-guidance.test.d.ts} +0 -0
  277. /package/dist/core/__tests__/{serial/flagship-lifecycle.test.d.ts → config-change-delta.test.d.ts} +0 -0
  278. /package/dist/core/__tests__/{serial/host-teardown-process-group.test.d.ts → integration/broker-fork-seam.test.d.ts} +0 -0
  279. /package/dist/core/__tests__/{serial/human-deliver-e2e.test.d.ts → integration/broker-sdk-wiring.test.d.ts} +0 -0
  280. /package/dist/core/__tests__/{serial/live-mutation.test.d.ts → integration/broker-snapshot-history.test.d.ts} +0 -0
  281. /package/dist/core/__tests__/{serial/refresh-stall-recycle.test.d.ts → integration/command-plugins.test.d.ts} +0 -0
  282. /package/dist/core/__tests__/{serial/revive.test.d.ts → integration/deferred-no-wake.test.d.ts} +0 -0
  283. /package/dist/core/__tests__/{serial/spawn-root.test.d.ts → integration/flagship-lifecycle.test.d.ts} +0 -0
  284. /package/dist/core/__tests__/{serial/subscription-delivery.test.d.ts → integration/host-teardown-process-group.test.d.ts} +0 -0
  285. /package/dist/core/__tests__/{serial/tmux-surface.test.d.ts → integration/human-deliver-e2e.test.d.ts} +0 -0
  286. /package/dist/core/__tests__/{serial/worktree.test.d.ts → integration/live-mutation-verbs.test.d.ts} +0 -0
  287. /package/dist/core/{human/__tests__/serial/inbox-core.test.d.ts → __tests__/integration/live-mutation.test.d.ts} +0 -0
  288. /package/dist/core/human/__tests__/{serial → integration}/inbox-core.test.js +0 -0
@@ -12,6 +12,7 @@ import { KeybindingsPanel } from "./panels/keybindings-panel.js";
12
12
  import { ModelsPanel } from "./panels/models-panel.js";
13
13
  import { PAGE_CHROME_ROWS, columns, padAnsi, pageFrame, theme, } from "../../core/tui/panel.js";
14
14
  import { PrefsPanel } from "./panels/prefs-panel.js";
15
+ import { ProfilesPanel } from "./panels/profiles-panel.js";
15
16
  import { ProviderPanel } from "./panels/provider-panel.js";
16
17
  /** Rail column width, including its badge gutter. */
17
18
  const RAIL_WIDTH = 22;
@@ -26,6 +27,7 @@ export class SettingsShell {
26
27
  models;
27
28
  keybindings;
28
29
  brokerLimits;
30
+ profiles;
29
31
  destinations;
30
32
  index = 0;
31
33
  /** The rail owns the arrow keys until you step into a panel. */
@@ -35,7 +37,7 @@ export class SettingsShell {
35
37
  cachedHeight;
36
38
  cachedLines;
37
39
  onCancel;
38
- constructor(tui, agentDir, runtime, registry, bindings, rawKeybindings, terminalRows, rawTmuxPassthrough = undefined) {
40
+ constructor(tui, agentDir, runtime, registry, bindings, rawKeybindings, terminalRows, rawTmuxPassthrough = undefined, initial) {
39
41
  this.tui = tui;
40
42
  this.bindings = bindings;
41
43
  this.terminalRows = terminalRows;
@@ -46,6 +48,10 @@ export class SettingsShell {
46
48
  this.models.onChange = invalidate;
47
49
  this.keybindings = new KeybindingsPanel(bindings, rawKeybindings, rawTmuxPassthrough, terminalRows, invalidate);
48
50
  this.brokerLimits = new BrokerLimitsPanel(invalidate);
51
+ // Profile purview and pins read against the directory the page was opened
52
+ // in — the same directory the startup menu was deciding for when `v` brought
53
+ // the user here.
54
+ this.profiles = new ProfilesPanel(process.cwd(), invalidate);
49
55
  const prefs = (group, title, subtitle) => new PrefsPanel(group, title, subtitle, invalidate);
50
56
  this.destinations = [
51
57
  {
@@ -72,6 +78,12 @@ export class SettingsShell {
72
78
  label: "Display",
73
79
  panel: prefs("display", "Display", "How an attached viewer renders a conversation."),
74
80
  },
81
+ {
82
+ id: "profiles",
83
+ group: "Workspace",
84
+ label: "Profiles",
85
+ panel: this.profiles,
86
+ },
75
87
  {
76
88
  id: "panes",
77
89
  group: "Workspace",
@@ -91,6 +103,16 @@ export class SettingsShell {
91
103
  panel: prefs("updates", "Updates", "How crouter checks for and applies new releases."),
92
104
  },
93
105
  ];
106
+ // A deep link lands ON its destination with the rail already stepped out of:
107
+ // the caller named where they wanted to be, not where to start navigating
108
+ // from.
109
+ if (initial !== undefined) {
110
+ const at = this.destinations.findIndex((destination) => destination.id === initial);
111
+ if (at >= 0) {
112
+ this.index = at;
113
+ this.railFocused = false;
114
+ }
115
+ }
94
116
  }
95
117
  // --- focus and navigation -------------------------------------------------
96
118
  set focused(value) {
@@ -155,6 +177,8 @@ export class SettingsShell {
155
177
  return this.models.isPickerOpen();
156
178
  case "keybindings":
157
179
  return this.keybindings.takesPriorityInput;
180
+ case "profiles":
181
+ return this.profiles.ownsInput(data);
158
182
  case "broker-limits":
159
183
  // Threshold fields take digits; a remapped destination gesture must
160
184
  // never swallow a number the user is typing into a limit.
@@ -280,9 +304,14 @@ export class SettingsShell {
280
304
  footer(width) {
281
305
  const right = `${this.label("crtr.setup.tab-next")}/${this.label("crtr.setup.tab-previous")} destination \u00b7 ${this.label("crtr.setup.cancel")} close`;
282
306
  const move = `${this.label("crtr.setup.list-down")}/${this.label("crtr.setup.list-up")} move \u00b7 ${this.label("crtr.setup.advance")} open`;
307
+ // A panel that has claimed Escape for its own "back" step must not also be
308
+ // advertised as the way out to the rail — one key, one meaning per screen.
309
+ const escapes = !this.panelOwnsKeyboard("\u001b");
283
310
  const candidates = this.railFocused
284
311
  ? [`${move} \u00b7 type a letter to jump`, move]
285
- : [`${this.panelHint()} \u00b7 esc rail`, this.panelHint()];
312
+ : escapes
313
+ ? [`${this.panelHint()} \u00b7 esc rail`, this.panelHint()]
314
+ : [this.panelHint()];
286
315
  for (const left of candidates) {
287
316
  const gap = width - visibleWidth(left) - visibleWidth(right);
288
317
  if (gap >= 2)
@@ -305,6 +334,8 @@ export class SettingsShell {
305
334
  return this.keybindings.footerHint();
306
335
  case "broker-limits":
307
336
  return `${move} field \u00b7 type a value \u00b7 ${this.label("crtr.setup.advance")} save`;
337
+ case "profiles":
338
+ return this.profiles.footerHint();
308
339
  default:
309
340
  return `${move} row \u00b7 ${this.label("crtr.setup.toggle")} or ${this.label("crtr.setup.cell-previous")}/${this.label("crtr.setup.cell-next")} change value`;
310
341
  }
@@ -349,14 +380,14 @@ export class SettingsShell {
349
380
  return lines;
350
381
  }
351
382
  }
352
- export async function runSettings() {
383
+ export async function runSettings(initial) {
353
384
  await reconcileInboxFrontDoor();
354
385
  if (!process.stdout.isTTY) {
355
386
  process.stdout.write("crtr sys settings needs a TTY. Run it in a terminal, or use `crtr sys config get|set` for scriptable access.\n");
356
387
  return;
357
388
  }
358
389
  await runSetupSettingsProcess(({ tui, terminal, agentDir, runtime, registry, bindings, rawUserConfig }, control) => {
359
- const shell = new SettingsShell(tui, agentDir, runtime, registry, bindings, rawUserConfig?.keybindings, () => terminal.rows, rawUserConfig?.tmux_passthrough);
390
+ const shell = new SettingsShell(tui, agentDir, runtime, registry, bindings, rawUserConfig?.keybindings, () => terminal.rows, rawUserConfig?.tmux_passthrough, initial);
360
391
  shell.onCancel = control.cancel;
361
392
  return shell;
362
393
  });
@@ -6,25 +6,41 @@
6
6
  // be reachable by a static import from here.
7
7
  import { defineLeaf } from '../../core/command.js';
8
8
  import { BROKER_LIMIT_OVERRIDE_PRECEDENCE } from './setup.js';
9
+ /** Rail destinations, in rail order. Kept here rather than imported from the
10
+ * shell so registering the `sys` subtree still costs no pi module graph. */
11
+ const PAGES = [
12
+ 'providers', 'models', 'keybindings', 'display', 'profiles', 'panes', 'broker-limits', 'updates',
13
+ ];
9
14
  export const sysSettingsLeaf = defineLeaf({
10
15
  name: 'settings',
11
- description: 'open the settings page — providers, models, keybindings, display, panes, broker limits, updates',
16
+ description: 'open the settings page — providers, models, keybindings, display, profiles, panes, broker limits, updates',
12
17
  whenToUse: 'the user wants to change crouter configuration interactively. Agents should use sys config get/set, which is scriptable; sys setup installs a fresh machine.',
13
18
  help: {
14
19
  name: 'sys settings',
15
20
  summary: 'open the interactive settings page for an already-installed crouter',
16
- inputNote: 'No input parameters.',
21
+ params: [
22
+ {
23
+ kind: 'flag',
24
+ name: 'page',
25
+ type: 'enum',
26
+ choices: [...PAGES],
27
+ required: false,
28
+ constraint: 'Open directly on one rail destination instead of the first. Omit to start on the rail.',
29
+ },
30
+ ],
17
31
  output: [],
18
32
  outputKind: 'object',
19
33
  effects: [
20
- 'Opens a pi-tui page whose left rail groups ongoing configuration: Intelligence (providers, models), Interface (keybindings, display), and Workspace (panes, broker limits, updates).',
34
+ 'Opens a pi-tui page whose left rail groups ongoing configuration: Intelligence (providers, models), Interface (keybindings, display), and Workspace (profiles, panes, broker limits, updates).',
35
+ 'Profiles edits are immediate: adding or removing a project directory, cycling its memory rung, setting a home, renaming, pausing and pinning a directory default all write the same profile manifests and pin file as the `crtr profile` leaves; deleting a profile runs the same cascade as `crtr profile delete --force`.',
21
36
  'Preference, model-ladder and keybinding edits save to the user config as you make them; saved keybinding changes also refresh crouter-owned tmux bindings without overwriting occupied user keys.',
22
37
  `Broker warning and automatic-revive hard-cap values save under user config brokerThresholds; crtrd reads them on its next supervision tick. ${BROKER_LIMIT_OVERRIDE_PRECEDENCE}`,
23
38
  'Requires a TTY. Without one it prints a pointer to sys config and exits.',
24
39
  ],
25
40
  },
26
- run: async () => {
27
- await (await import('./settings-shell.js')).runSettings();
41
+ run: async (input) => {
42
+ const page = input['page'];
43
+ await (await import('./settings-shell.js')).runSettings(page);
28
44
  },
29
45
  render: () => '',
30
46
  });
@@ -6,6 +6,8 @@ export declare const DEPS_GENERATED_MARKER = "crtr sys sync deps";
6
6
  interface DepsRow {
7
7
  source: string;
8
8
  target: string;
9
+ /** Full canonical name the vendored doc answers at (`<namespace>/deps/...`),
10
+ * except on an `excluded` row, which names the excluded package selector. */
9
11
  name: string;
10
12
  scope: 'project';
11
13
  status: 'imported' | 'would-import' | 'skipped' | 'excluded';
@@ -12,25 +12,31 @@
12
12
  // deps/ dir is never destroyed. A self-ignoring `.gitignore` keeps the
13
13
  // whole dir out of git.
14
14
  // • Each SKILL.md becomes its bundle dir's INDEX doc
15
- // (deps/<bundle>/INDEX.md): `crtr memory read deps/<bundle>` resolves it
16
- // via the bare-dir → INDEX contract, AND the bundle's relative sidecar
15
+ // (deps/<bundle>/INDEX.md), the document attached to that directory: it
16
+ // answers at `<namespace>/deps/<bundle>`, AND the bundle's relative sidecar
17
17
  // links (./references/x.md, ./docs/y.md) keep resolving on disk because
18
18
  // the bundle's file layout is preserved. Sidecar .md files get minimal
19
19
  // substrate frontmatter injected (lint-clean, system name/file none); other
20
20
  // files copy verbatim.
21
+ // • Physical layout is store-local (`deps/**` under the project's memory
22
+ // dir); every name the lane reports, links, or tells an agent to read is
23
+ // the full canonical name, composed with the store's declared namespace.
24
+ // The store must already declare one — this lane vendors documents into a
25
+ // project store, never the declaration that gives them their identity.
21
26
  // • Vendored bundle and sidecar docs sit at system name/file none, so the boot
22
27
  // catalog exposes their resolvable identities without loading their bodies.
23
28
  // The ONE generated top deps/INDEX.md sits at system preview/file none and
24
29
  // carries the routing catalog. The catalog is one read away, each vendored
25
30
  // doc another.
26
31
  import { copyFileSync, mkdirSync, readdirSync, rmSync } from 'node:fs';
27
- import { CRTR_DIR_NAME } from '../../types.js';
28
32
  import { basename, dirname, join, relative, resolve, sep } from 'node:path';
29
33
  import { defineLeaf } from '../../core/command.js';
30
34
  import { usage } from '../../core/errors.js';
31
35
  import { parseFrontmatterGeneric } from '../../core/frontmatter.js';
32
36
  import { pathExists, readJsonIfExists, readText, walkFiles, writeText } from '../../core/fs-utils.js';
33
- import { serializeMemoryDoc } from '../memory/shared.js';
37
+ import { composeCanonicalName } from '../../core/memory/identity.js';
38
+ import { openProjectMemoryStore } from '../../core/memory-resolver.js';
39
+ import { requireMountedStore, serializeMemoryDoc } from '../memory/shared.js';
34
40
  import { routeFromDescription, scalarString } from './sync-shared.js';
35
41
  import { isRecord } from '../../shared/predicates.js';
36
42
  /** Marker value written to the generated top INDEX's `generated-by` field —
@@ -207,7 +213,11 @@ export function runDepsSync(opts) {
207
213
  if (!pathExists(nodeModules)) {
208
214
  throw usage(`sys sync deps: ${nodeModules} does not exist; install dependencies first (npm ci / npm install), then re-run`);
209
215
  }
210
- const depsDir = join(projectRoot, CRTR_DIR_NAME, 'memory', 'deps');
216
+ // Identity before any planning: the store's declared namespace is what every
217
+ // reported row, catalog link, and read instruction composes under.
218
+ const store = requireMountedStore(openProjectMemoryStore(projectRoot));
219
+ const depsDir = join(store.storeRoot, 'deps');
220
+ const depsName = composeCanonicalName(store.namespace, 'deps');
211
221
  const exclusions = readDepsExclusions(projectRoot);
212
222
  const exclusionSet = new Set(exclusions.map((e) => exclusionKey(e.package, e.version, e.skill)));
213
223
  const selectorMatches = new Map(exclusions.map((e) => [exclusionKey(e.package, e.version, e.skill), 0]));
@@ -301,7 +311,7 @@ export function runDepsSync(opts) {
301
311
  rows.push({
302
312
  source: file,
303
313
  target: join(depsDir, ...targetRel.split('/')),
304
- name: `deps/${dirname(targetRel)}`,
314
+ name: `${depsName}/${dirname(targetRel)}`,
305
315
  scope: 'project',
306
316
  status: 'skipped',
307
317
  reason: `collides with same-named bundle from ${existing.pkg}`,
@@ -330,7 +340,7 @@ export function runDepsSync(opts) {
330
340
  rows.push({
331
341
  source: skill.sourceAbs,
332
342
  target: join(depsDir, ...targetRel.split('/')),
333
- name: `deps/${skill.bundleRel}`,
343
+ name: `${depsName}/${skill.bundleRel}`,
334
344
  scope: 'project',
335
345
  status,
336
346
  ...(n > 0 ? { reason: `+${n} sidecar file${n === 1 ? '' : 's'}` } : {}),
@@ -339,7 +349,7 @@ export function runDepsSync(opts) {
339
349
  rows.push({
340
350
  source: nodeModules,
341
351
  target: join(depsDir, 'INDEX.md'),
342
- name: 'deps',
352
+ name: depsName,
343
353
  scope: 'project',
344
354
  status,
345
355
  reason: `generated catalog of ${skills.length} docs from ${catalogPackages.size} package${catalogPackages.size === 1 ? '' : 's'}`,
@@ -383,7 +393,7 @@ export function runDepsSync(opts) {
383
393
  body = readText(entry.sourceAbs);
384
394
  }
385
395
  const parentBundle = bundleDirs.find((d) => targetRel.startsWith(`${d}/`));
386
- const parentName = parentBundle ? `deps/${parentBundle}` : 'a deps/ document';
396
+ const parentName = parentBundle ? `${depsName}/${parentBundle}` : `a ${depsName} document`;
387
397
  const fm = {
388
398
  kind: 'knowledge',
389
399
  'when-and-why-to-read': `When ${parentName} links to this file, this knowledge should be read because it carries the linked supporting reference.`,
@@ -407,7 +417,7 @@ export function runDepsSync(opts) {
407
417
  const key = `${skill.pkg}@${skill.version}`;
408
418
  const bucket = byPackage.get(key) ?? { version: skill.version, lines: [] };
409
419
  const desc = skill.description !== '' ? ` — ${condenseDescription(skill.description, 180)}` : '';
410
- bucket.lines.push(`- \`deps/${skill.bundleRel}\`${desc}`);
420
+ bucket.lines.push(`- \`${depsName}/${skill.bundleRel}\`${desc}`);
411
421
  byPackage.set(key, bucket);
412
422
  }
413
423
  const sections = [...byPackage.entries()]
@@ -420,7 +430,7 @@ export function runDepsSync(opts) {
420
430
  ? 'When deciding whether dependency-shipped agent docs are available in this project, this catalog should be read because no dependency guides are currently vendored.'
421
431
  : `When writing code against this project's dependencies (${shownLibs}), this catalog should be read ` +
422
432
  'because those packages ship their own authoritative agent guides, vendored below and readable with ' +
423
- '`crtr memory read deps/<name>`.',
433
+ `\`crtr memory read ${depsName}/<name>\`.`,
424
434
  'short-form': emptyCatalog
425
435
  ? 'No dependency-shipped agent docs are currently vendored.'
426
436
  : "Generated catalog of the agent docs shipped inside this project's npm dependencies.",
@@ -432,7 +442,7 @@ export function runDepsSync(opts) {
432
442
  : '# Dependency-shipped agent docs (generated)\n\n' +
433
443
  'Generated by `crtr sys sync deps` from the Agent Skill bundles inside this project\'s ' +
434
444
  'node_modules. Do not hand-edit: the whole `deps/` directory is wiped and regenerated on every run — ' +
435
- 're-run after dependencies change. Read any entry with `crtr memory read deps/<name>`.\n\n' +
445
+ `re-run after dependencies change. Read any entry with \`crtr memory read ${depsName}/<name>\`.\n\n` +
436
446
  sections;
437
447
  writeText(join(depsDir, 'INDEX.md'), serializeMemoryDoc(indexFm, indexBody));
438
448
  // Derived state never enters git: the dir ignores itself.
@@ -467,7 +477,7 @@ export const sysSyncDepsLeaf = defineLeaf({
467
477
  name: 'sys sync deps',
468
478
  summary: 'vendor npm-dependency Agent Skill bundles into <project>/.crouter/memory/deps/ (wholly derived, regenerated every run)',
469
479
  params: [
470
- { kind: 'flag', name: 'source', type: 'string', required: false, constraint: 'The project directory whose dependencies to vendor. Default: the nearest ancestor of cwd with a package.json. node_modules must already be installed there.' },
480
+ { kind: 'flag', name: 'source', type: 'string', required: false, constraint: 'The project directory whose dependencies to vendor. Default: the nearest ancestor of cwd with a package.json. node_modules must already be installed there, and its repository-root `.crouter/memory/INDEX.md` must declare a `namespace:`.' },
471
481
  { kind: 'flag', name: 'dry-run', type: 'bool', required: false, constraint: 'Report what would be vendored without writing anything.' },
472
482
  ],
473
483
  output: [
@@ -475,11 +485,12 @@ export const sysSyncDepsLeaf = defineLeaf({
475
485
  { name: 'wouldImport', type: 'number', required: true, constraint: 'Count of memory docs that would be written under --dry-run.' },
476
486
  { name: 'skipped', type: 'number', required: true, constraint: 'Count of same-named bundle collisions skipped (first-sorted package wins).' },
477
487
  { name: 'excluded', type: 'number', required: true, constraint: 'Count of dependency skill bundles excluded by exact package.json crtr.sync.deps.exclude selectors.' },
478
- { name: 'results', type: 'object[]', required: true, constraint: 'Each: {source,target,name,scope,status,reason?}; status is one of imported, would-import, skipped, excluded. An excluded row is a dependency bundle rejected before its files enter the vendoring planner.' },
488
+ { name: 'results', type: 'object[]', required: true, constraint: 'Each: {source,target,name,scope,status,reason?}; status is one of imported, would-import, skipped, excluded. `name` is the full canonical name the vendored doc answers at (`<namespace>/deps/<bundle>`), except on an excluded row, which names the `<package>@<version>:<skill>` selector. An excluded row is a dependency bundle rejected before its files enter the vendoring planner.' },
479
489
  ],
480
490
  outputKind: 'object',
481
491
  effects: [
482
- "Wipes and regenerates <project>/.crouter/memory/deps/ from installed dependency skills, except bundles selected by exact {package,version,skill} entries in package.json crtr.sync.deps.exclude. Each included SKILL.md becomes a system-name/file-none deps/<bundle>/INDEX.md (relative sidecar links keep resolving), Markdown sidecar docs are vendored alongside at the same rungs, other sidecar assets are copied verbatim, and a system-preview/file-none deps/INDEX.md catalog plus a self-ignoring .gitignore are written. Excluded bundles and their sidecars do not enter the catalog.",
492
+ "Wipes and regenerates <project>/.crouter/memory/deps/ from installed dependency skills, except bundles selected by exact {package,version,skill} entries in package.json crtr.sync.deps.exclude. Each included SKILL.md becomes a system-name/file-none deps/<bundle>/INDEX.md answering at <namespace>/deps/<bundle> (relative sidecar links keep resolving), Markdown sidecar docs are vendored alongside at the same rungs, other sidecar assets are copied verbatim, and a system-preview/file-none deps/INDEX.md catalog answering at <namespace>/deps plus a self-ignoring .gitignore are written. Excluded bundles and their sidecars do not enter the catalog.",
493
+ 'Refuses a project store whose repository root declares no namespace, naming `crtr sys migrate --dir <repositoryRoot>` as the remedy; it never declares one itself.',
483
494
  'With --dry-run: read-only; writes nothing.',
484
495
  ],
485
496
  },