agentic-qe 3.7.15 → 3.7.17

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 (301) hide show
  1. package/.claude/agents/v3/qe-devils-advocate.md +20 -0
  2. package/.claude/agents/v3/qe-gap-detector.md +25 -0
  3. package/.claude/agents/v3/qe-quality-gate.md +8 -0
  4. package/.claude/agents/v3/qe-requirements-validator.md +25 -0
  5. package/.claude/agents/v3/subagents/qe-code-reviewer.md +11 -0
  6. package/.claude/agents/v3/subagents/qe-integration-reviewer.md +11 -0
  7. package/.claude/agents/v3/subagents/qe-performance-reviewer.md +11 -0
  8. package/.claude/agents/v3/subagents/qe-security-reviewer.md +11 -0
  9. package/.claude/helpers/adr-compliance.sh +10 -10
  10. package/.claude/helpers/auto-memory-hook.mjs +24 -9
  11. package/.claude/helpers/brain-checkpoint.cjs +55 -134
  12. package/.claude/helpers/ddd-tracker.sh +2 -2
  13. package/.claude/helpers/guidance-hooks.sh +2 -2
  14. package/.claude/helpers/hook-handler.cjs +57 -18
  15. package/.claude/helpers/statusline.cjs +414 -595
  16. package/.claude/helpers/v3/quality-criteria/evidence-classification.md +116 -116
  17. package/.claude/helpers/v3/quality-criteria/htsm-categories.md +139 -139
  18. package/.claude/skills/README.md +8 -11
  19. package/.claude/skills/brutal-honesty-review/SKILL.md +3 -0
  20. package/.claude/skills/code-review-quality/SKILL.md +3 -0
  21. package/.claude/skills/qcsd-cicd-swarm/SKILL.md +79 -2075
  22. package/.claude/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +62 -0
  23. package/.claude/skills/qcsd-cicd-swarm/steps/02-core-agents.md +33 -0
  24. package/.claude/skills/qcsd-cicd-swarm/steps/03-batch1-results.md +21 -0
  25. package/.claude/skills/qcsd-cicd-swarm/steps/04-conditional-agents.md +23 -0
  26. package/.claude/skills/qcsd-cicd-swarm/steps/05-decision-synthesis.md +30 -0
  27. package/.claude/skills/qcsd-cicd-swarm/steps/06-report-generation.md +17 -0
  28. package/.claude/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +27 -0
  29. package/.claude/skills/qcsd-cicd-swarm/steps/08-deployment-advisor.md +25 -0
  30. package/.claude/skills/qcsd-cicd-swarm/steps/09-final-output.md +16 -0
  31. package/.claude/skills/qcsd-development-swarm/SKILL.md +79 -2027
  32. package/.claude/skills/qcsd-development-swarm/steps/01-flag-detection.md +50 -0
  33. package/.claude/skills/qcsd-development-swarm/steps/02-core-agents.md +29 -0
  34. package/.claude/skills/qcsd-development-swarm/steps/03-batch1-results.md +14 -0
  35. package/.claude/skills/qcsd-development-swarm/steps/04-conditional-agents.md +23 -0
  36. package/.claude/skills/qcsd-development-swarm/steps/05-decision-synthesis.md +30 -0
  37. package/.claude/skills/qcsd-development-swarm/steps/06-report-generation.md +16 -0
  38. package/.claude/skills/qcsd-development-swarm/steps/07-learning-persistence.md +25 -0
  39. package/.claude/skills/qcsd-development-swarm/steps/08-defect-predictor.md +25 -0
  40. package/.claude/skills/qcsd-development-swarm/steps/09-final-output.md +16 -0
  41. package/.claude/skills/qcsd-ideation-swarm/SKILL.md +94 -1894
  42. package/.claude/skills/qcsd-ideation-swarm/steps/01-flag-detection.md +57 -0
  43. package/.claude/skills/qcsd-ideation-swarm/steps/02-core-agents.md +29 -0
  44. package/.claude/skills/qcsd-ideation-swarm/steps/03-batch1-results.md +15 -0
  45. package/.claude/skills/qcsd-ideation-swarm/steps/04-conditional-agents.md +23 -0
  46. package/.claude/skills/qcsd-ideation-swarm/steps/05-decision-synthesis.md +29 -0
  47. package/.claude/skills/qcsd-ideation-swarm/steps/06-report-generation.md +18 -0
  48. package/.claude/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +29 -0
  49. package/.claude/skills/qcsd-ideation-swarm/steps/08-final-output.md +18 -0
  50. package/.claude/skills/qcsd-production-swarm/SKILL.md +88 -2663
  51. package/.claude/skills/qcsd-production-swarm/steps/01-flag-detection.md +206 -0
  52. package/.claude/skills/qcsd-production-swarm/steps/02-core-agents.md +428 -0
  53. package/.claude/skills/qcsd-production-swarm/steps/03-batch1-results.md +101 -0
  54. package/.claude/skills/qcsd-production-swarm/steps/04-conditional-agents.md +125 -0
  55. package/.claude/skills/qcsd-production-swarm/steps/05-decision-synthesis.md +136 -0
  56. package/.claude/skills/qcsd-production-swarm/steps/06-report-generation.md +181 -0
  57. package/.claude/skills/qcsd-production-swarm/steps/07-learning-persistence.md +185 -0
  58. package/.claude/skills/qcsd-production-swarm/steps/08-feedback-loop.md +122 -0
  59. package/.claude/skills/qcsd-production-swarm/steps/09-final-output.md +140 -0
  60. package/.claude/skills/qcsd-refinement-swarm/SKILL.md +59 -2312
  61. package/.claude/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +91 -0
  62. package/.claude/skills/qcsd-refinement-swarm/steps/02-core-agents.md +40 -0
  63. package/.claude/skills/qcsd-refinement-swarm/steps/03-batch1-results.md +40 -0
  64. package/.claude/skills/qcsd-refinement-swarm/steps/04-conditional-agents.md +35 -0
  65. package/.claude/skills/qcsd-refinement-swarm/steps/05-decision-synthesis.md +43 -0
  66. package/.claude/skills/qcsd-refinement-swarm/steps/06-report-generation.md +42 -0
  67. package/.claude/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +53 -0
  68. package/.claude/skills/qcsd-refinement-swarm/steps/08-transformation.md +36 -0
  69. package/.claude/skills/qcsd-refinement-swarm/steps/09-final-output.md +46 -0
  70. package/.claude/skills/sherlock-review/SKILL.md +3 -0
  71. package/.claude/skills/skill-builder/SKILL.md +103 -0
  72. package/.claude/skills/skills-manifest.json +1 -1
  73. package/CHANGELOG.md +44 -0
  74. package/assets/agents/v3/qe-devils-advocate.md +20 -0
  75. package/assets/agents/v3/qe-gap-detector.md +25 -0
  76. package/assets/agents/v3/qe-quality-gate.md +8 -0
  77. package/assets/agents/v3/qe-requirements-validator.md +25 -0
  78. package/assets/agents/v3/subagents/qe-code-reviewer.md +11 -0
  79. package/assets/agents/v3/subagents/qe-integration-reviewer.md +11 -0
  80. package/assets/agents/v3/subagents/qe-performance-reviewer.md +11 -0
  81. package/assets/agents/v3/subagents/qe-security-reviewer.md +11 -0
  82. package/assets/helpers/statusline-v3.cjs +693 -0
  83. package/assets/skills/brutal-honesty-review/SKILL.md +3 -0
  84. package/assets/skills/code-review-quality/SKILL.md +3 -0
  85. package/assets/skills/qcsd-cicd-swarm/SKILL.md +79 -2075
  86. package/assets/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +62 -0
  87. package/assets/skills/qcsd-cicd-swarm/steps/02-core-agents.md +33 -0
  88. package/assets/skills/qcsd-cicd-swarm/steps/03-batch1-results.md +21 -0
  89. package/assets/skills/qcsd-cicd-swarm/steps/04-conditional-agents.md +23 -0
  90. package/assets/skills/qcsd-cicd-swarm/steps/05-decision-synthesis.md +30 -0
  91. package/assets/skills/qcsd-cicd-swarm/steps/06-report-generation.md +17 -0
  92. package/assets/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +27 -0
  93. package/assets/skills/qcsd-cicd-swarm/steps/08-deployment-advisor.md +25 -0
  94. package/assets/skills/qcsd-cicd-swarm/steps/09-final-output.md +16 -0
  95. package/assets/skills/qcsd-development-swarm/SKILL.md +79 -2027
  96. package/assets/skills/qcsd-development-swarm/steps/01-flag-detection.md +50 -0
  97. package/assets/skills/qcsd-development-swarm/steps/02-core-agents.md +29 -0
  98. package/assets/skills/qcsd-development-swarm/steps/03-batch1-results.md +14 -0
  99. package/assets/skills/qcsd-development-swarm/steps/04-conditional-agents.md +23 -0
  100. package/assets/skills/qcsd-development-swarm/steps/05-decision-synthesis.md +30 -0
  101. package/assets/skills/qcsd-development-swarm/steps/06-report-generation.md +16 -0
  102. package/assets/skills/qcsd-development-swarm/steps/07-learning-persistence.md +25 -0
  103. package/assets/skills/qcsd-development-swarm/steps/08-defect-predictor.md +25 -0
  104. package/assets/skills/qcsd-development-swarm/steps/09-final-output.md +16 -0
  105. package/assets/skills/qcsd-ideation-swarm/SKILL.md +94 -1894
  106. package/assets/skills/qcsd-ideation-swarm/steps/01-flag-detection.md +57 -0
  107. package/assets/skills/qcsd-ideation-swarm/steps/02-core-agents.md +29 -0
  108. package/assets/skills/qcsd-ideation-swarm/steps/03-batch1-results.md +15 -0
  109. package/assets/skills/qcsd-ideation-swarm/steps/04-conditional-agents.md +23 -0
  110. package/assets/skills/qcsd-ideation-swarm/steps/05-decision-synthesis.md +29 -0
  111. package/assets/skills/qcsd-ideation-swarm/steps/06-report-generation.md +18 -0
  112. package/assets/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +29 -0
  113. package/assets/skills/qcsd-ideation-swarm/steps/08-final-output.md +18 -0
  114. package/assets/skills/qcsd-production-swarm/SKILL.md +88 -2663
  115. package/assets/skills/qcsd-production-swarm/steps/01-flag-detection.md +206 -0
  116. package/assets/skills/qcsd-production-swarm/steps/02-core-agents.md +428 -0
  117. package/assets/skills/qcsd-production-swarm/steps/03-batch1-results.md +101 -0
  118. package/assets/skills/qcsd-production-swarm/steps/04-conditional-agents.md +125 -0
  119. package/assets/skills/qcsd-production-swarm/steps/05-decision-synthesis.md +136 -0
  120. package/assets/skills/qcsd-production-swarm/steps/06-report-generation.md +181 -0
  121. package/assets/skills/qcsd-production-swarm/steps/07-learning-persistence.md +185 -0
  122. package/assets/skills/qcsd-production-swarm/steps/08-feedback-loop.md +122 -0
  123. package/assets/skills/qcsd-production-swarm/steps/09-final-output.md +140 -0
  124. package/assets/skills/qcsd-refinement-swarm/SKILL.md +59 -2312
  125. package/assets/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +91 -0
  126. package/assets/skills/qcsd-refinement-swarm/steps/02-core-agents.md +40 -0
  127. package/assets/skills/qcsd-refinement-swarm/steps/03-batch1-results.md +40 -0
  128. package/assets/skills/qcsd-refinement-swarm/steps/04-conditional-agents.md +35 -0
  129. package/assets/skills/qcsd-refinement-swarm/steps/05-decision-synthesis.md +43 -0
  130. package/assets/skills/qcsd-refinement-swarm/steps/06-report-generation.md +42 -0
  131. package/assets/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +53 -0
  132. package/assets/skills/qcsd-refinement-swarm/steps/08-transformation.md +36 -0
  133. package/assets/skills/qcsd-refinement-swarm/steps/09-final-output.md +46 -0
  134. package/assets/skills/sherlock-review/SKILL.md +3 -0
  135. package/assets/templates/agent-override-example.yaml +39 -0
  136. package/dist/agents/devils-advocate/agent.d.ts +25 -1
  137. package/dist/agents/devils-advocate/agent.js +108 -4
  138. package/dist/agents/devils-advocate/types.d.ts +54 -0
  139. package/dist/agents/devils-advocate/types.js +14 -0
  140. package/dist/agents/overlay-loader.d.ts +28 -0
  141. package/dist/agents/overlay-loader.js +232 -0
  142. package/dist/agents/overlay-schema.d.ts +56 -0
  143. package/dist/agents/overlay-schema.js +77 -0
  144. package/dist/analysis/branch-enumerator.d.ts +68 -0
  145. package/dist/analysis/branch-enumerator.js +393 -0
  146. package/dist/analysis/index.d.ts +2 -0
  147. package/dist/analysis/index.js +2 -0
  148. package/dist/cli/bundle.js +2469 -634
  149. package/dist/cli/commands/coverage.js +50 -0
  150. package/dist/cli/handlers/brain-handler.js +2 -1
  151. package/dist/context/compiler.d.ts +62 -0
  152. package/dist/context/compiler.js +143 -0
  153. package/dist/context/index.d.ts +8 -0
  154. package/dist/context/index.js +6 -0
  155. package/dist/context/sources/coverage-source.d.ts +15 -0
  156. package/dist/context/sources/coverage-source.js +77 -0
  157. package/dist/context/sources/git-source.d.ts +12 -0
  158. package/dist/context/sources/git-source.js +33 -0
  159. package/dist/context/sources/index.d.ts +6 -0
  160. package/dist/context/sources/index.js +5 -0
  161. package/dist/context/sources/memory-source.d.ts +17 -0
  162. package/dist/context/sources/memory-source.js +94 -0
  163. package/dist/context/sources/test-source.d.ts +13 -0
  164. package/dist/context/sources/test-source.js +53 -0
  165. package/dist/context/sources/types.d.ts +42 -0
  166. package/dist/context/sources/types.js +5 -0
  167. package/dist/domains/test-generation/coordinator.js +6 -4
  168. package/dist/feedback/feedback-loop.d.ts +5 -0
  169. package/dist/feedback/feedback-loop.js +12 -0
  170. package/dist/feedback/index.d.ts +1 -1
  171. package/dist/feedback/index.js +1 -1
  172. package/dist/init/agents-installer.d.ts +9 -0
  173. package/dist/init/agents-installer.js +72 -0
  174. package/dist/init/phases/07-hooks.d.ts +11 -0
  175. package/dist/init/phases/07-hooks.js +67 -0
  176. package/dist/init/phases/09-assets.js +3 -0
  177. package/dist/init/settings-merge.js +1 -1
  178. package/dist/kernel/hnsw-adapter.d.ts +3 -0
  179. package/dist/kernel/hnsw-adapter.js +11 -1
  180. package/dist/kernel/unified-memory-schemas.d.ts +1 -1
  181. package/dist/kernel/unified-memory-schemas.js +2 -0
  182. package/dist/kernel/unified-memory.js +25 -0
  183. package/dist/learning/experience-capture-middleware.js +24 -0
  184. package/dist/learning/sqlite-persistence.d.ts +3 -0
  185. package/dist/learning/sqlite-persistence.js +9 -0
  186. package/dist/learning/token-tracker.js +4 -0
  187. package/dist/mcp/bundle.js +3694 -3101
  188. package/dist/mcp/handlers/handler-factory.js +92 -11
  189. package/dist/mcp/services/task-router.d.ts +11 -0
  190. package/dist/mcp/services/task-router.js +26 -0
  191. package/dist/routing/qe-agent-registry.d.ts +11 -0
  192. package/dist/routing/qe-agent-registry.js +34 -0
  193. package/dist/routing/qe-task-router.d.ts +1 -0
  194. package/dist/routing/qe-task-router.js +34 -2
  195. package/dist/routing/routing-feedback.d.ts +5 -0
  196. package/dist/routing/routing-feedback.js +29 -3
  197. package/dist/routing/types.d.ts +2 -0
  198. package/dist/sync/pull-agent.js +2 -1
  199. package/dist/test-scheduling/pipeline.d.ts +7 -0
  200. package/dist/test-scheduling/pipeline.js +9 -0
  201. package/dist/validation/index.d.ts +3 -0
  202. package/dist/validation/index.js +10 -0
  203. package/dist/validation/pipeline.d.ts +80 -0
  204. package/dist/validation/pipeline.js +173 -0
  205. package/dist/validation/steps/requirements.d.ts +32 -0
  206. package/dist/validation/steps/requirements.js +596 -0
  207. package/package.json +6 -6
  208. package/.claude/agents/consensus/README.md +0 -253
  209. package/.claude/agents/deprecated/qe-api-contract-validator.md.v2 +0 -162
  210. package/.claude/agents/deprecated/qe-coverage-analyzer.md.v2 +0 -208
  211. package/.claude/agents/deprecated/qe-test-generator.md.v2 +0 -212
  212. package/.claude/agents/deprecated/qe-visual-tester.md.v2 +0 -216
  213. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -130
  214. package/.claude/agents/hive-mind/queen-coordinator.md +0 -203
  215. package/.claude/agents/hive-mind/scout-explorer.md +0 -242
  216. package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -193
  217. package/.claude/agents/hive-mind/worker-specialist.md +0 -217
  218. package/.claude/agents/neural/safla-neural.md +0 -74
  219. package/.claude/agents/optimization/README.md +0 -250
  220. package/.claude/agents/reasoning/agent.md +0 -816
  221. package/.claude/agents/reasoning/goal-planner.md +0 -73
  222. package/.claude/agents/subagents/qe-code-reviewer.md +0 -76
  223. package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +0 -76
  224. package/.claude/agents/subagents/qe-data-generator.md +0 -77
  225. package/.claude/agents/subagents/qe-flaky-investigator.md +0 -91
  226. package/.claude/agents/subagents/qe-integration-tester.md +0 -90
  227. package/.claude/agents/subagents/qe-performance-validator.md +0 -92
  228. package/.claude/agents/subagents/qe-security-auditor.md +0 -94
  229. package/.claude/agents/subagents/qe-test-data-architect-sub.md +0 -93
  230. package/.claude/agents/subagents/qe-test-implementer.md +0 -106
  231. package/.claude/agents/subagents/qe-test-refactorer.md +0 -117
  232. package/.claude/agents/subagents/qe-test-writer.md +0 -112
  233. package/.claude/agents/swarm/README.md +0 -190
  234. package/.claude/agents/templates/migration-plan.md +0 -746
  235. package/.claude/agents/testing/unit/tdd-london-swarm.md +0 -244
  236. package/.claude/agents/testing/validation/production-validator.md +0 -395
  237. package/.claude/agents/v3/README.md +0 -39
  238. package/.claude/agents/v3/typescript-specialist.yaml +0 -21
  239. package/.claude/agents/v3/v3-memory-specialist.md +0 -318
  240. package/.claude/agents/v3/v3-performance-engineer.md +0 -397
  241. package/.claude/agents/v3/v3-queen-coordinator.md +0 -98
  242. package/.claude/agents/v3/v3-security-architect.md +0 -174
  243. package/.claude/commands/README.md +0 -106
  244. package/.claude/commands/agents/README.md +0 -10
  245. package/.claude/commands/agents/agent-capabilities.md +0 -21
  246. package/.claude/commands/agents/agent-coordination.md +0 -28
  247. package/.claude/commands/agents/agent-spawning.md +0 -28
  248. package/.claude/commands/agents/agent-types.md +0 -26
  249. package/.claude/commands/coordination/README.md +0 -9
  250. package/.claude/commands/coordination/agent-spawn.md +0 -25
  251. package/.claude/commands/coordination/init.md +0 -44
  252. package/.claude/commands/coordination/orchestrate.md +0 -43
  253. package/.claude/commands/coordination/spawn.md +0 -45
  254. package/.claude/commands/coordination/swarm-init.md +0 -85
  255. package/.claude/commands/coordination/task-orchestrate.md +0 -25
  256. package/.claude/commands/hive-mind/README.md +0 -17
  257. package/.claude/commands/hive-mind/hive-mind-consensus.md +0 -8
  258. package/.claude/commands/hive-mind/hive-mind-init.md +0 -18
  259. package/.claude/commands/hive-mind/hive-mind-memory.md +0 -8
  260. package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
  261. package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
  262. package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
  263. package/.claude/commands/hive-mind/hive-mind-spawn.md +0 -21
  264. package/.claude/commands/hive-mind/hive-mind-status.md +0 -8
  265. package/.claude/commands/hive-mind/hive-mind-stop.md +0 -8
  266. package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
  267. package/.claude/commands/hive-mind/hive-mind.md +0 -27
  268. package/.claude/commands/memory/README.md +0 -9
  269. package/.claude/commands/memory/memory-persist.md +0 -25
  270. package/.claude/commands/memory/memory-search.md +0 -25
  271. package/.claude/commands/memory/memory-usage.md +0 -25
  272. package/.claude/commands/memory/neural.md +0 -47
  273. package/.claude/commands/swarm/README.md +0 -15
  274. package/.claude/commands/swarm/swarm-analysis.md +0 -8
  275. package/.claude/commands/swarm/swarm-background.md +0 -8
  276. package/.claude/commands/swarm/swarm-init.md +0 -19
  277. package/.claude/commands/swarm/swarm-modes.md +0 -8
  278. package/.claude/commands/swarm/swarm-monitor.md +0 -8
  279. package/.claude/commands/swarm/swarm-spawn.md +0 -19
  280. package/.claude/commands/swarm/swarm-status.md +0 -8
  281. package/.claude/commands/swarm/swarm-strategies.md +0 -8
  282. package/.claude/commands/swarm/swarm.md +0 -27
  283. package/.claude/commands/training/README.md +0 -9
  284. package/.claude/commands/training/model-update.md +0 -25
  285. package/.claude/commands/training/neural-patterns.md +0 -74
  286. package/.claude/commands/training/neural-train.md +0 -25
  287. package/.claude/commands/training/pattern-learn.md +0 -25
  288. package/.claude/commands/training/specialization.md +0 -63
  289. package/.claude/commands/workflows/README.md +0 -9
  290. package/.claude/commands/workflows/development.md +0 -78
  291. package/.claude/commands/workflows/research.md +0 -63
  292. package/.claude/commands/workflows/workflow-create.md +0 -25
  293. package/.claude/commands/workflows/workflow-execute.md +0 -25
  294. package/.claude/commands/workflows/workflow-export.md +0 -25
  295. package/.claude/skills/agentic-jujutsu/SKILL.md +0 -645
  296. package/.claude/skills/hive-mind-advanced/SKILL.md +0 -712
  297. package/.claude/skills/iterative-loop/SKILL.md +0 -371
  298. package/.claude/skills/performance-analysis/SKILL.md +0 -569
  299. package/.claude/skills/performance-analysis/evals/performance-analysis.yaml +0 -144
  300. package/.claude/skills/performance-analysis/schemas/output.json +0 -588
  301. package/.claude/skills/performance-analysis/scripts/validate-config.json +0 -36
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Branch Enumerator Utility (BMAD-004)
3
+ *
4
+ * Mechanically enumerates all branching constructs in TypeScript/JavaScript files
5
+ * without subjective risk scoring. Reports every unhandled path for completeness.
6
+ *
7
+ * Design: Strategy pattern (BranchEnumerator interface) for future multi-language support.
8
+ * Uses regex-based pattern matching (NOT AST parsing) to keep the utility lightweight
9
+ * and avoid parser version issues (Gap 5).
10
+ */
11
+ /**
12
+ * TypeScript/JavaScript branch enumerator.
13
+ * Uses line-by-line pattern matching for reliability.
14
+ */
15
+ export class TSBranchEnumerator {
16
+ language;
17
+ constructor(language = 'typescript') {
18
+ this.language = language;
19
+ }
20
+ enumerate(sourceCode, filePath) {
21
+ const branches = [];
22
+ const lines = sourceCode.split('\n');
23
+ // Track context for multi-line comment detection
24
+ let inBlockComment = false;
25
+ for (let i = 0; i < lines.length; i++) {
26
+ const line = lines[i];
27
+ const trimmed = line.trim();
28
+ const lineNum = i + 1;
29
+ const col = line.length - line.trimStart().length + 1;
30
+ // Skip block comments
31
+ if (inBlockComment) {
32
+ if (trimmed.includes('*/'))
33
+ inBlockComment = false;
34
+ continue;
35
+ }
36
+ if (trimmed.startsWith('/*')) {
37
+ inBlockComment = !trimmed.includes('*/');
38
+ continue;
39
+ }
40
+ // Skip line comments
41
+ if (trimmed.startsWith('//'))
42
+ continue;
43
+ // 1. if-without-else
44
+ if (/^\s*if\s*\(/.test(line)) {
45
+ const hasElse = this.findMatchingElse(lines, i);
46
+ if (!hasElse) {
47
+ branches.push({
48
+ file: filePath,
49
+ line: lineNum,
50
+ column: col,
51
+ language: this.language,
52
+ construct: 'if-without-else',
53
+ triggerCondition: 'when condition is false',
54
+ currentHandling: 'falls through — no else branch',
55
+ suggestedGuard: 'Add else branch or document why falsy path is safe',
56
+ severity: 'medium',
57
+ });
58
+ }
59
+ }
60
+ // 2. switch-no-default and switch-missing-break
61
+ if (/^\s*switch\s*\(/.test(line)) {
62
+ const switchBlock = this.extractBlock(lines, i);
63
+ if (switchBlock && !switchBlock.includes('default:') && !switchBlock.includes('default :')) {
64
+ branches.push({
65
+ file: filePath,
66
+ line: lineNum,
67
+ column: col,
68
+ language: this.language,
69
+ construct: 'switch-no-default',
70
+ triggerCondition: 'when value matches no case',
71
+ currentHandling: 'falls through — no default case',
72
+ suggestedGuard: 'Add default case with error handling or exhaustive check',
73
+ severity: 'high',
74
+ });
75
+ }
76
+ // 2b. switch-missing-break
77
+ if (switchBlock) {
78
+ const caseBlocks = switchBlock.match(/case\s+[^:]+:/g) || [];
79
+ const breakStatements = switchBlock.match(/\b(break|return|throw|continue)\b/g) || [];
80
+ if (caseBlocks.length > 0 && breakStatements.length < caseBlocks.length) {
81
+ branches.push({
82
+ file: filePath,
83
+ line: lineNum,
84
+ column: col,
85
+ language: this.language,
86
+ construct: 'switch-missing-break',
87
+ triggerCondition: 'when case falls through to next case',
88
+ currentHandling: 'fall-through — may execute unintended cases',
89
+ suggestedGuard: 'Add break/return to each case or add explicit // falls through comment',
90
+ severity: 'medium',
91
+ });
92
+ }
93
+ }
94
+ }
95
+ // 3. try-empty-catch
96
+ if (/\bcatch\s*\(/.test(trimmed) || /\bcatch\s*\{/.test(trimmed)) {
97
+ const catchBody = this.extractBlock(lines, i);
98
+ if (catchBody !== null) {
99
+ const bodyContent = catchBody.replace(/[{}]/g, '').trim();
100
+ if (bodyContent.length === 0 || /^\s*\/\//.test(bodyContent)) {
101
+ branches.push({
102
+ file: filePath,
103
+ line: lineNum,
104
+ column: col,
105
+ language: this.language,
106
+ construct: 'try-empty-catch',
107
+ triggerCondition: 'when exception is thrown',
108
+ currentHandling: 'exception silently swallowed',
109
+ suggestedGuard: 'Log the error or rethrow with context',
110
+ severity: 'high',
111
+ });
112
+ }
113
+ }
114
+ }
115
+ // 3b. try-no-finally
116
+ if (/\btry\s*\{/.test(trimmed)) {
117
+ const tryBlock = this.extractBlock(lines, i);
118
+ if (tryBlock) {
119
+ const afterTry = lines.slice(i, Math.min(i + 30, lines.length)).join('\n');
120
+ if (!afterTry.includes('finally')) {
121
+ branches.push({
122
+ file: filePath,
123
+ line: lineNum,
124
+ column: col,
125
+ language: this.language,
126
+ construct: 'try-no-finally',
127
+ triggerCondition: 'when cleanup is needed regardless of success/failure',
128
+ currentHandling: 'no finally block — cleanup may be skipped on exception',
129
+ suggestedGuard: 'Add finally block for resource cleanup if applicable',
130
+ severity: 'low',
131
+ });
132
+ }
133
+ }
134
+ }
135
+ // 4. Optional chaining ?.
136
+ if (trimmed.includes('?.')) {
137
+ const chainMatches = trimmed.match(/(\w+(?:\.\w+)*)\?\./g) || [];
138
+ for (const match of chainMatches) {
139
+ // Check if the result is used without null check
140
+ if (!trimmed.includes('??') && !trimmed.includes('|| ') && !trimmed.includes('if')) {
141
+ branches.push({
142
+ file: filePath,
143
+ line: lineNum,
144
+ column: col,
145
+ language: this.language,
146
+ construct: 'optional-chaining-null-path',
147
+ triggerCondition: `when ${match.replace('?.', '')} is null/undefined`,
148
+ currentHandling: 'returns undefined — may propagate',
149
+ suggestedGuard: 'Add ?? fallback or explicit null check',
150
+ severity: 'low',
151
+ });
152
+ break; // One per line
153
+ }
154
+ }
155
+ }
156
+ // 5. Nullish coalescing ??
157
+ if (trimmed.includes('??') && !trimmed.includes('?.')) {
158
+ branches.push({
159
+ file: filePath,
160
+ line: lineNum,
161
+ column: col,
162
+ language: this.language,
163
+ construct: 'nullish-coalescing-fallback',
164
+ triggerCondition: 'when left side is null/undefined',
165
+ currentHandling: 'uses fallback value',
166
+ suggestedGuard: 'Verify fallback value is appropriate for all null cases',
167
+ severity: 'low',
168
+ });
169
+ }
170
+ // 6. Promise without .catch
171
+ if (/\.\s*then\s*\(/.test(trimmed) && !trimmed.includes('.catch') && !trimmed.includes('await')) {
172
+ // Look ahead a few lines for .catch
173
+ const nextLines = lines.slice(i, Math.min(i + 5, lines.length)).join(' ');
174
+ if (!nextLines.includes('.catch') && !nextLines.includes('try')) {
175
+ branches.push({
176
+ file: filePath,
177
+ line: lineNum,
178
+ column: col,
179
+ language: this.language,
180
+ construct: 'promise-no-catch',
181
+ triggerCondition: 'when promise rejects',
182
+ currentHandling: 'unhandled rejection — may crash process',
183
+ suggestedGuard: 'Add .catch() handler or use try/catch with await',
184
+ severity: 'high',
185
+ });
186
+ }
187
+ }
188
+ // 7. Array methods with callbacks (empty array case)
189
+ const arrayMethods = ['map', 'filter', 'reduce', 'forEach', 'find', 'some', 'every', 'flatMap'];
190
+ for (const method of arrayMethods) {
191
+ const pattern = new RegExp(`\\.${method}\\s*\\(`);
192
+ if (pattern.test(trimmed)) {
193
+ // Check if there's an empty array check before
194
+ const prevLines = lines.slice(Math.max(0, i - 3), i).join(' ');
195
+ if (!prevLines.includes('.length') && !prevLines.includes('if (') && !prevLines.includes('?.')) {
196
+ branches.push({
197
+ file: filePath,
198
+ line: lineNum,
199
+ column: col,
200
+ language: this.language,
201
+ construct: 'array-callback-empty',
202
+ triggerCondition: `when array is empty before .${method}()`,
203
+ currentHandling: method === 'reduce'
204
+ ? 'may throw without initial value'
205
+ : 'returns empty result — may cause downstream issues',
206
+ suggestedGuard: method === 'reduce'
207
+ ? 'Provide initial value or check array length'
208
+ : 'Check array length or handle empty result',
209
+ severity: method === 'reduce' ? 'high' : 'low',
210
+ });
211
+ break; // One per line
212
+ }
213
+ }
214
+ }
215
+ // 8. Logical OR for defaults (falsy trap)
216
+ if (/\|\|\s*['"`\d]/.test(trimmed) && !trimmed.includes('??')) {
217
+ branches.push({
218
+ file: filePath,
219
+ line: lineNum,
220
+ column: col,
221
+ language: this.language,
222
+ construct: 'logical-or-falsy',
223
+ triggerCondition: 'when left side is falsy (0, "", false, null, undefined)',
224
+ currentHandling: 'uses fallback — may unintentionally override 0, "", or false',
225
+ suggestedGuard: 'Use ?? instead of || if only null/undefined should trigger fallback',
226
+ severity: 'medium',
227
+ });
228
+ }
229
+ // 9. Logical AND short-circuit
230
+ if (/&&\s*\w+\s*\(/.test(trimmed) && !trimmed.includes('if') && !trimmed.includes('while')) {
231
+ branches.push({
232
+ file: filePath,
233
+ line: lineNum,
234
+ column: col,
235
+ language: this.language,
236
+ construct: 'logical-and-short-circuit',
237
+ triggerCondition: 'when left side is falsy — right side never executes',
238
+ currentHandling: 'short-circuits — function call skipped silently',
239
+ suggestedGuard: 'Use explicit if-statement for clarity when side effects matter',
240
+ severity: 'low',
241
+ });
242
+ }
243
+ // 10. Complex ternary (nested or very long)
244
+ const ternaryMatches = trimmed.match(/\?/g) || [];
245
+ if (ternaryMatches.length >= 2 && trimmed.includes(':')) {
246
+ branches.push({
247
+ file: filePath,
248
+ line: lineNum,
249
+ column: col,
250
+ language: this.language,
251
+ construct: 'ternary-complex',
252
+ triggerCondition: 'when nested ternary conditions interact',
253
+ currentHandling: 'nested ternary — hard to read and maintain',
254
+ suggestedGuard: 'Refactor to if/else or switch for readability',
255
+ severity: 'medium',
256
+ });
257
+ }
258
+ // 11. Type guard without exhaustive handling
259
+ if (/\btypeof\s+\w+\s*===?\s*['"]/.test(trimmed) || /\binstanceof\b/.test(trimmed)) {
260
+ if (!trimmed.includes('else') && !this.findMatchingElse(lines, i)) {
261
+ branches.push({
262
+ file: filePath,
263
+ line: lineNum,
264
+ column: col,
265
+ language: this.language,
266
+ construct: 'type-guard-unhandled',
267
+ triggerCondition: 'when value does not match the guarded type',
268
+ currentHandling: 'unguarded type path — may cause runtime type errors',
269
+ suggestedGuard: 'Add else branch or exhaustive type checking',
270
+ severity: 'medium',
271
+ });
272
+ }
273
+ }
274
+ }
275
+ return branches;
276
+ }
277
+ /**
278
+ * Check if an if-statement has a matching else.
279
+ * Simple heuristic: look for 'else' at same or lower indentation within ~30 lines.
280
+ */
281
+ findMatchingElse(lines, ifLineIndex) {
282
+ const braceCount = { depth: 0 };
283
+ for (let i = ifLineIndex; i < Math.min(ifLineIndex + 30, lines.length); i++) {
284
+ const line = lines[i];
285
+ for (const ch of line) {
286
+ if (ch === '{')
287
+ braceCount.depth++;
288
+ if (ch === '}')
289
+ braceCount.depth--;
290
+ }
291
+ // After the if block closes, check for else
292
+ if (braceCount.depth === 0 && i > ifLineIndex) {
293
+ const nextLine = lines[i + 1]?.trim() || '';
294
+ if (nextLine.startsWith('else') ||
295
+ lines[i].trim().endsWith('else') ||
296
+ lines[i].trim().endsWith('else {')) {
297
+ return true;
298
+ }
299
+ // Also check same line (e.g., "} else {")
300
+ if (lines[i].includes('} else'))
301
+ return true;
302
+ break;
303
+ }
304
+ }
305
+ return false;
306
+ }
307
+ /**
308
+ * Extract the block (curly braces content) starting near a line.
309
+ */
310
+ extractBlock(lines, startIndex) {
311
+ let braceDepth = 0;
312
+ let started = false;
313
+ const blockLines = [];
314
+ for (let i = startIndex; i < Math.min(startIndex + 50, lines.length); i++) {
315
+ const line = lines[i];
316
+ for (const ch of line) {
317
+ if (ch === '{') {
318
+ braceDepth++;
319
+ started = true;
320
+ }
321
+ if (ch === '}')
322
+ braceDepth--;
323
+ }
324
+ if (started) {
325
+ blockLines.push(line);
326
+ if (braceDepth === 0) {
327
+ return blockLines.join('\n');
328
+ }
329
+ }
330
+ }
331
+ return null;
332
+ }
333
+ }
334
+ /**
335
+ * Enumerate branches in a source file.
336
+ */
337
+ export function enumerateBranches(sourceCode, filePath, language) {
338
+ const start = Date.now();
339
+ // Detect language from file extension
340
+ const detectedLang = language ||
341
+ (filePath.endsWith('.ts') || filePath.endsWith('.tsx') ? 'typescript' : 'javascript');
342
+ const enumerator = new TSBranchEnumerator(detectedLang);
343
+ const branches = enumerator.enumerate(sourceCode, filePath);
344
+ return {
345
+ file: filePath,
346
+ language: detectedLang,
347
+ branches,
348
+ totalConstructs: branches.length,
349
+ unhandledCount: branches.length,
350
+ duration: Date.now() - start,
351
+ };
352
+ }
353
+ /**
354
+ * Format enumeration result as markdown.
355
+ */
356
+ export function formatBranchReport(result) {
357
+ const lines = [];
358
+ lines.push(`# Branch Enumeration Report: ${result.file}`);
359
+ lines.push('');
360
+ lines.push(`**Language**: ${result.language} | **Branches**: ${result.unhandledCount} | **Duration**: ${result.duration}ms`);
361
+ lines.push('');
362
+ if (result.branches.length === 0) {
363
+ lines.push('No unhandled branches detected.');
364
+ return lines.join('\n');
365
+ }
366
+ // Group by severity
367
+ const bySeverity = { high: [], medium: [], low: [] };
368
+ for (const branch of result.branches) {
369
+ bySeverity[branch.severity].push(branch);
370
+ }
371
+ for (const severity of ['high', 'medium', 'low']) {
372
+ const group = bySeverity[severity];
373
+ if (group.length === 0)
374
+ continue;
375
+ lines.push(`## ${severity.toUpperCase()} Severity (${group.length})`);
376
+ lines.push('');
377
+ for (const branch of group) {
378
+ lines.push(`### ${branch.construct} — Line ${branch.line}`);
379
+ lines.push(`- **Trigger**: ${branch.triggerCondition}`);
380
+ lines.push(`- **Current**: ${branch.currentHandling}`);
381
+ lines.push(`- **Suggested**: ${branch.suggestedGuard}`);
382
+ lines.push('');
383
+ }
384
+ }
385
+ return lines.join('\n');
386
+ }
387
+ /**
388
+ * Format enumeration result as JSON.
389
+ */
390
+ export function formatBranchJSON(result) {
391
+ return JSON.stringify(result, null, 2);
392
+ }
393
+ //# sourceMappingURL=branch-enumerator.js.map
@@ -0,0 +1,2 @@
1
+ export * from './branch-enumerator.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export * from './branch-enumerator.js';
2
+ //# sourceMappingURL=index.js.map