@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
@@ -0,0 +1,394 @@
1
+ /**
2
+ * Tests for gap-patterns.ts — helpers, constants, and passes 1-4.
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import type { Plan } from './planner.js';
7
+ import {
8
+ gap,
9
+ taskText,
10
+ decisionText,
11
+ decisionsText,
12
+ containsAny,
13
+ analyzeStructure,
14
+ analyzeCompleteness,
15
+ analyzeFeasibility,
16
+ analyzeRisk,
17
+ METRIC_PATTERNS,
18
+ EXCLUSION_KEYWORDS,
19
+ OVERLY_BROAD_PATTERNS,
20
+ DEPENDENCY_KEYWORDS,
21
+ BREAKING_CHANGE_KEYWORDS,
22
+ MITIGATION_KEYWORDS,
23
+ VERIFICATION_KEYWORDS,
24
+ } from './gap-patterns.js';
25
+
26
+ function makePlan(overrides: Partial<Plan> = {}): Plan {
27
+ return {
28
+ id: 'plan-test',
29
+ objective: 'Implement user authentication with JWT tokens and session management',
30
+ scope: 'Auth module, middleware, and user service. Does not include OAuth providers.',
31
+ status: 'draft',
32
+ decisions: [
33
+ {
34
+ decision: 'Use JWT for stateless auth',
35
+ rationale: 'Because it scales horizontally without shared session store',
36
+ },
37
+ ],
38
+ tasks: [
39
+ {
40
+ id: 'task-1',
41
+ title: 'Add JWT signing',
42
+ description: 'Implement JWT sign/verify using built-in crypto module',
43
+ status: 'pending',
44
+ updatedAt: Date.now(),
45
+ },
46
+ {
47
+ id: 'task-2',
48
+ title: 'Add auth middleware',
49
+ description: 'Create Express middleware that validates JWT from Authorization header',
50
+ status: 'pending',
51
+ updatedAt: Date.now(),
52
+ },
53
+ {
54
+ id: 'task-3',
55
+ title: 'Add login endpoint',
56
+ description: 'POST /auth/login returns JWT after verifying credentials',
57
+ status: 'pending',
58
+ updatedAt: Date.now(),
59
+ },
60
+ {
61
+ id: 'task-4',
62
+ title: 'Add test coverage',
63
+ description: 'Test JWT signing, middleware rejection, and login flow end-to-end',
64
+ status: 'pending',
65
+ updatedAt: Date.now(),
66
+ },
67
+ ],
68
+ checks: [],
69
+ createdAt: Date.now(),
70
+ updatedAt: Date.now(),
71
+ ...overrides,
72
+ };
73
+ }
74
+
75
+ describe('Helper functions', () => {
76
+ describe('gap()', () => {
77
+ it('creates a PlanGap with auto-generated id', () => {
78
+ const result = gap('critical', 'structure', 'desc', 'rec');
79
+ expect(result.id).toMatch(/^gap_/);
80
+ expect(result.severity).toBe('critical');
81
+ expect(result.category).toBe('structure');
82
+ expect(result.description).toBe('desc');
83
+ expect(result.recommendation).toBe('rec');
84
+ });
85
+
86
+ it('includes location when provided', () => {
87
+ const result = gap('minor', 'clarity', 'd', 'r', 'objective');
88
+ expect(result.location).toBe('objective');
89
+ });
90
+
91
+ it('excludes location when undefined', () => {
92
+ const result = gap('minor', 'clarity', 'd', 'r');
93
+ expect(result).not.toHaveProperty('location');
94
+ });
95
+
96
+ it('includes _trigger when provided', () => {
97
+ const result = gap('minor', 'clarity', 'd', 'r', undefined, 'test_trigger');
98
+ expect(result._trigger).toBe('test_trigger');
99
+ });
100
+
101
+ it('excludes _trigger when undefined', () => {
102
+ const result = gap('minor', 'clarity', 'd', 'r');
103
+ expect(result).not.toHaveProperty('_trigger');
104
+ });
105
+ });
106
+
107
+ describe('taskText()', () => {
108
+ it('combines task titles and descriptions', () => {
109
+ const plan = makePlan();
110
+ const text = taskText(plan);
111
+ expect(text).toContain('Add JWT signing');
112
+ expect(text).toContain('Implement JWT sign/verify');
113
+ });
114
+
115
+ it('returns empty string for plan with no tasks', () => {
116
+ const plan = makePlan({ tasks: [] });
117
+ expect(taskText(plan)).toBe('');
118
+ });
119
+ });
120
+
121
+ describe('decisionText()', () => {
122
+ it('extracts text from string decision', () => {
123
+ expect(decisionText('Use JWT')).toBe('Use JWT');
124
+ });
125
+
126
+ it('extracts text from structured decision', () => {
127
+ const result = decisionText({ decision: 'Use JWT', rationale: 'scales well' });
128
+ expect(result).toBe('Use JWT scales well');
129
+ });
130
+ });
131
+
132
+ describe('decisionsText()', () => {
133
+ it('combines all decisions', () => {
134
+ const plan = makePlan();
135
+ const text = decisionsText(plan);
136
+ expect(text).toContain('Use JWT for stateless auth');
137
+ expect(text).toContain('scales horizontally');
138
+ });
139
+ });
140
+
141
+ describe('containsAny()', () => {
142
+ it('returns true when text contains a pattern', () => {
143
+ expect(containsAny('rewrite everything from scratch', ['from scratch'])).toBe(true);
144
+ });
145
+
146
+ it('is case-insensitive', () => {
147
+ expect(containsAny('FROM SCRATCH', ['from scratch'])).toBe(true);
148
+ });
149
+
150
+ it('returns false when no patterns match', () => {
151
+ expect(containsAny('simple change', ['everything', 'rewrite'])).toBe(false);
152
+ });
153
+
154
+ it('returns false for empty text', () => {
155
+ expect(containsAny('', ['test'])).toBe(false);
156
+ });
157
+
158
+ it('returns false for empty patterns', () => {
159
+ expect(containsAny('hello world', [])).toBe(false);
160
+ });
161
+ });
162
+ });
163
+
164
+ describe('Pattern constants', () => {
165
+ it('METRIC_PATTERNS matches numbers', () => {
166
+ expect(METRIC_PATTERNS.some((p) => p.test('reduce latency by 50%'))).toBe(true);
167
+ });
168
+
169
+ it('EXCLUSION_KEYWORDS includes common exclusion words', () => {
170
+ expect(EXCLUSION_KEYWORDS).toContain('exclude');
171
+ expect(EXCLUSION_KEYWORDS).toContain('not');
172
+ });
173
+
174
+ it('OVERLY_BROAD_PATTERNS includes dangerous scope terms', () => {
175
+ expect(OVERLY_BROAD_PATTERNS).toContain('complete rewrite');
176
+ });
177
+
178
+ it('DEPENDENCY_KEYWORDS includes ordering terms', () => {
179
+ expect(DEPENDENCY_KEYWORDS).toContain('depends');
180
+ expect(DEPENDENCY_KEYWORDS).toContain('prerequisite');
181
+ });
182
+
183
+ it('BREAKING_CHANGE_KEYWORDS includes migration terms', () => {
184
+ expect(BREAKING_CHANGE_KEYWORDS).toContain('breaking change');
185
+ expect(BREAKING_CHANGE_KEYWORDS).toContain('database migration');
186
+ });
187
+
188
+ it('MITIGATION_KEYWORDS includes safety terms', () => {
189
+ expect(MITIGATION_KEYWORDS).toContain('rollback');
190
+ expect(MITIGATION_KEYWORDS).toContain('feature flag');
191
+ });
192
+
193
+ it('VERIFICATION_KEYWORDS includes testing terms', () => {
194
+ expect(VERIFICATION_KEYWORDS).toContain('test');
195
+ expect(VERIFICATION_KEYWORDS).toContain('coverage');
196
+ });
197
+ });
198
+
199
+ describe('Pass 1: Structure', () => {
200
+ it('returns no gaps for a well-structured plan', () => {
201
+ const gaps = analyzeStructure(makePlan());
202
+ expect(gaps).toHaveLength(0);
203
+ });
204
+
205
+ it('returns critical gap for missing objective', () => {
206
+ const gaps = analyzeStructure(makePlan({ objective: '' }));
207
+ expect(gaps.some((g) => g._trigger === 'missing_or_short_objective')).toBe(true);
208
+ expect(gaps.find((g) => g._trigger === 'missing_or_short_objective')?.severity).toBe(
209
+ 'critical',
210
+ );
211
+ });
212
+
213
+ it('returns critical gap for short objective', () => {
214
+ const gaps = analyzeStructure(makePlan({ objective: 'Fix' }));
215
+ expect(gaps.some((g) => g._trigger === 'missing_or_short_objective')).toBe(true);
216
+ });
217
+
218
+ it('returns critical gap for missing scope', () => {
219
+ const gaps = analyzeStructure(makePlan({ scope: '' }));
220
+ expect(gaps.some((g) => g._trigger === 'missing_or_short_scope')).toBe(true);
221
+ });
222
+
223
+ it('returns critical gap for no tasks', () => {
224
+ const gaps = analyzeStructure(makePlan({ tasks: [] }));
225
+ expect(gaps.some((g) => g._trigger === 'no_tasks')).toBe(true);
226
+ });
227
+
228
+ it('returns multiple gaps for completely empty plan', () => {
229
+ const gaps = analyzeStructure(makePlan({ objective: '', scope: '', tasks: [] }));
230
+ expect(gaps.length).toBe(3);
231
+ expect(gaps.every((g) => g.severity === 'critical')).toBe(true);
232
+ });
233
+ });
234
+
235
+ describe('Pass 2: Completeness', () => {
236
+ it('flags objective without measurable metrics', () => {
237
+ const plan = makePlan({ objective: 'Improve the login experience for all users globally' });
238
+ const gaps = analyzeCompleteness(plan);
239
+ expect(gaps.some((g) => g._trigger === 'no_metrics_in_objective')).toBe(true);
240
+ });
241
+
242
+ it('does not flag objective with numbers', () => {
243
+ const plan = makePlan({ objective: 'Reduce login latency to under 200ms for 95% of users' });
244
+ const gaps = analyzeCompleteness(plan);
245
+ expect(gaps.some((g) => g._trigger === 'no_metrics_in_objective')).toBe(false);
246
+ });
247
+
248
+ it('flags short decisions', () => {
249
+ const plan = makePlan({ decisions: [{ decision: 'JWT', rationale: '' }] });
250
+ const gaps = analyzeCompleteness(plan);
251
+ expect(gaps.some((g) => g._trigger === 'short_decision')).toBe(true);
252
+ });
253
+
254
+ it('flags scope without exclusions', () => {
255
+ const plan = makePlan({ scope: 'Auth module and middleware for the API layer' });
256
+ const gaps = analyzeCompleteness(plan);
257
+ expect(gaps.some((g) => g._trigger === 'no_exclusions_in_scope')).toBe(true);
258
+ });
259
+
260
+ it('does not flag scope with exclusion keywords', () => {
261
+ const plan = makePlan({ scope: 'Auth module. Does not include OAuth providers.' });
262
+ const gaps = analyzeCompleteness(plan);
263
+ expect(gaps.some((g) => g._trigger === 'no_exclusions_in_scope')).toBe(false);
264
+ });
265
+ });
266
+
267
+ describe('Pass 3: Feasibility', () => {
268
+ it('flags overly broad scope', () => {
269
+ const plan = makePlan({ scope: 'Complete rewrite of the entire codebase' });
270
+ const gaps = analyzeFeasibility(plan);
271
+ expect(gaps.some((g) => g._trigger === 'overly_broad_scope')).toBe(true);
272
+ });
273
+
274
+ it('does not flag reasonable scope', () => {
275
+ const plan = makePlan();
276
+ const gaps = analyzeFeasibility(plan);
277
+ expect(gaps.some((g) => g._trigger === 'overly_broad_scope')).toBe(false);
278
+ });
279
+
280
+ it('flags missing dependencies for 4+ tasks', () => {
281
+ const plan = makePlan();
282
+ // Default plan has 4 tasks, no dependency keywords
283
+ const gaps = analyzeFeasibility(plan);
284
+ expect(gaps.some((g) => g._trigger === 'no_dependency_awareness')).toBe(true);
285
+ });
286
+
287
+ it('does not flag when tasks have dependsOn', () => {
288
+ const plan = makePlan({
289
+ tasks: [
290
+ {
291
+ id: 't1',
292
+ title: 'Setup',
293
+ description: 'Setup project',
294
+ status: 'pending',
295
+ updatedAt: Date.now(),
296
+ },
297
+ {
298
+ id: 't2',
299
+ title: 'Build',
300
+ description: 'Build feature',
301
+ status: 'pending',
302
+ dependsOn: ['t1'],
303
+ updatedAt: Date.now(),
304
+ },
305
+ {
306
+ id: 't3',
307
+ title: 'Test',
308
+ description: 'Test feature',
309
+ status: 'pending',
310
+ dependsOn: ['t2'],
311
+ updatedAt: Date.now(),
312
+ },
313
+ {
314
+ id: 't4',
315
+ title: 'Deploy',
316
+ description: 'Deploy to prod',
317
+ status: 'pending',
318
+ dependsOn: ['t3'],
319
+ updatedAt: Date.now(),
320
+ },
321
+ ],
322
+ });
323
+ const gaps = analyzeFeasibility(plan);
324
+ expect(gaps.some((g) => g._trigger === 'no_dependency_awareness')).toBe(false);
325
+ });
326
+
327
+ it('does not flag when 3 or fewer tasks', () => {
328
+ const plan = makePlan({
329
+ tasks: [
330
+ {
331
+ id: 't1',
332
+ title: 'Task 1',
333
+ description: 'Do something',
334
+ status: 'pending',
335
+ updatedAt: Date.now(),
336
+ },
337
+ {
338
+ id: 't2',
339
+ title: 'Task 2',
340
+ description: 'Do another thing',
341
+ status: 'pending',
342
+ updatedAt: Date.now(),
343
+ },
344
+ ],
345
+ });
346
+ const gaps = analyzeFeasibility(plan);
347
+ expect(gaps.some((g) => g._trigger === 'no_dependency_awareness')).toBe(false);
348
+ });
349
+ });
350
+
351
+ describe('Pass 4: Risk', () => {
352
+ it('flags breaking changes without mitigation', () => {
353
+ const plan = makePlan({
354
+ objective: 'Database migration to new schema with breaking changes',
355
+ scope: 'All tables and models. Does not include frontend.',
356
+ });
357
+ const gaps = analyzeRisk(plan);
358
+ expect(gaps.some((g) => g._trigger === 'breaking_without_mitigation')).toBe(true);
359
+ });
360
+
361
+ it('does not flag when mitigation is mentioned', () => {
362
+ const plan = makePlan({
363
+ objective: 'Database migration with breaking changes and rollback plan',
364
+ scope: 'All tables. Not including frontend.',
365
+ });
366
+ const gaps = analyzeRisk(plan);
367
+ expect(gaps.some((g) => g._trigger === 'breaking_without_mitigation')).toBe(false);
368
+ });
369
+
370
+ it('flags missing verification', () => {
371
+ const plan = makePlan({
372
+ objective: 'Refactor the authentication module for better performance',
373
+ scope: 'Auth module only. Not including user service.',
374
+ decisions: [{ decision: 'Use new pattern', rationale: 'Because it is cleaner code' }],
375
+ tasks: [
376
+ {
377
+ id: 't1',
378
+ title: 'Refactor auth',
379
+ description: 'Change the auth flow implementation',
380
+ status: 'pending',
381
+ updatedAt: Date.now(),
382
+ },
383
+ ],
384
+ });
385
+ const gaps = analyzeRisk(plan);
386
+ expect(gaps.some((g) => g._trigger === 'no_verification_mentioned')).toBe(true);
387
+ });
388
+
389
+ it('does not flag when testing is mentioned', () => {
390
+ const plan = makePlan(); // default plan has "test" in task descriptions
391
+ const gaps = analyzeRisk(plan);
392
+ expect(gaps.some((g) => g._trigger === 'no_verification_mentioned')).toBe(false);
393
+ });
394
+ });
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Gap analysis helpers, pattern constants, and structural passes (1-4).
3
+ * Contains shared utilities and the first four analysis passes that check
4
+ * structure, completeness, feasibility, and risk.
5
+ */
6
+
7
+ import type { Plan, PlanDecision } from './planner.js';
8
+ import type { PlanGap, GapSeverity, GapCategory } from './gap-types.js';
9
+ import {
10
+ generateGapId,
11
+ MIN_OBJECTIVE_LENGTH,
12
+ MIN_SCOPE_LENGTH,
13
+ MIN_DECISION_LENGTH,
14
+ } from './gap-types.js';
15
+
16
+ // ─── Helper Functions ────────────────────────────────────────────
17
+
18
+ /** Create a PlanGap with auto-generated ID. */
19
+ export function gap(
20
+ severity: GapSeverity,
21
+ category: GapCategory,
22
+ description: string,
23
+ recommendation: string,
24
+ location?: string,
25
+ trigger?: string,
26
+ ): PlanGap {
27
+ return {
28
+ id: generateGapId(),
29
+ severity,
30
+ category,
31
+ description,
32
+ recommendation,
33
+ ...(location ? { location } : {}),
34
+ ...(trigger ? { _trigger: trigger } : {}),
35
+ };
36
+ }
37
+
38
+ /** Combine all task descriptions + titles into a single text blob for analysis. */
39
+ export function taskText(plan: Plan): string {
40
+ return plan.tasks.map((t) => `${t.title} ${t.description}`).join(' ');
41
+ }
42
+
43
+ /** Extract text from a decision (supports both string and structured format). */
44
+ export function decisionText(d: string | PlanDecision): string {
45
+ return typeof d === 'string' ? d : `${d.decision} ${d.rationale}`;
46
+ }
47
+
48
+ /** Combine all decisions into a single text blob. */
49
+ export function decisionsText(plan: Plan): string {
50
+ return plan.decisions.map(decisionText).join(' ');
51
+ }
52
+
53
+ /** Check if text contains any of the given patterns (case-insensitive). */
54
+ export function containsAny(text: string, patterns: string[]): boolean {
55
+ const lower = text.toLowerCase();
56
+ return patterns.some((p) => lower.includes(p.toLowerCase()));
57
+ }
58
+
59
+ // ─── Pattern Constants (Passes 1-4) ─────────────────────────────
60
+
61
+ export const METRIC_PATTERNS = [
62
+ /\d+/,
63
+ /percent/i,
64
+ /reduce/i,
65
+ /increase/i,
66
+ /measure/i,
67
+ /target/i,
68
+ /goal/i,
69
+ /kpi/i,
70
+ /metric/i,
71
+ /benchmark/i,
72
+ ];
73
+
74
+ export const EXCLUSION_KEYWORDS = [
75
+ 'not',
76
+ 'exclude',
77
+ 'outside',
78
+ 'beyond',
79
+ 'limit',
80
+ 'except',
81
+ "won't",
82
+ 'will not',
83
+ ];
84
+
85
+ export const OVERLY_BROAD_PATTERNS = [
86
+ 'everything',
87
+ 'all systems',
88
+ 'entire codebase',
89
+ 'complete rewrite',
90
+ 'from scratch',
91
+ 'total overhaul',
92
+ 'rewrite everything',
93
+ ];
94
+
95
+ export const DEPENDENCY_KEYWORDS = [
96
+ 'depends',
97
+ 'dependency',
98
+ 'prerequisite',
99
+ 'requires',
100
+ 'blocked',
101
+ 'before',
102
+ ];
103
+
104
+ export const BREAKING_CHANGE_KEYWORDS = [
105
+ 'breaking change',
106
+ 'breaking',
107
+ 'migration',
108
+ 'deprecate',
109
+ 'remove api',
110
+ 'remove endpoint',
111
+ 'schema change',
112
+ 'database migration',
113
+ ];
114
+
115
+ export const MITIGATION_KEYWORDS = [
116
+ 'rollback',
117
+ 'backward compatible',
118
+ 'backwards compatible',
119
+ 'feature flag',
120
+ 'gradual',
121
+ 'phased',
122
+ 'fallback',
123
+ 'backup',
124
+ 'canary',
125
+ 'blue-green',
126
+ ];
127
+
128
+ export const VERIFICATION_KEYWORDS = [
129
+ 'test',
130
+ 'verify',
131
+ 'validate',
132
+ 'check',
133
+ 'assert',
134
+ 'confirm',
135
+ 'spec',
136
+ 'coverage',
137
+ ];
138
+
139
+ // ─── Pass 1: Structure ───────────────────────────────────────────
140
+
141
+ export function analyzeStructure(plan: Plan): PlanGap[] {
142
+ const gaps: PlanGap[] = [];
143
+
144
+ if (!plan.objective || plan.objective.trim().length < MIN_OBJECTIVE_LENGTH) {
145
+ gaps.push(
146
+ gap(
147
+ 'critical',
148
+ 'structure',
149
+ plan.objective
150
+ ? `Objective too short (${plan.objective.trim().length} chars, need ${MIN_OBJECTIVE_LENGTH}+).`
151
+ : 'Plan has no objective.',
152
+ 'Add a clear objective describing what this plan achieves.',
153
+ 'objective',
154
+ 'missing_or_short_objective',
155
+ ),
156
+ );
157
+ }
158
+
159
+ if (!plan.scope || plan.scope.trim().length < MIN_SCOPE_LENGTH) {
160
+ gaps.push(
161
+ gap(
162
+ 'critical',
163
+ 'structure',
164
+ plan.scope
165
+ ? `Scope too short (${plan.scope.trim().length} chars, need ${MIN_SCOPE_LENGTH}+).`
166
+ : 'Plan has no scope defined.',
167
+ 'Define the scope — what is included and excluded.',
168
+ 'scope',
169
+ 'missing_or_short_scope',
170
+ ),
171
+ );
172
+ }
173
+
174
+ if (plan.tasks.length === 0) {
175
+ gaps.push(
176
+ gap(
177
+ 'critical',
178
+ 'structure',
179
+ 'Plan has no tasks.',
180
+ 'Add at least one task to make the plan actionable.',
181
+ 'tasks',
182
+ 'no_tasks',
183
+ ),
184
+ );
185
+ }
186
+
187
+ return gaps;
188
+ }
189
+
190
+ // ─── Pass 2: Completeness ────────────────────────────────────────
191
+
192
+ export function analyzeCompleteness(plan: Plan): PlanGap[] {
193
+ const gaps: PlanGap[] = [];
194
+
195
+ if (plan.objective && !METRIC_PATTERNS.some((p) => p.test(plan.objective))) {
196
+ gaps.push(
197
+ gap(
198
+ 'minor',
199
+ 'completeness',
200
+ 'Objective has no measurable targets or metrics.',
201
+ 'Include quantifiable success criteria (numbers, percentages, concrete outcomes).',
202
+ 'objective',
203
+ 'no_metrics_in_objective',
204
+ ),
205
+ );
206
+ }
207
+
208
+ if (plan.decisions.length > 0) {
209
+ for (let i = 0; i < plan.decisions.length; i++) {
210
+ const d = plan.decisions[i];
211
+ const text = decisionText(d);
212
+ if (text.trim().length < MIN_DECISION_LENGTH) {
213
+ gaps.push(
214
+ gap(
215
+ 'major',
216
+ 'completeness',
217
+ `Decision ${i + 1} is too short (${text.trim().length} chars) — lacks rationale.`,
218
+ 'Expand each decision to include the reasoning (why this choice over alternatives).',
219
+ `decisions[${i}]`,
220
+ 'short_decision',
221
+ ),
222
+ );
223
+ }
224
+ }
225
+ }
226
+
227
+ if (plan.scope && !containsAny(plan.scope, EXCLUSION_KEYWORDS)) {
228
+ gaps.push(
229
+ gap(
230
+ 'minor',
231
+ 'completeness',
232
+ 'Scope does not mention what is excluded.',
233
+ 'Add explicit exclusions to prevent scope creep (e.g., "does NOT include…").',
234
+ 'scope',
235
+ 'no_exclusions_in_scope',
236
+ ),
237
+ );
238
+ }
239
+
240
+ return gaps;
241
+ }
242
+
243
+ // ─── Pass 3: Feasibility ─────────────────────────────────────────
244
+
245
+ export function analyzeFeasibility(plan: Plan): PlanGap[] {
246
+ const gaps: PlanGap[] = [];
247
+ const scopeAndTasks = `${plan.scope} ${taskText(plan)}`;
248
+
249
+ if (containsAny(scopeAndTasks, OVERLY_BROAD_PATTERNS)) {
250
+ gaps.push(
251
+ gap(
252
+ 'major',
253
+ 'feasibility',
254
+ 'Scope contains overly broad indicators — risk of unrealistic delivery.',
255
+ 'Narrow the scope to a well-defined subset. Prefer incremental delivery over big-bang rewrites.',
256
+ 'scope',
257
+ 'overly_broad_scope',
258
+ ),
259
+ );
260
+ }
261
+
262
+ if (plan.tasks.length > 3 && !containsAny(scopeAndTasks, DEPENDENCY_KEYWORDS)) {
263
+ const hasDeps = plan.tasks.some((t) => t.dependsOn && t.dependsOn.length > 0);
264
+ if (!hasDeps) {
265
+ gaps.push(
266
+ gap(
267
+ 'minor',
268
+ 'feasibility',
269
+ `${plan.tasks.length} tasks with no dependency mentions — execution order unclear.`,
270
+ 'Identify dependencies between tasks or add explicit ordering notes.',
271
+ 'tasks',
272
+ 'no_dependency_awareness',
273
+ ),
274
+ );
275
+ }
276
+ }
277
+
278
+ return gaps;
279
+ }
280
+
281
+ // ─── Pass 4: Risk ────────────────────────────────────────────────
282
+
283
+ export function analyzeRisk(plan: Plan): PlanGap[] {
284
+ const gaps: PlanGap[] = [];
285
+ const allText = `${plan.objective} ${plan.scope} ${taskText(plan)} ${decisionsText(plan)}`;
286
+
287
+ if (
288
+ containsAny(allText, BREAKING_CHANGE_KEYWORDS) &&
289
+ !containsAny(allText, MITIGATION_KEYWORDS)
290
+ ) {
291
+ gaps.push(
292
+ gap(
293
+ 'major',
294
+ 'risk',
295
+ 'Plan involves breaking changes but mentions no mitigation strategy.',
296
+ 'Add a rollback plan, feature flags, or phased migration approach.',
297
+ undefined,
298
+ 'breaking_without_mitigation',
299
+ ),
300
+ );
301
+ }
302
+
303
+ if (plan.tasks.length > 0 && !containsAny(allText, VERIFICATION_KEYWORDS)) {
304
+ gaps.push(
305
+ gap(
306
+ 'minor',
307
+ 'risk',
308
+ 'No verification or testing mentioned in the plan.',
309
+ 'Add at least one task or note about testing/validation.',
310
+ 'tasks',
311
+ 'no_verification_mentioned',
312
+ ),
313
+ );
314
+ }
315
+
316
+ return gaps;
317
+ }