@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,762 @@
1
+ /**
2
+ * Gate 3-4 Tests
3
+ *
4
+ * Tests for Code Quality (Gate 3) and Security Baseline (Gate 4)
5
+ *
6
+ * Test cases:
7
+ * Gate 3:
8
+ * 1. Gate 3 passes for clean code with short functions
9
+ * 2. Gate 3 flags functions > 50 lines
10
+ * 3. Gate 3 flags nesting > 4 levels
11
+ * 4. Gate 3 detects magic numbers without named constants
12
+ * 5. Gate 3 detects generic helper sprawl
13
+ *
14
+ * Gate 4:
15
+ * 6. Gate 4 passes when auth uses secure session management
16
+ * 7. Gate 4 flags hardcoded credentials
17
+ * 8. Gate 4 flags eval() usage
18
+ * 9. Gate 4 flags execSync with user input
19
+ * 10. Gate 4 flags SQL query concatenation
20
+ * 11. Gate 4 passes when env vars used for secrets
21
+ * 12. Gate 4 flags missing input validation
22
+ */
23
+
24
+ const { describe, it, beforeEach } = require('node:test');
25
+ const { strict: assert } = require('node:assert');
26
+
27
+ // Import Gate 3
28
+ const {
29
+ executeGate3,
30
+ checkFunctionLength,
31
+ calculateNestingDepth,
32
+ detectMagicNumbers,
33
+ detectGenericHelperSprawl,
34
+ THRESHOLDS,
35
+ } = require('../../bin/lib/gates/gate-03-code.cjs');
36
+
37
+ // Import Gate 4
38
+ const {
39
+ executeGate4,
40
+ detectEvalUsage,
41
+ detectExecUsage,
42
+ detectSqlInjection,
43
+ detectHardcodedSecrets,
44
+ checkSessionSecurity,
45
+ checkEnvVarUsage,
46
+ } = require('../../bin/lib/gates/gate-04-security.cjs');
47
+
48
+ // Import QualityGate for integration test
49
+ const { QualityGate } = require('../../bin/lib/quality-gate.cjs');
50
+ const { registerGate3 } = require('../../bin/lib/gates/gate-03-code.cjs');
51
+ const { registerGate4 } = require('../../bin/lib/gates/gate-04-security.cjs');
52
+
53
+ describe('Gate 3: Code Quality', () => {
54
+ describe('executeGate3', () => {
55
+ it('Gate 3 passes for clean code with short functions', async () => {
56
+ const context = {
57
+ files: [
58
+ {
59
+ path: '/src/utils.js',
60
+ content: `
61
+ function add(a, b) {
62
+ return a + b;
63
+ }
64
+
65
+ function greet(name) {
66
+ return 'Hello, ' + name;
67
+ }
68
+ `,
69
+ functions: [
70
+ {
71
+ name: 'add',
72
+ startLine: 1,
73
+ endLine: 3,
74
+ body: 'function add(a, b) {\n return a + b;\n}',
75
+ parameters: ['a', 'b'],
76
+ },
77
+ {
78
+ name: 'greet',
79
+ startLine: 5,
80
+ endLine: 7,
81
+ body: "function greet(name) {\n return 'Hello, ' + name;\n}",
82
+ parameters: ['name'],
83
+ },
84
+ ],
85
+ },
86
+ ],
87
+ };
88
+
89
+ const result = await executeGate3(context);
90
+
91
+ assert.strictEqual(result.passed, true);
92
+ assert.strictEqual(result.errors.length, 0);
93
+ });
94
+
95
+ it('Gate 3 flags functions > 50 lines', async () => {
96
+ // Generate a function with 55 lines
97
+ const longFunctionBody = 'function longFunction() {\n' +
98
+ Array(55).fill(' console.log("line");').join('\n') +
99
+ '\n}';
100
+
101
+ const context = {
102
+ files: [
103
+ {
104
+ path: '/src/long.js',
105
+ content: longFunctionBody,
106
+ functions: [
107
+ {
108
+ name: 'longFunction',
109
+ startLine: 1,
110
+ endLine: 56,
111
+ body: longFunctionBody,
112
+ parameters: [],
113
+ },
114
+ ],
115
+ },
116
+ ],
117
+ };
118
+
119
+ const result = await executeGate3(context);
120
+
121
+ assert.strictEqual(result.passed, false);
122
+ assert.ok(result.errors.length > 0);
123
+ assert.ok(result.errors.some(e => e.message.includes('longFunction')));
124
+ assert.ok(result.errors.some(e => e.message.includes('lines')));
125
+ });
126
+
127
+ it('Gate 3 flags nesting > 4 levels', async () => {
128
+ const deeplyNestedCode = `
129
+ function process() {
130
+ if (true) {
131
+ for (let i = 0; i < 10; i++) {
132
+ while (true) {
133
+ switch (x) {
134
+ case 1:
135
+ if (y) {
136
+ console.log('too deep');
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ `;
144
+
145
+ const context = {
146
+ files: [
147
+ {
148
+ path: '/src/nested.js',
149
+ content: deeplyNestedCode,
150
+ },
151
+ ],
152
+ };
153
+
154
+ const result = await executeGate3(context);
155
+
156
+ assert.strictEqual(result.passed, false);
157
+ assert.ok(result.errors.length > 0);
158
+ assert.ok(result.errors.some(e => e.message.includes('Nesting')));
159
+ });
160
+
161
+ it('Gate 3 detects magic numbers without named constants', async () => {
162
+ const codeWithMagicNumbers = `
163
+ function calculate() {
164
+ const tax = 1250 * 0.0875;
165
+ const discount = price * 0.15;
166
+ const shipping = 49.99;
167
+ return tax + discount + shipping;
168
+ }
169
+ `;
170
+
171
+ const context = {
172
+ files: [
173
+ {
174
+ path: '/src/calc.js',
175
+ content: codeWithMagicNumbers,
176
+ },
177
+ ],
178
+ namedConstants: [],
179
+ };
180
+
181
+ const result = await executeGate3(context);
182
+
183
+ assert.strictEqual(result.passed, true); // Magic numbers are warnings, not errors
184
+ assert.ok(result.warnings.length > 0);
185
+ assert.ok(result.warnings.some(w => w.includes('Magic number')));
186
+ });
187
+
188
+ it('Gate 3 detects generic helper sprawl', async () => {
189
+ const context = {
190
+ genericHelpers: [
191
+ { name: 'utils', usageCount: 5 },
192
+ { name: 'helpers', usageCount: 10 },
193
+ { name: 'common', usageCount: 0 },
194
+ ],
195
+ };
196
+
197
+ const result = await executeGate3(context);
198
+
199
+ assert.strictEqual(result.passed, true); // Helper sprawl is a warning
200
+ assert.ok(result.warnings.length > 0);
201
+ assert.ok(result.warnings.some(w => w.includes('Generic helper') || w.includes('utils') || w.includes('helpers')));
202
+ });
203
+ });
204
+
205
+ describe('checkFunctionLength', () => {
206
+ it('should pass for short functions', () => {
207
+ const shortBody = 'function test() {\n return 1;\n}';
208
+ const result = checkFunctionLength(shortBody);
209
+ assert.strictEqual(result.exceeds, false);
210
+ assert.strictEqual(result.length, 3);
211
+ });
212
+
213
+ it('should fail for long functions', () => {
214
+ const longBody = 'function test() {\n' +
215
+ Array(60).fill(' console.log("line");').join('\n') +
216
+ '\n}';
217
+ const result = checkFunctionLength(longBody);
218
+ assert.strictEqual(result.exceeds, true);
219
+ assert.ok(result.length > THRESHOLDS.maxFunctionLength);
220
+ });
221
+ });
222
+
223
+ describe('calculateNestingDepth', () => {
224
+ it('should calculate nesting depth correctly', () => {
225
+ const code = `
226
+ function test() {
227
+ if (true) {
228
+ for (let i = 0; i < 10; i++) {
229
+ while (true) {
230
+ console.log('deep');
231
+ }
232
+ }
233
+ }
234
+ }
235
+ `;
236
+ const depth = calculateNestingDepth(code);
237
+ // The function counts brace nesting: function->if->for->while = 4 levels
238
+ // But subtracts 1 for the outermost scope, so expected is 3
239
+ assert.strictEqual(depth, 3); // if -> for -> while
240
+ });
241
+
242
+ it('should return 0 for flat code', () => {
243
+ const code = 'const x = 1;\nconst y = 2;';
244
+ const depth = calculateNestingDepth(code);
245
+ assert.strictEqual(depth, 0);
246
+ });
247
+
248
+ it('should handle shallow nesting', () => {
249
+ const code = `
250
+ if (true) {
251
+ console.log('hello');
252
+ }
253
+ `;
254
+ const depth = calculateNestingDepth(code);
255
+ // Single if block = 1 level of braces, but no outer function scope
256
+ // So depth is 0 (we subtract 1 for the outermost scope)
257
+ assert.strictEqual(depth, 0);
258
+ });
259
+ });
260
+
261
+ describe('detectMagicNumbers', () => {
262
+ it('should detect magic numbers', () => {
263
+ const code = 'const x = 42; const y = 100;';
264
+ const magicNumbers = detectMagicNumbers(code);
265
+ assert.ok(magicNumbers.length > 0);
266
+ assert.ok(magicNumbers.some(m => m.value === 42));
267
+ });
268
+
269
+ it('should ignore 0, 1, 2', () => {
270
+ const code = 'for (let i = 0; i < 10; i += 1) { const x = 2; }';
271
+ const magicNumbers = detectMagicNumbers(code);
272
+ // 10 should still be detected
273
+ assert.ok(magicNumbers.some(m => m.value === 10));
274
+ });
275
+
276
+ it('should skip named constants', () => {
277
+ const code = 'const TAX_RATE = 0.0875; const tax = price * TAX_RATE;';
278
+ const namedConstants = [{ name: 'TAX_RATE', value: 0.0875 }];
279
+ const magicNumbers = detectMagicNumbers(code, namedConstants);
280
+ // Should not flag 0.0875 since it's a named constant
281
+ assert.strictEqual(magicNumbers.length, 0);
282
+ });
283
+
284
+ it('should skip numbers in strings', () => {
285
+ const code = 'const msg = "Price is 99.99"; const x = 42;';
286
+ const magicNumbers = detectMagicNumbers(code);
287
+ // Should only flag 42, not 99.99 in string
288
+ assert.ok(magicNumbers.some(m => m.value === 42));
289
+ assert.ok(!magicNumbers.some(m => m.value === 99.99));
290
+ });
291
+ });
292
+
293
+ describe('detectGenericHelperSprawl', () => {
294
+ it('should detect sprawl for generic helper names', () => {
295
+ const helpers = [
296
+ { name: 'utils', usageCount: 5 },
297
+ { name: 'helpers', usageCount: 10 },
298
+ ];
299
+ const issues = detectGenericHelperSprawl(helpers);
300
+ assert.ok(issues.length > 0);
301
+ assert.ok(issues.some(i => i.name === 'utils' || i.name === 'helpers'));
302
+ });
303
+
304
+ it('should not flag specific helper names', () => {
305
+ const helpers = [
306
+ { name: 'stringUtils', usageCount: 5 },
307
+ { name: 'dateHelpers', usageCount: 3 },
308
+ ];
309
+ const issues = detectGenericHelperSprawl(helpers);
310
+ assert.strictEqual(issues.length, 0);
311
+ });
312
+
313
+ it('should flag unused generic helpers', () => {
314
+ const helpers = [
315
+ { name: 'utils', usageCount: 0 },
316
+ ];
317
+ const issues = detectGenericHelperSprawl(helpers);
318
+ assert.ok(issues.length > 0);
319
+ assert.ok(issues.some(i => i.issue.includes('Unused')));
320
+ });
321
+ });
322
+ });
323
+
324
+ describe('Gate 4: Security Baseline', () => {
325
+ describe('executeGate4', () => {
326
+ it('Gate 4 passes when auth uses secure session management', async () => {
327
+ const secureCode = `
328
+ const session = require('express-session');
329
+ const RedisStore = require('connect-redis')(session);
330
+
331
+ app.use(session({
332
+ store: new RedisStore({ client: redisClient }),
333
+ secret: process.env.SESSION_SECRET,
334
+ resave: false,
335
+ saveUninitialized: false,
336
+ cookie: {
337
+ secure: true,
338
+ httpOnly: true,
339
+ sameSite: 'strict',
340
+ maxAge: 3600000
341
+ }
342
+ }));
343
+ `;
344
+
345
+ const context = {
346
+ files: [
347
+ {
348
+ path: '/src/auth.js',
349
+ content: secureCode,
350
+ },
351
+ ],
352
+ authConfig: {
353
+ method: 'session',
354
+ sessionStore: 'redis',
355
+ httpsEnforced: true,
356
+ csrfProtection: true,
357
+ hashingAlgorithm: 'bcrypt',
358
+ },
359
+ };
360
+
361
+ const result = await executeGate4(context);
362
+
363
+ assert.strictEqual(result.passed, true);
364
+ assert.strictEqual(result.errors.length, 0);
365
+ });
366
+
367
+ it('Gate 4 flags hardcoded credentials', async () => {
368
+ const insecureCode = `
369
+ const config = {
370
+ dbPassword: 'super_secret_password123',
371
+ apiKey: 'sk_live_abcdef1234567890abcdef',
372
+ awsKey: 'AKIAIOSFODNN7EXAMPLE'
373
+ };
374
+ `;
375
+
376
+ const context = {
377
+ files: [
378
+ {
379
+ path: '/src/config.js',
380
+ content: insecureCode,
381
+ },
382
+ ],
383
+ };
384
+
385
+ const result = await executeGate4(context);
386
+
387
+ assert.strictEqual(result.passed, false);
388
+ assert.ok(result.errors.length > 0);
389
+ assert.ok(result.errors.some(e => e.message.includes('password') || e.message.includes('secret') || e.message.includes('API')));
390
+ });
391
+
392
+ it('Gate 4 flags eval() usage', async () => {
393
+ const codeWithEval = `
394
+ function processUserInput(input) {
395
+ const result = eval(input);
396
+ return result;
397
+ }
398
+ `;
399
+
400
+ const context = {
401
+ files: [
402
+ {
403
+ path: '/src/dangerous.js',
404
+ content: codeWithEval,
405
+ },
406
+ ],
407
+ };
408
+
409
+ const result = await executeGate4(context);
410
+
411
+ assert.strictEqual(result.passed, false);
412
+ assert.ok(result.errors.length > 0);
413
+ assert.ok(result.errors.some(e => e.message.includes('eval')));
414
+ });
415
+
416
+ it('Gate 4 flags execSync with user input', async () => {
417
+ const codeWithExec = `
418
+ const { execSync } = require('child_process');
419
+
420
+ function runCommand(userInput) {
421
+ const result = execSync('echo ' + userInput, { encoding: 'utf-8' });
422
+ return result;
423
+ }
424
+ `;
425
+
426
+ const context = {
427
+ files: [
428
+ {
429
+ path: '/src/exec.js',
430
+ content: codeWithExec,
431
+ },
432
+ ],
433
+ };
434
+
435
+ const result = await executeGate4(context);
436
+
437
+ assert.strictEqual(result.passed, false);
438
+ assert.ok(result.errors.length > 0);
439
+ assert.ok(result.errors.some(e => e.message.includes('execSync') || e.message.includes('command injection')));
440
+ });
441
+
442
+ it('Gate 4 flags SQL query concatenation', async () => {
443
+ const codeWithSqlInjection = `
444
+ function getUserById(id) {
445
+ const query = 'SELECT * FROM users WHERE id = ' + id;
446
+ return db.query(query);
447
+ }
448
+
449
+ function searchUsers(name) {
450
+ return db.execute(\`SELECT * FROM users WHERE name = '\${name}'\`);
451
+ }
452
+ `;
453
+
454
+ const context = {
455
+ files: [
456
+ {
457
+ path: '/src/db.js',
458
+ content: codeWithSqlInjection,
459
+ },
460
+ ],
461
+ };
462
+
463
+ const result = await executeGate4(context);
464
+
465
+ assert.strictEqual(result.passed, false);
466
+ assert.ok(result.errors.length > 0);
467
+ assert.ok(result.errors.some(e => e.message.includes('SQL') || e.message.includes('parameterized')));
468
+ });
469
+
470
+ it('Gate 4 passes when env vars used for secrets', async () => {
471
+ const secureCode = `
472
+ const config = {
473
+ dbPassword: process.env.DB_PASSWORD,
474
+ apiKey: process.env.API_KEY,
475
+ jwtSecret: process.env.JWT_SECRET,
476
+ sessionSecret: process.env.SESSION_SECRET
477
+ };
478
+ `;
479
+
480
+ const context = {
481
+ files: [
482
+ {
483
+ path: '/src/config.js',
484
+ content: secureCode,
485
+ },
486
+ ],
487
+ };
488
+
489
+ const result = await executeGate4(context);
490
+
491
+ assert.strictEqual(result.passed, true);
492
+ assert.strictEqual(result.errors.length, 0);
493
+ });
494
+
495
+ it('Gate 4 flags missing input validation', async () => {
496
+ const codeWithoutValidation = `
497
+ app.post('/api/users', (req, res) => {
498
+ const { name, email, age } = req.body;
499
+ db.insert({ name, email, age });
500
+ res.json({ success: true });
501
+ });
502
+ `;
503
+
504
+ const context = {
505
+ files: [
506
+ {
507
+ path: '/src/routes.js',
508
+ content: codeWithoutValidation,
509
+ },
510
+ ],
511
+ hasInputValidation: false,
512
+ };
513
+
514
+ const result = await executeGate4(context);
515
+
516
+ assert.strictEqual(result.passed, false);
517
+ assert.ok(result.errors.length > 0);
518
+ assert.ok(result.errors.some(e => e.message.includes('input validation') || e.message.includes('Validation')));
519
+ });
520
+ });
521
+
522
+ describe('detectEvalUsage', () => {
523
+ it('should detect eval() calls', () => {
524
+ const code = 'const result = eval("1 + 1");';
525
+ const issues = detectEvalUsage(code);
526
+ assert.ok(issues.length > 0);
527
+ assert.ok(issues.some(i => i.type === 'eval'));
528
+ });
529
+
530
+ it('should detect Function constructor', () => {
531
+ const code = 'const fn = new Function("a", "b", "return a + b");';
532
+ const issues = detectEvalUsage(code);
533
+ assert.ok(issues.length > 0);
534
+ assert.ok(issues.some(i => i.type === 'function-constructor'));
535
+ });
536
+
537
+ it('should return empty for safe code', () => {
538
+ const code = 'const result = JSON.parse("{\"x\": 1}");';
539
+ const issues = detectEvalUsage(code);
540
+ assert.strictEqual(issues.length, 0);
541
+ });
542
+ });
543
+
544
+ describe('detectExecUsage', () => {
545
+ it('should detect execSync with user input', () => {
546
+ const code = 'execSync("ls " + req.params.path);';
547
+ const issues = detectExecUsage(code);
548
+ assert.ok(issues.length > 0);
549
+ assert.ok(issues.some(i => i.type === 'execSync-user-input'));
550
+ });
551
+
552
+ it('should warn about execSync without obvious user input', () => {
553
+ const code = 'execSync("npm install");';
554
+ const issues = detectExecUsage(code);
555
+ assert.ok(issues.length > 0);
556
+ assert.ok(issues.some(i => i.severity === 'warning'));
557
+ });
558
+ });
559
+
560
+ describe('detectSqlInjection', () => {
561
+ it('should detect string concatenation in SQL', () => {
562
+ const code = "db.query('SELECT * FROM users WHERE id = ' + userId);";
563
+ const issues = detectSqlInjection(code);
564
+ assert.ok(issues.length > 0);
565
+ assert.ok(issues.some(i => i.message.includes('SQL')));
566
+ });
567
+
568
+ it('should detect template literal SQL injection', () => {
569
+ const code = 'db.execute(`SELECT * FROM users WHERE name = "${name}"`);';
570
+ const issues = detectSqlInjection(code);
571
+ assert.ok(issues.length > 0);
572
+ assert.ok(issues.some(i => i.message.includes('parameterized')));
573
+ });
574
+ });
575
+
576
+ describe('detectHardcodedSecrets', () => {
577
+ it('should detect AWS keys', () => {
578
+ const code = "const key = 'AKIAIOSFODNN7EXAMPLE';";
579
+ const issues = detectHardcodedSecrets(code);
580
+ assert.ok(issues.length > 0);
581
+ assert.ok(issues.some(i => i.message.includes('AWS')));
582
+ });
583
+
584
+ it('should detect API keys', () => {
585
+ const code = "const apiKey = 'api_key_1234567890abcdef';";
586
+ const issues = detectHardcodedSecrets(code);
587
+ assert.ok(issues.length > 0);
588
+ assert.ok(issues.some(i => i.message.includes('API key')));
589
+ });
590
+
591
+ it('should detect passwords', () => {
592
+ const code = "const password = 'mySecretPassword123';";
593
+ const issues = detectHardcodedSecrets(code);
594
+ assert.ok(issues.length > 0);
595
+ assert.ok(issues.some(i => i.message.toLowerCase().includes('password')));
596
+ });
597
+
598
+ it('should skip process.env usage', () => {
599
+ const code = "const secret = process.env.SECRET_KEY;";
600
+ const issues = detectHardcodedSecrets(code);
601
+ assert.strictEqual(issues.length, 0);
602
+ });
603
+
604
+ it('should skip example values', () => {
605
+ const code = "const apiKey = 'YOUR_API_KEY_HERE';";
606
+ const issues = detectHardcodedSecrets(code);
607
+ assert.strictEqual(issues.length, 0);
608
+ });
609
+ });
610
+
611
+ describe('checkSessionSecurity', () => {
612
+ it('should detect insecure session config', () => {
613
+ const code = `
614
+ app.use(session({
615
+ cookie: {
616
+ secure: false,
617
+ httpOnly: false
618
+ }
619
+ }));
620
+ `;
621
+ const result = checkSessionSecurity(code);
622
+ assert.strictEqual(result.secure, false);
623
+ assert.ok(result.issues.length > 0);
624
+ });
625
+
626
+ it('should flag memory session store', () => {
627
+ const code = 'app.use(session({}));';
628
+ const result = checkSessionSecurity(code, { sessionStore: 'memory' });
629
+ assert.strictEqual(result.secure, false);
630
+ assert.ok(result.issues.some(i => i.message.includes('memory')));
631
+ });
632
+
633
+ it('should flag weak hashing algorithm', () => {
634
+ const code = 'app.use(session({}));';
635
+ const result = checkSessionSecurity(code, { hashingAlgorithm: 'md5' });
636
+ assert.strictEqual(result.secure, false);
637
+ assert.ok(result.issues.some(i => i.message.includes('md5') || i.message.includes('Weak')));
638
+ });
639
+ });
640
+
641
+ describe('checkEnvVarUsage', () => {
642
+ it('should recognize process.env usage', () => {
643
+ const code = 'const secret = process.env.SECRET_KEY;';
644
+ const result = checkEnvVarUsage(code);
645
+ assert.strictEqual(result.usesEnvVars, true);
646
+ assert.strictEqual(result.issues.length, 0);
647
+ });
648
+
649
+ it('should flag hardcoded sensitive values', () => {
650
+ const code = "const password = 'secret123';";
651
+ const result = checkEnvVarUsage(code);
652
+ assert.ok(result.issues.length > 0);
653
+ assert.ok(result.issues.some(i => i.message.includes('password')));
654
+ });
655
+ });
656
+ });
657
+
658
+ describe('Gate Integration Tests', () => {
659
+ let gates;
660
+
661
+ beforeEach(() => {
662
+ gates = new QualityGate();
663
+ });
664
+
665
+ it('Gate 3 registers with QualityGate coordinator', () => {
666
+ registerGate3(gates);
667
+
668
+ const registeredGates = gates.getRegisteredGates();
669
+ assert.ok(registeredGates.includes('gate-03-code'));
670
+ });
671
+
672
+ it('Gate 4 registers with QualityGate coordinator', () => {
673
+ registerGate4(gates);
674
+
675
+ const registeredGates = gates.getRegisteredGates();
676
+ assert.ok(registeredGates.includes('gate-04-security'));
677
+ });
678
+
679
+ it('Both gates execute successfully through coordinator', async () => {
680
+ registerGate3(gates);
681
+ registerGate4(gates);
682
+
683
+ const gate3Context = {
684
+ files: [
685
+ {
686
+ path: '/src/clean.js',
687
+ content: 'function add(a, b) { return a + b; }',
688
+ functions: [
689
+ { name: 'add', startLine: 1, endLine: 1, body: 'function add(a, b) { return a + b; }', parameters: ['a', 'b'] },
690
+ ],
691
+ },
692
+ ],
693
+ };
694
+
695
+ const gate4Context = {
696
+ files: [
697
+ {
698
+ path: '/src/secure.js',
699
+ content: 'const secret = process.env.SECRET_KEY;',
700
+ },
701
+ ],
702
+ authConfig: {
703
+ hashingAlgorithm: 'bcrypt',
704
+ httpsEnforced: true,
705
+ },
706
+ };
707
+
708
+ const gate3Result = await gates.executeGate('gate-03-code', gate3Context);
709
+ const gate4Result = await gates.executeGate('gate-04-security', gate4Context);
710
+
711
+ assert.strictEqual(gate3Result.passed, true);
712
+ assert.strictEqual(gate4Result.passed, true);
713
+ });
714
+
715
+ it('Gate 3 fails through coordinator for long functions', async () => {
716
+ registerGate3(gates);
717
+
718
+ const longFunctionBody = 'function longFunction() {\n' +
719
+ Array(60).fill(' console.log("line");').join('\n') +
720
+ '\n}';
721
+
722
+ const context = {
723
+ files: [
724
+ {
725
+ path: '/src/long.js',
726
+ content: longFunctionBody,
727
+ functions: [
728
+ { name: 'longFunction', startLine: 1, endLine: 61, body: longFunctionBody, parameters: [] },
729
+ ],
730
+ },
731
+ ],
732
+ };
733
+
734
+ const result = await gates.executeGate('gate-03-code', context);
735
+
736
+ assert.strictEqual(result.passed, false);
737
+ assert.ok(result.errors.length > 0);
738
+ });
739
+
740
+ it('Gate 4 fails through coordinator for security issues', async () => {
741
+ registerGate4(gates);
742
+
743
+ const insecureCode = `
744
+ const password = 'hardcoded123';
745
+ const result = eval(userInput);
746
+ `;
747
+
748
+ const context = {
749
+ files: [
750
+ {
751
+ path: '/src/insecure.js',
752
+ content: insecureCode,
753
+ },
754
+ ],
755
+ };
756
+
757
+ const result = await gates.executeGate('gate-04-security', context);
758
+
759
+ assert.strictEqual(result.passed, false);
760
+ assert.ok(result.errors.length > 0);
761
+ });
762
+ });