@planu/cli 0.63.7 → 0.64.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 (601) hide show
  1. package/dist/config/license-plans.json +16 -1
  2. package/dist/engine/a2a/capability-card.d.ts +16 -0
  3. package/dist/engine/a2a/capability-card.d.ts.map +1 -0
  4. package/dist/engine/a2a/capability-card.js +69 -0
  5. package/dist/engine/a2a/capability-card.js.map +1 -0
  6. package/dist/engine/a2a/delegate.d.ts +15 -0
  7. package/dist/engine/a2a/delegate.d.ts.map +1 -0
  8. package/dist/engine/a2a/delegate.js +47 -0
  9. package/dist/engine/a2a/delegate.js.map +1 -0
  10. package/dist/engine/a2a/fallback.d.ts +12 -0
  11. package/dist/engine/a2a/fallback.d.ts.map +1 -0
  12. package/dist/engine/a2a/fallback.js +52 -0
  13. package/dist/engine/a2a/fallback.js.map +1 -0
  14. package/dist/engine/a2a/index.d.ts +5 -0
  15. package/dist/engine/a2a/index.d.ts.map +1 -0
  16. package/dist/engine/a2a/index.js +6 -0
  17. package/dist/engine/a2a/index.js.map +1 -0
  18. package/dist/engine/a2a/task-manager.d.ts +39 -0
  19. package/dist/engine/a2a/task-manager.d.ts.map +1 -0
  20. package/dist/engine/a2a/task-manager.js +84 -0
  21. package/dist/engine/a2a/task-manager.js.map +1 -0
  22. package/dist/engine/ac-gap-detector/analyze-gaps.d.ts +13 -0
  23. package/dist/engine/ac-gap-detector/analyze-gaps.d.ts.map +1 -0
  24. package/dist/engine/ac-gap-detector/analyze-gaps.js +43 -0
  25. package/dist/engine/ac-gap-detector/analyze-gaps.js.map +1 -0
  26. package/dist/engine/ac-gap-detector/constants.d.ts +22 -0
  27. package/dist/engine/ac-gap-detector/constants.d.ts.map +1 -0
  28. package/dist/engine/ac-gap-detector/constants.js +143 -0
  29. package/dist/engine/ac-gap-detector/constants.js.map +1 -0
  30. package/dist/engine/ac-gap-detector/gap-rules.d.ts +16 -0
  31. package/dist/engine/ac-gap-detector/gap-rules.d.ts.map +1 -0
  32. package/dist/engine/ac-gap-detector/gap-rules.js +180 -0
  33. package/dist/engine/ac-gap-detector/gap-rules.js.map +1 -0
  34. package/dist/engine/ac-gap-detector/pattern-matcher.d.ts +16 -0
  35. package/dist/engine/ac-gap-detector/pattern-matcher.d.ts.map +1 -0
  36. package/dist/engine/ac-gap-detector/pattern-matcher.js +62 -0
  37. package/dist/engine/ac-gap-detector/pattern-matcher.js.map +1 -0
  38. package/dist/engine/ac-gap-detector.d.ts +3 -0
  39. package/dist/engine/ac-gap-detector.d.ts.map +1 -0
  40. package/dist/engine/ac-gap-detector.js +5 -0
  41. package/dist/engine/ac-gap-detector.js.map +1 -0
  42. package/dist/engine/audit-trail/attestation.d.ts +11 -0
  43. package/dist/engine/audit-trail/attestation.d.ts.map +1 -0
  44. package/dist/engine/audit-trail/attestation.js +47 -0
  45. package/dist/engine/audit-trail/attestation.js.map +1 -0
  46. package/dist/engine/audit-trail/index.d.ts +6 -0
  47. package/dist/engine/audit-trail/index.d.ts.map +1 -0
  48. package/dist/engine/audit-trail/index.js +6 -0
  49. package/dist/engine/audit-trail/index.js.map +1 -0
  50. package/dist/engine/audit-trail/logger.d.ts +17 -0
  51. package/dist/engine/audit-trail/logger.d.ts.map +1 -0
  52. package/dist/engine/audit-trail/logger.js +78 -0
  53. package/dist/engine/audit-trail/logger.js.map +1 -0
  54. package/dist/engine/audit-trail/query.d.ts +7 -0
  55. package/dist/engine/audit-trail/query.d.ts.map +1 -0
  56. package/dist/engine/audit-trail/query.js +61 -0
  57. package/dist/engine/audit-trail/query.js.map +1 -0
  58. package/dist/engine/audit-trail/utils.d.ts +18 -0
  59. package/dist/engine/audit-trail/utils.d.ts.map +1 -0
  60. package/dist/engine/audit-trail/utils.js +44 -0
  61. package/dist/engine/audit-trail/utils.js.map +1 -0
  62. package/dist/engine/audit-trail/verifier.d.ts +10 -0
  63. package/dist/engine/audit-trail/verifier.d.ts.map +1 -0
  64. package/dist/engine/audit-trail/verifier.js +78 -0
  65. package/dist/engine/audit-trail/verifier.js.map +1 -0
  66. package/dist/engine/auth/config.d.ts +20 -0
  67. package/dist/engine/auth/config.d.ts.map +1 -0
  68. package/dist/engine/auth/config.js +49 -0
  69. package/dist/engine/auth/config.js.map +1 -0
  70. package/dist/engine/auth/index.d.ts +6 -0
  71. package/dist/engine/auth/index.d.ts.map +1 -0
  72. package/dist/engine/auth/index.js +7 -0
  73. package/dist/engine/auth/index.js.map +1 -0
  74. package/dist/engine/auth/middleware.d.ts +19 -0
  75. package/dist/engine/auth/middleware.d.ts.map +1 -0
  76. package/dist/engine/auth/middleware.js +64 -0
  77. package/dist/engine/auth/middleware.js.map +1 -0
  78. package/dist/engine/auth/pkce.d.ts +17 -0
  79. package/dist/engine/auth/pkce.d.ts.map +1 -0
  80. package/dist/engine/auth/pkce.js +33 -0
  81. package/dist/engine/auth/pkce.js.map +1 -0
  82. package/dist/engine/auth/scope-mapper.d.ts +21 -0
  83. package/dist/engine/auth/scope-mapper.d.ts.map +1 -0
  84. package/dist/engine/auth/scope-mapper.js +124 -0
  85. package/dist/engine/auth/scope-mapper.js.map +1 -0
  86. package/dist/engine/auth/token-validator.d.ts +15 -0
  87. package/dist/engine/auth/token-validator.d.ts.map +1 -0
  88. package/dist/engine/auth/token-validator.js +121 -0
  89. package/dist/engine/auth/token-validator.js.map +1 -0
  90. package/dist/engine/ci-generator/index.d.ts.map +1 -1
  91. package/dist/engine/ci-generator/index.js +8 -2
  92. package/dist/engine/ci-generator/index.js.map +1 -1
  93. package/dist/engine/ci-generator/yaml-builder.d.ts +7 -2
  94. package/dist/engine/ci-generator/yaml-builder.d.ts.map +1 -1
  95. package/dist/engine/ci-generator/yaml-builder.js +49 -1
  96. package/dist/engine/ci-generator/yaml-builder.js.map +1 -1
  97. package/dist/engine/design-to-spec/ac-generator.d.ts +21 -0
  98. package/dist/engine/design-to-spec/ac-generator.d.ts.map +1 -0
  99. package/dist/engine/design-to-spec/ac-generator.js +185 -0
  100. package/dist/engine/design-to-spec/ac-generator.js.map +1 -0
  101. package/dist/engine/design-to-spec/index.d.ts +11 -0
  102. package/dist/engine/design-to-spec/index.d.ts.map +1 -0
  103. package/dist/engine/design-to-spec/index.js +19 -0
  104. package/dist/engine/design-to-spec/index.js.map +1 -0
  105. package/dist/engine/design-to-spec/parser.d.ts +7 -0
  106. package/dist/engine/design-to-spec/parser.d.ts.map +1 -0
  107. package/dist/engine/design-to-spec/parser.js +290 -0
  108. package/dist/engine/design-to-spec/parser.js.map +1 -0
  109. package/dist/engine/design-to-spec/spec-builder.d.ts +12 -0
  110. package/dist/engine/design-to-spec/spec-builder.d.ts.map +1 -0
  111. package/dist/engine/design-to-spec/spec-builder.js +148 -0
  112. package/dist/engine/design-to-spec/spec-builder.js.map +1 -0
  113. package/dist/engine/design-to-spec/ui-contract-builder.d.ts +17 -0
  114. package/dist/engine/design-to-spec/ui-contract-builder.d.ts.map +1 -0
  115. package/dist/engine/design-to-spec/ui-contract-builder.js +175 -0
  116. package/dist/engine/design-to-spec/ui-contract-builder.js.map +1 -0
  117. package/dist/engine/elicitation/builder.d.ts +37 -0
  118. package/dist/engine/elicitation/builder.d.ts.map +1 -0
  119. package/dist/engine/elicitation/builder.js +115 -0
  120. package/dist/engine/elicitation/builder.js.map +1 -0
  121. package/dist/engine/elicitation/fallback.d.ts +20 -0
  122. package/dist/engine/elicitation/fallback.d.ts.map +1 -0
  123. package/dist/engine/elicitation/fallback.js +72 -0
  124. package/dist/engine/elicitation/fallback.js.map +1 -0
  125. package/dist/engine/elicitation/index.d.ts +4 -0
  126. package/dist/engine/elicitation/index.d.ts.map +1 -0
  127. package/dist/engine/elicitation/index.js +5 -0
  128. package/dist/engine/elicitation/index.js.map +1 -0
  129. package/dist/engine/elicitation/response-parser.d.ts +9 -0
  130. package/dist/engine/elicitation/response-parser.d.ts.map +1 -0
  131. package/dist/engine/elicitation/response-parser.js +163 -0
  132. package/dist/engine/elicitation/response-parser.js.map +1 -0
  133. package/dist/engine/federation/cross-repo-resolver.d.ts +21 -0
  134. package/dist/engine/federation/cross-repo-resolver.d.ts.map +1 -0
  135. package/dist/engine/federation/cross-repo-resolver.js +75 -0
  136. package/dist/engine/federation/cross-repo-resolver.js.map +1 -0
  137. package/dist/engine/federation/drift-checker.d.ts +19 -0
  138. package/dist/engine/federation/drift-checker.d.ts.map +1 -0
  139. package/dist/engine/federation/drift-checker.js +114 -0
  140. package/dist/engine/federation/drift-checker.js.map +1 -0
  141. package/dist/engine/federation/federation-store.d.ts +25 -0
  142. package/dist/engine/federation/federation-store.d.ts.map +1 -0
  143. package/dist/engine/federation/federation-store.js +58 -0
  144. package/dist/engine/federation/federation-store.js.map +1 -0
  145. package/dist/engine/federation/index.d.ts +4 -0
  146. package/dist/engine/federation/index.d.ts.map +1 -0
  147. package/dist/engine/federation/index.js +5 -0
  148. package/dist/engine/federation/index.js.map +1 -0
  149. package/dist/engine/github/spec-ac-analyzer.d.ts +40 -0
  150. package/dist/engine/github/spec-ac-analyzer.d.ts.map +1 -0
  151. package/dist/engine/github/spec-ac-analyzer.js +181 -0
  152. package/dist/engine/github/spec-ac-analyzer.js.map +1 -0
  153. package/dist/engine/hooks/handlers/on-impl-change.d.ts +3 -1
  154. package/dist/engine/hooks/handlers/on-impl-change.d.ts.map +1 -1
  155. package/dist/engine/hooks/handlers/on-impl-change.js +25 -1
  156. package/dist/engine/hooks/handlers/on-impl-change.js.map +1 -1
  157. package/dist/engine/infrastructure/component-mapper.d.ts +9 -0
  158. package/dist/engine/infrastructure/component-mapper.d.ts.map +1 -0
  159. package/dist/engine/infrastructure/component-mapper.js +162 -0
  160. package/dist/engine/infrastructure/component-mapper.js.map +1 -0
  161. package/dist/engine/infrastructure/cost-estimator.d.ts +6 -0
  162. package/dist/engine/infrastructure/cost-estimator.d.ts.map +1 -0
  163. package/dist/engine/infrastructure/cost-estimator.js +48 -0
  164. package/dist/engine/infrastructure/cost-estimator.js.map +1 -0
  165. package/dist/engine/infrastructure/docker-compose-generator.d.ts +6 -0
  166. package/dist/engine/infrastructure/docker-compose-generator.d.ts.map +1 -0
  167. package/dist/engine/infrastructure/docker-compose-generator.js +201 -0
  168. package/dist/engine/infrastructure/docker-compose-generator.js.map +1 -0
  169. package/dist/engine/infrastructure/index.d.ts +15 -0
  170. package/dist/engine/infrastructure/index.d.ts.map +1 -0
  171. package/dist/engine/infrastructure/index.js +67 -0
  172. package/dist/engine/infrastructure/index.js.map +1 -0
  173. package/dist/engine/infrastructure/kubernetes-generator.d.ts +6 -0
  174. package/dist/engine/infrastructure/kubernetes-generator.d.ts.map +1 -0
  175. package/dist/engine/infrastructure/kubernetes-generator.js +141 -0
  176. package/dist/engine/infrastructure/kubernetes-generator.js.map +1 -0
  177. package/dist/engine/infrastructure/railway-generator.d.ts +6 -0
  178. package/dist/engine/infrastructure/railway-generator.d.ts.map +1 -0
  179. package/dist/engine/infrastructure/railway-generator.js +87 -0
  180. package/dist/engine/infrastructure/railway-generator.js.map +1 -0
  181. package/dist/engine/infrastructure/signal-detector.d.ts +7 -0
  182. package/dist/engine/infrastructure/signal-detector.d.ts.map +1 -0
  183. package/dist/engine/infrastructure/signal-detector.js +174 -0
  184. package/dist/engine/infrastructure/signal-detector.js.map +1 -0
  185. package/dist/engine/infrastructure/terraform-generator.d.ts +6 -0
  186. package/dist/engine/infrastructure/terraform-generator.d.ts.map +1 -0
  187. package/dist/engine/infrastructure/terraform-generator.js +241 -0
  188. package/dist/engine/infrastructure/terraform-generator.js.map +1 -0
  189. package/dist/engine/living-spec/annotation-parser.d.ts.map +1 -1
  190. package/dist/engine/living-spec/annotation-parser.js.map +1 -1
  191. package/dist/engine/living-spec/auto-updater.d.ts +58 -0
  192. package/dist/engine/living-spec/auto-updater.d.ts.map +1 -0
  193. package/dist/engine/living-spec/auto-updater.js +311 -0
  194. package/dist/engine/living-spec/auto-updater.js.map +1 -0
  195. package/dist/engine/living-spec/conflict-resolver.d.ts +46 -0
  196. package/dist/engine/living-spec/conflict-resolver.d.ts.map +1 -0
  197. package/dist/engine/living-spec/conflict-resolver.js +301 -0
  198. package/dist/engine/living-spec/conflict-resolver.js.map +1 -0
  199. package/dist/engine/living-spec/hash-tracker.d.ts.map +1 -1
  200. package/dist/engine/living-spec/hash-tracker.js.map +1 -1
  201. package/dist/engine/living-spec/index.d.ts +1 -0
  202. package/dist/engine/living-spec/index.d.ts.map +1 -1
  203. package/dist/engine/living-spec/index.js +1 -0
  204. package/dist/engine/living-spec/index.js.map +1 -1
  205. package/dist/engine/living-spec/signature-tracker.d.ts.map +1 -1
  206. package/dist/engine/living-spec/signature-tracker.js.map +1 -1
  207. package/dist/engine/observability/config.d.ts +16 -0
  208. package/dist/engine/observability/config.d.ts.map +1 -0
  209. package/dist/engine/observability/config.js +44 -0
  210. package/dist/engine/observability/config.js.map +1 -0
  211. package/dist/engine/observability/index.d.ts +7 -0
  212. package/dist/engine/observability/index.d.ts.map +1 -0
  213. package/dist/engine/observability/index.js +8 -0
  214. package/dist/engine/observability/index.js.map +1 -0
  215. package/dist/engine/observability/metrics.d.ts +12 -0
  216. package/dist/engine/observability/metrics.d.ts.map +1 -0
  217. package/dist/engine/observability/metrics.js +61 -0
  218. package/dist/engine/observability/metrics.js.map +1 -0
  219. package/dist/engine/observability/noop-tracer.d.ts +13 -0
  220. package/dist/engine/observability/noop-tracer.d.ts.map +1 -0
  221. package/dist/engine/observability/noop-tracer.js +41 -0
  222. package/dist/engine/observability/noop-tracer.js.map +1 -0
  223. package/dist/engine/observability/otel-tracer.d.ts +19 -0
  224. package/dist/engine/observability/otel-tracer.d.ts.map +1 -0
  225. package/dist/engine/observability/otel-tracer.js +134 -0
  226. package/dist/engine/observability/otel-tracer.js.map +1 -0
  227. package/dist/engine/observability/span-helpers.d.ts +28 -0
  228. package/dist/engine/observability/span-helpers.d.ts.map +1 -0
  229. package/dist/engine/observability/span-helpers.js +68 -0
  230. package/dist/engine/observability/span-helpers.js.map +1 -0
  231. package/dist/engine/observability/tracer.d.ts +26 -0
  232. package/dist/engine/observability/tracer.d.ts.map +1 -0
  233. package/dist/engine/observability/tracer.js +45 -0
  234. package/dist/engine/observability/tracer.js.map +1 -0
  235. package/dist/engine/rbac/index.d.ts +3 -0
  236. package/dist/engine/rbac/index.d.ts.map +1 -0
  237. package/dist/engine/rbac/index.js +4 -0
  238. package/dist/engine/rbac/index.js.map +1 -0
  239. package/dist/engine/rbac/permission-checker.d.ts +21 -0
  240. package/dist/engine/rbac/permission-checker.d.ts.map +1 -0
  241. package/dist/engine/rbac/permission-checker.js +74 -0
  242. package/dist/engine/rbac/permission-checker.js.map +1 -0
  243. package/dist/engine/rbac/roles.d.ts +12 -0
  244. package/dist/engine/rbac/roles.d.ts.map +1 -0
  245. package/dist/engine/rbac/roles.js +37 -0
  246. package/dist/engine/rbac/roles.js.map +1 -0
  247. package/dist/engine/shared/ac-extractor.d.ts +9 -0
  248. package/dist/engine/shared/ac-extractor.d.ts.map +1 -0
  249. package/dist/engine/shared/ac-extractor.js +36 -0
  250. package/dist/engine/shared/ac-extractor.js.map +1 -0
  251. package/dist/engine/shared/line-diff.d.ts +11 -0
  252. package/dist/engine/shared/line-diff.d.ts.map +1 -0
  253. package/dist/engine/shared/line-diff.js +32 -0
  254. package/dist/engine/shared/line-diff.js.map +1 -0
  255. package/dist/engine/spec-decomposer/analyzer.d.ts +18 -0
  256. package/dist/engine/spec-decomposer/analyzer.d.ts.map +1 -0
  257. package/dist/engine/spec-decomposer/analyzer.js +263 -0
  258. package/dist/engine/spec-decomposer/analyzer.js.map +1 -0
  259. package/dist/engine/spec-decomposer/file-mapper.d.ts +17 -0
  260. package/dist/engine/spec-decomposer/file-mapper.d.ts.map +1 -0
  261. package/dist/engine/spec-decomposer/file-mapper.js +96 -0
  262. package/dist/engine/spec-decomposer/file-mapper.js.map +1 -0
  263. package/dist/engine/spec-decomposer/index.d.ts +14 -0
  264. package/dist/engine/spec-decomposer/index.d.ts.map +1 -0
  265. package/dist/engine/spec-decomposer/index.js +50 -0
  266. package/dist/engine/spec-decomposer/index.js.map +1 -0
  267. package/dist/engine/spec-decomposer/ownership-resolver.d.ts +7 -0
  268. package/dist/engine/spec-decomposer/ownership-resolver.d.ts.map +1 -0
  269. package/dist/engine/spec-decomposer/ownership-resolver.js +169 -0
  270. package/dist/engine/spec-decomposer/ownership-resolver.js.map +1 -0
  271. package/dist/engine/spec-observability/index.d.ts +4 -0
  272. package/dist/engine/spec-observability/index.d.ts.map +1 -0
  273. package/dist/engine/spec-observability/index.js +4 -0
  274. package/dist/engine/spec-observability/index.js.map +1 -0
  275. package/dist/engine/spec-observability/metrics.d.ts +8 -0
  276. package/dist/engine/spec-observability/metrics.d.ts.map +1 -0
  277. package/dist/engine/spec-observability/metrics.js +116 -0
  278. package/dist/engine/spec-observability/metrics.js.map +1 -0
  279. package/dist/engine/spec-observability/tracker.d.ts +22 -0
  280. package/dist/engine/spec-observability/tracker.d.ts.map +1 -0
  281. package/dist/engine/spec-observability/tracker.js +77 -0
  282. package/dist/engine/spec-observability/tracker.js.map +1 -0
  283. package/dist/engine/spec-reader.d.ts +7 -0
  284. package/dist/engine/spec-reader.d.ts.map +1 -0
  285. package/dist/engine/spec-reader.js +23 -0
  286. package/dist/engine/spec-reader.js.map +1 -0
  287. package/dist/engine/spec-repair.d.ts +10 -0
  288. package/dist/engine/spec-repair.d.ts.map +1 -0
  289. package/dist/engine/spec-repair.js +388 -0
  290. package/dist/engine/spec-repair.js.map +1 -0
  291. package/dist/engine/spec-versioning/brancher.d.ts +17 -0
  292. package/dist/engine/spec-versioning/brancher.d.ts.map +1 -0
  293. package/dist/engine/spec-versioning/brancher.js +113 -0
  294. package/dist/engine/spec-versioning/brancher.js.map +1 -0
  295. package/dist/engine/spec-versioning/differ.d.ts +19 -0
  296. package/dist/engine/spec-versioning/differ.d.ts.map +1 -0
  297. package/dist/engine/spec-versioning/differ.js +151 -0
  298. package/dist/engine/spec-versioning/differ.js.map +1 -0
  299. package/dist/engine/spec-versioning/index.d.ts +5 -0
  300. package/dist/engine/spec-versioning/index.d.ts.map +1 -0
  301. package/dist/engine/spec-versioning/index.js +6 -0
  302. package/dist/engine/spec-versioning/index.js.map +1 -0
  303. package/dist/engine/spec-versioning/merger.d.ts +18 -0
  304. package/dist/engine/spec-versioning/merger.d.ts.map +1 -0
  305. package/dist/engine/spec-versioning/merger.js +113 -0
  306. package/dist/engine/spec-versioning/merger.js.map +1 -0
  307. package/dist/engine/spec-versioning/version-store.d.ts +18 -0
  308. package/dist/engine/spec-versioning/version-store.d.ts.map +1 -0
  309. package/dist/engine/spec-versioning/version-store.js +96 -0
  310. package/dist/engine/spec-versioning/version-store.js.map +1 -0
  311. package/dist/engine/well-known/discovery.d.ts +7 -0
  312. package/dist/engine/well-known/discovery.d.ts.map +1 -0
  313. package/dist/engine/well-known/discovery.js +109 -0
  314. package/dist/engine/well-known/discovery.js.map +1 -0
  315. package/dist/engine/well-known/index.d.ts +6 -0
  316. package/dist/engine/well-known/index.d.ts.map +1 -0
  317. package/dist/engine/well-known/index.js +5 -0
  318. package/dist/engine/well-known/index.js.map +1 -0
  319. package/dist/engine/well-known/manifest-generator.d.ts +7 -0
  320. package/dist/engine/well-known/manifest-generator.d.ts.map +1 -0
  321. package/dist/engine/well-known/manifest-generator.js +60 -0
  322. package/dist/engine/well-known/manifest-generator.js.map +1 -0
  323. package/dist/engine/well-known/manifest-schema.d.ts +92 -0
  324. package/dist/engine/well-known/manifest-schema.d.ts.map +1 -0
  325. package/dist/engine/well-known/manifest-schema.js +70 -0
  326. package/dist/engine/well-known/manifest-schema.js.map +1 -0
  327. package/dist/resources/spec-granular.d.ts +33 -0
  328. package/dist/resources/spec-granular.d.ts.map +1 -0
  329. package/dist/resources/spec-granular.js +299 -0
  330. package/dist/resources/spec-granular.js.map +1 -0
  331. package/dist/storage/federation-store.d.ts +29 -0
  332. package/dist/storage/federation-store.d.ts.map +1 -0
  333. package/dist/storage/federation-store.js +111 -0
  334. package/dist/storage/federation-store.js.map +1 -0
  335. package/dist/storage/index.d.ts +3 -0
  336. package/dist/storage/index.d.ts.map +1 -1
  337. package/dist/storage/index.js +3 -0
  338. package/dist/storage/index.js.map +1 -1
  339. package/dist/storage/rbac-store.d.ts +8 -0
  340. package/dist/storage/rbac-store.d.ts.map +1 -0
  341. package/dist/storage/rbac-store.js +75 -0
  342. package/dist/storage/rbac-store.js.map +1 -0
  343. package/dist/storage/spec-observability-store.d.ts +16 -0
  344. package/dist/storage/spec-observability-store.d.ts.map +1 -0
  345. package/dist/storage/spec-observability-store.js +55 -0
  346. package/dist/storage/spec-observability-store.js.map +1 -0
  347. package/dist/tools/a2a-handler.d.ts +14 -0
  348. package/dist/tools/a2a-handler.d.ts.map +1 -0
  349. package/dist/tools/a2a-handler.js +100 -0
  350. package/dist/tools/a2a-handler.js.map +1 -0
  351. package/dist/tools/assign-role-handler.d.ts +3 -0
  352. package/dist/tools/assign-role-handler.d.ts.map +1 -0
  353. package/dist/tools/assign-role-handler.js +25 -0
  354. package/dist/tools/assign-role-handler.js.map +1 -0
  355. package/dist/tools/audit-trail-handler.d.ts +4 -0
  356. package/dist/tools/audit-trail-handler.d.ts.map +1 -0
  357. package/dist/tools/audit-trail-handler.js +91 -0
  358. package/dist/tools/audit-trail-handler.js.map +1 -0
  359. package/dist/tools/auto-update-spec.d.ts +3 -0
  360. package/dist/tools/auto-update-spec.d.ts.map +1 -0
  361. package/dist/tools/auto-update-spec.js +43 -0
  362. package/dist/tools/auto-update-spec.js.map +1 -0
  363. package/dist/tools/branch-spec.d.ts +3 -0
  364. package/dist/tools/branch-spec.d.ts.map +1 -0
  365. package/dist/tools/branch-spec.js +68 -0
  366. package/dist/tools/branch-spec.js.map +1 -0
  367. package/dist/tools/configure-auth-handler.d.ts +15 -0
  368. package/dist/tools/configure-auth-handler.d.ts.map +1 -0
  369. package/dist/tools/configure-auth-handler.js +113 -0
  370. package/dist/tools/configure-auth-handler.js.map +1 -0
  371. package/dist/tools/configure-observability.d.ts +14 -0
  372. package/dist/tools/configure-observability.d.ts.map +1 -0
  373. package/dist/tools/configure-observability.js +96 -0
  374. package/dist/tools/configure-observability.js.map +1 -0
  375. package/dist/tools/configure-roles-handler.d.ts +4 -0
  376. package/dist/tools/configure-roles-handler.d.ts.map +1 -0
  377. package/dist/tools/configure-roles-handler.js +36 -0
  378. package/dist/tools/configure-roles-handler.js.map +1 -0
  379. package/dist/tools/create-spec-hu/ac-adapters/architecture-adapter.d.ts +7 -0
  380. package/dist/tools/create-spec-hu/ac-adapters/architecture-adapter.d.ts.map +1 -0
  381. package/dist/tools/create-spec-hu/ac-adapters/architecture-adapter.js +114 -0
  382. package/dist/tools/create-spec-hu/ac-adapters/architecture-adapter.js.map +1 -0
  383. package/dist/tools/create-spec-hu/ac-adapters/database-adapter.d.ts +7 -0
  384. package/dist/tools/create-spec-hu/ac-adapters/database-adapter.d.ts.map +1 -0
  385. package/dist/tools/create-spec-hu/ac-adapters/database-adapter.js +48 -0
  386. package/dist/tools/create-spec-hu/ac-adapters/database-adapter.js.map +1 -0
  387. package/dist/tools/create-spec-hu/ac-adapters/index.d.ts +14 -0
  388. package/dist/tools/create-spec-hu/ac-adapters/index.d.ts.map +1 -0
  389. package/dist/tools/create-spec-hu/ac-adapters/index.js +28 -0
  390. package/dist/tools/create-spec-hu/ac-adapters/index.js.map +1 -0
  391. package/dist/tools/create-spec-hu/ac-adapters/stack-adapter.d.ts +7 -0
  392. package/dist/tools/create-spec-hu/ac-adapters/stack-adapter.d.ts.map +1 -0
  393. package/dist/tools/create-spec-hu/ac-adapters/stack-adapter.js +99 -0
  394. package/dist/tools/create-spec-hu/ac-adapters/stack-adapter.js.map +1 -0
  395. package/dist/tools/create-spec-hu/ac-adapters/testing-adapter.d.ts +7 -0
  396. package/dist/tools/create-spec-hu/ac-adapters/testing-adapter.d.ts.map +1 -0
  397. package/dist/tools/create-spec-hu/ac-adapters/testing-adapter.js +62 -0
  398. package/dist/tools/create-spec-hu/ac-adapters/testing-adapter.js.map +1 -0
  399. package/dist/tools/create-spec-hu/hu-body-generators.d.ts.map +1 -1
  400. package/dist/tools/create-spec-hu/hu-body-generators.js +41 -19
  401. package/dist/tools/create-spec-hu/hu-body-generators.js.map +1 -1
  402. package/dist/tools/create-spec-tech/ficha-content.d.ts.map +1 -1
  403. package/dist/tools/create-spec-tech/ficha-content.js +235 -5
  404. package/dist/tools/create-spec-tech/ficha-content.js.map +1 -1
  405. package/dist/tools/decompose-spec.d.ts +7 -0
  406. package/dist/tools/decompose-spec.d.ts.map +1 -0
  407. package/dist/tools/decompose-spec.js +49 -0
  408. package/dist/tools/decompose-spec.js.map +1 -0
  409. package/dist/tools/design-to-spec.d.ts +12 -0
  410. package/dist/tools/design-to-spec.d.ts.map +1 -0
  411. package/dist/tools/design-to-spec.js +73 -0
  412. package/dist/tools/design-to-spec.js.map +1 -0
  413. package/dist/tools/detect-ac-gaps.d.ts +7 -0
  414. package/dist/tools/detect-ac-gaps.d.ts.map +1 -0
  415. package/dist/tools/detect-ac-gaps.js +63 -0
  416. package/dist/tools/detect-ac-gaps.js.map +1 -0
  417. package/dist/tools/discover-registry.d.ts +8 -0
  418. package/dist/tools/discover-registry.d.ts.map +1 -0
  419. package/dist/tools/discover-registry.js +79 -0
  420. package/dist/tools/discover-registry.js.map +1 -0
  421. package/dist/tools/federate-specs.d.ts +6 -0
  422. package/dist/tools/federate-specs.d.ts.map +1 -0
  423. package/dist/tools/federate-specs.js +41 -0
  424. package/dist/tools/federate-specs.js.map +1 -0
  425. package/dist/tools/federation-status.d.ts +6 -0
  426. package/dist/tools/federation-status.d.ts.map +1 -0
  427. package/dist/tools/federation-status.js +56 -0
  428. package/dist/tools/federation-status.js.map +1 -0
  429. package/dist/tools/generate-annotations.d.ts.map +1 -1
  430. package/dist/tools/generate-annotations.js +3 -1
  431. package/dist/tools/generate-annotations.js.map +1 -1
  432. package/dist/tools/generate-infrastructure.d.ts +3 -0
  433. package/dist/tools/generate-infrastructure.d.ts.map +1 -0
  434. package/dist/tools/generate-infrastructure.js +60 -0
  435. package/dist/tools/generate-infrastructure.js.map +1 -0
  436. package/dist/tools/merge-spec-branch.d.ts +3 -0
  437. package/dist/tools/merge-spec-branch.d.ts.map +1 -0
  438. package/dist/tools/merge-spec-branch.js +103 -0
  439. package/dist/tools/merge-spec-branch.js.map +1 -0
  440. package/dist/tools/publish-registry.d.ts +8 -0
  441. package/dist/tools/publish-registry.d.ts.map +1 -0
  442. package/dist/tools/publish-registry.js +76 -0
  443. package/dist/tools/publish-registry.js.map +1 -0
  444. package/dist/tools/register-a2a-tools.d.ts +3 -0
  445. package/dist/tools/register-a2a-tools.d.ts.map +1 -0
  446. package/dist/tools/register-a2a-tools.js +66 -0
  447. package/dist/tools/register-a2a-tools.js.map +1 -0
  448. package/dist/tools/register-audit-trail-tools.d.ts +3 -0
  449. package/dist/tools/register-audit-trail-tools.d.ts.map +1 -0
  450. package/dist/tools/register-audit-trail-tools.js +62 -0
  451. package/dist/tools/register-audit-trail-tools.js.map +1 -0
  452. package/dist/tools/register-decompose-tools.d.ts +3 -0
  453. package/dist/tools/register-decompose-tools.d.ts.map +1 -0
  454. package/dist/tools/register-decompose-tools.js +31 -0
  455. package/dist/tools/register-decompose-tools.js.map +1 -0
  456. package/dist/tools/register-federation-tools.d.ts +6 -0
  457. package/dist/tools/register-federation-tools.d.ts.map +1 -0
  458. package/dist/tools/register-federation-tools.js +48 -0
  459. package/dist/tools/register-federation-tools.js.map +1 -0
  460. package/dist/tools/register-infrastructure-tools.d.ts +3 -0
  461. package/dist/tools/register-infrastructure-tools.d.ts.map +1 -0
  462. package/dist/tools/register-infrastructure-tools.js +34 -0
  463. package/dist/tools/register-infrastructure-tools.js.map +1 -0
  464. package/dist/tools/register-living-spec-tools.d.ts.map +1 -1
  465. package/dist/tools/register-living-spec-tools.js +2 -8
  466. package/dist/tools/register-living-spec-tools.js.map +1 -1
  467. package/dist/tools/register-observability-tools.d.ts +3 -0
  468. package/dist/tools/register-observability-tools.d.ts.map +1 -0
  469. package/dist/tools/register-observability-tools.js +48 -0
  470. package/dist/tools/register-observability-tools.js.map +1 -0
  471. package/dist/tools/register-rbac-tools.d.ts +3 -0
  472. package/dist/tools/register-rbac-tools.d.ts.map +1 -0
  473. package/dist/tools/register-rbac-tools.js +36 -0
  474. package/dist/tools/register-rbac-tools.js.map +1 -0
  475. package/dist/tools/register-spec-observability-tools.d.ts +3 -0
  476. package/dist/tools/register-spec-observability-tools.d.ts.map +1 -0
  477. package/dist/tools/register-spec-observability-tools.js +24 -0
  478. package/dist/tools/register-spec-observability-tools.js.map +1 -0
  479. package/dist/tools/register-versioning-tools.d.ts +3 -0
  480. package/dist/tools/register-versioning-tools.d.ts.map +1 -0
  481. package/dist/tools/register-versioning-tools.js +93 -0
  482. package/dist/tools/register-versioning-tools.js.map +1 -0
  483. package/dist/tools/register-well-known-tools.d.ts +3 -0
  484. package/dist/tools/register-well-known-tools.d.ts.map +1 -0
  485. package/dist/tools/register-well-known-tools.js +36 -0
  486. package/dist/tools/register-well-known-tools.js.map +1 -0
  487. package/dist/tools/repair-spec.d.ts +9 -0
  488. package/dist/tools/repair-spec.d.ts.map +1 -0
  489. package/dist/tools/repair-spec.js +93 -0
  490. package/dist/tools/repair-spec.js.map +1 -0
  491. package/dist/tools/resolve-spec-conflict.d.ts +7 -0
  492. package/dist/tools/resolve-spec-conflict.d.ts.map +1 -0
  493. package/dist/tools/resolve-spec-conflict.js +63 -0
  494. package/dist/tools/resolve-spec-conflict.js.map +1 -0
  495. package/dist/tools/response-helpers.d.ts +42 -0
  496. package/dist/tools/response-helpers.d.ts.map +1 -1
  497. package/dist/tools/response-helpers.js +29 -0
  498. package/dist/tools/response-helpers.js.map +1 -1
  499. package/dist/tools/schemas/auth-schema.d.ts +12 -0
  500. package/dist/tools/schemas/auth-schema.d.ts.map +1 -0
  501. package/dist/tools/schemas/auth-schema.js +38 -0
  502. package/dist/tools/schemas/auth-schema.js.map +1 -0
  503. package/dist/tools/schemas/rbac.d.ts +26 -0
  504. package/dist/tools/schemas/rbac.d.ts.map +1 -0
  505. package/dist/tools/schemas/rbac.js +25 -0
  506. package/dist/tools/schemas/rbac.js.map +1 -0
  507. package/dist/tools/schemas/well-known.d.ts +12 -0
  508. package/dist/tools/schemas/well-known.d.ts.map +1 -0
  509. package/dist/tools/schemas/well-known.js +31 -0
  510. package/dist/tools/schemas/well-known.js.map +1 -0
  511. package/dist/tools/snapshot-spec-hashes.d.ts.map +1 -1
  512. package/dist/tools/snapshot-spec-hashes.js.map +1 -1
  513. package/dist/tools/spec-usage-report.d.ts +3 -0
  514. package/dist/tools/spec-usage-report.d.ts.map +1 -0
  515. package/dist/tools/spec-usage-report.js +95 -0
  516. package/dist/tools/spec-usage-report.js.map +1 -0
  517. package/dist/tools/start-hooks.d.ts.map +1 -1
  518. package/dist/tools/start-hooks.js +93 -16
  519. package/dist/tools/start-hooks.js.map +1 -1
  520. package/dist/tools/version-spec.d.ts +3 -0
  521. package/dist/tools/version-spec.d.ts.map +1 -0
  522. package/dist/tools/version-spec.js +54 -0
  523. package/dist/tools/version-spec.js.map +1 -0
  524. package/dist/types/a2a.d.ts +125 -0
  525. package/dist/types/a2a.d.ts.map +1 -0
  526. package/dist/types/a2a.js +3 -0
  527. package/dist/types/a2a.js.map +1 -0
  528. package/dist/types/ac-gap.d.ts +57 -0
  529. package/dist/types/ac-gap.d.ts.map +1 -0
  530. package/dist/types/ac-gap.js +3 -0
  531. package/dist/types/ac-gap.js.map +1 -0
  532. package/dist/types/audit-trail.d.ts +77 -0
  533. package/dist/types/audit-trail.d.ts.map +1 -0
  534. package/dist/types/audit-trail.js +3 -0
  535. package/dist/types/audit-trail.js.map +1 -0
  536. package/dist/types/auth.d.ts +82 -0
  537. package/dist/types/auth.d.ts.map +1 -0
  538. package/dist/types/auth.js +3 -0
  539. package/dist/types/auth.js.map +1 -0
  540. package/dist/types/ci.d.ts +10 -25
  541. package/dist/types/ci.d.ts.map +1 -1
  542. package/dist/types/design-to-spec.d.ts +89 -0
  543. package/dist/types/design-to-spec.d.ts.map +1 -0
  544. package/dist/types/design-to-spec.js +3 -0
  545. package/dist/types/design-to-spec.js.map +1 -0
  546. package/dist/types/elicitation.d.ts +109 -0
  547. package/dist/types/elicitation.d.ts.map +1 -0
  548. package/dist/types/elicitation.js +3 -0
  549. package/dist/types/elicitation.js.map +1 -0
  550. package/dist/types/federation.d.ts +95 -0
  551. package/dist/types/federation.d.ts.map +1 -0
  552. package/dist/types/federation.js +3 -0
  553. package/dist/types/federation.js.map +1 -0
  554. package/dist/types/file-hooks.d.ts +8 -6
  555. package/dist/types/file-hooks.d.ts.map +1 -1
  556. package/dist/types/github.d.ts +17 -0
  557. package/dist/types/github.d.ts.map +1 -1
  558. package/dist/types/index.d.ts +16 -0
  559. package/dist/types/index.d.ts.map +1 -1
  560. package/dist/types/index.js +16 -0
  561. package/dist/types/index.js.map +1 -1
  562. package/dist/types/infrastructure.d.ts +71 -0
  563. package/dist/types/infrastructure.d.ts.map +1 -0
  564. package/dist/types/infrastructure.js +3 -0
  565. package/dist/types/infrastructure.js.map +1 -0
  566. package/dist/types/living-spec.d.ts +100 -0
  567. package/dist/types/living-spec.d.ts.map +1 -1
  568. package/dist/types/observability.d.ts +105 -0
  569. package/dist/types/observability.d.ts.map +1 -0
  570. package/dist/types/observability.js +3 -0
  571. package/dist/types/observability.js.map +1 -0
  572. package/dist/types/rbac.d.ts +51 -0
  573. package/dist/types/rbac.d.ts.map +1 -0
  574. package/dist/types/rbac.js +4 -0
  575. package/dist/types/rbac.js.map +1 -0
  576. package/dist/types/resources.d.ts +20 -0
  577. package/dist/types/resources.d.ts.map +1 -0
  578. package/dist/types/resources.js +3 -0
  579. package/dist/types/resources.js.map +1 -0
  580. package/dist/types/spec/repair.d.ts +33 -0
  581. package/dist/types/spec/repair.d.ts.map +1 -0
  582. package/dist/types/spec/repair.js +3 -0
  583. package/dist/types/spec/repair.js.map +1 -0
  584. package/dist/types/spec-decomposer.d.ts +108 -0
  585. package/dist/types/spec-decomposer.d.ts.map +1 -0
  586. package/dist/types/spec-decomposer.js +4 -0
  587. package/dist/types/spec-decomposer.js.map +1 -0
  588. package/dist/types/spec-observability.d.ts +71 -0
  589. package/dist/types/spec-observability.d.ts.map +1 -0
  590. package/dist/types/spec-observability.js +4 -0
  591. package/dist/types/spec-observability.js.map +1 -0
  592. package/dist/types/spec-versioning.d.ts +117 -0
  593. package/dist/types/spec-versioning.d.ts.map +1 -0
  594. package/dist/types/spec-versioning.js +3 -0
  595. package/dist/types/spec-versioning.js.map +1 -0
  596. package/dist/types/well-known.d.ts +70 -0
  597. package/dist/types/well-known.d.ts.map +1 -0
  598. package/dist/types/well-known.js +3 -0
  599. package/dist/types/well-known.js.map +1 -0
  600. package/package.json +1 -1
  601. package/src/config/license-plans.json +16 -1
@@ -0,0 +1,263 @@
1
+ // engine/spec-decomposer/analyzer.ts — Analyze spec content into work units (SPEC-157)
2
+ // Reads spec.md acceptance criteria and technical.md file lists, then groups
3
+ // criteria into independent work units suitable for parallel agent execution.
4
+ import { readFile } from 'node:fs/promises';
5
+ import { extractAcceptanceCriteria } from '../shared/ac-extractor.js';
6
+ // ---------------------------------------------------------------------------
7
+ // Criterion classification
8
+ // ---------------------------------------------------------------------------
9
+ /** Keywords that suggest architecture/planning work → opus. */
10
+ const OPUS_KEYWORDS = [
11
+ 'architect',
12
+ 'design',
13
+ 'schema',
14
+ 'interface',
15
+ 'type',
16
+ 'pattern',
17
+ 'structure',
18
+ 'strategy',
19
+ 'dependency',
20
+ 'integration',
21
+ ];
22
+ /** Keywords that suggest read-only or search work → haiku. */
23
+ const HAIKU_KEYWORDS = [
24
+ 'list',
25
+ 'read',
26
+ 'search',
27
+ 'find',
28
+ 'query',
29
+ 'display',
30
+ 'show',
31
+ 'report',
32
+ 'summary',
33
+ 'status',
34
+ ];
35
+ function classifyModel(text) {
36
+ const lower = text.toLowerCase();
37
+ if (OPUS_KEYWORDS.some((kw) => lower.includes(kw))) {
38
+ return 'opus';
39
+ }
40
+ if (HAIKU_KEYWORDS.some((kw) => lower.includes(kw))) {
41
+ return 'haiku';
42
+ }
43
+ return 'sonnet';
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // File path extraction helpers
47
+ // ---------------------------------------------------------------------------
48
+ const FILE_PATTERN = /`((?:src|tests)\/[^`]+\.(?:ts|js|tsx|jsx))`/g;
49
+ const MD_FILE_PATTERN = /^\s*[-*]\s+`?((?:src|tests)\/[\w./-]+\.(?:ts|js|tsx|jsx))`?/gm;
50
+ const SECTION_PATTERN = /^#{2,4}\s+(.+)$/gm;
51
+ function extractFilesFromText(text) {
52
+ const files = new Set();
53
+ let match;
54
+ const pattern1 = new RegExp(FILE_PATTERN.source, 'g');
55
+ while ((match = pattern1.exec(text)) !== null) {
56
+ if (match[1]) {
57
+ files.add(match[1]);
58
+ }
59
+ }
60
+ const pattern2 = new RegExp(MD_FILE_PATTERN.source, 'gm');
61
+ while ((match = pattern2.exec(text)) !== null) {
62
+ if (match[1]) {
63
+ files.add(match[1]);
64
+ }
65
+ }
66
+ return [...files];
67
+ }
68
+ // ---------------------------------------------------------------------------
69
+ // Spec content parsers
70
+ // ---------------------------------------------------------------------------
71
+ /** Extract acceptance criteria lines from spec.md content. */
72
+ export function extractCriteriaFromContent(content) {
73
+ return extractAcceptanceCriteria(content);
74
+ }
75
+ /** Extract all file paths mentioned in technical.md content. */
76
+ export function extractFilesFromTechnical(content) {
77
+ return extractFilesFromText(content);
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Work unit grouping heuristics
81
+ // ---------------------------------------------------------------------------
82
+ /**
83
+ * Categories used to cluster criteria into work units.
84
+ * Each entry has a label and keywords that identify it.
85
+ */
86
+ const CATEGORY_RULES = [
87
+ {
88
+ id: 'types',
89
+ title: 'Types and interfaces',
90
+ keywords: ['type', 'interface', 'schema', 'model', 'struct'],
91
+ },
92
+ {
93
+ id: 'engine',
94
+ title: 'Engine / business logic',
95
+ keywords: ['engine', 'logic', 'algorithm', 'process', 'compute', 'analyze', 'detect'],
96
+ },
97
+ {
98
+ id: 'storage',
99
+ title: 'Storage / persistence',
100
+ keywords: ['storage', 'store', 'persist', 'save', 'load', 'database', 'file', 'read', 'write'],
101
+ },
102
+ {
103
+ id: 'tool',
104
+ title: 'MCP tool / handler',
105
+ keywords: ['tool', 'handler', 'endpoint', 'api', 'register', 'input', 'output'],
106
+ },
107
+ {
108
+ id: 'tests',
109
+ title: 'Tests',
110
+ keywords: ['test', 'spec', 'unit', 'coverage', 'mock', 'fixture', 'assert'],
111
+ },
112
+ ];
113
+ function categorize(criterion) {
114
+ const lower = criterion.toLowerCase();
115
+ for (const rule of CATEGORY_RULES) {
116
+ if (rule.keywords.some((kw) => lower.includes(kw))) {
117
+ return rule.id;
118
+ }
119
+ }
120
+ return 'general';
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Public API
124
+ // ---------------------------------------------------------------------------
125
+ /** Read spec.md file and return its content, or empty string on error. */
126
+ async function safeReadFile(filePath) {
127
+ try {
128
+ return await readFile(filePath, 'utf-8');
129
+ /* v8 ignore next 3 */
130
+ }
131
+ catch {
132
+ return '';
133
+ }
134
+ }
135
+ /**
136
+ * Analyze spec content from disk and produce raw work units.
137
+ * Groups acceptance criteria by category heuristics.
138
+ */
139
+ export async function analyzeSpec(specPath, technicalPath, maxTasks) {
140
+ const [specContent, techContent] = await Promise.all([
141
+ safeReadFile(specPath),
142
+ safeReadFile(technicalPath),
143
+ ]);
144
+ const criteria = extractCriteriaFromContent(specContent);
145
+ const allFiles = extractFilesFromTechnical(techContent);
146
+ return groupCriteriaIntoUnits(criteria, allFiles, maxTasks);
147
+ }
148
+ /**
149
+ * Group criteria lines into work units, respecting maxTasks limit.
150
+ * Exported for unit-testing without touching the filesystem.
151
+ */
152
+ export function groupCriteriaIntoUnits(criteria, allFiles, maxTasks) {
153
+ if (criteria.length === 0) {
154
+ // Generate a single fallback unit so orchestration always has something to run
155
+ return [
156
+ {
157
+ id: 'unit-general',
158
+ title: 'General implementation',
159
+ criteria: [],
160
+ suggestedFiles: allFiles,
161
+ recommendedModel: 'sonnet',
162
+ estimatedHours: 4,
163
+ },
164
+ ];
165
+ }
166
+ // Bucket criteria by category
167
+ const buckets = new Map();
168
+ for (const criterion of criteria) {
169
+ const cat = categorize(criterion);
170
+ const existing = buckets.get(cat) ?? [];
171
+ existing.push(criterion);
172
+ buckets.set(cat, existing);
173
+ }
174
+ // Assign files by rough path matching per category
175
+ const filesByCategory = buildFileCategoryMap(allFiles);
176
+ const units = [];
177
+ for (const entry of buckets.entries()) {
178
+ const catId = entry[0];
179
+ const catCriteria = entry[1];
180
+ const categoryInfo = CATEGORY_RULES.find((r) => r.id === catId) ?? {
181
+ id: catId,
182
+ title: catId,
183
+ };
184
+ const suggestedFiles = filesByCategory.get(catId) ?? [];
185
+ const combinedText = catCriteria.join(' ');
186
+ const model = classifyModel(combinedText);
187
+ const hours = Math.max(1, Math.ceil(catCriteria.length * 1.5));
188
+ units.push({
189
+ id: `unit-${catId}`,
190
+ title: categoryInfo.title,
191
+ criteria: catCriteria,
192
+ suggestedFiles,
193
+ recommendedModel: model,
194
+ estimatedHours: hours,
195
+ });
196
+ }
197
+ // If fewer than 2 units were produced, add uncategorized files to general
198
+ if (units.length === 0) {
199
+ units.push({
200
+ id: 'unit-general',
201
+ title: 'General implementation',
202
+ criteria,
203
+ suggestedFiles: allFiles,
204
+ recommendedModel: 'sonnet',
205
+ estimatedHours: Math.max(2, criteria.length * 1.5),
206
+ });
207
+ }
208
+ // Enforce maxTasks by merging excess units into the last one
209
+ return mergeExcessUnits(units, maxTasks);
210
+ }
211
+ /** Map file paths to category IDs based on path segments. */
212
+ function buildFileCategoryMap(files) {
213
+ const map = new Map();
214
+ for (const file of files) {
215
+ const lower = file.toLowerCase();
216
+ let assigned = false;
217
+ for (const rule of CATEGORY_RULES) {
218
+ if (rule.keywords.some((kw) => lower.includes(kw))) {
219
+ const existing = map.get(rule.id) ?? [];
220
+ existing.push(file);
221
+ map.set(rule.id, existing);
222
+ assigned = true;
223
+ break;
224
+ }
225
+ }
226
+ if (!assigned) {
227
+ const existing = map.get('general') ?? [];
228
+ existing.push(file);
229
+ map.set('general', existing);
230
+ }
231
+ }
232
+ return map;
233
+ }
234
+ /** Merge units beyond maxTasks into the last retained unit. */
235
+ function mergeExcessUnits(units, maxTasks) {
236
+ if (units.length <= maxTasks) {
237
+ return units;
238
+ }
239
+ const retained = units.slice(0, maxTasks - 1);
240
+ const overflow = units.slice(maxTasks - 1);
241
+ const merged = {
242
+ id: 'unit-general',
243
+ title: 'Combined implementation',
244
+ criteria: overflow.flatMap((u) => u.criteria),
245
+ suggestedFiles: [...new Set(overflow.flatMap((u) => u.suggestedFiles))],
246
+ recommendedModel: 'sonnet',
247
+ estimatedHours: overflow.reduce((acc, u) => acc + u.estimatedHours, 0),
248
+ };
249
+ return [...retained, merged];
250
+ }
251
+ /** Extract section headers from markdown content (used by file-mapper). */
252
+ export function extractSectionHeaders(content) {
253
+ const headers = [];
254
+ let match;
255
+ const pattern = new RegExp(SECTION_PATTERN.source, 'gm');
256
+ while ((match = pattern.exec(content)) !== null) {
257
+ if (match[1]) {
258
+ headers.push(match[1].trim());
259
+ }
260
+ }
261
+ return headers;
262
+ }
263
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { WorkUnit, MappedUnit } from '../../types/spec-decomposer.js';
2
+ /**
3
+ * Map work units to concrete file paths.
4
+ *
5
+ * Strategy:
6
+ * 1. Each unit starts with its suggestedFiles (from analyzer).
7
+ * 2. For remaining files in allFiles not yet assigned, we use path-hint scoring
8
+ * to assign them to the best-matching unit.
9
+ * 3. Files with score 0 for all units are distributed to the last unit (fallback).
10
+ */
11
+ export declare function mapUnitsToFiles(units: WorkUnit[], allFiles: string[]): MappedUnit[];
12
+ /**
13
+ * De-duplicate files within each mapped unit and ensure uniqueness.
14
+ * Called after mapUnitsToFiles() as a clean-up step.
15
+ */
16
+ export declare function deduplicateMappedFiles(units: MappedUnit[]): MappedUnit[];
17
+ //# sourceMappingURL=file-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-mapper.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/file-mapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAwC3E;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CA+CnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAKxE"}
@@ -0,0 +1,96 @@
1
+ // engine/spec-decomposer/file-mapper.ts — Map work units to specific files (SPEC-157)
2
+ // Given work units and a full list of project files, assigns concrete file paths
3
+ // to each unit based on path segment heuristics.
4
+ // ---------------------------------------------------------------------------
5
+ // Path segment heuristics
6
+ // ---------------------------------------------------------------------------
7
+ /** Map unit IDs to path segment patterns that indicate file relevance. */
8
+ const UNIT_PATH_HINTS = {
9
+ types: ['types/', '/types.ts', 'type.ts'],
10
+ engine: ['engine/', 'analyzer', 'calculator', 'processor', 'resolver', 'detector'],
11
+ storage: ['storage/', 'store.ts', '-store.ts', 'repository', 'persistence'],
12
+ tool: ['tools/', 'handler.ts', 'register-'],
13
+ tests: ['tests/', '.test.ts', '.spec.ts'],
14
+ general: [],
15
+ };
16
+ /**
17
+ * Score how relevant a file path is for a given unit ID.
18
+ * Returns 0 for irrelevant, higher values for stronger matches.
19
+ */
20
+ function scoreFilePath(filePath, unitId) {
21
+ const lower = filePath.toLowerCase();
22
+ const categoryId = unitId.replace(/^unit-/, '');
23
+ const hints = UNIT_PATH_HINTS[categoryId] ?? UNIT_PATH_HINTS.general ?? [];
24
+ let score = 0;
25
+ for (const hint of hints) {
26
+ if (lower.includes(hint)) {
27
+ score += 2;
28
+ }
29
+ }
30
+ // Bonus: file path contains a keyword from the unit's criteria (caller may inject)
31
+ return score;
32
+ }
33
+ // ---------------------------------------------------------------------------
34
+ // Public API
35
+ // ---------------------------------------------------------------------------
36
+ /**
37
+ * Map work units to concrete file paths.
38
+ *
39
+ * Strategy:
40
+ * 1. Each unit starts with its suggestedFiles (from analyzer).
41
+ * 2. For remaining files in allFiles not yet assigned, we use path-hint scoring
42
+ * to assign them to the best-matching unit.
43
+ * 3. Files with score 0 for all units are distributed to the last unit (fallback).
44
+ */
45
+ export function mapUnitsToFiles(units, allFiles) {
46
+ if (units.length === 0) {
47
+ return [];
48
+ }
49
+ // Seed each mapped unit with its suggestedFiles
50
+ const mapped = units.map((u) => ({
51
+ id: u.id,
52
+ title: u.title,
53
+ criteria: u.criteria,
54
+ files: [...u.suggestedFiles],
55
+ recommendedModel: u.recommendedModel,
56
+ estimatedHours: u.estimatedHours,
57
+ }));
58
+ // Track which files are already covered
59
+ const assignedFiles = new Set(units.flatMap((u) => u.suggestedFiles));
60
+ // Assign remaining files to best-matching unit
61
+ for (const file of allFiles) {
62
+ if (assignedFiles.has(file)) {
63
+ continue;
64
+ }
65
+ let bestUnitIndex = mapped.length - 1; // fallback: last unit
66
+ let bestScore = -1;
67
+ for (let i = 0; i < mapped.length; i++) {
68
+ const unit = mapped[i];
69
+ if (!unit) {
70
+ continue;
71
+ }
72
+ const score = scoreFilePath(file, unit.id);
73
+ if (score > bestScore) {
74
+ bestScore = score;
75
+ bestUnitIndex = i;
76
+ }
77
+ }
78
+ const target = mapped[bestUnitIndex];
79
+ if (target && !target.files.includes(file)) {
80
+ target.files.push(file);
81
+ assignedFiles.add(file);
82
+ }
83
+ }
84
+ return mapped;
85
+ }
86
+ /**
87
+ * De-duplicate files within each mapped unit and ensure uniqueness.
88
+ * Called after mapUnitsToFiles() as a clean-up step.
89
+ */
90
+ export function deduplicateMappedFiles(units) {
91
+ return units.map((unit) => ({
92
+ ...unit,
93
+ files: [...new Set(unit.files)],
94
+ }));
95
+ }
96
+ //# sourceMappingURL=file-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-mapper.js","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/file-mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export { analyzeSpec, groupCriteriaIntoUnits, extractCriteriaFromContent, extractFilesFromTechnical, } from './analyzer.js';
2
+ export { mapUnitsToFiles, deduplicateMappedFiles } from './file-mapper.js';
3
+ export { resolveFileOwnership } from './ownership-resolver.js';
4
+ import type { SpecDecomposeResult } from '../../types/spec-decomposer.js';
5
+ /**
6
+ * Main entry point: decompose a spec into parallelizable agent tasks.
7
+ *
8
+ * @param specPath Absolute path to the spec's spec.md file.
9
+ * @param technicalPath Absolute path to the spec's technical.md file.
10
+ * @param specId Spec identifier (e.g. "SPEC-042").
11
+ * @param maxTasks Maximum number of tasks to generate (default: 5).
12
+ */
13
+ export declare function decomposeSpec(specPath: string, technicalPath: string, specId: string, maxTasks?: number): Promise<SpecDecomposeResult>;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAK/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAK1E;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAA0B,GACnC,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
@@ -0,0 +1,50 @@
1
+ // engine/spec-decomposer/index.ts — Barrel export + main decomposeSpec() (SPEC-157)
2
+ export { analyzeSpec, groupCriteriaIntoUnits, extractCriteriaFromContent, extractFilesFromTechnical, } from './analyzer.js';
3
+ export { mapUnitsToFiles, deduplicateMappedFiles } from './file-mapper.js';
4
+ export { resolveFileOwnership } from './ownership-resolver.js';
5
+ import { analyzeSpec } from './analyzer.js';
6
+ import { mapUnitsToFiles, deduplicateMappedFiles } from './file-mapper.js';
7
+ import { resolveFileOwnership } from './ownership-resolver.js';
8
+ /** Default maximum number of agent tasks to generate. */
9
+ const DEFAULT_MAX_TASKS = 5;
10
+ /**
11
+ * Main entry point: decompose a spec into parallelizable agent tasks.
12
+ *
13
+ * @param specPath Absolute path to the spec's spec.md file.
14
+ * @param technicalPath Absolute path to the spec's technical.md file.
15
+ * @param specId Spec identifier (e.g. "SPEC-042").
16
+ * @param maxTasks Maximum number of tasks to generate (default: 5).
17
+ */
18
+ export async function decomposeSpec(specPath, technicalPath, specId, maxTasks = DEFAULT_MAX_TASKS) {
19
+ const clampedMax = Math.max(1, Math.min(maxTasks, 20));
20
+ // Step 1: Analyze spec content → raw work units
21
+ const workUnits = await analyzeSpec(specPath, technicalPath, clampedMax);
22
+ // Step 2: Map each work unit to concrete file paths
23
+ const allFiles = workUnits.flatMap((u) => u.suggestedFiles);
24
+ const rawMapped = mapUnitsToFiles(workUnits, allFiles);
25
+ const mapped = deduplicateMappedFiles(rawMapped);
26
+ // Step 3: Resolve file ownership conflicts + build tasks
27
+ const { tasks, fileOwnership, conflicts, executionPhases } = resolveFileOwnership(mapped);
28
+ // Step 4: Build warnings
29
+ const warnings = [];
30
+ for (const task of tasks) {
31
+ if (task.ownedFiles.length === 0) {
32
+ warnings.push(`Task "${task.id}" has no owned files — it may be too abstract.`);
33
+ }
34
+ }
35
+ if (tasks.length === 1) {
36
+ warnings.push('Only one task was generated — the spec may be too small for parallel execution.');
37
+ }
38
+ const orchestrationReady = tasks.length > 0 && warnings.filter((w) => w.includes('no owned')).length === 0;
39
+ return {
40
+ specId,
41
+ taskCount: tasks.length,
42
+ tasks,
43
+ fileOwnership,
44
+ conflicts,
45
+ executionPhases,
46
+ warnings,
47
+ orchestrationReady,
48
+ };
49
+ }
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/index.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,yDAAyD;AACzD,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,aAAqB,EACrB,MAAc,EACd,WAAmB,iBAAiB;IAEpC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAEvD,gDAAgD;IAChD,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;IAEzE,oDAAoD;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAEjD,yDAAyD;IACzD,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE1F,yBAAyB;IACzB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,gDAAgD,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,iFAAiF,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,kBAAkB,GACtB,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAElF,OAAO;QACL,MAAM;QACN,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,KAAK;QACL,aAAa;QACb,SAAS;QACT,eAAe;QACf,QAAQ;QACR,kBAAkB;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { MappedUnit, OwnershipResolutionResult } from '../../types/spec-decomposer.js';
2
+ /**
3
+ * Resolve file ownership and produce final AgentTask list, FileOwnership records,
4
+ * detected conflicts, and execution phases.
5
+ */
6
+ export declare function resolveFileOwnership(units: MappedUnit[]): OwnershipResolutionResult;
7
+ //# sourceMappingURL=ownership-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership-resolver.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-decomposer/ownership-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,UAAU,EAKV,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAiIxC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,yBAAyB,CA2DnF"}
@@ -0,0 +1,169 @@
1
+ // engine/spec-decomposer/ownership-resolver.ts — Resolve file ownership conflicts (SPEC-157)
2
+ // Ensures no two agent tasks claim the same file. When conflicts exist, the task
3
+ // with the highest file count wins ownership; other tasks receive a dependency instead.
4
+ // ---------------------------------------------------------------------------
5
+ // Conflict detection
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * Find files claimed by more than one mapped unit.
9
+ * Returns a map of filePath → unitIds that claim it.
10
+ */
11
+ function detectConflicts(units) {
12
+ const fileToUnits = new Map();
13
+ for (const unit of units) {
14
+ for (const file of unit.files) {
15
+ const existing = fileToUnits.get(file) ?? [];
16
+ existing.push(unit.id);
17
+ fileToUnits.set(file, existing);
18
+ }
19
+ }
20
+ // Keep only files with >1 claimant
21
+ const conflicts = new Map();
22
+ for (const [file, unitIds] of fileToUnits) {
23
+ if (unitIds.length > 1) {
24
+ conflicts.set(file, unitIds);
25
+ }
26
+ }
27
+ return conflicts;
28
+ }
29
+ // ---------------------------------------------------------------------------
30
+ // Ownership resolution
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Resolve ownership conflicts by awarding each contested file to the unit with
34
+ * the most files (primary owner) and removing it from the others.
35
+ * Returns a clean map of unitId → Set<filePath>.
36
+ */
37
+ function resolveOwnership(units, conflicts) {
38
+ // Start: each unit owns all its files
39
+ const ownership = new Map(units.map((u) => [u.id, new Set(u.files)]));
40
+ for (const [file, claimantIds] of conflicts) {
41
+ // Primary owner = unit with most files (acts as heaviest dependency)
42
+ const sorted = [...claimantIds].sort((a, b) => {
43
+ const aSize = ownership.get(a)?.size ?? 0;
44
+ const bSize = ownership.get(b)?.size ?? 0;
45
+ return bSize - aSize;
46
+ });
47
+ const winner = sorted[0];
48
+ if (!winner) {
49
+ continue;
50
+ }
51
+ // Remove file from all losers
52
+ for (const loserId of sorted.slice(1)) {
53
+ ownership.get(loserId)?.delete(file);
54
+ }
55
+ }
56
+ return ownership;
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Execution phase planning
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Assign tasks to execution phases.
63
+ * Tasks with no dependencies → phase 1 (parallel).
64
+ * Tasks with dependencies → subsequent phases.
65
+ */
66
+ function buildExecutionPhases(tasks) {
67
+ if (tasks.length === 0) {
68
+ return [];
69
+ }
70
+ const phases = [];
71
+ const placed = new Set();
72
+ let remaining = [...tasks];
73
+ while (remaining.length > 0) {
74
+ const phaseNumber = phases.length + 1;
75
+ // Tasks whose dependencies are all placed
76
+ const ready = remaining.filter((t) => t.dependencies.every((dep) => placed.has(dep)));
77
+ if (ready.length === 0) {
78
+ // Circular dependency safety: place everything left in one phase
79
+ const ids = remaining.map((t) => t.id);
80
+ phases.push({
81
+ phase: phaseNumber,
82
+ taskIds: ids,
83
+ reason: 'Remaining tasks (possible circular dependency detected)',
84
+ });
85
+ break;
86
+ }
87
+ const reason = ready.length === 1
88
+ ? `Single task with all dependencies satisfied`
89
+ : `${String(ready.length)} tasks with no file conflicts — run in parallel`;
90
+ phases.push({
91
+ phase: phaseNumber,
92
+ taskIds: ready.map((t) => t.id),
93
+ reason,
94
+ });
95
+ for (const t of ready) {
96
+ placed.add(t.id);
97
+ }
98
+ remaining = remaining.filter((t) => !placed.has(t.id));
99
+ }
100
+ return phases;
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Public API
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Resolve file ownership and produce final AgentTask list, FileOwnership records,
107
+ * detected conflicts, and execution phases.
108
+ */
109
+ export function resolveFileOwnership(units) {
110
+ const rawConflicts = detectConflicts(units);
111
+ const ownershipMap = resolveOwnership(units, rawConflicts);
112
+ // Build dependency edges: if unit B lost a file to unit A, B depends on A
113
+ const dependencyEdges = new Map();
114
+ for (const unit of units) {
115
+ dependencyEdges.set(unit.id, new Set());
116
+ }
117
+ const resolvedConflicts = [];
118
+ for (const [file, claimantIds] of rawConflicts) {
119
+ // Winner is the one that still owns the file after resolution
120
+ const winner = claimantIds.find((id) => ownershipMap.get(id)?.has(file));
121
+ if (!winner) {
122
+ continue;
123
+ }
124
+ const losers = claimantIds.filter((id) => id !== winner);
125
+ for (const loser of losers) {
126
+ dependencyEdges.get(loser)?.add(winner);
127
+ }
128
+ resolvedConflicts.push({
129
+ filePath: file,
130
+ conflictingTaskIds: claimantIds,
131
+ resolution: `Ownership awarded to ${winner}; ${losers.join(', ')} will depend on it.`,
132
+ });
133
+ }
134
+ // Build AgentTask array
135
+ const tasks = units.map((unit) => {
136
+ const ownedFiles = [...(ownershipMap.get(unit.id) ?? [])].sort();
137
+ const dependencies = [...(dependencyEdges.get(unit.id) ?? [])].sort();
138
+ // A task can run in parallel if it has no dependencies
139
+ const canRunParallel = dependencies.length === 0;
140
+ return {
141
+ id: unit.id,
142
+ title: unit.title,
143
+ description: buildDescription(unit, ownedFiles),
144
+ criteria: unit.criteria,
145
+ ownedFiles,
146
+ dependencies,
147
+ recommendedModel: unit.recommendedModel,
148
+ estimatedHours: unit.estimatedHours,
149
+ canRunParallel,
150
+ };
151
+ });
152
+ // Build FileOwnership records
153
+ const fileOwnership = tasks.flatMap((task) => task.ownedFiles.map((filePath) => ({ filePath, taskId: task.id })));
154
+ const executionPhases = buildExecutionPhases(tasks);
155
+ return { tasks, fileOwnership, conflicts: resolvedConflicts, executionPhases };
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Helpers
159
+ // ---------------------------------------------------------------------------
160
+ function buildDescription(unit, ownedFiles) {
161
+ const criteriaLines = unit.criteria.length > 0
162
+ ? `\nAcceptance criteria:\n${unit.criteria.map((c) => `- ${c}`).join('\n')}`
163
+ : '';
164
+ const fileLines = ownedFiles.length > 0
165
+ ? `\nOwned files (exclusive):\n${ownedFiles.map((f) => `- ${f}`).join('\n')}`
166
+ : '';
167
+ return `Implement ${unit.title}.${criteriaLines}${fileLines}`;
168
+ }
169
+ //# sourceMappingURL=ownership-resolver.js.map