@planu/cli 0.89.0 → 0.90.1

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 (446) hide show
  1. package/dist/cli/commands/activate.d.ts +14 -0
  2. package/dist/cli/commands/activate.d.ts.map +1 -0
  3. package/dist/cli/commands/activate.js +174 -0
  4. package/dist/cli/commands/activate.js.map +1 -0
  5. package/dist/cli/commands/doctor.d.ts +16 -0
  6. package/dist/cli/commands/doctor.d.ts.map +1 -0
  7. package/dist/cli/commands/doctor.js +162 -0
  8. package/dist/cli/commands/doctor.js.map +1 -0
  9. package/dist/cli/commands/install.d.ts +48 -0
  10. package/dist/cli/commands/install.d.ts.map +1 -0
  11. package/dist/cli/commands/install.js +348 -0
  12. package/dist/cli/commands/install.js.map +1 -0
  13. package/dist/cli/commands/uninstall.d.ts +10 -0
  14. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  15. package/dist/cli/commands/uninstall.js +133 -0
  16. package/dist/cli/commands/uninstall.js.map +1 -0
  17. package/dist/cli/router.d.ts.map +1 -1
  18. package/dist/cli/router.js +9 -1
  19. package/dist/cli/router.js.map +1 -1
  20. package/dist/config/license-plans.json +2 -1
  21. package/dist/engine/agent-generator.test.d.ts +2 -0
  22. package/dist/engine/agent-generator.test.d.ts.map +1 -0
  23. package/dist/engine/agent-generator.test.js +556 -0
  24. package/dist/engine/agent-generator.test.js.map +1 -0
  25. package/dist/engine/analyzer.test.d.ts +2 -0
  26. package/dist/engine/analyzer.test.d.ts.map +1 -0
  27. package/dist/engine/analyzer.test.js +1461 -0
  28. package/dist/engine/analyzer.test.js.map +1 -0
  29. package/dist/engine/auditor.test.d.ts +2 -0
  30. package/dist/engine/auditor.test.d.ts.map +1 -0
  31. package/dist/engine/auditor.test.js +2075 -0
  32. package/dist/engine/auditor.test.js.map +1 -0
  33. package/dist/engine/doc-generator.test.d.ts +2 -0
  34. package/dist/engine/doc-generator.test.d.ts.map +1 -0
  35. package/dist/engine/doc-generator.test.js +961 -0
  36. package/dist/engine/doc-generator.test.js.map +1 -0
  37. package/dist/engine/estimator.test.d.ts +2 -0
  38. package/dist/engine/estimator.test.d.ts.map +1 -0
  39. package/dist/engine/estimator.test.js +334 -0
  40. package/dist/engine/estimator.test.js.map +1 -0
  41. package/dist/engine/skill-generator.test.d.ts +2 -0
  42. package/dist/engine/skill-generator.test.d.ts.map +1 -0
  43. package/dist/engine/skill-generator.test.js +742 -0
  44. package/dist/engine/skill-generator.test.js.map +1 -0
  45. package/dist/engine/spec-migrator/filesystem-import.d.ts +14 -0
  46. package/dist/engine/spec-migrator/filesystem-import.d.ts.map +1 -0
  47. package/dist/engine/spec-migrator/filesystem-import.js +96 -0
  48. package/dist/engine/spec-migrator/filesystem-import.js.map +1 -0
  49. package/dist/engine/spec-migrator/flatten-specs.d.ts +12 -0
  50. package/dist/engine/spec-migrator/flatten-specs.d.ts.map +1 -0
  51. package/dist/engine/spec-migrator/flatten-specs.js +111 -0
  52. package/dist/engine/spec-migrator/flatten-specs.js.map +1 -0
  53. package/dist/engine/spec-migrator/folder-operations.d.ts +9 -0
  54. package/dist/engine/spec-migrator/folder-operations.d.ts.map +1 -0
  55. package/dist/engine/spec-migrator/folder-operations.js +109 -0
  56. package/dist/engine/spec-migrator/folder-operations.js.map +1 -0
  57. package/dist/engine/spec-migrator/frontmatter-parser.d.ts +11 -0
  58. package/dist/engine/spec-migrator/frontmatter-parser.d.ts.map +1 -0
  59. package/dist/engine/spec-migrator/frontmatter-parser.js +92 -0
  60. package/dist/engine/spec-migrator/frontmatter-parser.js.map +1 -0
  61. package/dist/engine/spec-migrator/index.d.ts +9 -0
  62. package/dist/engine/spec-migrator/index.d.ts.map +1 -0
  63. package/dist/engine/spec-migrator/index.js +18 -0
  64. package/dist/engine/spec-migrator/index.js.map +1 -0
  65. package/dist/engine/spec-migrator/legacy-migration.d.ts +13 -0
  66. package/dist/engine/spec-migrator/legacy-migration.d.ts.map +1 -0
  67. package/dist/engine/spec-migrator/legacy-migration.js +75 -0
  68. package/dist/engine/spec-migrator/legacy-migration.js.map +1 -0
  69. package/dist/engine/spec-migrator/migration-validator.d.ts +20 -0
  70. package/dist/engine/spec-migrator/migration-validator.d.ts.map +1 -0
  71. package/dist/engine/spec-migrator/migration-validator.js +35 -0
  72. package/dist/engine/spec-migrator/migration-validator.js.map +1 -0
  73. package/dist/engine/spec-migrator/path-utils.d.ts +13 -0
  74. package/dist/engine/spec-migrator/path-utils.d.ts.map +1 -0
  75. package/dist/engine/spec-migrator/path-utils.js +40 -0
  76. package/dist/engine/spec-migrator/path-utils.js.map +1 -0
  77. package/dist/engine/spec-migrator/prefix-migration.d.ts +11 -0
  78. package/dist/engine/spec-migrator/prefix-migration.d.ts.map +1 -0
  79. package/dist/engine/spec-migrator/prefix-migration.js +73 -0
  80. package/dist/engine/spec-migrator/prefix-migration.js.map +1 -0
  81. package/dist/engine/spec-migrator/reconcile-paths.d.ts +12 -0
  82. package/dist/engine/spec-migrator/reconcile-paths.d.ts.map +1 -0
  83. package/dist/engine/spec-migrator/reconcile-paths.js +77 -0
  84. package/dist/engine/spec-migrator/reconcile-paths.js.map +1 -0
  85. package/dist/engine/spec-migrator/version-detection.d.ts +5 -0
  86. package/dist/engine/spec-migrator/version-detection.d.ts.map +1 -0
  87. package/dist/engine/spec-migrator/version-detection.js +19 -0
  88. package/dist/engine/spec-migrator/version-detection.js.map +1 -0
  89. package/dist/engine/spec-migrator.d.ts +1 -58
  90. package/dist/engine/spec-migrator.d.ts.map +1 -1
  91. package/dist/engine/spec-migrator.js +2 -658
  92. package/dist/engine/spec-migrator.js.map +1 -1
  93. package/dist/engine/spec-summary-html/dashboard-renderer.d.ts +6 -0
  94. package/dist/engine/spec-summary-html/dashboard-renderer.d.ts.map +1 -0
  95. package/dist/engine/spec-summary-html/dashboard-renderer.js +333 -0
  96. package/dist/engine/spec-summary-html/dashboard-renderer.js.map +1 -0
  97. package/dist/engine/spec-summary-html/hash-utils.d.ts +11 -0
  98. package/dist/engine/spec-summary-html/hash-utils.d.ts.map +1 -0
  99. package/dist/engine/spec-summary-html/hash-utils.js +39 -0
  100. package/dist/engine/spec-summary-html/hash-utils.js.map +1 -0
  101. package/dist/engine/spec-summary-html/index.d.ts +4 -0
  102. package/dist/engine/spec-summary-html/index.d.ts.map +1 -0
  103. package/dist/engine/spec-summary-html/index.js +6 -0
  104. package/dist/engine/spec-summary-html/index.js.map +1 -0
  105. package/dist/engine/spec-summary-html/report-renderer.d.ts +9 -0
  106. package/dist/engine/spec-summary-html/report-renderer.d.ts.map +1 -0
  107. package/dist/engine/spec-summary-html/report-renderer.js +139 -0
  108. package/dist/engine/spec-summary-html/report-renderer.js.map +1 -0
  109. package/dist/engine/spec-summary-html.d.ts +1 -0
  110. package/dist/engine/spec-summary-html.d.ts.map +1 -1
  111. package/dist/engine/spec-summary-html.js +19 -473
  112. package/dist/engine/spec-summary-html.js.map +1 -1
  113. package/dist/engine/update-notifier.d.ts +8 -0
  114. package/dist/engine/update-notifier.d.ts.map +1 -0
  115. package/dist/engine/update-notifier.js +130 -0
  116. package/dist/engine/update-notifier.js.map +1 -0
  117. package/dist/engine/validator/dor-dod.d.ts.map +1 -1
  118. package/dist/engine/validator/dor-dod.js +8 -5
  119. package/dist/engine/validator/dor-dod.js.map +1 -1
  120. package/dist/engine/validator.d.ts.map +1 -1
  121. package/dist/engine/validator.js +4 -3
  122. package/dist/engine/validator.js.map +1 -1
  123. package/dist/engine/validator.test.d.ts +2 -0
  124. package/dist/engine/validator.test.d.ts.map +1 -0
  125. package/dist/engine/validator.test.js +2371 -0
  126. package/dist/engine/validator.test.js.map +1 -0
  127. package/dist/engine/web-fetcher.test.d.ts +2 -0
  128. package/dist/engine/web-fetcher.test.d.ts.map +1 -0
  129. package/dist/engine/web-fetcher.test.js +360 -0
  130. package/dist/engine/web-fetcher.test.js.map +1 -0
  131. package/dist/i18n/index.test.d.ts +2 -0
  132. package/dist/i18n/index.test.d.ts.map +1 -0
  133. package/dist/i18n/index.test.js +375 -0
  134. package/dist/i18n/index.test.js.map +1 -0
  135. package/dist/index.js +8 -0
  136. package/dist/index.js.map +1 -1
  137. package/dist/index.test.d.ts +2 -0
  138. package/dist/index.test.d.ts.map +1 -0
  139. package/dist/index.test.js +124 -0
  140. package/dist/index.test.js.map +1 -0
  141. package/dist/resources/patterns.test.d.ts +2 -0
  142. package/dist/resources/patterns.test.d.ts.map +1 -0
  143. package/dist/resources/patterns.test.js +142 -0
  144. package/dist/resources/patterns.test.js.map +1 -0
  145. package/dist/resources/process.test.d.ts +2 -0
  146. package/dist/resources/process.test.d.ts.map +1 -0
  147. package/dist/resources/process.test.js +48 -0
  148. package/dist/resources/process.test.js.map +1 -0
  149. package/dist/resources/registry.test.d.ts +2 -0
  150. package/dist/resources/registry.test.d.ts.map +1 -0
  151. package/dist/resources/registry.test.js +138 -0
  152. package/dist/resources/registry.test.js.map +1 -0
  153. package/dist/resources/specs.test.d.ts +2 -0
  154. package/dist/resources/specs.test.d.ts.map +1 -0
  155. package/dist/resources/specs.test.js +130 -0
  156. package/dist/resources/specs.test.js.map +1 -0
  157. package/dist/resources/templates.test.d.ts +2 -0
  158. package/dist/resources/templates.test.d.ts.map +1 -0
  159. package/dist/resources/templates.test.js +119 -0
  160. package/dist/resources/templates.test.js.map +1 -0
  161. package/dist/smoke.test.d.ts +2 -0
  162. package/dist/smoke.test.d.ts.map +1 -0
  163. package/dist/smoke.test.js +229 -0
  164. package/dist/smoke.test.js.map +1 -0
  165. package/dist/storage/base-store.test.d.ts +2 -0
  166. package/dist/storage/base-store.test.d.ts.map +1 -0
  167. package/dist/storage/base-store.test.js +180 -0
  168. package/dist/storage/base-store.test.js.map +1 -0
  169. package/dist/storage/global-store.test.d.ts +2 -0
  170. package/dist/storage/global-store.test.d.ts.map +1 -0
  171. package/dist/storage/global-store.test.js +327 -0
  172. package/dist/storage/global-store.test.js.map +1 -0
  173. package/dist/storage/index.test.d.ts +2 -0
  174. package/dist/storage/index.test.d.ts.map +1 -0
  175. package/dist/storage/index.test.js +56 -0
  176. package/dist/storage/index.test.js.map +1 -0
  177. package/dist/storage/knowledge-store.test.d.ts +2 -0
  178. package/dist/storage/knowledge-store.test.d.ts.map +1 -0
  179. package/dist/storage/knowledge-store.test.js +368 -0
  180. package/dist/storage/knowledge-store.test.js.map +1 -0
  181. package/dist/storage/metrics-store.test.d.ts +2 -0
  182. package/dist/storage/metrics-store.test.d.ts.map +1 -0
  183. package/dist/storage/metrics-store.test.js +212 -0
  184. package/dist/storage/metrics-store.test.js.map +1 -0
  185. package/dist/storage/pattern-store.test.d.ts +2 -0
  186. package/dist/storage/pattern-store.test.d.ts.map +1 -0
  187. package/dist/storage/pattern-store.test.js +224 -0
  188. package/dist/storage/pattern-store.test.js.map +1 -0
  189. package/dist/storage/spec-store.test.d.ts +2 -0
  190. package/dist/storage/spec-store.test.d.ts.map +1 -0
  191. package/dist/storage/spec-store.test.js +227 -0
  192. package/dist/storage/spec-store.test.js.map +1 -0
  193. package/dist/tools/audit.test.d.ts +2 -0
  194. package/dist/tools/audit.test.d.ts.map +1 -0
  195. package/dist/tools/audit.test.js +169 -0
  196. package/dist/tools/audit.test.js.map +1 -0
  197. package/dist/tools/challenge-spec.test.d.ts +2 -0
  198. package/dist/tools/challenge-spec.test.d.ts.map +1 -0
  199. package/dist/tools/challenge-spec.test.js +782 -0
  200. package/dist/tools/challenge-spec.test.js.map +1 -0
  201. package/dist/tools/check-versions.test.d.ts +2 -0
  202. package/dist/tools/check-versions.test.d.ts.map +1 -0
  203. package/dist/tools/check-versions.test.js +214 -0
  204. package/dist/tools/check-versions.test.js.map +1 -0
  205. package/dist/tools/clarify-requirements.test.d.ts +2 -0
  206. package/dist/tools/clarify-requirements.test.d.ts.map +1 -0
  207. package/dist/tools/clarify-requirements.test.js +161 -0
  208. package/dist/tools/clarify-requirements.test.js.map +1 -0
  209. package/dist/tools/consult-docs.test.d.ts +2 -0
  210. package/dist/tools/consult-docs.test.d.ts.map +1 -0
  211. package/dist/tools/consult-docs.test.js +140 -0
  212. package/dist/tools/consult-docs.test.js.map +1 -0
  213. package/dist/tools/create-spec.test.d.ts +2 -0
  214. package/dist/tools/create-spec.test.d.ts.map +1 -0
  215. package/dist/tools/create-spec.test.js +233 -0
  216. package/dist/tools/create-spec.test.js.map +1 -0
  217. package/dist/tools/define-ui-contract.test.d.ts +2 -0
  218. package/dist/tools/define-ui-contract.test.d.ts.map +1 -0
  219. package/dist/tools/define-ui-contract.test.js +479 -0
  220. package/dist/tools/define-ui-contract.test.js.map +1 -0
  221. package/dist/tools/design-schema.test.d.ts +2 -0
  222. package/dist/tools/design-schema.test.d.ts.map +1 -0
  223. package/dist/tools/design-schema.test.js +301 -0
  224. package/dist/tools/design-schema.test.js.map +1 -0
  225. package/dist/tools/detect-agent.test.d.ts +2 -0
  226. package/dist/tools/detect-agent.test.d.ts.map +1 -0
  227. package/dist/tools/detect-agent.test.js +133 -0
  228. package/dist/tools/detect-agent.test.js.map +1 -0
  229. package/dist/tools/detect-drift.test.d.ts +2 -0
  230. package/dist/tools/detect-drift.test.d.ts.map +1 -0
  231. package/dist/tools/detect-drift.test.js +312 -0
  232. package/dist/tools/detect-drift.test.js.map +1 -0
  233. package/dist/tools/discover-mcps.test.d.ts +2 -0
  234. package/dist/tools/discover-mcps.test.d.ts.map +1 -0
  235. package/dist/tools/discover-mcps.test.js +345 -0
  236. package/dist/tools/discover-mcps.test.js.map +1 -0
  237. package/dist/tools/estimate.test.d.ts +2 -0
  238. package/dist/tools/estimate.test.d.ts.map +1 -0
  239. package/dist/tools/estimate.test.js +137 -0
  240. package/dist/tools/estimate.test.js.map +1 -0
  241. package/dist/tools/generate-adr.test.d.ts +2 -0
  242. package/dist/tools/generate-adr.test.d.ts.map +1 -0
  243. package/dist/tools/generate-adr.test.js +206 -0
  244. package/dist/tools/generate-adr.test.js.map +1 -0
  245. package/dist/tools/generate-checklist.test.d.ts +2 -0
  246. package/dist/tools/generate-checklist.test.d.ts.map +1 -0
  247. package/dist/tools/generate-checklist.test.js +201 -0
  248. package/dist/tools/generate-checklist.test.js.map +1 -0
  249. package/dist/tools/generate-docs.test.d.ts +2 -0
  250. package/dist/tools/generate-docs.test.d.ts.map +1 -0
  251. package/dist/tools/generate-docs.test.js +183 -0
  252. package/dist/tools/generate-docs.test.js.map +1 -0
  253. package/dist/tools/generate-execution-plan.test.d.ts +2 -0
  254. package/dist/tools/generate-execution-plan.test.d.ts.map +1 -0
  255. package/dist/tools/generate-execution-plan.test.js +643 -0
  256. package/dist/tools/generate-execution-plan.test.js.map +1 -0
  257. package/dist/tools/generate-rules.test.d.ts +2 -0
  258. package/dist/tools/generate-rules.test.d.ts.map +1 -0
  259. package/dist/tools/generate-rules.test.js +148 -0
  260. package/dist/tools/generate-rules.test.js.map +1 -0
  261. package/dist/tools/generate-skill.test.d.ts +2 -0
  262. package/dist/tools/generate-skill.test.d.ts.map +1 -0
  263. package/dist/tools/generate-skill.test.js +138 -0
  264. package/dist/tools/generate-skill.test.js.map +1 -0
  265. package/dist/tools/generate-sub-agent.test.d.ts +2 -0
  266. package/dist/tools/generate-sub-agent.test.d.ts.map +1 -0
  267. package/dist/tools/generate-sub-agent.test.js +162 -0
  268. package/dist/tools/generate-sub-agent.test.js.map +1 -0
  269. package/dist/tools/generate-tests.test.d.ts +2 -0
  270. package/dist/tools/generate-tests.test.d.ts.map +1 -0
  271. package/dist/tools/generate-tests.test.js +222 -0
  272. package/dist/tools/generate-tests.test.js.map +1 -0
  273. package/dist/tools/init-constitution.test.d.ts +2 -0
  274. package/dist/tools/init-constitution.test.d.ts.map +1 -0
  275. package/dist/tools/init-constitution.test.js +398 -0
  276. package/dist/tools/init-constitution.test.js.map +1 -0
  277. package/dist/tools/init-project/config-builder.d.ts +12 -0
  278. package/dist/tools/init-project/config-builder.d.ts.map +1 -0
  279. package/dist/tools/init-project/config-builder.js +31 -0
  280. package/dist/tools/init-project/config-builder.js.map +1 -0
  281. package/dist/tools/init-project/git-setup.d.ts +8 -0
  282. package/dist/tools/init-project/git-setup.d.ts.map +1 -0
  283. package/dist/tools/init-project/git-setup.js +70 -0
  284. package/dist/tools/init-project/git-setup.js.map +1 -0
  285. package/dist/tools/init-project/handler.d.ts.map +1 -1
  286. package/dist/tools/init-project/handler.js +25 -371
  287. package/dist/tools/init-project/handler.js.map +1 -1
  288. package/dist/tools/init-project/lifecycle-helpers.d.ts +32 -0
  289. package/dist/tools/init-project/lifecycle-helpers.d.ts.map +1 -0
  290. package/dist/tools/init-project/lifecycle-helpers.js +153 -0
  291. package/dist/tools/init-project/lifecycle-helpers.js.map +1 -0
  292. package/dist/tools/init-project/migration-runner.d.ts +28 -0
  293. package/dist/tools/init-project/migration-runner.d.ts.map +1 -0
  294. package/dist/tools/init-project/migration-runner.js +57 -0
  295. package/dist/tools/init-project/migration-runner.js.map +1 -0
  296. package/dist/tools/init-project/rules-writer.d.ts +14 -0
  297. package/dist/tools/init-project/rules-writer.d.ts.map +1 -0
  298. package/dist/tools/init-project/rules-writer.js +43 -0
  299. package/dist/tools/init-project/rules-writer.js.map +1 -0
  300. package/dist/tools/init-project/scaffold-writer.d.ts +29 -0
  301. package/dist/tools/init-project/scaffold-writer.d.ts.map +1 -0
  302. package/dist/tools/init-project/scaffold-writer.js +76 -0
  303. package/dist/tools/init-project/scaffold-writer.js.map +1 -0
  304. package/dist/tools/init-project/stack-detector.d.ts +16 -0
  305. package/dist/tools/init-project/stack-detector.d.ts.map +1 -0
  306. package/dist/tools/init-project/stack-detector.js +19 -0
  307. package/dist/tools/init-project/stack-detector.js.map +1 -0
  308. package/dist/tools/init-project.test.d.ts +2 -0
  309. package/dist/tools/init-project.test.d.ts.map +1 -0
  310. package/dist/tools/init-project.test.js +158 -0
  311. package/dist/tools/init-project.test.js.map +1 -0
  312. package/dist/tools/integrate-pm.test.d.ts +2 -0
  313. package/dist/tools/integrate-pm.test.d.ts.map +1 -0
  314. package/dist/tools/integrate-pm.test.js +558 -0
  315. package/dist/tools/integrate-pm.test.js.map +1 -0
  316. package/dist/tools/learn.test.d.ts +2 -0
  317. package/dist/tools/learn.test.d.ts.map +1 -0
  318. package/dist/tools/learn.test.js +123 -0
  319. package/dist/tools/learn.test.js.map +1 -0
  320. package/dist/tools/list-specs.js +1 -1
  321. package/dist/tools/list-specs.js.map +1 -1
  322. package/dist/tools/list-specs.test.d.ts +2 -0
  323. package/dist/tools/list-specs.test.d.ts.map +1 -0
  324. package/dist/tools/list-specs.test.js +110 -0
  325. package/dist/tools/list-specs.test.js.map +1 -0
  326. package/dist/tools/manage-context.test.d.ts +2 -0
  327. package/dist/tools/manage-context.test.d.ts.map +1 -0
  328. package/dist/tools/manage-context.test.js +359 -0
  329. package/dist/tools/manage-context.test.js.map +1 -0
  330. package/dist/tools/manage-git.test.d.ts +2 -0
  331. package/dist/tools/manage-git.test.d.ts.map +1 -0
  332. package/dist/tools/manage-git.test.js +882 -0
  333. package/dist/tools/manage-git.test.js.map +1 -0
  334. package/dist/tools/orchestrate.test.d.ts +2 -0
  335. package/dist/tools/orchestrate.test.d.ts.map +1 -0
  336. package/dist/tools/orchestrate.test.js +1117 -0
  337. package/dist/tools/orchestrate.test.js.map +1 -0
  338. package/dist/tools/reconcile-spec.test.d.ts +2 -0
  339. package/dist/tools/reconcile-spec.test.d.ts.map +1 -0
  340. package/dist/tools/reconcile-spec.test.js +259 -0
  341. package/dist/tools/reconcile-spec.test.js.map +1 -0
  342. package/dist/tools/red-team.d.ts +3 -0
  343. package/dist/tools/red-team.d.ts.map +1 -0
  344. package/dist/tools/red-team.js +302 -0
  345. package/dist/tools/red-team.js.map +1 -0
  346. package/dist/tools/register-platform-tools/design-stack-tools.d.ts.map +1 -1
  347. package/dist/tools/register-platform-tools/design-stack-tools.js +14 -0
  348. package/dist/tools/register-platform-tools/design-stack-tools.js.map +1 -1
  349. package/dist/tools/register-platform-tools.test.d.ts +2 -0
  350. package/dist/tools/register-platform-tools.test.d.ts.map +1 -0
  351. package/dist/tools/register-platform-tools.test.js +404 -0
  352. package/dist/tools/register-platform-tools.test.js.map +1 -0
  353. package/dist/tools/register-spec-tools.test.d.ts +2 -0
  354. package/dist/tools/register-spec-tools.test.d.ts.map +1 -0
  355. package/dist/tools/register-spec-tools.test.js +407 -0
  356. package/dist/tools/register-spec-tools.test.js.map +1 -0
  357. package/dist/tools/reverse-engineer.test.d.ts +2 -0
  358. package/dist/tools/reverse-engineer.test.d.ts.map +1 -0
  359. package/dist/tools/reverse-engineer.test.js +206 -0
  360. package/dist/tools/reverse-engineer.test.js.map +1 -0
  361. package/dist/tools/schemas.d.ts +20 -0
  362. package/dist/tools/schemas.d.ts.map +1 -0
  363. package/dist/tools/schemas.js +133 -0
  364. package/dist/tools/schemas.js.map +1 -0
  365. package/dist/tools/schemas.test.d.ts +2 -0
  366. package/dist/tools/schemas.test.d.ts.map +1 -0
  367. package/dist/tools/schemas.test.js +245 -0
  368. package/dist/tools/schemas.test.js.map +1 -0
  369. package/dist/tools/set-locale.test.d.ts +2 -0
  370. package/dist/tools/set-locale.test.d.ts.map +1 -0
  371. package/dist/tools/set-locale.test.js +74 -0
  372. package/dist/tools/set-locale.test.js.map +1 -0
  373. package/dist/tools/suggest-mcps.test.d.ts +2 -0
  374. package/dist/tools/suggest-mcps.test.d.ts.map +1 -0
  375. package/dist/tools/suggest-mcps.test.js +198 -0
  376. package/dist/tools/suggest-mcps.test.js.map +1 -0
  377. package/dist/tools/suggest-stack.test.d.ts +2 -0
  378. package/dist/tools/suggest-stack.test.d.ts.map +1 -0
  379. package/dist/tools/suggest-stack.test.js +181 -0
  380. package/dist/tools/suggest-stack.test.js.map +1 -0
  381. package/dist/tools/suggest-tooling.test.d.ts +2 -0
  382. package/dist/tools/suggest-tooling.test.d.ts.map +1 -0
  383. package/dist/tools/suggest-tooling.test.js +213 -0
  384. package/dist/tools/suggest-tooling.test.js.map +1 -0
  385. package/dist/tools/summarize-spec.test.d.ts +2 -0
  386. package/dist/tools/summarize-spec.test.d.ts.map +1 -0
  387. package/dist/tools/summarize-spec.test.js +180 -0
  388. package/dist/tools/summarize-spec.test.js.map +1 -0
  389. package/dist/tools/update-status/dod-gates.d.ts +16 -0
  390. package/dist/tools/update-status/dod-gates.d.ts.map +1 -0
  391. package/dist/tools/update-status/dod-gates.js +117 -0
  392. package/dist/tools/update-status/dod-gates.js.map +1 -0
  393. package/dist/tools/update-status/file-sync.d.ts +6 -0
  394. package/dist/tools/update-status/file-sync.d.ts.map +1 -0
  395. package/dist/tools/update-status/file-sync.js +112 -0
  396. package/dist/tools/update-status/file-sync.js.map +1 -0
  397. package/dist/tools/update-status/index.d.ts +3 -0
  398. package/dist/tools/update-status/index.d.ts.map +1 -0
  399. package/dist/tools/update-status/index.js +181 -0
  400. package/dist/tools/update-status/index.js.map +1 -0
  401. package/dist/tools/update-status/response-builder.d.ts +4 -0
  402. package/dist/tools/update-status/response-builder.d.ts.map +1 -0
  403. package/dist/tools/update-status/response-builder.js +69 -0
  404. package/dist/tools/update-status/response-builder.js.map +1 -0
  405. package/dist/tools/update-status/side-effects.d.ts +15 -0
  406. package/dist/tools/update-status/side-effects.d.ts.map +1 -0
  407. package/dist/tools/update-status/side-effects.js +64 -0
  408. package/dist/tools/update-status/side-effects.js.map +1 -0
  409. package/dist/tools/update-status/transition-guard.d.ts +20 -0
  410. package/dist/tools/update-status/transition-guard.d.ts.map +1 -0
  411. package/dist/tools/update-status/transition-guard.js +75 -0
  412. package/dist/tools/update-status/transition-guard.js.map +1 -0
  413. package/dist/tools/update-status.d.ts +1 -2
  414. package/dist/tools/update-status.d.ts.map +1 -1
  415. package/dist/tools/update-status.js +2 -481
  416. package/dist/tools/update-status.js.map +1 -1
  417. package/dist/tools/update-status.test.d.ts +2 -0
  418. package/dist/tools/update-status.test.d.ts.map +1 -0
  419. package/dist/tools/update-status.test.js +142 -0
  420. package/dist/tools/update-status.test.js.map +1 -0
  421. package/dist/tools/validate.d.ts.map +1 -1
  422. package/dist/tools/validate.js +6 -4
  423. package/dist/tools/validate.js.map +1 -1
  424. package/dist/tools/validate.test.d.ts +2 -0
  425. package/dist/tools/validate.test.d.ts.map +1 -0
  426. package/dist/tools/validate.test.js +137 -0
  427. package/dist/tools/validate.test.js.map +1 -0
  428. package/dist/types/analysis.d.ts +2 -1
  429. package/dist/types/analysis.d.ts.map +1 -1
  430. package/dist/types/index.d.ts +2 -0
  431. package/dist/types/index.d.ts.map +1 -1
  432. package/dist/types/index.js +2 -0
  433. package/dist/types/index.js.map +1 -1
  434. package/dist/types/red-team.d.ts +29 -0
  435. package/dist/types/red-team.d.ts.map +1 -0
  436. package/dist/types/red-team.js +3 -0
  437. package/dist/types/red-team.js.map +1 -0
  438. package/dist/types/update-notifier.d.ts +5 -0
  439. package/dist/types/update-notifier.d.ts.map +1 -0
  440. package/dist/types/update-notifier.js +3 -0
  441. package/dist/types/update-notifier.js.map +1 -0
  442. package/package.json +9 -2
  443. package/src/config/license-plans.json +2 -1
  444. package/src/i18n/messages/en.json +5 -0
  445. package/src/i18n/messages/es.json +5 -0
  446. package/src/i18n/messages/pt.json +5 -0
@@ -1,482 +1,3 @@
1
- import { t, ti } from '../i18n/index.js';
2
- import { formatSuccess, addNextSteps } from './response-helpers.js';
3
- import { specStore, metricsStore, knowledgeStore } from '../storage/index.js';
4
- import { calculateAccuracy } from '../engine/estimator.js';
5
- import { validateDoR } from '../engine/dor-dod.js';
6
- import { validateSpec } from '../engine/validator.js';
7
- import { generateDoD } from '../engine/validator/dor-dod.js';
8
- import { cascadeCheck } from '../engine/spec-versioner.js';
9
- import { dispatchFeedbackEvent } from './learn.js';
10
- import { generateProgressUpdate, generateProgressContent } from '../engine/progress-writer.js';
11
- import { runImplementingActions, runDoneActions } from './update-status-actions.js';
12
- import { compactObj } from '../engine/compact-obj.js';
13
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
14
- import { dirname } from 'node:path';
15
- import { appendChangelogEntry } from '../engine/spec-changelog/index.js';
16
- import { dispatchHookEvent } from './manage-hooks.js';
17
- import { runComplianceGates } from './update-status-convention-gate.js';
18
- import { buildStatusChangePayload } from '../engine/hooks/triggers.js';
19
- import { regenerateSpecSummaryHtml } from '../engine/spec-summary-html.js';
20
- import { notifyStoreChange } from '../engine/doc-generator/portal/regen-hook.js';
21
- import { autoReconcileOnDone } from './update-status-reconcile.js';
22
- // ---------------------------------------------------------------------------
23
- // Metric helpers (extracted to reduce cyclomatic complexity of handleUpdateStatus)
24
- // ---------------------------------------------------------------------------
25
- async function recordDoneMetrics(projectId, specId, spec, actuals) {
26
- const accuracyScore = calculateAccuracy(spec.estimation, actuals.devHours + actuals.reviewHours);
27
- const metricEntry = {
28
- specId,
29
- difficulty: spec.difficulty,
30
- estimated: spec.estimation,
31
- actual: actuals,
32
- accuracyScore,
33
- };
34
- await metricsStore.addMetricEntry(projectId, metricEntry);
35
- if (accuracyScore < 0.7 || accuracyScore > 1.3) {
36
- try {
37
- void dispatchFeedbackEvent(projectId, {
38
- type: 'validate',
39
- specId,
40
- input: { specType: spec.type, scope: spec.scope, difficulty: spec.difficulty },
41
- outcome: {
42
- estimationAccuracy: accuracyScore,
43
- estimatedHours: spec.estimation.devHours + spec.estimation.reviewHours,
44
- actualHours: actuals.devHours + actuals.reviewHours,
45
- },
46
- delta: { accuracyDrift: Math.abs(1 - accuracyScore) },
47
- timestamp: new Date().toISOString(),
48
- });
49
- }
50
- catch {
51
- /* best-effort */
52
- }
53
- }
54
- }
55
- async function syncSpecFiles(updatedSpec, currentStatus, newStatus) {
56
- if (updatedSpec.specPath) {
57
- try {
58
- const specContent = await readFile(updatedSpec.specPath, 'utf-8');
59
- const { updateFrontmatterField } = await import('../engine/frontmatter-parser.js');
60
- const updatedContent = updateFrontmatterField(specContent, 'status', newStatus);
61
- await writeFile(updatedSpec.specPath, updatedContent, 'utf-8');
62
- }
63
- catch (err) {
64
- const msg = err instanceof Error ? err.message : String(err);
65
- console.warn(`[Planu] update_status: failed to sync spec.md for ${updatedSpec.id} at ${updatedSpec.specPath}: ${msg}`);
66
- }
67
- }
68
- else {
69
- console.warn(`[Planu] update_status: specPath not set for ${updatedSpec.id} — spec.md not updated on disk. ` +
70
- 'Run reconcile_spec to re-link this spec to its file.');
71
- }
72
- if (updatedSpec.progressPath) {
73
- try {
74
- const existing = await readFile(updatedSpec.progressPath, 'utf-8');
75
- const updatedProgress = generateProgressUpdate(updatedSpec, currentStatus, existing);
76
- await writeFile(updatedSpec.progressPath, updatedProgress, 'utf-8');
77
- }
78
- catch {
79
- try {
80
- const progressContent = generateProgressContent(updatedSpec);
81
- await mkdir(dirname(updatedSpec.progressPath), { recursive: true });
82
- await writeFile(updatedSpec.progressPath, progressContent, 'utf-8');
83
- }
84
- catch (err) {
85
- const msg = err instanceof Error ? err.message : String(err);
86
- console.warn(`[Planu] update_status: failed to write progress.md for ${updatedSpec.id}: ${msg}`);
87
- }
88
- }
89
- }
90
- }
91
- /**
92
- * Valid state transitions for spec lifecycle.
93
- * draft -> review -> approved -> implementing -> done
94
- * Also allow: review -> draft (send back), approved -> review (reconsider)
95
- */
96
- const VALID_TRANSITIONS = {
97
- draft: ['review', 'discarded'],
98
- review: ['draft', 'approved', 'discarded'],
99
- approved: ['review', 'implementing', 'discarded'],
100
- implementing: ['approved', 'done', 'discarded'],
101
- done: [], // terminal state
102
- discarded: [], // terminal state
103
- };
104
- // ---------------------------------------------------------------------------
105
- // Response formatting (extracted to reduce cyclomatic complexity)
106
- // ---------------------------------------------------------------------------
107
- const STATUS_EMOJIS = {
108
- draft: '📝',
109
- review: '🔍',
110
- approved: '✅',
111
- implementing: '⚙️',
112
- done: '🎉',
113
- discarded: '🗑️',
114
- };
115
- function buildStatusResponse(result, specId, currentStatus, newStatus, reconciliationMarkdown) {
116
- const fromEmoji = STATUS_EMOJIS[currentStatus];
117
- const toEmoji = STATUS_EMOJIS[newStatus];
118
- const r = result;
119
- const lines = [
120
- `**SPEC-${specId}** moved: ${fromEmoji} \`${currentStatus}\` → ${toEmoji} \`${newStatus}\``,
121
- ];
122
- if (r.autoBranch) {
123
- lines.push(`\n🌿 Branch created: \`${r.autoBranch}\``);
124
- }
125
- if (r.protectedBranchWarning) {
126
- lines.push(`\n⚠️ ${r.protectedBranchWarning}`);
127
- }
128
- if (r.mergeWarning) {
129
- lines.push(`\n⚠️ ${r.mergeWarning}`);
130
- }
131
- if (r.validationWarning) {
132
- lines.push(`\n⚠️ ${r.validationWarning}`);
133
- }
134
- if (r.prSuggestion) {
135
- lines.push(`\n🔗 ${r.prSuggestion.title}`);
136
- }
137
- if (r.metrics) {
138
- lines.push(`\n📊 Accuracy: ${Math.round(r.metrics.accuracyScore * 100)}% | ` +
139
- `Estimated: ${String(r.metrics.estimatedHours)}h → Actual: ${String(r.metrics.actualHours)}h`);
140
- }
141
- if (r.validateScore !== null && r.validateScore !== undefined) {
142
- lines.push(`\n✅ Validate score: ${String(r.validateScore)}/100`);
143
- }
144
- if (r.cascade.affectedSpecs.length > 0) {
145
- lines.push(`\n🔗 Downstream specs affected: ${r.cascade.affectedSpecs.map((s) => `SPEC-${s}`).join(', ')}`);
146
- }
147
- if (r.constitutionWarnings && r.constitutionWarnings.length > 0) {
148
- lines.push(`\n⚠️ **Constitution Warnings**\n${r.constitutionWarnings.map((w) => `- ${w.description}`).join('\n')}`);
149
- }
150
- if (r.conventionWarnings && r.conventionWarnings.length > 0) {
151
- lines.push(`\n⚠️ **Convention Violations**\n${r.conventionWarnings.map((w) => `- ${w}`).join('\n')}`);
152
- }
153
- if (r.compileWarnings && r.compileWarnings.length > 0) {
154
- lines.push(`\n⚠️ **Compile Warnings**\n${r.compileWarnings.map((w) => `- ${w}`).join('\n')}`);
155
- }
156
- if (r.lintWarnings && r.lintWarnings.length > 0) {
157
- lines.push(`\n⚠️ **Lint Warnings**\n${r.lintWarnings.map((w) => `- ${w}`).join('\n')}`);
158
- }
159
- if (r.testWarnings && r.testWarnings.length > 0) {
160
- lines.push(`\n⚠️ **Test Warnings**\n${r.testWarnings.map((w) => `- ${w}`).join('\n')}`);
161
- }
162
- const allNextSteps = [...(r.implementingSuggestions ?? [])];
163
- const baseText = formatSuccess(t('tools.response.statusTitle'), lines.join(''));
164
- const withNextSteps = allNextSteps.length > 0 ? addNextSteps(baseText, allNextSteps) : baseText;
165
- const markdownText = reconciliationMarkdown
166
- ? `${withNextSteps}\n\n${reconciliationMarkdown}`
167
- : withNextSteps;
168
- return {
169
- content: [{ type: 'text', text: markdownText }],
170
- structuredContent: result,
171
- };
172
- }
173
- // ---------------------------------------------------------------------------
174
- // Helpers
175
- // ---------------------------------------------------------------------------
176
- async function tryReconcile(newStatus, specId, projectId) {
177
- if (newStatus !== 'done') {
178
- return null;
179
- }
180
- return autoReconcileOnDone(specId, projectId).catch(() => null);
181
- }
182
- /** Fire-and-forget side effects after a successful status transition. */
183
- function fireAndForgetSideEffects(params) {
184
- const { knowledge, allSpecs, specId, newStatus, validateScore, projectId, spec, currentStatus } = params;
185
- // Auto-regenerate planu/index.html (fire-and-forget, never blocks result)
186
- if (knowledge?.projectPath) {
187
- void regenerateSpecSummaryHtml(knowledge.projectPath, allSpecs, [specId]);
188
- const changedStores = ['specs'];
189
- if (newStatus === 'done') {
190
- changedStores.push('metrics');
191
- }
192
- notifyStoreChange(knowledge.projectPath, ...changedStores);
193
- }
194
- // SPEC-222 Trigger 3: Auto-stage planu/ when done and validate OK (fire-and-forget)
195
- if (newStatus === 'done' && validateScore !== null && knowledge?.projectPath) {
196
- void import('node:child_process').then(({ execSync }) => {
197
- try {
198
- execSync('git add planu/', { cwd: knowledge.projectPath, stdio: 'pipe' });
199
- }
200
- catch {
201
- /* best-effort — non-blocking */
202
- }
203
- });
204
- }
205
- // Dispatch on_spec_status_change hook event (fire-and-forget)
206
- void dispatchHookEvent(projectId, buildStatusChangePayload(projectId, specId, spec.title, currentStatus, newStatus));
207
- }
208
- /** SPEC-222 Trigger 1: Run validate engine before marking done. Returns score or null on error/skip. */
209
- async function runValidateGate(spec, projectPath, forceStatus) {
210
- if (forceStatus) {
211
- return { blocked: false, score: null };
212
- }
213
- try {
214
- const validateResult = await validateSpec(spec, projectPath);
215
- if (validateResult.score < 70) {
216
- return { blocked: true, score: validateResult.score };
217
- }
218
- return { blocked: false, score: validateResult.score };
219
- }
220
- catch {
221
- /* best-effort — don't block transition if validate fails */
222
- return { blocked: false, score: null };
223
- }
224
- }
225
- // ---------------------------------------------------------------------------
226
- // Main handler
227
- // ---------------------------------------------------------------------------
228
- export async function handleUpdateStatus(params) {
229
- const { specId, projectId, status: newStatus, actuals, reviewNotes } = params;
230
- try {
231
- // Get the current spec
232
- const spec = await specStore.getSpec(projectId, specId);
233
- if (!spec) {
234
- return {
235
- content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
236
- isError: true,
237
- };
238
- }
239
- const currentStatus = spec.status;
240
- // Validate state transition
241
- const validNextStates = VALID_TRANSITIONS[currentStatus];
242
- if (!validNextStates.includes(newStatus)) {
243
- return {
244
- content: [
245
- {
246
- type: 'text',
247
- text: ti('spec.invalidTransition', {
248
- from: currentStatus,
249
- to: newStatus,
250
- }),
251
- },
252
- ],
253
- isError: true,
254
- };
255
- }
256
- // Gate: DoR must pass before transitioning to 'implementing'
257
- if (newStatus === 'implementing') {
258
- const dorResult = validateDoR(spec);
259
- if (!dorResult.isValid) {
260
- void dispatchFeedbackEvent(projectId, {
261
- type: 'checklist',
262
- specId,
263
- input: { gate: 'dor', specType: spec.type },
264
- outcome: { passed: false, failedItems: dorResult.blockingItems },
265
- delta: { failedCount: dorResult.blockingItems.length },
266
- timestamp: new Date().toISOString(),
267
- });
268
- return {
269
- content: [
270
- {
271
- type: 'text',
272
- text: JSON.stringify({
273
- error: 'DoR gate failed',
274
- message: dorResult.humanMessage,
275
- expertSummary: dorResult.expertSummary,
276
- blockingItems: dorResult.blockingItems,
277
- warningItems: dorResult.warningItems,
278
- }, null, 2),
279
- },
280
- ],
281
- isError: true,
282
- };
283
- }
284
- }
285
- // Load knowledge for project path (needed for DoD gates, validate trigger and HTML regen)
286
- const knowledge = await knowledgeStore.getKnowledge(projectId);
287
- // Gate: DoD must pass before transitioning to 'done' (unless force=true)
288
- if (newStatus === 'done' && !params.force) {
289
- const dod = await generateDoD(spec, undefined, undefined, knowledge?.projectPath);
290
- const requiredItems = dod.items.filter((i) => i.required);
291
- const blockingItems = requiredItems
292
- .filter((i) => i.status === 'failed')
293
- .map((i) => i.description);
294
- const warningItems = dod.items
295
- .filter((i) => !i.required && i.status !== 'passed')
296
- .map((i) => i.description);
297
- if (blockingItems.length > 0) {
298
- const humanMessage = `❌ DoD gate failed: ${blockingItems.slice(0, 3).join('; ')}${blockingItems.length > 3 ? ` (and ${blockingItems.length - 3} more)` : ''}`;
299
- const expertSummary = `DoD: ${dod.passedCount}/${dod.items.length} passed | Blocking: ${blockingItems.length} | Warnings: ${warningItems.length}`;
300
- const fixHints = blockingItems.map((item) => `💡 To fix: ${item}`);
301
- void dispatchFeedbackEvent(projectId, {
302
- type: 'checklist',
303
- specId,
304
- input: { gate: 'dod', specType: spec.type },
305
- outcome: { passed: false, failedItems: blockingItems },
306
- delta: { failedCount: blockingItems.length },
307
- timestamp: new Date().toISOString(),
308
- });
309
- const failedItems = requiredItems
310
- .filter((i) => i.status === 'failed')
311
- .map((i) => ({ id: i.id, description: i.description, category: i.category }));
312
- return {
313
- content: [
314
- {
315
- type: 'text',
316
- text: JSON.stringify({
317
- error: 'DoD gate failed',
318
- message: humanMessage,
319
- expertSummary,
320
- blockingItems,
321
- failedItems,
322
- warningItems,
323
- fixHints,
324
- gateResults: dod.gateResults ?? null,
325
- hint: '💡 Alternatively: use force:true to bypass all gates',
326
- }, null, 2),
327
- },
328
- ],
329
- isError: true,
330
- structuredContent: {
331
- error: 'dod_gate_failed',
332
- code: 422,
333
- context: {
334
- specId,
335
- blockingItems,
336
- warningItems,
337
- passed: dod.passedCount,
338
- total: dod.items.length,
339
- },
340
- fixHint: blockingItems[0]
341
- ? `Fix: ${blockingItems[0]}. Use force:true to bypass all gates.`
342
- : 'Use force:true to bypass all gates.',
343
- },
344
- };
345
- }
346
- }
347
- // SPEC-222 Trigger 1: Auto-validate before marking done
348
- let validateScore = null;
349
- if (newStatus === 'done') {
350
- const validateGate = await runValidateGate(spec, knowledge?.projectPath ?? '', params.forceStatus);
351
- if (validateGate.blocked) {
352
- return {
353
- isError: true,
354
- content: [
355
- {
356
- type: 'text',
357
- text: `Blocked: validate score ${String(validateGate.score)}/100 — below 70. Fix issues or use forceStatus:true.`,
358
- },
359
- ],
360
- };
361
- }
362
- validateScore = validateGate.score;
363
- }
364
- // SPEC-190: Run all compliance gates in parallel (convention + constitution + compile + lint + test, non-blocking)
365
- const { conventionWarnings, constitutionWarnings, compileWarnings, lintWarnings, testWarnings, } = await runComplianceGates(projectId, spec.title, spec.tags, newStatus);
366
- // If transitioning to 'done', actuals are required (validate before side effects)
367
- if (newStatus === 'done' && !actuals) {
368
- return {
369
- content: [{ type: 'text', text: ti('spec.actualsRequired', {}) }],
370
- isError: true,
371
- structuredContent: {
372
- error: 'actuals_required',
373
- code: 400,
374
- context: { specId, newStatus },
375
- fixHint: 'Provide the actuals field with implementation notes before marking as done.',
376
- },
377
- };
378
- }
379
- // Run transition-specific actions
380
- const implActions = newStatus === 'implementing' ? await runImplementingActions(projectId, specId) : null;
381
- const doneActions = newStatus === 'done' ? await runDoneActions(projectId, specId, spec.gitBranch) : null;
382
- // Build the update
383
- const updates = {
384
- status: newStatus,
385
- };
386
- // Store review notes when sending back (review→draft or approved→review)
387
- if (reviewNotes) {
388
- const existing = spec.reviewNotes ?? [];
389
- updates.reviewNotes = [
390
- ...existing,
391
- `[${new Date().toISOString()}] ${currentStatus}→${newStatus}: ${reviewNotes}`,
392
- ];
393
- }
394
- // If actuals are provided, save them
395
- if (actuals) {
396
- updates.actuals = actuals;
397
- }
398
- // Update the spec
399
- const updatedSpec = await specStore.updateSpec(projectId, specId, updates);
400
- // Sync spec.md frontmatter and progress.md (best-effort)
401
- await syncSpecFiles(updatedSpec, currentStatus, newStatus);
402
- // If spec is done and has actuals, record metrics
403
- if (newStatus === 'done' && actuals) {
404
- await recordDoneMetrics(projectId, specId, spec, actuals);
405
- }
406
- // Generate changelog entry for status change (AC-03, AC-08)
407
- let changelogUpdated = false;
408
- if (updatedSpec.specPath) {
409
- const specDir = dirname(updatedSpec.specPath);
410
- changelogUpdated = await appendChangelogEntry({
411
- specDir,
412
- specId,
413
- entry: {
414
- timestamp: new Date().toISOString(),
415
- type: 'status_changed',
416
- description: `Estado cambio de \`${currentStatus}\` a \`${newStatus}\`.`,
417
- triggeredBy: 'update_status',
418
- before: { criteriaCount: 0, completedCount: 0, status: currentStatus },
419
- after: { criteriaCount: 0, completedCount: 0, status: newStatus },
420
- },
421
- });
422
- }
423
- // Cascade check: notify downstream specs of the status change
424
- const allSpecs = await specStore.listSpecs(projectId);
425
- const cascadeResult = cascadeCheck(specId, allSpecs, newStatus);
426
- const result = compactObj({
427
- specId,
428
- projectId,
429
- previousStatus: currentStatus,
430
- newStatus,
431
- actuals: actuals ?? null,
432
- autoBranch: implActions?.autoBranch ?? null,
433
- protectedBranchWarning: implActions?.protectedBranchWarning ?? null,
434
- mergeWarning: doneActions?.mergeWarning ?? null,
435
- validationWarning: doneActions?.validationWarning ?? null,
436
- uncommittedWarning: doneActions?.uncommittedWarning ?? null,
437
- prSuggestion: doneActions?.prSuggestion ?? null,
438
- changelogUpdated,
439
- implementingSuggestions: implActions?.suggestions ?? null,
440
- validateScore,
441
- constitutionWarnings: constitutionWarnings.length > 0 ? constitutionWarnings : null,
442
- conventionWarnings: conventionWarnings.length > 0 ? conventionWarnings : null,
443
- compileWarnings: compileWarnings.length > 0 ? compileWarnings : null,
444
- lintWarnings: lintWarnings.length > 0 ? lintWarnings : null,
445
- testWarnings: testWarnings.length > 0 ? testWarnings : null,
446
- cascade: cascadeResult,
447
- metrics: newStatus === 'done' && actuals
448
- ? {
449
- accuracyScore: calculateAccuracy(spec.estimation, actuals.devHours + actuals.reviewHours),
450
- estimatedHours: spec.estimation.devHours + spec.estimation.reviewHours,
451
- actualHours: actuals.devHours + actuals.reviewHours,
452
- estimatedCost: spec.estimation.totalCostUsd,
453
- actualCost: actuals.totalCostUsd,
454
- }
455
- : null,
456
- updatedAt: updatedSpec.updatedAt,
457
- message: ti('tools.update_status.success', { specId, status: newStatus }),
458
- });
459
- // Fire-and-forget side effects (non-blocking)
460
- fireAndForgetSideEffects({
461
- knowledge,
462
- allSpecs,
463
- specId,
464
- newStatus,
465
- validateScore,
466
- projectId,
467
- spec,
468
- currentStatus,
469
- });
470
- // Auto-reconcile token costs when spec reaches done (best-effort, non-blocking)
471
- const reconciliationMarkdown = await tryReconcile(newStatus, specId, projectId);
472
- return buildStatusResponse(result, specId, currentStatus, newStatus, reconciliationMarkdown);
473
- }
474
- catch (error) {
475
- const message = error instanceof Error ? error.message : String(error);
476
- return {
477
- content: [{ type: 'text', text: ti('errors.internalError', { message }) }],
478
- isError: true,
479
- };
480
- }
481
- }
1
+ // tools/update-status.ts Re-export barrel (implementation split into update-status/)
2
+ export { handleUpdateStatus } from './update-status/index.js';
482
3
  //# sourceMappingURL=update-status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-status.js","sourceRoot":"","sources":["../../src/tools/update-status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-status.js","sourceRoot":"","sources":["../../src/tools/update-status.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=update-status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-status.test.d.ts","sourceRoot":"","sources":["../../src/tools/update-status.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,142 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ vi.mock('../i18n/index.js', () => ({
3
+ ti: vi.fn((_key, params) => `translated:${JSON.stringify(params)}`),
4
+ }));
5
+ vi.mock('../storage/index.js', () => ({
6
+ specStore: {
7
+ getSpec: vi.fn(),
8
+ updateSpec: vi.fn(),
9
+ },
10
+ metricsStore: {
11
+ addMetricEntry: vi.fn(),
12
+ },
13
+ }));
14
+ vi.mock('../engine/estimator.js', () => ({
15
+ calculateAccuracy: vi.fn(),
16
+ }));
17
+ import { handleUpdateStatus } from './update-status.js';
18
+ import { specStore, metricsStore } from '../storage/index.js';
19
+ import { calculateAccuracy } from '../engine/estimator.js';
20
+ const makeSpec = (overrides = {}) => ({
21
+ id: 'SPEC-001',
22
+ title: 'Test Spec',
23
+ status: 'draft',
24
+ difficulty: 3,
25
+ estimation: {
26
+ devHours: 8,
27
+ reviewHours: 2,
28
+ totalCostUsd: 500,
29
+ recommendedModel: 'sonnet',
30
+ tokenOptimization: { mode: 'local' },
31
+ },
32
+ actuals: null,
33
+ ...overrides,
34
+ });
35
+ const makeActuals = () => ({
36
+ devHours: 10,
37
+ reviewHours: 3,
38
+ tokensOpus: 5000,
39
+ tokensSonnet: 10000,
40
+ apiCostUsd: 2.0,
41
+ humanCostUsd: 650,
42
+ totalCostUsd: 652,
43
+ completedAt: '2024-01-15',
44
+ notes: 'Done',
45
+ });
46
+ beforeEach(() => {
47
+ vi.clearAllMocks();
48
+ });
49
+ describe('handleUpdateStatus', () => {
50
+ it('should return error when spec not found', async () => {
51
+ vi.mocked(specStore.getSpec).mockResolvedValue(null);
52
+ const result = await handleUpdateStatus({
53
+ specId: 'SPEC-999',
54
+ projectId: 'proj-123',
55
+ status: 'review',
56
+ });
57
+ expect(result.isError).toBe(true);
58
+ });
59
+ it('should transition draft to review', async () => {
60
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'draft' }));
61
+ vi.mocked(specStore.updateSpec).mockResolvedValue({ ...makeSpec({ status: 'review' }), updatedAt: '2024-01-10' });
62
+ const result = await handleUpdateStatus({
63
+ specId: 'SPEC-001',
64
+ projectId: 'proj-123',
65
+ status: 'review',
66
+ });
67
+ expect(result.isError).toBeUndefined();
68
+ const parsed = JSON.parse(result.content[0].text);
69
+ expect(parsed.previousStatus).toBe('draft');
70
+ expect(parsed.newStatus).toBe('review');
71
+ });
72
+ it('should reject invalid transition draft to done', async () => {
73
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'draft' }));
74
+ const result = await handleUpdateStatus({
75
+ specId: 'SPEC-001',
76
+ projectId: 'proj-123',
77
+ status: 'done',
78
+ });
79
+ expect(result.isError).toBe(true);
80
+ });
81
+ it('should reject transition from done', async () => {
82
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'done' }));
83
+ const result = await handleUpdateStatus({
84
+ specId: 'SPEC-001',
85
+ projectId: 'proj-123',
86
+ status: 'draft',
87
+ });
88
+ expect(result.isError).toBe(true);
89
+ });
90
+ it('should require actuals when transitioning to done', async () => {
91
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'implementing' }));
92
+ const result = await handleUpdateStatus({
93
+ specId: 'SPEC-001',
94
+ projectId: 'proj-123',
95
+ status: 'done',
96
+ });
97
+ expect(result.isError).toBe(true);
98
+ });
99
+ it('should transition to done with actuals and record metrics', async () => {
100
+ const actuals = makeActuals();
101
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'implementing' }));
102
+ vi.mocked(specStore.updateSpec).mockResolvedValue({
103
+ ...makeSpec({ status: 'done', actuals }),
104
+ updatedAt: '2024-01-15',
105
+ });
106
+ vi.mocked(calculateAccuracy).mockReturnValue(0.85);
107
+ vi.mocked(metricsStore.addMetricEntry).mockResolvedValue(undefined);
108
+ const result = await handleUpdateStatus({
109
+ specId: 'SPEC-001',
110
+ projectId: 'proj-123',
111
+ status: 'done',
112
+ actuals: actuals,
113
+ });
114
+ expect(result.isError).toBeUndefined();
115
+ const parsed = JSON.parse(result.content[0].text);
116
+ expect(parsed.newStatus).toBe('done');
117
+ expect(parsed.actuals).toBeDefined();
118
+ expect(parsed.metrics).toBeDefined();
119
+ expect(parsed.metrics.accuracyScore).toBe(0.85);
120
+ expect(metricsStore.addMetricEntry).toHaveBeenCalled();
121
+ });
122
+ it('should allow review to draft (send back)', async () => {
123
+ vi.mocked(specStore.getSpec).mockResolvedValue(makeSpec({ status: 'review' }));
124
+ vi.mocked(specStore.updateSpec).mockResolvedValue({ ...makeSpec({ status: 'draft' }), updatedAt: '2024-01-10' });
125
+ const result = await handleUpdateStatus({
126
+ specId: 'SPEC-001',
127
+ projectId: 'proj-123',
128
+ status: 'draft',
129
+ });
130
+ expect(result.isError).toBeUndefined();
131
+ });
132
+ it('should handle errors gracefully', async () => {
133
+ vi.mocked(specStore.getSpec).mockRejectedValue(new Error('DB error'));
134
+ const result = await handleUpdateStatus({
135
+ specId: 'SPEC-001',
136
+ projectId: 'proj-123',
137
+ status: 'review',
138
+ });
139
+ expect(result.isError).toBe(true);
140
+ });
141
+ });
142
+ //# sourceMappingURL=update-status.test.js.map