@soleri/core 9.0.4 → 9.3.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 (744) hide show
  1. package/data/flows/build.flow.yaml +8 -9
  2. package/data/flows/deliver.flow.yaml +9 -10
  3. package/data/flows/design.flow.yaml +3 -4
  4. package/data/flows/enhance.flow.yaml +5 -6
  5. package/data/flows/explore.flow.yaml +3 -4
  6. package/data/flows/fix.flow.yaml +5 -6
  7. package/data/flows/plan.flow.yaml +4 -5
  8. package/data/flows/review.flow.yaml +3 -4
  9. package/dist/brain/intelligence.d.ts +27 -0
  10. package/dist/brain/intelligence.d.ts.map +1 -1
  11. package/dist/brain/intelligence.js +160 -14
  12. package/dist/brain/intelligence.js.map +1 -1
  13. package/dist/brain/learning-radar.d.ts +4 -0
  14. package/dist/brain/learning-radar.d.ts.map +1 -1
  15. package/dist/brain/learning-radar.js +20 -1
  16. package/dist/brain/learning-radar.js.map +1 -1
  17. package/dist/brain/strength-scorer.d.ts +31 -0
  18. package/dist/brain/strength-scorer.d.ts.map +1 -0
  19. package/dist/brain/strength-scorer.js +264 -0
  20. package/dist/brain/strength-scorer.js.map +1 -0
  21. package/dist/chat/agent-loop.d.ts.map +1 -1
  22. package/dist/chat/agent-loop.js +2 -0
  23. package/dist/chat/agent-loop.js.map +1 -1
  24. package/dist/chat/notifications.d.ts.map +1 -1
  25. package/dist/chat/notifications.js +2 -0
  26. package/dist/chat/notifications.js.map +1 -1
  27. package/dist/claudemd/compose.js +1 -1
  28. package/dist/claudemd/compose.js.map +1 -1
  29. package/dist/control/intent-router.d.ts.map +1 -1
  30. package/dist/control/intent-router.js +12 -4
  31. package/dist/control/intent-router.js.map +1 -1
  32. package/dist/curator/contradiction-detector.d.ts +27 -0
  33. package/dist/curator/contradiction-detector.d.ts.map +1 -0
  34. package/dist/curator/contradiction-detector.js +62 -0
  35. package/dist/curator/contradiction-detector.js.map +1 -0
  36. package/dist/curator/curator.d.ts +3 -4
  37. package/dist/curator/curator.d.ts.map +1 -1
  38. package/dist/curator/curator.js +94 -453
  39. package/dist/curator/curator.js.map +1 -1
  40. package/dist/curator/duplicate-detector.d.ts +14 -0
  41. package/dist/curator/duplicate-detector.d.ts.map +1 -0
  42. package/dist/curator/duplicate-detector.js +77 -0
  43. package/dist/curator/duplicate-detector.js.map +1 -0
  44. package/dist/curator/health-audit.d.ts +15 -0
  45. package/dist/curator/health-audit.d.ts.map +1 -0
  46. package/dist/curator/health-audit.js +97 -0
  47. package/dist/curator/health-audit.js.map +1 -0
  48. package/dist/curator/metadata-enricher.d.ts +17 -0
  49. package/dist/curator/metadata-enricher.d.ts.map +1 -0
  50. package/dist/curator/metadata-enricher.js +60 -0
  51. package/dist/curator/metadata-enricher.js.map +1 -0
  52. package/dist/curator/schema.d.ts +7 -0
  53. package/dist/curator/schema.d.ts.map +1 -0
  54. package/dist/curator/schema.js +62 -0
  55. package/dist/curator/schema.js.map +1 -0
  56. package/dist/curator/tag-manager.d.ts +36 -0
  57. package/dist/curator/tag-manager.d.ts.map +1 -0
  58. package/dist/curator/tag-manager.js +78 -0
  59. package/dist/curator/tag-manager.js.map +1 -0
  60. package/dist/engine/bin/soleri-engine.js +24 -3
  61. package/dist/engine/bin/soleri-engine.js.map +1 -1
  62. package/dist/engine/core-ops.d.ts.map +1 -1
  63. package/dist/engine/core-ops.js +23 -8
  64. package/dist/engine/core-ops.js.map +1 -1
  65. package/dist/engine/module-manifest.d.ts.map +1 -1
  66. package/dist/engine/module-manifest.js +42 -2
  67. package/dist/engine/module-manifest.js.map +1 -1
  68. package/dist/engine/register-engine.d.ts.map +1 -1
  69. package/dist/engine/register-engine.js +50 -2
  70. package/dist/engine/register-engine.js.map +1 -1
  71. package/dist/errors/retry.d.ts.map +1 -1
  72. package/dist/errors/retry.js +2 -0
  73. package/dist/errors/retry.js.map +1 -1
  74. package/dist/facades/types.d.ts +1 -1
  75. package/dist/flows/chain-types.d.ts +18 -18
  76. package/dist/flows/gate-evaluator.d.ts.map +1 -1
  77. package/dist/flows/gate-evaluator.js +22 -0
  78. package/dist/flows/gate-evaluator.js.map +1 -1
  79. package/dist/flows/types.d.ts +157 -28
  80. package/dist/flows/types.d.ts.map +1 -1
  81. package/dist/flows/types.js +4 -0
  82. package/dist/flows/types.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +9 -1
  86. package/dist/index.js.map +1 -1
  87. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  88. package/dist/intake/intake-pipeline.js +1 -0
  89. package/dist/intake/intake-pipeline.js.map +1 -1
  90. package/dist/intake/text-ingester.d.ts.map +1 -1
  91. package/dist/intake/text-ingester.js +2 -0
  92. package/dist/intake/text-ingester.js.map +1 -1
  93. package/dist/llm/key-pool.d.ts +1 -1
  94. package/dist/llm/key-pool.d.ts.map +1 -1
  95. package/dist/llm/key-pool.js +3 -4
  96. package/dist/llm/key-pool.js.map +1 -1
  97. package/dist/llm/utils.d.ts.map +1 -1
  98. package/dist/llm/utils.js +2 -0
  99. package/dist/llm/utils.js.map +1 -1
  100. package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
  101. package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
  102. package/dist/migrations/migration-runner.test-helpers.js +47 -0
  103. package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
  104. package/dist/operator/operator-profile.d.ts +44 -0
  105. package/dist/operator/operator-profile.d.ts.map +1 -0
  106. package/dist/operator/operator-profile.js +383 -0
  107. package/dist/operator/operator-profile.js.map +1 -0
  108. package/dist/operator/operator-signals.d.ts +45 -0
  109. package/dist/operator/operator-signals.d.ts.map +1 -0
  110. package/dist/operator/operator-signals.js +228 -0
  111. package/dist/operator/operator-signals.js.map +1 -0
  112. package/dist/operator/operator-types.d.ts +360 -0
  113. package/dist/operator/operator-types.d.ts.map +1 -0
  114. package/dist/operator/operator-types.js +24 -0
  115. package/dist/operator/operator-types.js.map +1 -0
  116. package/dist/packs/types.d.ts +27 -27
  117. package/dist/paths.d.ts +40 -0
  118. package/dist/paths.d.ts.map +1 -0
  119. package/dist/paths.js +98 -0
  120. package/dist/paths.js.map +1 -0
  121. package/dist/persistence/index.d.ts +1 -1
  122. package/dist/persistence/index.d.ts.map +1 -1
  123. package/dist/persistence/index.js +1 -1
  124. package/dist/persistence/index.js.map +1 -1
  125. package/dist/persistence/sqlite-provider.d.ts +2 -0
  126. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  127. package/dist/persistence/sqlite-provider.js +8 -5
  128. package/dist/persistence/sqlite-provider.js.map +1 -1
  129. package/dist/planning/evidence-collector.d.ts +13 -1
  130. package/dist/planning/evidence-collector.d.ts.map +1 -1
  131. package/dist/planning/evidence-collector.js +33 -0
  132. package/dist/planning/evidence-collector.js.map +1 -1
  133. package/dist/planning/gap-analysis.d.ts +5 -4
  134. package/dist/planning/gap-analysis.d.ts.map +1 -1
  135. package/dist/planning/gap-analysis.js +7 -341
  136. package/dist/planning/gap-analysis.js.map +1 -1
  137. package/dist/planning/gap-passes.d.ts +19 -0
  138. package/dist/planning/gap-passes.d.ts.map +1 -0
  139. package/dist/planning/gap-passes.js +174 -0
  140. package/dist/planning/gap-passes.js.map +1 -0
  141. package/dist/planning/gap-patterns.d.ts +29 -0
  142. package/dist/planning/gap-patterns.d.ts.map +1 -0
  143. package/dist/planning/gap-patterns.js +175 -0
  144. package/dist/planning/gap-patterns.js.map +1 -0
  145. package/dist/planning/gap-types.d.ts +1 -1
  146. package/dist/planning/gap-types.d.ts.map +1 -1
  147. package/dist/planning/gap-types.js +1 -0
  148. package/dist/planning/gap-types.js.map +1 -1
  149. package/dist/planning/github-projection.d.ts +122 -0
  150. package/dist/planning/github-projection.d.ts.map +1 -0
  151. package/dist/planning/github-projection.js +313 -0
  152. package/dist/planning/github-projection.js.map +1 -0
  153. package/dist/planning/impact-analyzer.d.ts +26 -0
  154. package/dist/planning/impact-analyzer.d.ts.map +1 -0
  155. package/dist/planning/impact-analyzer.js +201 -0
  156. package/dist/planning/impact-analyzer.js.map +1 -0
  157. package/dist/planning/plan-lifecycle.d.ts +136 -0
  158. package/dist/planning/plan-lifecycle.d.ts.map +1 -0
  159. package/dist/planning/plan-lifecycle.js +309 -0
  160. package/dist/planning/plan-lifecycle.js.map +1 -0
  161. package/dist/planning/planner-types.d.ts +202 -0
  162. package/dist/planning/planner-types.d.ts.map +1 -0
  163. package/dist/planning/planner-types.js +6 -0
  164. package/dist/planning/planner-types.js.map +1 -0
  165. package/dist/planning/planner.d.ts +31 -383
  166. package/dist/planning/planner.d.ts.map +1 -1
  167. package/dist/planning/planner.js +151 -832
  168. package/dist/planning/planner.js.map +1 -1
  169. package/dist/planning/rationalization-detector.d.ts +32 -0
  170. package/dist/planning/rationalization-detector.d.ts.map +1 -0
  171. package/dist/planning/rationalization-detector.js +89 -0
  172. package/dist/planning/rationalization-detector.js.map +1 -0
  173. package/dist/planning/reconciliation-engine.d.ts +47 -0
  174. package/dist/planning/reconciliation-engine.d.ts.map +1 -0
  175. package/dist/planning/reconciliation-engine.js +128 -0
  176. package/dist/planning/reconciliation-engine.js.map +1 -0
  177. package/dist/planning/task-verifier.d.ts +85 -0
  178. package/dist/planning/task-verifier.d.ts.map +1 -0
  179. package/dist/planning/task-verifier.js +235 -0
  180. package/dist/planning/task-verifier.js.map +1 -0
  181. package/dist/plugins/types.d.ts +4 -4
  182. package/dist/runtime/admin-ops.d.ts +2 -2
  183. package/dist/runtime/admin-ops.d.ts.map +1 -1
  184. package/dist/runtime/admin-ops.js +44 -17
  185. package/dist/runtime/admin-ops.js.map +1 -1
  186. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  187. package/dist/runtime/admin-setup-ops.js +22 -46
  188. package/dist/runtime/admin-setup-ops.js.map +1 -1
  189. package/dist/runtime/archive-ops.d.ts +10 -0
  190. package/dist/runtime/archive-ops.d.ts.map +1 -0
  191. package/dist/runtime/archive-ops.js +310 -0
  192. package/dist/runtime/archive-ops.js.map +1 -0
  193. package/dist/runtime/branching-ops.d.ts +12 -0
  194. package/dist/runtime/branching-ops.d.ts.map +1 -0
  195. package/dist/runtime/branching-ops.js +100 -0
  196. package/dist/runtime/branching-ops.js.map +1 -0
  197. package/dist/runtime/capture-ops.d.ts.map +1 -1
  198. package/dist/runtime/capture-ops.js +42 -7
  199. package/dist/runtime/capture-ops.js.map +1 -1
  200. package/dist/runtime/claude-md-helpers.js +1 -1
  201. package/dist/runtime/claude-md-helpers.js.map +1 -1
  202. package/dist/runtime/context-health.d.ts +31 -0
  203. package/dist/runtime/context-health.d.ts.map +1 -0
  204. package/dist/runtime/context-health.js +57 -0
  205. package/dist/runtime/context-health.js.map +1 -0
  206. package/dist/runtime/facades/archive-facade.d.ts +10 -0
  207. package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
  208. package/dist/runtime/facades/archive-facade.js +11 -0
  209. package/dist/runtime/facades/archive-facade.js.map +1 -0
  210. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  211. package/dist/runtime/facades/brain-facade.js +2 -0
  212. package/dist/runtime/facades/brain-facade.js.map +1 -1
  213. package/dist/runtime/facades/branching-facade.d.ts +7 -0
  214. package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
  215. package/dist/runtime/facades/branching-facade.js +8 -0
  216. package/dist/runtime/facades/branching-facade.js.map +1 -0
  217. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  218. package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
  219. package/dist/runtime/facades/chat-facade.js +15 -800
  220. package/dist/runtime/facades/chat-facade.js.map +1 -1
  221. package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
  222. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
  223. package/dist/runtime/facades/chat-service-ops.js +332 -0
  224. package/dist/runtime/facades/chat-service-ops.js.map +1 -0
  225. package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
  226. package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
  227. package/dist/runtime/facades/chat-session-ops.js +136 -0
  228. package/dist/runtime/facades/chat-session-ops.js.map +1 -0
  229. package/dist/runtime/facades/chat-state.d.ts +31 -0
  230. package/dist/runtime/facades/chat-state.d.ts.map +1 -0
  231. package/dist/runtime/facades/chat-state.js +32 -0
  232. package/dist/runtime/facades/chat-state.js.map +1 -0
  233. package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
  234. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
  235. package/dist/runtime/facades/chat-transport-ops.js +337 -0
  236. package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
  237. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  238. package/dist/runtime/facades/control-facade.js +4 -1
  239. package/dist/runtime/facades/control-facade.js.map +1 -1
  240. package/dist/runtime/facades/index.d.ts.map +1 -1
  241. package/dist/runtime/facades/index.js +48 -0
  242. package/dist/runtime/facades/index.js.map +1 -1
  243. package/dist/runtime/facades/intake-facade.d.ts +9 -0
  244. package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
  245. package/dist/runtime/facades/intake-facade.js +11 -0
  246. package/dist/runtime/facades/intake-facade.js.map +1 -0
  247. package/dist/runtime/facades/links-facade.d.ts +9 -0
  248. package/dist/runtime/facades/links-facade.d.ts.map +1 -0
  249. package/dist/runtime/facades/links-facade.js +10 -0
  250. package/dist/runtime/facades/links-facade.js.map +1 -0
  251. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  252. package/dist/runtime/facades/memory-facade.js +75 -6
  253. package/dist/runtime/facades/memory-facade.js.map +1 -1
  254. package/dist/runtime/facades/operator-facade.d.ts +8 -0
  255. package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
  256. package/dist/runtime/facades/operator-facade.js +220 -0
  257. package/dist/runtime/facades/operator-facade.js.map +1 -0
  258. package/dist/runtime/facades/orchestrate-facade.js +3 -3
  259. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  260. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  261. package/dist/runtime/facades/plan-facade.js +42 -6
  262. package/dist/runtime/facades/plan-facade.js.map +1 -1
  263. package/dist/runtime/facades/review-facade.d.ts +7 -0
  264. package/dist/runtime/facades/review-facade.d.ts.map +1 -0
  265. package/dist/runtime/facades/review-facade.js +8 -0
  266. package/dist/runtime/facades/review-facade.js.map +1 -0
  267. package/dist/runtime/facades/sync-facade.d.ts +7 -0
  268. package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
  269. package/dist/runtime/facades/sync-facade.js +8 -0
  270. package/dist/runtime/facades/sync-facade.js.map +1 -0
  271. package/dist/runtime/facades/tier-facade.d.ts +7 -0
  272. package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
  273. package/dist/runtime/facades/tier-facade.js +8 -0
  274. package/dist/runtime/facades/tier-facade.js.map +1 -0
  275. package/dist/runtime/facades/vault-facade.d.ts +12 -1
  276. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  277. package/dist/runtime/facades/vault-facade.js +55 -251
  278. package/dist/runtime/facades/vault-facade.js.map +1 -1
  279. package/dist/runtime/github-integration.d.ts +49 -0
  280. package/dist/runtime/github-integration.d.ts.map +1 -0
  281. package/dist/runtime/github-integration.js +120 -0
  282. package/dist/runtime/github-integration.js.map +1 -0
  283. package/dist/runtime/grading-ops.js +1 -1
  284. package/dist/runtime/grading-ops.js.map +1 -1
  285. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  286. package/dist/runtime/memory-extra-ops.js +6 -2
  287. package/dist/runtime/memory-extra-ops.js.map +1 -1
  288. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  289. package/dist/runtime/orchestrate-ops.js +386 -37
  290. package/dist/runtime/orchestrate-ops.js.map +1 -1
  291. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  292. package/dist/runtime/planning-extra-ops.js +69 -4
  293. package/dist/runtime/planning-extra-ops.js.map +1 -1
  294. package/dist/runtime/review-ops.d.ts +10 -0
  295. package/dist/runtime/review-ops.d.ts.map +1 -0
  296. package/dist/runtime/review-ops.js +97 -0
  297. package/dist/runtime/review-ops.js.map +1 -0
  298. package/dist/runtime/runtime.d.ts.map +1 -1
  299. package/dist/runtime/runtime.js +29 -12
  300. package/dist/runtime/runtime.js.map +1 -1
  301. package/dist/runtime/session-briefing.d.ts +3 -0
  302. package/dist/runtime/session-briefing.d.ts.map +1 -1
  303. package/dist/runtime/session-briefing.js +72 -1
  304. package/dist/runtime/session-briefing.js.map +1 -1
  305. package/dist/runtime/sync-ops.d.ts +12 -0
  306. package/dist/runtime/sync-ops.d.ts.map +1 -0
  307. package/dist/runtime/sync-ops.js +288 -0
  308. package/dist/runtime/sync-ops.js.map +1 -0
  309. package/dist/runtime/tier-ops.d.ts +13 -0
  310. package/dist/runtime/tier-ops.d.ts.map +1 -0
  311. package/dist/runtime/tier-ops.js +110 -0
  312. package/dist/runtime/tier-ops.js.map +1 -0
  313. package/dist/runtime/types.d.ts +10 -4
  314. package/dist/runtime/types.d.ts.map +1 -1
  315. package/dist/runtime/vault-extra-ops.d.ts +5 -4
  316. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  317. package/dist/runtime/vault-extra-ops.js +5 -300
  318. package/dist/runtime/vault-extra-ops.js.map +1 -1
  319. package/dist/runtime/vault-sharing-ops.d.ts +4 -4
  320. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  321. package/dist/runtime/vault-sharing-ops.js +5 -300
  322. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  323. package/dist/skills/sync-skills.d.ts +27 -0
  324. package/dist/skills/sync-skills.d.ts.map +1 -0
  325. package/dist/skills/sync-skills.js +81 -0
  326. package/dist/skills/sync-skills.js.map +1 -0
  327. package/dist/update-check.d.ts +14 -0
  328. package/dist/update-check.d.ts.map +1 -0
  329. package/dist/update-check.js +96 -0
  330. package/dist/update-check.js.map +1 -0
  331. package/dist/vault/linking.d.ts +10 -12
  332. package/dist/vault/linking.d.ts.map +1 -1
  333. package/dist/vault/linking.js +140 -161
  334. package/dist/vault/linking.js.map +1 -1
  335. package/dist/vault/vault-entries.d.ts +69 -0
  336. package/dist/vault/vault-entries.d.ts.map +1 -0
  337. package/dist/vault/vault-entries.js +299 -0
  338. package/dist/vault/vault-entries.js.map +1 -0
  339. package/dist/vault/vault-interfaces.d.ts +153 -0
  340. package/dist/vault/vault-interfaces.d.ts.map +1 -0
  341. package/dist/vault/vault-interfaces.js +2 -0
  342. package/dist/vault/vault-interfaces.js.map +1 -0
  343. package/dist/vault/vault-maintenance.d.ts +40 -0
  344. package/dist/vault/vault-maintenance.d.ts.map +1 -0
  345. package/dist/vault/vault-maintenance.js +146 -0
  346. package/dist/vault/vault-maintenance.js.map +1 -0
  347. package/dist/vault/vault-markdown-sync.d.ts +22 -0
  348. package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
  349. package/dist/vault/vault-markdown-sync.js +143 -0
  350. package/dist/vault/vault-markdown-sync.js.map +1 -0
  351. package/dist/vault/vault-memories.d.ts +61 -0
  352. package/dist/vault/vault-memories.d.ts.map +1 -0
  353. package/dist/vault/vault-memories.js +242 -0
  354. package/dist/vault/vault-memories.js.map +1 -0
  355. package/dist/vault/vault-schema.d.ts +9 -0
  356. package/dist/vault/vault-schema.d.ts.map +1 -0
  357. package/dist/vault/vault-schema.js +205 -0
  358. package/dist/vault/vault-schema.js.map +1 -0
  359. package/dist/vault/vault.d.ts +29 -81
  360. package/dist/vault/vault.d.ts.map +1 -1
  361. package/dist/vault/vault.js +82 -931
  362. package/dist/vault/vault.js.map +1 -1
  363. package/package.json +7 -7
  364. package/src/agency/agency-manager.test.ts +620 -0
  365. package/src/agency/default-rules.test.ts +236 -0
  366. package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
  367. package/src/{__tests__ → brain}/brain.test.ts +1 -1
  368. package/src/brain/intelligence.ts +196 -15
  369. package/src/brain/learning-radar.ts +22 -1
  370. package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
  371. package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
  372. package/src/capabilities/chain-mapping.test.ts +66 -0
  373. package/src/capabilities/registry.test.ts +359 -0
  374. package/src/chat/agent-loop.test.ts +384 -0
  375. package/src/chat/agent-loop.ts +2 -0
  376. package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
  377. package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
  378. package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
  379. package/src/chat/mcp-bridge.test.ts +178 -0
  380. package/src/chat/notifications.ts +2 -0
  381. package/src/chat/output-compressor.test.ts +164 -0
  382. package/src/claudemd/compose.test.ts +178 -0
  383. package/src/claudemd/compose.ts +1 -1
  384. package/src/claudemd/inject.test.ts +201 -0
  385. package/src/context/context-engine.test.ts +506 -0
  386. package/src/control/identity-manager.test.ts +305 -0
  387. package/src/control/intent-router.test.ts +360 -0
  388. package/src/control/intent-router.ts +13 -4
  389. package/src/curator/classifier.test.ts +110 -0
  390. package/src/curator/contradiction-detector.test.ts +205 -0
  391. package/src/curator/contradiction-detector.ts +87 -0
  392. package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
  393. package/src/{__tests__ → curator}/curator.test.ts +77 -1
  394. package/src/curator/curator.ts +160 -600
  395. package/src/curator/duplicate-detector.test.ts +245 -0
  396. package/src/curator/duplicate-detector.ts +103 -0
  397. package/src/curator/health-audit.ts +126 -0
  398. package/src/curator/metadata-enricher.ts +84 -0
  399. package/src/curator/quality-gate.test.ts +175 -0
  400. package/src/curator/schema.ts +65 -0
  401. package/src/curator/tag-manager.test.ts +173 -0
  402. package/src/curator/tag-manager.ts +109 -0
  403. package/src/domain-packs/inject-rules.test.ts +117 -0
  404. package/src/domain-packs/knowledge-installer.test.ts +163 -0
  405. package/src/domain-packs/loader.test.ts +86 -0
  406. package/src/domain-packs/pack-runtime.test.ts +140 -0
  407. package/src/domain-packs/skills-installer.test.ts +135 -0
  408. package/src/domain-packs/token-resolver.test.ts +148 -0
  409. package/src/domain-packs/types.test.ts +144 -0
  410. package/src/enforcement/adapters/claude-code.test.ts +216 -0
  411. package/src/enforcement/registry.test.ts +258 -0
  412. package/src/engine/bin/soleri-engine.ts +30 -4
  413. package/src/engine/core-ops.test.ts +254 -0
  414. package/src/engine/core-ops.ts +25 -8
  415. package/src/engine/module-manifest.test.ts +125 -0
  416. package/src/engine/module-manifest.ts +42 -2
  417. package/src/engine/register-engine.test.ts +235 -0
  418. package/src/engine/register-engine.ts +50 -3
  419. package/src/errors/classify.test.ts +203 -0
  420. package/src/errors/retry.test.ts +153 -0
  421. package/src/errors/retry.ts +2 -0
  422. package/src/errors/types.test.ts +108 -0
  423. package/src/events/event-bus.test.ts +149 -0
  424. package/src/extensions/middleware.test.ts +234 -0
  425. package/src/facades/facade-factory.test.ts +470 -0
  426. package/src/flows/chain-runner.test.ts +273 -0
  427. package/src/flows/context-router.test.ts +52 -0
  428. package/src/flows/dispatch-registry.test.ts +128 -0
  429. package/src/flows/epilogue.test.ts +113 -0
  430. package/src/flows/executor.test.ts +263 -0
  431. package/src/flows/gate-evaluator.test.ts +200 -0
  432. package/src/flows/gate-evaluator.ts +23 -0
  433. package/src/flows/types.ts +4 -0
  434. package/src/governance/governance.test.ts +842 -0
  435. package/src/{__tests__ → health}/health-registry.test.ts +75 -55
  436. package/src/health/vault-integrity.test.ts +110 -0
  437. package/src/index.ts +92 -0
  438. package/src/intake/content-classifier.test.ts +279 -0
  439. package/src/intake/dedup-gate.test.ts +147 -0
  440. package/src/intake/intake-pipeline.test.ts +508 -0
  441. package/src/intake/intake-pipeline.ts +1 -0
  442. package/src/intake/text-ingester.test.ts +200 -0
  443. package/src/intake/text-ingester.ts +2 -0
  444. package/src/llm/key-pool.test.ts +234 -0
  445. package/src/llm/key-pool.ts +3 -4
  446. package/src/llm/llm-client.test.ts +342 -0
  447. package/src/llm/oauth-discovery.test.ts +180 -0
  448. package/src/llm/utils.test.ts +371 -0
  449. package/src/llm/utils.ts +2 -0
  450. package/src/{__tests__ → logging}/logger.test.ts +44 -62
  451. package/src/loop/loop-manager.test.ts +515 -0
  452. package/src/migrations/migration-runner.edge-cases.test.ts +314 -0
  453. package/src/migrations/migration-runner.test-helpers.ts +64 -0
  454. package/src/migrations/migration-runner.test.ts +385 -0
  455. package/src/operator/auto-signal-pipeline.test.ts +207 -0
  456. package/src/operator/operator-profile-extended.test.ts +330 -0
  457. package/src/operator/operator-profile.test.ts +332 -0
  458. package/src/operator/operator-profile.ts +485 -0
  459. package/src/operator/operator-signals-extended.test.ts +257 -0
  460. package/src/operator/operator-signals.test.ts +277 -0
  461. package/src/operator/operator-signals.ts +262 -0
  462. package/src/operator/operator-types.ts +444 -0
  463. package/src/operator/prompts/hook-precompact-operator-dispatch.md +98 -0
  464. package/src/operator/prompts/subagent-soft-signal-extractor.md +130 -0
  465. package/src/operator/prompts/subagent-synthesis-cognition.md +190 -0
  466. package/src/operator/prompts/subagent-synthesis-communication.md +146 -0
  467. package/src/operator/prompts/subagent-synthesis-technical.md +170 -0
  468. package/src/operator/prompts/subagent-synthesis-trust.md +149 -0
  469. package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
  470. package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
  471. package/src/paths.ts +115 -0
  472. package/src/persistence/index.ts +1 -1
  473. package/src/persistence/sqlite-provider.test.ts +540 -0
  474. package/src/persistence/sqlite-provider.ts +8 -5
  475. package/src/persona/defaults.test.ts +55 -0
  476. package/src/persona/loader.test.ts +67 -0
  477. package/src/persona/prompt-generator.test.ts +127 -0
  478. package/src/planning/evidence-collector.test.ts +515 -0
  479. package/src/planning/evidence-collector.ts +47 -0
  480. package/src/planning/gap-analysis-alternatives.test.ts +199 -0
  481. package/src/planning/gap-analysis.ts +21 -636
  482. package/src/planning/gap-passes.test.ts +554 -0
  483. package/src/planning/gap-passes.ts +367 -0
  484. package/src/planning/gap-patterns.test.ts +394 -0
  485. package/src/planning/gap-patterns.ts +317 -0
  486. package/src/planning/gap-types.ts +4 -1
  487. package/src/planning/github-projection.test.ts +182 -0
  488. package/src/planning/github-projection.ts +446 -0
  489. package/src/planning/impact-analyzer.test.ts +167 -0
  490. package/src/planning/impact-analyzer.ts +251 -0
  491. package/src/planning/plan-lifecycle.test.ts +379 -0
  492. package/src/planning/plan-lifecycle.ts +377 -0
  493. package/src/planning/planner-types.ts +215 -0
  494. package/src/{__tests__ → planning}/planner.test.ts +179 -15
  495. package/src/planning/planner.ts +221 -1112
  496. package/src/planning/rationalization-detector.test.ts +156 -0
  497. package/src/planning/rationalization-detector.ts +136 -0
  498. package/src/planning/reconciliation-engine.test.ts +158 -0
  499. package/src/planning/reconciliation-engine.ts +161 -0
  500. package/src/planning/task-verifier.test.ts +267 -0
  501. package/src/planning/task-verifier.ts +309 -0
  502. package/src/planning/verification-protocol.test.ts +201 -0
  503. package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
  504. package/src/playbooks/index.test.ts +77 -0
  505. package/src/playbooks/playbook-executor.test.ts +253 -0
  506. package/src/playbooks/playbook-registry.test.ts +232 -0
  507. package/src/playbooks/playbook-seeder.test.ts +153 -0
  508. package/src/plugins/plugin-loader.test.ts +217 -0
  509. package/src/plugins/plugin-registry.test.ts +284 -0
  510. package/src/project/project-registry.test.ts +439 -0
  511. package/src/prompts/parser.test.ts +100 -0
  512. package/src/prompts/template-manager.test.ts +112 -0
  513. package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
  514. package/src/queue/job-queue.test.ts +327 -0
  515. package/src/queue/pipeline-runner.test.ts +209 -0
  516. package/src/runtime/admin-extra-ops.test.ts +513 -0
  517. package/src/runtime/admin-ops.test.ts +255 -0
  518. package/src/runtime/admin-ops.ts +45 -17
  519. package/src/runtime/admin-setup-ops.test.ts +327 -0
  520. package/src/runtime/admin-setup-ops.ts +26 -42
  521. package/src/runtime/archive-ops.test.ts +272 -0
  522. package/src/runtime/archive-ops.ts +347 -0
  523. package/src/runtime/branching-ops.test.ts +144 -0
  524. package/src/runtime/branching-ops.ts +107 -0
  525. package/src/runtime/capture-ops.test.ts +419 -0
  526. package/src/runtime/capture-ops.ts +50 -8
  527. package/src/runtime/chain-ops.test.ts +159 -0
  528. package/src/runtime/claude-md-helpers.test.ts +189 -0
  529. package/src/runtime/claude-md-helpers.ts +1 -1
  530. package/src/runtime/context-health.test.ts +76 -0
  531. package/src/runtime/context-health.ts +83 -0
  532. package/src/runtime/curator-extra-ops.test.ts +204 -0
  533. package/src/runtime/deprecation.test.ts +98 -0
  534. package/src/runtime/domain-ops.test.ts +278 -0
  535. package/src/runtime/facades/admin-facade.test.ts +330 -0
  536. package/src/runtime/facades/agency-facade.test.ts +278 -0
  537. package/src/runtime/facades/archive-facade.test.ts +308 -0
  538. package/src/runtime/facades/archive-facade.ts +14 -0
  539. package/src/runtime/facades/brain-facade.test.ts +818 -0
  540. package/src/runtime/facades/brain-facade.ts +2 -0
  541. package/src/runtime/facades/branching-facade.test.ts +43 -0
  542. package/src/runtime/facades/branching-facade.ts +11 -0
  543. package/src/runtime/facades/chat-facade.test.ts +219 -0
  544. package/src/runtime/facades/chat-facade.ts +15 -906
  545. package/src/runtime/facades/chat-service-ops.test.ts +381 -0
  546. package/src/runtime/facades/chat-service-ops.ts +376 -0
  547. package/src/runtime/facades/chat-session-ops.test.ts +212 -0
  548. package/src/runtime/facades/chat-session-ops.ts +146 -0
  549. package/src/runtime/facades/chat-state.ts +60 -0
  550. package/src/runtime/facades/chat-transport-ops.test.ts +336 -0
  551. package/src/runtime/facades/chat-transport-ops.ts +379 -0
  552. package/src/runtime/facades/context-facade.test.ts +123 -0
  553. package/src/runtime/facades/control-facade.test.ts +436 -0
  554. package/src/runtime/facades/control-facade.ts +6 -1
  555. package/src/runtime/facades/curator-facade.test.ts +303 -0
  556. package/src/runtime/facades/index.ts +48 -0
  557. package/src/runtime/facades/intake-facade.test.ts +215 -0
  558. package/src/runtime/facades/intake-facade.ts +14 -0
  559. package/src/runtime/facades/links-facade.test.ts +203 -0
  560. package/src/runtime/facades/links-facade.ts +13 -0
  561. package/src/runtime/facades/loop-facade.test.ts +262 -0
  562. package/src/runtime/facades/memory-facade.test.ts +283 -0
  563. package/src/runtime/facades/memory-facade.ts +78 -6
  564. package/src/runtime/facades/operator-facade.test.ts +221 -0
  565. package/src/runtime/facades/operator-facade.ts +244 -0
  566. package/src/runtime/facades/orchestrate-facade.test.ts +191 -0
  567. package/src/runtime/facades/orchestrate-facade.ts +3 -3
  568. package/src/runtime/facades/plan-facade.test.ts +283 -0
  569. package/src/runtime/facades/plan-facade.ts +47 -6
  570. package/src/runtime/facades/review-facade.test.ts +82 -0
  571. package/src/runtime/facades/review-facade.ts +11 -0
  572. package/src/runtime/facades/sync-facade.test.ts +113 -0
  573. package/src/runtime/facades/sync-facade.ts +11 -0
  574. package/src/runtime/facades/tier-facade.test.ts +47 -0
  575. package/src/runtime/facades/tier-facade.ts +11 -0
  576. package/src/runtime/facades/vault-facade.test.ts +563 -0
  577. package/src/runtime/facades/vault-facade.ts +66 -265
  578. package/src/runtime/feature-flags.test.ts +140 -0
  579. package/src/runtime/github-integration.test.ts +89 -0
  580. package/src/runtime/github-integration.ts +162 -0
  581. package/src/runtime/grading-ops.test.ts +172 -0
  582. package/src/runtime/grading-ops.ts +1 -1
  583. package/src/runtime/intake-ops.test.ts +261 -0
  584. package/src/runtime/loop-ops.test.ts +248 -0
  585. package/src/runtime/memory-cross-project-ops.test.ts +188 -0
  586. package/src/runtime/memory-extra-ops.test.ts +453 -0
  587. package/src/runtime/memory-extra-ops.ts +6 -2
  588. package/src/runtime/orchestrate-ops.test.ts +302 -0
  589. package/src/runtime/orchestrate-ops.ts +461 -45
  590. package/src/runtime/pack-ops.test.ts +175 -0
  591. package/src/runtime/planning-extra-ops.test.ts +593 -0
  592. package/src/runtime/planning-extra-ops.ts +74 -4
  593. package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
  594. package/src/runtime/playbook-ops.test.ts +285 -0
  595. package/src/runtime/plugin-ops.test.ts +259 -0
  596. package/src/runtime/project-ops.test.ts +255 -0
  597. package/src/runtime/review-ops.test.ts +142 -0
  598. package/src/runtime/review-ops.ts +99 -0
  599. package/src/runtime/runtime.test.ts +363 -0
  600. package/src/runtime/runtime.ts +41 -12
  601. package/src/runtime/session-briefing.test.ts +431 -0
  602. package/src/runtime/session-briefing.ts +86 -1
  603. package/src/runtime/sync-ops.test.ts +212 -0
  604. package/src/runtime/sync-ops.ts +325 -0
  605. package/src/runtime/telemetry-ops.test.ts +157 -0
  606. package/src/runtime/tier-ops.test.ts +159 -0
  607. package/src/runtime/tier-ops.ts +119 -0
  608. package/src/runtime/types.ts +10 -4
  609. package/src/runtime/vault-extra-ops.test.ts +270 -0
  610. package/src/runtime/vault-extra-ops.ts +5 -332
  611. package/src/runtime/vault-linking-ops.test.ts +237 -0
  612. package/src/runtime/vault-sharing-ops.test.ts +127 -0
  613. package/src/runtime/vault-sharing-ops.ts +5 -329
  614. package/src/skills/sync-skills.ts +98 -0
  615. package/src/streams/normalize.test.ts +95 -0
  616. package/src/streams/replayable-stream.test.ts +166 -0
  617. package/src/telemetry/telemetry.test.ts +143 -0
  618. package/src/transport/http-server.test.ts +394 -0
  619. package/src/transport/lsp-server.test.ts +458 -0
  620. package/src/transport/rate-limiter.test.ts +126 -0
  621. package/src/transport/session-manager.test.ts +133 -0
  622. package/src/transport/token-auth.test.ts +136 -0
  623. package/src/transport/ws-server.test.ts +297 -0
  624. package/src/update-check.ts +111 -0
  625. package/src/vault/__tests__/vault-characterization.test.ts +579 -0
  626. package/src/vault/content-hash.test.ts +78 -0
  627. package/src/vault/git-vault-sync.test.ts +234 -0
  628. package/src/vault/knowledge-review.test.ts +269 -0
  629. package/src/vault/linking.test.ts +391 -0
  630. package/src/vault/linking.ts +188 -181
  631. package/src/vault/obsidian-sync.test.ts +345 -0
  632. package/src/vault/playbook.test.ts +152 -0
  633. package/src/vault/scope-detector.test.ts +185 -0
  634. package/src/vault/vault-branching.test.ts +252 -0
  635. package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
  636. package/src/vault/vault-entries.ts +426 -0
  637. package/src/vault/vault-maintenance.ts +200 -0
  638. package/src/vault/vault-manager.test.ts +206 -0
  639. package/src/vault/vault-markdown-sync.test.ts +203 -0
  640. package/src/vault/vault-markdown-sync.ts +163 -0
  641. package/src/vault/vault-memories.ts +339 -0
  642. package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
  643. package/src/vault/vault-schema.ts +238 -0
  644. package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
  645. package/src/{__tests__ → vault}/vault.test.ts +2 -2
  646. package/src/vault/vault.ts +87 -1123
  647. package/dist/cognee/client.d.ts +0 -43
  648. package/dist/cognee/client.d.ts.map +0 -1
  649. package/dist/cognee/client.js +0 -375
  650. package/dist/cognee/client.js.map +0 -1
  651. package/dist/cognee/sync-manager.d.ts +0 -153
  652. package/dist/cognee/sync-manager.d.ts.map +0 -1
  653. package/dist/cognee/sync-manager.js +0 -390
  654. package/dist/cognee/sync-manager.js.map +0 -1
  655. package/dist/cognee/types.d.ts +0 -62
  656. package/dist/cognee/types.d.ts.map +0 -1
  657. package/dist/cognee/types.js +0 -3
  658. package/dist/cognee/types.js.map +0 -1
  659. package/dist/governance/index.d.ts +0 -3
  660. package/dist/governance/index.d.ts.map +0 -1
  661. package/dist/governance/index.js +0 -2
  662. package/dist/governance/index.js.map +0 -1
  663. package/dist/health/doctor-checks.d.ts +0 -15
  664. package/dist/health/doctor-checks.d.ts.map +0 -1
  665. package/dist/health/doctor-checks.js +0 -98
  666. package/dist/health/doctor-checks.js.map +0 -1
  667. package/dist/persistence/postgres-provider.d.ts +0 -81
  668. package/dist/persistence/postgres-provider.d.ts.map +0 -1
  669. package/dist/persistence/postgres-provider.js +0 -256
  670. package/dist/persistence/postgres-provider.js.map +0 -1
  671. package/dist/runtime/cognee-sync-ops.d.ts +0 -12
  672. package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
  673. package/dist/runtime/cognee-sync-ops.js +0 -93
  674. package/dist/runtime/cognee-sync-ops.js.map +0 -1
  675. package/dist/runtime/core-ops.d.ts +0 -23
  676. package/dist/runtime/core-ops.d.ts.map +0 -1
  677. package/dist/runtime/core-ops.js +0 -1296
  678. package/dist/runtime/core-ops.js.map +0 -1
  679. package/dist/runtime/facades/cognee-facade.d.ts +0 -8
  680. package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
  681. package/dist/runtime/facades/cognee-facade.js +0 -156
  682. package/dist/runtime/facades/cognee-facade.js.map +0 -1
  683. package/src/__tests__/admin-extra-ops.test.ts +0 -484
  684. package/src/__tests__/admin-ops.test.ts +0 -268
  685. package/src/__tests__/admin-setup-ops.test.ts +0 -355
  686. package/src/__tests__/agency-manager.test.ts +0 -374
  687. package/src/__tests__/agent-loop.test.ts +0 -256
  688. package/src/__tests__/capture-ops.test.ts +0 -784
  689. package/src/__tests__/claudemd.test.ts +0 -282
  690. package/src/__tests__/content-hash.test.ts +0 -60
  691. package/src/__tests__/context-engine.test.ts +0 -251
  692. package/src/__tests__/core-ops.test.ts +0 -550
  693. package/src/__tests__/curator-extra-ops.test.ts +0 -383
  694. package/src/__tests__/deprecation.test.ts +0 -78
  695. package/src/__tests__/domain-ops.test.ts +0 -226
  696. package/src/__tests__/domain-packs.test.ts +0 -421
  697. package/src/__tests__/enforcement.test.ts +0 -153
  698. package/src/__tests__/errors.test.ts +0 -388
  699. package/src/__tests__/extensions.test.ts +0 -233
  700. package/src/__tests__/facade-factory.test.ts +0 -271
  701. package/src/__tests__/feature-flags.test.ts +0 -137
  702. package/src/__tests__/flows.test.ts +0 -604
  703. package/src/__tests__/git-vault-sync.test.ts +0 -230
  704. package/src/__tests__/governance.test.ts +0 -522
  705. package/src/__tests__/grading-ops.test.ts +0 -361
  706. package/src/__tests__/identity-manager.test.ts +0 -243
  707. package/src/__tests__/intake-pipeline.test.ts +0 -162
  708. package/src/__tests__/intent-router.test.ts +0 -222
  709. package/src/__tests__/knowledge-review.test.ts +0 -104
  710. package/src/__tests__/llm-client.test.ts +0 -69
  711. package/src/__tests__/llm.test.ts +0 -556
  712. package/src/__tests__/loader.test.ts +0 -176
  713. package/src/__tests__/loop-ops.test.ts +0 -469
  714. package/src/__tests__/lsp-transport.test.ts +0 -442
  715. package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
  716. package/src/__tests__/memory-extra-ops.test.ts +0 -352
  717. package/src/__tests__/migration-runner.test.ts +0 -170
  718. package/src/__tests__/module-manifest-drift.test.ts +0 -59
  719. package/src/__tests__/normalize.test.ts +0 -85
  720. package/src/__tests__/obsidian-sync.test.ts +0 -354
  721. package/src/__tests__/orchestrate-ops.test.ts +0 -289
  722. package/src/__tests__/pack-ops.test.ts +0 -146
  723. package/src/__tests__/persistence.test.ts +0 -291
  724. package/src/__tests__/planning-extra-ops.test.ts +0 -706
  725. package/src/__tests__/playbook-executor.test.ts +0 -249
  726. package/src/__tests__/playbook-registry.test.ts +0 -326
  727. package/src/__tests__/playbook-seeder.test.ts +0 -163
  728. package/src/__tests__/playbook.test.ts +0 -389
  729. package/src/__tests__/plugin-ops.test.ts +0 -411
  730. package/src/__tests__/plugin-system.test.ts +0 -509
  731. package/src/__tests__/project-ops.test.ts +0 -381
  732. package/src/__tests__/replayable-stream.test.ts +0 -177
  733. package/src/__tests__/runtime.test.ts +0 -95
  734. package/src/__tests__/scope-detector.test.ts +0 -121
  735. package/src/__tests__/template-manager.test.ts +0 -222
  736. package/src/__tests__/token-resolver.test.ts +0 -79
  737. package/src/__tests__/transport.test.ts +0 -758
  738. package/src/__tests__/vault-branching.test.ts +0 -274
  739. package/src/__tests__/vault-extra-ops.test.ts +0 -482
  740. package/src/__tests__/vault-integrity.test.ts +0 -71
  741. package/src/__tests__/vault-manager.test.ts +0 -238
  742. package/src/__tests__/ws-transport.test.ts +0 -479
  743. package/src/engine/index.ts +0 -21
  744. package/src/persona/index.ts +0 -9
@@ -1,137 +1,42 @@
1
+ /**
2
+ * Planner facade — delegates to extracted modules, owns persistence.
3
+ * Re-exports all public types for backward compatibility.
4
+ */
1
5
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
2
- import { createHash } from 'node:crypto';
3
6
  import { dirname } from 'node:path';
4
- import { SEVERITY_WEIGHTS, CATEGORY_PENALTY_CAPS, CATEGORY_BONUS_CAPS } from './gap-types.js';
5
7
  import { runGapAnalysis } from './gap-analysis.js';
6
- /**
7
- * Valid status transitions.
8
- * Each key maps to the set of statuses it can transition to.
9
- * Ported from Salvador's LIFECYCLE_TRANSITIONS.
10
- */
11
- export const LIFECYCLE_TRANSITIONS = {
12
- brainstorming: ['draft'],
13
- draft: ['approved'],
14
- approved: ['executing'],
15
- executing: ['validating', 'reconciling'],
16
- validating: ['reconciling', 'executing'],
17
- reconciling: ['completed'],
18
- completed: ['archived'],
19
- archived: [],
20
- };
21
- /**
22
- * Statuses where the 30-minute TTL should NOT apply.
23
- * Plans in these states may span multiple sessions.
24
- */
25
- export const NON_EXPIRING_STATUSES = [
26
- 'brainstorming',
27
- 'executing',
28
- 'validating',
29
- 'reconciling',
30
- ];
31
- /**
32
- * Validate a lifecycle status transition.
33
- * Returns true if the transition is valid, false otherwise.
34
- */
35
- export function isValidTransition(from, to) {
36
- return LIFECYCLE_TRANSITIONS[from].includes(to);
37
- }
38
- /**
39
- * Get the valid next statuses for a given status.
40
- */
41
- export function getValidNextStatuses(status) {
42
- return LIFECYCLE_TRANSITIONS[status];
43
- }
44
- /**
45
- * Check if a status should have TTL expiration.
46
- * Plans in executing/reconciling states persist indefinitely.
47
- */
48
- export function shouldExpire(status) {
49
- return !NON_EXPIRING_STATUSES.includes(status);
50
- }
51
- /**
52
- * Severity weights for drift accuracy score calculation.
53
- * Score = 100 - sum(drift_items * weight_per_impact)
54
- * Ported from Salvador's plan-lifecycle-types.ts.
55
- */
56
- export const DRIFT_WEIGHTS = {
57
- high: 20,
58
- medium: 10,
59
- low: 5,
60
- };
61
- /**
62
- * Calculate drift accuracy score from drift items.
63
- * Score = max(0, 100 - sum(weight_per_impact))
64
- * Ported from Salvador's calculateDriftScore.
65
- */
66
- export function calculateDriftScore(items) {
67
- let deductions = 0;
68
- for (const item of items) {
69
- deductions += DRIFT_WEIGHTS[item.impact];
70
- }
71
- return Math.max(0, 100 - deductions);
72
- }
73
- /**
74
- * Calculate score from gaps with severity-weighted deductions and iteration leniency.
75
- * Ported from Salvador MCP's plan-grading.ts.
76
- *
77
- * - Minor gaps: weight=0 on iteration 1 (free sketching), weight=1 on iteration 2, full weight on 3+
78
- * - Per-category deductions are capped before summing (prevents one category from tanking the score)
79
- * - Score = max(0, 100 - totalDeductions)
80
- */
81
- export function calculateScore(gaps, iteration = 1) {
82
- const categoryDeductions = new Map();
83
- const categoryBonuses = new Map();
84
- for (const gap of gaps) {
85
- let weight = SEVERITY_WEIGHTS[gap.severity];
86
- // Iteration leniency for minor gaps
87
- if (gap.severity === 'minor') {
88
- if (iteration === 1)
89
- weight = 0;
90
- else if (iteration === 2)
91
- weight = 1;
92
- // iteration 3+: full weight (2)
93
- }
94
- const category = gap.category;
95
- if (weight < 0) {
96
- // Bonus — accumulate as positive value for capping, apply as negative deduction
97
- categoryBonuses.set(category, (categoryBonuses.get(category) ?? 0) + Math.abs(weight));
98
- }
99
- else {
100
- categoryDeductions.set(category, (categoryDeductions.get(category) ?? 0) + weight);
101
- }
102
- }
103
- let deductions = 0;
104
- for (const [category, total] of categoryDeductions) {
105
- const cap = CATEGORY_PENALTY_CAPS[category];
106
- deductions += cap !== undefined ? Math.min(total, cap) : total;
107
- }
108
- let bonuses = 0;
109
- for (const [category, total] of categoryBonuses) {
110
- const cap = CATEGORY_BONUS_CAPS[category];
111
- bonuses += cap !== undefined ? Math.min(total, cap) : total;
112
- }
113
- return Math.max(0, Math.min(100, 100 - deductions + bonuses));
114
- }
8
+ export * from './plan-lifecycle.js';
9
+ export * from './reconciliation-engine.js';
10
+ export * from './task-verifier.js';
11
+ export * from './planner-types.js';
12
+ import { applyTransition, scoreToGrade, gradeToMinScore, PlanGradeRejectionError, hasCircularDependencies, applyIteration, applySplitTasks, calculateScore, applyTaskStatusUpdate, createPlanObject, } from './plan-lifecycle.js';
13
+ import { buildReconciliationReport, buildAutoReconcileInput, computeExecutionSummary, } from './reconciliation-engine.js';
14
+ import { createEvidence, verifyTaskLogic, verifyPlanLogic, verifyDeliverablesLogic, createDeliverable, buildSpecReviewPrompt, buildQualityReviewPrompt, } from './task-verifier.js';
115
15
  export class Planner {
116
16
  filePath;
117
17
  store;
118
18
  gapOptions;
119
- constructor(filePath, gapOptions) {
19
+ minGradeForApproval;
20
+ constructor(filePath, options) {
120
21
  this.filePath = filePath;
121
- this.gapOptions = gapOptions;
22
+ if (options && 'minGradeForApproval' in options) {
23
+ this.gapOptions = options.gapOptions;
24
+ this.minGradeForApproval = options.minGradeForApproval ?? 'A';
25
+ }
26
+ else {
27
+ this.gapOptions = options;
28
+ this.minGradeForApproval = 'A';
29
+ }
122
30
  this.store = this.load();
123
31
  }
124
32
  load() {
125
- if (!existsSync(this.filePath)) {
33
+ if (!existsSync(this.filePath))
126
34
  return { version: '1.0', plans: [] };
127
- }
128
35
  try {
129
36
  const data = readFileSync(this.filePath, 'utf-8');
130
37
  const store = JSON.parse(data);
131
- // Backward compatibility: ensure every plan has a checks array
132
- for (const plan of store.plans) {
38
+ for (const plan of store.plans)
133
39
  plan.checks = plan.checks ?? [];
134
- }
135
40
  return store;
136
41
  }
137
42
  catch {
@@ -142,31 +47,25 @@ export class Planner {
142
47
  mkdirSync(dirname(this.filePath), { recursive: true });
143
48
  writeFileSync(this.filePath, JSON.stringify(this.store, null, 2), 'utf-8');
144
49
  }
50
+ transition(plan, to) {
51
+ const r = applyTransition(plan.status, to);
52
+ plan.status = r.status;
53
+ plan.updatedAt = r.updatedAt;
54
+ }
55
+ requirePlan(planId) {
56
+ const plan = this.get(planId);
57
+ if (!plan)
58
+ throw new Error(`Plan not found: ${planId}`);
59
+ return plan;
60
+ }
61
+ requireTask(plan, taskId) {
62
+ const task = plan.tasks.find((t) => t.id === taskId);
63
+ if (!task)
64
+ throw new Error(`Task not found: ${taskId}`);
65
+ return task;
66
+ }
145
67
  create(params) {
146
- const now = Date.now();
147
- const plan = {
148
- id: `plan-${now}-${Math.random().toString(36).slice(2, 8)}`,
149
- objective: params.objective,
150
- scope: params.scope,
151
- status: params.initialStatus ?? 'draft',
152
- decisions: params.decisions ?? [],
153
- tasks: (params.tasks ?? []).map((t, i) => ({
154
- id: `task-${i + 1}`,
155
- title: t.title,
156
- description: t.description,
157
- status: 'pending',
158
- updatedAt: now,
159
- })),
160
- ...(params.approach !== undefined && { approach: params.approach }),
161
- ...(params.context !== undefined && { context: params.context }),
162
- ...(params.success_criteria !== undefined && { success_criteria: params.success_criteria }),
163
- ...(params.tool_chain !== undefined && { tool_chain: params.tool_chain }),
164
- ...(params.flow !== undefined && { flow: params.flow }),
165
- ...(params.target_mode !== undefined && { target_mode: params.target_mode }),
166
- checks: [],
167
- createdAt: now,
168
- updatedAt: now,
169
- };
68
+ const plan = createPlanObject(params);
170
69
  this.store.plans.push(plan);
171
70
  this.save();
172
71
  return plan;
@@ -177,9 +76,6 @@ export class Planner {
177
76
  list() {
178
77
  return [...this.store.plans];
179
78
  }
180
- /**
181
- * Permanently remove a plan by ID. Returns true if found and removed.
182
- */
183
79
  remove(planId) {
184
80
  const idx = this.store.plans.findIndex((p) => p.id === planId);
185
81
  if (idx < 0)
@@ -188,114 +84,82 @@ export class Planner {
188
84
  this.save();
189
85
  return true;
190
86
  }
191
- /**
192
- * Transition a plan to a new status using the typed FSM.
193
- * Validates that the transition is allowed before applying it.
194
- */
195
- transition(plan, to) {
196
- if (!isValidTransition(plan.status, to)) {
197
- const valid = getValidNextStatuses(plan.status);
198
- throw new Error(`Invalid transition: '${plan.status}' → '${to}'. ` +
199
- `Valid transitions from '${plan.status}': ${valid.length > 0 ? valid.join(', ') : 'none'}`);
200
- }
201
- plan.status = to;
202
- plan.updatedAt = Date.now();
203
- }
204
- /**
205
- * Promote a brainstorming plan to draft status.
206
- * Only allowed from 'brainstorming'.
207
- */
208
87
  promoteToDraft(planId) {
209
- const plan = this.get(planId);
210
- if (!plan)
211
- throw new Error(`Plan not found: ${planId}`);
88
+ const plan = this.requirePlan(planId);
212
89
  this.transition(plan, 'draft');
213
90
  this.save();
214
91
  return plan;
215
92
  }
216
93
  approve(planId) {
217
- const plan = this.get(planId);
218
- if (!plan)
219
- throw new Error(`Plan not found: ${planId}`);
94
+ const plan = this.requirePlan(planId);
95
+ const check = plan.latestCheck;
96
+ if (check && check.score < gradeToMinScore(this.minGradeForApproval)) {
97
+ throw new PlanGradeRejectionError(check.grade, check.score, this.minGradeForApproval, check.gaps);
98
+ }
220
99
  this.transition(plan, 'approved');
221
100
  this.save();
222
101
  return plan;
223
102
  }
224
103
  startExecution(planId) {
225
- const plan = this.get(planId);
226
- if (!plan)
227
- throw new Error(`Plan not found: ${planId}`);
104
+ const plan = this.requirePlan(planId);
228
105
  this.transition(plan, 'executing');
229
106
  this.save();
230
107
  return plan;
231
108
  }
232
- updateTask(planId, taskId, status) {
233
- const plan = this.get(planId);
234
- if (!plan)
235
- throw new Error(`Plan not found: ${planId}`);
236
- if (plan.status !== 'executing' && plan.status !== 'validating')
237
- throw new Error(`Cannot update tasks on plan in '${plan.status}' status — must be 'executing' or 'validating'`);
238
- const task = plan.tasks.find((t) => t.id === taskId);
239
- if (!task)
240
- throw new Error(`Task not found: ${taskId}`);
241
- const now = Date.now();
242
- // Auto-set startedAt on first in_progress transition
243
- if (status === 'in_progress' && !task.startedAt) {
244
- task.startedAt = now;
245
- }
246
- // Auto-set completedAt and compute durationMs on terminal transitions
247
- if (status === 'completed' || status === 'skipped' || status === 'failed') {
248
- task.completedAt = now;
249
- if (task.startedAt) {
250
- if (!task.metrics)
251
- task.metrics = {};
252
- task.metrics.durationMs = now - task.startedAt;
253
- }
254
- }
255
- task.status = status;
256
- task.updatedAt = now;
257
- plan.updatedAt = now;
258
- this.save();
259
- return plan;
260
- }
261
- /**
262
- * Transition plan to 'validating' state (post-execution verification).
263
- * Only allowed from 'executing'.
264
- */
265
109
  startValidation(planId) {
266
- const plan = this.get(planId);
267
- if (!plan)
268
- throw new Error(`Plan not found: ${planId}`);
110
+ const plan = this.requirePlan(planId);
269
111
  this.transition(plan, 'validating');
270
112
  this.save();
271
113
  return plan;
272
114
  }
273
- /**
274
- * Transition plan to 'reconciling' state.
275
- * Allowed from 'executing' or 'validating'.
276
- */
277
115
  startReconciliation(planId) {
278
- const plan = this.get(planId);
279
- if (!plan)
280
- throw new Error(`Plan not found: ${planId}`);
116
+ const plan = this.requirePlan(planId);
281
117
  this.transition(plan, 'reconciling');
282
118
  this.save();
283
119
  return plan;
284
120
  }
285
- /**
286
- * Complete a plan. Only allowed from 'reconciling'.
287
- * Use startReconciliation() + reconcile() + complete() for the full lifecycle,
288
- * or reconcile() which auto-transitions through reconciling completed.
289
- */
121
+ updateTask(planId, taskId, status) {
122
+ const plan = this.requirePlan(planId);
123
+ if (plan.status !== 'executing' && plan.status !== 'validating')
124
+ throw new Error(`Cannot update tasks on plan in '${plan.status}' status — must be 'executing' or 'validating'`);
125
+ applyTaskStatusUpdate(this.requireTask(plan, taskId), status);
126
+ plan.updatedAt = Date.now();
127
+ this.save();
128
+ return plan;
129
+ }
130
+ reconcile(planId, report) {
131
+ const plan = this.requirePlan(planId);
132
+ if (plan.status !== 'executing' &&
133
+ plan.status !== 'validating' &&
134
+ plan.status !== 'reconciling')
135
+ throw new Error(`Cannot reconcile plan in '${plan.status}' status — must be 'executing', 'validating', or 'reconciling'`);
136
+ plan.reconciliation = buildReconciliationReport(planId, report);
137
+ plan.executionSummary = computeExecutionSummary(plan.tasks);
138
+ if (plan.status === 'executing' || plan.status === 'validating')
139
+ plan.status = 'reconciling';
140
+ plan.status = 'completed';
141
+ plan.updatedAt = Date.now();
142
+ this.save();
143
+ return plan;
144
+ }
290
145
  complete(planId) {
291
- const plan = this.get(planId);
292
- if (!plan)
293
- throw new Error(`Plan not found: ${planId}`);
294
- plan.executionSummary = this.computeExecutionSummary(plan);
146
+ const plan = this.requirePlan(planId);
147
+ if (plan.status === 'executing' || plan.status === 'validating')
148
+ return this.reconcile(planId, { actualOutcome: 'All tasks completed', reconciledBy: 'auto' });
149
+ plan.executionSummary = computeExecutionSummary(plan.tasks);
295
150
  this.transition(plan, 'completed');
296
151
  this.save();
297
152
  return plan;
298
153
  }
154
+ autoReconcile(planId) {
155
+ const plan = this.requirePlan(planId);
156
+ if (plan.status !== 'executing' && plan.status !== 'validating')
157
+ throw new Error(`Cannot auto-reconcile plan in '${plan.status}' status — must be 'executing' or 'validating'`);
158
+ const result = buildAutoReconcileInput(plan.tasks);
159
+ if (!result.canAutoReconcile || !result.input)
160
+ return null;
161
+ return this.reconcile(planId, result.input);
162
+ }
299
163
  getExecuting() {
300
164
  return this.store.plans.filter((p) => p.status === 'executing' || p.status === 'validating');
301
165
  }
@@ -307,145 +171,26 @@ export class Planner {
307
171
  p.status === 'validating' ||
308
172
  p.status === 'reconciling');
309
173
  }
310
- /**
311
- * Iterate on a draft plan — modify objective, scope, decisions, or tasks.
312
- * Only allowed on plans in 'draft' status.
313
- */
314
174
  iterate(planId, changes) {
315
- const plan = this.get(planId);
316
- if (!plan)
317
- throw new Error(`Plan not found: ${planId}`);
175
+ const plan = this.requirePlan(planId);
318
176
  if (plan.status !== 'draft' && plan.status !== 'brainstorming')
319
177
  throw new Error(`Cannot iterate plan in '${plan.status}' status — must be 'draft' or 'brainstorming'`);
320
- const now = Date.now();
321
- if (changes.objective !== undefined)
322
- plan.objective = changes.objective;
323
- if (changes.scope !== undefined)
324
- plan.scope = changes.scope;
325
- if (changes.decisions !== undefined)
326
- plan.decisions = changes.decisions;
327
- if (changes.approach !== undefined)
328
- plan.approach = changes.approach;
329
- if (changes.context !== undefined)
330
- plan.context = changes.context;
331
- if (changes.success_criteria !== undefined)
332
- plan.success_criteria = changes.success_criteria;
333
- if (changes.tool_chain !== undefined)
334
- plan.tool_chain = changes.tool_chain;
335
- if (changes.flow !== undefined)
336
- plan.flow = changes.flow;
337
- if (changes.target_mode !== undefined)
338
- plan.target_mode = changes.target_mode;
339
- // Remove tasks by ID
340
- if (changes.removeTasks && changes.removeTasks.length > 0) {
341
- const removeSet = new Set(changes.removeTasks);
342
- plan.tasks = plan.tasks.filter((t) => !removeSet.has(t.id));
343
- }
344
- // Add new tasks
345
- if (changes.addTasks && changes.addTasks.length > 0) {
346
- const maxIndex = plan.tasks.reduce((max, t) => {
347
- const num = parseInt(t.id.replace('task-', ''), 10);
348
- return isNaN(num) ? max : Math.max(max, num);
349
- }, 0);
350
- for (let i = 0; i < changes.addTasks.length; i++) {
351
- plan.tasks.push({
352
- id: `task-${maxIndex + i + 1}`,
353
- title: changes.addTasks[i].title,
354
- description: changes.addTasks[i].description,
355
- status: 'pending',
356
- updatedAt: now,
357
- });
358
- }
359
- }
360
- plan.updatedAt = now;
178
+ applyIteration(plan, changes);
361
179
  this.save();
362
180
  return plan;
363
181
  }
364
- /**
365
- * Split a plan's tasks into sub-tasks with dependency tracking.
366
- * Replaces existing tasks with a new set that includes dependency references.
367
- * Only allowed on 'draft' or 'approved' plans.
368
- */
369
182
  splitTasks(planId, tasks) {
370
- const plan = this.get(planId);
371
- if (!plan)
372
- throw new Error(`Plan not found: ${planId}`);
183
+ const plan = this.requirePlan(planId);
373
184
  if (plan.status !== 'brainstorming' && plan.status !== 'draft' && plan.status !== 'approved')
374
185
  throw new Error(`Cannot split tasks on plan in '${plan.status}' status — must be 'brainstorming', 'draft', or 'approved'`);
375
- const now = Date.now();
376
- plan.tasks = tasks.map((t, i) => ({
377
- id: `task-${i + 1}`,
378
- title: t.title,
379
- description: t.description,
380
- status: 'pending',
381
- dependsOn: t.dependsOn,
382
- ...(t.acceptanceCriteria && { acceptanceCriteria: t.acceptanceCriteria }),
383
- updatedAt: now,
384
- }));
385
- // Validate dependency references
386
- const taskIds = new Set(plan.tasks.map((t) => t.id));
387
- for (const task of plan.tasks) {
388
- if (task.dependsOn) {
389
- for (const dep of task.dependsOn) {
390
- if (!taskIds.has(dep)) {
391
- throw new Error(`Task '${task.id}' depends on unknown task '${dep}'`);
392
- }
393
- }
394
- }
395
- }
396
- plan.updatedAt = now;
186
+ applySplitTasks(plan, tasks);
397
187
  this.save();
398
188
  return plan;
399
189
  }
400
- /**
401
- * Reconcile a plan — compare what was planned vs what actually happened.
402
- * Uses impact-weighted drift scoring (ported from Salvador's calculateDriftScore).
403
- *
404
- * Transitions: executing → reconciling → completed (automatic).
405
- * Also allowed from 'validating' and 'reconciling' states.
406
- */
407
- reconcile(planId, report) {
408
- const plan = this.get(planId);
409
- if (!plan)
410
- throw new Error(`Plan not found: ${planId}`);
411
- if (plan.status !== 'executing' &&
412
- plan.status !== 'validating' &&
413
- plan.status !== 'reconciling')
414
- throw new Error(`Cannot reconcile plan in '${plan.status}' status — must be 'executing', 'validating', or 'reconciling'`);
415
- const driftItems = report.driftItems ?? [];
416
- // Impact-weighted drift scoring (ported from Salvador)
417
- const accuracy = calculateDriftScore(driftItems);
418
- plan.reconciliation = {
419
- planId,
420
- accuracy,
421
- driftItems,
422
- summary: report.actualOutcome,
423
- reconciledAt: Date.now(),
424
- };
425
- // Compute execution summary from per-task metrics
426
- plan.executionSummary = this.computeExecutionSummary(plan);
427
- // Transition through reconciling → completed via FSM
428
- if (plan.status === 'executing' || plan.status === 'validating') {
429
- plan.status = 'reconciling';
430
- }
431
- // Auto-complete after reconciliation
432
- plan.status = 'completed';
433
- plan.updatedAt = Date.now();
434
- this.save();
435
- return plan;
436
- }
437
- /**
438
- * Add review evidence to a plan or specific task.
439
- */
440
190
  addReview(planId, review) {
441
- const plan = this.get(planId);
442
- if (!plan)
443
- throw new Error(`Plan not found: ${planId}`);
444
- if (review.taskId) {
445
- const task = plan.tasks.find((t) => t.id === review.taskId);
446
- if (!task)
447
- throw new Error(`Task not found: ${review.taskId}`);
448
- }
191
+ const plan = this.requirePlan(planId);
192
+ if (review.taskId)
193
+ this.requireTask(plan, review.taskId);
449
194
  if (!plan.reviews)
450
195
  plan.reviews = [];
451
196
  plan.reviews.push({
@@ -460,432 +205,101 @@ export class Planner {
460
205
  this.save();
461
206
  return plan;
462
207
  }
463
- /**
464
- * Get dispatch instructions for a specific task — returns the task and its
465
- * unmet dependencies so a subagent knows what to work on and what to wait for.
466
- */
467
- getDispatch(planId, taskId) {
468
- const plan = this.get(planId);
469
- if (!plan)
470
- throw new Error(`Plan not found: ${planId}`);
471
- const task = plan.tasks.find((t) => t.id === taskId);
472
- if (!task)
473
- throw new Error(`Task not found: ${taskId}`);
474
- const unmetDependencies = [];
475
- if (task.dependsOn) {
476
- for (const depId of task.dependsOn) {
477
- const dep = plan.tasks.find((t) => t.id === depId);
478
- if (dep && dep.status !== 'completed') {
479
- unmetDependencies.push(dep);
480
- }
481
- }
482
- }
483
- const result = {
484
- task,
485
- unmetDependencies,
486
- ready: unmetDependencies.length === 0,
487
- };
488
- // Include deliverable status if deliverables exist
489
- if (task.deliverables && task.deliverables.length > 0) {
490
- result.deliverableStatus = {
491
- count: task.deliverables.length,
492
- staleCount: task.deliverables.filter((d) => d.stale).length,
493
- };
494
- }
495
- return result;
208
+ setGitHubProjection(planId, projection) {
209
+ const plan = this.requirePlan(planId);
210
+ plan.githubProjection = projection;
211
+ plan.updatedAt = Date.now();
212
+ this.save();
213
+ return plan;
496
214
  }
497
- // ─── Execution Metrics & Deliverables ──────────────────────────
498
- /**
499
- * Compute aggregate execution summary from per-task metrics.
500
- * Called from reconcile() and complete() to populate plan.executionSummary.
501
- */
502
- computeExecutionSummary(plan) {
503
- let totalDurationMs = 0;
504
- let tasksCompleted = 0;
505
- let tasksSkipped = 0;
506
- let tasksFailed = 0;
507
- let tasksWithDuration = 0;
508
- for (const task of plan.tasks) {
509
- if (task.status === 'completed')
510
- tasksCompleted++;
511
- else if (task.status === 'skipped')
512
- tasksSkipped++;
513
- else if (task.status === 'failed')
514
- tasksFailed++;
515
- if (task.metrics?.durationMs) {
516
- totalDurationMs += task.metrics.durationMs;
517
- tasksWithDuration++;
518
- }
215
+ getDispatch(planId, taskId) {
216
+ const plan = this.requirePlan(planId);
217
+ const task = this.requireTask(plan, taskId);
218
+ const unmetDeps = [];
219
+ for (const depId of task.dependsOn ?? []) {
220
+ const dep = plan.tasks.find((t) => t.id === depId);
221
+ if (dep && dep.status !== 'completed')
222
+ unmetDeps.push(dep);
519
223
  }
520
224
  return {
521
- totalDurationMs,
522
- tasksCompleted,
523
- tasksSkipped,
524
- tasksFailed,
525
- avgTaskDurationMs: tasksWithDuration > 0 ? Math.round(totalDurationMs / tasksWithDuration) : 0,
225
+ task,
226
+ unmetDependencies: unmetDeps,
227
+ ready: unmetDeps.length === 0,
228
+ ...(task.deliverables?.length && {
229
+ deliverableStatus: {
230
+ count: task.deliverables.length,
231
+ staleCount: task.deliverables.filter((d) => d.stale).length,
232
+ },
233
+ }),
526
234
  };
527
235
  }
528
- /**
529
- * Submit a deliverable for a task. Auto-computes SHA-256 hash for file deliverables.
530
- */
531
236
  submitDeliverable(planId, taskId, deliverable) {
532
- const plan = this.get(planId);
533
- if (!plan)
534
- throw new Error(`Plan not found: ${planId}`);
535
- const task = plan.tasks.find((t) => t.id === taskId);
536
- if (!task)
537
- throw new Error(`Task not found: ${taskId}`);
538
- const entry = {
539
- type: deliverable.type,
540
- path: deliverable.path,
541
- };
542
- // Auto-compute hash for file deliverables
543
- if (deliverable.type === 'file' && !deliverable.hash) {
544
- try {
545
- if (existsSync(deliverable.path)) {
546
- const content = readFileSync(deliverable.path);
547
- entry.hash = createHash('sha256').update(content).digest('hex');
548
- }
549
- }
550
- catch {
551
- // Graceful degradation — skip hash if file can't be read
552
- }
553
- }
554
- else if (deliverable.hash) {
555
- entry.hash = deliverable.hash;
556
- }
237
+ const plan = this.requirePlan(planId);
238
+ const task = this.requireTask(plan, taskId);
557
239
  if (!task.deliverables)
558
240
  task.deliverables = [];
559
- task.deliverables.push(entry);
241
+ task.deliverables.push(createDeliverable(deliverable));
560
242
  task.updatedAt = Date.now();
561
243
  plan.updatedAt = Date.now();
562
244
  this.save();
563
245
  return task;
564
246
  }
565
- /**
566
- * Verify all deliverables for a task.
567
- * - file: checks existsSync + SHA-256 hash match
568
- * - vault_entry: checks vault.get(path) non-null (requires vault instance)
569
- * - url: skips (just records, no fetch)
570
- */
571
247
  verifyDeliverables(planId, taskId, vault) {
572
- const plan = this.get(planId);
573
- if (!plan)
574
- throw new Error(`Plan not found: ${planId}`);
575
- const task = plan.tasks.find((t) => t.id === taskId);
576
- if (!task)
577
- throw new Error(`Task not found: ${taskId}`);
578
- const deliverables = task.deliverables ?? [];
579
- let staleCount = 0;
580
- const now = Date.now();
581
- for (const d of deliverables) {
582
- d.stale = false;
583
- if (d.type === 'file') {
584
- if (!existsSync(d.path)) {
585
- d.stale = true;
586
- staleCount++;
587
- }
588
- else if (d.hash) {
589
- try {
590
- const content = readFileSync(d.path);
591
- const currentHash = createHash('sha256').update(content).digest('hex');
592
- if (currentHash !== d.hash) {
593
- d.stale = true;
594
- staleCount++;
595
- }
596
- }
597
- catch {
598
- d.stale = true;
599
- staleCount++;
600
- }
601
- }
602
- d.verifiedAt = now;
603
- }
604
- else if (d.type === 'vault_entry') {
605
- if (vault) {
606
- const entry = vault.get(d.path);
607
- if (!entry) {
608
- d.stale = true;
609
- staleCount++;
610
- }
611
- }
612
- d.verifiedAt = now;
613
- }
614
- // url: skip — just record
615
- }
248
+ const plan = this.requirePlan(planId);
249
+ const task = this.requireTask(plan, taskId);
250
+ const result = verifyDeliverablesLogic(task.deliverables ?? [], vault);
251
+ task.deliverables = result.deliverables;
616
252
  plan.updatedAt = Date.now();
617
253
  this.save();
618
- return { verified: staleCount === 0, deliverables, staleCount };
254
+ return result;
619
255
  }
620
- // ─── Evidence & Verification ────────────────────────────────────
621
- /**
622
- * Submit evidence for a task acceptance criterion.
623
- * Evidence is stored on the task and used by verifyTask() to check completeness.
624
- */
625
256
  submitEvidence(planId, taskId, evidence) {
626
- const plan = this.get(planId);
627
- if (!plan)
628
- throw new Error(`Plan not found: ${planId}`);
629
- const task = plan.tasks.find((t) => t.id === taskId);
630
- if (!task)
631
- throw new Error(`Task not found: ${taskId}`);
632
- if (!task.evidence)
633
- task.evidence = [];
634
- task.evidence.push({
635
- criterion: evidence.criterion,
636
- content: evidence.content,
637
- type: evidence.type,
638
- submittedAt: Date.now(),
639
- });
257
+ const plan = this.requirePlan(planId);
258
+ const task = this.requireTask(plan, taskId);
259
+ task.evidence = createEvidence(task.evidence ?? [], evidence);
640
260
  task.updatedAt = Date.now();
641
261
  plan.updatedAt = Date.now();
642
262
  this.save();
643
263
  return task;
644
264
  }
645
- /**
646
- * Verify a task — check that evidence exists for all acceptance criteria
647
- * and any reviews have passed.
648
- * Returns verification status with details.
649
- */
650
265
  verifyTask(planId, taskId) {
651
- const plan = this.get(planId);
652
- if (!plan)
653
- throw new Error(`Plan not found: ${planId}`);
654
- const task = plan.tasks.find((t) => t.id === taskId);
655
- if (!task)
656
- throw new Error(`Task not found: ${taskId}`);
657
- // Check evidence coverage
658
- const criteria = task.acceptanceCriteria ?? [];
659
- const evidencedCriteria = new Set((task.evidence ?? []).map((e) => e.criterion));
660
- const missingCriteria = criteria.filter((c) => !evidencedCriteria.has(c));
661
- // Check task-level reviews
662
- const taskReviews = (plan.reviews ?? []).filter((r) => r.taskId === taskId);
663
- let reviewStatus = 'no_reviews';
664
- if (taskReviews.length > 0) {
665
- const latest = taskReviews[taskReviews.length - 1];
666
- reviewStatus = latest.outcome;
667
- }
668
- const verified = task.status === 'completed' &&
669
- missingCriteria.length === 0 &&
670
- (reviewStatus === 'approved' || reviewStatus === 'no_reviews');
671
- if (verified !== task.verified) {
672
- task.verified = verified;
266
+ const plan = this.requirePlan(planId);
267
+ const task = this.requireTask(plan, taskId);
268
+ const result = verifyTaskLogic(task, plan.reviews ?? []);
269
+ if (result.verified !== task.verified) {
270
+ task.verified = result.verified;
673
271
  task.updatedAt = Date.now();
674
272
  plan.updatedAt = Date.now();
675
273
  this.save();
676
274
  }
677
- return { verified, task, missingCriteria, reviewStatus };
275
+ return { ...result, task };
678
276
  }
679
- /**
680
- * Verify an entire plan — check all tasks are in a final state,
681
- * all verification-required tasks have evidence, no tasks stuck in_progress.
682
- * Returns a validation report.
683
- */
684
277
  verifyPlan(planId) {
685
- const plan = this.get(planId);
686
- if (!plan)
687
- throw new Error(`Plan not found: ${planId}`);
688
- const issues = [];
689
- let verified = 0;
690
- let completed = 0;
691
- let skipped = 0;
692
- let failed = 0;
693
- let pending = 0;
694
- let inProgress = 0;
695
- for (const task of plan.tasks) {
696
- switch (task.status) {
697
- case 'completed':
698
- completed++;
699
- break;
700
- case 'skipped':
701
- skipped++;
702
- break;
703
- case 'failed':
704
- failed++;
705
- break;
706
- case 'pending':
707
- pending++;
708
- break;
709
- case 'in_progress':
710
- inProgress++;
711
- break;
712
- }
713
- if (task.verified)
714
- verified++;
715
- // Check for stuck tasks
716
- if (task.status === 'in_progress') {
717
- issues.push({ taskId: task.id, issue: 'Task stuck in in_progress state' });
718
- }
719
- if (task.status === 'pending') {
720
- issues.push({ taskId: task.id, issue: 'Task still pending — not started' });
721
- }
722
- // Check evidence for completed tasks with acceptance criteria
723
- if (task.status === 'completed' &&
724
- task.acceptanceCriteria &&
725
- task.acceptanceCriteria.length > 0) {
726
- const evidencedCriteria = new Set((task.evidence ?? []).map((e) => e.criterion));
727
- const missing = task.acceptanceCriteria.filter((c) => !evidencedCriteria.has(c));
728
- if (missing.length > 0) {
729
- issues.push({
730
- taskId: task.id,
731
- issue: `Missing evidence for ${missing.length} criteria: ${missing.join(', ')}`,
732
- });
733
- }
734
- }
735
- }
736
- const valid = issues.length === 0 && pending === 0 && inProgress === 0;
737
- return {
738
- valid,
739
- planId,
740
- issues,
741
- summary: {
742
- total: plan.tasks.length,
743
- completed,
744
- skipped,
745
- failed,
746
- pending,
747
- inProgress,
748
- verified,
749
- },
750
- };
751
- }
752
- /**
753
- * Auto-reconcile a plan — fast path for plans with minimal drift.
754
- * Checks all tasks are in final state, generates reconciliation report automatically.
755
- * Returns null if drift is too significant for auto-reconciliation (>2 non-completed tasks).
756
- */
757
- autoReconcile(planId) {
758
- const plan = this.get(planId);
759
- if (!plan)
760
- throw new Error(`Plan not found: ${planId}`);
761
- if (plan.status !== 'executing' && plan.status !== 'validating')
762
- throw new Error(`Cannot auto-reconcile plan in '${plan.status}' status — must be 'executing' or 'validating'`);
763
- const completed = plan.tasks.filter((t) => t.status === 'completed').length;
764
- const skipped = plan.tasks.filter((t) => t.status === 'skipped').length;
765
- const failed = plan.tasks.filter((t) => t.status === 'failed').length;
766
- const pending = plan.tasks.filter((t) => t.status === 'pending').length;
767
- const inProgress = plan.tasks.filter((t) => t.status === 'in_progress').length;
768
- // Can't auto-reconcile if tasks are still in progress
769
- if (inProgress > 0)
770
- return null;
771
- // Can't auto-reconcile if too many non-completed tasks
772
- if (pending + failed > 2)
773
- return null;
774
- const driftItems = [];
775
- for (const task of plan.tasks) {
776
- if (task.status === 'skipped') {
777
- driftItems.push({
778
- type: 'skipped',
779
- description: `Task '${task.title}' was skipped`,
780
- impact: 'medium',
781
- rationale: 'Task not executed during plan implementation',
782
- });
783
- }
784
- else if (task.status === 'failed') {
785
- driftItems.push({
786
- type: 'modified',
787
- description: `Task '${task.title}' failed`,
788
- impact: 'high',
789
- rationale: 'Task execution failed',
790
- });
791
- }
792
- else if (task.status === 'pending') {
793
- driftItems.push({
794
- type: 'skipped',
795
- description: `Task '${task.title}' was never started`,
796
- impact: 'low',
797
- rationale: 'Task left in pending state',
798
- });
799
- }
800
- }
801
- return this.reconcile(planId, {
802
- actualOutcome: `Auto-reconciled: ${completed}/${plan.tasks.length} tasks completed, ${skipped} skipped, ${failed} failed`,
803
- driftItems,
804
- reconciledBy: 'auto',
805
- });
278
+ return verifyPlanLogic(planId, this.requirePlan(planId).tasks);
806
279
  }
807
- /**
808
- * Generate a review prompt for spec compliance checking.
809
- * Used by subagent dispatch — the controller generates the prompt, a subagent executes it.
810
- */
811
280
  generateReviewSpec(planId, taskId) {
812
- const plan = this.get(planId);
813
- if (!plan)
814
- throw new Error(`Plan not found: ${planId}`);
815
- const task = plan.tasks.find((t) => t.id === taskId);
816
- if (!task)
817
- throw new Error(`Task not found: ${taskId}`);
818
- const criteria = task.acceptanceCriteria?.length
819
- ? `\n\nAcceptance Criteria:\n${task.acceptanceCriteria.map((c, i) => `${i + 1}. ${c}`).join('\n')}`
820
- : '';
821
- const prompt = [
822
- `# Spec Compliance Review`,
823
- ``,
824
- `## Task: ${task.title}`,
825
- `**Description:** ${task.description}`,
826
- `**Plan Objective:** ${plan.objective}${criteria}`,
827
- ``,
828
- `## Review Checklist`,
829
- `1. Does the implementation match the task description?`,
830
- `2. Are all acceptance criteria satisfied?`,
831
- `3. Does it align with the plan's overall objective?`,
832
- `4. Are there any spec deviations?`,
833
- ``,
834
- `Provide: outcome (approved/rejected/needs_changes) and detailed comments.`,
835
- ].join('\n');
836
- return { prompt, task, plan };
281
+ const plan = this.requirePlan(planId);
282
+ const task = this.requireTask(plan, taskId);
283
+ return { prompt: buildSpecReviewPrompt(task, plan.objective), task, plan };
837
284
  }
838
- /**
839
- * Generate a review prompt for code quality checking.
840
- */
841
285
  generateReviewQuality(planId, taskId) {
842
- const plan = this.get(planId);
843
- if (!plan)
844
- throw new Error(`Plan not found: ${planId}`);
845
- const task = plan.tasks.find((t) => t.id === taskId);
846
- if (!task)
847
- throw new Error(`Task not found: ${taskId}`);
848
- const prompt = [
849
- `# Code Quality Review`,
850
- ``,
851
- `## Task: ${task.title}`,
852
- `**Description:** ${task.description}`,
853
- ``,
854
- `## Quality Checklist`,
855
- `1. **Correctness** — Does it work as intended?`,
856
- `2. **Security** — No injection, XSS, or OWASP top 10 vulnerabilities?`,
857
- `3. **Performance** — No unnecessary allocations, N+1 queries, or blocking calls?`,
858
- `4. **Maintainability** — Clear naming, appropriate abstractions, documented intent?`,
859
- `5. **Testing** — Adequate test coverage for the changes?`,
860
- `6. **Error Handling** — Graceful degradation, no swallowed errors?`,
861
- `7. **Conventions** — Follows project coding standards?`,
862
- ``,
863
- `Provide: outcome (approved/rejected/needs_changes) and detailed comments.`,
864
- ].join('\n');
865
- return { prompt, task, plan };
286
+ const plan = this.requirePlan(planId);
287
+ const task = this.requireTask(plan, taskId);
288
+ return { prompt: buildQualityReviewPrompt(task), task, plan };
866
289
  }
867
- /**
868
- * Archive completed plans — transitions them to 'archived' status.
869
- * If olderThanDays is provided, only archives plans older than that.
870
- * Returns the archived plans.
871
- */
872
290
  archive(olderThanDays) {
873
291
  const cutoff = olderThanDays !== undefined
874
292
  ? Date.now() - olderThanDays * 24 * 60 * 60 * 1000
875
- : Date.now() + 1; // +1ms so archive() with no args archives all completed plans
293
+ : Date.now() + 1;
876
294
  const toArchive = this.store.plans.filter((p) => p.status === 'completed' && p.updatedAt < cutoff);
877
295
  for (const plan of toArchive) {
878
296
  plan.status = 'archived';
879
297
  plan.updatedAt = Date.now();
880
298
  }
881
- if (toArchive.length > 0) {
299
+ if (toArchive.length > 0)
882
300
  this.save();
883
- }
884
301
  return toArchive;
885
302
  }
886
- /**
887
- * Get statistics about all plans.
888
- */
889
303
  stats() {
890
304
  const plans = this.store.plans;
891
305
  const byStatus = {
@@ -909,41 +323,21 @@ export class Planner {
909
323
  for (const p of plans) {
910
324
  byStatus[p.status]++;
911
325
  totalTasks += p.tasks.length;
912
- for (const t of p.tasks) {
326
+ for (const t of p.tasks)
913
327
  tasksByStatus[t.status]++;
914
- }
915
328
  }
916
329
  return {
917
330
  total: plans.length,
918
331
  byStatus,
919
- avgTasksPerPlan: plans.length > 0 ? Math.round((totalTasks / plans.length) * 100) / 100 : 0,
920
332
  totalTasks,
921
333
  tasksByStatus,
334
+ avgTasksPerPlan: plans.length > 0 ? Math.round((totalTasks / plans.length) * 100) / 100 : 0,
922
335
  };
923
336
  }
924
- // ─── Grading ──────────────────────────────────────────────────────
925
- /**
926
- * Grade a plan using gap analysis with severity-weighted scoring.
927
- * Ported from Salvador MCP's multi-pass grading engine.
928
- *
929
- * 6 built-in passes + optional custom passes (domain-specific checks).
930
- *
931
- * Scoring:
932
- * - Each gap has a severity (critical=30, major=15, minor=2, info=0)
933
- * - Deductions are per-category with optional caps
934
- * - Iteration leniency: minor gaps free on iter 1, half on iter 2, full on 3+
935
- * - Score = max(0, 100 - deductions)
936
- *
937
- * Grade thresholds: A+=95, A=90, B=80, C=70, D=60, F=<60
938
- */
939
337
  grade(planId) {
940
- const plan = this.get(planId);
941
- if (!plan)
942
- throw new Error(`Plan not found: ${planId}`);
943
- // Run 6-pass gap analysis
338
+ const plan = this.requirePlan(planId);
944
339
  const gaps = runGapAnalysis(plan, this.gapOptions);
945
- // Add circular dependency check (structural, not covered by gap-analysis passes)
946
- if (this.hasCircularDependencies(plan)) {
340
+ if (hasCircularDependencies(plan.tasks)) {
947
341
  gaps.push({
948
342
  id: `gap_${Date.now()}_circ`,
949
343
  severity: 'critical',
@@ -954,14 +348,12 @@ export class Planner {
954
348
  _trigger: 'circular_dependencies',
955
349
  });
956
350
  }
957
- // Iteration = number of previous checks + 1
958
351
  const iteration = plan.checks.length + 1;
959
352
  const score = calculateScore(gaps, iteration);
960
- const grade = this.scoreToGrade(score);
961
353
  const check = {
962
354
  checkId: `chk-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
963
355
  planId,
964
- grade,
356
+ grade: scoreToGrade(score),
965
357
  score,
966
358
  gaps,
967
359
  iteration,
@@ -973,88 +365,15 @@ export class Planner {
973
365
  this.save();
974
366
  return check;
975
367
  }
976
- /**
977
- * Get the latest check for a plan.
978
- */
979
368
  getLatestCheck(planId) {
980
- const plan = this.get(planId);
981
- if (!plan)
982
- throw new Error(`Plan not found: ${planId}`);
983
- return plan.latestCheck ?? null;
369
+ return this.requirePlan(planId).latestCheck ?? null;
984
370
  }
985
- /**
986
- * Get all checks for a plan (history).
987
- */
988
371
  getCheckHistory(planId) {
989
- const plan = this.get(planId);
990
- if (!plan)
991
- throw new Error(`Plan not found: ${planId}`);
992
- return [...plan.checks];
372
+ return [...this.requirePlan(planId).checks];
993
373
  }
994
- /**
995
- * Auto-grade: grade the plan and return whether it meets a target grade.
996
- */
997
374
  meetsGrade(planId, targetGrade) {
998
375
  const check = this.grade(planId);
999
- const targetScore = this.gradeToMinScore(targetGrade);
1000
- return { meets: check.score >= targetScore, check };
1001
- }
1002
- // ─── Grading Helpers ──────────────────────────────────────────────
1003
- scoreToGrade(score) {
1004
- if (score >= 95)
1005
- return 'A+';
1006
- if (score >= 90)
1007
- return 'A';
1008
- if (score >= 80)
1009
- return 'B';
1010
- if (score >= 70)
1011
- return 'C';
1012
- if (score >= 60)
1013
- return 'D';
1014
- return 'F';
1015
- }
1016
- gradeToMinScore(grade) {
1017
- switch (grade) {
1018
- case 'A+':
1019
- return 95;
1020
- case 'A':
1021
- return 90;
1022
- case 'B':
1023
- return 80;
1024
- case 'C':
1025
- return 70;
1026
- case 'D':
1027
- return 60;
1028
- case 'F':
1029
- return 0;
1030
- }
1031
- }
1032
- hasCircularDependencies(plan) {
1033
- const visited = new Set();
1034
- const inStack = new Set();
1035
- const taskMap = new Map(plan.tasks.map((t) => [t.id, t]));
1036
- const dfs = (taskId) => {
1037
- if (inStack.has(taskId))
1038
- return true;
1039
- if (visited.has(taskId))
1040
- return false;
1041
- visited.add(taskId);
1042
- inStack.add(taskId);
1043
- const task = taskMap.get(taskId);
1044
- if (task?.dependsOn) {
1045
- for (const dep of task.dependsOn) {
1046
- if (dfs(dep))
1047
- return true;
1048
- }
1049
- }
1050
- inStack.delete(taskId);
1051
- return false;
1052
- };
1053
- for (const task of plan.tasks) {
1054
- if (dfs(task.id))
1055
- return true;
1056
- }
1057
- return false;
376
+ return { meets: check.score >= gradeToMinScore(targetGrade), check };
1058
377
  }
1059
378
  }
1060
379
  //# sourceMappingURL=planner.js.map