@howlil/ez-agents 3.4.2 → 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 -462
- 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 -0
- package/agents/ez-requirements-agent.md +377 -0
- 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/install.js +3221 -3272
- 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 -41
- 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 -45
- package/commands/ez/progress.md +36 -24
- 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 +1692 -716
- 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 -0
- 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 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- 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/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- 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 -0
- package/ez-agents/bin/lib/git-utils.cjs +118 -0
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +40 -2
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +99 -154
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- 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 -0
- package/ez-agents/bin/lib/safe-exec.cjs +128 -214
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- 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 -0
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- 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 -0
- 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 -200
- package/ez-agents/references/tier-strategy.md +103 -0
- 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 -0
- 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 -0
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- 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 -0
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -0
- 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 +131 -30
- 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 +169 -3
- package/ez-agents/workflows/help.md +86 -133
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/new-milestone.md +340 -11
- package/ez-agents/workflows/new-project.md +294 -318
- package/ez-agents/workflows/plan-phase.md +22 -40
- package/ez-agents/workflows/progress.md +15 -25
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/resume-session.md +215 -0
- 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 -64
- 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-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- 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/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/health.md +0 -22
- 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/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/set-profile.md +0 -34
- 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/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/research-phase.md +0 -74
- 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,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate 5 Validator Tests
|
|
3
|
+
* Tests for the testing coverage gate validator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { strict as assert } from 'assert';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import os from 'os';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Import the validator
|
|
17
|
+
const { validateCoverage, getArchetypeThresholds } = await import(path.join(__dirname, '../../../.planning/gates/gate-05-testing/validator.cjs'));
|
|
18
|
+
|
|
19
|
+
describe('Gate 5 Validator', () => {
|
|
20
|
+
describe('getArchetypeThresholds', () => {
|
|
21
|
+
it('should return MVP thresholds', () => {
|
|
22
|
+
const thresholds = getArchetypeThresholds('mvp');
|
|
23
|
+
assert.strictEqual(thresholds.lines, 60);
|
|
24
|
+
assert.strictEqual(thresholds.branches, 40);
|
|
25
|
+
assert.strictEqual(thresholds.functions, 50);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return Medium thresholds', () => {
|
|
29
|
+
const thresholds = getArchetypeThresholds('medium');
|
|
30
|
+
assert.strictEqual(thresholds.lines, 80);
|
|
31
|
+
assert.strictEqual(thresholds.branches, 60);
|
|
32
|
+
assert.strictEqual(thresholds.functions, 70);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return Enterprise thresholds', () => {
|
|
36
|
+
const thresholds = getArchetypeThresholds('enterprise');
|
|
37
|
+
assert.strictEqual(thresholds.lines, 95);
|
|
38
|
+
assert.strictEqual(thresholds.branches, 80);
|
|
39
|
+
assert.strictEqual(thresholds.functions, 90);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should throw for unknown archetype', () => {
|
|
43
|
+
assert.throws(
|
|
44
|
+
() => getArchetypeThresholds('invalid'),
|
|
45
|
+
/Unknown archetype/
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('validateCoverage', () => {
|
|
51
|
+
let tempDir;
|
|
52
|
+
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gate5-test-'));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
try {
|
|
59
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// Ignore cleanup errors
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should return failure when coverage report missing', () => {
|
|
66
|
+
const result = validateCoverage(tempDir, 'mvp');
|
|
67
|
+
assert.strictEqual(result.pass, false);
|
|
68
|
+
assert.ok(result.failures.some(f => f.includes('Coverage execution failed')));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should return failure when coverage below threshold', () => {
|
|
72
|
+
// Create a mock coverage report with low coverage
|
|
73
|
+
const coverageDir = path.join(tempDir, 'coverage');
|
|
74
|
+
fs.mkdirSync(coverageDir);
|
|
75
|
+
|
|
76
|
+
const mockCoverage = {
|
|
77
|
+
totals: {
|
|
78
|
+
lines: { pct: 30 },
|
|
79
|
+
branches: { pct: 20 },
|
|
80
|
+
functions: { pct: 25 }
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
fs.writeFileSync(
|
|
85
|
+
path.join(coverageDir, 'coverage-summary.json'),
|
|
86
|
+
JSON.stringify(mockCoverage)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const result = validateCoverage(tempDir, 'mvp');
|
|
90
|
+
assert.strictEqual(result.pass, false);
|
|
91
|
+
assert.ok(result.failures.length > 0);
|
|
92
|
+
assert.ok(result.failures.some(f => f.includes('Lines coverage')));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should return success when coverage meets threshold', () => {
|
|
96
|
+
// Create a mock coverage report with good coverage
|
|
97
|
+
const coverageDir = path.join(tempDir, 'coverage');
|
|
98
|
+
fs.mkdirSync(coverageDir);
|
|
99
|
+
|
|
100
|
+
const mockCoverage = {
|
|
101
|
+
totals: {
|
|
102
|
+
lines: { pct: 70 },
|
|
103
|
+
branches: { pct: 50 },
|
|
104
|
+
functions: { pct: 60 }
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
fs.writeFileSync(
|
|
109
|
+
path.join(coverageDir, 'coverage-summary.json'),
|
|
110
|
+
JSON.stringify(mockCoverage)
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const result = validateCoverage(tempDir, 'mvp');
|
|
114
|
+
assert.strictEqual(result.pass, true);
|
|
115
|
+
assert.strictEqual(result.failures.length, 0);
|
|
116
|
+
assert.strictEqual(result.report.lines, 70);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should use correct thresholds for medium archetype', () => {
|
|
120
|
+
const coverageDir = path.join(tempDir, 'coverage');
|
|
121
|
+
fs.mkdirSync(coverageDir);
|
|
122
|
+
|
|
123
|
+
const mockCoverage = {
|
|
124
|
+
totals: {
|
|
125
|
+
lines: { pct: 75 }, // Below medium (80%) but above mvp (60%)
|
|
126
|
+
branches: { pct: 55 },
|
|
127
|
+
functions: { pct: 65 }
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
fs.writeFileSync(
|
|
132
|
+
path.join(coverageDir, 'coverage-summary.json'),
|
|
133
|
+
JSON.stringify(mockCoverage)
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Should fail for medium
|
|
137
|
+
const mediumResult = validateCoverage(tempDir, 'medium');
|
|
138
|
+
assert.strictEqual(mediumResult.pass, false);
|
|
139
|
+
|
|
140
|
+
// Should pass for mvp
|
|
141
|
+
const mvpResult = validateCoverage(tempDir, 'mvp');
|
|
142
|
+
assert.strictEqual(mvpResult.pass, true);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate 6 Documentation Validator Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import { strict as assert } from 'assert';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
// Import the validator
|
|
16
|
+
const { validateDocs, getRequiredDocs, validateSections } = await import(path.join(__dirname, '../../../.planning/gates/gate-06-docs/validator.cjs'));
|
|
17
|
+
|
|
18
|
+
describe('Gate 6 Validator', () => {
|
|
19
|
+
describe('getRequiredDocs', () => {
|
|
20
|
+
it('should return MVP documentation requirements', () => {
|
|
21
|
+
const docs = getRequiredDocs('mvp');
|
|
22
|
+
assert.ok(Array.isArray(docs));
|
|
23
|
+
assert.ok(docs.some(d => d.path === 'README.md'));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return Medium documentation requirements', () => {
|
|
27
|
+
const docs = getRequiredDocs('medium');
|
|
28
|
+
assert.ok(docs.length >= 3);
|
|
29
|
+
assert.ok(docs.some(d => d.path === 'README.md'));
|
|
30
|
+
assert.ok(docs.some(d => d.path === 'docs/api.md'));
|
|
31
|
+
assert.ok(docs.some(d => d.path === 'docs/deployment.md'));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should return Enterprise documentation requirements', () => {
|
|
35
|
+
const docs = getRequiredDocs('enterprise');
|
|
36
|
+
assert.ok(docs.length >= 5);
|
|
37
|
+
assert.ok(docs.some(d => d.path === 'docs/architecture.md'));
|
|
38
|
+
assert.ok(docs.some(d => d.path === 'docs/runbooks/'));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should throw for unknown tier', () => {
|
|
42
|
+
assert.throws(
|
|
43
|
+
() => getRequiredDocs('invalid'),
|
|
44
|
+
/Unknown tier/
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('validateSections', () => {
|
|
50
|
+
let tempFile;
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
tempFile = path.join(os.tmpdir(), `test-${Date.now()}.md`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
try {
|
|
58
|
+
fs.unlinkSync(tempFile);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
// Ignore
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should return failure when document does not exist', () => {
|
|
65
|
+
const result = validateSections('/nonexistent/file.md', ['Section 1']);
|
|
66
|
+
assert.strictEqual(result.pass, false);
|
|
67
|
+
assert.strictEqual(result.exists, false);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should return failure when document is too short', () => {
|
|
71
|
+
fs.writeFileSync(tempFile, 'too short');
|
|
72
|
+
const result = validateSections(tempFile, ['Section 1']);
|
|
73
|
+
assert.strictEqual(result.pass, false);
|
|
74
|
+
assert.ok(result.missingSections.some(m => m.includes('too short')));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should pass when all sections present', () => {
|
|
78
|
+
const content = `# Test Document
|
|
79
|
+
|
|
80
|
+
## Section 1
|
|
81
|
+
|
|
82
|
+
Content here.
|
|
83
|
+
|
|
84
|
+
## Section 2
|
|
85
|
+
|
|
86
|
+
More content.
|
|
87
|
+
`;
|
|
88
|
+
fs.writeFileSync(tempFile, content);
|
|
89
|
+
const result = validateSections(tempFile, ['Section 1', 'Section 2']);
|
|
90
|
+
assert.strictEqual(result.pass, true);
|
|
91
|
+
assert.strictEqual(result.missingSections.length, 0);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should fail when sections missing', () => {
|
|
95
|
+
const content = `# Test Document
|
|
96
|
+
|
|
97
|
+
## Section 1
|
|
98
|
+
|
|
99
|
+
This is some content here that makes the file longer than 50 bytes minimum requirement.
|
|
100
|
+
`;
|
|
101
|
+
fs.writeFileSync(tempFile, content);
|
|
102
|
+
const result = validateSections(tempFile, ['Section 1', 'Section 2', 'Section 3']);
|
|
103
|
+
assert.strictEqual(result.pass, false);
|
|
104
|
+
assert.ok(result.missingSections.some(m => m.includes('Section 2')));
|
|
105
|
+
assert.ok(result.missingSections.some(m => m.includes('Section 3')));
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('validateDocs', () => {
|
|
110
|
+
let tempDir;
|
|
111
|
+
|
|
112
|
+
beforeEach(() => {
|
|
113
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gate6-test-'));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
afterEach(() => {
|
|
117
|
+
try {
|
|
118
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
119
|
+
} catch (e) {
|
|
120
|
+
// Ignore cleanup errors
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should fail when required documentation is missing', async () => {
|
|
125
|
+
const result = await validateDocs(tempDir, 'mvp');
|
|
126
|
+
assert.strictEqual(result.pass, false);
|
|
127
|
+
assert.ok(result.failures.some(f => f.includes('Missing')));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should pass when MVP documentation exists with required sections', async () => {
|
|
131
|
+
// Create README.md with required sections
|
|
132
|
+
const readmeContent = `# Project
|
|
133
|
+
|
|
134
|
+
Brief description of the project goes here to make the file longer.
|
|
135
|
+
|
|
136
|
+
## Installation
|
|
137
|
+
|
|
138
|
+
Install instructions with detailed content to meet minimum file size requirements.
|
|
139
|
+
|
|
140
|
+
## Usage
|
|
141
|
+
|
|
142
|
+
Usage instructions with detailed content to meet minimum file size requirements.
|
|
143
|
+
|
|
144
|
+
## Configuration
|
|
145
|
+
|
|
146
|
+
Config instructions with detailed content to meet minimum file size requirements.
|
|
147
|
+
`;
|
|
148
|
+
fs.writeFileSync(path.join(tempDir, 'README.md'), readmeContent);
|
|
149
|
+
|
|
150
|
+
const result = await validateDocs(tempDir, 'mvp');
|
|
151
|
+
assert.strictEqual(result.pass, true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should fail when sections are missing', async () => {
|
|
155
|
+
// Create README.md without all required sections
|
|
156
|
+
const readmeContent = `# Project
|
|
157
|
+
|
|
158
|
+
## Installation
|
|
159
|
+
|
|
160
|
+
Install instructions.
|
|
161
|
+
`;
|
|
162
|
+
fs.writeFileSync(path.join(tempDir, 'README.md'), readmeContent);
|
|
163
|
+
|
|
164
|
+
const result = await validateDocs(tempDir, 'mvp');
|
|
165
|
+
assert.strictEqual(result.pass, false);
|
|
166
|
+
assert.ok(result.failures.some(f => f.includes('Missing section')));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should validate medium tier requirements', async () => {
|
|
170
|
+
// Create docs directory
|
|
171
|
+
const docsDir = path.join(tempDir, 'docs');
|
|
172
|
+
fs.mkdirSync(docsDir);
|
|
173
|
+
|
|
174
|
+
// Create README.md with sufficient content
|
|
175
|
+
fs.writeFileSync(path.join(tempDir, 'README.md'), `# Project
|
|
176
|
+
|
|
177
|
+
Brief project description with enough content to meet minimum file size requirements.
|
|
178
|
+
|
|
179
|
+
## Installation
|
|
180
|
+
|
|
181
|
+
Installation instructions with detailed content to meet minimum file size requirements.
|
|
182
|
+
|
|
183
|
+
## Usage
|
|
184
|
+
|
|
185
|
+
Usage instructions with detailed content to meet minimum file size requirements.
|
|
186
|
+
|
|
187
|
+
## Configuration
|
|
188
|
+
|
|
189
|
+
Configuration instructions with detailed content to meet minimum file size requirements.
|
|
190
|
+
|
|
191
|
+
## API Reference
|
|
192
|
+
|
|
193
|
+
API reference overview with detailed content to meet minimum file size requirements.
|
|
194
|
+
`);
|
|
195
|
+
|
|
196
|
+
// Create api.md with sufficient content
|
|
197
|
+
fs.writeFileSync(path.join(docsDir, 'api.md'), `# API Docs
|
|
198
|
+
|
|
199
|
+
API documentation overview with enough content to meet minimum file size requirements.
|
|
200
|
+
|
|
201
|
+
## Endpoints
|
|
202
|
+
|
|
203
|
+
Endpoints section with detailed content to meet minimum file size requirements.
|
|
204
|
+
|
|
205
|
+
## Request/Response
|
|
206
|
+
|
|
207
|
+
Request/Response section with detailed content to meet minimum file size requirements.
|
|
208
|
+
|
|
209
|
+
## Authentication
|
|
210
|
+
|
|
211
|
+
Authentication section with detailed content to meet minimum file size requirements.
|
|
212
|
+
|
|
213
|
+
## Error Codes
|
|
214
|
+
|
|
215
|
+
Error Codes section with detailed content to meet minimum file size requirements.
|
|
216
|
+
`);
|
|
217
|
+
|
|
218
|
+
// Create deployment.md with sufficient content
|
|
219
|
+
fs.writeFileSync(path.join(docsDir, 'deployment.md'), `# Deployment
|
|
220
|
+
|
|
221
|
+
Deployment guide overview with enough content to meet minimum file size requirements.
|
|
222
|
+
|
|
223
|
+
## Prerequisites
|
|
224
|
+
|
|
225
|
+
Prerequisites section with detailed content to meet minimum file size requirements.
|
|
226
|
+
|
|
227
|
+
## Environment Variables
|
|
228
|
+
|
|
229
|
+
Environment Variables section with detailed content to meet minimum file size requirements.
|
|
230
|
+
|
|
231
|
+
## Deploy Steps
|
|
232
|
+
|
|
233
|
+
Deploy Steps section with detailed content to meet minimum file size requirements.
|
|
234
|
+
|
|
235
|
+
## Rollback
|
|
236
|
+
|
|
237
|
+
Rollback section with detailed content to meet minimum file size requirements.
|
|
238
|
+
`);
|
|
239
|
+
|
|
240
|
+
const result = await validateDocs(tempDir, 'medium');
|
|
241
|
+
assert.strictEqual(result.pass, true);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate 7 Release Readiness Validator Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import { strict as assert } from 'assert';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
// Import the validator
|
|
16
|
+
const {
|
|
17
|
+
validateReleaseReadiness,
|
|
18
|
+
getReleaseRequirements,
|
|
19
|
+
validateRollbackPlan
|
|
20
|
+
} = await import(path.join(__dirname, '../../../.planning/gates/gate-07-release/validator.cjs'));
|
|
21
|
+
|
|
22
|
+
describe('Gate 7 Validator', () => {
|
|
23
|
+
describe('getReleaseRequirements', () => {
|
|
24
|
+
it('should return MVP requirements', () => {
|
|
25
|
+
const reqs = getReleaseRequirements('mvp');
|
|
26
|
+
assert.ok(reqs.requirements.includes('smoke_tests'));
|
|
27
|
+
assert.ok(reqs.requirements.includes('rollback_plan'));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return Medium requirements', () => {
|
|
31
|
+
const reqs = getReleaseRequirements('medium');
|
|
32
|
+
assert.ok(reqs.requirements.includes('smoke_tests'));
|
|
33
|
+
assert.ok(reqs.requirements.includes('rollback_plan'));
|
|
34
|
+
assert.ok(reqs.requirements.includes('monitoring'));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should return Enterprise requirements', () => {
|
|
38
|
+
const reqs = getReleaseRequirements('enterprise');
|
|
39
|
+
assert.ok(reqs.requirements.includes('smoke_tests'));
|
|
40
|
+
assert.ok(reqs.requirements.includes('rollback_plan'));
|
|
41
|
+
assert.ok(reqs.requirements.includes('monitoring'));
|
|
42
|
+
assert.ok(reqs.requirements.includes('runbooks'));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should throw for unknown tier', () => {
|
|
46
|
+
assert.throws(
|
|
47
|
+
() => getReleaseRequirements('invalid'),
|
|
48
|
+
/Unknown tier/
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('validateRollbackPlan', () => {
|
|
54
|
+
let tempFile;
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
tempFile = path.join(os.tmpdir(), `rollback-${Date.now()}.md`);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
try {
|
|
62
|
+
fs.unlinkSync(tempFile);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
// Ignore
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return failure when rollback plan does not exist', () => {
|
|
69
|
+
const result = validateRollbackPlan('/nonexistent/rollback.md');
|
|
70
|
+
assert.strictEqual(result.pass, false);
|
|
71
|
+
assert.strictEqual(result.valid, false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should fail when rollback plan has too few steps', () => {
|
|
75
|
+
const content = `# Rollback Plan
|
|
76
|
+
|
|
77
|
+
1. Stop the app
|
|
78
|
+
2. Start the app
|
|
79
|
+
`;
|
|
80
|
+
fs.writeFileSync(tempFile, content);
|
|
81
|
+
const result = validateRollbackPlan(tempFile);
|
|
82
|
+
assert.strictEqual(result.pass, false);
|
|
83
|
+
assert.ok(result.issues.some(i => i.includes('too simple')));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should pass when rollback plan is complete', () => {
|
|
87
|
+
const content = `# Rollback Plan
|
|
88
|
+
|
|
89
|
+
## Backup Procedure
|
|
90
|
+
1. Create database backup
|
|
91
|
+
2. Backup current code
|
|
92
|
+
|
|
93
|
+
## Revert Procedure
|
|
94
|
+
1. Stop the application
|
|
95
|
+
2. Restore previous version
|
|
96
|
+
3. Restore database from backup
|
|
97
|
+
4. Restart application
|
|
98
|
+
|
|
99
|
+
## Verification
|
|
100
|
+
1. Check health endpoint
|
|
101
|
+
2. Verify core functionality
|
|
102
|
+
3. Monitor error rates
|
|
103
|
+
`;
|
|
104
|
+
fs.writeFileSync(tempFile, content);
|
|
105
|
+
const result = validateRollbackPlan(tempFile);
|
|
106
|
+
assert.strictEqual(result.pass, true);
|
|
107
|
+
assert.ok(result.stepCount >= 3);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should fail when missing backup procedure', () => {
|
|
111
|
+
const content = `# Rollback Plan
|
|
112
|
+
|
|
113
|
+
1. Revert code
|
|
114
|
+
2. Restart app
|
|
115
|
+
`;
|
|
116
|
+
fs.writeFileSync(tempFile, content);
|
|
117
|
+
const result = validateRollbackPlan(tempFile);
|
|
118
|
+
assert.strictEqual(result.pass, false);
|
|
119
|
+
assert.ok(result.issues.some(i => i.includes('backup')));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('validateReleaseReadiness', () => {
|
|
124
|
+
let tempDir;
|
|
125
|
+
|
|
126
|
+
beforeEach(() => {
|
|
127
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gate7-test-'));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
afterEach(() => {
|
|
131
|
+
try {
|
|
132
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// Ignore cleanup errors
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should fail MVP when rollback plan missing', () => {
|
|
139
|
+
const result = validateReleaseReadiness(tempDir, 'mvp');
|
|
140
|
+
assert.strictEqual(result.pass, false);
|
|
141
|
+
assert.ok(result.failures.some(f => f.includes('Rollback')));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should pass MVP with valid rollback plan', () => {
|
|
145
|
+
// Create docs directory and rollback plan
|
|
146
|
+
const docsDir = path.join(tempDir, 'docs');
|
|
147
|
+
fs.mkdirSync(docsDir);
|
|
148
|
+
|
|
149
|
+
const rollbackContent = `# Rollback Plan
|
|
150
|
+
|
|
151
|
+
## Backup
|
|
152
|
+
1. Backup database
|
|
153
|
+
2. Backup code
|
|
154
|
+
|
|
155
|
+
## Revert
|
|
156
|
+
1. Stop application
|
|
157
|
+
2. Restore previous version
|
|
158
|
+
3. Restore database
|
|
159
|
+
4. Restart application
|
|
160
|
+
|
|
161
|
+
## Verify
|
|
162
|
+
1. Check health
|
|
163
|
+
2. Test functionality
|
|
164
|
+
`;
|
|
165
|
+
fs.writeFileSync(path.join(docsDir, 'rollback.md'), rollbackContent);
|
|
166
|
+
|
|
167
|
+
const result = validateReleaseReadiness(tempDir, 'mvp');
|
|
168
|
+
assert.strictEqual(result.pass, true);
|
|
169
|
+
assert.strictEqual(result.rollback_valid, true);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should fail medium tier without monitoring', () => {
|
|
173
|
+
// Create valid rollback
|
|
174
|
+
const docsDir = path.join(tempDir, 'docs');
|
|
175
|
+
fs.mkdirSync(docsDir);
|
|
176
|
+
fs.writeFileSync(path.join(docsDir, 'rollback.md'), `# Rollback
|
|
177
|
+
|
|
178
|
+
## Backup
|
|
179
|
+
1. Backup DB
|
|
180
|
+
|
|
181
|
+
## Revert
|
|
182
|
+
1. Stop
|
|
183
|
+
2. Restore
|
|
184
|
+
3. Start
|
|
185
|
+
|
|
186
|
+
## Verify
|
|
187
|
+
1. Check
|
|
188
|
+
`);
|
|
189
|
+
|
|
190
|
+
const result = validateReleaseReadiness(tempDir, 'medium');
|
|
191
|
+
assert.strictEqual(result.pass, false);
|
|
192
|
+
assert.ok(result.failures.some(f => f.includes('Monitoring')));
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should pass medium tier with monitoring configured', () => {
|
|
196
|
+
// Create docs and monitoring
|
|
197
|
+
const docsDir = path.join(tempDir, 'docs');
|
|
198
|
+
fs.mkdirSync(docsDir);
|
|
199
|
+
fs.mkdirSync(path.join(tempDir, '.planning', 'observability'), { recursive: true });
|
|
200
|
+
|
|
201
|
+
fs.writeFileSync(path.join(docsDir, 'rollback.md'), `# Rollback
|
|
202
|
+
|
|
203
|
+
## Backup
|
|
204
|
+
1. Backup DB
|
|
205
|
+
|
|
206
|
+
## Revert
|
|
207
|
+
1. Stop
|
|
208
|
+
2. Restore previous version
|
|
209
|
+
3. Start
|
|
210
|
+
|
|
211
|
+
## Verify
|
|
212
|
+
1. Check
|
|
213
|
+
`);
|
|
214
|
+
|
|
215
|
+
const result = validateReleaseReadiness(tempDir, 'medium');
|
|
216
|
+
assert.strictEqual(result.pass, true, `Expected pass but got failures: ${result.failures.join(', ')}`);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|