@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.
- package/README.md +735 -537
- package/agents/ez-architect-agent.md +267 -0
- package/agents/ez-backend-agent.md +303 -0
- package/agents/ez-chief-strategist.md +271 -0
- package/agents/ez-codebase-mapper.md +770 -770
- package/agents/ez-context-manager.md +319 -0
- package/agents/ez-debugger.md +1255 -1255
- package/agents/ez-design-expert.md +347 -0
- package/agents/ez-devops-agent.md +331 -0
- package/agents/ez-executor.md +487 -487
- package/agents/ez-frontend-agent.md +322 -0
- package/agents/ez-phase-researcher.md +553 -553
- package/agents/ez-planner.md +1307 -1307
- package/agents/ez-product-engineer.md +435 -0
- package/agents/ez-project-researcher.md +629 -629
- package/agents/ez-qa-agent.md +320 -0
- package/agents/ez-release-agent.md +333 -333
- package/agents/ez-requirements-agent.md +377 -377
- package/agents/ez-roadmapper.md +650 -650
- package/agents/ez-technical-writer.md +551 -0
- package/agents/ez-ux-expert.md +393 -0
- package/agents/ez-verifier.md +579 -579
- package/bin/guards/autonomy-guard.cjs +346 -0
- package/bin/guards/context-budget-guard.cjs +278 -0
- package/bin/guards/hallucination-guard.cjs +380 -0
- package/bin/guards/hidden-state-guard.cjs +182 -0
- package/bin/guards/team-overhead-guard.cjs +266 -0
- package/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/bin/lib/archetype-detector.cjs +289 -0
- package/bin/lib/assistant-adapter.cjs +361 -0
- package/bin/lib/audit-exec.cjs +175 -0
- package/bin/lib/auth.cjs +176 -0
- package/bin/lib/backup-service.cjs +422 -0
- package/bin/lib/bdd-validator.cjs +622 -0
- package/bin/lib/business-flow-mapper.cjs +429 -0
- package/bin/lib/circuit-breaker.cjs +276 -0
- package/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/bin/lib/codebase-analyzer.cjs +241 -0
- package/bin/lib/commands.cjs +691 -0
- package/bin/lib/config.cjs +236 -0
- package/bin/lib/constraint-extractor.cjs +526 -0
- package/bin/lib/content-scanner.cjs +238 -0
- package/bin/lib/context-cache.cjs +154 -0
- package/bin/lib/context-compressor.cjs +102 -0
- package/bin/lib/context-deduplicator.cjs +105 -0
- package/bin/lib/context-errors.cjs +78 -0
- package/bin/lib/context-manager.cjs +338 -0
- package/bin/lib/context-metadata-tracker.cjs +140 -0
- package/bin/lib/context-relevance-scorer.cjs +99 -0
- package/bin/lib/core.cjs +507 -0
- package/bin/lib/cost-alerts.cjs +174 -0
- package/bin/lib/cost-tracker.cjs +275 -0
- package/bin/lib/crash-recovery.cjs +220 -0
- package/bin/lib/dependency-graph.cjs +319 -0
- package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/bin/lib/deploy/deploy-status.cjs +74 -0
- package/bin/lib/discussion-synthesizer.cjs +439 -0
- package/bin/lib/error-cache.cjs +114 -0
- package/bin/lib/error-registry.cjs +177 -0
- package/bin/lib/file-access.cjs +207 -0
- package/bin/lib/file-lock.cjs +236 -0
- package/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/bin/lib/finops/cost-reporter.cjs +132 -0
- package/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/bin/lib/finops/spot-manager.cjs +118 -0
- package/bin/lib/framework-detector.cjs +396 -0
- package/bin/lib/frontmatter.cjs +313 -0
- package/bin/lib/fs-utils.cjs +153 -0
- package/bin/lib/gate-executor.cjs +272 -0
- package/bin/lib/gates/README.md +374 -0
- package/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/bin/lib/gates/gate-03-code.cjs +635 -0
- package/bin/lib/gates/gate-04-security.cjs +829 -0
- package/bin/lib/git-errors.cjs +83 -0
- package/bin/lib/git-utils.cjs +321 -0
- package/bin/lib/git-workflow-engine.cjs +1157 -0
- package/bin/lib/health-check.cjs +227 -0
- package/bin/lib/index.cjs +279 -0
- package/bin/lib/init.cjs +725 -0
- package/bin/lib/lock-logger.cjs +194 -0
- package/bin/lib/lock-state.cjs +263 -0
- package/bin/lib/lockfile-validator.cjs +227 -0
- package/bin/lib/log-rotation.cjs +71 -0
- package/bin/lib/logger.cjs +125 -0
- package/bin/lib/memory-compression.cjs +256 -0
- package/bin/lib/milestone.cjs +247 -0
- package/bin/lib/model-provider.cjs +241 -0
- package/bin/lib/package-manager-detector.cjs +203 -0
- package/bin/lib/package-manager-executor.cjs +385 -0
- package/bin/lib/package-manager-service.cjs +216 -0
- package/bin/lib/perf/api-monitor.cjs +88 -0
- package/bin/lib/perf/db-optimizer.cjs +78 -0
- package/bin/lib/perf/frontend-performance.cjs +56 -0
- package/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/bin/lib/perf/perf-baseline.cjs +102 -0
- package/bin/lib/perf/perf-reporter.cjs +117 -0
- package/bin/lib/perf/regression-detector.cjs +92 -0
- package/bin/lib/phase.cjs +963 -0
- package/bin/lib/planning-write.cjs +123 -0
- package/bin/lib/project-reporter.cjs +565 -0
- package/bin/lib/quality-gate.cjs +332 -0
- package/bin/lib/quality-metrics.cjs +324 -0
- package/bin/lib/recovery-manager.cjs +98 -0
- package/bin/lib/release-validator.cjs +617 -0
- package/bin/lib/retry.cjs +119 -0
- package/bin/lib/roadmap.cjs +309 -0
- package/bin/lib/safe-exec.cjs +173 -0
- package/bin/lib/safe-path.cjs +130 -0
- package/bin/lib/security-errors.cjs +62 -0
- package/bin/lib/session-chain.cjs +304 -0
- package/bin/lib/session-errors.cjs +81 -0
- package/bin/lib/session-export.cjs +251 -0
- package/bin/lib/session-import.cjs +262 -0
- package/bin/lib/session-manager.cjs +280 -0
- package/bin/lib/skill-context.cjs +148 -0
- package/bin/lib/skill-matcher.cjs +236 -0
- package/bin/lib/skill-registry.cjs +360 -0
- package/bin/lib/skill-resolver.cjs +449 -0
- package/bin/lib/skill-triggers.cjs +90 -0
- package/bin/lib/skill-validator.cjs +270 -0
- package/bin/lib/skill-versioning.cjs +355 -0
- package/bin/lib/stack-detector.cjs +399 -0
- package/bin/lib/state.cjs +736 -0
- package/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/bin/lib/temp-file.cjs +239 -0
- package/bin/lib/template.cjs +223 -0
- package/bin/lib/test-file-lock.cjs +112 -0
- package/bin/lib/test-graceful.cjs +93 -0
- package/bin/lib/test-logger.cjs +60 -0
- package/bin/lib/test-safe-exec.cjs +38 -0
- package/bin/lib/test-safe-path.cjs +33 -0
- package/bin/lib/test-temp-file.cjs +125 -0
- package/bin/lib/tier-manager.cjs +428 -0
- package/bin/lib/timeout-exec.cjs +63 -0
- package/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/bin/lib/url-fetch.cjs +170 -0
- package/bin/lib/verify.cjs +863 -0
- package/bin/update.js +217 -214
- package/commands/deploy.cjs +53 -0
- package/commands/ez/add-tests.md +41 -41
- package/commands/ez/audit-milestone.md +36 -36
- package/commands/ez/complete-milestone.md +136 -136
- package/commands/ez/discuss-phase.md +90 -90
- package/commands/ez/execute-phase.md +52 -52
- package/commands/ez/help.md +22 -22
- package/commands/ez/map-codebase.md +71 -71
- package/commands/ez/new-milestone.md +44 -44
- package/commands/ez/new-project.md +51 -42
- package/commands/ez/plan-phase.md +53 -53
- package/commands/ez/progress.md +36 -36
- package/commands/ez/quick.md +45 -45
- package/commands/ez/resume-work.md +40 -40
- package/commands/ez/run-phase.md +580 -0
- package/commands/ez/settings.md +36 -36
- package/commands/ez/update.md +37 -37
- package/commands/ez/verify-work.md +402 -38
- package/commands/health-check.cjs +44 -0
- package/commands/rollback.cjs +47 -0
- package/ez-agents/bin/ez-tools.cjs +599 -2
- package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
- package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
- package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
- package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
- package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
- package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
- package/ez-agents/bin/lib/audit-exec.cjs +166 -167
- package/ez-agents/bin/lib/auth.cjs +176 -176
- package/ez-agents/bin/lib/backup-service.cjs +422 -0
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -622
- package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
- package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
- package/ez-agents/bin/lib/commands.cjs +685 -685
- package/ez-agents/bin/lib/config.cjs +41 -1
- package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -238
- package/ez-agents/bin/lib/context-cache.cjs +154 -154
- package/ez-agents/bin/lib/context-errors.cjs +71 -71
- package/ez-agents/bin/lib/context-manager.cjs +220 -220
- package/ez-agents/bin/lib/core.cjs +507 -512
- package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
- package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
- package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
- package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -207
- package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
- package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
- package/ez-agents/bin/lib/framework-detector.cjs +396 -0
- package/ez-agents/bin/lib/frontmatter.cjs +3 -1
- package/ez-agents/bin/lib/gates/README.md +374 -0
- package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
- package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -83
- package/ez-agents/bin/lib/git-utils.cjs +321 -321
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -1157
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +2 -8
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -227
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +22 -47
- package/ez-agents/bin/lib/memory-compression.cjs +256 -256
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -203
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -385
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -216
- package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
- package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
- package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
- package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
- package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
- package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
- package/ez-agents/bin/lib/project-reporter.cjs +502 -0
- package/ez-agents/bin/lib/quality-gate.cjs +332 -0
- package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
- package/ez-agents/bin/lib/release-validator.cjs +617 -614
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -304
- package/ez-agents/bin/lib/session-errors.cjs +81 -81
- package/ez-agents/bin/lib/session-export.cjs +251 -251
- package/ez-agents/bin/lib/session-import.cjs +262 -262
- package/ez-agents/bin/lib/session-manager.cjs +280 -280
- package/ez-agents/bin/lib/skill-context.cjs +148 -0
- package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
- package/ez-agents/bin/lib/skill-registry.cjs +341 -0
- package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
- package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
- package/ez-agents/bin/lib/skill-validator.cjs +270 -0
- package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
- package/ez-agents/bin/lib/stack-detector.cjs +399 -0
- package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -428
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -170
- package/ez-agents/bin/lib/verify.cjs +863 -863
- package/ez-agents/references/decimal-phase-calculation.md +65 -65
- package/ez-agents/references/git-integration.md +248 -248
- package/ez-agents/references/git-planning-commit.md +38 -38
- package/ez-agents/references/metrics-schema.md +118 -118
- package/ez-agents/references/model-profile-resolution.md +34 -34
- package/ez-agents/references/model-profiles.md +93 -93
- package/ez-agents/references/phase-argument-parsing.md +61 -61
- package/ez-agents/references/planning-config.md +340 -340
- package/ez-agents/references/tier-strategy.md +103 -103
- package/ez-agents/references/ui-brand.md +160 -160
- package/ez-agents/references/verification-patterns.md +612 -612
- package/ez-agents/templates/DEBUG.md +164 -164
- package/ez-agents/templates/UAT.md +247 -247
- package/ez-agents/templates/agent-output-format.md +404 -0
- package/ez-agents/templates/bdd-feature.md +173 -173
- package/ez-agents/templates/codebase/architecture.md +255 -255
- package/ez-agents/templates/codebase/structure.md +285 -285
- package/ez-agents/templates/copilot-instructions.md +7 -7
- package/ez-agents/templates/debug-subagent-prompt.md +91 -91
- package/ez-agents/templates/discovery.md +146 -146
- package/ez-agents/templates/discussion.md +68 -68
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -205
- package/ez-agents/templates/mode-workflow-templates.md +301 -0
- package/ez-agents/templates/phase-prompt.md +610 -610
- package/ez-agents/templates/planner-subagent-prompt.md +117 -117
- package/ez-agents/templates/project.md +184 -184
- package/ez-agents/templates/release-checklist.md +136 -133
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -201
- package/ez-agents/templates/security-user-setup.md +244 -0
- package/ez-agents/templates/skill-validation-rules.md +476 -0
- package/ez-agents/templates/state.md +180 -176
- package/ez-agents/templates/summary-complex.md +59 -59
- package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
- package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
- package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
- package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
- package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
- package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
- package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
- package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
- package/ez-agents/workflows/audit-milestone.md +1 -1
- package/ez-agents/workflows/autonomous.md +844 -844
- package/ez-agents/workflows/complete-milestone.md +1 -1
- package/ez-agents/workflows/discuss-phase.md +1 -1
- package/ez-agents/workflows/execute-phase.md +124 -3
- package/ez-agents/workflows/help.md +42 -181
- package/ez-agents/workflows/hotfix.md +291 -291
- package/ez-agents/workflows/new-milestone.md +713 -713
- package/ez-agents/workflows/new-project.md +1089 -1107
- package/ez-agents/workflows/plan-phase.md +0 -40
- package/ez-agents/workflows/release.md +253 -253
- package/ez-agents/workflows/resume-session.md +215 -215
- package/ez-agents/workflows/run-phase.md +531 -0
- package/ez-agents/workflows/settings.md +2 -35
- package/hooks/dist/ez-check-update.js +81 -81
- package/hooks/dist/ez-context-monitor.js +148 -141
- package/hooks/dist/ez-statusline.js +115 -115
- package/package.json +78 -71
- package/scripts/fix-qwen-installation.js +144 -144
- package/agents/ez-integration-checker.md +0 -443
- package/agents/ez-nyquist-auditor.md +0 -176
- package/agents/ez-observer-agent.md +0 -260
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-scrum-master-agent.md +0 -242
- package/agents/ez-tech-lead-agent.md +0 -267
- package/agents/ez-ui-auditor.md +0 -439
- package/agents/ez-ui-checker.md +0 -300
- package/agents/ez-ui-researcher.md +0 -353
- package/commands/ez/add-phase.md +0 -43
- package/commands/ez/add-todo.md +0 -47
- package/commands/ez/arch-review.md +0 -102
- package/commands/ez/auth.md +0 -87
- package/commands/ez/autonomous.md +0 -41
- package/commands/ez/check-todos.md +0 -45
- package/commands/ez/cleanup.md +0 -18
- package/commands/ez/debug.md +0 -168
- package/commands/ez/export-session.md +0 -79
- package/commands/ez/gather-requirements.md +0 -117
- package/commands/ez/git-workflow.md +0 -72
- package/commands/ez/health.md +0 -22
- package/commands/ez/hotfix.md +0 -120
- package/commands/ez/import-session.md +0 -82
- package/commands/ez/insert-phase.md +0 -32
- package/commands/ez/join-discord.md +0 -18
- package/commands/ez/list-phase-assumptions.md +0 -46
- package/commands/ez/list-sessions.md +0 -96
- package/commands/ez/package-manager.md +0 -316
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/preflight.md +0 -79
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/release.md +0 -153
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/resume.md +0 -107
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/standup.md +0 -85
- package/commands/ez/stats.md +0 -18
- package/commands/ez/ui-phase.md +0 -34
- package/commands/ez/ui-review.md +0 -32
- package/commands/ez/validate-phase.md +0 -35
- package/ez-agents/bin/lib/metrics-tracker.cjs +0 -406
- package/ez-agents/templates/UI-SPEC.md +0 -100
- package/ez-agents/templates/VALIDATION.md +0 -76
- package/ez-agents/templates/context.md +0 -352
- package/ez-agents/templates/verification-report.md +0 -322
- package/ez-agents/workflows/arch-review.md +0 -54
- package/ez-agents/workflows/export-session.md +0 -255
- package/ez-agents/workflows/gather-requirements.md +0 -206
- package/ez-agents/workflows/import-session.md +0 -303
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/standup.md +0 -64
- package/ez-agents/workflows/ui-phase.md +0 -290
- package/ez-agents/workflows/ui-review.md +0 -157
- package/ez-agents/workflows/validate-phase.md +0 -167
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate 2: Architecture Review
|
|
3
|
+
*
|
|
4
|
+
* Validates architecture against skill recommendations and checks for overengineering.
|
|
5
|
+
*
|
|
6
|
+
* Checks:
|
|
7
|
+
* 1. Structure matches skill recommendations (when skill registry is available)
|
|
8
|
+
* 2. Abstraction layer count is appropriate (< 3 for most projects)
|
|
9
|
+
* 3. No premature optimization patterns (microservices, repository pattern without need)
|
|
10
|
+
* 4. No unnecessary CQRS for simple CRUD operations
|
|
11
|
+
*
|
|
12
|
+
* @module gates/gate-02-architecture
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { z } = require('zod');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Zod schema for a file in the proposed architecture
|
|
21
|
+
* @type {z.ZodSchema}
|
|
22
|
+
*/
|
|
23
|
+
const fileSchema = z.object({
|
|
24
|
+
/** File path relative to project root */
|
|
25
|
+
path: z.string(),
|
|
26
|
+
/** File type/category (e.g., 'controller', 'service', 'repository', 'model') */
|
|
27
|
+
type: z.string().optional(),
|
|
28
|
+
/** Abstraction layer depth (0 = root, 1 = first layer, etc.) */
|
|
29
|
+
layer: z.number().int().min(0).optional(),
|
|
30
|
+
/** Dependencies (other files this file depends on) */
|
|
31
|
+
dependencies: z.array(z.string()).optional(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Zod schema for architecture component
|
|
36
|
+
* @type {z.ZodSchema}
|
|
37
|
+
*/
|
|
38
|
+
const componentSchema = z.object({
|
|
39
|
+
/** Component name */
|
|
40
|
+
name: z.string(),
|
|
41
|
+
/** Component type (e.g., 'controller', 'service', 'repository', 'use-case') */
|
|
42
|
+
type: z.string(),
|
|
43
|
+
/** Layer depth */
|
|
44
|
+
layer: z.number().int().min(0),
|
|
45
|
+
/** Files in this component */
|
|
46
|
+
files: z.array(z.string()).optional(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Zod schema for skill recommendation
|
|
51
|
+
* @type {z.ZodSchema}
|
|
52
|
+
*/
|
|
53
|
+
const skillRecommendationSchema = z.object({
|
|
54
|
+
/** Skill name */
|
|
55
|
+
skillName: z.string(),
|
|
56
|
+
/** Recommended project structure */
|
|
57
|
+
recommendedStructure: z.array(z.string()).optional(),
|
|
58
|
+
/** Best practices */
|
|
59
|
+
bestPractices: z.array(z.string()).optional(),
|
|
60
|
+
/** Anti-patterns to avoid */
|
|
61
|
+
antiPatterns: z.array(z.string()).optional(),
|
|
62
|
+
/** Maximum recommended abstraction layers */
|
|
63
|
+
maxAbstractionLayers: z.number().int().min(1).optional(),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Zod schema for the gate context
|
|
68
|
+
* @type {z.ZodSchema}
|
|
69
|
+
*/
|
|
70
|
+
const gateContextSchema = z.object({
|
|
71
|
+
/** Proposed project structure (array of files) */
|
|
72
|
+
files: z.array(fileSchema).optional(),
|
|
73
|
+
/** Architecture components */
|
|
74
|
+
components: z.array(componentSchema).optional(),
|
|
75
|
+
/** Project tier/archetype (mvp, medium, enterprise) */
|
|
76
|
+
projectTier: z.enum(['mvp', 'medium', 'enterprise']).optional(),
|
|
77
|
+
/** Skill recommendations (from Skill Registry) */
|
|
78
|
+
skillRecommendations: z.array(skillRecommendationSchema).optional(),
|
|
79
|
+
/** Explicit architecture description */
|
|
80
|
+
architecture: z.object({
|
|
81
|
+
/** Number of abstraction layers */
|
|
82
|
+
abstractionLayers: z.number().int().min(0).optional(),
|
|
83
|
+
/** Patterns used */
|
|
84
|
+
patterns: z.array(z.string()).optional(),
|
|
85
|
+
/** Justification for complex patterns */
|
|
86
|
+
justifications: z.record(z.string()).optional(),
|
|
87
|
+
}).optional(),
|
|
88
|
+
/** Simple flags for common patterns */
|
|
89
|
+
hasRepositoryPattern: z.boolean().optional(),
|
|
90
|
+
hasCQRS: z.boolean().optional(),
|
|
91
|
+
hasEventBus: z.boolean().optional(),
|
|
92
|
+
hasMicroservices: z.boolean().optional(),
|
|
93
|
+
/** Event count (for detecting overengineering) */
|
|
94
|
+
eventCount: z.number().int().min(0).optional(),
|
|
95
|
+
/** CRUD operation count */
|
|
96
|
+
crudOperationCount: z.number().int().min(0).optional(),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Default abstraction layer thresholds by project tier
|
|
101
|
+
*/
|
|
102
|
+
const ABSTRACTION_THRESHOLDS = {
|
|
103
|
+
mvp: 2, // MVP: max 2 layers (e.g., controller → service)
|
|
104
|
+
medium: 3, // Medium: max 3 layers (e.g., controller → service → repository)
|
|
105
|
+
enterprise: 4, // Enterprise: max 4 layers (e.g., controller → service → repository → domain)
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Count abstraction layers from file structure
|
|
110
|
+
*
|
|
111
|
+
* Analyzes file paths and types to determine the depth of abstraction layers.
|
|
112
|
+
* Common layers: controller → service → repository → model/domain
|
|
113
|
+
*
|
|
114
|
+
* @param {Array} files - Array of file objects with path and type
|
|
115
|
+
* @returns {number} Maximum abstraction layer depth
|
|
116
|
+
*/
|
|
117
|
+
function countAbstractionLayers(files) {
|
|
118
|
+
if (!files || files.length === 0) {
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// If files have explicit layer property, use the maximum
|
|
123
|
+
const maxLayer = Math.max(...files.map(f => f.layer ?? 0));
|
|
124
|
+
if (maxLayer > 0) {
|
|
125
|
+
return maxLayer;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Otherwise, infer from file paths and types
|
|
129
|
+
const layerTypes = new Set();
|
|
130
|
+
|
|
131
|
+
for (const file of files) {
|
|
132
|
+
const filePath = file.path || '';
|
|
133
|
+
const fileType = file.type || '';
|
|
134
|
+
|
|
135
|
+
// Check type field first
|
|
136
|
+
if (fileType) {
|
|
137
|
+
layerTypes.add(fileType.toLowerCase());
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Infer from path
|
|
141
|
+
const pathLower = filePath.toLowerCase();
|
|
142
|
+
if (pathLower.includes('/controller') || pathLower.includes('/controllers')) {
|
|
143
|
+
layerTypes.add('controller');
|
|
144
|
+
}
|
|
145
|
+
if (pathLower.includes('/service') || pathLower.includes('/services')) {
|
|
146
|
+
layerTypes.add('service');
|
|
147
|
+
}
|
|
148
|
+
if (pathLower.includes('/repository') || pathLower.includes('/repositories') ||
|
|
149
|
+
pathLower.includes('/dao') || pathLower.includes('/data-access')) {
|
|
150
|
+
layerTypes.add('repository');
|
|
151
|
+
}
|
|
152
|
+
if (pathLower.includes('/use-case') || pathLower.includes('/usecase') ||
|
|
153
|
+
pathLower.includes('/usecase') || pathLower.includes('/commands') ||
|
|
154
|
+
pathLower.includes('/queries') || pathLower.includes('/handlers')) {
|
|
155
|
+
layerTypes.add('use-case');
|
|
156
|
+
}
|
|
157
|
+
if (pathLower.includes('/model') || pathLower.includes('/models') ||
|
|
158
|
+
pathLower.includes('/domain') || pathLower.includes('/entity')) {
|
|
159
|
+
layerTypes.add('model');
|
|
160
|
+
}
|
|
161
|
+
if (pathLower.includes('/middleware')) {
|
|
162
|
+
layerTypes.add('middleware');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Define typical layer ordering
|
|
167
|
+
const layerOrder = ['middleware', 'controller', 'use-case', 'service', 'repository', 'model'];
|
|
168
|
+
|
|
169
|
+
// Count distinct layers present
|
|
170
|
+
let layerCount = 0;
|
|
171
|
+
for (const layer of layerOrder) {
|
|
172
|
+
if (layerTypes.has(layer)) {
|
|
173
|
+
layerCount++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return layerCount;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Detect premature repository pattern
|
|
182
|
+
*
|
|
183
|
+
* Repository pattern is overengineering when:
|
|
184
|
+
* - Project is MVP tier with simple CRUD
|
|
185
|
+
* - No complex data access logic
|
|
186
|
+
* - Single data source (no need to swap databases)
|
|
187
|
+
*
|
|
188
|
+
* @param {Object} context - Gate context
|
|
189
|
+
* @returns {{ detected: boolean, reason: string }}
|
|
190
|
+
*/
|
|
191
|
+
function detectPrematureRepository(context) {
|
|
192
|
+
const result = { detected: false, reason: '' };
|
|
193
|
+
|
|
194
|
+
// If explicitly flagged
|
|
195
|
+
if (context.hasRepositoryPattern) {
|
|
196
|
+
const tier = context.projectTier || 'mvp';
|
|
197
|
+
const crudCount = context.crudOperationCount ?? 0;
|
|
198
|
+
|
|
199
|
+
// Check if there's justification first - if provided, allow it
|
|
200
|
+
if (context.architecture?.justifications?.repository) {
|
|
201
|
+
// Justification provided, allow it
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// MVP with simple CRUD (< 10 operations) - likely overengineering
|
|
206
|
+
if (tier === 'mvp' && crudCount < 10) {
|
|
207
|
+
result.detected = true;
|
|
208
|
+
result.reason = 'Repository pattern detected in MVP project with simple CRUD operations. ' +
|
|
209
|
+
'Consider using direct data access for MVP tier. Add justification if pattern is necessary.';
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Detect unnecessary CQRS
|
|
219
|
+
*
|
|
220
|
+
* CQRS is overengineering when:
|
|
221
|
+
* - Simple CRUD application
|
|
222
|
+
* - No complex read/write separation needs
|
|
223
|
+
* - Low event count
|
|
224
|
+
*
|
|
225
|
+
* @param {Object} context - Gate context
|
|
226
|
+
* @returns {{ detected: boolean, reason: string }}
|
|
227
|
+
*/
|
|
228
|
+
function detectUnnecessaryCQRS(context) {
|
|
229
|
+
const result = { detected: false, reason: '' };
|
|
230
|
+
|
|
231
|
+
// If explicitly flagged
|
|
232
|
+
if (context.hasCQRS) {
|
|
233
|
+
const crudCount = context.crudOperationCount ?? 0;
|
|
234
|
+
const eventCount = context.eventCount ?? 0;
|
|
235
|
+
const tier = context.projectTier || 'mvp';
|
|
236
|
+
|
|
237
|
+
// Check justification first - if provided, allow it
|
|
238
|
+
if (context.architecture?.justifications?.cqrs) {
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Simple CRUD with CQRS - likely overengineering
|
|
243
|
+
if (crudCount < 15 && eventCount < 5) {
|
|
244
|
+
result.detected = true;
|
|
245
|
+
result.reason = `CQRS pattern detected for simple CRUD application (${crudCount} operations, ${eventCount} events). ` +
|
|
246
|
+
'CQRS adds complexity; consider using for projects with complex read/write separation needs or high event volume.';
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// MVP with CQRS but low complexity
|
|
251
|
+
if (tier === 'mvp' && (crudCount < 20 || eventCount < 10)) {
|
|
252
|
+
result.detected = true;
|
|
253
|
+
result.reason = 'CQRS in MVP project without clear justification. ' +
|
|
254
|
+
'Add explicit justification explaining read/write separation needs.';
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Detect premature event bus / event-driven architecture
|
|
263
|
+
*
|
|
264
|
+
* Event bus is overengineering when:
|
|
265
|
+
* - Very few events (< 3)
|
|
266
|
+
* - Simple application flow
|
|
267
|
+
* - No async processing needs
|
|
268
|
+
*
|
|
269
|
+
* @param {Object} context - Gate context
|
|
270
|
+
* @returns {{ detected: boolean, reason: string }}
|
|
271
|
+
*/
|
|
272
|
+
function detectPrematureEventBus(context) {
|
|
273
|
+
const result = { detected: false, reason: '' };
|
|
274
|
+
|
|
275
|
+
if (context.hasEventBus) {
|
|
276
|
+
const eventCount = context.eventCount ?? 0;
|
|
277
|
+
|
|
278
|
+
if (eventCount < 3) {
|
|
279
|
+
result.detected = true;
|
|
280
|
+
result.reason = `Event bus with only ${eventCount} events. ` +
|
|
281
|
+
'For 1-2 events, consider direct function calls or simple pub/sub. ' +
|
|
282
|
+
'Event bus adds complexity that may not be justified.';
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Detect premature microservices
|
|
292
|
+
*
|
|
293
|
+
* Microservices are overengineering when:
|
|
294
|
+
* - MVP tier project
|
|
295
|
+
* - Small team (< 5 developers implied by MVP)
|
|
296
|
+
* - No explicit scalability requirements
|
|
297
|
+
*
|
|
298
|
+
* @param {Object} context - Gate context
|
|
299
|
+
* @returns {{ detected: boolean, reason: string }}
|
|
300
|
+
*/
|
|
301
|
+
function detectPrematureMicroservices(context) {
|
|
302
|
+
const result = { detected: false, reason: '' };
|
|
303
|
+
|
|
304
|
+
if (context.hasMicroservices) {
|
|
305
|
+
const tier = context.projectTier || 'mvp';
|
|
306
|
+
|
|
307
|
+
// Check justification first - if provided, allow it
|
|
308
|
+
if (context.architecture?.justifications?.microservices) {
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (tier === 'mvp') {
|
|
313
|
+
result.detected = true;
|
|
314
|
+
result.reason = 'Microservices architecture in MVP project. ' +
|
|
315
|
+
'Consider monolith-first approach for MVP. Microservices add operational complexity ' +
|
|
316
|
+
'that should be justified by team size, scalability needs, or domain complexity.';
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Other tiers without justification
|
|
321
|
+
result.detected = true;
|
|
322
|
+
result.reason = 'Microservices without explicit justification. ' +
|
|
323
|
+
'Add justification explaining domain boundaries, team structure, or scalability requirements.';
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Check structure against skill recommendations
|
|
331
|
+
*
|
|
332
|
+
* @param {Array} skillRecommendations - Array of skill recommendations
|
|
333
|
+
* @param {Object} architecture - Proposed architecture
|
|
334
|
+
* @returns {{ deviations: Array<{skill: string, deviation: string, suggestion: string}>, matched: string[] }}
|
|
335
|
+
*/
|
|
336
|
+
function checkSkillAlignment(skillRecommendations, architecture) {
|
|
337
|
+
const deviations = [];
|
|
338
|
+
const matched = [];
|
|
339
|
+
|
|
340
|
+
if (!skillRecommendations || skillRecommendations.length === 0) {
|
|
341
|
+
return { deviations, matched };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
for (const skill of skillRecommendations) {
|
|
345
|
+
const skillName = skill.skillName;
|
|
346
|
+
|
|
347
|
+
// Check recommended structure
|
|
348
|
+
if (skill.recommendedStructure && architecture?.patterns) {
|
|
349
|
+
const recommendedPatterns = skill.recommendedStructure.map(s => s.toLowerCase());
|
|
350
|
+
const actualPatterns = architecture.patterns.map(p => p.toLowerCase());
|
|
351
|
+
|
|
352
|
+
for (const recommended of recommendedPatterns) {
|
|
353
|
+
if (actualPatterns.some(p => p.includes(recommended))) {
|
|
354
|
+
matched.push(`${skillName}: ${recommended}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Check anti-patterns
|
|
360
|
+
if (skill.antiPatterns && architecture?.patterns) {
|
|
361
|
+
const antiPatterns = skill.antiPatterns.map(ap => ap.toLowerCase());
|
|
362
|
+
const actualPatterns = architecture.patterns.map(p => p.toLowerCase());
|
|
363
|
+
|
|
364
|
+
for (const antiPattern of antiPatterns) {
|
|
365
|
+
if (actualPatterns.some(p => p.includes(antiPattern))) {
|
|
366
|
+
deviations.push({
|
|
367
|
+
skill: skillName,
|
|
368
|
+
deviation: `Uses anti-pattern '${antiPattern}' flagged by skill`,
|
|
369
|
+
suggestion: skill.bestPractices?.[0] || 'Review skill recommendations',
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Check abstraction layers
|
|
376
|
+
if (skill.maxAbstractionLayers && architecture?.abstractionLayers) {
|
|
377
|
+
if (architecture.abstractionLayers > skill.maxAbstractionLayers) {
|
|
378
|
+
deviations.push({
|
|
379
|
+
skill: skillName,
|
|
380
|
+
deviation: `Abstraction layers (${architecture.abstractionLayers}) exceeds skill recommendation (${skill.maxAbstractionLayers})`,
|
|
381
|
+
suggestion: `Consider reducing to ${skill.maxAbstractionLayers} layers or fewer`,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return { deviations, matched };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Gate 2 Executor: Architecture Review
|
|
392
|
+
*
|
|
393
|
+
* @param {Object} context - Gate context (validated against gateContextSchema)
|
|
394
|
+
* @returns {Promise<{ passed: boolean, errors: Array<{path: string, message: string}>, warnings: string[] }>}
|
|
395
|
+
*/
|
|
396
|
+
async function executeGate2(context) {
|
|
397
|
+
const errors = [];
|
|
398
|
+
const warnings = [];
|
|
399
|
+
|
|
400
|
+
// Determine project tier
|
|
401
|
+
const tier = context.projectTier || 'mvp';
|
|
402
|
+
const maxLayers = ABSTRACTION_THRESHOLDS[tier];
|
|
403
|
+
|
|
404
|
+
// Count abstraction layers
|
|
405
|
+
let abstractionLayers = context.architecture?.abstractionLayers;
|
|
406
|
+
if (abstractionLayers === undefined && context.files) {
|
|
407
|
+
abstractionLayers = countAbstractionLayers(context.files);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (abstractionLayers !== undefined) {
|
|
411
|
+
if (abstractionLayers > maxLayers) {
|
|
412
|
+
errors.push({
|
|
413
|
+
path: 'architecture.abstractionLayers',
|
|
414
|
+
message: `Too many abstraction layers (${abstractionLayers}) for ${tier} project. ` +
|
|
415
|
+
`Maximum recommended: ${maxLayers}. Consider flattening architecture.`,
|
|
416
|
+
});
|
|
417
|
+
} else if (abstractionLayers > 3) {
|
|
418
|
+
warnings.push(
|
|
419
|
+
`Architecture has ${abstractionLayers} abstraction layers. ` +
|
|
420
|
+
'Consider simplifying if possible. Layers > 3 often indicate overengineering.'
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Check for overengineering patterns
|
|
426
|
+
|
|
427
|
+
// 1. Premature repository pattern
|
|
428
|
+
const repoCheck = detectPrematureRepository(context);
|
|
429
|
+
if (repoCheck.detected) {
|
|
430
|
+
errors.push({
|
|
431
|
+
path: 'architecture.patterns',
|
|
432
|
+
message: repoCheck.reason,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// 2. Unnecessary CQRS
|
|
437
|
+
const cqrsCheck = detectUnnecessaryCQRS(context);
|
|
438
|
+
if (cqrsCheck.detected) {
|
|
439
|
+
errors.push({
|
|
440
|
+
path: 'architecture.patterns',
|
|
441
|
+
message: cqrsCheck.reason,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// 3. Premature event bus
|
|
446
|
+
const eventBusCheck = detectPrematureEventBus(context);
|
|
447
|
+
if (eventBusCheck.detected) {
|
|
448
|
+
warnings.push(eventBusCheck.reason);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// 4. Premature microservices
|
|
452
|
+
const microservicesCheck = detectPrematureMicroservices(context);
|
|
453
|
+
if (microservicesCheck.detected) {
|
|
454
|
+
errors.push({
|
|
455
|
+
path: 'architecture.patterns',
|
|
456
|
+
message: microservicesCheck.reason,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Check skill alignment
|
|
461
|
+
if (context.skillRecommendations && context.skillRecommendations.length > 0) {
|
|
462
|
+
const { deviations, matched } = checkSkillAlignment(
|
|
463
|
+
context.skillRecommendations,
|
|
464
|
+
context.architecture
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
for (const deviation of deviations) {
|
|
468
|
+
warnings.push(
|
|
469
|
+
`Skill '${deviation.skill}': ${deviation.deviation}. ` +
|
|
470
|
+
`Suggestion: ${deviation.suggestion}`
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Log matched recommendations (info only)
|
|
475
|
+
if (matched.length > 0) {
|
|
476
|
+
// Could add to a separate 'info' field if needed
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Check for unjustified deviations from skill recommendations
|
|
481
|
+
if (context.architecture?.justifications) {
|
|
482
|
+
// Justifications provided - acknowledge but don't block
|
|
483
|
+
const justificationKeys = Object.keys(context.architecture.justifications);
|
|
484
|
+
if (justificationKeys.length > 0) {
|
|
485
|
+
// This is informational - justifications allow deviation from recommendations
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return {
|
|
490
|
+
passed: errors.length === 0,
|
|
491
|
+
errors,
|
|
492
|
+
warnings,
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Create and register Gate 2 with a QualityGate instance
|
|
498
|
+
*
|
|
499
|
+
* @param {QualityGate} gateCoordinator - QualityGate coordinator instance
|
|
500
|
+
* @returns {void}
|
|
501
|
+
*/
|
|
502
|
+
function registerGate2(gateCoordinator) {
|
|
503
|
+
gateCoordinator.registerGate('gate-02-architecture', gateContextSchema, executeGate2);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Load skill recommendations from Skill Registry
|
|
508
|
+
*
|
|
509
|
+
* @param {string} [skillRegistryPath] - Optional path to skill registry module
|
|
510
|
+
* @returns {Promise<Array>} Array of skill recommendations
|
|
511
|
+
*/
|
|
512
|
+
async function loadSkillRecommendations(skillRegistryPath) {
|
|
513
|
+
try {
|
|
514
|
+
// Try to load skill registry if path provided
|
|
515
|
+
if (skillRegistryPath && fs.existsSync(skillRegistryPath)) {
|
|
516
|
+
const { SkillRegistry } = require(skillRegistryPath);
|
|
517
|
+
const registry = new SkillRegistry();
|
|
518
|
+
await registry.load();
|
|
519
|
+
|
|
520
|
+
// Get all skills and extract recommendations
|
|
521
|
+
const skills = registry.getAll();
|
|
522
|
+
return skills
|
|
523
|
+
.filter(s => s.recommended_structure || s.best_practices || s.anti_patterns)
|
|
524
|
+
.map(s => ({
|
|
525
|
+
skillName: s.name,
|
|
526
|
+
recommendedStructure: s.recommended_structure,
|
|
527
|
+
bestPractices: s.best_practices,
|
|
528
|
+
antiPatterns: s.anti_patterns,
|
|
529
|
+
maxAbstractionLayers: s.max_abstraction_layers,
|
|
530
|
+
}));
|
|
531
|
+
}
|
|
532
|
+
} catch (err) {
|
|
533
|
+
// Skill registry not available - return empty array
|
|
534
|
+
// Gate will still work with explicit context.skillRecommendations
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return [];
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
module.exports = {
|
|
541
|
+
executeGate2,
|
|
542
|
+
registerGate2,
|
|
543
|
+
fileSchema,
|
|
544
|
+
componentSchema,
|
|
545
|
+
skillRecommendationSchema,
|
|
546
|
+
gateContextSchema,
|
|
547
|
+
countAbstractionLayers,
|
|
548
|
+
detectPrematureRepository,
|
|
549
|
+
detectUnnecessaryCQRS,
|
|
550
|
+
detectPrematureEventBus,
|
|
551
|
+
detectPrematureMicroservices,
|
|
552
|
+
checkSkillAlignment,
|
|
553
|
+
loadSkillRecommendations,
|
|
554
|
+
ABSTRACTION_THRESHOLDS,
|
|
555
|
+
};
|