@soleri/core 9.0.3 → 9.2.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 (701) hide show
  1. package/dist/brain/intelligence.d.ts +27 -0
  2. package/dist/brain/intelligence.d.ts.map +1 -1
  3. package/dist/brain/intelligence.js +160 -14
  4. package/dist/brain/intelligence.js.map +1 -1
  5. package/dist/brain/learning-radar.d.ts +4 -0
  6. package/dist/brain/learning-radar.d.ts.map +1 -1
  7. package/dist/brain/learning-radar.js +20 -1
  8. package/dist/brain/learning-radar.js.map +1 -1
  9. package/dist/brain/strength-scorer.d.ts +31 -0
  10. package/dist/brain/strength-scorer.d.ts.map +1 -0
  11. package/dist/brain/strength-scorer.js +264 -0
  12. package/dist/brain/strength-scorer.js.map +1 -0
  13. package/dist/chat/agent-loop.d.ts.map +1 -1
  14. package/dist/chat/agent-loop.js +2 -0
  15. package/dist/chat/agent-loop.js.map +1 -1
  16. package/dist/chat/notifications.d.ts.map +1 -1
  17. package/dist/chat/notifications.js +2 -0
  18. package/dist/chat/notifications.js.map +1 -1
  19. package/dist/claudemd/compose.js +1 -1
  20. package/dist/claudemd/compose.js.map +1 -1
  21. package/dist/control/intent-router.d.ts.map +1 -1
  22. package/dist/control/intent-router.js +12 -4
  23. package/dist/control/intent-router.js.map +1 -1
  24. package/dist/curator/contradiction-detector.d.ts +27 -0
  25. package/dist/curator/contradiction-detector.d.ts.map +1 -0
  26. package/dist/curator/contradiction-detector.js +62 -0
  27. package/dist/curator/contradiction-detector.js.map +1 -0
  28. package/dist/curator/curator.d.ts +3 -4
  29. package/dist/curator/curator.d.ts.map +1 -1
  30. package/dist/curator/curator.js +90 -525
  31. package/dist/curator/curator.js.map +1 -1
  32. package/dist/curator/duplicate-detector.d.ts +14 -0
  33. package/dist/curator/duplicate-detector.d.ts.map +1 -0
  34. package/dist/curator/duplicate-detector.js +77 -0
  35. package/dist/curator/duplicate-detector.js.map +1 -0
  36. package/dist/curator/health-audit.d.ts +15 -0
  37. package/dist/curator/health-audit.d.ts.map +1 -0
  38. package/dist/curator/health-audit.js +97 -0
  39. package/dist/curator/health-audit.js.map +1 -0
  40. package/dist/curator/metadata-enricher.d.ts +17 -0
  41. package/dist/curator/metadata-enricher.d.ts.map +1 -0
  42. package/dist/curator/metadata-enricher.js +60 -0
  43. package/dist/curator/metadata-enricher.js.map +1 -0
  44. package/dist/curator/schema.d.ts +7 -0
  45. package/dist/curator/schema.d.ts.map +1 -0
  46. package/dist/curator/schema.js +62 -0
  47. package/dist/curator/schema.js.map +1 -0
  48. package/dist/curator/tag-manager.d.ts +36 -0
  49. package/dist/curator/tag-manager.d.ts.map +1 -0
  50. package/dist/curator/tag-manager.js +78 -0
  51. package/dist/curator/tag-manager.js.map +1 -0
  52. package/dist/engine/bin/soleri-engine.js +55 -3
  53. package/dist/engine/bin/soleri-engine.js.map +1 -1
  54. package/dist/engine/core-ops.d.ts.map +1 -1
  55. package/dist/engine/core-ops.js +33 -10
  56. package/dist/engine/core-ops.js.map +1 -1
  57. package/dist/engine/module-manifest.d.ts.map +1 -1
  58. package/dist/engine/module-manifest.js +22 -2
  59. package/dist/engine/module-manifest.js.map +1 -1
  60. package/dist/engine/register-engine.d.ts.map +1 -1
  61. package/dist/engine/register-engine.js +26 -2
  62. package/dist/engine/register-engine.js.map +1 -1
  63. package/dist/errors/retry.d.ts.map +1 -1
  64. package/dist/errors/retry.js +2 -0
  65. package/dist/errors/retry.js.map +1 -1
  66. package/dist/facades/types.d.ts +1 -1
  67. package/dist/flows/chain-types.d.ts +18 -18
  68. package/dist/flows/gate-evaluator.d.ts.map +1 -1
  69. package/dist/flows/gate-evaluator.js +22 -0
  70. package/dist/flows/gate-evaluator.js.map +1 -1
  71. package/dist/flows/types.d.ts +157 -28
  72. package/dist/flows/types.d.ts.map +1 -1
  73. package/dist/flows/types.js +4 -0
  74. package/dist/flows/types.js.map +1 -1
  75. package/dist/index.d.ts +10 -2
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +9 -1
  78. package/dist/index.js.map +1 -1
  79. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  80. package/dist/intake/intake-pipeline.js +1 -0
  81. package/dist/intake/intake-pipeline.js.map +1 -1
  82. package/dist/intake/text-ingester.d.ts.map +1 -1
  83. package/dist/intake/text-ingester.js +2 -0
  84. package/dist/intake/text-ingester.js.map +1 -1
  85. package/dist/llm/key-pool.d.ts +1 -1
  86. package/dist/llm/key-pool.d.ts.map +1 -1
  87. package/dist/llm/key-pool.js +3 -4
  88. package/dist/llm/key-pool.js.map +1 -1
  89. package/dist/llm/utils.d.ts.map +1 -1
  90. package/dist/llm/utils.js +2 -0
  91. package/dist/llm/utils.js.map +1 -1
  92. package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
  93. package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
  94. package/dist/migrations/migration-runner.test-helpers.js +47 -0
  95. package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
  96. package/dist/operator/operator-profile.d.ts +44 -0
  97. package/dist/operator/operator-profile.d.ts.map +1 -0
  98. package/dist/operator/operator-profile.js +377 -0
  99. package/dist/operator/operator-profile.js.map +1 -0
  100. package/dist/operator/operator-signals.d.ts +45 -0
  101. package/dist/operator/operator-signals.d.ts.map +1 -0
  102. package/dist/operator/operator-signals.js +228 -0
  103. package/dist/operator/operator-signals.js.map +1 -0
  104. package/dist/operator/operator-types.d.ts +360 -0
  105. package/dist/operator/operator-types.d.ts.map +1 -0
  106. package/dist/operator/operator-types.js +24 -0
  107. package/dist/operator/operator-types.js.map +1 -0
  108. package/dist/packs/types.d.ts +27 -27
  109. package/dist/paths.d.ts +40 -0
  110. package/dist/paths.d.ts.map +1 -0
  111. package/dist/paths.js +98 -0
  112. package/dist/paths.js.map +1 -0
  113. package/dist/persistence/index.d.ts +1 -1
  114. package/dist/persistence/index.d.ts.map +1 -1
  115. package/dist/persistence/index.js +1 -1
  116. package/dist/persistence/index.js.map +1 -1
  117. package/dist/persistence/sqlite-provider.d.ts +2 -0
  118. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  119. package/dist/persistence/sqlite-provider.js +8 -5
  120. package/dist/persistence/sqlite-provider.js.map +1 -1
  121. package/dist/planning/evidence-collector.d.ts +13 -1
  122. package/dist/planning/evidence-collector.d.ts.map +1 -1
  123. package/dist/planning/evidence-collector.js +33 -0
  124. package/dist/planning/evidence-collector.js.map +1 -1
  125. package/dist/planning/gap-analysis.d.ts +5 -4
  126. package/dist/planning/gap-analysis.d.ts.map +1 -1
  127. package/dist/planning/gap-analysis.js +7 -341
  128. package/dist/planning/gap-analysis.js.map +1 -1
  129. package/dist/planning/gap-passes.d.ts +19 -0
  130. package/dist/planning/gap-passes.d.ts.map +1 -0
  131. package/dist/planning/gap-passes.js +157 -0
  132. package/dist/planning/gap-passes.js.map +1 -0
  133. package/dist/planning/gap-patterns.d.ts +29 -0
  134. package/dist/planning/gap-patterns.d.ts.map +1 -0
  135. package/dist/planning/gap-patterns.js +129 -0
  136. package/dist/planning/gap-patterns.js.map +1 -0
  137. package/dist/planning/gap-types.d.ts +1 -1
  138. package/dist/planning/gap-types.d.ts.map +1 -1
  139. package/dist/planning/gap-types.js +1 -0
  140. package/dist/planning/gap-types.js.map +1 -1
  141. package/dist/planning/github-projection.d.ts +122 -0
  142. package/dist/planning/github-projection.d.ts.map +1 -0
  143. package/dist/planning/github-projection.js +294 -0
  144. package/dist/planning/github-projection.js.map +1 -0
  145. package/dist/planning/impact-analyzer.d.ts +26 -0
  146. package/dist/planning/impact-analyzer.d.ts.map +1 -0
  147. package/dist/planning/impact-analyzer.js +199 -0
  148. package/dist/planning/impact-analyzer.js.map +1 -0
  149. package/dist/planning/plan-lifecycle.d.ts +136 -0
  150. package/dist/planning/plan-lifecycle.d.ts.map +1 -0
  151. package/dist/planning/plan-lifecycle.js +296 -0
  152. package/dist/planning/plan-lifecycle.js.map +1 -0
  153. package/dist/planning/planner-types.d.ts +202 -0
  154. package/dist/planning/planner-types.d.ts.map +1 -0
  155. package/dist/planning/planner-types.js +6 -0
  156. package/dist/planning/planner-types.js.map +1 -0
  157. package/dist/planning/planner.d.ts +31 -383
  158. package/dist/planning/planner.d.ts.map +1 -1
  159. package/dist/planning/planner.js +154 -878
  160. package/dist/planning/planner.js.map +1 -1
  161. package/dist/planning/rationalization-detector.d.ts +32 -0
  162. package/dist/planning/rationalization-detector.d.ts.map +1 -0
  163. package/dist/planning/rationalization-detector.js +89 -0
  164. package/dist/planning/rationalization-detector.js.map +1 -0
  165. package/dist/planning/reconciliation-engine.d.ts +47 -0
  166. package/dist/planning/reconciliation-engine.d.ts.map +1 -0
  167. package/dist/planning/reconciliation-engine.js +128 -0
  168. package/dist/planning/reconciliation-engine.js.map +1 -0
  169. package/dist/planning/task-verifier.d.ts +85 -0
  170. package/dist/planning/task-verifier.d.ts.map +1 -0
  171. package/dist/planning/task-verifier.js +227 -0
  172. package/dist/planning/task-verifier.js.map +1 -0
  173. package/dist/plugins/types.d.ts +4 -4
  174. package/dist/runtime/admin-ops.d.ts +2 -2
  175. package/dist/runtime/admin-ops.d.ts.map +1 -1
  176. package/dist/runtime/admin-ops.js +44 -17
  177. package/dist/runtime/admin-ops.js.map +1 -1
  178. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  179. package/dist/runtime/admin-setup-ops.js +21 -46
  180. package/dist/runtime/admin-setup-ops.js.map +1 -1
  181. package/dist/runtime/archive-ops.d.ts +10 -0
  182. package/dist/runtime/archive-ops.d.ts.map +1 -0
  183. package/dist/runtime/archive-ops.js +310 -0
  184. package/dist/runtime/archive-ops.js.map +1 -0
  185. package/dist/runtime/capture-ops.d.ts.map +1 -1
  186. package/dist/runtime/capture-ops.js +42 -7
  187. package/dist/runtime/capture-ops.js.map +1 -1
  188. package/dist/runtime/claude-md-helpers.js +1 -1
  189. package/dist/runtime/claude-md-helpers.js.map +1 -1
  190. package/dist/runtime/context-health.d.ts +31 -0
  191. package/dist/runtime/context-health.d.ts.map +1 -0
  192. package/dist/runtime/context-health.js +57 -0
  193. package/dist/runtime/context-health.js.map +1 -0
  194. package/dist/runtime/facades/archive-facade.d.ts +10 -0
  195. package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
  196. package/dist/runtime/facades/archive-facade.js +11 -0
  197. package/dist/runtime/facades/archive-facade.js.map +1 -0
  198. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  199. package/dist/runtime/facades/brain-facade.js +2 -0
  200. package/dist/runtime/facades/brain-facade.js.map +1 -1
  201. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  202. package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
  203. package/dist/runtime/facades/chat-facade.js +15 -800
  204. package/dist/runtime/facades/chat-facade.js.map +1 -1
  205. package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
  206. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
  207. package/dist/runtime/facades/chat-service-ops.js +330 -0
  208. package/dist/runtime/facades/chat-service-ops.js.map +1 -0
  209. package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
  210. package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
  211. package/dist/runtime/facades/chat-session-ops.js +136 -0
  212. package/dist/runtime/facades/chat-session-ops.js.map +1 -0
  213. package/dist/runtime/facades/chat-state.d.ts +31 -0
  214. package/dist/runtime/facades/chat-state.d.ts.map +1 -0
  215. package/dist/runtime/facades/chat-state.js +32 -0
  216. package/dist/runtime/facades/chat-state.js.map +1 -0
  217. package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
  218. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
  219. package/dist/runtime/facades/chat-transport-ops.js +337 -0
  220. package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
  221. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  222. package/dist/runtime/facades/control-facade.js +4 -1
  223. package/dist/runtime/facades/control-facade.js.map +1 -1
  224. package/dist/runtime/facades/index.d.ts.map +1 -1
  225. package/dist/runtime/facades/index.js +6 -0
  226. package/dist/runtime/facades/index.js.map +1 -1
  227. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  228. package/dist/runtime/facades/memory-facade.js +75 -6
  229. package/dist/runtime/facades/memory-facade.js.map +1 -1
  230. package/dist/runtime/facades/operator-facade.d.ts +8 -0
  231. package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
  232. package/dist/runtime/facades/operator-facade.js +220 -0
  233. package/dist/runtime/facades/operator-facade.js.map +1 -0
  234. package/dist/runtime/facades/orchestrate-facade.js +3 -3
  235. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  236. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  237. package/dist/runtime/facades/plan-facade.js +39 -6
  238. package/dist/runtime/facades/plan-facade.js.map +1 -1
  239. package/dist/runtime/facades/review-facade.d.ts +7 -0
  240. package/dist/runtime/facades/review-facade.d.ts.map +1 -0
  241. package/dist/runtime/facades/review-facade.js +8 -0
  242. package/dist/runtime/facades/review-facade.js.map +1 -0
  243. package/dist/runtime/facades/sync-facade.d.ts +7 -0
  244. package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
  245. package/dist/runtime/facades/sync-facade.js +8 -0
  246. package/dist/runtime/facades/sync-facade.js.map +1 -0
  247. package/dist/runtime/facades/vault-facade.d.ts +4 -1
  248. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  249. package/dist/runtime/facades/vault-facade.js +13 -66
  250. package/dist/runtime/facades/vault-facade.js.map +1 -1
  251. package/dist/runtime/github-integration.d.ts +49 -0
  252. package/dist/runtime/github-integration.d.ts.map +1 -0
  253. package/dist/runtime/github-integration.js +113 -0
  254. package/dist/runtime/github-integration.js.map +1 -0
  255. package/dist/runtime/grading-ops.js +1 -1
  256. package/dist/runtime/grading-ops.js.map +1 -1
  257. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  258. package/dist/runtime/memory-extra-ops.js +6 -2
  259. package/dist/runtime/memory-extra-ops.js.map +1 -1
  260. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  261. package/dist/runtime/orchestrate-ops.js +367 -40
  262. package/dist/runtime/orchestrate-ops.js.map +1 -1
  263. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  264. package/dist/runtime/planning-extra-ops.js +69 -4
  265. package/dist/runtime/planning-extra-ops.js.map +1 -1
  266. package/dist/runtime/review-ops.d.ts +10 -0
  267. package/dist/runtime/review-ops.d.ts.map +1 -0
  268. package/dist/runtime/review-ops.js +97 -0
  269. package/dist/runtime/review-ops.js.map +1 -0
  270. package/dist/runtime/runtime.d.ts.map +1 -1
  271. package/dist/runtime/runtime.js +27 -12
  272. package/dist/runtime/runtime.js.map +1 -1
  273. package/dist/runtime/session-briefing.d.ts +3 -0
  274. package/dist/runtime/session-briefing.d.ts.map +1 -1
  275. package/dist/runtime/session-briefing.js +68 -1
  276. package/dist/runtime/session-briefing.js.map +1 -1
  277. package/dist/runtime/sync-ops.d.ts +12 -0
  278. package/dist/runtime/sync-ops.d.ts.map +1 -0
  279. package/dist/runtime/sync-ops.js +288 -0
  280. package/dist/runtime/sync-ops.js.map +1 -0
  281. package/dist/runtime/types.d.ts +10 -4
  282. package/dist/runtime/types.d.ts.map +1 -1
  283. package/dist/runtime/vault-extra-ops.d.ts +5 -4
  284. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  285. package/dist/runtime/vault-extra-ops.js +5 -300
  286. package/dist/runtime/vault-extra-ops.js.map +1 -1
  287. package/dist/runtime/vault-sharing-ops.d.ts +4 -4
  288. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  289. package/dist/runtime/vault-sharing-ops.js +5 -300
  290. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  291. package/dist/skills/sync-skills.d.ts +27 -0
  292. package/dist/skills/sync-skills.d.ts.map +1 -0
  293. package/dist/skills/sync-skills.js +81 -0
  294. package/dist/skills/sync-skills.js.map +1 -0
  295. package/dist/update-check.d.ts +14 -0
  296. package/dist/update-check.d.ts.map +1 -0
  297. package/dist/update-check.js +96 -0
  298. package/dist/update-check.js.map +1 -0
  299. package/dist/vault/linking.d.ts +10 -12
  300. package/dist/vault/linking.d.ts.map +1 -1
  301. package/dist/vault/linking.js +104 -161
  302. package/dist/vault/linking.js.map +1 -1
  303. package/dist/vault/vault-entries.d.ts +69 -0
  304. package/dist/vault/vault-entries.d.ts.map +1 -0
  305. package/dist/vault/vault-entries.js +257 -0
  306. package/dist/vault/vault-entries.js.map +1 -0
  307. package/dist/vault/vault-interfaces.d.ts +153 -0
  308. package/dist/vault/vault-interfaces.d.ts.map +1 -0
  309. package/dist/vault/vault-interfaces.js +2 -0
  310. package/dist/vault/vault-interfaces.js.map +1 -0
  311. package/dist/vault/vault-maintenance.d.ts +40 -0
  312. package/dist/vault/vault-maintenance.d.ts.map +1 -0
  313. package/dist/vault/vault-maintenance.js +142 -0
  314. package/dist/vault/vault-maintenance.js.map +1 -0
  315. package/dist/vault/vault-markdown-sync.d.ts +22 -0
  316. package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
  317. package/dist/vault/vault-markdown-sync.js +143 -0
  318. package/dist/vault/vault-markdown-sync.js.map +1 -0
  319. package/dist/vault/vault-memories.d.ts +61 -0
  320. package/dist/vault/vault-memories.d.ts.map +1 -0
  321. package/dist/vault/vault-memories.js +240 -0
  322. package/dist/vault/vault-memories.js.map +1 -0
  323. package/dist/vault/vault-schema.d.ts +9 -0
  324. package/dist/vault/vault-schema.d.ts.map +1 -0
  325. package/dist/vault/vault-schema.js +179 -0
  326. package/dist/vault/vault-schema.js.map +1 -0
  327. package/dist/vault/vault.d.ts +29 -81
  328. package/dist/vault/vault.d.ts.map +1 -1
  329. package/dist/vault/vault.js +78 -931
  330. package/dist/vault/vault.js.map +1 -1
  331. package/package.json +1 -1
  332. package/src/agency/agency-manager.test.ts +600 -0
  333. package/src/agency/default-rules.test.ts +228 -0
  334. package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
  335. package/src/{__tests__ → brain}/brain.test.ts +1 -1
  336. package/src/brain/intelligence.ts +196 -15
  337. package/src/brain/learning-radar.ts +22 -1
  338. package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
  339. package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
  340. package/src/brain/strength-scorer.ts +404 -0
  341. package/src/capabilities/chain-mapping.test.ts +66 -0
  342. package/src/capabilities/registry.test.ts +369 -0
  343. package/src/chat/agent-loop.test.ts +394 -0
  344. package/src/chat/agent-loop.ts +2 -0
  345. package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
  346. package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
  347. package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
  348. package/src/chat/mcp-bridge.test.ts +173 -0
  349. package/src/chat/notifications.ts +2 -0
  350. package/src/chat/output-compressor.test.ts +164 -0
  351. package/src/claudemd/compose.test.ts +178 -0
  352. package/src/claudemd/compose.ts +1 -1
  353. package/src/claudemd/inject.test.ts +211 -0
  354. package/src/context/context-engine.test.ts +461 -0
  355. package/src/control/identity-manager.test.ts +305 -0
  356. package/src/control/intent-router.test.ts +360 -0
  357. package/src/control/intent-router.ts +13 -4
  358. package/src/curator/classifier.test.ts +104 -0
  359. package/src/curator/contradiction-detector.test.ts +180 -0
  360. package/src/curator/contradiction-detector.ts +87 -0
  361. package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
  362. package/src/{__tests__ → curator}/curator.test.ts +77 -1
  363. package/src/curator/curator.ts +115 -777
  364. package/src/curator/duplicate-detector.test.ts +183 -0
  365. package/src/curator/duplicate-detector.ts +103 -0
  366. package/src/curator/health-audit.ts +126 -0
  367. package/src/curator/metadata-enricher.ts +84 -0
  368. package/src/curator/quality-gate.test.ts +135 -0
  369. package/src/curator/schema.ts +65 -0
  370. package/src/curator/tag-manager.test.ts +165 -0
  371. package/src/curator/tag-manager.ts +109 -0
  372. package/src/domain-packs/inject-rules.test.ts +117 -0
  373. package/src/domain-packs/knowledge-installer.test.ts +171 -0
  374. package/src/domain-packs/loader.test.ts +86 -0
  375. package/src/domain-packs/pack-runtime.test.ts +140 -0
  376. package/src/domain-packs/skills-installer.test.ts +135 -0
  377. package/src/domain-packs/token-resolver.test.ts +150 -0
  378. package/src/domain-packs/types.test.ts +130 -0
  379. package/src/enforcement/adapters/claude-code.test.ts +216 -0
  380. package/src/enforcement/registry.test.ts +264 -0
  381. package/src/engine/bin/soleri-engine.ts +59 -3
  382. package/src/engine/core-ops.test.ts +254 -0
  383. package/src/engine/core-ops.ts +35 -10
  384. package/src/engine/module-manifest.test.ts +124 -0
  385. package/src/engine/module-manifest.ts +22 -2
  386. package/src/engine/register-engine.test.ts +230 -0
  387. package/src/engine/register-engine.ts +26 -2
  388. package/src/errors/classify.test.ts +199 -0
  389. package/src/errors/retry.test.ts +156 -0
  390. package/src/errors/retry.ts +2 -0
  391. package/src/errors/types.test.ts +108 -0
  392. package/src/events/event-bus.test.ts +149 -0
  393. package/src/extensions/middleware.test.ts +234 -0
  394. package/src/facades/facade-factory.test.ts +424 -0
  395. package/src/flows/chain-runner.test.ts +273 -0
  396. package/src/flows/context-router.test.ts +52 -0
  397. package/src/flows/dispatch-registry.test.ts +128 -0
  398. package/src/flows/epilogue.test.ts +107 -0
  399. package/src/flows/executor.test.ts +263 -0
  400. package/src/flows/gate-evaluator.test.ts +194 -0
  401. package/src/flows/gate-evaluator.ts +25 -0
  402. package/src/flows/types.ts +4 -0
  403. package/src/governance/governance.test.ts +726 -0
  404. package/src/health/health-registry.test.ts +186 -0
  405. package/src/health/vault-integrity.test.ts +110 -0
  406. package/src/index.ts +92 -0
  407. package/src/intake/content-classifier.test.ts +209 -0
  408. package/src/intake/dedup-gate.test.ts +131 -0
  409. package/src/intake/intake-pipeline.test.ts +506 -0
  410. package/src/intake/intake-pipeline.ts +1 -0
  411. package/src/intake/text-ingester.test.ts +194 -0
  412. package/src/intake/text-ingester.ts +2 -0
  413. package/src/llm/key-pool.test.ts +236 -0
  414. package/src/llm/key-pool.ts +3 -4
  415. package/src/llm/llm-client.test.ts +345 -0
  416. package/src/llm/oauth-discovery.test.ts +180 -0
  417. package/src/llm/utils.test.ts +327 -0
  418. package/src/llm/utils.ts +2 -0
  419. package/src/{__tests__ → logging}/logger.test.ts +41 -62
  420. package/src/loop/loop-manager.test.ts +519 -0
  421. package/src/migrations/migration-runner.edge-cases.test.ts +319 -0
  422. package/src/migrations/migration-runner.test-helpers.ts +64 -0
  423. package/src/migrations/migration-runner.test.ts +385 -0
  424. package/src/operator/auto-signal-pipeline.test.ts +207 -0
  425. package/src/operator/operator-profile-extended.test.ts +320 -0
  426. package/src/operator/operator-profile.test.ts +314 -0
  427. package/src/operator/operator-profile.ts +469 -0
  428. package/src/operator/operator-signals-extended.test.ts +245 -0
  429. package/src/operator/operator-signals.test.ts +281 -0
  430. package/src/operator/operator-signals.ts +261 -0
  431. package/src/operator/operator-types.ts +444 -0
  432. package/src/operator/prompts/hook-precompact-operator-dispatch.md +94 -0
  433. package/src/operator/prompts/subagent-soft-signal-extractor.md +125 -0
  434. package/src/operator/prompts/subagent-synthesis-cognition.md +181 -0
  435. package/src/operator/prompts/subagent-synthesis-communication.md +140 -0
  436. package/src/operator/prompts/subagent-synthesis-technical.md +160 -0
  437. package/src/operator/prompts/subagent-synthesis-trust.md +143 -0
  438. package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
  439. package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
  440. package/src/paths.ts +115 -0
  441. package/src/persistence/index.ts +1 -1
  442. package/src/persistence/sqlite-provider.test.ts +540 -0
  443. package/src/persistence/sqlite-provider.ts +8 -5
  444. package/src/persona/defaults.test.ts +59 -0
  445. package/src/persona/loader.test.ts +67 -0
  446. package/src/persona/prompt-generator.test.ts +127 -0
  447. package/src/planning/evidence-collector.test.ts +406 -0
  448. package/src/planning/evidence-collector.ts +50 -0
  449. package/src/planning/gap-analysis-alternatives.test.ts +169 -0
  450. package/src/planning/gap-analysis.ts +21 -636
  451. package/src/planning/gap-passes.test.ts +372 -0
  452. package/src/planning/gap-passes.ts +298 -0
  453. package/src/planning/gap-patterns.test.ts +320 -0
  454. package/src/planning/gap-patterns.ts +234 -0
  455. package/src/planning/gap-types.ts +4 -1
  456. package/src/planning/github-projection.test.ts +177 -0
  457. package/src/planning/github-projection.ts +425 -0
  458. package/src/planning/impact-analyzer.test.ts +180 -0
  459. package/src/planning/impact-analyzer.ts +264 -0
  460. package/src/planning/plan-lifecycle.test.ts +312 -0
  461. package/src/planning/plan-lifecycle.ts +346 -0
  462. package/src/planning/planner-types.ts +215 -0
  463. package/src/{__tests__ → planning}/planner.test.ts +169 -15
  464. package/src/planning/planner.ts +197 -1228
  465. package/src/planning/rationalization-detector.test.ts +171 -0
  466. package/src/planning/rationalization-detector.ts +138 -0
  467. package/src/planning/reconciliation-engine.test.ts +141 -0
  468. package/src/planning/reconciliation-engine.ts +162 -0
  469. package/src/planning/task-verifier.test.ts +235 -0
  470. package/src/planning/task-verifier.ts +303 -0
  471. package/src/planning/verification-protocol.test.ts +201 -0
  472. package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
  473. package/src/playbooks/index.test.ts +77 -0
  474. package/src/playbooks/playbook-executor.test.ts +255 -0
  475. package/src/playbooks/playbook-registry.test.ts +232 -0
  476. package/src/playbooks/playbook-seeder.test.ts +153 -0
  477. package/src/plugins/plugin-loader.test.ts +212 -0
  478. package/src/plugins/plugin-registry.test.ts +272 -0
  479. package/src/project/project-registry.test.ts +428 -0
  480. package/src/prompts/parser.test.ts +100 -0
  481. package/src/prompts/template-manager.test.ts +109 -0
  482. package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
  483. package/src/queue/job-queue.test.ts +331 -0
  484. package/src/queue/pipeline-runner.test.ts +209 -0
  485. package/src/runtime/admin-extra-ops.test.ts +527 -0
  486. package/src/runtime/admin-ops.test.ts +257 -0
  487. package/src/runtime/admin-ops.ts +45 -17
  488. package/src/runtime/admin-setup-ops.test.ts +328 -0
  489. package/src/runtime/admin-setup-ops.ts +20 -43
  490. package/src/runtime/archive-ops.test.ts +269 -0
  491. package/src/runtime/archive-ops.ts +347 -0
  492. package/src/runtime/capture-ops.test.ts +433 -0
  493. package/src/runtime/capture-ops.ts +50 -8
  494. package/src/runtime/chain-ops.test.ts +149 -0
  495. package/src/runtime/claude-md-helpers.test.ts +191 -0
  496. package/src/runtime/claude-md-helpers.ts +1 -1
  497. package/src/runtime/context-health.test.ts +78 -0
  498. package/src/runtime/context-health.ts +85 -0
  499. package/src/runtime/curator-extra-ops.test.ts +202 -0
  500. package/src/runtime/deprecation.test.ts +98 -0
  501. package/src/runtime/domain-ops.test.ts +268 -0
  502. package/src/runtime/facades/admin-facade.test.ts +333 -0
  503. package/src/runtime/facades/agency-facade.test.ts +278 -0
  504. package/src/runtime/facades/archive-facade.test.ts +294 -0
  505. package/src/runtime/facades/archive-facade.ts +14 -0
  506. package/src/runtime/facades/brain-facade.test.ts +714 -0
  507. package/src/runtime/facades/brain-facade.ts +2 -0
  508. package/src/runtime/facades/chat-facade.test.ts +166 -0
  509. package/src/runtime/facades/chat-facade.ts +15 -906
  510. package/src/runtime/facades/chat-service-ops.test.ts +276 -0
  511. package/src/runtime/facades/chat-service-ops.ts +374 -0
  512. package/src/runtime/facades/chat-session-ops.test.ts +197 -0
  513. package/src/runtime/facades/chat-session-ops.ts +146 -0
  514. package/src/runtime/facades/chat-state.ts +60 -0
  515. package/src/runtime/facades/chat-transport-ops.test.ts +269 -0
  516. package/src/runtime/facades/chat-transport-ops.ts +380 -0
  517. package/src/runtime/facades/context-facade.test.ts +108 -0
  518. package/src/runtime/facades/control-facade.test.ts +436 -0
  519. package/src/runtime/facades/control-facade.ts +6 -1
  520. package/src/runtime/facades/curator-facade.test.ts +303 -0
  521. package/src/runtime/facades/index.ts +6 -0
  522. package/src/runtime/facades/loop-facade.test.ts +245 -0
  523. package/src/runtime/facades/memory-facade.test.ts +269 -0
  524. package/src/runtime/facades/memory-facade.ts +78 -6
  525. package/src/runtime/facades/operator-facade.test.ts +208 -0
  526. package/src/runtime/facades/operator-facade.ts +236 -0
  527. package/src/runtime/facades/orchestrate-facade.test.ts +185 -0
  528. package/src/runtime/facades/orchestrate-facade.ts +3 -3
  529. package/src/runtime/facades/plan-facade.test.ts +266 -0
  530. package/src/runtime/facades/plan-facade.ts +42 -6
  531. package/src/runtime/facades/review-facade.test.ts +82 -0
  532. package/src/runtime/facades/review-facade.ts +11 -0
  533. package/src/runtime/facades/sync-facade.test.ts +113 -0
  534. package/src/runtime/facades/sync-facade.ts +11 -0
  535. package/src/runtime/facades/vault-facade.test.ts +631 -0
  536. package/src/runtime/facades/vault-facade.ts +15 -70
  537. package/src/runtime/feature-flags.test.ts +140 -0
  538. package/src/runtime/github-integration.test.ts +89 -0
  539. package/src/runtime/github-integration.ts +159 -0
  540. package/src/runtime/grading-ops.test.ts +141 -0
  541. package/src/runtime/grading-ops.ts +1 -1
  542. package/src/runtime/intake-ops.test.ts +208 -0
  543. package/src/runtime/loop-ops.test.ts +238 -0
  544. package/src/runtime/memory-cross-project-ops.test.ts +177 -0
  545. package/src/runtime/memory-extra-ops.test.ts +453 -0
  546. package/src/runtime/memory-extra-ops.ts +6 -2
  547. package/src/runtime/orchestrate-ops.test.ts +302 -0
  548. package/src/runtime/orchestrate-ops.ts +435 -46
  549. package/src/runtime/pack-ops.test.ts +158 -0
  550. package/src/runtime/planning-extra-ops.test.ts +583 -0
  551. package/src/runtime/planning-extra-ops.ts +72 -4
  552. package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
  553. package/src/runtime/playbook-ops.test.ts +262 -0
  554. package/src/runtime/plugin-ops.test.ts +201 -0
  555. package/src/runtime/project-ops.test.ts +235 -0
  556. package/src/runtime/review-ops.test.ts +142 -0
  557. package/src/runtime/review-ops.ts +99 -0
  558. package/src/runtime/runtime.test.ts +363 -0
  559. package/src/runtime/runtime.ts +39 -12
  560. package/src/runtime/session-briefing.test.ts +302 -0
  561. package/src/runtime/session-briefing.ts +80 -1
  562. package/src/runtime/sync-ops.test.ts +221 -0
  563. package/src/runtime/sync-ops.ts +325 -0
  564. package/src/runtime/telemetry-ops.test.ts +132 -0
  565. package/src/runtime/types.ts +10 -4
  566. package/src/runtime/vault-extra-ops.test.ts +246 -0
  567. package/src/runtime/vault-extra-ops.ts +5 -332
  568. package/src/runtime/vault-linking-ops.test.ts +237 -0
  569. package/src/runtime/vault-sharing-ops.test.ts +130 -0
  570. package/src/runtime/vault-sharing-ops.ts +5 -329
  571. package/src/skills/sync-skills.ts +108 -0
  572. package/src/streams/normalize.test.ts +95 -0
  573. package/src/streams/replayable-stream.test.ts +166 -0
  574. package/src/telemetry/telemetry.test.ts +143 -0
  575. package/src/transport/http-server.test.ts +394 -0
  576. package/src/transport/lsp-server.test.ts +458 -0
  577. package/src/transport/rate-limiter.test.ts +126 -0
  578. package/src/transport/session-manager.test.ts +133 -0
  579. package/src/transport/token-auth.test.ts +136 -0
  580. package/src/transport/ws-server.test.ts +294 -0
  581. package/src/update-check.ts +111 -0
  582. package/src/vault/__tests__/vault-characterization.test.ts +168 -0
  583. package/src/vault/content-hash.test.ts +78 -0
  584. package/src/vault/git-vault-sync.test.ts +234 -0
  585. package/src/vault/knowledge-review.test.ts +269 -0
  586. package/src/vault/linking.test.ts +358 -0
  587. package/src/vault/linking.ts +149 -183
  588. package/src/vault/obsidian-sync.test.ts +342 -0
  589. package/src/vault/playbook.test.ts +152 -0
  590. package/src/vault/scope-detector.test.ts +187 -0
  591. package/src/vault/vault-branching.test.ts +250 -0
  592. package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
  593. package/src/vault/vault-entries.ts +282 -0
  594. package/src/vault/vault-interfaces.ts +56 -0
  595. package/src/vault/vault-maintenance.ts +205 -0
  596. package/src/vault/vault-manager.test.ts +206 -0
  597. package/src/vault/vault-markdown-sync.test.ts +203 -0
  598. package/src/vault/vault-markdown-sync.ts +160 -0
  599. package/src/vault/vault-memories.ts +339 -0
  600. package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
  601. package/src/vault/vault-schema.ts +181 -0
  602. package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
  603. package/src/{__tests__ → vault}/vault.test.ts +2 -2
  604. package/src/vault/vault.ts +89 -1171
  605. package/dist/cognee/client.d.ts +0 -43
  606. package/dist/cognee/client.d.ts.map +0 -1
  607. package/dist/cognee/client.js +0 -375
  608. package/dist/cognee/client.js.map +0 -1
  609. package/dist/cognee/sync-manager.d.ts +0 -153
  610. package/dist/cognee/sync-manager.d.ts.map +0 -1
  611. package/dist/cognee/sync-manager.js +0 -390
  612. package/dist/cognee/sync-manager.js.map +0 -1
  613. package/dist/cognee/types.d.ts +0 -62
  614. package/dist/cognee/types.d.ts.map +0 -1
  615. package/dist/cognee/types.js +0 -3
  616. package/dist/cognee/types.js.map +0 -1
  617. package/dist/governance/index.d.ts +0 -3
  618. package/dist/governance/index.d.ts.map +0 -1
  619. package/dist/governance/index.js +0 -2
  620. package/dist/governance/index.js.map +0 -1
  621. package/dist/health/doctor-checks.d.ts +0 -15
  622. package/dist/health/doctor-checks.d.ts.map +0 -1
  623. package/dist/health/doctor-checks.js +0 -98
  624. package/dist/health/doctor-checks.js.map +0 -1
  625. package/dist/persistence/postgres-provider.d.ts +0 -81
  626. package/dist/persistence/postgres-provider.d.ts.map +0 -1
  627. package/dist/persistence/postgres-provider.js +0 -256
  628. package/dist/persistence/postgres-provider.js.map +0 -1
  629. package/dist/runtime/cognee-sync-ops.d.ts +0 -12
  630. package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
  631. package/dist/runtime/cognee-sync-ops.js +0 -93
  632. package/dist/runtime/cognee-sync-ops.js.map +0 -1
  633. package/dist/runtime/core-ops.d.ts +0 -23
  634. package/dist/runtime/core-ops.d.ts.map +0 -1
  635. package/dist/runtime/core-ops.js +0 -1296
  636. package/dist/runtime/core-ops.js.map +0 -1
  637. package/dist/runtime/facades/cognee-facade.d.ts +0 -8
  638. package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
  639. package/dist/runtime/facades/cognee-facade.js +0 -156
  640. package/dist/runtime/facades/cognee-facade.js.map +0 -1
  641. package/src/__tests__/admin-extra-ops.test.ts +0 -484
  642. package/src/__tests__/admin-ops.test.ts +0 -268
  643. package/src/__tests__/admin-setup-ops.test.ts +0 -355
  644. package/src/__tests__/agency-manager.test.ts +0 -374
  645. package/src/__tests__/agent-loop.test.ts +0 -256
  646. package/src/__tests__/capture-ops.test.ts +0 -784
  647. package/src/__tests__/claudemd.test.ts +0 -282
  648. package/src/__tests__/content-hash.test.ts +0 -60
  649. package/src/__tests__/context-engine.test.ts +0 -251
  650. package/src/__tests__/core-ops.test.ts +0 -550
  651. package/src/__tests__/curator-extra-ops.test.ts +0 -383
  652. package/src/__tests__/deprecation.test.ts +0 -78
  653. package/src/__tests__/domain-ops.test.ts +0 -226
  654. package/src/__tests__/domain-packs.test.ts +0 -421
  655. package/src/__tests__/enforcement.test.ts +0 -153
  656. package/src/__tests__/errors.test.ts +0 -388
  657. package/src/__tests__/extensions.test.ts +0 -233
  658. package/src/__tests__/facade-factory.test.ts +0 -271
  659. package/src/__tests__/feature-flags.test.ts +0 -137
  660. package/src/__tests__/flows.test.ts +0 -604
  661. package/src/__tests__/git-vault-sync.test.ts +0 -230
  662. package/src/__tests__/governance.test.ts +0 -522
  663. package/src/__tests__/grading-ops.test.ts +0 -361
  664. package/src/__tests__/health-registry.test.ts +0 -173
  665. package/src/__tests__/identity-manager.test.ts +0 -243
  666. package/src/__tests__/intake-pipeline.test.ts +0 -162
  667. package/src/__tests__/intent-router.test.ts +0 -222
  668. package/src/__tests__/knowledge-review.test.ts +0 -104
  669. package/src/__tests__/llm-client.test.ts +0 -69
  670. package/src/__tests__/llm.test.ts +0 -556
  671. package/src/__tests__/loader.test.ts +0 -176
  672. package/src/__tests__/loop-ops.test.ts +0 -469
  673. package/src/__tests__/lsp-transport.test.ts +0 -442
  674. package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
  675. package/src/__tests__/memory-extra-ops.test.ts +0 -352
  676. package/src/__tests__/migration-runner.test.ts +0 -170
  677. package/src/__tests__/module-manifest-drift.test.ts +0 -59
  678. package/src/__tests__/normalize.test.ts +0 -85
  679. package/src/__tests__/obsidian-sync.test.ts +0 -354
  680. package/src/__tests__/orchestrate-ops.test.ts +0 -289
  681. package/src/__tests__/pack-ops.test.ts +0 -146
  682. package/src/__tests__/persistence.test.ts +0 -291
  683. package/src/__tests__/planning-extra-ops.test.ts +0 -706
  684. package/src/__tests__/playbook-executor.test.ts +0 -249
  685. package/src/__tests__/playbook-registry.test.ts +0 -326
  686. package/src/__tests__/playbook-seeder.test.ts +0 -163
  687. package/src/__tests__/playbook.test.ts +0 -389
  688. package/src/__tests__/plugin-ops.test.ts +0 -411
  689. package/src/__tests__/plugin-system.test.ts +0 -509
  690. package/src/__tests__/project-ops.test.ts +0 -381
  691. package/src/__tests__/replayable-stream.test.ts +0 -177
  692. package/src/__tests__/runtime.test.ts +0 -95
  693. package/src/__tests__/scope-detector.test.ts +0 -121
  694. package/src/__tests__/template-manager.test.ts +0 -222
  695. package/src/__tests__/token-resolver.test.ts +0 -79
  696. package/src/__tests__/transport.test.ts +0 -758
  697. package/src/__tests__/vault-branching.test.ts +0 -274
  698. package/src/__tests__/vault-extra-ops.test.ts +0 -482
  699. package/src/__tests__/vault-integrity.test.ts +0 -71
  700. package/src/__tests__/vault-manager.test.ts +0 -238
  701. package/src/__tests__/ws-transport.test.ts +0 -479
@@ -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;
@@ -174,12 +73,7 @@ export class Planner {
174
73
  get(planId) {
175
74
  return this.store.plans.find((p) => p.id === planId) ?? null;
176
75
  }
177
- list() {
178
- return [...this.store.plans];
179
- }
180
- /**
181
- * Permanently remove a plan by ID. Returns true if found and removed.
182
- */
76
+ list() { return [...this.store.plans]; }
183
77
  remove(planId) {
184
78
  const idx = this.store.plans.findIndex((p) => p.id === planId);
185
79
  if (idx < 0)
@@ -188,784 +82,239 @@ export class Planner {
188
82
  this.save();
189
83
  return true;
190
84
  }
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
85
  promoteToDraft(planId) {
209
- const plan = this.get(planId);
210
- if (!plan)
211
- throw new Error(`Plan not found: ${planId}`);
86
+ const plan = this.requirePlan(planId);
212
87
  this.transition(plan, 'draft');
213
88
  this.save();
214
89
  return plan;
215
90
  }
216
91
  approve(planId) {
217
- const plan = this.get(planId);
218
- if (!plan)
219
- throw new Error(`Plan not found: ${planId}`);
92
+ const plan = this.requirePlan(planId);
93
+ const check = plan.latestCheck;
94
+ if (check && check.score < gradeToMinScore(this.minGradeForApproval)) {
95
+ throw new PlanGradeRejectionError(check.grade, check.score, this.minGradeForApproval, check.gaps);
96
+ }
220
97
  this.transition(plan, 'approved');
221
98
  this.save();
222
99
  return plan;
223
100
  }
224
101
  startExecution(planId) {
225
- const plan = this.get(planId);
226
- if (!plan)
227
- throw new Error(`Plan not found: ${planId}`);
102
+ const plan = this.requirePlan(planId);
228
103
  this.transition(plan, 'executing');
229
104
  this.save();
230
105
  return plan;
231
106
  }
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
107
  startValidation(planId) {
266
- const plan = this.get(planId);
267
- if (!plan)
268
- throw new Error(`Plan not found: ${planId}`);
108
+ const plan = this.requirePlan(planId);
269
109
  this.transition(plan, 'validating');
270
110
  this.save();
271
111
  return plan;
272
112
  }
273
- /**
274
- * Transition plan to 'reconciling' state.
275
- * Allowed from 'executing' or 'validating'.
276
- */
277
113
  startReconciliation(planId) {
278
- const plan = this.get(planId);
279
- if (!plan)
280
- throw new Error(`Plan not found: ${planId}`);
114
+ const plan = this.requirePlan(planId);
281
115
  this.transition(plan, 'reconciling');
282
116
  this.save();
283
117
  return plan;
284
118
  }
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
- */
119
+ updateTask(planId, taskId, status) {
120
+ const plan = this.requirePlan(planId);
121
+ if (plan.status !== 'executing' && plan.status !== 'validating')
122
+ throw new Error(`Cannot update tasks on plan in '${plan.status}' status — must be 'executing' or 'validating'`);
123
+ applyTaskStatusUpdate(this.requireTask(plan, taskId), status);
124
+ plan.updatedAt = Date.now();
125
+ this.save();
126
+ return plan;
127
+ }
128
+ reconcile(planId, report) {
129
+ const plan = this.requirePlan(planId);
130
+ if (plan.status !== 'executing' && plan.status !== 'validating' && plan.status !== 'reconciling')
131
+ throw new Error(`Cannot reconcile plan in '${plan.status}' status — must be 'executing', 'validating', or 'reconciling'`);
132
+ plan.reconciliation = buildReconciliationReport(planId, report);
133
+ plan.executionSummary = computeExecutionSummary(plan.tasks);
134
+ if (plan.status === 'executing' || plan.status === 'validating')
135
+ plan.status = 'reconciling';
136
+ plan.status = 'completed';
137
+ plan.updatedAt = Date.now();
138
+ this.save();
139
+ return plan;
140
+ }
290
141
  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);
142
+ const plan = this.requirePlan(planId);
143
+ if (plan.status === 'executing' || plan.status === 'validating')
144
+ return this.reconcile(planId, { actualOutcome: 'All tasks completed', reconciledBy: 'auto' });
145
+ plan.executionSummary = computeExecutionSummary(plan.tasks);
295
146
  this.transition(plan, 'completed');
296
147
  this.save();
297
148
  return plan;
298
149
  }
150
+ autoReconcile(planId) {
151
+ const plan = this.requirePlan(planId);
152
+ if (plan.status !== 'executing' && plan.status !== 'validating')
153
+ throw new Error(`Cannot auto-reconcile plan in '${plan.status}' status — must be 'executing' or 'validating'`);
154
+ const result = buildAutoReconcileInput(plan.tasks);
155
+ if (!result.canAutoReconcile || !result.input)
156
+ return null;
157
+ return this.reconcile(planId, result.input);
158
+ }
299
159
  getExecuting() {
300
160
  return this.store.plans.filter((p) => p.status === 'executing' || p.status === 'validating');
301
161
  }
302
162
  getActive() {
303
- return this.store.plans.filter((p) => p.status === 'brainstorming' ||
304
- p.status === 'draft' ||
305
- p.status === 'approved' ||
306
- p.status === 'executing' ||
307
- p.status === 'validating' ||
308
- p.status === 'reconciling');
163
+ return this.store.plans.filter((p) => p.status === 'brainstorming' || p.status === 'draft' || p.status === 'approved' ||
164
+ p.status === 'executing' || p.status === 'validating' || p.status === 'reconciling');
309
165
  }
310
- /**
311
- * Iterate on a draft plan — modify objective, scope, decisions, or tasks.
312
- * Only allowed on plans in 'draft' status.
313
- */
314
166
  iterate(planId, changes) {
315
- const plan = this.get(planId);
316
- if (!plan)
317
- throw new Error(`Plan not found: ${planId}`);
167
+ const plan = this.requirePlan(planId);
318
168
  if (plan.status !== 'draft' && plan.status !== 'brainstorming')
319
169
  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;
170
+ applyIteration(plan, changes);
361
171
  this.save();
362
172
  return plan;
363
173
  }
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
174
  splitTasks(planId, tasks) {
370
- const plan = this.get(planId);
371
- if (!plan)
372
- throw new Error(`Plan not found: ${planId}`);
175
+ const plan = this.requirePlan(planId);
373
176
  if (plan.status !== 'brainstorming' && plan.status !== 'draft' && plan.status !== 'approved')
374
177
  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;
397
- this.save();
398
- return plan;
399
- }
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();
178
+ applySplitTasks(plan, tasks);
434
179
  this.save();
435
180
  return plan;
436
181
  }
437
- /**
438
- * Add review evidence to a plan or specific task.
439
- */
440
182
  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
- }
183
+ const plan = this.requirePlan(planId);
184
+ if (review.taskId)
185
+ this.requireTask(plan, review.taskId);
449
186
  if (!plan.reviews)
450
187
  plan.reviews = [];
451
188
  plan.reviews.push({
452
- planId,
453
- taskId: review.taskId,
454
- reviewer: review.reviewer,
455
- outcome: review.outcome,
456
- comments: review.comments,
457
- reviewedAt: Date.now(),
189
+ planId, taskId: review.taskId, reviewer: review.reviewer,
190
+ outcome: review.outcome, comments: review.comments, reviewedAt: Date.now(),
458
191
  });
459
192
  plan.updatedAt = Date.now();
460
193
  this.save();
461
194
  return plan;
462
195
  }
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;
196
+ setGitHubProjection(planId, projection) {
197
+ const plan = this.requirePlan(planId);
198
+ plan.githubProjection = projection;
199
+ plan.updatedAt = Date.now();
200
+ this.save();
201
+ return plan;
496
202
  }
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
- }
203
+ getDispatch(planId, taskId) {
204
+ const plan = this.requirePlan(planId);
205
+ const task = this.requireTask(plan, taskId);
206
+ const unmetDeps = [];
207
+ for (const depId of task.dependsOn ?? []) {
208
+ const dep = plan.tasks.find((t) => t.id === depId);
209
+ if (dep && dep.status !== 'completed')
210
+ unmetDeps.push(dep);
519
211
  }
520
212
  return {
521
- totalDurationMs,
522
- tasksCompleted,
523
- tasksSkipped,
524
- tasksFailed,
525
- avgTaskDurationMs: tasksWithDuration > 0 ? Math.round(totalDurationMs / tasksWithDuration) : 0,
213
+ task, unmetDependencies: unmetDeps, ready: unmetDeps.length === 0,
214
+ ...(task.deliverables?.length && {
215
+ deliverableStatus: { count: task.deliverables.length, staleCount: task.deliverables.filter((d) => d.stale).length },
216
+ }),
526
217
  };
527
218
  }
528
- /**
529
- * Submit a deliverable for a task. Auto-computes SHA-256 hash for file deliverables.
530
- */
531
219
  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
- }
220
+ const plan = this.requirePlan(planId);
221
+ const task = this.requireTask(plan, taskId);
557
222
  if (!task.deliverables)
558
223
  task.deliverables = [];
559
- task.deliverables.push(entry);
224
+ task.deliverables.push(createDeliverable(deliverable));
560
225
  task.updatedAt = Date.now();
561
226
  plan.updatedAt = Date.now();
562
227
  this.save();
563
228
  return task;
564
229
  }
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
230
  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
- }
231
+ const plan = this.requirePlan(planId);
232
+ const task = this.requireTask(plan, taskId);
233
+ const result = verifyDeliverablesLogic(task.deliverables ?? [], vault);
234
+ task.deliverables = result.deliverables;
616
235
  plan.updatedAt = Date.now();
617
236
  this.save();
618
- return { verified: staleCount === 0, deliverables, staleCount };
237
+ return result;
619
238
  }
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
239
  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
- });
240
+ const plan = this.requirePlan(planId);
241
+ const task = this.requireTask(plan, taskId);
242
+ task.evidence = createEvidence(task.evidence ?? [], evidence);
640
243
  task.updatedAt = Date.now();
641
244
  plan.updatedAt = Date.now();
642
245
  this.save();
643
246
  return task;
644
247
  }
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
248
  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;
249
+ const plan = this.requirePlan(planId);
250
+ const task = this.requireTask(plan, taskId);
251
+ const result = verifyTaskLogic(task, plan.reviews ?? []);
252
+ if (result.verified !== task.verified) {
253
+ task.verified = result.verified;
673
254
  task.updatedAt = Date.now();
674
255
  plan.updatedAt = Date.now();
675
256
  this.save();
676
257
  }
677
- return { verified, task, missingCriteria, reviewStatus };
258
+ return { ...result, task };
678
259
  }
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
260
  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
- };
261
+ return verifyPlanLogic(planId, this.requirePlan(planId).tasks);
751
262
  }
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
- });
806
- }
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
263
  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 };
264
+ const plan = this.requirePlan(planId);
265
+ const task = this.requireTask(plan, taskId);
266
+ return { prompt: buildSpecReviewPrompt(task, plan.objective), task, plan };
837
267
  }
838
- /**
839
- * Generate a review prompt for code quality checking.
840
- */
841
268
  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 };
269
+ const plan = this.requirePlan(planId);
270
+ const task = this.requireTask(plan, taskId);
271
+ return { prompt: buildQualityReviewPrompt(task), task, plan };
866
272
  }
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
273
  archive(olderThanDays) {
873
274
  const cutoff = olderThanDays !== undefined
874
- ? Date.now() - olderThanDays * 24 * 60 * 60 * 1000
875
- : Date.now() + 1; // +1ms so archive() with no args archives all completed plans
275
+ ? Date.now() - olderThanDays * 24 * 60 * 60 * 1000 : Date.now() + 1;
876
276
  const toArchive = this.store.plans.filter((p) => p.status === 'completed' && p.updatedAt < cutoff);
877
277
  for (const plan of toArchive) {
878
278
  plan.status = 'archived';
879
279
  plan.updatedAt = Date.now();
880
280
  }
881
- if (toArchive.length > 0) {
281
+ if (toArchive.length > 0)
882
282
  this.save();
883
- }
884
283
  return toArchive;
885
284
  }
886
- /**
887
- * Get statistics about all plans.
888
- */
889
285
  stats() {
890
286
  const plans = this.store.plans;
891
- const byStatus = {
892
- brainstorming: 0,
893
- draft: 0,
894
- approved: 0,
895
- executing: 0,
896
- validating: 0,
897
- reconciling: 0,
898
- completed: 0,
899
- archived: 0,
900
- };
901
- const tasksByStatus = {
902
- pending: 0,
903
- in_progress: 0,
904
- completed: 0,
905
- skipped: 0,
906
- failed: 0,
907
- };
287
+ const byStatus = { brainstorming: 0, draft: 0, approved: 0, executing: 0,
288
+ validating: 0, reconciling: 0, completed: 0, archived: 0 };
289
+ const tasksByStatus = { pending: 0, in_progress: 0, completed: 0, skipped: 0, failed: 0 };
908
290
  let totalTasks = 0;
909
291
  for (const p of plans) {
910
292
  byStatus[p.status]++;
911
293
  totalTasks += p.tasks.length;
912
- for (const t of p.tasks) {
294
+ for (const t of p.tasks)
913
295
  tasksByStatus[t.status]++;
914
- }
915
296
  }
916
297
  return {
917
- total: plans.length,
918
- byStatus,
298
+ total: plans.length, byStatus, totalTasks, tasksByStatus,
919
299
  avgTasksPerPlan: plans.length > 0 ? Math.round((totalTasks / plans.length) * 100) / 100 : 0,
920
- totalTasks,
921
- tasksByStatus,
922
300
  };
923
301
  }
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
302
  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
303
+ const plan = this.requirePlan(planId);
944
304
  const gaps = runGapAnalysis(plan, this.gapOptions);
945
- // Add circular dependency check (structural, not covered by gap-analysis passes)
946
- if (this.hasCircularDependencies(plan)) {
305
+ if (hasCircularDependencies(plan.tasks)) {
947
306
  gaps.push({
948
- id: `gap_${Date.now()}_circ`,
949
- severity: 'critical',
950
- category: 'structure',
307
+ id: `gap_${Date.now()}_circ`, severity: 'critical', category: 'structure',
951
308
  description: 'Circular dependencies detected among tasks.',
952
309
  recommendation: 'Remove circular dependency chains so tasks can be executed in order.',
953
- location: 'tasks',
954
- _trigger: 'circular_dependencies',
310
+ location: 'tasks', _trigger: 'circular_dependencies',
955
311
  });
956
312
  }
957
- // Iteration = number of previous checks + 1
958
313
  const iteration = plan.checks.length + 1;
959
314
  const score = calculateScore(gaps, iteration);
960
- const grade = this.scoreToGrade(score);
961
315
  const check = {
962
316
  checkId: `chk-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
963
- planId,
964
- grade,
965
- score,
966
- gaps,
967
- iteration,
968
- checkedAt: Date.now(),
317
+ planId, grade: scoreToGrade(score), score, gaps, iteration, checkedAt: Date.now(),
969
318
  };
970
319
  plan.checks.push(check);
971
320
  plan.latestCheck = check;
@@ -973,88 +322,15 @@ export class Planner {
973
322
  this.save();
974
323
  return check;
975
324
  }
976
- /**
977
- * Get the latest check for a plan.
978
- */
979
325
  getLatestCheck(planId) {
980
- const plan = this.get(planId);
981
- if (!plan)
982
- throw new Error(`Plan not found: ${planId}`);
983
- return plan.latestCheck ?? null;
326
+ return this.requirePlan(planId).latestCheck ?? null;
984
327
  }
985
- /**
986
- * Get all checks for a plan (history).
987
- */
988
328
  getCheckHistory(planId) {
989
- const plan = this.get(planId);
990
- if (!plan)
991
- throw new Error(`Plan not found: ${planId}`);
992
- return [...plan.checks];
329
+ return [...this.requirePlan(planId).checks];
993
330
  }
994
- /**
995
- * Auto-grade: grade the plan and return whether it meets a target grade.
996
- */
997
331
  meetsGrade(planId, targetGrade) {
998
332
  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;
333
+ return { meets: check.score >= gradeToMinScore(targetGrade), check };
1058
334
  }
1059
335
  }
1060
336
  //# sourceMappingURL=planner.js.map