@soleri/core 2.4.0 → 2.6.0

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 (328) hide show
  1. package/dist/brain/brain.d.ts +7 -0
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +56 -9
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/intelligence.d.ts +1 -0
  6. package/dist/brain/intelligence.d.ts.map +1 -1
  7. package/dist/brain/intelligence.js +164 -148
  8. package/dist/brain/intelligence.js.map +1 -1
  9. package/dist/brain/types.d.ts +2 -2
  10. package/dist/brain/types.d.ts.map +1 -1
  11. package/dist/cognee/client.d.ts +3 -0
  12. package/dist/cognee/client.d.ts.map +1 -1
  13. package/dist/cognee/client.js +17 -0
  14. package/dist/cognee/client.js.map +1 -1
  15. package/dist/cognee/sync-manager.d.ts +94 -0
  16. package/dist/cognee/sync-manager.d.ts.map +1 -0
  17. package/dist/cognee/sync-manager.js +293 -0
  18. package/dist/cognee/sync-manager.js.map +1 -0
  19. package/dist/control/identity-manager.d.ts +3 -1
  20. package/dist/control/identity-manager.d.ts.map +1 -1
  21. package/dist/control/identity-manager.js +49 -51
  22. package/dist/control/identity-manager.js.map +1 -1
  23. package/dist/control/intent-router.d.ts +1 -0
  24. package/dist/control/intent-router.d.ts.map +1 -1
  25. package/dist/control/intent-router.js +32 -32
  26. package/dist/control/intent-router.js.map +1 -1
  27. package/dist/curator/curator.d.ts +9 -1
  28. package/dist/curator/curator.d.ts.map +1 -1
  29. package/dist/curator/curator.js +104 -92
  30. package/dist/curator/curator.js.map +1 -1
  31. package/dist/errors/classify.d.ts +13 -0
  32. package/dist/errors/classify.d.ts.map +1 -0
  33. package/dist/errors/classify.js +97 -0
  34. package/dist/errors/classify.js.map +1 -0
  35. package/dist/errors/index.d.ts +6 -0
  36. package/dist/errors/index.d.ts.map +1 -0
  37. package/dist/errors/index.js +4 -0
  38. package/dist/errors/index.js.map +1 -0
  39. package/dist/errors/retry.d.ts +40 -0
  40. package/dist/errors/retry.d.ts.map +1 -0
  41. package/dist/errors/retry.js +97 -0
  42. package/dist/errors/retry.js.map +1 -0
  43. package/dist/errors/types.d.ts +48 -0
  44. package/dist/errors/types.d.ts.map +1 -0
  45. package/dist/errors/types.js +59 -0
  46. package/dist/errors/types.js.map +1 -0
  47. package/dist/governance/governance.d.ts +1 -0
  48. package/dist/governance/governance.d.ts.map +1 -1
  49. package/dist/governance/governance.js +51 -68
  50. package/dist/governance/governance.js.map +1 -1
  51. package/dist/index.d.ts +26 -5
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +22 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/intake/content-classifier.d.ts +14 -0
  56. package/dist/intake/content-classifier.d.ts.map +1 -0
  57. package/dist/intake/content-classifier.js +125 -0
  58. package/dist/intake/content-classifier.js.map +1 -0
  59. package/dist/intake/dedup-gate.d.ts +17 -0
  60. package/dist/intake/dedup-gate.d.ts.map +1 -0
  61. package/dist/intake/dedup-gate.js +66 -0
  62. package/dist/intake/dedup-gate.js.map +1 -0
  63. package/dist/intake/intake-pipeline.d.ts +63 -0
  64. package/dist/intake/intake-pipeline.d.ts.map +1 -0
  65. package/dist/intake/intake-pipeline.js +373 -0
  66. package/dist/intake/intake-pipeline.js.map +1 -0
  67. package/dist/intake/types.d.ts +65 -0
  68. package/dist/intake/types.d.ts.map +1 -0
  69. package/dist/intake/types.js +3 -0
  70. package/dist/intake/types.js.map +1 -0
  71. package/dist/intelligence/loader.js +1 -1
  72. package/dist/intelligence/loader.js.map +1 -1
  73. package/dist/intelligence/types.d.ts +3 -1
  74. package/dist/intelligence/types.d.ts.map +1 -1
  75. package/dist/loop/loop-manager.d.ts +58 -7
  76. package/dist/loop/loop-manager.d.ts.map +1 -1
  77. package/dist/loop/loop-manager.js +280 -6
  78. package/dist/loop/loop-manager.js.map +1 -1
  79. package/dist/loop/types.d.ts +69 -1
  80. package/dist/loop/types.d.ts.map +1 -1
  81. package/dist/loop/types.js +4 -1
  82. package/dist/loop/types.js.map +1 -1
  83. package/dist/persistence/index.d.ts +4 -0
  84. package/dist/persistence/index.d.ts.map +1 -0
  85. package/dist/persistence/index.js +3 -0
  86. package/dist/persistence/index.js.map +1 -0
  87. package/dist/persistence/postgres-provider.d.ts +46 -0
  88. package/dist/persistence/postgres-provider.d.ts.map +1 -0
  89. package/dist/persistence/postgres-provider.js +115 -0
  90. package/dist/persistence/postgres-provider.js.map +1 -0
  91. package/dist/persistence/sqlite-provider.d.ts +28 -0
  92. package/dist/persistence/sqlite-provider.d.ts.map +1 -0
  93. package/dist/persistence/sqlite-provider.js +97 -0
  94. package/dist/persistence/sqlite-provider.js.map +1 -0
  95. package/dist/persistence/types.d.ts +58 -0
  96. package/dist/persistence/types.d.ts.map +1 -0
  97. package/dist/persistence/types.js +8 -0
  98. package/dist/persistence/types.js.map +1 -0
  99. package/dist/planning/gap-analysis.d.ts +47 -4
  100. package/dist/planning/gap-analysis.d.ts.map +1 -1
  101. package/dist/planning/gap-analysis.js +190 -13
  102. package/dist/planning/gap-analysis.js.map +1 -1
  103. package/dist/planning/gap-types.d.ts +1 -1
  104. package/dist/planning/gap-types.d.ts.map +1 -1
  105. package/dist/planning/gap-types.js.map +1 -1
  106. package/dist/planning/planner.d.ts +277 -9
  107. package/dist/planning/planner.d.ts.map +1 -1
  108. package/dist/planning/planner.js +611 -46
  109. package/dist/planning/planner.js.map +1 -1
  110. package/dist/playbooks/generic/brainstorming.d.ts +9 -0
  111. package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
  112. package/dist/playbooks/generic/brainstorming.js +105 -0
  113. package/dist/playbooks/generic/brainstorming.js.map +1 -0
  114. package/dist/playbooks/generic/code-review.d.ts +11 -0
  115. package/dist/playbooks/generic/code-review.d.ts.map +1 -0
  116. package/dist/playbooks/generic/code-review.js +176 -0
  117. package/dist/playbooks/generic/code-review.js.map +1 -0
  118. package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
  119. package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
  120. package/dist/playbooks/generic/subagent-execution.js +68 -0
  121. package/dist/playbooks/generic/subagent-execution.js.map +1 -0
  122. package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
  123. package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
  124. package/dist/playbooks/generic/systematic-debugging.js +87 -0
  125. package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
  126. package/dist/playbooks/generic/tdd.d.ts +9 -0
  127. package/dist/playbooks/generic/tdd.d.ts.map +1 -0
  128. package/dist/playbooks/generic/tdd.js +70 -0
  129. package/dist/playbooks/generic/tdd.js.map +1 -0
  130. package/dist/playbooks/generic/verification.d.ts +9 -0
  131. package/dist/playbooks/generic/verification.d.ts.map +1 -0
  132. package/dist/playbooks/generic/verification.js +74 -0
  133. package/dist/playbooks/generic/verification.js.map +1 -0
  134. package/dist/playbooks/index.d.ts +4 -0
  135. package/dist/playbooks/index.d.ts.map +1 -0
  136. package/dist/playbooks/index.js +5 -0
  137. package/dist/playbooks/index.js.map +1 -0
  138. package/dist/playbooks/playbook-registry.d.ts +42 -0
  139. package/dist/playbooks/playbook-registry.d.ts.map +1 -0
  140. package/dist/playbooks/playbook-registry.js +227 -0
  141. package/dist/playbooks/playbook-registry.js.map +1 -0
  142. package/dist/playbooks/playbook-seeder.d.ts +47 -0
  143. package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
  144. package/dist/playbooks/playbook-seeder.js +104 -0
  145. package/dist/playbooks/playbook-seeder.js.map +1 -0
  146. package/dist/playbooks/playbook-types.d.ts +132 -0
  147. package/dist/playbooks/playbook-types.d.ts.map +1 -0
  148. package/dist/playbooks/playbook-types.js +12 -0
  149. package/dist/playbooks/playbook-types.js.map +1 -0
  150. package/dist/project/project-registry.d.ts +4 -4
  151. package/dist/project/project-registry.d.ts.map +1 -1
  152. package/dist/project/project-registry.js +30 -57
  153. package/dist/project/project-registry.js.map +1 -1
  154. package/dist/prompts/index.d.ts +4 -0
  155. package/dist/prompts/index.d.ts.map +1 -0
  156. package/dist/prompts/index.js +3 -0
  157. package/dist/prompts/index.js.map +1 -0
  158. package/dist/prompts/parser.d.ts +17 -0
  159. package/dist/prompts/parser.d.ts.map +1 -0
  160. package/dist/prompts/parser.js +47 -0
  161. package/dist/prompts/parser.js.map +1 -0
  162. package/dist/prompts/template-manager.d.ts +25 -0
  163. package/dist/prompts/template-manager.d.ts.map +1 -0
  164. package/dist/prompts/template-manager.js +71 -0
  165. package/dist/prompts/template-manager.js.map +1 -0
  166. package/dist/prompts/types.d.ts +26 -0
  167. package/dist/prompts/types.d.ts.map +1 -0
  168. package/dist/prompts/types.js +5 -0
  169. package/dist/prompts/types.js.map +1 -0
  170. package/dist/runtime/admin-extra-ops.d.ts +5 -3
  171. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  172. package/dist/runtime/admin-extra-ops.js +348 -11
  173. package/dist/runtime/admin-extra-ops.js.map +1 -1
  174. package/dist/runtime/admin-ops.d.ts.map +1 -1
  175. package/dist/runtime/admin-ops.js +10 -3
  176. package/dist/runtime/admin-ops.js.map +1 -1
  177. package/dist/runtime/capture-ops.d.ts.map +1 -1
  178. package/dist/runtime/capture-ops.js +20 -2
  179. package/dist/runtime/capture-ops.js.map +1 -1
  180. package/dist/runtime/cognee-sync-ops.d.ts +12 -0
  181. package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
  182. package/dist/runtime/cognee-sync-ops.js +55 -0
  183. package/dist/runtime/cognee-sync-ops.js.map +1 -0
  184. package/dist/runtime/core-ops.d.ts +8 -6
  185. package/dist/runtime/core-ops.d.ts.map +1 -1
  186. package/dist/runtime/core-ops.js +226 -9
  187. package/dist/runtime/core-ops.js.map +1 -1
  188. package/dist/runtime/curator-extra-ops.d.ts +2 -2
  189. package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
  190. package/dist/runtime/curator-extra-ops.js +15 -3
  191. package/dist/runtime/curator-extra-ops.js.map +1 -1
  192. package/dist/runtime/domain-ops.js +2 -2
  193. package/dist/runtime/domain-ops.js.map +1 -1
  194. package/dist/runtime/grading-ops.d.ts.map +1 -1
  195. package/dist/runtime/grading-ops.js.map +1 -1
  196. package/dist/runtime/intake-ops.d.ts +14 -0
  197. package/dist/runtime/intake-ops.d.ts.map +1 -0
  198. package/dist/runtime/intake-ops.js +110 -0
  199. package/dist/runtime/intake-ops.js.map +1 -0
  200. package/dist/runtime/loop-ops.d.ts +5 -4
  201. package/dist/runtime/loop-ops.d.ts.map +1 -1
  202. package/dist/runtime/loop-ops.js +84 -12
  203. package/dist/runtime/loop-ops.js.map +1 -1
  204. package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -1
  205. package/dist/runtime/memory-cross-project-ops.js.map +1 -1
  206. package/dist/runtime/memory-extra-ops.js +5 -5
  207. package/dist/runtime/memory-extra-ops.js.map +1 -1
  208. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  209. package/dist/runtime/orchestrate-ops.js +8 -2
  210. package/dist/runtime/orchestrate-ops.js.map +1 -1
  211. package/dist/runtime/planning-extra-ops.d.ts +13 -5
  212. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  213. package/dist/runtime/planning-extra-ops.js +381 -18
  214. package/dist/runtime/planning-extra-ops.js.map +1 -1
  215. package/dist/runtime/playbook-ops.d.ts +14 -0
  216. package/dist/runtime/playbook-ops.d.ts.map +1 -0
  217. package/dist/runtime/playbook-ops.js +141 -0
  218. package/dist/runtime/playbook-ops.js.map +1 -0
  219. package/dist/runtime/project-ops.d.ts.map +1 -1
  220. package/dist/runtime/project-ops.js +7 -2
  221. package/dist/runtime/project-ops.js.map +1 -1
  222. package/dist/runtime/runtime.d.ts.map +1 -1
  223. package/dist/runtime/runtime.js +28 -9
  224. package/dist/runtime/runtime.js.map +1 -1
  225. package/dist/runtime/types.d.ts +8 -0
  226. package/dist/runtime/types.d.ts.map +1 -1
  227. package/dist/runtime/vault-extra-ops.d.ts +4 -2
  228. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  229. package/dist/runtime/vault-extra-ops.js +383 -4
  230. package/dist/runtime/vault-extra-ops.js.map +1 -1
  231. package/dist/vault/playbook.d.ts +34 -0
  232. package/dist/vault/playbook.d.ts.map +1 -0
  233. package/dist/vault/playbook.js +60 -0
  234. package/dist/vault/playbook.js.map +1 -0
  235. package/dist/vault/vault.d.ts +52 -32
  236. package/dist/vault/vault.d.ts.map +1 -1
  237. package/dist/vault/vault.js +300 -181
  238. package/dist/vault/vault.js.map +1 -1
  239. package/package.json +9 -3
  240. package/src/__tests__/admin-extra-ops.test.ts +62 -15
  241. package/src/__tests__/admin-ops.test.ts +2 -2
  242. package/src/__tests__/brain.test.ts +3 -3
  243. package/src/__tests__/cognee-integration.test.ts +80 -0
  244. package/src/__tests__/cognee-sync-manager.test.ts +103 -0
  245. package/src/__tests__/core-ops.test.ts +36 -4
  246. package/src/__tests__/curator-extra-ops.test.ts +24 -2
  247. package/src/__tests__/errors.test.ts +388 -0
  248. package/src/__tests__/grading-ops.test.ts +28 -7
  249. package/src/__tests__/intake-pipeline.test.ts +162 -0
  250. package/src/__tests__/loop-ops.test.ts +74 -3
  251. package/src/__tests__/memory-cross-project-ops.test.ts +3 -1
  252. package/src/__tests__/orchestrate-ops.test.ts +8 -3
  253. package/src/__tests__/persistence.test.ts +291 -0
  254. package/src/__tests__/planner.test.ts +99 -21
  255. package/src/__tests__/planning-extra-ops.test.ts +168 -10
  256. package/src/__tests__/playbook-registry.test.ts +326 -0
  257. package/src/__tests__/playbook-seeder.test.ts +163 -0
  258. package/src/__tests__/playbook.test.ts +389 -0
  259. package/src/__tests__/postgres-provider.test.ts +58 -0
  260. package/src/__tests__/project-ops.test.ts +18 -4
  261. package/src/__tests__/template-manager.test.ts +222 -0
  262. package/src/__tests__/vault-extra-ops.test.ts +82 -7
  263. package/src/__tests__/vault.test.ts +184 -0
  264. package/src/brain/brain.ts +71 -9
  265. package/src/brain/intelligence.ts +258 -307
  266. package/src/brain/types.ts +2 -2
  267. package/src/cognee/client.ts +18 -0
  268. package/src/cognee/sync-manager.ts +389 -0
  269. package/src/control/identity-manager.ts +77 -75
  270. package/src/control/intent-router.ts +55 -57
  271. package/src/curator/curator.ts +199 -139
  272. package/src/errors/classify.ts +102 -0
  273. package/src/errors/index.ts +5 -0
  274. package/src/errors/retry.ts +132 -0
  275. package/src/errors/types.ts +81 -0
  276. package/src/governance/governance.ts +90 -107
  277. package/src/index.ts +116 -3
  278. package/src/intake/content-classifier.ts +146 -0
  279. package/src/intake/dedup-gate.ts +92 -0
  280. package/src/intake/intake-pipeline.ts +503 -0
  281. package/src/intake/types.ts +69 -0
  282. package/src/intelligence/loader.ts +1 -1
  283. package/src/intelligence/types.ts +3 -1
  284. package/src/loop/loop-manager.ts +325 -7
  285. package/src/loop/types.ts +72 -1
  286. package/src/persistence/index.ts +9 -0
  287. package/src/persistence/postgres-provider.ts +157 -0
  288. package/src/persistence/sqlite-provider.ts +115 -0
  289. package/src/persistence/types.ts +74 -0
  290. package/src/planning/gap-analysis.ts +286 -17
  291. package/src/planning/gap-types.ts +4 -1
  292. package/src/planning/planner.ts +828 -55
  293. package/src/playbooks/generic/brainstorming.ts +110 -0
  294. package/src/playbooks/generic/code-review.ts +181 -0
  295. package/src/playbooks/generic/subagent-execution.ts +74 -0
  296. package/src/playbooks/generic/systematic-debugging.ts +92 -0
  297. package/src/playbooks/generic/tdd.ts +75 -0
  298. package/src/playbooks/generic/verification.ts +79 -0
  299. package/src/playbooks/index.ts +27 -0
  300. package/src/playbooks/playbook-registry.ts +284 -0
  301. package/src/playbooks/playbook-seeder.ts +119 -0
  302. package/src/playbooks/playbook-types.ts +162 -0
  303. package/src/project/project-registry.ts +81 -74
  304. package/src/prompts/index.ts +3 -0
  305. package/src/prompts/parser.ts +59 -0
  306. package/src/prompts/template-manager.ts +77 -0
  307. package/src/prompts/types.ts +28 -0
  308. package/src/runtime/admin-extra-ops.ts +391 -13
  309. package/src/runtime/admin-ops.ts +17 -6
  310. package/src/runtime/capture-ops.ts +25 -6
  311. package/src/runtime/cognee-sync-ops.ts +63 -0
  312. package/src/runtime/core-ops.ts +258 -8
  313. package/src/runtime/curator-extra-ops.ts +17 -3
  314. package/src/runtime/domain-ops.ts +2 -2
  315. package/src/runtime/grading-ops.ts +11 -2
  316. package/src/runtime/intake-ops.ts +126 -0
  317. package/src/runtime/loop-ops.ts +96 -13
  318. package/src/runtime/memory-cross-project-ops.ts +1 -2
  319. package/src/runtime/memory-extra-ops.ts +5 -5
  320. package/src/runtime/orchestrate-ops.ts +8 -2
  321. package/src/runtime/planning-extra-ops.ts +414 -23
  322. package/src/runtime/playbook-ops.ts +169 -0
  323. package/src/runtime/project-ops.ts +9 -3
  324. package/src/runtime/runtime.ts +36 -10
  325. package/src/runtime/types.ts +8 -0
  326. package/src/runtime/vault-extra-ops.ts +425 -4
  327. package/src/vault/playbook.ts +87 -0
  328. package/src/vault/vault.ts +419 -235
@@ -1,21 +1,31 @@
1
1
  /**
2
- * Extended planning operations — 9 ops for advanced plan lifecycle management.
2
+ * Extended planning operations — 22 ops for advanced plan lifecycle management.
3
3
  *
4
4
  * These complement the 5 basic planning ops in core-ops.ts with:
5
5
  * iteration, splitting, reconciliation, lifecycle completion,
6
- * dispatch, review, archival, task listing, and statistics.
6
+ * dispatch, review, archival, task listing, statistics,
7
+ * evidence submission, verification, validation, auto-reconciliation,
8
+ * review prompt generation, brainstorming, execution metrics,
9
+ * deliverable submission, and deliverable verification.
7
10
  */
8
11
 
9
12
  import { z } from 'zod';
10
13
  import type { OpDefinition } from '../facades/types.js';
11
14
  import type { AgentRuntime } from './types.js';
12
- import type { DriftItem } from '../planning/planner.js';
15
+ import type { DriftItem, TaskEvidence } from '../planning/planner.js';
16
+ import { matchPlaybooks, type PlaybookMatchResult } from '../playbooks/index.js';
17
+ import { entryToPlaybookDefinition } from '../playbooks/index.js';
13
18
 
14
19
  /**
15
- * Create 9 extended planning operations for an agent runtime.
20
+ * Create 22 extended planning operations for an agent runtime.
16
21
  *
17
- * Groups: mutation (plan_iterate, plan_split, plan_reconcile, plan_complete_lifecycle,
18
- * plan_review, plan_archive), query (plan_dispatch, plan_list_tasks, plan_stats).
22
+ * Groups:
23
+ * mutation: plan_iterate, plan_split, plan_reconcile, plan_complete_lifecycle,
24
+ * plan_review, plan_archive, plan_submit_evidence, plan_auto_reconcile,
25
+ * plan_review_outcome, plan_record_task_metrics, plan_submit_deliverable
26
+ * query: plan_dispatch, plan_list_tasks, plan_stats, plan_verify_task,
27
+ * plan_verify_plan, plan_validate, plan_review_spec, plan_review_quality,
28
+ * plan_brainstorm, plan_execution_metrics, plan_verify_deliverables
19
29
  */
20
30
  export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
21
31
  const { planner, vault } = runtime;
@@ -31,15 +41,15 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
31
41
  planId: z.string().describe('ID of the draft plan to iterate on'),
32
42
  objective: z.string().optional().describe('New objective (replaces existing)'),
33
43
  scope: z.string().optional().describe('New scope (replaces existing)'),
34
- decisions: z.array(z.string()).optional().describe('New decisions list (replaces existing)'),
44
+ decisions: z
45
+ .array(z.string())
46
+ .optional()
47
+ .describe('New decisions list (replaces existing)'),
35
48
  addTasks: z
36
49
  .array(z.object({ title: z.string(), description: z.string() }))
37
50
  .optional()
38
51
  .describe('Tasks to append'),
39
- removeTasks: z
40
- .array(z.string())
41
- .optional()
42
- .describe('Task IDs to remove'),
52
+ removeTasks: z.array(z.string()).optional().describe('Task IDs to remove'),
43
53
  }),
44
54
  handler: async (params) => {
45
55
  try {
@@ -135,10 +145,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
135
145
  auth: 'write',
136
146
  schema: z.object({
137
147
  planId: z.string().describe('Plan ID (must be completed with reconciliation data)'),
138
- patterns: z
139
- .array(z.string())
140
- .optional()
141
- .describe('Patterns discovered during execution'),
148
+ patterns: z.array(z.string()).optional().describe('Patterns discovered during execution'),
142
149
  antiPatterns: z
143
150
  .array(z.string())
144
151
  .optional()
@@ -208,10 +215,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
208
215
  }),
209
216
  handler: async (params) => {
210
217
  try {
211
- const dispatch = planner.getDispatch(
212
- params.planId as string,
213
- params.taskId as string,
214
- );
218
+ const dispatch = planner.getDispatch(params.planId as string, params.taskId as string);
215
219
  return dispatch;
216
220
  } catch (err) {
217
221
  return { error: (err as Error).message };
@@ -229,9 +233,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
229
233
  planId: z.string().describe('Plan ID to review'),
230
234
  taskId: z.string().optional().describe('Specific task ID (omit to review the whole plan)'),
231
235
  reviewer: z.string().describe('Name or ID of reviewer'),
232
- outcome: z
233
- .enum(['approved', 'rejected', 'needs_changes'])
234
- .describe('Review outcome'),
236
+ outcome: z.enum(['approved', 'rejected', 'needs_changes']).describe('Review outcome'),
235
237
  comments: z.string().describe('Review comments'),
236
238
  }),
237
239
  handler: async (params) => {
@@ -266,7 +268,10 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
266
268
  try {
267
269
  const olderThanDays = (params.olderThanDays as number) ?? 30;
268
270
  const archived = planner.archive(olderThanDays);
269
- return { archived: archived.length, plans: archived.map((p) => ({ id: p.id, objective: p.objective })) };
271
+ return {
272
+ archived: archived.length,
273
+ plans: archived.map((p) => ({ id: p.id, objective: p.objective })),
274
+ };
270
275
  } catch (err) {
271
276
  return { error: (err as Error).message };
272
277
  }
@@ -323,5 +328,391 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
323
328
  }
324
329
  },
325
330
  },
331
+
332
+ // ─── Evidence Submission (#148) ──────────────────────────────
333
+ {
334
+ name: 'plan_submit_evidence',
335
+ description:
336
+ 'Submit command output evidence for a task acceptance criterion. Makes playbook verification gates enforceable.',
337
+ auth: 'write',
338
+ schema: z.object({
339
+ planId: z.string().describe('Plan ID'),
340
+ taskId: z.string().describe('Task ID to submit evidence for'),
341
+ criterion: z.string().describe('Which acceptance criterion this evidence satisfies'),
342
+ content: z
343
+ .string()
344
+ .describe('Evidence content — command output, URL, file path, or description'),
345
+ type: z.enum(['command_output', 'url', 'file', 'description']).describe('Evidence type'),
346
+ }),
347
+ handler: async (params) => {
348
+ try {
349
+ const task = planner.submitEvidence(params.planId as string, params.taskId as string, {
350
+ criterion: params.criterion as string,
351
+ content: params.content as string,
352
+ type: params.type as TaskEvidence['type'],
353
+ });
354
+ return {
355
+ submitted: true,
356
+ taskId: task.id,
357
+ evidenceCount: task.evidence?.length ?? 0,
358
+ };
359
+ } catch (err) {
360
+ return { error: (err as Error).message };
361
+ }
362
+ },
363
+ },
364
+
365
+ // ─── Verify Task (#148) ─────────────────────────────────────
366
+ {
367
+ name: 'plan_verify_task',
368
+ description:
369
+ 'Check task evidence submitted + reviews passed → mark verified. Returns verification status with details.',
370
+ auth: 'read',
371
+ schema: z.object({
372
+ planId: z.string().describe('Plan ID'),
373
+ taskId: z.string().describe('Task ID to verify'),
374
+ }),
375
+ handler: async (params) => {
376
+ try {
377
+ return planner.verifyTask(params.planId as string, params.taskId as string);
378
+ } catch (err) {
379
+ return { error: (err as Error).message };
380
+ }
381
+ },
382
+ },
383
+
384
+ // ─── Verify Plan (#148) ─────────────────────────────────────
385
+ {
386
+ name: 'plan_verify_plan',
387
+ description:
388
+ 'Check all tasks verified → plan is ready for reconciliation. Returns validation status with per-task issues.',
389
+ auth: 'read',
390
+ schema: z.object({
391
+ planId: z.string().describe('Plan ID to verify'),
392
+ }),
393
+ handler: async (params) => {
394
+ try {
395
+ return planner.verifyPlan(params.planId as string);
396
+ } catch (err) {
397
+ return { error: (err as Error).message };
398
+ }
399
+ },
400
+ },
401
+
402
+ // ─── Review Spec (#149) ─────────────────────────────────────
403
+ {
404
+ name: 'plan_review_spec',
405
+ description:
406
+ 'Generate a spec compliance review prompt for a task. Stage 1 of the two-stage subagent review model.',
407
+ auth: 'read',
408
+ schema: z.object({
409
+ planId: z.string().describe('Plan ID'),
410
+ taskId: z.string().describe('Task ID to generate review prompt for'),
411
+ }),
412
+ handler: async (params) => {
413
+ try {
414
+ return planner.generateReviewSpec(params.planId as string, params.taskId as string);
415
+ } catch (err) {
416
+ return { error: (err as Error).message };
417
+ }
418
+ },
419
+ },
420
+
421
+ // ─── Review Quality (#149) ──────────────────────────────────
422
+ {
423
+ name: 'plan_review_quality',
424
+ description:
425
+ 'Generate a code quality review prompt for a task. Stage 2 of the two-stage subagent review model.',
426
+ auth: 'read',
427
+ schema: z.object({
428
+ planId: z.string().describe('Plan ID'),
429
+ taskId: z.string().describe('Task ID to generate review prompt for'),
430
+ }),
431
+ handler: async (params) => {
432
+ try {
433
+ return planner.generateReviewQuality(params.planId as string, params.taskId as string);
434
+ } catch (err) {
435
+ return { error: (err as Error).message };
436
+ }
437
+ },
438
+ },
439
+
440
+ // ─── Review Outcome (#149) ──────────────────────────────────
441
+ {
442
+ name: 'plan_review_outcome',
443
+ description:
444
+ 'Record a subagent review pass/fail result with feedback. Works alongside plan_review for structured review tracking.',
445
+ auth: 'write',
446
+ schema: z.object({
447
+ planId: z.string().describe('Plan ID'),
448
+ taskId: z.string().describe('Task ID being reviewed'),
449
+ reviewType: z
450
+ .enum(['spec', 'quality'])
451
+ .describe('Type of review — spec compliance or code quality'),
452
+ reviewer: z.string().describe('Reviewer identifier (subagent name)'),
453
+ outcome: z.enum(['approved', 'rejected', 'needs_changes']).describe('Review outcome'),
454
+ comments: z.string().describe('Review comments and feedback'),
455
+ }),
456
+ handler: async (params) => {
457
+ try {
458
+ const plan = planner.addReview(params.planId as string, {
459
+ taskId: params.taskId as string,
460
+ reviewer: `${params.reviewType}-review:${params.reviewer}`,
461
+ outcome: params.outcome as 'approved' | 'rejected' | 'needs_changes',
462
+ comments: params.comments as string,
463
+ });
464
+ return {
465
+ recorded: true,
466
+ totalReviews: plan.reviews?.length ?? 0,
467
+ taskId: params.taskId,
468
+ reviewType: params.reviewType,
469
+ outcome: params.outcome,
470
+ };
471
+ } catch (err) {
472
+ return { error: (err as Error).message };
473
+ }
474
+ },
475
+ },
476
+
477
+ // ─── Brainstorm (#150) ──────────────────────────────────────
478
+ {
479
+ name: 'plan_brainstorm',
480
+ description:
481
+ 'Match a playbook for the given intent/text and return its brainstorm sections. ' +
482
+ 'Enforces the brainstorming gate — design must be explored before plan creation.',
483
+ auth: 'read',
484
+ schema: z.object({
485
+ intent: z
486
+ .enum(['BUILD', 'FIX', 'REVIEW', 'PLAN', 'IMPROVE', 'DELIVER'])
487
+ .optional()
488
+ .describe('Detected intent (optional, improves matching)'),
489
+ text: z.string().describe('Task description text to match against playbooks'),
490
+ }),
491
+ handler: async (params) => {
492
+ try {
493
+ // Load vault playbooks for matching
494
+ const vaultEntries = vault.list({ type: 'playbook' });
495
+ const vaultPlaybooks = vaultEntries
496
+ .map((e) => entryToPlaybookDefinition(e))
497
+ .filter((p): p is NonNullable<typeof p> => p !== null);
498
+
499
+ const intent = params.intent as
500
+ | 'BUILD'
501
+ | 'FIX'
502
+ | 'REVIEW'
503
+ | 'PLAN'
504
+ | 'IMPROVE'
505
+ | 'DELIVER'
506
+ | undefined;
507
+ const result: PlaybookMatchResult = matchPlaybooks(
508
+ intent,
509
+ params.text as string,
510
+ vaultPlaybooks,
511
+ );
512
+
513
+ if (!result.playbook) {
514
+ return { matched: false, sections: [], playbook: null };
515
+ }
516
+
517
+ // Gather brainstorm sections from matched playbooks
518
+ const sections = [
519
+ ...(result.playbook.generic?.brainstormSections ?? []),
520
+ ...(result.playbook.domain?.brainstormSections ?? []),
521
+ ];
522
+
523
+ return {
524
+ matched: true,
525
+ label: result.playbook.label,
526
+ genericMatch: result.genericMatch ?? null,
527
+ domainMatch: result.domainMatch ?? null,
528
+ sections,
529
+ gates: result.playbook.mergedGates,
530
+ toolInjections: result.playbook.mergedTools,
531
+ };
532
+ } catch (err) {
533
+ return { error: (err as Error).message };
534
+ }
535
+ },
536
+ },
537
+
538
+ // ─── Auto-Reconcile (#151) ──────────────────────────────────
539
+ {
540
+ name: 'plan_auto_reconcile',
541
+ description:
542
+ 'Automated fast-path reconciliation. Checks task completion status, generates drift report automatically. ' +
543
+ 'Returns null if drift is too significant (>2 non-completed tasks).',
544
+ auth: 'write',
545
+ schema: z.object({
546
+ planId: z.string().describe('Plan ID to auto-reconcile'),
547
+ }),
548
+ handler: async (params) => {
549
+ try {
550
+ const result = planner.autoReconcile(params.planId as string);
551
+ if (!result) {
552
+ return {
553
+ autoReconciled: false,
554
+ reason: 'Drift too significant for auto-reconciliation — use manual plan_reconcile',
555
+ };
556
+ }
557
+ return {
558
+ autoReconciled: true,
559
+ accuracy: result.reconciliation!.accuracy,
560
+ driftCount: result.reconciliation!.driftItems.length,
561
+ plan: result,
562
+ };
563
+ } catch (err) {
564
+ return { error: (err as Error).message };
565
+ }
566
+ },
567
+ },
568
+
569
+ // ─── Validate Plan (#152) ───────────────────────────────────
570
+ {
571
+ name: 'plan_validate',
572
+ description:
573
+ 'Post-execution validation — checks all tasks final, evidence exists for verification tasks, ' +
574
+ 'no tasks stuck in_progress. Run before reconciliation.',
575
+ auth: 'read',
576
+ schema: z.object({
577
+ planId: z.string().describe('Plan ID to validate'),
578
+ }),
579
+ handler: async (params) => {
580
+ try {
581
+ return planner.verifyPlan(params.planId as string);
582
+ } catch (err) {
583
+ return { error: (err as Error).message };
584
+ }
585
+ },
586
+ },
587
+
588
+ // ─── Execution Metrics (#80) ─────────────────────────────────
589
+ {
590
+ name: 'plan_execution_metrics',
591
+ description:
592
+ 'Per-task timing and aggregate execution summary for a plan. Shows duration, status counts, and average task time.',
593
+ auth: 'read',
594
+ schema: z.object({
595
+ planId: z.string().describe('Plan ID to get metrics for'),
596
+ }),
597
+ handler: async (params) => {
598
+ try {
599
+ const plan = planner.get(params.planId as string);
600
+ if (!plan) return { error: `Plan not found: ${params.planId}` };
601
+
602
+ const taskMetrics = plan.tasks.map((t) => ({
603
+ id: t.id,
604
+ title: t.title,
605
+ status: t.status,
606
+ startedAt: t.startedAt ?? null,
607
+ completedAt: t.completedAt ?? null,
608
+ metrics: t.metrics ?? null,
609
+ }));
610
+
611
+ return {
612
+ planId: plan.id,
613
+ status: plan.status,
614
+ executionSummary: plan.executionSummary ?? null,
615
+ taskMetrics,
616
+ };
617
+ } catch (err) {
618
+ return { error: (err as Error).message };
619
+ }
620
+ },
621
+ },
622
+
623
+ // ─── Record Task Metrics (#80) ──────────────────────────────
624
+ {
625
+ name: 'plan_record_task_metrics',
626
+ description:
627
+ 'Record execution metrics for a task — tool calls, model tier, estimated cost. Merges with existing metrics.',
628
+ auth: 'write',
629
+ schema: z.object({
630
+ planId: z.string().describe('Plan ID'),
631
+ taskId: z.string().describe('Task ID to record metrics for'),
632
+ toolCalls: z.number().optional().describe('Number of tool calls made'),
633
+ modelTier: z.string().optional().describe('Model tier used (e.g., "opus", "sonnet")'),
634
+ estimatedCostUsd: z.number().optional().describe('Estimated cost in USD'),
635
+ iterations: z.number().optional().describe('Number of iterations taken'),
636
+ }),
637
+ handler: async (params) => {
638
+ try {
639
+ const plan = planner.get(params.planId as string);
640
+ if (!plan) return { error: `Plan not found: ${params.planId}` };
641
+ const task = plan.tasks.find((t) => t.id === params.taskId);
642
+ if (!task) return { error: `Task not found: ${params.taskId}` };
643
+
644
+ if (!task.metrics) task.metrics = {};
645
+ if (params.toolCalls !== undefined) task.metrics.toolCalls = params.toolCalls as number;
646
+ if (params.modelTier !== undefined) task.metrics.modelTier = params.modelTier as string;
647
+ if (params.estimatedCostUsd !== undefined)
648
+ task.metrics.estimatedCostUsd = params.estimatedCostUsd as number;
649
+ if (params.iterations !== undefined)
650
+ task.metrics.iterations = params.iterations as number;
651
+
652
+ task.updatedAt = Date.now();
653
+ plan.updatedAt = Date.now();
654
+
655
+ return {
656
+ recorded: true,
657
+ taskId: task.id,
658
+ metrics: task.metrics,
659
+ };
660
+ } catch (err) {
661
+ return { error: (err as Error).message };
662
+ }
663
+ },
664
+ },
665
+
666
+ // ─── Submit Deliverable (#83) ───────────────────────────────
667
+ {
668
+ name: 'plan_submit_deliverable',
669
+ description:
670
+ 'Record a deliverable on a task. Auto-computes SHA-256 hash for file deliverables.',
671
+ auth: 'write',
672
+ schema: z.object({
673
+ planId: z.string().describe('Plan ID'),
674
+ taskId: z.string().describe('Task ID to attach deliverable to'),
675
+ type: z.enum(['file', 'vault_entry', 'url']).describe('Deliverable type'),
676
+ path: z.string().describe('File path, vault entry ID, or URL'),
677
+ }),
678
+ handler: async (params) => {
679
+ try {
680
+ const task = planner.submitDeliverable(params.planId as string, params.taskId as string, {
681
+ type: params.type as 'file' | 'vault_entry' | 'url',
682
+ path: params.path as string,
683
+ });
684
+ return {
685
+ submitted: true,
686
+ taskId: task.id,
687
+ deliverableCount: task.deliverables?.length ?? 0,
688
+ };
689
+ } catch (err) {
690
+ return { error: (err as Error).message };
691
+ }
692
+ },
693
+ },
694
+
695
+ // ─── Verify Deliverables (#83) ──────────────────────────────
696
+ {
697
+ name: 'plan_verify_deliverables',
698
+ description:
699
+ 'Verify all deliverables for a task — checks file existence + SHA-256 hash match, vault entry existence. Returns stale count.',
700
+ auth: 'read',
701
+ schema: z.object({
702
+ planId: z.string().describe('Plan ID'),
703
+ taskId: z.string().describe('Task ID to verify deliverables for'),
704
+ }),
705
+ handler: async (params) => {
706
+ try {
707
+ return planner.verifyDeliverables(
708
+ params.planId as string,
709
+ params.taskId as string,
710
+ vault,
711
+ );
712
+ } catch (err) {
713
+ return { error: (err as Error).message };
714
+ }
715
+ },
716
+ },
326
717
  ];
327
718
  }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Playbook Operations — 5 ops for playbook management.
3
+ *
4
+ * Existing ops (moved from core-ops.ts):
5
+ * playbook_list, playbook_get, playbook_create
6
+ *
7
+ * New ops:
8
+ * playbook_match — match playbooks by intent + text
9
+ * playbook_seed — seed built-in playbooks into vault
10
+ */
11
+
12
+ import { z } from 'zod';
13
+ import type { OpDefinition } from '../facades/types.js';
14
+ import type { AgentRuntime } from './types.js';
15
+ import { parsePlaybookFromEntry, validatePlaybook } from '../vault/playbook.js';
16
+ import {
17
+ matchPlaybooks,
18
+ seedDefaultPlaybooks,
19
+ entryToPlaybookDefinition,
20
+ } from '../playbooks/index.js';
21
+ import type { PlaybookIntent } from '../playbooks/index.js';
22
+
23
+ export function createPlaybookOps(runtime: AgentRuntime): OpDefinition[] {
24
+ const { vault } = runtime;
25
+
26
+ return [
27
+ // ─── playbook_list ──────────────────────────────────────────────
28
+ {
29
+ name: 'playbook_list',
30
+ description: 'List playbooks stored in the vault, optionally filtered by domain.',
31
+ auth: 'read',
32
+ schema: z.object({
33
+ domain: z.string().optional(),
34
+ limit: z.number().optional(),
35
+ }),
36
+ handler: async (params) => {
37
+ const entries = vault.list({
38
+ type: 'playbook',
39
+ domain: params.domain as string | undefined,
40
+ limit: (params.limit as number) ?? 50,
41
+ });
42
+ const playbooks = entries.map((e) => parsePlaybookFromEntry(e)).filter((p) => p !== null);
43
+ return { playbooks, count: playbooks.length };
44
+ },
45
+ },
46
+
47
+ // ─── playbook_get ───────────────────────────────────────────────
48
+ {
49
+ name: 'playbook_get',
50
+ description: 'Get a single playbook by ID, parsed into structured steps.',
51
+ auth: 'read',
52
+ schema: z.object({ id: z.string() }),
53
+ handler: async (params) => {
54
+ const entry = vault.get(params.id as string);
55
+ if (!entry) return { error: 'Playbook not found: ' + params.id };
56
+ if (entry.type !== 'playbook') return { error: 'Entry is not a playbook: ' + params.id };
57
+ const playbook = parsePlaybookFromEntry(entry);
58
+ if (!playbook) return { error: 'Failed to parse playbook context: ' + params.id };
59
+ return playbook;
60
+ },
61
+ },
62
+
63
+ // ─── playbook_create ────────────────────────────────────────────
64
+ {
65
+ name: 'playbook_create',
66
+ description:
67
+ 'Create a playbook with structured steps. Validates step ordering and builds vault entry automatically.',
68
+ auth: 'write',
69
+ schema: z.object({
70
+ id: z.string().optional(),
71
+ title: z.string(),
72
+ domain: z.string(),
73
+ description: z.string(),
74
+ steps: z.array(
75
+ z.object({
76
+ title: z.string(),
77
+ description: z.string(),
78
+ validation: z.string().optional(),
79
+ }),
80
+ ),
81
+ tags: z.array(z.string()).optional().default([]),
82
+ severity: z.enum(['critical', 'warning', 'suggestion']).optional().default('suggestion'),
83
+ }),
84
+ handler: async (params) => {
85
+ const title = params.title as string;
86
+ const domain = params.domain as string;
87
+ const rawSteps = params.steps as Array<{
88
+ title: string;
89
+ description: string;
90
+ validation?: string;
91
+ }>;
92
+
93
+ const steps = rawSteps.map((s, i) => ({ ...s, order: i + 1 }));
94
+ const id =
95
+ (params.id as string | undefined) ??
96
+ `playbook-${domain}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
97
+
98
+ const playbook = {
99
+ id,
100
+ title,
101
+ domain,
102
+ description: params.description as string,
103
+ steps,
104
+ tags: params.tags as string[],
105
+ createdAt: Date.now(),
106
+ updatedAt: Date.now(),
107
+ };
108
+
109
+ const validation = validatePlaybook(playbook);
110
+ if (!validation.valid) {
111
+ return { created: false, id, errors: validation.errors };
112
+ }
113
+
114
+ vault.add({
115
+ id,
116
+ type: 'playbook',
117
+ domain,
118
+ title,
119
+ severity:
120
+ (params.severity as 'critical' | 'warning' | 'suggestion' | undefined) ?? 'suggestion',
121
+ description: params.description as string,
122
+ context: JSON.stringify({ steps }),
123
+ tags: params.tags as string[],
124
+ });
125
+
126
+ return { created: true, id, steps: steps.length };
127
+ },
128
+ },
129
+
130
+ // ─── playbook_match (NEW) ───────────────────────────────────────
131
+ {
132
+ name: 'playbook_match',
133
+ description:
134
+ 'Match playbooks by intent and text. Combines vault-stored and built-in playbooks, returns best match with merged gates/tasks/tools.',
135
+ auth: 'read',
136
+ schema: z.object({
137
+ intent: z
138
+ .enum(['BUILD', 'FIX', 'REVIEW', 'PLAN', 'IMPROVE', 'DELIVER'])
139
+ .optional()
140
+ .describe('Plan intent for matching'),
141
+ text: z.string().describe('Plan objective + scope text to match against'),
142
+ }),
143
+ handler: async (params) => {
144
+ const intent = params.intent as PlaybookIntent | undefined;
145
+ const text = params.text as string;
146
+
147
+ // Load vault playbooks and convert to PlaybookDefinition
148
+ const vaultEntries = vault.list({ type: 'playbook', limit: 200 });
149
+ const vaultPlaybooks = vaultEntries
150
+ .map((e) => entryToPlaybookDefinition(e))
151
+ .filter((p): p is NonNullable<typeof p> => p !== null);
152
+
153
+ const result = matchPlaybooks(intent, text, vaultPlaybooks);
154
+ return result;
155
+ },
156
+ },
157
+
158
+ // ─── playbook_seed (NEW) ────────────────────────────────────────
159
+ {
160
+ name: 'playbook_seed',
161
+ description:
162
+ 'Seed built-in playbooks into the vault. Idempotent — skips existing playbooks. Seeds 6 generic playbooks (TDD, brainstorming, code-review, subagent-execution, debugging, verification).',
163
+ auth: 'write',
164
+ handler: async () => {
165
+ return seedDefaultPlaybooks(vault);
166
+ },
167
+ },
168
+ ];
169
+ }