@soleri/core 9.15.0 → 9.16.7

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/data/flows/deliver.flow.yaml +11 -0
  2. package/data/flows/design.flow.yaml +4 -14
  3. package/data/flows/enhance.flow.yaml +10 -0
  4. package/data/flows/explore.flow.yaml +16 -0
  5. package/data/flows/fix.flow.yaml +1 -1
  6. package/data/flows/review.flow.yaml +13 -4
  7. package/dist/capabilities/chain-mapping.d.ts.map +1 -1
  8. package/dist/capabilities/chain-mapping.js +5 -4
  9. package/dist/capabilities/chain-mapping.js.map +1 -1
  10. package/dist/capabilities/registry.d.ts +6 -0
  11. package/dist/capabilities/registry.d.ts.map +1 -1
  12. package/dist/capabilities/registry.js +3 -2
  13. package/dist/capabilities/registry.js.map +1 -1
  14. package/dist/context/context-engine.js +1 -1
  15. package/dist/context/context-engine.js.map +1 -1
  16. package/dist/engine/core-ops.d.ts.map +1 -1
  17. package/dist/engine/core-ops.js +38 -1
  18. package/dist/engine/core-ops.js.map +1 -1
  19. package/dist/flows/epilogue.d.ts +5 -1
  20. package/dist/flows/epilogue.d.ts.map +1 -1
  21. package/dist/flows/epilogue.js +11 -3
  22. package/dist/flows/epilogue.js.map +1 -1
  23. package/dist/flows/executor.d.ts.map +1 -1
  24. package/dist/flows/executor.js +13 -5
  25. package/dist/flows/executor.js.map +1 -1
  26. package/dist/flows/index.d.ts +1 -2
  27. package/dist/flows/index.d.ts.map +1 -1
  28. package/dist/flows/index.js +1 -0
  29. package/dist/flows/index.js.map +1 -1
  30. package/dist/flows/plan-builder.d.ts +17 -1
  31. package/dist/flows/plan-builder.d.ts.map +1 -1
  32. package/dist/flows/plan-builder.js +67 -6
  33. package/dist/flows/plan-builder.js.map +1 -1
  34. package/dist/flows/probes.d.ts +1 -1
  35. package/dist/flows/probes.d.ts.map +1 -1
  36. package/dist/flows/probes.js +15 -3
  37. package/dist/flows/probes.js.map +1 -1
  38. package/dist/flows/types.d.ts +31 -4
  39. package/dist/flows/types.d.ts.map +1 -1
  40. package/dist/flows/types.js +6 -1
  41. package/dist/flows/types.js.map +1 -1
  42. package/dist/index.d.ts +8 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +7 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/packs/pack-installer.d.ts.map +1 -1
  47. package/dist/packs/pack-installer.js +28 -2
  48. package/dist/packs/pack-installer.js.map +1 -1
  49. package/dist/planning/planner-types.d.ts +2 -0
  50. package/dist/planning/planner-types.d.ts.map +1 -1
  51. package/dist/planning/planner.d.ts +1 -0
  52. package/dist/planning/planner.d.ts.map +1 -1
  53. package/dist/planning/planner.js +7 -0
  54. package/dist/planning/planner.js.map +1 -1
  55. package/dist/playbooks/playbook-executor.d.ts +10 -1
  56. package/dist/playbooks/playbook-executor.d.ts.map +1 -1
  57. package/dist/playbooks/playbook-executor.js +8 -2
  58. package/dist/playbooks/playbook-executor.js.map +1 -1
  59. package/dist/playbooks/playbook-types.d.ts +8 -0
  60. package/dist/playbooks/playbook-types.d.ts.map +1 -1
  61. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  62. package/dist/runtime/admin-extra-ops.js +30 -0
  63. package/dist/runtime/admin-extra-ops.js.map +1 -1
  64. package/dist/runtime/admin-ops.d.ts.map +1 -1
  65. package/dist/runtime/admin-ops.js +60 -21
  66. package/dist/runtime/admin-ops.js.map +1 -1
  67. package/dist/runtime/admin-setup-ops.d.ts +11 -0
  68. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  69. package/dist/runtime/admin-setup-ops.js +87 -17
  70. package/dist/runtime/admin-setup-ops.js.map +1 -1
  71. package/dist/runtime/capture-ops.d.ts.map +1 -1
  72. package/dist/runtime/capture-ops.js +38 -12
  73. package/dist/runtime/capture-ops.js.map +1 -1
  74. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  75. package/dist/runtime/facades/brain-facade.js +16 -4
  76. package/dist/runtime/facades/brain-facade.js.map +1 -1
  77. package/dist/runtime/facades/context-facade.d.ts.map +1 -1
  78. package/dist/runtime/facades/context-facade.js +9 -3
  79. package/dist/runtime/facades/context-facade.js.map +1 -1
  80. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  81. package/dist/runtime/facades/memory-facade.js +20 -7
  82. package/dist/runtime/facades/memory-facade.js.map +1 -1
  83. package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -1
  84. package/dist/runtime/facades/orchestrate-facade.js +12 -0
  85. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  86. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  87. package/dist/runtime/facades/plan-facade.js +113 -4
  88. package/dist/runtime/facades/plan-facade.js.map +1 -1
  89. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  90. package/dist/runtime/facades/vault-facade.js +24 -3
  91. package/dist/runtime/facades/vault-facade.js.map +1 -1
  92. package/dist/runtime/orchestrate-ops.d.ts +21 -0
  93. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  94. package/dist/runtime/orchestrate-ops.js +132 -38
  95. package/dist/runtime/orchestrate-ops.js.map +1 -1
  96. package/dist/runtime/schema-helpers.d.ts.map +1 -1
  97. package/dist/runtime/schema-helpers.js +4 -0
  98. package/dist/runtime/schema-helpers.js.map +1 -1
  99. package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
  100. package/dist/runtime/vault-linking-ops.js +16 -3
  101. package/dist/runtime/vault-linking-ops.js.map +1 -1
  102. package/dist/scheduler/cron-validator.d.ts +15 -0
  103. package/dist/scheduler/cron-validator.d.ts.map +1 -0
  104. package/dist/scheduler/cron-validator.js +93 -0
  105. package/dist/scheduler/cron-validator.js.map +1 -0
  106. package/dist/scheduler/platform-linux.d.ts +14 -0
  107. package/dist/scheduler/platform-linux.d.ts.map +1 -0
  108. package/dist/scheduler/platform-linux.js +107 -0
  109. package/dist/scheduler/platform-linux.js.map +1 -0
  110. package/dist/scheduler/platform-macos.d.ts +15 -0
  111. package/dist/scheduler/platform-macos.d.ts.map +1 -0
  112. package/dist/scheduler/platform-macos.js +131 -0
  113. package/dist/scheduler/platform-macos.js.map +1 -0
  114. package/dist/scheduler/scheduler-ops.d.ts +14 -0
  115. package/dist/scheduler/scheduler-ops.d.ts.map +1 -0
  116. package/dist/scheduler/scheduler-ops.js +77 -0
  117. package/dist/scheduler/scheduler-ops.js.map +1 -0
  118. package/dist/scheduler/scheduler.d.ts +55 -0
  119. package/dist/scheduler/scheduler.d.ts.map +1 -0
  120. package/dist/scheduler/scheduler.js +144 -0
  121. package/dist/scheduler/scheduler.js.map +1 -0
  122. package/dist/scheduler/types.d.ts +48 -0
  123. package/dist/scheduler/types.d.ts.map +1 -0
  124. package/dist/scheduler/types.js +6 -0
  125. package/dist/scheduler/types.js.map +1 -0
  126. package/dist/skills/sync-skills.d.ts +11 -0
  127. package/dist/skills/sync-skills.d.ts.map +1 -1
  128. package/dist/skills/sync-skills.js +132 -38
  129. package/dist/skills/sync-skills.js.map +1 -1
  130. package/dist/utils/worktree-reaper.d.ts +38 -0
  131. package/dist/utils/worktree-reaper.d.ts.map +1 -0
  132. package/dist/utils/worktree-reaper.js +85 -0
  133. package/dist/utils/worktree-reaper.js.map +1 -0
  134. package/dist/vault/scope-detector.d.ts.map +1 -1
  135. package/dist/vault/scope-detector.js +37 -4
  136. package/dist/vault/scope-detector.js.map +1 -1
  137. package/dist/vault/vault-entries.d.ts.map +1 -1
  138. package/dist/vault/vault-entries.js +3 -1
  139. package/dist/vault/vault-entries.js.map +1 -1
  140. package/package.json +1 -1
  141. package/src/agency/agency-manager.test.ts +4 -4
  142. package/src/agency/default-rules.test.ts +0 -13
  143. package/src/brain/brain-intelligence.test.ts +0 -5
  144. package/src/brain/second-brain-features.test.ts +2 -14
  145. package/src/capabilities/chain-mapping.test.ts +1 -6
  146. package/src/capabilities/chain-mapping.ts +6 -4
  147. package/src/capabilities/registry.test.ts +1 -1
  148. package/src/capabilities/registry.ts +9 -2
  149. package/src/chat/agent-loop.test.ts +1 -1
  150. package/src/chat/chat-enhanced.test.ts +0 -8
  151. package/src/claudemd/compose.test.ts +0 -5
  152. package/src/context/context-engine.test.ts +0 -1
  153. package/src/context/context-engine.ts +1 -1
  154. package/src/control/intent-router.test.ts +2 -2
  155. package/src/curator/tag-manager.test.ts +0 -4
  156. package/src/domain-packs/types.test.ts +0 -5
  157. package/src/dream/dream.test.ts +0 -7
  158. package/src/enforcement/registry.test.ts +2 -2
  159. package/src/engine/core-ops.test.ts +4 -22
  160. package/src/engine/core-ops.ts +36 -1
  161. package/src/engine/module-manifest.test.ts +1 -31
  162. package/src/engine/register-engine.test.ts +3 -33
  163. package/src/errors/retry.test.ts +3 -1
  164. package/src/flows/chain-runner.test.ts +0 -6
  165. package/src/flows/context-router.test.ts +3 -3
  166. package/src/flows/epilogue.test.ts +40 -2
  167. package/src/flows/epilogue.ts +11 -2
  168. package/src/flows/executor.test.ts +48 -2
  169. package/src/flows/executor.ts +15 -5
  170. package/src/flows/index.ts +1 -3
  171. package/src/flows/plan-builder.test.ts +201 -0
  172. package/src/flows/plan-builder.ts +81 -5
  173. package/src/flows/probes.ts +17 -3
  174. package/src/flows/types.ts +31 -2
  175. package/src/health/health-registry.test.ts +3 -1
  176. package/src/index.ts +17 -0
  177. package/src/intake/dedup-gate.test.ts +2 -6
  178. package/src/intake/text-ingester.test.ts +3 -4
  179. package/src/llm/llm-client.test.ts +1 -1
  180. package/src/llm/utils.test.ts +1 -1
  181. package/src/migrations/migration-runner.test.ts +0 -1
  182. package/src/operator/operator-context-store.test.ts +0 -13
  183. package/src/operator/operator-profile.test.ts +2 -20
  184. package/src/packs/pack-installer.ts +28 -2
  185. package/src/packs/pack-system.test.ts +2 -2
  186. package/src/persona/defaults.test.ts +19 -19
  187. package/src/planning/gap-passes.test.ts +0 -46
  188. package/src/planning/gap-patterns.test.ts +0 -42
  189. package/src/planning/goal-ancestry.test.ts +3 -1
  190. package/src/planning/plan-lifecycle.test.ts +15 -7
  191. package/src/planning/planner-types.ts +2 -0
  192. package/src/planning/planner.ts +8 -0
  193. package/src/planning/reconciliation-engine.test.ts +3 -10
  194. package/src/planning/task-complexity-assessor.test.ts +0 -5
  195. package/src/planning/task-verifier.test.ts +3 -1
  196. package/src/playbooks/generic/generic-playbooks.test.ts +0 -28
  197. package/src/playbooks/index.test.ts +0 -55
  198. package/src/playbooks/playbook-executor.test.ts +76 -0
  199. package/src/playbooks/playbook-executor.ts +24 -3
  200. package/src/playbooks/playbook-types.ts +8 -0
  201. package/src/plugins/plugin-registry.test.ts +6 -2
  202. package/src/project/project-registry.test.ts +2 -0
  203. package/src/queue/async-infrastructure.test.ts +6 -4
  204. package/src/queue/job-queue.test.ts +13 -7
  205. package/src/runtime/admin-extra-ops.test.ts +35 -30
  206. package/src/runtime/admin-extra-ops.ts +30 -0
  207. package/src/runtime/admin-ops.test.ts +0 -4
  208. package/src/runtime/admin-ops.ts +63 -21
  209. package/src/runtime/admin-setup-ops.test.ts +185 -13
  210. package/src/runtime/admin-setup-ops.ts +86 -16
  211. package/src/runtime/archive-ops.test.ts +0 -28
  212. package/src/runtime/branching-ops.test.ts +0 -17
  213. package/src/runtime/capture-ops.test.ts +41 -16
  214. package/src/runtime/capture-ops.ts +78 -46
  215. package/src/runtime/chain-ops.test.ts +0 -21
  216. package/src/runtime/facades/admin-facade.test.ts +0 -34
  217. package/src/runtime/facades/agency-facade.test.ts +0 -39
  218. package/src/runtime/facades/archive-facade.test.ts +0 -43
  219. package/src/runtime/facades/brain-facade.test.ts +8 -99
  220. package/src/runtime/facades/brain-facade.ts +29 -12
  221. package/src/runtime/facades/branching-facade.test.ts +30 -17
  222. package/src/runtime/facades/chat-facade.test.ts +0 -91
  223. package/src/runtime/facades/chat-service-ops.test.ts +0 -24
  224. package/src/runtime/facades/chat-session-ops.test.ts +0 -12
  225. package/src/runtime/facades/chat-transport-ops.test.ts +0 -23
  226. package/src/runtime/facades/context-facade.test.ts +0 -17
  227. package/src/runtime/facades/context-facade.ts +11 -4
  228. package/src/runtime/facades/control-facade.test.ts +0 -30
  229. package/src/runtime/facades/curator-facade.test.ts +0 -33
  230. package/src/runtime/facades/intake-facade.test.ts +0 -33
  231. package/src/runtime/facades/links-facade.test.ts +0 -37
  232. package/src/runtime/facades/loop-facade.test.ts +0 -26
  233. package/src/runtime/facades/memory-facade.test.ts +0 -18
  234. package/src/runtime/facades/memory-facade.ts +27 -11
  235. package/src/runtime/facades/operator-facade.test.ts +0 -31
  236. package/src/runtime/facades/orchestrate-facade.test.ts +0 -21
  237. package/src/runtime/facades/orchestrate-facade.ts +12 -0
  238. package/src/runtime/facades/plan-facade.test.ts +7 -32
  239. package/src/runtime/facades/plan-facade.ts +137 -4
  240. package/src/runtime/facades/review-facade.test.ts +1 -49
  241. package/src/runtime/facades/sync-facade.test.ts +24 -41
  242. package/src/runtime/facades/tier-facade.test.ts +30 -22
  243. package/src/runtime/facades/vault-facade.test.ts +0 -41
  244. package/src/runtime/facades/vault-facade.ts +26 -3
  245. package/src/runtime/grading-ops.test.ts +0 -27
  246. package/src/runtime/intake-ops.test.ts +0 -19
  247. package/src/runtime/loop-ops.test.ts +0 -48
  248. package/src/runtime/memory-cross-project-ops.test.ts +0 -14
  249. package/src/runtime/memory-extra-ops.test.ts +4 -8
  250. package/src/runtime/orchestrate-ops.test.ts +238 -19
  251. package/src/runtime/orchestrate-ops.ts +166 -41
  252. package/src/runtime/pack-ops.test.ts +0 -26
  253. package/src/runtime/planning-extra-ops.test.ts +2 -14
  254. package/src/runtime/playbook-ops-execution.test.ts +9 -20
  255. package/src/runtime/playbook-ops.test.ts +4 -67
  256. package/src/runtime/review-ops.test.ts +0 -15
  257. package/src/runtime/schema-helpers.ts +4 -0
  258. package/src/runtime/sync-ops.test.ts +0 -18
  259. package/src/runtime/tier-ops.test.ts +0 -21
  260. package/src/runtime/vault-extra-ops.test.ts +0 -12
  261. package/src/runtime/vault-linking-ops.test.ts +0 -4
  262. package/src/runtime/vault-linking-ops.ts +26 -8
  263. package/src/runtime/vault-sharing-ops.test.ts +0 -9
  264. package/src/scheduler/cron-validator.ts +101 -0
  265. package/src/scheduler/platform-linux.ts +122 -0
  266. package/src/scheduler/platform-macos.ts +150 -0
  267. package/src/scheduler/scheduler-ops.ts +77 -0
  268. package/src/scheduler/scheduler.test.ts +247 -0
  269. package/src/scheduler/scheduler.ts +174 -0
  270. package/src/scheduler/types.ts +52 -0
  271. package/src/skills/__tests__/sync-skills.test.ts +6 -17
  272. package/src/skills/global-claude-md.test.ts +113 -0
  273. package/src/skills/sync-skills.ts +143 -35
  274. package/src/skills/validate-skills.test.ts +12 -11
  275. package/src/telemetry/telemetry.test.ts +1 -0
  276. package/src/transport/http-server.test.ts +3 -0
  277. package/src/transport/session-manager.test.ts +3 -1
  278. package/src/transport/token-auth.test.ts +6 -9
  279. package/src/transport/ws-server.test.ts +10 -2
  280. package/src/utils/worktree-reaper.ts +113 -0
  281. package/src/vault/__tests__/vault-characterization.test.ts +0 -108
  282. package/src/vault/linking.test.ts +0 -2
  283. package/src/vault/playbook.test.ts +4 -1
  284. package/src/vault/scope-detector.test.ts +3 -1
  285. package/src/vault/scope-detector.ts +42 -4
  286. package/src/vault/vault-connect.test.ts +1 -1
  287. package/src/vault/vault-entries.ts +3 -1
  288. package/src/vault/vault.test.ts +23 -8
@@ -121,30 +121,6 @@ describe('chat-service-ops', () => {
121
121
  ops = createChatServiceOps(state);
122
122
  });
123
123
 
124
- it('exports 18 service ops', () => {
125
- const names = ops.map((o) => o.name);
126
- expect(names).toEqual([
127
- 'chat_cancel_create',
128
- 'chat_cancel_stop',
129
- 'chat_cancel_status',
130
- 'chat_update_init',
131
- 'chat_update_request',
132
- 'chat_update_confirm',
133
- 'chat_file_detect_intent',
134
- 'chat_file_build_content',
135
- 'chat_file_cleanup',
136
- 'chat_notify_init',
137
- 'chat_notify_start',
138
- 'chat_notify_stop',
139
- 'chat_notify_poll',
140
- 'chat_notify_status',
141
- 'chat_browser_init',
142
- 'chat_browser_acquire',
143
- 'chat_browser_release',
144
- 'chat_browser_status',
145
- ]);
146
- });
147
-
148
124
  // ─── Task Cancellation ─────────────────────────────────────────
149
125
 
150
126
  describe('chat_cancel_create', () => {
@@ -68,18 +68,6 @@ describe('chat-session-ops', () => {
68
68
  ops = createChatSessionOps(state);
69
69
  });
70
70
 
71
- it('exports 6 session ops', () => {
72
- const names = ops.map((o) => o.name);
73
- expect(names).toEqual([
74
- 'chat_session_init',
75
- 'chat_session_get',
76
- 'chat_session_append',
77
- 'chat_session_clear',
78
- 'chat_session_delete',
79
- 'chat_session_list',
80
- ]);
81
- });
82
-
83
71
  describe('chat_session_init', () => {
84
72
  it('initializes session manager and returns status', async () => {
85
73
  const op = findOp(ops, 'chat_session_init');
@@ -111,29 +111,6 @@ describe('chat-transport-ops', () => {
111
111
  ops = createChatTransportOps(state);
112
112
  });
113
113
 
114
- it('exports 17 transport ops', () => {
115
- const names = ops.map((o) => o.name);
116
- expect(names).toEqual([
117
- 'chat_chunk_response',
118
- 'chat_auth_init',
119
- 'chat_auth_check',
120
- 'chat_auth_authenticate',
121
- 'chat_auth_revoke',
122
- 'chat_auth_status',
123
- 'chat_bridge_init',
124
- 'chat_bridge_register',
125
- 'chat_bridge_list',
126
- 'chat_bridge_execute',
127
- 'chat_compress_output',
128
- 'chat_voice_transcribe',
129
- 'chat_voice_synthesize',
130
- 'chat_queue_init',
131
- 'chat_queue_inbox',
132
- 'chat_queue_reply',
133
- 'chat_queue_drain',
134
- ]);
135
- });
136
-
137
114
  // ─── Chunking ──────────────────────────────────────────────────
138
115
 
139
116
  describe('chat_chunk_response', () => {
@@ -51,23 +51,6 @@ describe('context-facade', () => {
51
51
  ops = captureOps(createContextFacadeOps(makeRuntime(mockEngine)));
52
52
  });
53
53
 
54
- it('registers all 3 ops', () => {
55
- expect(ops.size).toBe(3);
56
- expect([...ops.keys()]).toEqual(
57
- expect.arrayContaining([
58
- 'context_extract_entities',
59
- 'context_retrieve_knowledge',
60
- 'context_analyze',
61
- ]),
62
- );
63
- });
64
-
65
- it('has correct auth levels', () => {
66
- expect(ops.get('context_extract_entities')!.auth).toBe('read');
67
- expect(ops.get('context_retrieve_knowledge')!.auth).toBe('read');
68
- expect(ops.get('context_analyze')!.auth).toBe('read');
69
- });
70
-
71
54
  // ─── context_extract_entities ──────────────────────────────────
72
55
 
73
56
  it('context_extract_entities calls engine with prompt', async () => {
@@ -15,11 +15,18 @@ export function createContextFacadeOps(runtime: AgentRuntime): OpDefinition[] {
15
15
  description:
16
16
  'Extract named entities from a prompt — files, functions, domains, actions, technologies, patterns.',
17
17
  auth: 'read',
18
- schema: z.object({
19
- prompt: z.string().describe('The user prompt to analyze.'),
20
- }),
18
+ schema: z
19
+ .object({
20
+ prompt: z.string().optional().describe('The user prompt to analyze.'),
21
+ text: z.string().optional().describe('Alias for prompt — use either field.'),
22
+ })
23
+ .refine((v) => v.prompt !== undefined || v.text !== undefined, {
24
+ message: 'Provide either "prompt" or "text"',
25
+ }),
21
26
  handler: async (params) => {
22
- return contextEngine.extractEntities(params.prompt as string);
27
+ const input =
28
+ (params.prompt as string | undefined) ?? (params.text as string | undefined) ?? '';
29
+ return contextEngine.extractEntities(input);
23
30
  },
24
31
  },
25
32
  {
@@ -51,36 +51,6 @@ describe('createControlFacadeOps', () => {
51
51
  ops = createControlFacadeOps(runtime);
52
52
  });
53
53
 
54
- it('returns all expected ops', () => {
55
- const names = ops.map((o) => o.name);
56
- expect(names).toContain('get_identity');
57
- expect(names).toContain('update_identity');
58
- expect(names).toContain('add_guideline');
59
- expect(names).toContain('remove_guideline');
60
- expect(names).toContain('rollback_identity');
61
- expect(names).toContain('route_intent');
62
- expect(names).toContain('morph');
63
- expect(names).toContain('get_behavior_rules');
64
- expect(names).toContain('governance_policy');
65
- expect(names).toContain('governance_proposals');
66
- expect(names).toContain('governance_stats');
67
- expect(names).toContain('governance_expire');
68
- expect(names).toContain('governance_dashboard');
69
- expect(names).toContain('routing_feedback');
70
- expect(names).toContain('routing_accuracy');
71
- });
72
-
73
- it('assigns correct auth levels', () => {
74
- expect(findOp(ops, 'get_identity').auth).toBe('read');
75
- expect(findOp(ops, 'update_identity').auth).toBe('write');
76
- expect(findOp(ops, 'route_intent').auth).toBe('read');
77
- expect(findOp(ops, 'morph').auth).toBe('write');
78
- expect(findOp(ops, 'governance_policy').auth).toBe('write');
79
- expect(findOp(ops, 'governance_stats').auth).toBe('read');
80
- expect(findOp(ops, 'routing_feedback').auth).toBe('write');
81
- expect(findOp(ops, 'routing_accuracy').auth).toBe('read');
82
- });
83
-
84
54
  describe('get_identity', () => {
85
55
  it('returns identity when found', async () => {
86
56
  const identity = { agentId: 'test', name: 'Test Agent', version: 1 };
@@ -74,39 +74,6 @@ describe('createCuratorFacadeOps', () => {
74
74
  ops = createCuratorFacadeOps(runtime);
75
75
  });
76
76
 
77
- it('returns all expected ops', () => {
78
- const names = ops.map((o) => o.name);
79
- expect(names).toContain('curator_status');
80
- expect(names).toContain('curator_detect_duplicates');
81
- expect(names).toContain('curator_contradictions');
82
- expect(names).toContain('curator_resolve_contradiction');
83
- expect(names).toContain('curator_groom');
84
- expect(names).toContain('curator_groom_all');
85
- expect(names).toContain('curator_consolidate');
86
- expect(names).toContain('curator_health_audit');
87
- // Extra ops
88
- expect(names).toContain('curator_entry_history');
89
- expect(names).toContain('curator_record_snapshot');
90
- expect(names).toContain('curator_queue_stats');
91
- expect(names).toContain('curator_enrich');
92
- expect(names).toContain('curator_hybrid_contradictions');
93
- expect(names).toContain('curator_pipeline_status');
94
- expect(names).toContain('curator_enqueue_pipeline');
95
- expect(names).toContain('curator_schedule_start');
96
- expect(names).toContain('curator_schedule_stop');
97
- });
98
-
99
- it('assigns correct auth levels', () => {
100
- expect(findOp(ops, 'curator_status').auth).toBe('read');
101
- expect(findOp(ops, 'curator_detect_duplicates').auth).toBe('read');
102
- expect(findOp(ops, 'curator_contradictions').auth).toBe('read');
103
- expect(findOp(ops, 'curator_resolve_contradiction').auth).toBe('write');
104
- expect(findOp(ops, 'curator_groom').auth).toBe('write');
105
- expect(findOp(ops, 'curator_groom_all').auth).toBe('write');
106
- expect(findOp(ops, 'curator_consolidate').auth).toBe('write');
107
- expect(findOp(ops, 'curator_health_audit').auth).toBe('read');
108
- });
109
-
110
77
  describe('curator_status', () => {
111
78
  it('returns curator status', async () => {
112
79
  const result = await findOp(ops, 'curator_status').handler({});
@@ -50,39 +50,6 @@ describe('intake-facade', () => {
50
50
  ops = captureOps(createIntakeFacadeOps(runtime));
51
51
  });
52
52
 
53
- // ─── Registration ─────────────────────────────────────────────────
54
-
55
- it('returns exactly 7 ops', () => {
56
- expect(ops.size).toBe(7);
57
- });
58
-
59
- it('includes all expected op names', () => {
60
- const expected = [
61
- 'intake_ingest_book',
62
- 'intake_process',
63
- 'intake_status',
64
- 'intake_preview',
65
- 'ingest_url',
66
- 'ingest_text',
67
- 'ingest_batch',
68
- ];
69
- for (const name of expected) {
70
- expect(ops.has(name), `missing op: ${name}`).toBe(true);
71
- }
72
- });
73
-
74
- // ─── Auth levels ─────────────────────────────────────────────────
75
-
76
- it('has correct auth levels', () => {
77
- expect(ops.get('intake_ingest_book')!.auth).toBe('write');
78
- expect(ops.get('intake_process')!.auth).toBe('write');
79
- expect(ops.get('intake_status')!.auth).toBe('read');
80
- expect(ops.get('intake_preview')!.auth).toBe('read');
81
- expect(ops.get('ingest_url')!.auth).toBe('write');
82
- expect(ops.get('ingest_text')!.auth).toBe('write');
83
- expect(ops.get('ingest_batch')!.auth).toBe('write');
84
- });
85
-
86
53
  // ─── Delegation ─────────────────────────────────────────────────
87
54
 
88
55
  describe('intake_ingest_book', () => {
@@ -50,43 +50,6 @@ describe('links-facade', () => {
50
50
  ops = captureOps(createLinksFacadeOps(runtime));
51
51
  });
52
52
 
53
- // ─── Registration ──────────────────────────────────────────────────
54
-
55
- it('registers exactly 9 ops', () => {
56
- expect(ops.size).toBe(9);
57
- });
58
-
59
- it('includes all expected op names', () => {
60
- const expected = [
61
- 'link_entries',
62
- 'unlink_entries',
63
- 'get_links',
64
- 'traverse',
65
- 'suggest_links',
66
- 'get_orphans',
67
- 'relink_vault',
68
- 'backfill_links',
69
- 'link_stats',
70
- ];
71
- for (const name of expected) {
72
- expect(ops.has(name), `missing op: ${name}`).toBe(true);
73
- }
74
- });
75
-
76
- // ─── Auth levels ───────────────────────────────────────────────────
77
-
78
- it('has correct auth levels', () => {
79
- expect(ops.get('link_entries')!.auth).toBe('write');
80
- expect(ops.get('unlink_entries')!.auth).toBe('write');
81
- expect(ops.get('get_links')!.auth).toBe('read');
82
- expect(ops.get('traverse')!.auth).toBe('read');
83
- expect(ops.get('suggest_links')!.auth).toBe('read');
84
- expect(ops.get('get_orphans')!.auth).toBe('read');
85
- expect(ops.get('relink_vault')!.auth).toBe('write');
86
- expect(ops.get('backfill_links')!.auth).toBe('write');
87
- expect(ops.get('link_stats')!.auth).toBe('read');
88
- });
89
-
90
53
  // ─── Handler delegation ───────────────────────────────────────────
91
54
 
92
55
  describe('link_entries', () => {
@@ -87,32 +87,6 @@ describe('loop-facade', () => {
87
87
  ops = captureOps(createLoopFacadeOps(makeRuntime(mockLoop)));
88
88
  });
89
89
 
90
- it('registers all 9 ops', () => {
91
- expect(ops.size).toBe(9);
92
- const names = [...ops.keys()];
93
- expect(names).toContain('loop_start');
94
- expect(names).toContain('loop_iterate');
95
- expect(names).toContain('loop_iterate_gate');
96
- expect(names).toContain('loop_status');
97
- expect(names).toContain('loop_cancel');
98
- expect(names).toContain('loop_history');
99
- expect(names).toContain('loop_is_active');
100
- expect(names).toContain('loop_complete');
101
- expect(names).toContain('loop_anomaly_check');
102
- });
103
-
104
- it('has correct auth levels', () => {
105
- expect(ops.get('loop_start')!.auth).toBe('write');
106
- expect(ops.get('loop_iterate')!.auth).toBe('write');
107
- expect(ops.get('loop_iterate_gate')!.auth).toBe('write');
108
- expect(ops.get('loop_status')!.auth).toBe('read');
109
- expect(ops.get('loop_cancel')!.auth).toBe('write');
110
- expect(ops.get('loop_history')!.auth).toBe('read');
111
- expect(ops.get('loop_is_active')!.auth).toBe('read');
112
- expect(ops.get('loop_complete')!.auth).toBe('write');
113
- expect(ops.get('loop_anomaly_check')!.auth).toBe('read');
114
- });
115
-
116
90
  // ─── loop_start ────────────────────────────────────────────────
117
91
 
118
92
  it('loop_start creates a loop with defaults', async () => {
@@ -30,24 +30,6 @@ describe('memory-facade', () => {
30
30
  vault.close();
31
31
  });
32
32
 
33
- it('registers base + extra + cross-project ops', () => {
34
- // 4 base + 18 extra + 3 cross-project = 25
35
- expect(ops.size).toBeGreaterThanOrEqual(25);
36
- expect([...ops.keys()]).toContain('memory_search');
37
- expect([...ops.keys()]).toContain('memory_capture');
38
- expect([...ops.keys()]).toContain('memory_list');
39
- expect([...ops.keys()]).toContain('session_capture');
40
- expect([...ops.keys()]).toContain('memory_delete');
41
- expect([...ops.keys()]).toContain('memory_promote_to_global');
42
- });
43
-
44
- it('has correct auth levels for base ops', () => {
45
- expect(ops.get('memory_search')!.auth).toBe('read');
46
- expect(ops.get('memory_capture')!.auth).toBe('write');
47
- expect(ops.get('memory_list')!.auth).toBe('read');
48
- expect(ops.get('session_capture')!.auth).toBe('write');
49
- });
50
-
51
33
  // ─── memory_capture ────────────────────────────────────────────
52
34
 
53
35
  it('memory_capture stores a memory', async () => {
@@ -60,21 +60,37 @@ export function createMemoryFacadeOps(runtime: AgentRuntime): OpDefinition[] {
60
60
  name: 'memory_capture',
61
61
  description: 'Capture a memory — session summary, lesson learned, or preference.',
62
62
  auth: 'write',
63
- schema: z.object({
64
- projectPath: z.string(),
65
- type: z.enum(['session', 'lesson', 'preference']),
66
- context: z.string(),
67
- summary: z.string(),
68
- topics: z.array(z.string()).optional().default([]),
69
- filesModified: z.array(z.string()).optional().default([]),
70
- toolsUsed: z.array(z.string()).optional().default([]),
71
- }),
63
+ schema: z
64
+ .object({
65
+ projectPath: z.string().optional().default('.'),
66
+ type: z
67
+ .enum(['session', 'lesson', 'preference'])
68
+ .optional()
69
+ .default('lesson')
70
+ .describe('Memory type: session | lesson | preference (default: "lesson")'),
71
+ context: z.string().optional().describe('What was happening — situation or task context'),
72
+ summary: z.string().optional().describe('What was learned or decided'),
73
+ content: z
74
+ .string()
75
+ .optional()
76
+ .describe('Alias: sets both context and summary when neither is provided'),
77
+ topics: z.array(z.string()).optional().default([]),
78
+ filesModified: z.array(z.string()).optional().default([]),
79
+ toolsUsed: z.array(z.string()).optional().default([]),
80
+ })
81
+ .refine(
82
+ (v) => v.context !== undefined || v.summary !== undefined || v.content !== undefined,
83
+ {
84
+ message: 'Provide at least one of: context, summary, or content',
85
+ },
86
+ ),
72
87
  handler: async (params) => {
88
+ const rawContent = params.content as string | undefined;
73
89
  const memory = vault.captureMemory({
74
90
  projectPath: params.projectPath as string,
75
91
  type: params.type as 'session' | 'lesson' | 'preference',
76
- context: params.context as string,
77
- summary: params.summary as string,
92
+ context: (params.context as string | undefined) ?? rawContent ?? '',
93
+ summary: (params.summary as string | undefined) ?? rawContent ?? '',
78
94
  topics: (params.topics as string[]) ?? [],
79
95
  filesModified: (params.filesModified as string[]) ?? [],
80
96
  toolsUsed: (params.toolsUsed as string[]) ?? [],
@@ -41,37 +41,6 @@ describe('operator-facade (colocated)', () => {
41
41
  vault.close();
42
42
  });
43
43
 
44
- it('registers all 10 ops', () => {
45
- expect(ops.size).toBe(10);
46
- expect([...ops.keys()]).toEqual(
47
- expect.arrayContaining([
48
- 'profile_get',
49
- 'profile_update_section',
50
- 'profile_correct',
51
- 'profile_delete',
52
- 'profile_export',
53
- 'signal_accumulate',
54
- 'signal_list',
55
- 'signal_stats',
56
- 'synthesis_check',
57
- 'profile_snapshot',
58
- ]),
59
- );
60
- });
61
-
62
- it('has correct auth levels', () => {
63
- expect(ops.get('profile_get')!.auth).toBe('read');
64
- expect(ops.get('profile_update_section')!.auth).toBe('write');
65
- expect(ops.get('profile_correct')!.auth).toBe('write');
66
- expect(ops.get('profile_delete')!.auth).toBe('admin');
67
- expect(ops.get('profile_export')!.auth).toBe('read');
68
- expect(ops.get('signal_accumulate')!.auth).toBe('write');
69
- expect(ops.get('signal_list')!.auth).toBe('read');
70
- expect(ops.get('signal_stats')!.auth).toBe('read');
71
- expect(ops.get('synthesis_check')!.auth).toBe('read');
72
- expect(ops.get('profile_snapshot')!.auth).toBe('write');
73
- });
74
-
75
44
  // ─── profile_get ───────────────────────────────────────────────
76
45
 
77
46
  it('profile_get returns null when no profile', async () => {
@@ -62,27 +62,6 @@ describe('orchestrate-facade', () => {
62
62
  vault.close();
63
63
  });
64
64
 
65
- it('registers session_start + satellite ops', () => {
66
- expect(ops.size).toBeGreaterThanOrEqual(20);
67
- expect([...ops.keys()]).toContain('session_start');
68
- expect([...ops.keys()]).toContain('orchestrate_plan');
69
- expect([...ops.keys()]).toContain('orchestrate_execute');
70
- expect([...ops.keys()]).toContain('orchestrate_complete');
71
- expect([...ops.keys()]).toContain('orchestrate_status');
72
- expect([...ops.keys()]).toContain('orchestrate_quick_capture');
73
- expect([...ops.keys()]).toContain('project_get');
74
- expect([...ops.keys()]).toContain('project_list');
75
- expect([...ops.keys()]).toContain('playbook_list');
76
- });
77
-
78
- it('has correct auth levels', () => {
79
- expect(ops.get('session_start')!.auth).toBe('write');
80
- expect(ops.get('orchestrate_plan')!.auth).toBe('write');
81
- expect(ops.get('orchestrate_status')!.auth).toBe('read');
82
- expect(ops.get('project_get')!.auth).toBe('read');
83
- expect(ops.get('project_list')!.auth).toBe('read');
84
- });
85
-
86
65
  // ─── session_start ─────────────────────────────────────────────
87
66
 
88
67
  it('session_start registers project and returns stats', async () => {
@@ -120,6 +120,18 @@ export function createOrchestrateFacadeOps(runtime: AgentRuntime): OpDefinition[
120
120
  /* dream module not available — skip silently */
121
121
  }
122
122
 
123
+ // Auto-reap stale worktrees — best-effort, non-blocking
124
+ try {
125
+ const { worktreeReap } = await import('../../utils/worktree-reaper.js');
126
+ Promise.resolve()
127
+ .then(() => worktreeReap(projectPath))
128
+ .catch(() => {
129
+ /* best-effort */
130
+ });
131
+ } catch {
132
+ /* worktree-reaper not available — skip silently */
133
+ }
134
+
123
135
  // ─── Pre-flight manifest ───────────────────────────────
124
136
  let skills: string[] = [];
125
137
  try {
@@ -48,26 +48,6 @@ describe('plan-facade', () => {
48
48
  vault.close();
49
49
  });
50
50
 
51
- it('registers base + extra + grading + chain ops', () => {
52
- // 5 base + 22 extra + 5 grading + 5 chain = 37
53
- expect(ops.size).toBeGreaterThanOrEqual(32);
54
- expect([...ops.keys()]).toContain('create_plan');
55
- expect([...ops.keys()]).toContain('get_plan');
56
- expect([...ops.keys()]).toContain('approve_plan');
57
- expect([...ops.keys()]).toContain('update_task');
58
- expect([...ops.keys()]).toContain('complete_plan');
59
- expect([...ops.keys()]).toContain('plan_grade');
60
- expect([...ops.keys()]).toContain('chain_execute');
61
- });
62
-
63
- it('has correct auth levels for base ops', () => {
64
- expect(ops.get('create_plan')!.auth).toBe('write');
65
- expect(ops.get('get_plan')!.auth).toBe('read');
66
- expect(ops.get('approve_plan')!.auth).toBe('write');
67
- expect(ops.get('update_task')!.auth).toBe('write');
68
- expect(ops.get('complete_plan')!.auth).toBe('write');
69
- });
70
-
71
51
  // ─── create_plan ───────────────────────────────────────────────
72
52
 
73
53
  it('create_plan creates a draft plan', async () => {
@@ -91,7 +71,7 @@ describe('plan-facade', () => {
91
71
  });
92
72
  expect(result.success).toBe(true);
93
73
  const plan = (result.data as Record<string, unknown>).plan as Record<string, unknown>;
94
- expect((plan.tasks as unknown[]).length).toBe(1);
74
+ expect((plan.tasks as unknown[]).length).toBeGreaterThanOrEqual(1);
95
75
  });
96
76
 
97
77
  // ─── get_plan ──────────────────────────────────────────────────
@@ -366,11 +346,11 @@ describe('plan-facade', () => {
366
346
  vaultEntryIds: string[];
367
347
  };
368
348
  expect(data.created).toBe(true);
369
- expect(data.vaultEntryIds.length).toBeGreaterThan(0);
349
+ expect(data.vaultEntryIds).toHaveLength(1); // exactly one seeded entry matches
370
350
  // Decisions should contain vault pattern references with entryId markers
371
351
  const decisions = data.plan.decisions as string[];
372
352
  const vaultDecisions = decisions.filter((d) => d.startsWith('Vault pattern:'));
373
- expect(vaultDecisions.length).toBeGreaterThan(0);
353
+ expect(vaultDecisions).toHaveLength(1); // one vault entry injected one decision
374
354
  // Each vault decision should have an [entryId:...] marker for brain feedback
375
355
  for (const vd of vaultDecisions) {
376
356
  expect(vd).toMatch(/\[entryId:[^\]]+\]/);
@@ -413,19 +393,14 @@ describe('plan-facade', () => {
413
393
  const decisions = data.plan.decisions as string[];
414
394
  // User decision preserved
415
395
  expect(decisions).toContain('Use vitest as test runner');
416
- // Vault enrichment added
417
- if (data.vaultEntryIds.length > 0) {
418
- const vaultDecisions = decisions.filter((d) => d.startsWith('Vault pattern:'));
419
- expect(vaultDecisions.length).toBeGreaterThan(0);
420
- }
396
+ // Vault enrichment added — one seeded entry matches the 'testing' query
397
+ expect(data.vaultEntryIds).toHaveLength(1);
398
+ const vaultDecisions = decisions.filter((d) => d.startsWith('Vault pattern:'));
399
+ expect(vaultDecisions).toHaveLength(1);
421
400
  });
422
401
 
423
402
  // ─── plan_close_stale ─────────────────────────────────────────
424
403
 
425
- it('plan_close_stale op is registered', () => {
426
- expect([...ops.keys()]).toContain('plan_close_stale');
427
- });
428
-
429
404
  it('plan_close_stale returns no plans when none are stale', async () => {
430
405
  const result = await executeOp(ops, 'plan_close_stale', {});
431
406
  expect(result.success).toBe(true);