@howlil/ez-agents 3.5.0 → 4.0.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 (382) hide show
  1. package/README.md +735 -537
  2. package/agents/ez-architect-agent.md +267 -0
  3. package/agents/ez-backend-agent.md +303 -0
  4. package/agents/ez-chief-strategist.md +271 -0
  5. package/agents/ez-codebase-mapper.md +770 -770
  6. package/agents/ez-context-manager.md +319 -0
  7. package/agents/ez-debugger.md +1255 -1255
  8. package/agents/ez-design-expert.md +347 -0
  9. package/agents/ez-devops-agent.md +331 -0
  10. package/agents/ez-executor.md +487 -487
  11. package/agents/ez-frontend-agent.md +322 -0
  12. package/agents/ez-phase-researcher.md +553 -553
  13. package/agents/ez-planner.md +1307 -1307
  14. package/agents/ez-product-engineer.md +435 -0
  15. package/agents/ez-project-researcher.md +629 -629
  16. package/agents/ez-qa-agent.md +320 -0
  17. package/agents/ez-release-agent.md +333 -333
  18. package/agents/ez-requirements-agent.md +377 -377
  19. package/agents/ez-roadmapper.md +650 -650
  20. package/agents/ez-technical-writer.md +551 -0
  21. package/agents/ez-ux-expert.md +393 -0
  22. package/agents/ez-verifier.md +579 -579
  23. package/bin/guards/autonomy-guard.cjs +346 -0
  24. package/bin/guards/context-budget-guard.cjs +278 -0
  25. package/bin/guards/hallucination-guard.cjs +380 -0
  26. package/bin/guards/hidden-state-guard.cjs +182 -0
  27. package/bin/guards/team-overhead-guard.cjs +266 -0
  28. package/bin/guards/tool-sprawl-guard.cjs +271 -0
  29. package/bin/lib/analytics/analytics-collector.cjs +86 -0
  30. package/bin/lib/analytics/analytics-reporter.cjs +130 -0
  31. package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
  32. package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
  33. package/bin/lib/analytics/nps-tracker.cjs +147 -0
  34. package/bin/lib/archetype-detector.cjs +289 -0
  35. package/bin/lib/assistant-adapter.cjs +361 -0
  36. package/bin/lib/audit-exec.cjs +175 -0
  37. package/bin/lib/auth.cjs +176 -0
  38. package/bin/lib/backup-service.cjs +422 -0
  39. package/bin/lib/bdd-validator.cjs +622 -0
  40. package/bin/lib/business-flow-mapper.cjs +429 -0
  41. package/bin/lib/circuit-breaker.cjs +276 -0
  42. package/bin/lib/code-complexity-analyzer.cjs +360 -0
  43. package/bin/lib/codebase-analyzer.cjs +241 -0
  44. package/bin/lib/commands.cjs +691 -0
  45. package/bin/lib/config.cjs +236 -0
  46. package/bin/lib/constraint-extractor.cjs +526 -0
  47. package/bin/lib/content-scanner.cjs +238 -0
  48. package/bin/lib/context-cache.cjs +154 -0
  49. package/bin/lib/context-compressor.cjs +102 -0
  50. package/bin/lib/context-deduplicator.cjs +105 -0
  51. package/bin/lib/context-errors.cjs +78 -0
  52. package/bin/lib/context-manager.cjs +338 -0
  53. package/bin/lib/context-metadata-tracker.cjs +140 -0
  54. package/bin/lib/context-relevance-scorer.cjs +99 -0
  55. package/bin/lib/core.cjs +507 -0
  56. package/bin/lib/cost-alerts.cjs +174 -0
  57. package/bin/lib/cost-tracker.cjs +275 -0
  58. package/bin/lib/crash-recovery.cjs +220 -0
  59. package/bin/lib/dependency-graph.cjs +319 -0
  60. package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
  61. package/bin/lib/deploy/deploy-detector.cjs +69 -0
  62. package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
  63. package/bin/lib/deploy/deploy-health-check.cjs +88 -0
  64. package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
  65. package/bin/lib/deploy/deploy-rollback.cjs +72 -0
  66. package/bin/lib/deploy/deploy-runner.cjs +97 -0
  67. package/bin/lib/deploy/deploy-status.cjs +74 -0
  68. package/bin/lib/discussion-synthesizer.cjs +439 -0
  69. package/bin/lib/error-cache.cjs +114 -0
  70. package/bin/lib/error-registry.cjs +177 -0
  71. package/bin/lib/file-access.cjs +207 -0
  72. package/bin/lib/file-lock.cjs +236 -0
  73. package/bin/lib/finops/budget-enforcer.cjs +126 -0
  74. package/bin/lib/finops/cost-reporter.cjs +132 -0
  75. package/bin/lib/finops/finops-analyzer.cjs +112 -0
  76. package/bin/lib/finops/spot-manager.cjs +118 -0
  77. package/bin/lib/framework-detector.cjs +396 -0
  78. package/bin/lib/frontmatter.cjs +313 -0
  79. package/bin/lib/fs-utils.cjs +153 -0
  80. package/bin/lib/gate-executor.cjs +272 -0
  81. package/bin/lib/gates/README.md +374 -0
  82. package/bin/lib/gates/gate-01-requirement.cjs +303 -0
  83. package/bin/lib/gates/gate-02-architecture.cjs +555 -0
  84. package/bin/lib/gates/gate-03-code.cjs +635 -0
  85. package/bin/lib/gates/gate-04-security.cjs +829 -0
  86. package/bin/lib/git-errors.cjs +83 -0
  87. package/bin/lib/git-utils.cjs +321 -0
  88. package/bin/lib/git-workflow-engine.cjs +1157 -0
  89. package/bin/lib/health-check.cjs +227 -0
  90. package/bin/lib/index.cjs +279 -0
  91. package/bin/lib/init.cjs +725 -0
  92. package/bin/lib/lock-logger.cjs +194 -0
  93. package/bin/lib/lock-state.cjs +263 -0
  94. package/bin/lib/lockfile-validator.cjs +227 -0
  95. package/bin/lib/log-rotation.cjs +71 -0
  96. package/bin/lib/logger.cjs +125 -0
  97. package/bin/lib/memory-compression.cjs +256 -0
  98. package/bin/lib/milestone.cjs +247 -0
  99. package/bin/lib/model-provider.cjs +241 -0
  100. package/bin/lib/package-manager-detector.cjs +203 -0
  101. package/bin/lib/package-manager-executor.cjs +385 -0
  102. package/bin/lib/package-manager-service.cjs +216 -0
  103. package/bin/lib/perf/api-monitor.cjs +88 -0
  104. package/bin/lib/perf/db-optimizer.cjs +78 -0
  105. package/bin/lib/perf/frontend-performance.cjs +56 -0
  106. package/bin/lib/perf/perf-analyzer.cjs +77 -0
  107. package/bin/lib/perf/perf-baseline.cjs +102 -0
  108. package/bin/lib/perf/perf-reporter.cjs +117 -0
  109. package/bin/lib/perf/regression-detector.cjs +92 -0
  110. package/bin/lib/phase.cjs +963 -0
  111. package/bin/lib/planning-write.cjs +123 -0
  112. package/bin/lib/project-reporter.cjs +565 -0
  113. package/bin/lib/quality-gate.cjs +332 -0
  114. package/bin/lib/quality-metrics.cjs +324 -0
  115. package/bin/lib/recovery-manager.cjs +98 -0
  116. package/bin/lib/release-validator.cjs +617 -0
  117. package/bin/lib/retry.cjs +119 -0
  118. package/bin/lib/roadmap.cjs +309 -0
  119. package/bin/lib/safe-exec.cjs +173 -0
  120. package/bin/lib/safe-path.cjs +130 -0
  121. package/bin/lib/security-errors.cjs +62 -0
  122. package/bin/lib/session-chain.cjs +304 -0
  123. package/bin/lib/session-errors.cjs +81 -0
  124. package/bin/lib/session-export.cjs +251 -0
  125. package/bin/lib/session-import.cjs +262 -0
  126. package/bin/lib/session-manager.cjs +280 -0
  127. package/bin/lib/skill-context.cjs +148 -0
  128. package/bin/lib/skill-matcher.cjs +236 -0
  129. package/bin/lib/skill-registry.cjs +360 -0
  130. package/bin/lib/skill-resolver.cjs +449 -0
  131. package/bin/lib/skill-triggers.cjs +90 -0
  132. package/bin/lib/skill-validator.cjs +270 -0
  133. package/bin/lib/skill-versioning.cjs +355 -0
  134. package/bin/lib/stack-detector.cjs +399 -0
  135. package/bin/lib/state.cjs +736 -0
  136. package/bin/lib/tech-debt-analyzer.cjs +309 -0
  137. package/bin/lib/temp-file.cjs +239 -0
  138. package/bin/lib/template.cjs +223 -0
  139. package/bin/lib/test-file-lock.cjs +112 -0
  140. package/bin/lib/test-graceful.cjs +93 -0
  141. package/bin/lib/test-logger.cjs +60 -0
  142. package/bin/lib/test-safe-exec.cjs +38 -0
  143. package/bin/lib/test-safe-path.cjs +33 -0
  144. package/bin/lib/test-temp-file.cjs +125 -0
  145. package/bin/lib/tier-manager.cjs +428 -0
  146. package/bin/lib/timeout-exec.cjs +63 -0
  147. package/bin/lib/tradeoff-analyzer.cjs +284 -0
  148. package/bin/lib/url-fetch.cjs +170 -0
  149. package/bin/lib/verify.cjs +863 -0
  150. package/bin/update.js +217 -214
  151. package/commands/deploy.cjs +53 -0
  152. package/commands/ez/add-tests.md +41 -41
  153. package/commands/ez/audit-milestone.md +36 -36
  154. package/commands/ez/complete-milestone.md +136 -136
  155. package/commands/ez/discuss-phase.md +90 -90
  156. package/commands/ez/execute-phase.md +52 -52
  157. package/commands/ez/help.md +22 -22
  158. package/commands/ez/map-codebase.md +71 -71
  159. package/commands/ez/new-milestone.md +44 -44
  160. package/commands/ez/new-project.md +51 -42
  161. package/commands/ez/plan-phase.md +53 -53
  162. package/commands/ez/progress.md +36 -36
  163. package/commands/ez/quick.md +45 -45
  164. package/commands/ez/resume-work.md +40 -40
  165. package/commands/ez/run-phase.md +580 -0
  166. package/commands/ez/settings.md +36 -36
  167. package/commands/ez/update.md +37 -37
  168. package/commands/ez/verify-work.md +402 -38
  169. package/commands/health-check.cjs +44 -0
  170. package/commands/rollback.cjs +47 -0
  171. package/ez-agents/bin/ez-tools.cjs +599 -2
  172. package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
  173. package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
  174. package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
  175. package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
  176. package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
  177. package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
  178. package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
  179. package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
  180. package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
  181. package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
  182. package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
  183. package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
  184. package/ez-agents/bin/lib/audit-exec.cjs +166 -167
  185. package/ez-agents/bin/lib/auth.cjs +176 -176
  186. package/ez-agents/bin/lib/backup-service.cjs +422 -0
  187. package/ez-agents/bin/lib/bdd-validator.cjs +622 -622
  188. package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
  189. package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
  190. package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
  191. package/ez-agents/bin/lib/commands.cjs +685 -685
  192. package/ez-agents/bin/lib/config.cjs +41 -1
  193. package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
  194. package/ez-agents/bin/lib/content-scanner.cjs +238 -238
  195. package/ez-agents/bin/lib/context-cache.cjs +154 -154
  196. package/ez-agents/bin/lib/context-errors.cjs +71 -71
  197. package/ez-agents/bin/lib/context-manager.cjs +220 -220
  198. package/ez-agents/bin/lib/core.cjs +507 -512
  199. package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
  200. package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
  201. package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
  202. package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
  203. package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
  204. package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
  205. package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
  206. package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
  207. package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
  208. package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
  209. package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
  210. package/ez-agents/bin/lib/file-access.cjs +207 -207
  211. package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
  212. package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
  213. package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
  214. package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
  215. package/ez-agents/bin/lib/framework-detector.cjs +396 -0
  216. package/ez-agents/bin/lib/frontmatter.cjs +3 -1
  217. package/ez-agents/bin/lib/gates/README.md +374 -0
  218. package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
  219. package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
  220. package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
  221. package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
  222. package/ez-agents/bin/lib/git-errors.cjs +83 -83
  223. package/ez-agents/bin/lib/git-utils.cjs +321 -321
  224. package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -1157
  225. package/ez-agents/bin/lib/health-check.cjs +162 -162
  226. package/ez-agents/bin/lib/index.cjs +2 -8
  227. package/ez-agents/bin/lib/init.cjs +0 -2
  228. package/ez-agents/bin/lib/lockfile-validator.cjs +227 -227
  229. package/ez-agents/bin/lib/log-rotation.cjs +71 -0
  230. package/ez-agents/bin/lib/logger.cjs +22 -47
  231. package/ez-agents/bin/lib/memory-compression.cjs +256 -256
  232. package/ez-agents/bin/lib/package-manager-detector.cjs +203 -203
  233. package/ez-agents/bin/lib/package-manager-executor.cjs +385 -385
  234. package/ez-agents/bin/lib/package-manager-service.cjs +216 -216
  235. package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
  236. package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
  237. package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
  238. package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
  239. package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
  240. package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
  241. package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
  242. package/ez-agents/bin/lib/project-reporter.cjs +502 -0
  243. package/ez-agents/bin/lib/quality-gate.cjs +332 -0
  244. package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
  245. package/ez-agents/bin/lib/release-validator.cjs +617 -614
  246. package/ez-agents/bin/lib/security-errors.cjs +62 -0
  247. package/ez-agents/bin/lib/session-chain.cjs +304 -304
  248. package/ez-agents/bin/lib/session-errors.cjs +81 -81
  249. package/ez-agents/bin/lib/session-export.cjs +251 -251
  250. package/ez-agents/bin/lib/session-import.cjs +262 -262
  251. package/ez-agents/bin/lib/session-manager.cjs +280 -280
  252. package/ez-agents/bin/lib/skill-context.cjs +148 -0
  253. package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
  254. package/ez-agents/bin/lib/skill-registry.cjs +341 -0
  255. package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
  256. package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
  257. package/ez-agents/bin/lib/skill-validator.cjs +270 -0
  258. package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
  259. package/ez-agents/bin/lib/stack-detector.cjs +399 -0
  260. package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
  261. package/ez-agents/bin/lib/tier-manager.cjs +428 -428
  262. package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
  263. package/ez-agents/bin/lib/url-fetch.cjs +170 -170
  264. package/ez-agents/bin/lib/verify.cjs +863 -863
  265. package/ez-agents/references/decimal-phase-calculation.md +65 -65
  266. package/ez-agents/references/git-integration.md +248 -248
  267. package/ez-agents/references/git-planning-commit.md +38 -38
  268. package/ez-agents/references/metrics-schema.md +118 -118
  269. package/ez-agents/references/model-profile-resolution.md +34 -34
  270. package/ez-agents/references/model-profiles.md +93 -93
  271. package/ez-agents/references/phase-argument-parsing.md +61 -61
  272. package/ez-agents/references/planning-config.md +340 -340
  273. package/ez-agents/references/tier-strategy.md +103 -103
  274. package/ez-agents/references/ui-brand.md +160 -160
  275. package/ez-agents/references/verification-patterns.md +612 -612
  276. package/ez-agents/templates/DEBUG.md +164 -164
  277. package/ez-agents/templates/UAT.md +247 -247
  278. package/ez-agents/templates/agent-output-format.md +404 -0
  279. package/ez-agents/templates/bdd-feature.md +173 -173
  280. package/ez-agents/templates/codebase/architecture.md +255 -255
  281. package/ez-agents/templates/codebase/structure.md +285 -285
  282. package/ez-agents/templates/copilot-instructions.md +7 -7
  283. package/ez-agents/templates/debug-subagent-prompt.md +91 -91
  284. package/ez-agents/templates/discovery.md +146 -146
  285. package/ez-agents/templates/discussion.md +68 -68
  286. package/ez-agents/templates/handoff-protocol.md +294 -0
  287. package/ez-agents/templates/incident-runbook.md +205 -205
  288. package/ez-agents/templates/mode-workflow-templates.md +301 -0
  289. package/ez-agents/templates/phase-prompt.md +610 -610
  290. package/ez-agents/templates/planner-subagent-prompt.md +117 -117
  291. package/ez-agents/templates/project.md +184 -184
  292. package/ez-agents/templates/release-checklist.md +136 -133
  293. package/ez-agents/templates/research.md +552 -552
  294. package/ez-agents/templates/rollback-plan.md +201 -201
  295. package/ez-agents/templates/security-user-setup.md +244 -0
  296. package/ez-agents/templates/skill-validation-rules.md +476 -0
  297. package/ez-agents/templates/state.md +180 -176
  298. package/ez-agents/templates/summary-complex.md +59 -59
  299. package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
  300. package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
  301. package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
  302. package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
  303. package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
  304. package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
  305. package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
  306. package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
  307. package/ez-agents/workflows/audit-milestone.md +1 -1
  308. package/ez-agents/workflows/autonomous.md +844 -844
  309. package/ez-agents/workflows/complete-milestone.md +1 -1
  310. package/ez-agents/workflows/discuss-phase.md +1 -1
  311. package/ez-agents/workflows/execute-phase.md +124 -3
  312. package/ez-agents/workflows/help.md +42 -181
  313. package/ez-agents/workflows/hotfix.md +291 -291
  314. package/ez-agents/workflows/new-milestone.md +713 -713
  315. package/ez-agents/workflows/new-project.md +1089 -1107
  316. package/ez-agents/workflows/plan-phase.md +0 -40
  317. package/ez-agents/workflows/release.md +253 -253
  318. package/ez-agents/workflows/resume-session.md +215 -215
  319. package/ez-agents/workflows/run-phase.md +531 -0
  320. package/ez-agents/workflows/settings.md +2 -35
  321. package/hooks/dist/ez-check-update.js +81 -81
  322. package/hooks/dist/ez-context-monitor.js +148 -141
  323. package/hooks/dist/ez-statusline.js +115 -115
  324. package/package.json +78 -71
  325. package/scripts/fix-qwen-installation.js +144 -144
  326. package/agents/ez-integration-checker.md +0 -443
  327. package/agents/ez-nyquist-auditor.md +0 -176
  328. package/agents/ez-observer-agent.md +0 -260
  329. package/agents/ez-plan-checker.md +0 -706
  330. package/agents/ez-research-synthesizer.md +0 -247
  331. package/agents/ez-scrum-master-agent.md +0 -242
  332. package/agents/ez-tech-lead-agent.md +0 -267
  333. package/agents/ez-ui-auditor.md +0 -439
  334. package/agents/ez-ui-checker.md +0 -300
  335. package/agents/ez-ui-researcher.md +0 -353
  336. package/commands/ez/add-phase.md +0 -43
  337. package/commands/ez/add-todo.md +0 -47
  338. package/commands/ez/arch-review.md +0 -102
  339. package/commands/ez/auth.md +0 -87
  340. package/commands/ez/autonomous.md +0 -41
  341. package/commands/ez/check-todos.md +0 -45
  342. package/commands/ez/cleanup.md +0 -18
  343. package/commands/ez/debug.md +0 -168
  344. package/commands/ez/export-session.md +0 -79
  345. package/commands/ez/gather-requirements.md +0 -117
  346. package/commands/ez/git-workflow.md +0 -72
  347. package/commands/ez/health.md +0 -22
  348. package/commands/ez/hotfix.md +0 -120
  349. package/commands/ez/import-session.md +0 -82
  350. package/commands/ez/insert-phase.md +0 -32
  351. package/commands/ez/join-discord.md +0 -18
  352. package/commands/ez/list-phase-assumptions.md +0 -46
  353. package/commands/ez/list-sessions.md +0 -96
  354. package/commands/ez/package-manager.md +0 -316
  355. package/commands/ez/pause-work.md +0 -38
  356. package/commands/ez/plan-milestone-gaps.md +0 -34
  357. package/commands/ez/preflight.md +0 -79
  358. package/commands/ez/reapply-patches.md +0 -124
  359. package/commands/ez/release.md +0 -153
  360. package/commands/ez/remove-phase.md +0 -31
  361. package/commands/ez/research-phase.md +0 -190
  362. package/commands/ez/resume.md +0 -107
  363. package/commands/ez/set-profile.md +0 -34
  364. package/commands/ez/standup.md +0 -85
  365. package/commands/ez/stats.md +0 -18
  366. package/commands/ez/ui-phase.md +0 -34
  367. package/commands/ez/ui-review.md +0 -32
  368. package/commands/ez/validate-phase.md +0 -35
  369. package/ez-agents/bin/lib/metrics-tracker.cjs +0 -406
  370. package/ez-agents/templates/UI-SPEC.md +0 -100
  371. package/ez-agents/templates/VALIDATION.md +0 -76
  372. package/ez-agents/templates/context.md +0 -352
  373. package/ez-agents/templates/verification-report.md +0 -322
  374. package/ez-agents/workflows/arch-review.md +0 -54
  375. package/ez-agents/workflows/export-session.md +0 -255
  376. package/ez-agents/workflows/gather-requirements.md +0 -206
  377. package/ez-agents/workflows/import-session.md +0 -303
  378. package/ez-agents/workflows/research-phase.md +0 -74
  379. package/ez-agents/workflows/standup.md +0 -64
  380. package/ez-agents/workflows/ui-phase.md +0 -290
  381. package/ez-agents/workflows/ui-review.md +0 -157
  382. package/ez-agents/workflows/validate-phase.md +0 -167
@@ -0,0 +1,812 @@
1
+ /**
2
+ * Gate 1-2 Tests
3
+ *
4
+ * Tests for Requirement Completeness (Gate 1) and Architecture Review (Gate 2)
5
+ *
6
+ * Test cases:
7
+ * Gate 1:
8
+ * 1. Gate 1 passes when all REQ-IDs mapped
9
+ * 2. Gate 1 fails with errors for unmapped REQ-IDs
10
+ * 3. Gate 1 passes when acceptance criteria in Given-When-Then
11
+ * 4. Gate 1 fails when acceptance criteria missing
12
+ *
13
+ * Gate 2:
14
+ * 5. Gate 2 passes when structure matches skill recommendations
15
+ * 6. Gate 2 fails when structure deviates without justification
16
+ * 7. Gate 2 counts abstraction layers correctly
17
+ * 8. Gate 2 flags >3 abstraction layers as warning
18
+ * 9. Gate 2 detects premature repository pattern
19
+ * 10. Gate 2 detects unnecessary CQRS for simple CRUD
20
+ */
21
+
22
+ const { describe, it, beforeEach } = require('vitest');
23
+ const { strict: assert } = require('assert');
24
+
25
+ // Import Gate 1
26
+ const {
27
+ executeGate1,
28
+ checkGivenWhenThenFormat,
29
+ extractRequirementIds,
30
+ buildRequirementTaskMap,
31
+ buildRequirementPhaseMap,
32
+ } = require('../../ez-agents/bin/lib/gates/gate-01-requirement.cjs');
33
+
34
+ // Import Gate 2
35
+ const {
36
+ executeGate2,
37
+ countAbstractionLayers,
38
+ detectPrematureRepository,
39
+ detectUnnecessaryCQRS,
40
+ detectPrematureEventBus,
41
+ detectPrematureMicroservices,
42
+ checkSkillAlignment,
43
+ ABSTRACTION_THRESHOLDS,
44
+ } = require('../../ez-agents/bin/lib/gates/gate-02-architecture.cjs');
45
+
46
+ // Import QualityGate for integration test
47
+ const { QualityGate } = require('../../ez-agents/bin/lib/quality-gate.cjs');
48
+ const { registerGate1 } = require('../../ez-agents/bin/lib/gates/gate-01-requirement.cjs');
49
+ const { registerGate2 } = require('../../ez-agents/bin/lib/gates/gate-02-architecture.cjs');
50
+
51
+ describe('Gate 1: Requirement Completeness', () => {
52
+ describe('executeGate1', () => {
53
+ it('Gate 1 passes when all REQ-IDs mapped', async () => {
54
+ const context = {
55
+ requirements: [
56
+ {
57
+ id: 'REQ-001',
58
+ description: 'User can log in',
59
+ acceptanceCriteria: [
60
+ 'Given valid credentials, When login form submitted, Then user is authenticated',
61
+ ],
62
+ mappedTasks: ['task-001'],
63
+ },
64
+ {
65
+ id: 'REQ-002',
66
+ description: 'User can log out',
67
+ acceptanceCriteria: [
68
+ 'Given authenticated session, When logout clicked, Then session is terminated',
69
+ ],
70
+ mappedPhases: ['phase-01'],
71
+ },
72
+ ],
73
+ tasks: [
74
+ { id: 'task-001', name: 'Implement login', requirements: ['REQ-001'] },
75
+ ],
76
+ phases: [
77
+ { id: 'phase-01', name: 'Authentication', requirements: ['REQ-002'] },
78
+ ],
79
+ };
80
+
81
+ const result = await executeGate1(context);
82
+
83
+ assert.strictEqual(result.passed, true);
84
+ assert.strictEqual(result.errors.length, 0);
85
+ });
86
+
87
+ it('Gate 1 fails with errors for unmapped REQ-IDs', async () => {
88
+ const context = {
89
+ requirements: [
90
+ {
91
+ id: 'REQ-001',
92
+ description: 'User can log in',
93
+ acceptanceCriteria: [
94
+ 'Given valid credentials, When login form submitted, Then user is authenticated',
95
+ ],
96
+ // No mappedTasks or mappedPhases
97
+ },
98
+ {
99
+ id: 'REQ-002',
100
+ description: 'User can log out',
101
+ acceptanceCriteria: [
102
+ 'Given authenticated session, When logout clicked, Then session is terminated',
103
+ ],
104
+ mappedTasks: ['task-001'],
105
+ },
106
+ ],
107
+ tasks: [
108
+ { id: 'task-001', name: 'Implement logout', requirements: ['REQ-002'] },
109
+ ],
110
+ // No phases
111
+ };
112
+
113
+ const result = await executeGate1(context);
114
+
115
+ assert.strictEqual(result.passed, false);
116
+ assert.strictEqual(result.errors.length, 1);
117
+ assert.strictEqual(result.errors[0].path, 'requirements[0].id');
118
+ assert.ok(result.errors[0].message.includes('REQ-001'));
119
+ assert.ok(result.errors[0].message.includes('not mapped'));
120
+ });
121
+
122
+ it('Gate 1 passes when acceptance criteria in Given-When-Then', async () => {
123
+ const context = {
124
+ requirements: [
125
+ {
126
+ id: 'REQ-001',
127
+ description: 'User can reset password',
128
+ acceptanceCriteria: [
129
+ 'Given user has forgotten password, When reset link requested, Then email is sent',
130
+ ],
131
+ mappedTasks: ['task-001'],
132
+ },
133
+ ],
134
+ tasks: [
135
+ { id: 'task-001', name: 'Implement password reset', requirements: ['REQ-001'] },
136
+ ],
137
+ };
138
+
139
+ const result = await executeGate1(context);
140
+
141
+ assert.strictEqual(result.passed, true);
142
+ assert.strictEqual(result.errors.length, 0);
143
+ });
144
+
145
+ it('Gate 1 fails when acceptance criteria missing Given-When-Then', async () => {
146
+ const context = {
147
+ requirements: [
148
+ {
149
+ id: 'REQ-001',
150
+ description: 'User can reset password',
151
+ acceptanceCriteria: [
152
+ 'Password reset works', // Not in Given-When-Then format
153
+ ],
154
+ mappedTasks: ['task-001'],
155
+ },
156
+ ],
157
+ tasks: [
158
+ { id: 'task-001', name: 'Implement password reset', requirements: ['REQ-001'] },
159
+ ],
160
+ };
161
+
162
+ const result = await executeGate1(context);
163
+
164
+ assert.strictEqual(result.passed, false);
165
+ assert.strictEqual(result.errors.length, 1);
166
+ assert.strictEqual(result.errors[0].path, 'requirements[0].acceptanceCriteria');
167
+ assert.ok(result.errors[0].message.includes('Given-When-Then'));
168
+ });
169
+ });
170
+
171
+ describe('checkGivenWhenThenFormat', () => {
172
+ it('should validate proper Given-When-Then format', () => {
173
+ const result = checkGivenWhenThenFormat([
174
+ 'Given valid credentials, When login submitted, Then user authenticated',
175
+ ]);
176
+
177
+ assert.strictEqual(result.valid, true);
178
+ assert.strictEqual(result.missingComponents.length, 0);
179
+ });
180
+
181
+ it('should detect missing Given component', () => {
182
+ const result = checkGivenWhenThenFormat([
183
+ 'When login submitted, Then user authenticated',
184
+ ]);
185
+
186
+ assert.strictEqual(result.valid, false);
187
+ assert.ok(result.missingComponents.includes('Given'));
188
+ });
189
+
190
+ it('should detect missing When component', () => {
191
+ const result = checkGivenWhenThenFormat([
192
+ 'Given valid credentials, Then user authenticated',
193
+ ]);
194
+
195
+ assert.strictEqual(result.valid, false);
196
+ assert.ok(result.missingComponents.includes('When'));
197
+ });
198
+
199
+ it('should detect missing Then component', () => {
200
+ const result = checkGivenWhenThenFormat([
201
+ 'Given valid credentials, When login submitted',
202
+ ]);
203
+
204
+ assert.strictEqual(result.valid, false);
205
+ assert.ok(result.missingComponents.includes('Then'));
206
+ });
207
+
208
+ it('should handle multi-line format', () => {
209
+ const result = checkGivenWhenThenFormat([
210
+ 'Given user is on login page',
211
+ 'When user enters valid credentials',
212
+ 'Then user is redirected to dashboard',
213
+ ]);
214
+
215
+ assert.strictEqual(result.valid, true);
216
+ });
217
+
218
+ it('should handle format with colons', () => {
219
+ const result = checkGivenWhenThenFormat([
220
+ 'Given: user has valid session',
221
+ 'When: user clicks logout',
222
+ 'Then: session is destroyed',
223
+ ]);
224
+
225
+ assert.strictEqual(result.valid, true);
226
+ });
227
+ });
228
+
229
+ describe('extractRequirementIds', () => {
230
+ it('should extract REQ-IDs from text', () => {
231
+ const text = 'This implements REQ-001 and REQ-002 for the login feature';
232
+ const ids = extractRequirementIds(text);
233
+
234
+ assert.deepStrictEqual(ids, ['REQ-001', 'REQ-002']);
235
+ });
236
+
237
+ it('should extract various ID formats', () => {
238
+ const text = 'Covers GRAPH-01, GATE-02, and REQ-100';
239
+ const ids = extractRequirementIds(text);
240
+
241
+ assert.deepStrictEqual(ids.sort(), ['GATE-02', 'GRAPH-01', 'REQ-100'].sort());
242
+ });
243
+
244
+ it('should return empty array for no matches', () => {
245
+ const text = 'No requirement IDs here';
246
+ const ids = extractRequirementIds(text);
247
+
248
+ assert.deepStrictEqual(ids, []);
249
+ });
250
+
251
+ it('should deduplicate IDs', () => {
252
+ const text = 'REQ-001 is related to REQ-001';
253
+ const ids = extractRequirementIds(text);
254
+
255
+ assert.deepStrictEqual(ids, ['REQ-001']);
256
+ });
257
+ });
258
+
259
+ describe('buildRequirementTaskMap', () => {
260
+ it('should build map from task requirements', () => {
261
+ const tasks = [
262
+ { id: 'task-001', name: 'Login', requirements: ['REQ-001', 'REQ-002'] },
263
+ { id: 'task-002', name: 'Logout', requirements: ['REQ-003'] },
264
+ ];
265
+
266
+ const map = buildRequirementTaskMap(tasks);
267
+
268
+ assert.ok(map.has('REQ-001'));
269
+ assert.ok(map.has('REQ-002'));
270
+ assert.ok(map.has('REQ-003'));
271
+ assert.strictEqual(map.get('REQ-001').has('task-001'), true);
272
+ assert.strictEqual(map.get('REQ-003').has('task-002'), true);
273
+ });
274
+
275
+ it('should handle tasks without requirements', () => {
276
+ const tasks = [
277
+ { id: 'task-001', name: 'Setup' },
278
+ ];
279
+
280
+ const map = buildRequirementTaskMap(tasks);
281
+
282
+ assert.strictEqual(map.size, 0);
283
+ });
284
+
285
+ it('should handle empty task array', () => {
286
+ const map = buildRequirementTaskMap([]);
287
+ assert.strictEqual(map.size, 0);
288
+ });
289
+
290
+ it('should handle null/undefined input', () => {
291
+ assert.strictEqual(buildRequirementTaskMap(null).size, 0);
292
+ assert.strictEqual(buildRequirementTaskMap(undefined).size, 0);
293
+ });
294
+ });
295
+
296
+ describe('buildRequirementPhaseMap', () => {
297
+ it('should build map from phase requirements', () => {
298
+ const phases = [
299
+ { id: 'phase-01', name: 'Auth', requirements: ['REQ-001', 'REQ-002'] },
300
+ { id: 'phase-02', name: 'Dashboard', requirements: ['REQ-003'] },
301
+ ];
302
+
303
+ const map = buildRequirementPhaseMap(phases);
304
+
305
+ assert.ok(map.has('REQ-001'));
306
+ assert.ok(map.has('REQ-003'));
307
+ assert.strictEqual(map.get('REQ-001').has('phase-01'), true);
308
+ });
309
+ });
310
+ });
311
+
312
+ describe('Gate 2: Architecture Review', () => {
313
+ describe('executeGate2', () => {
314
+ it('Gate 2 passes when structure matches skill recommendations', async () => {
315
+ const context = {
316
+ projectTier: 'mvp',
317
+ architecture: {
318
+ abstractionLayers: 2,
319
+ patterns: ['controller', 'service'],
320
+ },
321
+ skillRecommendations: [
322
+ {
323
+ skillName: 'nodejs-mvp',
324
+ recommendedStructure: ['controller', 'service'],
325
+ bestPractices: ['Keep it simple'],
326
+ antiPatterns: [],
327
+ maxAbstractionLayers: 2,
328
+ },
329
+ ],
330
+ };
331
+
332
+ const result = await executeGate2(context);
333
+
334
+ assert.strictEqual(result.passed, true);
335
+ assert.strictEqual(result.errors.length, 0);
336
+ });
337
+
338
+ it('Gate 2 fails when structure deviates without justification', async () => {
339
+ const context = {
340
+ projectTier: 'mvp',
341
+ architecture: {
342
+ abstractionLayers: 4,
343
+ patterns: ['controller', 'service', 'repository', 'use-case', 'domain'],
344
+ },
345
+ };
346
+
347
+ const result = await executeGate2(context);
348
+
349
+ assert.strictEqual(result.passed, false);
350
+ assert.ok(result.errors.length > 0);
351
+ assert.ok(result.errors.some(e => e.path === 'architecture.abstractionLayers'));
352
+ });
353
+
354
+ it('Gate 2 counts abstraction layers correctly', async () => {
355
+ const context = {
356
+ projectTier: 'medium',
357
+ files: [
358
+ { path: '/controllers/UserController.js', type: 'controller' },
359
+ { path: '/services/UserService.js', type: 'service' },
360
+ { path: '/repositories/UserRepository.js', type: 'repository' },
361
+ { path: '/models/User.js', type: 'model' },
362
+ ],
363
+ };
364
+
365
+ const result = await executeGate2(context);
366
+
367
+ // 4 layers for medium tier (max 3) should fail
368
+ assert.strictEqual(result.passed, false);
369
+ assert.ok(result.errors.some(e => e.message.includes('abstraction layers')));
370
+ });
371
+
372
+ it('Gate 2 flags >3 abstraction layers as warning', async () => {
373
+ const context = {
374
+ projectTier: 'enterprise',
375
+ architecture: {
376
+ abstractionLayers: 4,
377
+ patterns: ['controller', 'service', 'repository', 'domain'],
378
+ },
379
+ };
380
+
381
+ const result = await executeGate2(context);
382
+
383
+ // Enterprise allows 4 layers, so it should pass but may have warnings
384
+ assert.strictEqual(result.passed, true);
385
+ // Check for warning about >3 layers
386
+ assert.ok(
387
+ result.warnings.some(w => w.includes('abstraction layers')) ||
388
+ result.errors.length === 0
389
+ );
390
+ });
391
+
392
+ it('Gate 2 detects premature repository pattern', async () => {
393
+ const context = {
394
+ projectTier: 'mvp',
395
+ hasRepositoryPattern: true,
396
+ crudOperationCount: 5,
397
+ };
398
+
399
+ const result = await executeGate2(context);
400
+
401
+ assert.strictEqual(result.passed, false);
402
+ assert.ok(result.errors.some(e => e.message.includes('Repository pattern')));
403
+ });
404
+
405
+ it('Gate 2 detects unnecessary CQRS for simple CRUD', async () => {
406
+ const context = {
407
+ projectTier: 'mvp',
408
+ hasCQRS: true,
409
+ crudOperationCount: 8,
410
+ eventCount: 2,
411
+ };
412
+
413
+ const result = await executeGate2(context);
414
+
415
+ assert.strictEqual(result.passed, false);
416
+ assert.ok(result.errors.some(e => e.message.includes('CQRS')));
417
+ });
418
+ });
419
+
420
+ describe('countAbstractionLayers', () => {
421
+ it('should count layers from file types', () => {
422
+ const files = [
423
+ { path: '/controllers/UserController.js', type: 'controller' },
424
+ { path: '/services/UserService.js', type: 'service' },
425
+ { path: '/models/User.js', type: 'model' },
426
+ ];
427
+
428
+ const layers = countAbstractionLayers(files);
429
+ assert.strictEqual(layers, 3);
430
+ });
431
+
432
+ it('should count layers from path inference', () => {
433
+ const files = [
434
+ { path: '/controllers/UserController.js' },
435
+ { path: '/services/UserService.js' },
436
+ { path: '/repositories/UserRepository.js' },
437
+ { path: '/models/User.js' },
438
+ ];
439
+
440
+ const layers = countAbstractionLayers(files);
441
+ assert.strictEqual(layers, 4);
442
+ });
443
+
444
+ it('should use explicit layer property', () => {
445
+ const files = [
446
+ { path: '/file1.js', layer: 0 },
447
+ { path: '/file2.js', layer: 1 },
448
+ { path: '/file3.js', layer: 2 },
449
+ { path: '/file4.js', layer: 3 },
450
+ ];
451
+
452
+ const layers = countAbstractionLayers(files);
453
+ assert.strictEqual(layers, 3);
454
+ });
455
+
456
+ it('should return 0 for empty array', () => {
457
+ const layers = countAbstractionLayers([]);
458
+ assert.strictEqual(layers, 0);
459
+ });
460
+
461
+ it('should handle middleware layer', () => {
462
+ const files = [
463
+ { path: '/middleware/AuthMiddleware.js', type: 'middleware' },
464
+ { path: '/controllers/UserController.js', type: 'controller' },
465
+ { path: '/services/UserService.js', type: 'service' },
466
+ ];
467
+
468
+ const layers = countAbstractionLayers(files);
469
+ assert.strictEqual(layers, 3);
470
+ });
471
+ });
472
+
473
+ describe('detectPrematureRepository', () => {
474
+ it('should detect repository pattern in MVP with simple CRUD', () => {
475
+ const context = {
476
+ projectTier: 'mvp',
477
+ hasRepositoryPattern: true,
478
+ crudOperationCount: 5,
479
+ };
480
+
481
+ const result = detectPrematureRepository(context);
482
+
483
+ assert.strictEqual(result.detected, true);
484
+ assert.ok(result.reason.includes('Repository pattern'));
485
+ });
486
+
487
+ it('should not detect when CRUD count is high', () => {
488
+ const context = {
489
+ projectTier: 'mvp',
490
+ hasRepositoryPattern: true,
491
+ crudOperationCount: 15,
492
+ };
493
+
494
+ const result = detectPrematureRepository(context);
495
+
496
+ assert.strictEqual(result.detected, false);
497
+ });
498
+
499
+ it('should allow with justification', () => {
500
+ const context = {
501
+ projectTier: 'mvp',
502
+ hasRepositoryPattern: true,
503
+ crudOperationCount: 5,
504
+ architecture: {
505
+ justifications: {
506
+ repository: 'Multiple data sources require abstraction',
507
+ },
508
+ },
509
+ };
510
+
511
+ const result = detectPrematureRepository(context);
512
+
513
+ assert.strictEqual(result.detected, false);
514
+ });
515
+
516
+ it('should not detect for medium tier', () => {
517
+ const context = {
518
+ projectTier: 'medium',
519
+ hasRepositoryPattern: true,
520
+ crudOperationCount: 8,
521
+ };
522
+
523
+ const result = detectPrematureRepository(context);
524
+
525
+ assert.strictEqual(result.detected, false);
526
+ });
527
+ });
528
+
529
+ describe('detectUnnecessaryCQRS', () => {
530
+ it('should detect CQRS for simple CRUD', () => {
531
+ const context = {
532
+ projectTier: 'mvp',
533
+ hasCQRS: true,
534
+ crudOperationCount: 8,
535
+ eventCount: 2,
536
+ };
537
+
538
+ const result = detectUnnecessaryCQRS(context);
539
+
540
+ assert.strictEqual(result.detected, true);
541
+ assert.ok(result.reason.includes('CQRS'));
542
+ });
543
+
544
+ it('should not detect CQRS with high event count', () => {
545
+ const context = {
546
+ projectTier: 'medium',
547
+ hasCQRS: true,
548
+ crudOperationCount: 20,
549
+ eventCount: 15,
550
+ };
551
+
552
+ const result = detectUnnecessaryCQRS(context);
553
+
554
+ assert.strictEqual(result.detected, false);
555
+ });
556
+
557
+ it('should allow CQRS with justification', () => {
558
+ const context = {
559
+ projectTier: 'mvp',
560
+ hasCQRS: true,
561
+ crudOperationCount: 8,
562
+ eventCount: 2,
563
+ architecture: {
564
+ justifications: {
565
+ cqrs: 'Complex read/write separation required for reporting',
566
+ },
567
+ },
568
+ };
569
+
570
+ const result = detectUnnecessaryCQRS(context);
571
+
572
+ assert.strictEqual(result.detected, false);
573
+ });
574
+ });
575
+
576
+ describe('detectPrematureEventBus', () => {
577
+ it('should detect event bus with few events', () => {
578
+ const context = {
579
+ hasEventBus: true,
580
+ eventCount: 2,
581
+ };
582
+
583
+ const result = detectPrematureEventBus(context);
584
+
585
+ assert.strictEqual(result.detected, true);
586
+ assert.ok(result.reason.includes('Event bus'));
587
+ });
588
+
589
+ it('should not detect event bus with many events', () => {
590
+ const context = {
591
+ hasEventBus: true,
592
+ eventCount: 10,
593
+ };
594
+
595
+ const result = detectPrematureEventBus(context);
596
+
597
+ assert.strictEqual(result.detected, false);
598
+ });
599
+ });
600
+
601
+ describe('detectPrematureMicroservices', () => {
602
+ it('should detect microservices in MVP', () => {
603
+ const context = {
604
+ projectTier: 'mvp',
605
+ hasMicroservices: true,
606
+ };
607
+
608
+ const result = detectPrematureMicroservices(context);
609
+
610
+ assert.strictEqual(result.detected, true);
611
+ assert.ok(result.reason.includes('Microservices'));
612
+ });
613
+
614
+ it('should allow microservices with justification', () => {
615
+ const context = {
616
+ projectTier: 'mvp',
617
+ hasMicroservices: true,
618
+ architecture: {
619
+ justifications: {
620
+ microservices: 'Existing domain boundaries from legacy system',
621
+ },
622
+ },
623
+ };
624
+
625
+ const result = detectPrematureMicroservices(context);
626
+
627
+ assert.strictEqual(result.detected, false);
628
+ });
629
+
630
+ it('should not detect for enterprise tier', () => {
631
+ const context = {
632
+ projectTier: 'enterprise',
633
+ hasMicroservices: true,
634
+ };
635
+
636
+ const result = detectPrematureMicroservices(context);
637
+
638
+ // Enterprise without justification still warns
639
+ assert.strictEqual(result.detected, true);
640
+ });
641
+ });
642
+
643
+ describe('checkSkillAlignment', () => {
644
+ it('should return empty deviations when aligned', () => {
645
+ const skillRecommendations = [
646
+ {
647
+ skillName: 'nodejs-mvp',
648
+ recommendedStructure: ['controller', 'service'],
649
+ antiPatterns: ['repository'],
650
+ },
651
+ ];
652
+
653
+ const architecture = {
654
+ patterns: ['controller', 'service'],
655
+ };
656
+
657
+ const result = checkSkillAlignment(skillRecommendations, architecture);
658
+
659
+ assert.strictEqual(result.deviations.length, 0);
660
+ });
661
+
662
+ it('should detect anti-pattern usage', () => {
663
+ const skillRecommendations = [
664
+ {
665
+ skillName: 'nodejs-mvp',
666
+ recommendedStructure: ['controller', 'service'],
667
+ antiPatterns: ['repository', 'cqrs'],
668
+ bestPractices: ['Keep it simple'],
669
+ },
670
+ ];
671
+
672
+ const architecture = {
673
+ patterns: ['controller', 'service', 'repository'],
674
+ };
675
+
676
+ const result = checkSkillAlignment(skillRecommendations, architecture);
677
+
678
+ assert.strictEqual(result.deviations.length, 1);
679
+ assert.strictEqual(result.deviations[0].skill, 'nodejs-mvp');
680
+ assert.ok(result.deviations[0].deviation.includes('repository'));
681
+ });
682
+
683
+ it('should detect abstraction layer violations', () => {
684
+ const skillRecommendations = [
685
+ {
686
+ skillName: 'nodejs-mvp',
687
+ maxAbstractionLayers: 2,
688
+ },
689
+ ];
690
+
691
+ const architecture = {
692
+ abstractionLayers: 4,
693
+ };
694
+
695
+ const result = checkSkillAlignment(skillRecommendations, architecture);
696
+
697
+ assert.strictEqual(result.deviations.length, 1);
698
+ assert.ok(result.deviations[0].deviation.includes('Abstraction layers'));
699
+ });
700
+
701
+ it('should handle empty skill recommendations', () => {
702
+ const result = checkSkillAlignment([], { patterns: ['controller'] });
703
+
704
+ assert.strictEqual(result.deviations.length, 0);
705
+ assert.strictEqual(result.matched.length, 0);
706
+ });
707
+ });
708
+
709
+ describe('ABSTRACTION_THRESHOLDS', () => {
710
+ it('should have correct thresholds for each tier', () => {
711
+ assert.strictEqual(ABSTRACTION_THRESHOLDS.mvp, 2);
712
+ assert.strictEqual(ABSTRACTION_THRESHOLDS.medium, 3);
713
+ assert.strictEqual(ABSTRACTION_THRESHOLDS.enterprise, 4);
714
+ });
715
+ });
716
+ });
717
+
718
+ describe('Gate Integration Tests', () => {
719
+ let gates;
720
+
721
+ beforeEach(() => {
722
+ gates = new QualityGate();
723
+ });
724
+
725
+ it('Gate 1 registers with QualityGate coordinator', () => {
726
+ registerGate1(gates);
727
+
728
+ const registeredGates = gates.getRegisteredGates();
729
+ assert.ok(registeredGates.includes('gate-01-requirement'));
730
+ });
731
+
732
+ it('Gate 2 registers with QualityGate coordinator', () => {
733
+ registerGate2(gates);
734
+
735
+ const registeredGates = gates.getRegisteredGates();
736
+ assert.ok(registeredGates.includes('gate-02-architecture'));
737
+ });
738
+
739
+ it('Both gates execute successfully through coordinator', async () => {
740
+ registerGate1(gates);
741
+ registerGate2(gates);
742
+
743
+ const gate1Context = {
744
+ requirements: [
745
+ {
746
+ id: 'REQ-001',
747
+ description: 'User can log in',
748
+ acceptanceCriteria: [
749
+ 'Given valid credentials, When login submitted, Then authenticated',
750
+ ],
751
+ mappedTasks: ['task-001'],
752
+ },
753
+ ],
754
+ tasks: [
755
+ { id: 'task-001', name: 'Implement login', requirements: ['REQ-001'] },
756
+ ],
757
+ };
758
+
759
+ const gate2Context = {
760
+ projectTier: 'mvp',
761
+ architecture: {
762
+ abstractionLayers: 2,
763
+ patterns: ['controller', 'service'],
764
+ },
765
+ };
766
+
767
+ const gate1Result = await gates.executeGate('gate-01-requirement', gate1Context);
768
+ const gate2Result = await gates.executeGate('gate-02-architecture', gate2Context);
769
+
770
+ assert.strictEqual(gate1Result.passed, true);
771
+ assert.strictEqual(gate2Result.passed, true);
772
+ });
773
+
774
+ it('Gate 1 fails through coordinator for unmapped requirements', async () => {
775
+ registerGate1(gates);
776
+
777
+ const context = {
778
+ requirements: [
779
+ {
780
+ id: 'REQ-001',
781
+ description: 'User can log in',
782
+ acceptanceCriteria: [
783
+ 'Given valid credentials, When login submitted, Then authenticated',
784
+ ],
785
+ // No mapping
786
+ },
787
+ ],
788
+ };
789
+
790
+ const result = await gates.executeGate('gate-01-requirement', context);
791
+
792
+ assert.strictEqual(result.passed, false);
793
+ assert.ok(result.errors.length > 0);
794
+ });
795
+
796
+ it('Gate 2 fails through coordinator for overengineering', async () => {
797
+ registerGate2(gates);
798
+
799
+ const context = {
800
+ projectTier: 'mvp',
801
+ hasRepositoryPattern: true,
802
+ hasCQRS: true,
803
+ crudOperationCount: 5,
804
+ eventCount: 2,
805
+ };
806
+
807
+ const result = await gates.executeGate('gate-02-architecture', context);
808
+
809
+ assert.strictEqual(result.passed, false);
810
+ assert.ok(result.errors.length > 0);
811
+ });
812
+ });