@planu/cli 0.28.0 → 0.30.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 (297) hide show
  1. package/dist/config/model-routing-rules.json +98 -0
  2. package/dist/engine/ai-cost-estimator/core.d.ts.map +1 -1
  3. package/dist/engine/ai-cost-estimator/core.js +2 -202
  4. package/dist/engine/ai-cost-estimator/core.js.map +1 -1
  5. package/dist/engine/ai-cost-estimator/recommender.d.ts +8 -0
  6. package/dist/engine/ai-cost-estimator/recommender.d.ts.map +1 -0
  7. package/dist/engine/ai-cost-estimator/recommender.js +94 -0
  8. package/dist/engine/ai-cost-estimator/recommender.js.map +1 -0
  9. package/dist/engine/ai-cost-estimator/spec-loader.d.ts +13 -0
  10. package/dist/engine/ai-cost-estimator/spec-loader.d.ts.map +1 -0
  11. package/dist/engine/ai-cost-estimator/spec-loader.js +102 -0
  12. package/dist/engine/ai-cost-estimator/spec-loader.js.map +1 -0
  13. package/dist/engine/ci-generator/planu-config.d.ts +7 -0
  14. package/dist/engine/ci-generator/planu-config.d.ts.map +1 -0
  15. package/dist/engine/ci-generator/planu-config.js +40 -0
  16. package/dist/engine/ci-generator/planu-config.js.map +1 -0
  17. package/dist/engine/ci-generator/planu-steps.d.ts +11 -0
  18. package/dist/engine/ci-generator/planu-steps.d.ts.map +1 -0
  19. package/dist/engine/ci-generator/planu-steps.js +292 -0
  20. package/dist/engine/ci-generator/planu-steps.js.map +1 -0
  21. package/dist/engine/code-transforms/transform-engine.d.ts +7 -0
  22. package/dist/engine/code-transforms/transform-engine.d.ts.map +1 -0
  23. package/dist/engine/code-transforms/transform-engine.js +67 -0
  24. package/dist/engine/code-transforms/transform-engine.js.map +1 -0
  25. package/dist/engine/code-transforms/typescript/add-error-handling.d.ts +6 -0
  26. package/dist/engine/code-transforms/typescript/add-error-handling.d.ts.map +1 -0
  27. package/dist/engine/code-transforms/typescript/add-error-handling.js +92 -0
  28. package/dist/engine/code-transforms/typescript/add-error-handling.js.map +1 -0
  29. package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts +6 -0
  30. package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts.map +1 -0
  31. package/dist/engine/code-transforms/typescript/add-jsdoc.js +83 -0
  32. package/dist/engine/code-transforms/typescript/add-jsdoc.js.map +1 -0
  33. package/dist/engine/code-transforms/typescript/add-types.d.ts +3 -0
  34. package/dist/engine/code-transforms/typescript/add-types.d.ts.map +1 -0
  35. package/dist/engine/code-transforms/typescript/add-types.js +182 -0
  36. package/dist/engine/code-transforms/typescript/add-types.js.map +1 -0
  37. package/dist/engine/code-transforms/typescript/ast-utils.d.ts +38 -0
  38. package/dist/engine/code-transforms/typescript/ast-utils.d.ts.map +1 -0
  39. package/dist/engine/code-transforms/typescript/ast-utils.js +90 -0
  40. package/dist/engine/code-transforms/typescript/ast-utils.js.map +1 -0
  41. package/dist/engine/code-transforms/typescript/extract-interface.d.ts +6 -0
  42. package/dist/engine/code-transforms/typescript/extract-interface.d.ts.map +1 -0
  43. package/dist/engine/code-transforms/typescript/extract-interface.js +103 -0
  44. package/dist/engine/code-transforms/typescript/extract-interface.js.map +1 -0
  45. package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts +3 -0
  46. package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts.map +1 -0
  47. package/dist/engine/code-transforms/typescript/modernize-syntax.js +213 -0
  48. package/dist/engine/code-transforms/typescript/modernize-syntax.js.map +1 -0
  49. package/dist/engine/code-transforms/typescript/rename-symbol.d.ts +8 -0
  50. package/dist/engine/code-transforms/typescript/rename-symbol.d.ts.map +1 -0
  51. package/dist/engine/code-transforms/typescript/rename-symbol.js +40 -0
  52. package/dist/engine/code-transforms/typescript/rename-symbol.js.map +1 -0
  53. package/dist/engine/mermaid/core.d.ts +18 -0
  54. package/dist/engine/mermaid/core.d.ts.map +1 -0
  55. package/dist/engine/mermaid/core.js +88 -0
  56. package/dist/engine/mermaid/core.js.map +1 -0
  57. package/dist/engine/mermaid/diagram-generators.d.ts +22 -0
  58. package/dist/engine/mermaid/diagram-generators.d.ts.map +1 -0
  59. package/dist/engine/mermaid/diagram-generators.js +139 -0
  60. package/dist/engine/mermaid/diagram-generators.js.map +1 -0
  61. package/dist/engine/mermaid/helpers.d.ts +8 -0
  62. package/dist/engine/mermaid/helpers.d.ts.map +1 -0
  63. package/dist/engine/mermaid/helpers.js +61 -0
  64. package/dist/engine/mermaid/helpers.js.map +1 -0
  65. package/dist/engine/mermaid-generator.d.ts +2 -37
  66. package/dist/engine/mermaid-generator.d.ts.map +1 -1
  67. package/dist/engine/mermaid-generator.js +4 -276
  68. package/dist/engine/mermaid-generator.js.map +1 -1
  69. package/dist/engine/model-router/complexity-analyzer.d.ts +26 -0
  70. package/dist/engine/model-router/complexity-analyzer.d.ts.map +1 -0
  71. package/dist/engine/model-router/complexity-analyzer.js +182 -0
  72. package/dist/engine/model-router/complexity-analyzer.js.map +1 -0
  73. package/dist/engine/model-router/cost-estimator.d.ts +6 -0
  74. package/dist/engine/model-router/cost-estimator.d.ts.map +1 -0
  75. package/dist/engine/model-router/cost-estimator.js +60 -0
  76. package/dist/engine/model-router/cost-estimator.js.map +1 -0
  77. package/dist/engine/model-router/historical-learner.d.ts +26 -0
  78. package/dist/engine/model-router/historical-learner.d.ts.map +1 -0
  79. package/dist/engine/model-router/historical-learner.js +91 -0
  80. package/dist/engine/model-router/historical-learner.js.map +1 -0
  81. package/dist/engine/model-router/rules-engine.d.ts +13 -0
  82. package/dist/engine/model-router/rules-engine.d.ts.map +1 -0
  83. package/dist/engine/model-router/rules-engine.js +142 -0
  84. package/dist/engine/model-router/rules-engine.js.map +1 -0
  85. package/dist/engine/spec-coverage/criteria-mapper.d.ts +1 -2
  86. package/dist/engine/spec-coverage/criteria-mapper.d.ts.map +1 -1
  87. package/dist/engine/spec-coverage/criteria-mapper.js +4 -203
  88. package/dist/engine/spec-coverage/criteria-mapper.js.map +1 -1
  89. package/dist/engine/spec-coverage/keyword-extractor.d.ts +10 -0
  90. package/dist/engine/spec-coverage/keyword-extractor.d.ts.map +1 -0
  91. package/dist/engine/spec-coverage/keyword-extractor.js +147 -0
  92. package/dist/engine/spec-coverage/keyword-extractor.js.map +1 -0
  93. package/dist/engine/spec-coverage/test-matchers.d.ts +9 -0
  94. package/dist/engine/spec-coverage/test-matchers.d.ts.map +1 -0
  95. package/dist/engine/spec-coverage/test-matchers.js +59 -0
  96. package/dist/engine/spec-coverage/test-matchers.js.map +1 -0
  97. package/dist/engine/spec-templates/catalog-extra.d.ts +1 -1
  98. package/dist/engine/spec-templates/catalog-extra.d.ts.map +1 -1
  99. package/dist/engine/spec-templates/catalog-extra.js +8 -363
  100. package/dist/engine/spec-templates/catalog-extra.js.map +1 -1
  101. package/dist/engine/spec-templates/catalog-industry.d.ts +4 -0
  102. package/dist/engine/spec-templates/catalog-industry.d.ts.map +1 -0
  103. package/dist/engine/spec-templates/catalog-industry.js +19 -0
  104. package/dist/engine/spec-templates/catalog-industry.js.map +1 -0
  105. package/dist/engine/spec-templates/catalog.d.ts +1 -1
  106. package/dist/engine/spec-templates/catalog.d.ts.map +1 -1
  107. package/dist/engine/spec-templates/catalog.js +12 -381
  108. package/dist/engine/spec-templates/catalog.js.map +1 -1
  109. package/dist/engine/spec-templates/custom-loader.d.ts +12 -0
  110. package/dist/engine/spec-templates/custom-loader.d.ts.map +1 -0
  111. package/dist/engine/spec-templates/custom-loader.js +99 -0
  112. package/dist/engine/spec-templates/custom-loader.js.map +1 -0
  113. package/dist/engine/spec-templates/index.d.ts +4 -2
  114. package/dist/engine/spec-templates/index.d.ts.map +1 -1
  115. package/dist/engine/spec-templates/index.js +4 -2
  116. package/dist/engine/spec-templates/index.js.map +1 -1
  117. package/dist/engine/spec-templates/query.d.ts +12 -4
  118. package/dist/engine/spec-templates/query.d.ts.map +1 -1
  119. package/dist/engine/spec-templates/query.js +29 -7
  120. package/dist/engine/spec-templates/query.js.map +1 -1
  121. package/dist/engine/spec-templates/renderer.d.ts +27 -2
  122. package/dist/engine/spec-templates/renderer.d.ts.map +1 -1
  123. package/dist/engine/spec-templates/renderer.js +119 -4
  124. package/dist/engine/spec-templates/renderer.js.map +1 -1
  125. package/dist/engine/spec-templates/templates-api-ui.d.ts +6 -0
  126. package/dist/engine/spec-templates/templates-api-ui.d.ts.map +1 -0
  127. package/dist/engine/spec-templates/templates-api-ui.js +215 -0
  128. package/dist/engine/spec-templates/templates-api-ui.js.map +1 -0
  129. package/dist/engine/spec-templates/templates-auth-crud.d.ts +6 -0
  130. package/dist/engine/spec-templates/templates-auth-crud.d.ts.map +1 -0
  131. package/dist/engine/spec-templates/templates-auth-crud.js +225 -0
  132. package/dist/engine/spec-templates/templates-auth-crud.js.map +1 -0
  133. package/dist/engine/spec-templates/templates-data-security.d.ts +6 -0
  134. package/dist/engine/spec-templates/templates-data-security.d.ts.map +1 -0
  135. package/dist/engine/spec-templates/templates-data-security.js +198 -0
  136. package/dist/engine/spec-templates/templates-data-security.js.map +1 -0
  137. package/dist/engine/spec-templates/templates-industry-ecom.d.ts +6 -0
  138. package/dist/engine/spec-templates/templates-industry-ecom.d.ts.map +1 -0
  139. package/dist/engine/spec-templates/templates-industry-ecom.js +209 -0
  140. package/dist/engine/spec-templates/templates-industry-ecom.js.map +1 -0
  141. package/dist/engine/spec-templates/templates-industry-fintech.d.ts +8 -0
  142. package/dist/engine/spec-templates/templates-industry-fintech.d.ts.map +1 -0
  143. package/dist/engine/spec-templates/templates-industry-fintech.js +350 -0
  144. package/dist/engine/spec-templates/templates-industry-fintech.js.map +1 -0
  145. package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts +3 -0
  146. package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts.map +1 -0
  147. package/dist/engine/spec-templates/templates-industry-health-ecom.js +5 -0
  148. package/dist/engine/spec-templates/templates-industry-health-ecom.js.map +1 -0
  149. package/dist/engine/spec-templates/templates-industry-health.d.ts +6 -0
  150. package/dist/engine/spec-templates/templates-industry-health.d.ts.map +1 -0
  151. package/dist/engine/spec-templates/templates-industry-health.js +208 -0
  152. package/dist/engine/spec-templates/templates-industry-health.js.map +1 -0
  153. package/dist/engine/spec-templates/templates-industry-saas.d.ts +8 -0
  154. package/dist/engine/spec-templates/templates-industry-saas.d.ts.map +1 -0
  155. package/dist/engine/spec-templates/templates-industry-saas.js +323 -0
  156. package/dist/engine/spec-templates/templates-industry-saas.js.map +1 -0
  157. package/dist/engine/spec-templates/templates-perf-integration.d.ts +6 -0
  158. package/dist/engine/spec-templates/templates-perf-integration.d.ts.map +1 -0
  159. package/dist/engine/spec-templates/templates-perf-integration.js +226 -0
  160. package/dist/engine/spec-templates/templates-perf-integration.js.map +1 -0
  161. package/dist/engine/vector-store/hnsw.d.ts +37 -0
  162. package/dist/engine/vector-store/hnsw.d.ts.map +1 -0
  163. package/dist/engine/vector-store/hnsw.js +294 -0
  164. package/dist/engine/vector-store/hnsw.js.map +1 -0
  165. package/dist/engine/vector-store/similarity.d.ts +21 -0
  166. package/dist/engine/vector-store/similarity.d.ts.map +1 -0
  167. package/dist/engine/vector-store/similarity.js +86 -0
  168. package/dist/engine/vector-store/similarity.js.map +1 -0
  169. package/dist/engine/vector-store/tfidf.d.ts +35 -0
  170. package/dist/engine/vector-store/tfidf.d.ts.map +1 -0
  171. package/dist/engine/vector-store/tfidf.js +255 -0
  172. package/dist/engine/vector-store/tfidf.js.map +1 -0
  173. package/dist/index.js +6 -0
  174. package/dist/index.js.map +1 -1
  175. package/dist/storage/vector-store/backend-factory.d.ts +9 -0
  176. package/dist/storage/vector-store/backend-factory.d.ts.map +1 -0
  177. package/dist/storage/vector-store/backend-factory.js +33 -0
  178. package/dist/storage/vector-store/backend-factory.js.map +1 -0
  179. package/dist/storage/vector-store/json-fallback.d.ts +21 -0
  180. package/dist/storage/vector-store/json-fallback.d.ts.map +1 -0
  181. package/dist/storage/vector-store/json-fallback.js +85 -0
  182. package/dist/storage/vector-store/json-fallback.js.map +1 -0
  183. package/dist/storage/vector-store/migrator.d.ts +10 -0
  184. package/dist/storage/vector-store/migrator.d.ts.map +1 -0
  185. package/dist/storage/vector-store/migrator.js +139 -0
  186. package/dist/storage/vector-store/migrator.js.map +1 -0
  187. package/dist/storage/vector-store/sqlite-adapter.d.ts +28 -0
  188. package/dist/storage/vector-store/sqlite-adapter.d.ts.map +1 -0
  189. package/dist/storage/vector-store/sqlite-adapter.js +142 -0
  190. package/dist/storage/vector-store/sqlite-adapter.js.map +1 -0
  191. package/dist/tools/ci-planu-handler.d.ts +8 -0
  192. package/dist/tools/ci-planu-handler.d.ts.map +1 -0
  193. package/dist/tools/ci-planu-handler.js +44 -0
  194. package/dist/tools/ci-planu-handler.js.map +1 -0
  195. package/dist/tools/create-spec/constitution-validator.d.ts +4 -0
  196. package/dist/tools/create-spec/constitution-validator.d.ts.map +1 -0
  197. package/dist/tools/create-spec/constitution-validator.js +37 -0
  198. package/dist/tools/create-spec/constitution-validator.js.map +1 -0
  199. package/dist/tools/create-spec/post-creation.d.ts +11 -0
  200. package/dist/tools/create-spec/post-creation.d.ts.map +1 -0
  201. package/dist/tools/create-spec/post-creation.js +48 -0
  202. package/dist/tools/create-spec/post-creation.js.map +1 -0
  203. package/dist/tools/create-spec/spec-builder.d.ts +14 -0
  204. package/dist/tools/create-spec/spec-builder.d.ts.map +1 -0
  205. package/dist/tools/create-spec/spec-builder.js +131 -0
  206. package/dist/tools/create-spec/spec-builder.js.map +1 -0
  207. package/dist/tools/create-spec.d.ts.map +1 -1
  208. package/dist/tools/create-spec.js +42 -172
  209. package/dist/tools/create-spec.js.map +1 -1
  210. package/dist/tools/init-project/handler.d.ts.map +1 -1
  211. package/dist/tools/init-project/handler.js +24 -159
  212. package/dist/tools/init-project/handler.js.map +1 -1
  213. package/dist/tools/init-project/result-builder.d.ts +4 -0
  214. package/dist/tools/init-project/result-builder.d.ts.map +1 -0
  215. package/dist/tools/init-project/result-builder.js +150 -0
  216. package/dist/tools/init-project/result-builder.js.map +1 -0
  217. package/dist/tools/learn.d.ts.map +1 -1
  218. package/dist/tools/learn.js +67 -14
  219. package/dist/tools/learn.js.map +1 -1
  220. package/dist/tools/recommend-model-handler.d.ts +8 -0
  221. package/dist/tools/recommend-model-handler.d.ts.map +1 -0
  222. package/dist/tools/recommend-model-handler.js +65 -0
  223. package/dist/tools/recommend-model-handler.js.map +1 -0
  224. package/dist/tools/register-ci-tools.d.ts.map +1 -1
  225. package/dist/tools/register-ci-tools.js +36 -0
  226. package/dist/tools/register-ci-tools.js.map +1 -1
  227. package/dist/tools/register-model-tools.d.ts +3 -0
  228. package/dist/tools/register-model-tools.d.ts.map +1 -0
  229. package/dist/tools/register-model-tools.js +50 -0
  230. package/dist/tools/register-model-tools.js.map +1 -0
  231. package/dist/tools/register-search-tools.d.ts +7 -0
  232. package/dist/tools/register-search-tools.d.ts.map +1 -0
  233. package/dist/tools/register-search-tools.js +34 -0
  234. package/dist/tools/register-search-tools.js.map +1 -0
  235. package/dist/tools/register-template-tools.d.ts.map +1 -1
  236. package/dist/tools/register-template-tools.js +21 -8
  237. package/dist/tools/register-template-tools.js.map +1 -1
  238. package/dist/tools/register-transform-tools.d.ts +3 -0
  239. package/dist/tools/register-transform-tools.d.ts.map +1 -0
  240. package/dist/tools/register-transform-tools.js +29 -0
  241. package/dist/tools/register-transform-tools.js.map +1 -0
  242. package/dist/tools/semantic-search-handler.d.ts +7 -0
  243. package/dist/tools/semantic-search-handler.d.ts.map +1 -0
  244. package/dist/tools/semantic-search-handler.js +72 -0
  245. package/dist/tools/semantic-search-handler.js.map +1 -0
  246. package/dist/tools/spec-templates.d.ts +1 -1
  247. package/dist/tools/spec-templates.d.ts.map +1 -1
  248. package/dist/tools/spec-templates.js +20 -6
  249. package/dist/tools/spec-templates.js.map +1 -1
  250. package/dist/tools/transform-code-handler.d.ts +7 -0
  251. package/dist/tools/transform-code-handler.d.ts.map +1 -0
  252. package/dist/tools/transform-code-handler.js +58 -0
  253. package/dist/tools/transform-code-handler.js.map +1 -0
  254. package/dist/types/advanced-framework.d.ts +47 -0
  255. package/dist/types/advanced-framework.d.ts.map +1 -0
  256. package/dist/types/advanced-framework.js +3 -0
  257. package/dist/types/advanced-framework.js.map +1 -0
  258. package/dist/types/ci.d.ts +51 -0
  259. package/dist/types/ci.d.ts.map +1 -1
  260. package/dist/types/code-transforms.d.ts +114 -0
  261. package/dist/types/code-transforms.d.ts.map +1 -0
  262. package/dist/types/code-transforms.js +11 -0
  263. package/dist/types/code-transforms.js.map +1 -0
  264. package/dist/types/css-framework.d.ts +110 -0
  265. package/dist/types/css-framework.d.ts.map +1 -0
  266. package/dist/types/css-framework.js +3 -0
  267. package/dist/types/css-framework.js.map +1 -0
  268. package/dist/types/dashboard.d.ts +77 -0
  269. package/dist/types/dashboard.d.ts.map +1 -0
  270. package/dist/types/dashboard.js +2 -0
  271. package/dist/types/dashboard.js.map +1 -0
  272. package/dist/types/index.d.ts +3 -0
  273. package/dist/types/index.d.ts.map +1 -1
  274. package/dist/types/index.js +3 -0
  275. package/dist/types/index.js.map +1 -1
  276. package/dist/types/model-routing.d.ts +127 -0
  277. package/dist/types/model-routing.d.ts.map +1 -0
  278. package/dist/types/model-routing.js +3 -0
  279. package/dist/types/model-routing.js.map +1 -0
  280. package/dist/types/project/core.d.ts +46 -5
  281. package/dist/types/project/core.d.ts.map +1 -1
  282. package/dist/types/spec/core.d.ts +28 -1
  283. package/dist/types/spec/core.d.ts.map +1 -1
  284. package/dist/types/spec/inputs.d.ts +1 -6
  285. package/dist/types/spec/inputs.d.ts.map +1 -1
  286. package/dist/types/spec-templates.d.ts +51 -1
  287. package/dist/types/spec-templates.d.ts.map +1 -1
  288. package/dist/types/ui.d.ts +3 -231
  289. package/dist/types/ui.d.ts.map +1 -1
  290. package/dist/types/ui.js +7 -1
  291. package/dist/types/ui.js.map +1 -1
  292. package/dist/types/vector-store.d.ts +144 -0
  293. package/dist/types/vector-store.d.ts.map +1 -0
  294. package/dist/types/vector-store.js +3 -0
  295. package/dist/types/vector-store.js.map +1 -0
  296. package/package.json +1 -1
  297. package/src/config/model-routing-rules.json +98 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-estimator.d.ts","sourceRoot":"","sources":["../../../src/engine/model-router/cost-estimator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,SAAS,EAEV,MAAM,sBAAsB,CAAC;AAkD9B,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAYvF;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAMjG"}
@@ -0,0 +1,60 @@
1
+ // engine/model-router/cost-estimator.ts — Token and USD cost estimation per model tier.
2
+ // SPEC-076 AC-04
3
+ import pricingJson from '../../config/ai-model-pricing.json' with { type: 'json' };
4
+ // ---------------------------------------------------------------------------
5
+ // Pricing lookup
6
+ // ---------------------------------------------------------------------------
7
+ const MODEL_IDS = {
8
+ haiku: 'claude-haiku-3-5',
9
+ sonnet: 'claude-sonnet-4',
10
+ opus: 'claude-opus-4',
11
+ };
12
+ function getPricing(tier) {
13
+ const modelId = MODEL_IDS[tier];
14
+ const entry = pricingJson.models.find((m) => m.id === modelId);
15
+ /* c8 ignore next 3 */
16
+ if (!entry) {
17
+ return { id: modelId, inputPricePerMillion: 3, outputPricePerMillion: 15 };
18
+ }
19
+ return entry;
20
+ }
21
+ // ---------------------------------------------------------------------------
22
+ // Token estimation heuristic
23
+ // ---------------------------------------------------------------------------
24
+ /** Base token estimates per complexity range (overall score brackets). */
25
+ function estimateTokens(signals) {
26
+ const score = signals.overallScore;
27
+ // Read-only tasks consume less output
28
+ const outputMultiplier = signals.isReadOnly ? 0.3 : 1;
29
+ if (score < 0.3) {
30
+ return { input: 2_000, output: Math.round(1_000 * outputMultiplier) };
31
+ }
32
+ if (score < 0.6) {
33
+ return { input: 8_000, output: Math.round(5_000 * outputMultiplier) };
34
+ }
35
+ return { input: 20_000, output: Math.round(15_000 * outputMultiplier) };
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Public API
39
+ // ---------------------------------------------------------------------------
40
+ /** Calculate the cost estimate for a given model tier and complexity signals. */
41
+ export function calculateCost(tier, signals) {
42
+ const pricing = getPricing(tier);
43
+ const tokens = estimateTokens(signals);
44
+ const inputCost = (tokens.input / 1_000_000) * pricing.inputPricePerMillion;
45
+ const outputCost = (tokens.output / 1_000_000) * pricing.outputPricePerMillion;
46
+ return {
47
+ estimatedTokens: tokens.input + tokens.output,
48
+ estimatedUSD: Math.round((inputCost + outputCost) * 10_000) / 10_000,
49
+ breakdown: { input: tokens.input, output: tokens.output },
50
+ };
51
+ }
52
+ /** Calculate costs for all three tiers so the user can compare. */
53
+ export function calculateAllTierCosts(signals) {
54
+ return {
55
+ haiku: calculateCost('haiku', signals),
56
+ sonnet: calculateCost('sonnet', signals),
57
+ opus: calculateCost('opus', signals),
58
+ };
59
+ }
60
+ //# sourceMappingURL=cost-estimator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-estimator.js","sourceRoot":"","sources":["../../../src/engine/model-router/cost-estimator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { HistoricalAdjustment, ModelOutcome, ModelTier } from '../../types/index.js';
2
+ /** Record a model outcome for future learning. */
3
+ export declare function recordOutcome(outcome: ModelOutcome): void;
4
+ /** Get all recorded outcomes (for testing / export). */
5
+ export declare function getOutcomes(): readonly ModelOutcome[];
6
+ /** Clear all outcomes (for testing). */
7
+ export declare function clearOutcomes(): void;
8
+ /** Load outcomes from an external source (e.g. JSON file). */
9
+ export declare function loadOutcomes(loaded: ModelOutcome[]): void;
10
+ /**
11
+ * Find outcomes whose taskSignature matches the given signature.
12
+ * Uses exact match for now; vector similarity can be added later (SPEC-075).
13
+ */
14
+ export declare function findSimilarOutcomes(taskSignature: string): ModelOutcome[];
15
+ /**
16
+ * Compute a task signature from a description or spec ID.
17
+ * For now this is a simple normalisation; in the future it can use embeddings.
18
+ */
19
+ export declare function computeTaskSignature(text: string): string;
20
+ /**
21
+ * Given the rules engine recommendation and a task signature,
22
+ * adjust the tier based on historical outcomes.
23
+ * Maximum adjustment: plus or minus 1 tier.
24
+ */
25
+ export declare function adjustFromHistory(recommendedModel: ModelTier, taskSignature: string): HistoricalAdjustment;
26
+ //# sourceMappingURL=historical-learner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"historical-learner.d.ts","sourceRoot":"","sources":["../../../src/engine/model-router/historical-learner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAuB1F,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAEzD;AAED,wDAAwD;AACxD,wBAAgB,WAAW,IAAI,SAAS,YAAY,EAAE,CAErD;AAED,wCAAwC;AACxC,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,EAAE,CAEzE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,SAAS,EAC3B,aAAa,EAAE,MAAM,GACpB,oBAAoB,CA6CtB"}
@@ -0,0 +1,91 @@
1
+ // engine/model-router/historical-learner.ts — Learn from past model outcomes.
2
+ // SPEC-076 AC-03
3
+ // ---------------------------------------------------------------------------
4
+ // In-memory outcome store (JSON persistence is left to the storage layer)
5
+ // ---------------------------------------------------------------------------
6
+ let outcomes = [];
7
+ const TIER_ORDER = ['haiku', 'sonnet', 'opus'];
8
+ function tierIndex(tier) {
9
+ return TIER_ORDER.indexOf(tier);
10
+ }
11
+ function tierByIndex(index) {
12
+ const clamped = Math.max(0, Math.min(index, TIER_ORDER.length - 1));
13
+ return TIER_ORDER[clamped] ?? 'sonnet';
14
+ }
15
+ // ---------------------------------------------------------------------------
16
+ // Public API
17
+ // ---------------------------------------------------------------------------
18
+ /** Record a model outcome for future learning. */
19
+ export function recordOutcome(outcome) {
20
+ outcomes.push(outcome);
21
+ }
22
+ /** Get all recorded outcomes (for testing / export). */
23
+ export function getOutcomes() {
24
+ return outcomes;
25
+ }
26
+ /** Clear all outcomes (for testing). */
27
+ export function clearOutcomes() {
28
+ outcomes = [];
29
+ }
30
+ /** Load outcomes from an external source (e.g. JSON file). */
31
+ export function loadOutcomes(loaded) {
32
+ outcomes = [...loaded];
33
+ }
34
+ /**
35
+ * Find outcomes whose taskSignature matches the given signature.
36
+ * Uses exact match for now; vector similarity can be added later (SPEC-075).
37
+ */
38
+ export function findSimilarOutcomes(taskSignature) {
39
+ return outcomes.filter((o) => o.taskSignature === taskSignature);
40
+ }
41
+ /**
42
+ * Compute a task signature from a description or spec ID.
43
+ * For now this is a simple normalisation; in the future it can use embeddings.
44
+ */
45
+ export function computeTaskSignature(text) {
46
+ return text.trim().toLowerCase().replace(/\s+/g, '-').slice(0, 80);
47
+ }
48
+ /**
49
+ * Given the rules engine recommendation and a task signature,
50
+ * adjust the tier based on historical outcomes.
51
+ * Maximum adjustment: plus or minus 1 tier.
52
+ */
53
+ export function adjustFromHistory(recommendedModel, taskSignature) {
54
+ const similar = findSimilarOutcomes(taskSignature);
55
+ if (similar.length === 0) {
56
+ return {
57
+ adjustedModel: recommendedModel,
58
+ reason: 'No historical data available.',
59
+ adjusted: false,
60
+ };
61
+ }
62
+ const successCount = similar.filter((o) => o.success).length;
63
+ const failCount = similar.length - successCount;
64
+ const successRate = successCount / similar.length;
65
+ // Check if a lighter model was consistently successful
66
+ const lighterSuccesses = similar.filter((o) => o.success && tierIndex(o.modelUsed) < tierIndex(recommendedModel));
67
+ if (lighterSuccesses.length >= 2 && successRate > 0.8) {
68
+ const lighterTier = tierByIndex(tierIndex(recommendedModel) - 1);
69
+ return {
70
+ adjustedModel: lighterTier,
71
+ reason: `Historical data shows a lighter model (${lighterTier}) succeeded ${String(lighterSuccesses.length)} times for similar tasks.`,
72
+ adjusted: true,
73
+ };
74
+ }
75
+ // Check if the recommended model or lighter models frequently failed
76
+ const recFailures = similar.filter((o) => !o.success && tierIndex(o.modelUsed) <= tierIndex(recommendedModel));
77
+ if (recFailures.length >= 2 && failCount > successCount) {
78
+ const heavierTier = tierByIndex(tierIndex(recommendedModel) + 1);
79
+ return {
80
+ adjustedModel: heavierTier,
81
+ reason: `Historical data shows ${String(recFailures.length)} failures at tier ${recommendedModel} or below — upgrading to ${heavierTier}.`,
82
+ adjusted: true,
83
+ };
84
+ }
85
+ return {
86
+ adjustedModel: recommendedModel,
87
+ reason: 'Historical data supports the current recommendation.',
88
+ adjusted: false,
89
+ };
90
+ }
91
+ //# sourceMappingURL=historical-learner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"historical-learner.js","sourceRoot":"","sources":["../../../src/engine/model-router/historical-learner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ComplexitySignals, RoutingRule, RuleCondition, RuleMatch, RulesEngineResult } from '../../types/index.js';
2
+ /** Evaluate a single condition against a signal value. */
3
+ export declare function evaluateCondition(signals: ComplexitySignals, condition: RuleCondition): boolean;
4
+ /** Evaluate a single rule against the given signals. */
5
+ export declare function evaluateRule(signals: ComplexitySignals, rule: RoutingRule): RuleMatch;
6
+ /** Load rules from the built-in config. Custom rules support is left as a hook. */
7
+ export declare function loadRules(customRules?: RoutingRule[]): RoutingRule[];
8
+ /**
9
+ * Evaluate all rules against the given signals and return the best model
10
+ * recommendation with alternatives.
11
+ */
12
+ export declare function evaluateRules(signals: ComplexitySignals, customRules?: RoutingRule[]): RulesEngineResult;
13
+ //# sourceMappingURL=rules-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-engine.d.ts","sourceRoot":"","sources":["../../../src/engine/model-router/rules-engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAEjB,WAAW,EAEX,aAAa,EACb,SAAS,EACT,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAyB9B,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,CA6B/F;AAMD,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,CAWrF;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAQpE;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,EAAE,GAC1B,iBAAiB,CAmDnB"}
@@ -0,0 +1,142 @@
1
+ // engine/model-router/rules-engine.ts — Deterministic rules evaluation for model routing.
2
+ // SPEC-076 AC-02
3
+ import defaultRulesJson from '../../config/model-routing-rules.json' with { type: 'json' };
4
+ // ---------------------------------------------------------------------------
5
+ // Model tier ordering (for tie-breaking: higher index = more capable)
6
+ // ---------------------------------------------------------------------------
7
+ const TIER_ORDER = ['haiku', 'sonnet', 'opus'];
8
+ function tierIndex(tier) {
9
+ return TIER_ORDER.indexOf(tier);
10
+ }
11
+ // ---------------------------------------------------------------------------
12
+ // Condition evaluation
13
+ // ---------------------------------------------------------------------------
14
+ function getSignalValue(signals, signal) {
15
+ return signals[signal];
16
+ }
17
+ /** Evaluate a single condition against a signal value. */
18
+ export function evaluateCondition(signals, condition) {
19
+ const raw = getSignalValue(signals, condition.signal);
20
+ if (raw === undefined) {
21
+ return false;
22
+ }
23
+ const { operator, value } = condition;
24
+ switch (operator) {
25
+ case 'eq':
26
+ return raw === value;
27
+ case 'gt':
28
+ return typeof raw === 'number' && typeof value === 'number' && raw > value;
29
+ case 'gte':
30
+ return typeof raw === 'number' && typeof value === 'number' && raw >= value;
31
+ case 'lt':
32
+ return typeof raw === 'number' && typeof value === 'number' && raw < value;
33
+ case 'lte':
34
+ return typeof raw === 'number' && typeof value === 'number' && raw <= value;
35
+ case 'between': {
36
+ if (typeof raw !== 'number' || !Array.isArray(value)) {
37
+ return false;
38
+ }
39
+ const [lo, hi] = value;
40
+ return raw >= lo && raw <= hi;
41
+ }
42
+ default:
43
+ return false;
44
+ }
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Rule evaluation
48
+ // ---------------------------------------------------------------------------
49
+ /** Evaluate a single rule against the given signals. */
50
+ export function evaluateRule(signals, rule) {
51
+ // An empty conditions list means "always match" (catch-all)
52
+ if (rule.conditions.length === 0) {
53
+ return { rule, matchRatio: 1, confidence: rule.weight };
54
+ }
55
+ const matches = rule.conditions.filter((c) => evaluateCondition(signals, c));
56
+ const matchRatio = matches.length / rule.conditions.length;
57
+ const confidence = matchRatio * rule.weight;
58
+ return { rule, matchRatio, confidence };
59
+ }
60
+ /** Load rules from the built-in config. Custom rules support is left as a hook. */
61
+ export function loadRules(customRules) {
62
+ const config = defaultRulesJson;
63
+ const base = config.rules;
64
+ if (!customRules || customRules.length === 0) {
65
+ return base;
66
+ }
67
+ // Custom rules have higher priority: prepend them
68
+ return [...customRules, ...base];
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Main evaluation
72
+ // ---------------------------------------------------------------------------
73
+ /**
74
+ * Evaluate all rules against the given signals and return the best model
75
+ * recommendation with alternatives.
76
+ */
77
+ export function evaluateRules(signals, customRules) {
78
+ const rules = loadRules(customRules);
79
+ const matches = rules.map((r) => evaluateRule(signals, r));
80
+ // Only keep matches where at least all conditions matched (matchRatio === 1)
81
+ // unless no rule fully matches, then relax to best partial match
82
+ let fullMatches = matches.filter((m) => m.matchRatio === 1 && m.confidence > 0);
83
+ if (fullMatches.length === 0) {
84
+ fullMatches = matches.filter((m) => m.confidence > 0);
85
+ }
86
+ // Sort by confidence desc, then by tier capability desc (tie-break: more capable wins)
87
+ fullMatches.sort((a, b) => {
88
+ const confDiff = b.confidence - a.confidence;
89
+ if (Math.abs(confDiff) > 0.001) {
90
+ return confDiff;
91
+ }
92
+ return tierIndex(b.rule.result) - tierIndex(a.rule.result);
93
+ });
94
+ const best = fullMatches[0];
95
+ /* c8 ignore next 5 */
96
+ if (!best) {
97
+ // Absolute fallback — should never happen because of the catch-all sonnet rule
98
+ return {
99
+ model: 'sonnet',
100
+ confidence: 0.5,
101
+ reasoning: ['Default: sonnet (no rule matched)'],
102
+ alternatives: [],
103
+ };
104
+ }
105
+ const reasoning = buildReasoning(best, signals);
106
+ // Collect alternatives (different model tiers from other matches)
107
+ const seen = new Set([best.rule.result]);
108
+ const alternatives = [];
109
+ for (const m of fullMatches) {
110
+ if (!seen.has(m.rule.result)) {
111
+ seen.add(m.rule.result);
112
+ alternatives.push({ model: m.rule.result, confidence: m.confidence });
113
+ }
114
+ }
115
+ return {
116
+ model: best.rule.result,
117
+ confidence: best.confidence,
118
+ reasoning,
119
+ alternatives,
120
+ };
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Reasoning builder
124
+ // ---------------------------------------------------------------------------
125
+ function buildReasoning(match, signals) {
126
+ const reasons = [];
127
+ reasons.push(`Rule "${match.rule.name}" matched with confidence ${match.confidence.toFixed(2)}.`);
128
+ if (signals.criteriaCount > 15) {
129
+ reasons.push(`High criteria count (${String(signals.criteriaCount)}) suggests a complex task.`);
130
+ }
131
+ if (signals.crossLayerCount > 2) {
132
+ reasons.push(`Cross-layer changes (${String(signals.crossLayerCount)} layers) increase coordination complexity.`);
133
+ }
134
+ if (signals.isReadOnly) {
135
+ reasons.push('Read-only task — a lighter model can handle this efficiently.');
136
+ }
137
+ if (signals.hasSecurityImplications) {
138
+ reasons.push('Security implications detected — a more capable model is recommended.');
139
+ }
140
+ return reasons;
141
+ }
142
+ //# sourceMappingURL=rules-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-engine.js","sourceRoot":"","sources":["../../../src/engine/model-router/rules-engine.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { CriterionCoverage, CoverageTestFile, RawCriterion } from '../../types/index.js';
2
+ export { extractKeywords } from './keyword-extractor.js';
2
3
  /**
3
4
  * Parses HU.md content and returns a list of acceptance criteria with their
4
5
  * identifiers and descriptions. Supports flexible AC formats:
@@ -13,6 +14,4 @@ export declare function extractCriteria(huContent: string): readonly RawCriterio
13
14
  * defined in SPEC-068. Returns the full CriterionCoverage for that criterion.
14
15
  */
15
16
  export declare function mapTestsToCriterion(criterion: RawCriterion, testFiles: readonly CoverageTestFile[], testContents: ReadonlyMap<string, string>, specId: string): CriterionCoverage;
16
- /** Extracts 3–5 meaningful keywords from an AC description text. */
17
- export declare function extractKeywords(text: string): readonly string[];
18
17
  //# sourceMappingURL=criteria-mapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"criteria-mapper.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-coverage/criteria-mapper.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAIjB,gBAAgB,EAChB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAiF9B;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAmC1E;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,SAAS,gBAAgB,EAAE,EACtC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,MAAM,EAAE,MAAM,GACb,iBAAiB,CAsCnB;AAsFD,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAkB/D"}
1
+ {"version":3,"file":"criteria-mapper.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-coverage/criteria-mapper.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAIjB,gBAAgB,EAChB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAmC1E;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,SAAS,gBAAgB,EAAE,EACtC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,MAAM,EAAE,MAAM,GACb,iBAAiB,CAsCnB"}
@@ -1,78 +1,9 @@
1
1
  // engine/spec-coverage/criteria-mapper.ts — Extracts acceptance criteria from
2
2
  // HU.md and maps test files to each criterion using 3 strategies.
3
- // ---------------------------------------------------------------------------
4
- // Stop words for heuristic keyword extraction
5
- // ---------------------------------------------------------------------------
6
- const STOP_WORDS = new Set([
7
- 'the',
8
- 'a',
9
- 'an',
10
- 'is',
11
- 'are',
12
- 'was',
13
- 'were',
14
- 'be',
15
- 'been',
16
- 'being',
17
- 'have',
18
- 'has',
19
- 'had',
20
- 'do',
21
- 'does',
22
- 'did',
23
- 'will',
24
- 'would',
25
- 'could',
26
- 'should',
27
- 'may',
28
- 'might',
29
- 'shall',
30
- 'must',
31
- 'can',
32
- 'to',
33
- 'of',
34
- 'in',
35
- 'on',
36
- 'at',
37
- 'by',
38
- 'for',
39
- 'with',
40
- 'from',
41
- 'as',
42
- 'and',
43
- 'or',
44
- 'but',
45
- 'not',
46
- 'no',
47
- 'if',
48
- 'when',
49
- 'where',
50
- 'that',
51
- 'which',
52
- 'this',
53
- 'it',
54
- 'its',
55
- 'el',
56
- 'la',
57
- 'los',
58
- 'las',
59
- 'un',
60
- 'una',
61
- 'de',
62
- 'del',
63
- 'en',
64
- 'que',
65
- 'se',
66
- 'por',
67
- 'para',
68
- 'con',
69
- 'al',
70
- 'lo',
71
- 'le',
72
- 'les',
73
- 'y',
74
- 'o',
75
- ]);
3
+ import { findDirectReferences, findSpecReferences, findKeywordMatches } from './test-matchers.js';
4
+ import { extractKeywords } from './keyword-extractor.js';
5
+ // Re-export for backward compatibility
6
+ export { extractKeywords } from './keyword-extractor.js';
76
7
  // ---------------------------------------------------------------------------
77
8
  // AC extraction
78
9
  // ---------------------------------------------------------------------------
@@ -152,136 +83,6 @@ export function mapTestsToCriterion(criterion, testFiles, testContents, specId)
152
83
  };
153
84
  }
154
85
  // ---------------------------------------------------------------------------
155
- // Strategy implementations
156
- // ---------------------------------------------------------------------------
157
- /** Strategy 1: look for AC-ID or AC ID (with space or no dash) in test content. */
158
- function findDirectReferences(acId, testFiles, testContents) {
159
- const matches = [];
160
- // Build regex variants: AC-01, AC01, #AC-01, AC 01
161
- const acNum = acId.replace('AC-', '');
162
- const pattern = new RegExp(`\\b(?:AC[-\\s]?${acNum}|#AC-?${acNum})\\b`, 'i');
163
- for (const tf of testFiles) {
164
- const content = testContents.get(tf.file) ?? '';
165
- if (!pattern.test(content)) {
166
- continue;
167
- }
168
- // Extract the test name from the first matching line
169
- const testName = extractTestName(content, pattern);
170
- matches.push({ file: tf.file, testName, strategy: 'direct-reference' });
171
- }
172
- return matches;
173
- }
174
- /** Strategy 2: look for SPEC-ID in file path or content. */
175
- function findSpecReferences(specId, testFiles, testContents) {
176
- const matches = [];
177
- const specPattern = new RegExp(`\\b${specId.replace('-', '[-_]?')}\\b`, 'i');
178
- for (const tf of testFiles) {
179
- const inPath = specPattern.test(tf.file);
180
- const content = testContents.get(tf.file) ?? '';
181
- const inContent = specPattern.test(content);
182
- if (!inPath && !inContent) {
183
- continue;
184
- }
185
- const testName = inContent ? extractTestName(content, specPattern) : tf.file;
186
- matches.push({ file: tf.file, testName, strategy: 'spec-reference' });
187
- }
188
- return matches;
189
- }
190
- /** Strategy 3: match keywords from criterion text against test names in files. */
191
- function findKeywordMatches(keywords, testFiles, testContents) {
192
- const matches = [];
193
- for (const tf of testFiles) {
194
- const content = testContents.get(tf.file) ?? '';
195
- // Extract all describe/it/test block names
196
- const testNames = extractAllTestNames(content);
197
- const combinedText = [...testNames, tf.file].join(' ').toLowerCase();
198
- const matchCount = keywords.filter((kw) => combinedText.includes(kw.toLowerCase())).length;
199
- if (matchCount >= 2) {
200
- matches.push({
201
- file: tf.file,
202
- /* v8 ignore next 1 */
203
- testName: testNames[0] ?? tf.file,
204
- strategy: 'heuristic',
205
- });
206
- }
207
- }
208
- return matches;
209
- }
210
- // ---------------------------------------------------------------------------
211
- // Keyword extraction
212
- // ---------------------------------------------------------------------------
213
- /** Extracts 3–5 meaningful keywords from an AC description text. */
214
- export function extractKeywords(text) {
215
- const words = text
216
- .toLowerCase()
217
- .replace(/[^a-zA-Z0-9\s_àáéíóúñüÀÁÉÍÓÚÑÜ]/g, ' ')
218
- .split(/\s+/)
219
- .filter((w) => w.length >= 3 && !STOP_WORDS.has(w));
220
- // De-duplicate preserving order
221
- const seen = new Set();
222
- const unique = [];
223
- for (const w of words) {
224
- if (!seen.has(w)) {
225
- seen.add(w);
226
- unique.push(w);
227
- }
228
- }
229
- return unique.slice(0, 5);
230
- }
231
- // ---------------------------------------------------------------------------
232
- // Test name extraction helpers
233
- // ---------------------------------------------------------------------------
234
- /** Patterns for extracting test block names from source code. */
235
- const TEST_NAME_PATTERNS = [
236
- /(?:describe|it|test|context|suite|feature|scenario)\s*\(\s*['"`](.*?)['"`]/g,
237
- /(?:func\s+Test\w+)\s*\(/g, // Go: func TestXxx(
238
- /(?:def\s+test_\w+)\s*\(/g, // Python: def test_xxx(
239
- /#\[test\]\s*(?:fn\s+(\w+))/g, // Rust: #[test] fn name
240
- /(?:func|fun)\s+(test\w+)\s*\(/gi, // Swift/Kotlin
241
- ];
242
- /** Extracts the first matching test name from source code. */
243
- function extractTestName(content, nearPattern) {
244
- // Find the line with the pattern match, then look for a nearby test name
245
- const lines = content.split('\n');
246
- for (let i = 0; i < lines.length; i++) {
247
- /* v8 ignore next 1 */
248
- const line = lines[i] ?? '';
249
- if (!nearPattern.test(line)) {
250
- continue;
251
- }
252
- // Look in ±5 lines for a test name
253
- const start = Math.max(0, i - 5);
254
- const end = Math.min(lines.length - 1, i + 5);
255
- for (let j = start; j <= end; j++) {
256
- /* v8 ignore next 1 */
257
- const nearby = lines[j] ?? '';
258
- const nameMatch = /(?:describe|it|test|context)\s*\(\s*['"`](.*?)['"`]/.exec(nearby);
259
- if (nameMatch?.[1]) {
260
- return nameMatch[1];
261
- }
262
- }
263
- return line.trim().slice(0, 80);
264
- }
265
- return '';
266
- }
267
- /** Extracts all test/describe block names from source code. */
268
- function extractAllTestNames(content) {
269
- const names = [];
270
- for (const pattern of TEST_NAME_PATTERNS) {
271
- pattern.lastIndex = 0;
272
- let match;
273
- while ((match = pattern.exec(content)) !== null) {
274
- /* v8 ignore next 1 */
275
- const name = match[1] ?? match[0];
276
- /* v8 ignore next 1 */
277
- if (name) {
278
- names.push(name);
279
- }
280
- }
281
- }
282
- return names;
283
- }
284
- // ---------------------------------------------------------------------------
285
86
  // Result builder
286
87
  // ---------------------------------------------------------------------------
287
88
  function buildResult(acId, description, status, strategy, rawMatches, testFiles) {
@@ -1 +1 @@
1
- {"version":3,"file":"criteria-mapper.js","sourceRoot":"","sources":["../../../src/engine/spec-coverage/criteria-mapper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"criteria-mapper.js","sourceRoot":"","sources":["../../../src/engine/spec-coverage/criteria-mapper.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kEAAkE;AAUlE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,uCAAuC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,4DAA4D;IAC5D,MAAM,eAAe,GAAG,gEAAgE,CAAC;IACzF,8CAA8C;IAC9C,MAAM,YAAY,GAAG,2BAA2B,CAAC;IAEjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,OAAO,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,EAAE,CAAC;QACtD,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAClD,sBAAsB;YACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,SAAS;YACX,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;gBAClC,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAuB,EACvB,SAAsC,EACtC,YAAyC,EACzC,MAAc;IAEd,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAEjD,kDAAkD;IAClD,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC1E,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IACjG,CAAC;IAED,kDAAkD;IAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACxE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAC7F,CAAC;IAED,kDAAkD;IAClD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QAC/E,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,WAAW,CAChB,IAAI,EACJ,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,SAAS,CACV,CAAC;QACJ,CAAC;IACH,CAAC;IAED,WAAW;IACX,OAAO;QACL,IAAI;QACJ,WAAW;QACX,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,EAAE;KACV,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,SAAS,WAAW,CAClB,IAAY,EACZ,WAAmB,EACnB,MAAsB,EACtB,QAAyB,EACzB,UAAuB,EACvB,SAAsC;IAEtC,8DAA8D;IAC9D,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,cAAc,GAClB,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;IAE5F,MAAM,eAAe,GAAmB,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;IAEhF,OAAO;QACL,IAAI;QACJ,WAAW;QACX,MAAM,EAAE,eAAe;QACvB,QAAQ;QACR,KAAK,EAAE,UAAU;KAClB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,QAAQ,CAAC,IAAY,EAAE,MAAc;IAC5C,OAAO,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;AACxE,CAAC"}