@north-light/crouter 0.3.227 → 0.3.229

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 (312) 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/04-base-worker.md +1 -1
  7. package/dist/builtin-memory/insights/init.md +5 -5
  8. package/dist/builtin-memory/internal/INDEX.md +1 -1
  9. package/dist/builtin-memory/internal/agent-shaping.md +11 -11
  10. package/dist/builtin-memory/internal/examples/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/memory-loading.md +6 -6
  12. package/dist/builtin-memory/internal/plugins.md +1 -1
  13. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +50 -37
  14. package/dist/clients/attach/__tests__/pane-tag-successor.test.js +56 -0
  15. package/dist/clients/attach/__tests__/profile-files.test.js +21 -0
  16. package/dist/clients/attach/chrome/inbox-strip.js +11 -7
  17. package/dist/clients/attach/session/pane-tag.d.ts +28 -2
  18. package/dist/clients/attach/session/pane-tag.js +48 -22
  19. package/dist/clients/attach/session/profile-files.d.ts +6 -0
  20. package/dist/clients/attach/session/profile-files.js +44 -11
  21. package/dist/clients/attach/slash/dispatch.js +4 -7
  22. package/dist/clients/attach/viewer.js +588 -596
  23. package/dist/commands/__tests__/surface-reload-target.test.js +21 -0
  24. package/dist/commands/api-client.d.ts +3 -7
  25. package/dist/commands/api-client.js +7 -12
  26. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +292 -0
  27. package/dist/commands/memory/__tests__/repository-root-lint.test.js +146 -0
  28. package/dist/commands/memory/delete.js +51 -24
  29. package/dist/commands/memory/edit.js +50 -10
  30. package/dist/commands/memory/find.js +105 -56
  31. package/dist/commands/memory/history.js +51 -31
  32. package/dist/commands/memory/lint.d.ts +0 -9
  33. package/dist/commands/memory/lint.js +78 -322
  34. package/dist/commands/memory/list.d.ts +12 -4
  35. package/dist/commands/memory/list.js +64 -25
  36. package/dist/commands/memory/move.js +103 -73
  37. package/dist/commands/memory/origin.js +35 -5
  38. package/dist/commands/memory/read.d.ts +4 -0
  39. package/dist/commands/memory/read.js +132 -80
  40. package/dist/commands/memory/shared.d.ts +115 -25
  41. package/dist/commands/memory/shared.js +331 -74
  42. package/dist/commands/memory/write.js +72 -21
  43. package/dist/commands/memory.js +2 -2
  44. package/dist/commands/node/create.d.ts +1 -1
  45. package/dist/commands/node/create.js +1 -1
  46. package/dist/commands/node/inspect.js +1 -1
  47. package/dist/commands/node/lifecycle.js +5 -5
  48. package/dist/commands/pkg/market-manage.js +25 -24
  49. package/dist/commands/pkg/plugin-manage.d.ts +22 -6
  50. package/dist/commands/pkg/plugin-manage.js +118 -25
  51. package/dist/commands/pkg/shared.d.ts +8 -0
  52. package/dist/commands/pkg/shared.js +23 -20
  53. package/dist/commands/surface-reload.d.ts +5 -0
  54. package/dist/commands/surface-reload.js +9 -1
  55. package/dist/commands/sys/__tests__/migrate.test.js +1140 -22
  56. package/dist/commands/sys/__tests__/sync-project-guidance.test.js +218 -0
  57. package/dist/commands/sys/migrate.js +126 -140
  58. package/dist/commands/sys/panels/profiles-panel.d.ts +66 -0
  59. package/dist/commands/sys/panels/profiles-panel.js +599 -0
  60. package/dist/commands/sys/settings-shell.d.ts +4 -2
  61. package/dist/commands/sys/settings-shell.js +35 -4
  62. package/dist/commands/sys/settings.js +21 -5
  63. package/dist/commands/sys/sync-deps.d.ts +2 -0
  64. package/dist/commands/sys/sync-deps.js +26 -15
  65. package/dist/commands/sys/sync-project-guidance.js +228 -145
  66. package/dist/commands/sys/sync-skills.js +28 -17
  67. package/dist/commands/sys/update.js +11 -3
  68. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +15 -2
  69. package/dist/core/__tests__/config-change-delta.test.js +106 -0
  70. package/dist/core/__tests__/context-intro.test.js +13 -9
  71. package/dist/core/__tests__/daemon-boot.test.js +22 -16
  72. package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +5 -1
  73. package/dist/core/__tests__/human-deliver.test.js +19 -0
  74. package/dist/core/__tests__/inline-memory-refs.test.js +50 -46
  75. package/dist/core/__tests__/{serial → integration}/broker-fork-seam.test.js +1 -1
  76. package/dist/core/__tests__/{serial → integration}/broker-sdk-wiring.test.js +1 -1
  77. package/dist/core/__tests__/{serial → integration}/broker-snapshot-history.test.js +1 -1
  78. package/dist/core/__tests__/{serial → integration}/command-plugins.test.js +94 -3
  79. package/dist/core/__tests__/{serial → integration}/deferred-no-wake.test.js +1 -1
  80. package/dist/core/__tests__/{serial → integration}/flagship-lifecycle.test.js +13 -27
  81. package/dist/core/__tests__/{serial → integration}/host-teardown-process-group.test.js +1 -1
  82. package/dist/core/__tests__/{serial → integration}/human-deliver-e2e.test.js +1 -1
  83. package/dist/core/__tests__/{live-mutation-verbs.test.js → integration/live-mutation-verbs.test.js} +22 -33
  84. package/dist/core/__tests__/{serial → integration}/live-mutation.test.js +21 -41
  85. package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +1 -0
  86. package/dist/core/__tests__/{serial → integration}/refresh-stall-recycle.test.js +1 -1
  87. package/dist/core/__tests__/integration/revive.test.d.ts +1 -0
  88. package/dist/core/__tests__/{serial → integration}/revive.test.js +38 -19
  89. package/dist/core/__tests__/integration/spawn-root.test.d.ts +1 -0
  90. package/dist/core/__tests__/{serial → integration}/spawn-root.test.js +104 -1
  91. package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +1 -0
  92. package/dist/core/__tests__/{serial → integration}/subscription-delivery.test.js +1 -1
  93. package/dist/core/__tests__/integration/tmux-surface.test.d.ts +1 -0
  94. package/dist/core/__tests__/{serial → integration}/tmux-surface.test.js +1 -1
  95. package/dist/core/__tests__/integration/worktree-land.test.d.ts +1 -0
  96. package/dist/core/__tests__/integration/worktree-land.test.js +400 -0
  97. package/dist/core/__tests__/integration/worktree-reap.test.d.ts +1 -0
  98. package/dist/core/__tests__/{serial/worktree.test.js → integration/worktree-reap.test.js} +6 -338
  99. package/dist/core/__tests__/kickoff.test.js +16 -5
  100. package/dist/core/__tests__/memory-resolver-precedence.test.js +122 -91
  101. package/dist/core/__tests__/nested-store-discovery.test.js +5 -3
  102. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
  103. package/dist/core/__tests__/on-read-dedup-resume.test.js +39 -27
  104. package/dist/core/__tests__/on-read-nested-store.test.js +19 -13
  105. package/dist/core/__tests__/profile-project-memory-delivery.test.js +138 -44
  106. package/dist/core/__tests__/repository-association.test.d.ts +1 -0
  107. package/dist/core/__tests__/repository-association.test.js +153 -0
  108. package/dist/core/__tests__/repository-root-identity.test.d.ts +1 -0
  109. package/dist/core/__tests__/repository-root-identity.test.js +219 -0
  110. package/dist/core/__tests__/review-model-floor.test.js +12 -4
  111. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +27 -11
  112. package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +1 -0
  113. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +40 -0
  114. package/dist/core/canvas/canvas.d.ts +3 -0
  115. package/dist/core/canvas/canvas.js +30 -10
  116. package/dist/core/canvas/db.js +28 -1
  117. package/dist/core/canvas/paths.d.ts +4 -6
  118. package/dist/core/canvas/paths.js +8 -6
  119. package/dist/core/canvas/render-source.js +2 -2
  120. package/dist/core/canvas/types.d.ts +9 -13
  121. package/dist/core/config.d.ts +3 -3
  122. package/dist/core/config.js +3 -3
  123. package/dist/core/exclusive-lock.d.ts +2 -0
  124. package/dist/core/exclusive-lock.js +21 -0
  125. package/dist/core/git.d.ts +0 -1
  126. package/dist/core/git.js +0 -3
  127. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +1 -0
  128. package/dist/core/human/feedback-companion.js +3 -0
  129. package/dist/core/human/scan.js +8 -1
  130. package/dist/core/keybindings/catalog.d.ts +2 -2
  131. package/dist/core/keybindings/catalog.js +2 -1
  132. package/dist/core/memory/doc-link-grammar.js +2 -2
  133. package/dist/core/memory/history.d.ts +24 -0
  134. package/dist/core/memory/history.js +66 -1
  135. package/dist/core/memory/identity.d.ts +65 -0
  136. package/dist/core/memory/identity.js +185 -0
  137. package/dist/core/memory/inline-ref-guidance.d.ts +1 -1
  138. package/dist/core/memory/inline-ref-guidance.js +1 -1
  139. package/dist/core/memory/inline-ref-inventory.d.ts +3 -10
  140. package/dist/core/memory/inline-ref-inventory.js +30 -62
  141. package/dist/core/memory/lint.d.ts +129 -0
  142. package/dist/core/memory/lint.js +517 -0
  143. package/dist/core/memory/project-namespace.d.ts +31 -0
  144. package/dist/core/memory/project-namespace.js +85 -0
  145. package/dist/core/memory/repository-association.d.ts +31 -0
  146. package/dist/core/memory/repository-association.js +129 -0
  147. package/dist/core/memory/tree.d.ts +39 -0
  148. package/dist/core/memory/tree.js +93 -0
  149. package/dist/core/memory-resolver.d.ts +193 -90
  150. package/dist/core/memory-resolver.js +461 -375
  151. package/dist/core/nested-stores.js +6 -13
  152. package/dist/core/profiles/select.d.ts +4 -1
  153. package/dist/core/profiles/select.js +108 -48
  154. package/dist/core/review/__tests__/capture-origin.test.js +2 -2
  155. package/dist/core/review/__tests__/stage-identity.test.js +2 -2
  156. package/dist/core/review/companion.js +11 -2
  157. package/dist/core/runtime/bearings.d.ts +2 -2
  158. package/dist/core/runtime/bearings.js +3 -3
  159. package/dist/core/runtime/broker/daemon-ops.d.ts +2 -2
  160. package/dist/core/runtime/broker/rebind.js +5 -0
  161. package/dist/core/runtime/broker-extension-render.d.ts +7 -3
  162. package/dist/core/runtime/broker-extension-render.js +10 -5
  163. package/dist/core/runtime/broker-persona-guidance.d.ts +19 -5
  164. package/dist/core/runtime/broker-persona-guidance.js +122 -27
  165. package/dist/core/runtime/deliver-live.d.ts +16 -4
  166. package/dist/core/runtime/deliver-live.js +29 -15
  167. package/dist/core/runtime/kickoff.d.ts +3 -3
  168. package/dist/core/runtime/kickoff.js +8 -16
  169. package/dist/core/runtime/launch.js +1 -1
  170. package/dist/core/runtime/lifecycle.js +2 -3
  171. package/dist/core/runtime/nodes.d.ts +3 -4
  172. package/dist/core/runtime/nodes.js +3 -4
  173. package/dist/core/runtime/persona.d.ts +8 -12
  174. package/dist/core/runtime/persona.js +24 -96
  175. package/dist/core/runtime/promote.d.ts +2 -2
  176. package/dist/core/runtime/promote.js +8 -21
  177. package/dist/core/runtime/revive.js +20 -17
  178. package/dist/core/runtime/spawn.js +18 -7
  179. package/dist/core/runtime/tmux-bindings.js +2 -3
  180. package/dist/core/runtime/warm-pool.js +3 -4
  181. package/dist/core/scope.js +2 -0
  182. package/dist/core/self-update.d.ts +0 -2
  183. package/dist/core/self-update.js +2 -35
  184. package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +1 -0
  185. package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +28 -0
  186. package/dist/core/substrate/index.d.ts +2 -2
  187. package/dist/core/substrate/index.js +1 -1
  188. package/dist/core/substrate/injected-store.d.ts +43 -27
  189. package/dist/core/substrate/injected-store.js +208 -104
  190. package/dist/core/substrate/listings.d.ts +19 -12
  191. package/dist/core/substrate/listings.js +75 -52
  192. package/dist/core/substrate/on-read-node.d.ts +4 -7
  193. package/dist/core/substrate/on-read-node.js +6 -8
  194. package/dist/core/substrate/on-read.d.ts +22 -25
  195. package/dist/core/substrate/on-read.js +103 -147
  196. package/dist/core/substrate/render-node.d.ts +4 -7
  197. package/dist/core/substrate/render-node.js +5 -7
  198. package/dist/core/substrate/render.d.ts +21 -3
  199. package/dist/core/substrate/render.js +291 -223
  200. package/dist/core/substrate/schema.d.ts +1 -13
  201. package/dist/core/substrate/schema.js +5 -40
  202. package/dist/core/substrate/session-cache.d.ts +14 -4
  203. package/dist/core/substrate/session-cache.js +40 -22
  204. package/dist/core/substrate/surface-match.d.ts +9 -7
  205. package/dist/core/substrate/surface-match.js +26 -25
  206. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +30 -0
  207. package/dist/daemon/__tests__/helpers/source-daemon.js +174 -0
  208. package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +1 -0
  209. package/dist/daemon/__tests__/integration/migration-startup.test.js +97 -0
  210. package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +21 -5
  211. package/dist/daemon/api/handlers/broker-ops.js +21 -16
  212. package/dist/daemon/api/handlers/memory.js +2 -0
  213. package/dist/daemon/crtrd.js +2 -0
  214. package/dist/daemon/human/finish.js +8 -1
  215. package/dist/daemon/manage.d.ts +0 -1
  216. package/dist/daemon/manage.js +7 -16
  217. package/dist/daemon/startup-policy.d.ts +1 -0
  218. package/dist/daemon/startup-policy.js +1 -0
  219. package/dist/migrations/001-surfaces-frontmatter.js +21 -109
  220. package/dist/migrations/002-profile-project-memory.js +1 -0
  221. package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +26 -0
  222. package/dist/migrations/003-repository-root-memory-identity/front-door.js +231 -0
  223. package/dist/migrations/003-repository-root-memory-identity/index.d.ts +2 -0
  224. package/dist/migrations/003-repository-root-memory-identity/index.js +513 -0
  225. package/dist/migrations/003-repository-root-memory-identity/references.d.ts +95 -0
  226. package/dist/migrations/003-repository-root-memory-identity/references.js +469 -0
  227. package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +39 -0
  228. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +349 -0
  229. package/dist/migrations/__tests__/activation-concurrency.test.d.ts +1 -0
  230. package/dist/migrations/__tests__/activation-concurrency.test.js +145 -0
  231. package/dist/migrations/__tests__/activation.test.d.ts +1 -0
  232. package/dist/migrations/__tests__/activation.test.js +149 -0
  233. package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +1 -0
  234. package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +149 -0
  235. package/dist/migrations/activation.d.ts +16 -0
  236. package/dist/migrations/activation.js +78 -0
  237. package/dist/migrations/convergent.d.ts +14 -3
  238. package/dist/migrations/convergent.js +21 -10
  239. package/dist/migrations/corpus.d.ts +78 -0
  240. package/dist/migrations/corpus.js +497 -0
  241. package/dist/migrations/frontmatter-splice.d.ts +15 -0
  242. package/dist/migrations/frontmatter-splice.js +176 -0
  243. package/dist/migrations/registry.d.ts +6 -1
  244. package/dist/migrations/registry.js +7 -2
  245. package/dist/migrations/runner.d.ts +41 -0
  246. package/dist/migrations/runner.js +81 -0
  247. package/dist/migrations/types.d.ts +148 -9
  248. package/dist/migrations/types.js +9 -2
  249. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +225 -17
  250. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +11 -3
  251. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -5
  252. package/dist/pi-extensions/canvas-context-intro.js +50 -46
  253. package/dist/pi-extensions/canvas-doc-substrate.d.ts +1 -8
  254. package/dist/pi-extensions/canvas-doc-substrate.js +55 -122
  255. package/dist/pi-extensions/canvas-stophook.js +6 -13
  256. package/dist/shared/generated-context.d.ts +0 -3
  257. package/dist/shared/generated-context.js +0 -57
  258. package/dist/shared/tool-groups.js +2 -3
  259. package/dist/types.d.ts +8 -11
  260. package/dist/types.js +4 -31
  261. package/package.json +5 -4
  262. package/runtime.lock.json +2 -2
  263. package/dist/builtin-memory/05-kinds/design/00-base.md +0 -17
  264. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +0 -15
  265. package/dist/builtin-memory/05-kinds/design/design-contract.md +0 -19
  266. package/dist/builtin-memory/05-kinds/developer/00-base.md +0 -17
  267. package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +0 -15
  268. package/dist/builtin-memory/05-kinds/plan/00-base.md +0 -17
  269. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +0 -17
  270. package/dist/builtin-memory/05-kinds/plan/plan-contract.md +0 -28
  271. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -15
  272. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -15
  273. package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +0 -13
  274. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -17
  275. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +0 -17
  276. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -17
  277. package/dist/builtin-memory/05-kinds/spec/00-base.md +0 -17
  278. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +0 -15
  279. package/dist/builtin-memory/05-kinds/spec/requirements.md +0 -15
  280. package/dist/builtin-memory/design/guide.md +0 -35
  281. package/dist/builtin-memory/design/roadmap.md +0 -21
  282. package/dist/builtin-memory/development.md +0 -113
  283. package/dist/builtin-memory/plan/roadmap.md +0 -25
  284. package/dist/builtin-memory/spec/guide.md +0 -53
  285. package/dist/builtin-memory/spec/requirements.md +0 -29
  286. package/dist/builtin-memory/spec/roadmap.md +0 -36
  287. package/dist/builtin-memory/testing.md +0 -39
  288. /package/dist/api/__tests__/{serial → integration}/client.test.d.ts +0 -0
  289. /package/dist/api/__tests__/{serial → integration}/client.test.js +0 -0
  290. /package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{serial → integration}/provider-rotation.test.ts +0 -0
  291. /package/dist/clients/{inbox/__tests__/serial/inbox-controller.test.d.ts → attach/__tests__/pane-tag-successor.test.d.ts} +0 -0
  292. /package/dist/clients/{inbox/__tests__/serial/mount-panel.test.d.ts → attach/__tests__/profile-files.test.d.ts} +0 -0
  293. /package/dist/{core/__tests__/live-mutation-verbs.test.d.ts → clients/inbox/__tests__/integration/inbox-controller.test.d.ts} +0 -0
  294. /package/dist/clients/inbox/__tests__/{serial → integration}/inbox-controller.test.js +0 -0
  295. /package/dist/{core/__tests__/serial/broker-fork-seam.test.d.ts → clients/inbox/__tests__/integration/mount-panel.test.d.ts} +0 -0
  296. /package/dist/clients/inbox/__tests__/{serial → integration}/mount-panel.test.js +0 -0
  297. /package/dist/{core/__tests__/serial/broker-sdk-wiring.test.d.ts → commands/__tests__/surface-reload-target.test.d.ts} +0 -0
  298. /package/dist/{core/__tests__/serial/broker-snapshot-history.test.d.ts → commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts} +0 -0
  299. /package/dist/{core/__tests__/serial/command-plugins.test.d.ts → commands/memory/__tests__/repository-root-lint.test.d.ts} +0 -0
  300. /package/dist/{core/__tests__/serial/deferred-no-wake.test.d.ts → commands/sys/__tests__/sync-project-guidance.test.d.ts} +0 -0
  301. /package/dist/core/__tests__/{serial/flagship-lifecycle.test.d.ts → config-change-delta.test.d.ts} +0 -0
  302. /package/dist/core/__tests__/{serial/host-teardown-process-group.test.d.ts → integration/broker-fork-seam.test.d.ts} +0 -0
  303. /package/dist/core/__tests__/{serial/human-deliver-e2e.test.d.ts → integration/broker-sdk-wiring.test.d.ts} +0 -0
  304. /package/dist/core/__tests__/{serial/live-mutation.test.d.ts → integration/broker-snapshot-history.test.d.ts} +0 -0
  305. /package/dist/core/__tests__/{serial/refresh-stall-recycle.test.d.ts → integration/command-plugins.test.d.ts} +0 -0
  306. /package/dist/core/__tests__/{serial/revive.test.d.ts → integration/deferred-no-wake.test.d.ts} +0 -0
  307. /package/dist/core/__tests__/{serial/spawn-root.test.d.ts → integration/flagship-lifecycle.test.d.ts} +0 -0
  308. /package/dist/core/__tests__/{serial/subscription-delivery.test.d.ts → integration/host-teardown-process-group.test.d.ts} +0 -0
  309. /package/dist/core/__tests__/{serial/tmux-surface.test.d.ts → integration/human-deliver-e2e.test.d.ts} +0 -0
  310. /package/dist/core/__tests__/{serial/worktree.test.d.ts → integration/live-mutation-verbs.test.d.ts} +0 -0
  311. /package/dist/core/{human/__tests__/serial/inbox-core.test.d.ts → __tests__/integration/live-mutation.test.d.ts} +0 -0
  312. /package/dist/core/human/__tests__/{serial → integration}/inbox-core.test.js +0 -0
@@ -113,13 +113,13 @@ export interface NodeIdentity {
113
113
  kind: string;
114
114
  mode: Mode;
115
115
  lifecycle: Lifecycle;
116
- /** The last persona state {mode,lifecycle} the node was GIVEN transition
117
- * guidance for. Meta-only (not a db column). Born equal to the node's initial
118
- * {mode,lifecycle} at spawn so a fresh node never gets spurious guidance. The
119
- * persona injector (runtime/persona.ts) compares the live {mode,lifecycle}
120
- * against this and, on drift, injects guidance for the new state then commits
121
- * it here. */
116
+ /** The last {kind,mode,lifecycle} whose context delivery was acknowledged.
117
+ * Meta-only (not a db column). Born equal to the initial persona; later
118
+ * changes advance only after a baseline or provider-gated transition is
119
+ * durably registered. Historical rows may omit `kind`; reads resolve it to
120
+ * the current kind so they do not fabricate a transition. */
122
121
  persona_ack?: {
122
+ kind?: string;
123
123
  mode: Mode;
124
124
  lifecycle: Lifecycle;
125
125
  };
@@ -130,14 +130,10 @@ export interface NodeIdentity {
130
130
  * `parent` so an INDEPENDENT root (parent=null) still records its lineage.
131
131
  * Audit only; null for a user-opened root. Defaults to `parent` for a child. */
132
132
  spawned_by?: string | null;
133
- /** Fork provenance — the `--fork-from` source this node was forked from at
134
- * spawn (the node id / session path / pi session uuid the caller passed). pi
135
- * COPIED that conversation into this node's first session, so the node boots
136
- * carrying the SOURCE's first-person history. Persisted here so the boot
137
- * intro can assert this node's OWN identity over that inherited narrative
138
- * (without it a fork impersonates its source). Undefined for a fresh node;
139
- * identity/audit only. */
133
+ /** Raw `--fork-from` operand retained for identity framing and audit. */
140
134
  fork_from?: string | null;
135
+ /** Resolved absolute source session file used for every pre-bind fork retry. */
136
+ fork_source_file?: string | null;
141
137
  /** Immutable review-companion binding. Undefined for ordinary nodes. */
142
138
  review_binding?: ReviewBinding | null;
143
139
  /** New subscriptions this node opens default to passive when true. */
@@ -147,7 +147,7 @@ export interface MergedLaunchConfig {
147
147
  * follow-up fix this parameterization exists for). */
148
148
  export declare function readMergedLaunchConfig(targetCwd?: string, targetProfileId?: string | null): MergedLaunchConfig;
149
149
  /** The effective `KindConfig` for one full kind string (top-level, e.g.
150
- * `developer`, or sub-kind, e.g. `plan/reviewers/security`), across
150
+ * `developer`, or sub-kind, e.g. `audit/security`), across
151
151
  * project > user > builtin precedence. Returns `undefined` for a kind no
152
152
  * scope registers — existence is deliberately NOT validated here (kind
153
153
  * existence/launch-menu enumeration is a caller concern); this only
@@ -160,8 +160,8 @@ export declare function resolveKindConfig(kind: string): KindConfig | undefined;
160
160
  export declare function assertInstalledKind(kind: string): void;
161
161
  /** The sub-kinds available to spawn FROM a given top-level kind — every
162
162
  * registered sub-kind (full path contains `/`) whose `availableTo` (default:
163
- * its own top-level ancestor, e.g. `plan/reviewers/security` defaults to
164
- * `['plan']`) includes `kind` or `'*'`. The single source both `sys
163
+ * its own top-level ancestor, e.g. `audit/security` defaults to
164
+ * `['audit']`) includes `kind` or `'*'`. The single source both `sys
165
165
  * prompt-review --list`'s `subPersonas` metadata and the live sub-persona
166
166
  * spawn-menu splice (`core/substrate/render.ts`) read, so the two can never
167
167
  * drift apart. Sorted by full kind name for stable rendering. */
@@ -796,7 +796,7 @@ export function readMergedLaunchConfig(targetCwd = process.cwd(), targetProfileI
796
796
  return { kinds, modelLadders, ...(Object.keys(modelRoutes).length > 0 ? { modelRoutes } : {}), ...(modelRouting !== undefined ? { modelRouting } : {}), spawnEnv };
797
797
  }
798
798
  /** The effective `KindConfig` for one full kind string (top-level, e.g.
799
- * `developer`, or sub-kind, e.g. `plan/reviewers/security`), across
799
+ * `developer`, or sub-kind, e.g. `audit/security`), across
800
800
  * project > user > builtin precedence. Returns `undefined` for a kind no
801
801
  * scope registers — existence is deliberately NOT validated here (kind
802
802
  * existence/launch-menu enumeration is a caller concern); this only
@@ -820,8 +820,8 @@ export function assertInstalledKind(kind) {
820
820
  }
821
821
  /** The sub-kinds available to spawn FROM a given top-level kind — every
822
822
  * registered sub-kind (full path contains `/`) whose `availableTo` (default:
823
- * its own top-level ancestor, e.g. `plan/reviewers/security` defaults to
824
- * `['plan']`) includes `kind` or `'*'`. The single source both `sys
823
+ * its own top-level ancestor, e.g. `audit/security` defaults to
824
+ * `['audit']`) includes `kind` or `'*'`. The single source both `sys
825
825
  * prompt-review --list`'s `subPersonas` metadata and the live sub-persona
826
826
  * spawn-menu splice (`core/substrate/render.ts`) read, so the two can never
827
827
  * drift apart. Sorted by full kind name for stable rendering. */
@@ -12,3 +12,5 @@ export interface ExclusiveLockOptions {
12
12
  * however long its operation runs.
13
13
  */
14
14
  export declare function withExclusiveDirectoryLock<T>(path: string, operation: () => T, options?: ExclusiveLockOptions): T;
15
+ /** Run an awaited operation under the same token-checked directory lock. */
16
+ export declare function withExclusiveDirectoryLockAsync<T>(path: string, operation: () => Promise<T>, options?: ExclusiveLockOptions): Promise<T>;
@@ -5,6 +5,7 @@ const POLL_MS = 10;
5
5
  const DEFAULT_STALE_MS = 30_000;
6
6
  const DEFAULT_TIMEOUT_MS = 5_000;
7
7
  function pause(ms) { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); }
8
+ function pauseAsync(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
8
9
  function markerPath(path, token) { return `${path}/${MARKER_PREFIX}${token}`; }
9
10
  function observedMarkerToken(path) {
10
11
  try {
@@ -122,3 +123,23 @@ export function withExclusiveDirectoryLock(path, operation, options = {}) {
122
123
  rmSync(lock.path, { recursive: true, force: true });
123
124
  }
124
125
  }
126
+ /** Run an awaited operation under the same token-checked directory lock. */
127
+ export async function withExclusiveDirectoryLockAsync(path, operation, options = {}) {
128
+ const staleMs = options.staleMs ?? DEFAULT_STALE_MS;
129
+ const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
130
+ let lock = tryAcquire(path, staleMs);
131
+ while (lock === null) {
132
+ if (Date.now() >= deadline) {
133
+ throw options.timeoutError?.() ?? new Error(`timed out waiting for the exclusive lock: ${path}`);
134
+ }
135
+ await pauseAsync(Math.min(POLL_MS, Math.max(0, deadline - Date.now())));
136
+ lock = tryAcquire(path, staleMs);
137
+ }
138
+ try {
139
+ return await operation();
140
+ }
141
+ finally {
142
+ if (existsSync(markerPath(lock.path, lock.token)))
143
+ rmSync(lock.path, { recursive: true, force: true });
144
+ }
145
+ }
@@ -13,7 +13,6 @@ export declare function clone(url: string, dest: string, opts?: {
13
13
  ref?: string;
14
14
  depth?: number;
15
15
  }): GitResult;
16
- export declare function pull(cwd: string): GitResult;
17
16
  export declare function fetch(cwd: string, ref?: string): GitResult;
18
17
  export declare function lsRemote(url: string): GitResult;
19
18
  export declare function currentSha(cwd: string): string | null;
package/dist/core/git.js CHANGED
@@ -35,9 +35,6 @@ export function clone(url, dest, opts = {}) {
35
35
  }
36
36
  return res;
37
37
  }
38
- export function pull(cwd) {
39
- return gitSync(['pull', '--ff-only'], cwd);
40
- }
41
38
  export function fetch(cwd, ref) {
42
39
  const args = ['fetch', 'origin'];
43
40
  if (ref)
@@ -16,6 +16,7 @@ import { headlessBrokerHost } from '../runtime/host.js';
16
16
  import { spawnNode } from '../runtime/nodes.js';
17
17
  import { reviveNode } from '../runtime/revive.js';
18
18
  import { materializeSessionBranchAt } from '../runtime/session-branch.js';
19
+ import { initializeForkContextExposure } from '../substrate/injected-store.js';
19
20
  import { pagePath } from './convention.js';
20
21
  export function feedbackCompanionBranchPath(dir) { return `${dir}/companion-branch.jsonl`; }
21
22
  /** Hex sha256 of the ticket's page document, recorded at first comment so the
@@ -73,6 +74,7 @@ export async function realizeFeedbackCompanion(args) {
73
74
  parent: args.senderNodeId,
74
75
  subscribe: false,
75
76
  forkFrom: branchFile,
77
+ forkSourceFile: branchFile,
76
78
  modelOverride: capture.modelSpec,
77
79
  reviewBinding: {
78
80
  kind: 'page_feedback',
@@ -85,6 +87,7 @@ export async function realizeFeedbackCompanion(args) {
85
87
  launch,
86
88
  });
87
89
  try {
90
+ initializeForkContextExposure(node.node_id, args.senderNodeId);
88
91
  reviveNode(node.node_id, { resume: false });
89
92
  if (!await awaitCompanionBind(node.node_id, COMPANION_BIND_DEADLINE_MS)) {
90
93
  throw new Error(`feedback companion did not bind within ${COMPANION_BIND_DEADLINE_MS}ms`);
@@ -1,4 +1,4 @@
1
- import { readdirSync, statSync } from 'node:fs';
1
+ import { existsSync, readdirSync, statSync } from 'node:fs';
2
2
  import { basename, join } from 'node:path';
3
3
  import { claimPath, isResolved, pageManifestPath, reviewPath } from './convention.js';
4
4
  import { readJsonOrNull } from '../fs-utils.js';
@@ -27,6 +27,13 @@ function reviewSummary(dir, id) {
27
27
  return { dir, id, kind: 'review', title: review.title, subtitle: review.subtitle, file: review.file, output: review.output, source: review.source, blockedSince: review.blockedSince, claim: claimSummary(dir) };
28
28
  }
29
29
  function pageSummary(dir, id) {
30
+ // The tickets root IS the canvas node root, so all but a handful of these
31
+ // directories hold no page at all. Gate on the manifest's presence with one
32
+ // stat instead of letting `parsePage` throw: a thrown ENOENT carries a V8
33
+ // stack capture, which over thousands of node directories is the whole cost
34
+ // of a scan.
35
+ if (!existsSync(pageManifestPath(dir)))
36
+ return null;
30
37
  let manifest;
31
38
  try {
32
39
  manifest = parsePage(dir);
@@ -4,12 +4,12 @@ type TmuxMenuAction = 'open' | 'attach' | 'show' | 'view-settings' | 'fold-tools
4
4
  type TmuxMenuEntryAction = Exclude<TmuxMenuAction, 'open' | 'attach'> | `issue.${'idea' | 'bug'}`;
5
5
  type GraphAction = 'down' | 'up' | 'first' | 'last' | 'collapse-or-manager' | 'expand-or-child' | 'focus' | 'revive' | 'focus-manager' | 'close-subtree' | 'dismiss';
6
6
  type BrowseAction = 'quit' | 'down' | 'up' | 'first' | 'last' | 'expand-or-child' | 'collapse-or-parent' | 'toggle-fold' | 'tab-next' | 'tab-previous' | `tab.${1 | 2 | 3 | 4 | 5}` | 'close-subtree' | 'confirm-close' | 'sort' | 'scope' | 'profile' | 'residents' | 'preview' | 'search' | 'revive-now' | 'focus' | 'focus-background' | 'yank-id';
7
- type ProfileMenuAction = 'up' | 'down' | 'select' | 'accept-default' | 'abort' | `slot.${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}` | 'create' | 'search-existing' | 'use-root' | 'set-default' | 'add-directory' | 'unpin';
7
+ type ProfileMenuAction = 'up' | 'down' | 'select' | 'accept-default' | 'abort' | `slot.${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}` | 'create' | 'search-existing' | 'use-root' | 'set-default' | 'add-directory' | 'unpin' | 'manage';
8
8
  type SetupAction = 'cancel' | 'tab-next' | 'tab-previous' | 'open' | 'list-down' | 'list-up' | 'toggle' | 'details' | 'advance' | 'cell-previous' | 'cell-next';
9
9
  type SetupKeybindingAction = 'edit' | 'commit-edit' | 'cancel-edit' | 'unbind' | 'reset-row' | 'reset-all' | 'save' | 'discard' | 'page-up' | 'page-down' | 'filter' | 'filter-delete' | 'filter-clear';
10
10
  type SetupModelsAction = 'open' | 'commit' | 'cancel' | 'scope-next';
11
11
  export type BindingId = `crtr.tmux.menu.${TmuxMenuAction}` | `crtr.tmux.menu.issue.${'idea' | 'bug'}` | AttachMenuBindingId | `crtr.tmux.menu-global.${TmuxMenuEntryAction}` | `crtr.tmux.node.${'next' | 'previous'}` | 'crtr.tmux.inbox.toggle' | `crtr.attach.scroll.${'up' | 'down' | 'page-up' | 'page-down' | 'live'}` | 'crtr.attach.mouse.toggle' | 'crtr.attach.copy.message' | 'crtr.attach.help.toggle' | `crtr.attach.search.${'next' | 'previous' | 'edit' | 'close'}` | AttachBindingId | `crtr.graph.${GraphAction}` | `crtr.graph.confirm.${'accept' | 'cancel'}` | `crtr.inspector.${'force-quit' | 'down' | 'up' | 'section-next' | 'section-prev' | 'page-down' | 'page-up' | 'toggle-detail' | 'cancel-item' | 'open-log' | 'confirm' | 'dismiss' | 'retarget' | 'refresh' | 'quit'}` | `crtr.browse.${BrowseAction}` | `crtr.browse.search.${'cancel' | 'commit' | 'delete' | 'quit'}` | `crtr.profile.menu.${ProfileMenuAction}` | `crtr.profile.search.${'up' | 'down' | 'pick' | 'back' | 'delete' | 'abort'}` | `crtr.setup.${SetupAction}` | `crtr.setup.confirm.${'accept' | 'back'}` | `crtr.setup.keybindings.${SetupKeybindingAction}` | `crtr.setup.models.${SetupModelsAction}`;
12
- export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.attach">, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.tmux.node.next"> | BindingDefinition<"crtr.tmux.node.previous"> | BindingDefinition<"crtr.tmux.inbox.toggle"> | BindingDefinition<"crtr.attach.scroll.up"> | BindingDefinition<"crtr.attach.scroll.down"> | BindingDefinition<"crtr.attach.scroll.page-up"> | BindingDefinition<"crtr.attach.scroll.page-down"> | BindingDefinition<"crtr.attach.scroll.live"> | BindingDefinition<"crtr.attach.mouse.toggle"> | BindingDefinition<"crtr.attach.copy.message"> | BindingDefinition<"crtr.attach.search.next"> | BindingDefinition<"crtr.attach.search.previous"> | BindingDefinition<"crtr.attach.search.edit"> | BindingDefinition<"crtr.attach.search.close"> | BindingDefinition<"crtr.graph.down"> | BindingDefinition<"crtr.graph.up"> | BindingDefinition<"crtr.graph.first"> | BindingDefinition<"crtr.graph.last"> | BindingDefinition<"crtr.graph.collapse-or-manager"> | BindingDefinition<"crtr.graph.expand-or-child"> | BindingDefinition<"crtr.graph.focus"> | BindingDefinition<"crtr.graph.revive"> | BindingDefinition<"crtr.graph.focus-manager"> | BindingDefinition<"crtr.graph.close-subtree"> | BindingDefinition<"crtr.graph.dismiss"> | BindingDefinition<"crtr.graph.confirm.accept"> | BindingDefinition<"crtr.graph.confirm.cancel"> | BindingDefinition<"crtr.inspector.force-quit"> | BindingDefinition<"crtr.inspector.down"> | BindingDefinition<"crtr.inspector.up"> | BindingDefinition<"crtr.inspector.section-next"> | BindingDefinition<"crtr.inspector.section-prev"> | BindingDefinition<"crtr.inspector.page-down"> | BindingDefinition<"crtr.inspector.page-up"> | BindingDefinition<"crtr.inspector.toggle-detail"> | BindingDefinition<"crtr.inspector.cancel-item"> | BindingDefinition<"crtr.inspector.open-log"> | BindingDefinition<"crtr.inspector.confirm"> | BindingDefinition<"crtr.inspector.dismiss"> | BindingDefinition<"crtr.inspector.retarget"> | BindingDefinition<"crtr.inspector.refresh"> | BindingDefinition<"crtr.inspector.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.profile"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.focus-background"> | BindingDefinition<"crtr.browse.yank-id"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.9">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">, BindingDefinition<"crtr.setup.cell-previous">, BindingDefinition<"crtr.setup.cell-next">, BindingDefinition<"crtr.setup.models.open">, BindingDefinition<"crtr.setup.models.scope-next">, BindingDefinition<"crtr.setup.models.commit">, BindingDefinition<"crtr.setup.models.cancel">];
12
+ export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.attach">, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.tmux.node.next"> | BindingDefinition<"crtr.tmux.node.previous"> | BindingDefinition<"crtr.tmux.inbox.toggle"> | BindingDefinition<"crtr.attach.scroll.up"> | BindingDefinition<"crtr.attach.scroll.down"> | BindingDefinition<"crtr.attach.scroll.page-up"> | BindingDefinition<"crtr.attach.scroll.page-down"> | BindingDefinition<"crtr.attach.scroll.live"> | BindingDefinition<"crtr.attach.mouse.toggle"> | BindingDefinition<"crtr.attach.copy.message"> | BindingDefinition<"crtr.attach.search.next"> | BindingDefinition<"crtr.attach.search.previous"> | BindingDefinition<"crtr.attach.search.edit"> | BindingDefinition<"crtr.attach.search.close"> | BindingDefinition<"crtr.graph.down"> | BindingDefinition<"crtr.graph.up"> | BindingDefinition<"crtr.graph.first"> | BindingDefinition<"crtr.graph.last"> | BindingDefinition<"crtr.graph.collapse-or-manager"> | BindingDefinition<"crtr.graph.expand-or-child"> | BindingDefinition<"crtr.graph.focus"> | BindingDefinition<"crtr.graph.revive"> | BindingDefinition<"crtr.graph.focus-manager"> | BindingDefinition<"crtr.graph.close-subtree"> | BindingDefinition<"crtr.graph.dismiss"> | BindingDefinition<"crtr.graph.confirm.accept"> | BindingDefinition<"crtr.graph.confirm.cancel"> | BindingDefinition<"crtr.inspector.force-quit"> | BindingDefinition<"crtr.inspector.down"> | BindingDefinition<"crtr.inspector.up"> | BindingDefinition<"crtr.inspector.section-next"> | BindingDefinition<"crtr.inspector.section-prev"> | BindingDefinition<"crtr.inspector.page-down"> | BindingDefinition<"crtr.inspector.page-up"> | BindingDefinition<"crtr.inspector.toggle-detail"> | BindingDefinition<"crtr.inspector.cancel-item"> | BindingDefinition<"crtr.inspector.open-log"> | BindingDefinition<"crtr.inspector.confirm"> | BindingDefinition<"crtr.inspector.dismiss"> | BindingDefinition<"crtr.inspector.retarget"> | BindingDefinition<"crtr.inspector.refresh"> | BindingDefinition<"crtr.inspector.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.profile"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.focus-background"> | BindingDefinition<"crtr.browse.yank-id"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.9">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.menu.manage">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">, BindingDefinition<"crtr.setup.cell-previous">, BindingDefinition<"crtr.setup.cell-next">, BindingDefinition<"crtr.setup.models.open">, BindingDefinition<"crtr.setup.models.scope-next">, BindingDefinition<"crtr.setup.models.commit">, BindingDefinition<"crtr.setup.models.cancel">];
13
13
  export declare const BINDING_IDS: ReadonlySet<string>;
14
14
  /** True for an action whose direct gesture is handled inside an attach viewer.
15
15
  * Tmux menu selectors and root shortcuts are chrome, not pane input. */
@@ -77,7 +77,7 @@ export const BINDING_CATALOG = Object.freeze([
77
77
  ...attachEntry('crtr.tmux.menu.attach.model-ladder.previous', 'crtr.attach.model-ladder.previous', 'Previous model', 'Move to the previous model ladder rung.', ['['], ['alt+shift+m']),
78
78
  ...attachEntry('crtr.tmux.menu.attach.command.inspect', 'crtr.attach.command.inspect', 'Inspect loaded command', 'Open the loaded slash command’s expanded prompt.', ['h'], ['alt+shift+h']),
79
79
  ...attachEntry('crtr.tmux.menu.attach.file-review', 'crtr.attach.file-review', 'Review a file', 'Open a line-anchored review of a file named in the transcript.', [], ['alt+shift+r']),
80
- ...attachEntry('crtr.tmux.menu.attach.profile-files', 'crtr.attach.profile-files', 'Search profile files', 'Search files across the node’s profile projects, profile memory, cwd, and ancestor crouter memory stores.', ['f'], ['ctrl+f']),
80
+ ...attachEntry('crtr.tmux.menu.attach.profile-files', 'crtr.attach.profile-files', 'Search profile files', 'Fuzzy-match path segments across the node family’s working directories, profile projects and memory, and ancestor crouter memory stores; Ctrl+Y copies a selected path.', ['f'], ['ctrl+f']),
81
81
  ...attachEntry('crtr.tmux.menu.attach.search', 'crtr.attach.search', 'Search transcript', 'Search the transcript as it is currently displayed — folded tool output is not searched until it is unfolded.', ['/'], ['alt+/']),
82
82
  ...attachEntry('crtr.tmux.menu.attach.whip', 'crtr.attach.whip', 'Whip agent', 'Interrupt the agent and send a playful command.', ['w'], []),
83
83
  b('crtr.attach.scroll.up', 'Attach', 'Scroll up', 'Scroll the transcript one line up.', ['shift+up'], 'terminal', ATTACH_CONTEXTS),
@@ -171,6 +171,7 @@ function profileBindings() {
171
171
  b('crtr.profile.menu.set-default', 'Profiles', 'Set default', 'Set the selected profile as default.', ['d'], 'terminal', [menu]),
172
172
  b('crtr.profile.menu.add-directory', 'Profiles', 'Add directory', 'Add a directory to the profile.', ['a'], 'terminal', [menu]),
173
173
  b('crtr.profile.menu.unpin', 'Profiles', 'Unpin directory', 'Unpin the selected directory.', ['u'], 'terminal', [menu]),
174
+ b('crtr.profile.menu.manage', 'Profiles', 'Manage profiles', 'Open the profiles settings page in a popup.', ['v'], 'terminal', [menu]),
174
175
  b('crtr.profile.search.up', 'Profiles', 'Move up', 'Move to the previous search result.', ['up', 'ctrl+p'], 'terminal', [search]),
175
176
  b('crtr.profile.search.down', 'Profiles', 'Move down', 'Move to the next search result.', ['down', 'ctrl+n'], 'terminal', [search]),
176
177
  b('crtr.profile.search.pick', 'Profiles', 'Pick profile', 'Pick the highlighted profile.', ['enter'], 'terminal', [search]),
@@ -16,10 +16,10 @@
16
16
  // This module never resolves anything: `findDocLinks` returns candidate links;
17
17
  // a caller decides a link is live by testing `name` against the corpus of
18
18
  // resolvable canonical names.
19
- // A canonical doc name: one or more `[A-Za-z0-9_-]+` segments joined by `/`.
19
+ // A canonical doc name: one or more `[A-Za-z0-9._-]+` segments joined by `/`.
20
20
  // Anything else between `[[` `]]` (spaces, `|` aliases, empty segments) is NOT
21
21
  // a doc link — the grammar has no alias/label form, by design.
22
- const NAME_RE = /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*$/;
22
+ const NAME_RE = /^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/;
23
23
  const LINK_RE = /\[\[([^\[\]\n]+)\]\]/g;
24
24
  /** Is `name` a well-formed canonical doc-link name? */
25
25
  export function isDocLinkName(name) {
@@ -1,3 +1,4 @@
1
+ import type { MemoryDoc } from '../memory-resolver.js';
1
2
  /** Sidecar tree name under a store's `memory/` dir. Dot-prefixed and holding
2
3
  * only `.jsonl`, so every substrate scan (which filters to `*.md`, and in
3
4
  * `lint`'s case skips dot-dirs outright) passes it over without an exclusion
@@ -37,6 +38,29 @@ export declare function buildHistoryRecord(input: {
37
38
  before: string;
38
39
  after: string;
39
40
  }): HistoryRecord;
41
+ /** Derive a live document's sidecar from its descriptor. The descriptor's
42
+ * physical path is authoritative: canonical names carry a project namespace,
43
+ * while sidecars remain in the owning store's physical tree. */
44
+ export declare function historyLogPathForDoc(doc: Pick<MemoryDoc, 'root' | 'path'>): string;
45
+ export interface DeletedHistoryCandidate {
46
+ path: string;
47
+ representation: 'directory-index' | 'leaf-file';
48
+ winner: boolean;
49
+ }
50
+ export interface DeletedHistoryResolution {
51
+ logPath: string;
52
+ candidates: readonly DeletedHistoryCandidate[];
53
+ collision?: {
54
+ paths: readonly string[];
55
+ winner: string;
56
+ };
57
+ }
58
+ /** Resolve a deleted document's physical history without reintroducing a
59
+ * canonical-name fallback. `localName` is already stripped of the selected
60
+ * project's exact namespace. The directory-index sidecar is deliberately
61
+ * probed first, and therefore wins deterministically if both physical forms
62
+ * survive; callers can expose `candidates`/`collision` for diagnostics. */
63
+ export declare function resolveDeletedHistoryLogPath(storeRoot: string, localName: string): DeletedHistoryResolution | null;
40
64
  /** Append one record. Single write of one line — concurrent appends interleave
41
65
  * whole records, and every record stands alone, so no lock is needed. */
42
66
  export declare function appendHistoryRecord(logPath: string, record: HistoryRecord): void;
@@ -10,11 +10,12 @@
10
10
  // The raw file is the consumer contract: an external reader (a product surface
11
11
  // reading a store off disk) parses one JSON object per line and computes its
12
12
  // own diffs. Nothing here shells out to git.
13
- import { appendFileSync } from 'node:fs';
13
+ import { appendFileSync, readdirSync } from 'node:fs';
14
14
  import { dirname, join, relative } from 'node:path';
15
15
  import { ensureDir, pathExists, readText } from '../fs-utils.js';
16
16
  import { general } from '../errors.js';
17
17
  import { parseFrontmatterGeneric } from '../frontmatter.js';
18
+ import { normalizeNameSegment } from './identity.js';
18
19
  /** Sidecar tree name under a store's `memory/` dir. Dot-prefixed and holding
19
20
  * only `.jsonl`, so every substrate scan (which filters to `*.md`, and in
20
21
  * `lint`'s case skips dot-dirs outright) passes it over without an exclusion
@@ -48,6 +49,70 @@ export function buildHistoryRecord(input) {
48
49
  };
49
50
  return record;
50
51
  }
52
+ /** Derive a live document's sidecar from its descriptor. The descriptor's
53
+ * physical path is authoritative: canonical names carry a project namespace,
54
+ * while sidecars remain in the owning store's physical tree. */
55
+ export function historyLogPathForDoc(doc) {
56
+ return historyLogPathFor(doc.root, doc.path);
57
+ }
58
+ function matchingDirs(parent, segment) {
59
+ let entries;
60
+ try {
61
+ entries = readdirSync(parent, { withFileTypes: true });
62
+ }
63
+ catch {
64
+ return [];
65
+ }
66
+ return entries
67
+ .filter((entry) => entry.isDirectory() && normalizeNameSegment(entry.name) === segment)
68
+ .sort((a, b) => (a.name === segment ? -1 : b.name === segment ? 1 : a.name.localeCompare(b.name)))
69
+ .map((entry) => join(parent, entry.name));
70
+ }
71
+ function matchingFiles(parent, stem) {
72
+ let entries;
73
+ try {
74
+ entries = readdirSync(parent, { withFileTypes: true });
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ return entries
80
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl') && normalizeNameSegment(entry.name.slice(0, -'.jsonl'.length)) === stem)
81
+ .sort((a, b) => (a.name === `${stem}.jsonl` ? -1 : b.name === `${stem}.jsonl` ? 1 : a.name.localeCompare(b.name)))
82
+ .map((entry) => join(parent, entry.name));
83
+ }
84
+ function historyFilesForSegments(historyDir, segments, stem) {
85
+ let parents = [historyDir];
86
+ for (const segment of segments) {
87
+ parents = parents.flatMap((parent) => matchingDirs(parent, segment));
88
+ if (parents.length === 0)
89
+ return [];
90
+ }
91
+ return parents.flatMap((parent) => matchingFiles(parent, stem));
92
+ }
93
+ /** Resolve a deleted document's physical history without reintroducing a
94
+ * canonical-name fallback. `localName` is already stripped of the selected
95
+ * project's exact namespace. The directory-index sidecar is deliberately
96
+ * probed first, and therefore wins deterministically if both physical forms
97
+ * survive; callers can expose `candidates`/`collision` for diagnostics. */
98
+ export function resolveDeletedHistoryLogPath(storeRoot, localName) {
99
+ const segments = localName.split('/').filter((segment) => segment !== '').map(normalizeNameSegment);
100
+ const historyDir = join(storeRoot, HISTORY_DIR);
101
+ const indexPaths = historyFilesForSegments(historyDir, segments, 'INDEX');
102
+ const leafPaths = segments.length === 0 ? [] : historyFilesForSegments(historyDir, segments.slice(0, -1), segments[segments.length - 1]);
103
+ const candidates = [
104
+ ...indexPaths.map((path) => ({ path, representation: 'directory-index', winner: false })),
105
+ ...leafPaths.map((path) => ({ path, representation: 'leaf-file', winner: false })),
106
+ ];
107
+ if (candidates.length === 0)
108
+ return null;
109
+ candidates[0].winner = true;
110
+ return {
111
+ logPath: candidates[0].path,
112
+ candidates,
113
+ ...(candidates.length > 1 ? { collision: { paths: candidates.map((candidate) => candidate.path), winner: candidates[0].path } } : {}),
114
+ };
115
+ }
51
116
  /** Append one record. Single write of one line — concurrent appends interleave
52
117
  * whole records, and every record stands alone, so no lock is needed. */
53
118
  export function appendHistoryRecord(logPath, record) {
@@ -0,0 +1,65 @@
1
+ /** The filename (and path segment) whose document fronts its directory. */
2
+ export declare const INDEX_SEGMENT = "INDEX";
3
+ /** Strip an optional `NN-` ordering prefix from ONE segment. */
4
+ export declare function normalizeNameSegment(segment: string): string;
5
+ /** Slugify one authored or filesystem label into a canonical segment. */
6
+ export declare function slugCanonicalSegment(raw: string): string;
7
+ /** Slugify a derived label into canonical path segments. Empty segments are
8
+ * intentionally dropped; owner paths use slugCanonicalSegment directly. */
9
+ export declare function slugCanonicalPath(raw: string): string;
10
+ /** Strip the ordering prefix from EVERY segment of a slash-separated name:
11
+ * `01-spine/00-has-manager` -> `spine/has-manager`. */
12
+ export declare function normalizeDocName(name: string): string;
13
+ /** Split a name into segments, dropping empties from `//`, a leading `/`, or an
14
+ * empty name. */
15
+ export declare function canonicalSegments(name: string): string[];
16
+ /** The canonical directory containing `name`, or `''` at the top. */
17
+ export declare function canonicalParent(name: string): string;
18
+ /** Remove EXACTLY ONE trailing `INDEX` segment. `a/INDEX` -> `a`; `INDEX` ->
19
+ * `''` (a store root); `a/INDEX/INDEX` -> `a/INDEX` (the inner segment is an
20
+ * ordinary directory name). */
21
+ export declare function collapseTrailingIndex(name: string): string;
22
+ export type DocRepresentation = 'leaf-file' | 'directory-index';
23
+ /** Which form a store-relative markdown path takes. */
24
+ export declare function representationForPath(physicalRelativePath: string): DocRepresentation;
25
+ /** Store-local name derived from a store-relative markdown path: ordering
26
+ * prefixes stripped from every segment and one trailing `INDEX` collapsed.
27
+ * Empty only for a store root `INDEX.md`. */
28
+ export declare function localNameFromPath(physicalRelativePath: string): string;
29
+ /** The store-relative markdown path a local name occupies in a given form.
30
+ * Both forms are checked before any create or move, so occupancy never depends
31
+ * on which one a store happens to use. */
32
+ export declare function physicalRelativePathFor(localName: string, representation: DocRepresentation): string;
33
+ /** A document's explicit frontmatter `name` as a local name — normalized with
34
+ * one trailing `INDEX` collapsed — or `null` when it carries none. */
35
+ export declare function explicitLocalName(fm: Record<string, unknown> | null | undefined): string | null;
36
+ /** A document's store-local name: its explicit frontmatter `name` when present,
37
+ * else the path-derived local name. Explicit names are local to their store —
38
+ * they never carry the store's namespace. */
39
+ export declare function resolveLocalName(fm: Record<string, unknown> | null | undefined, pathDerivedLocalName: string): string;
40
+ /** namespace ⊕ local — the only address. Composition is unconditional: a local
41
+ * name that already looks namespace-prefixed is composed anyway, so identity
42
+ * never depends on string coincidence. An empty result means a namespace-less
43
+ * store root, which has no valid canonical identity. */
44
+ export declare function composeCanonicalName(namespace: string, localName: string): string;
45
+ /** The canonical directory a document's `./` memory-read entries match against:
46
+ * a directory document anchors at its own name, an ordinary leaf at its
47
+ * canonical parent. */
48
+ export declare function routingAnchorFor(canonicalName: string, representation: DocRepresentation): string;
49
+ /** The local name a canonical name has inside `namespace`, or `null` when it
50
+ * falls outside it. Exact on segment boundaries: `a/bc` is not inside `a/b`.
51
+ * The namespace itself yields `''` — the store root document. */
52
+ export declare function stripNamespace(canonicalName: string, namespace: string): string | null;
53
+ export type IdentityValidation = {
54
+ ok: true;
55
+ } | {
56
+ ok: false;
57
+ reason: string;
58
+ };
59
+ /** A project store's declared namespace, or an installed plugin's mount prefix:
60
+ * one or more normalized segments, never ending in `INDEX`. */
61
+ export declare function validateNamespace(namespace: string): IdentityValidation;
62
+ /** An explicit non-root `name:`: a non-empty local name, never ending in
63
+ * `INDEX` (its directory name is the identity) and never carrying its own
64
+ * store's namespace. */
65
+ export declare function validateExplicitLocalName(localName: string, namespace?: string): IdentityValidation;