agentic-qe 1.4.3 → 1.5.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/.claude/agents/qe-api-contract-validator.md +133 -27
- package/.claude/agents/qe-api-contract-validator.md.backup +1148 -0
- package/.claude/agents/qe-api-contract-validator.md.backup-20251107-134747 +1148 -0
- package/.claude/agents/qe-api-contract-validator.md.backup-phase2-20251107-140039 +1123 -0
- package/.claude/agents/qe-chaos-engineer.md +142 -23
- package/.claude/agents/qe-chaos-engineer.md.backup +808 -0
- package/.claude/agents/qe-chaos-engineer.md.backup-20251107-134747 +808 -0
- package/.claude/agents/qe-chaos-engineer.md.backup-phase2-20251107-140039 +787 -0
- package/.claude/agents/qe-code-complexity.md +111 -23
- package/.claude/agents/qe-code-complexity.md.backup +291 -0
- package/.claude/agents/qe-code-complexity.md.backup-20251107-134747 +291 -0
- package/.claude/agents/qe-code-complexity.md.backup-phase2-20251107-140039 +286 -0
- package/.claude/agents/qe-coverage-analyzer.md +306 -30
- package/.claude/agents/qe-coverage-analyzer.md.backup +467 -0
- package/.claude/agents/qe-coverage-analyzer.md.backup-20251107-134747 +467 -0
- package/.claude/agents/qe-coverage-analyzer.md.backup-phase2-20251107-140039 +438 -0
- package/.claude/agents/qe-deployment-readiness.md +84 -28
- package/.claude/agents/qe-deployment-readiness.md.backup +1166 -0
- package/.claude/agents/qe-deployment-readiness.md.backup-20251107-134747 +1166 -0
- package/.claude/agents/qe-deployment-readiness.md.backup-phase2-20251107-140039 +1140 -0
- package/.claude/agents/qe-flaky-test-hunter.md +277 -35
- package/.claude/agents/qe-flaky-test-hunter.md.backup +1195 -0
- package/.claude/agents/qe-flaky-test-hunter.md.backup-20251107-134747 +1195 -0
- package/.claude/agents/qe-flaky-test-hunter.md.backup-phase2-20251107-140039 +1162 -0
- package/.claude/agents/qe-fleet-commander.md +126 -23
- package/.claude/agents/qe-fleet-commander.md.backup +718 -0
- package/.claude/agents/qe-fleet-commander.md.backup-20251107-134747 +718 -0
- package/.claude/agents/qe-fleet-commander.md.backup-phase2-20251107-140039 +697 -0
- package/.claude/agents/qe-performance-tester.md +314 -57
- package/.claude/agents/qe-performance-tester.md.backup +428 -0
- package/.claude/agents/qe-performance-tester.md.backup-20251107-134747 +428 -0
- package/.claude/agents/qe-performance-tester.md.backup-phase2-20251107-140039 +372 -0
- package/.claude/agents/qe-production-intelligence.md +126 -27
- package/.claude/agents/qe-production-intelligence.md.backup +1219 -0
- package/.claude/agents/qe-production-intelligence.md.backup-20251107-134747 +1219 -0
- package/.claude/agents/qe-production-intelligence.md.backup-phase2-20251107-140039 +1194 -0
- package/.claude/agents/qe-quality-analyzer.md +127 -32
- package/.claude/agents/qe-quality-analyzer.md.backup +425 -0
- package/.claude/agents/qe-quality-analyzer.md.backup-20251107-134747 +425 -0
- package/.claude/agents/qe-quality-analyzer.md.backup-phase2-20251107-140039 +394 -0
- package/.claude/agents/qe-quality-gate.md +148 -33
- package/.claude/agents/qe-quality-gate.md.backup +446 -0
- package/.claude/agents/qe-quality-gate.md.backup-20251107-134747 +446 -0
- package/.claude/agents/qe-quality-gate.md.backup-phase2-20251107-140039 +415 -0
- package/.claude/agents/qe-regression-risk-analyzer.md +78 -27
- package/.claude/agents/qe-regression-risk-analyzer.md.backup +1009 -0
- package/.claude/agents/qe-regression-risk-analyzer.md.backup-20251107-134747 +1009 -0
- package/.claude/agents/qe-regression-risk-analyzer.md.backup-phase2-20251107-140039 +984 -0
- package/.claude/agents/qe-requirements-validator.md +131 -27
- package/.claude/agents/qe-requirements-validator.md.backup +748 -0
- package/.claude/agents/qe-requirements-validator.md.backup-20251107-134747 +748 -0
- package/.claude/agents/qe-requirements-validator.md.backup-phase2-20251107-140039 +723 -0
- package/.claude/agents/qe-security-scanner.md +137 -62
- package/.claude/agents/qe-security-scanner.md.backup +634 -0
- package/.claude/agents/qe-security-scanner.md.backup-20251107-134747 +634 -0
- package/.claude/agents/qe-security-scanner.md.backup-phase2-20251107-140039 +573 -0
- package/.claude/agents/qe-test-data-architect.md +129 -26
- package/.claude/agents/qe-test-data-architect.md.backup +1064 -0
- package/.claude/agents/qe-test-data-architect.md.backup-20251107-134747 +1064 -0
- package/.claude/agents/qe-test-data-architect.md.backup-phase2-20251107-140039 +1040 -0
- package/.claude/agents/qe-test-executor.md +165 -21
- package/.claude/agents/qe-test-executor.md.backup +389 -0
- package/.claude/agents/qe-test-executor.md.backup-20251107-134747 +389 -0
- package/.claude/agents/qe-test-executor.md.backup-phase2-20251107-140039 +369 -0
- package/.claude/agents/qe-test-generator.md +379 -34
- package/.claude/agents/qe-test-generator.md.backup +997 -0
- package/.claude/agents/qe-test-generator.md.backup-20251107-134747 +997 -0
- package/.claude/agents/qe-visual-tester.md +236 -23
- package/.claude/agents/qe-visual-tester.md.backup +777 -0
- package/.claude/agents/qe-visual-tester.md.backup-20251107-134747 +777 -0
- package/.claude/agents/qe-visual-tester.md.backup-phase2-20251107-140039 +756 -0
- package/.claude/agents/subagents/qe-code-reviewer.md +59 -0
- package/.claude/agents/subagents/qe-data-generator.md +60 -0
- package/.claude/agents/subagents/qe-integration-tester.md +77 -0
- package/.claude/agents/subagents/qe-performance-validator.md +55 -0
- package/.claude/agents/subagents/qe-security-auditor.md +51 -0
- package/.claude/agents/subagents/qe-test-implementer.md +371 -0
- package/.claude/agents/subagents/qe-test-refactorer.md +510 -0
- package/.claude/agents/subagents/qe-test-writer.md +603 -0
- package/.claude/skills/accessibility-testing/SKILL.md +764 -777
- package/.claude/skills/agentic-quality-engineering/SKILL.md +0 -6
- package/.claude/skills/api-testing-patterns/SKILL.md +0 -12
- package/.claude/skills/bug-reporting-excellence/SKILL.md +0 -6
- package/.claude/skills/chaos-engineering-resilience/SKILL.md +0 -6
- package/.claude/skills/code-review-quality/SKILL.md +0 -6
- package/.claude/skills/compatibility-testing/SKILL.md +0 -6
- package/.claude/skills/compliance-testing/SKILL.md +0 -6
- package/.claude/skills/consultancy-practices/SKILL.md +0 -6
- package/.claude/skills/context-driven-testing/SKILL.md +0 -6
- package/.claude/skills/contract-testing/SKILL.md +0 -6
- package/.claude/skills/database-testing/SKILL.md +0 -6
- package/.claude/skills/exploratory-testing-advanced/SKILL.md +0 -6
- package/.claude/skills/holistic-testing-pact/SKILL.md +0 -6
- package/.claude/skills/localization-testing/SKILL.md +0 -6
- package/.claude/skills/mobile-testing/SKILL.md +535 -548
- package/.claude/skills/mutation-testing/SKILL.md +0 -6
- package/.claude/skills/performance-testing/SKILL.md +0 -6
- package/.claude/skills/quality-metrics/SKILL.md +0 -12
- package/.claude/skills/refactoring-patterns/SKILL.md +0 -6
- package/.claude/skills/regression-testing/SKILL.md +1033 -1045
- package/.claude/skills/risk-based-testing/SKILL.md +0 -12
- package/.claude/skills/security-testing/SKILL.md +0 -6
- package/.claude/skills/shift-left-testing/SKILL.md +529 -535
- package/.claude/skills/shift-right-testing/SKILL.md +585 -591
- package/.claude/skills/tdd-london-chicago/SKILL.md +0 -6
- package/.claude/skills/technical-writing/SKILL.md +0 -6
- package/.claude/skills/test-automation-strategy/SKILL.md +0 -6
- package/.claude/skills/test-data-management/SKILL.md +1054 -1067
- package/.claude/skills/test-design-techniques/SKILL.md +0 -6
- package/.claude/skills/test-environment-management/SKILL.md +0 -6
- package/.claude/skills/test-reporting-analytics/SKILL.md +0 -6
- package/.claude/skills/visual-testing-advanced/SKILL.md +0 -6
- package/.claude/skills/xp-practices/SKILL.md +0 -6
- package/CHANGELOG.md +504 -0
- package/README.md +24 -16
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +97 -44
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/core/FleetManager.d.ts.map +1 -1
- package/dist/core/FleetManager.js +17 -5
- package/dist/core/FleetManager.js.map +1 -1
- package/dist/core/MemoryManager.d.ts +27 -0
- package/dist/core/MemoryManager.d.ts.map +1 -1
- package/dist/core/MemoryManager.js +69 -4
- package/dist/core/MemoryManager.js.map +1 -1
- package/dist/core/PatternDatabaseAdapter.d.ts.map +1 -1
- package/dist/core/PatternDatabaseAdapter.js +14 -4
- package/dist/core/PatternDatabaseAdapter.js.map +1 -1
- package/dist/learning/LearningEngine.d.ts.map +1 -1
- package/dist/learning/LearningEngine.js +18 -4
- package/dist/learning/LearningEngine.js.map +1 -1
- package/dist/mcp/handlers/coordination/index.d.ts +14 -14
- package/dist/mcp/handlers/coordination/index.d.ts.map +1 -1
- package/dist/mcp/handlers/coordination/index.js +14 -14
- package/dist/mcp/handlers/coordination/index.js.map +1 -1
- package/dist/mcp/handlers/coordination/task-status.d.ts.map +1 -1
- package/dist/mcp/handlers/coordination/task-status.js +3 -5
- package/dist/mcp/handlers/coordination/task-status.js.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.d.ts.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.js +39 -10
- package/dist/mcp/handlers/phase2/Phase2Tools.js.map +1 -1
- package/dist/mcp/handlers/phase3/Phase3DomainTools.d.ts +63 -0
- package/dist/mcp/handlers/phase3/Phase3DomainTools.d.ts.map +1 -0
- package/dist/mcp/handlers/phase3/Phase3DomainTools.js +885 -0
- package/dist/mcp/handlers/phase3/Phase3DomainTools.js.map +1 -0
- package/dist/mcp/handlers/phase3/index.d.ts +6 -0
- package/dist/mcp/handlers/phase3/index.d.ts.map +1 -0
- package/dist/mcp/handlers/phase3/index.js +10 -0
- package/dist/mcp/handlers/phase3/index.js.map +1 -0
- package/dist/mcp/handlers/prediction/index.d.ts +10 -10
- package/dist/mcp/handlers/prediction/index.d.ts.map +1 -1
- package/dist/mcp/handlers/prediction/index.js +10 -10
- package/dist/mcp/handlers/prediction/index.js.map +1 -1
- package/dist/mcp/handlers/security/check-authz.d.ts +152 -0
- package/dist/mcp/handlers/security/check-authz.d.ts.map +1 -0
- package/dist/mcp/handlers/security/check-authz.js +434 -0
- package/dist/mcp/handlers/security/check-authz.js.map +1 -0
- package/dist/mcp/handlers/security/generate-report.d.ts +156 -0
- package/dist/mcp/handlers/security/generate-report.d.ts.map +1 -0
- package/dist/mcp/handlers/security/generate-report.js +469 -0
- package/dist/mcp/handlers/security/generate-report.js.map +1 -0
- package/dist/mcp/handlers/security/index.d.ts +80 -0
- package/dist/mcp/handlers/security/index.d.ts.map +1 -0
- package/dist/mcp/handlers/security/index.js +91 -0
- package/dist/mcp/handlers/security/index.js.map +1 -0
- package/dist/mcp/handlers/security/scan-comprehensive.d.ts +66 -0
- package/dist/mcp/handlers/security/scan-comprehensive.d.ts.map +1 -0
- package/dist/mcp/handlers/security/scan-comprehensive.js +296 -0
- package/dist/mcp/handlers/security/scan-comprehensive.js.map +1 -0
- package/dist/mcp/handlers/security/scan-dependencies.d.ts +148 -0
- package/dist/mcp/handlers/security/scan-dependencies.d.ts.map +1 -0
- package/dist/mcp/handlers/security/scan-dependencies.js +354 -0
- package/dist/mcp/handlers/security/scan-dependencies.js.map +1 -0
- package/dist/mcp/handlers/security/validate-auth.d.ts +128 -0
- package/dist/mcp/handlers/security/validate-auth.d.ts.map +1 -0
- package/dist/mcp/handlers/security/validate-auth.js +294 -0
- package/dist/mcp/handlers/security/validate-auth.js.map +1 -0
- package/dist/mcp/handlers/task-orchestrate.d.ts +21 -1
- package/dist/mcp/handlers/task-orchestrate.d.ts.map +1 -1
- package/dist/mcp/handlers/task-orchestrate.js +32 -2
- package/dist/mcp/handlers/task-orchestrate.js.map +1 -1
- package/dist/mcp/handlers/test/generate-integration-tests.d.ts +95 -0
- package/dist/mcp/handlers/test/generate-integration-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/test/generate-integration-tests.js +286 -0
- package/dist/mcp/handlers/test/generate-integration-tests.js.map +1 -0
- package/dist/mcp/handlers/test/generate-unit-tests.d.ts +89 -0
- package/dist/mcp/handlers/test/generate-unit-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/test/generate-unit-tests.js +273 -0
- package/dist/mcp/handlers/test/generate-unit-tests.js.map +1 -0
- package/dist/mcp/handlers/test/optimize-test-suite.d.ts +97 -0
- package/dist/mcp/handlers/test/optimize-test-suite.d.ts.map +1 -0
- package/dist/mcp/handlers/test/optimize-test-suite.js +282 -0
- package/dist/mcp/handlers/test/optimize-test-suite.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +212 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/deprecated.d.ts +1390 -0
- package/dist/mcp/tools/deprecated.d.ts.map +1 -0
- package/dist/mcp/tools/deprecated.js +859 -0
- package/dist/mcp/tools/deprecated.js.map +1 -0
- package/dist/mcp/tools/qe/api-contract/index.d.ts +138 -0
- package/dist/mcp/tools/qe/api-contract/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/api-contract/index.js +572 -0
- package/dist/mcp/tools/qe/api-contract/index.js.map +1 -0
- package/dist/mcp/tools/qe/code-quality/analyze-complexity.d.ts +110 -0
- package/dist/mcp/tools/qe/code-quality/analyze-complexity.d.ts.map +1 -0
- package/dist/mcp/tools/qe/code-quality/analyze-complexity.js +381 -0
- package/dist/mcp/tools/qe/code-quality/analyze-complexity.js.map +1 -0
- package/dist/mcp/tools/qe/code-quality/calculate-quality-metrics.d.ts +115 -0
- package/dist/mcp/tools/qe/code-quality/calculate-quality-metrics.d.ts.map +1 -0
- package/dist/mcp/tools/qe/code-quality/calculate-quality-metrics.js +461 -0
- package/dist/mcp/tools/qe/code-quality/calculate-quality-metrics.js.map +1 -0
- package/dist/mcp/tools/qe/code-quality/index.d.ts +12 -0
- package/dist/mcp/tools/qe/code-quality/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/code-quality/index.js +30 -0
- package/dist/mcp/tools/qe/code-quality/index.js.map +1 -0
- package/dist/mcp/tools/qe/coverage/analyze-with-risk-scoring.d.ts +58 -0
- package/dist/mcp/tools/qe/coverage/analyze-with-risk-scoring.d.ts.map +1 -0
- package/dist/mcp/tools/qe/coverage/analyze-with-risk-scoring.js +172 -0
- package/dist/mcp/tools/qe/coverage/analyze-with-risk-scoring.js.map +1 -0
- package/dist/mcp/tools/qe/coverage/calculate-trends.d.ts +73 -0
- package/dist/mcp/tools/qe/coverage/calculate-trends.d.ts.map +1 -0
- package/dist/mcp/tools/qe/coverage/calculate-trends.js +240 -0
- package/dist/mcp/tools/qe/coverage/calculate-trends.js.map +1 -0
- package/dist/mcp/tools/qe/coverage/detect-gaps-ml.d.ts +38 -0
- package/dist/mcp/tools/qe/coverage/detect-gaps-ml.d.ts.map +1 -0
- package/dist/mcp/tools/qe/coverage/detect-gaps-ml.js +204 -0
- package/dist/mcp/tools/qe/coverage/detect-gaps-ml.js.map +1 -0
- package/dist/mcp/tools/qe/coverage/index.d.ts +12 -0
- package/dist/mcp/tools/qe/coverage/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/coverage/index.js +23 -0
- package/dist/mcp/tools/qe/coverage/index.js.map +1 -0
- package/dist/mcp/tools/qe/coverage/recommend-tests.d.ts +46 -0
- package/dist/mcp/tools/qe/coverage/recommend-tests.d.ts.map +1 -0
- package/dist/mcp/tools/qe/coverage/recommend-tests.js +248 -0
- package/dist/mcp/tools/qe/coverage/recommend-tests.js.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/analyze-patterns.d.ts +179 -0
- package/dist/mcp/tools/qe/flaky-detection/analyze-patterns.d.ts.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/analyze-patterns.js +554 -0
- package/dist/mcp/tools/qe/flaky-detection/analyze-patterns.js.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/detect-statistical.d.ts +172 -0
- package/dist/mcp/tools/qe/flaky-detection/detect-statistical.d.ts.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/detect-statistical.js +498 -0
- package/dist/mcp/tools/qe/flaky-detection/detect-statistical.js.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/index.d.ts +35 -0
- package/dist/mcp/tools/qe/flaky-detection/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/index.js +66 -0
- package/dist/mcp/tools/qe/flaky-detection/index.js.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/stabilize-auto.d.ts +159 -0
- package/dist/mcp/tools/qe/flaky-detection/stabilize-auto.d.ts.map +1 -0
- package/dist/mcp/tools/qe/flaky-detection/stabilize-auto.js +462 -0
- package/dist/mcp/tools/qe/flaky-detection/stabilize-auto.js.map +1 -0
- package/dist/mcp/tools/qe/fleet/index.d.ts +422 -0
- package/dist/mcp/tools/qe/fleet/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/fleet/index.js +652 -0
- package/dist/mcp/tools/qe/fleet/index.js.map +1 -0
- package/dist/mcp/tools/qe/performance/analyze-bottlenecks.d.ts +180 -0
- package/dist/mcp/tools/qe/performance/analyze-bottlenecks.d.ts.map +1 -0
- package/dist/mcp/tools/qe/performance/analyze-bottlenecks.js +347 -0
- package/dist/mcp/tools/qe/performance/analyze-bottlenecks.js.map +1 -0
- package/dist/mcp/tools/qe/performance/generate-report.d.ts +146 -0
- package/dist/mcp/tools/qe/performance/generate-report.d.ts.map +1 -0
- package/dist/mcp/tools/qe/performance/generate-report.js +354 -0
- package/dist/mcp/tools/qe/performance/generate-report.js.map +1 -0
- package/dist/mcp/tools/qe/performance/index.d.ts +13 -0
- package/dist/mcp/tools/qe/performance/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/performance/index.js +24 -0
- package/dist/mcp/tools/qe/performance/index.js.map +1 -0
- package/dist/mcp/tools/qe/performance/monitor-realtime.d.ts +120 -0
- package/dist/mcp/tools/qe/performance/monitor-realtime.d.ts.map +1 -0
- package/dist/mcp/tools/qe/performance/monitor-realtime.js +215 -0
- package/dist/mcp/tools/qe/performance/monitor-realtime.js.map +1 -0
- package/dist/mcp/tools/qe/performance/run-benchmark.d.ts +68 -0
- package/dist/mcp/tools/qe/performance/run-benchmark.d.ts.map +1 -0
- package/dist/mcp/tools/qe/performance/run-benchmark.js +120 -0
- package/dist/mcp/tools/qe/performance/run-benchmark.js.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/assess-deployment-risk.d.ts +239 -0
- package/dist/mcp/tools/qe/quality-gates/assess-deployment-risk.d.ts.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/assess-deployment-risk.js +671 -0
- package/dist/mcp/tools/qe/quality-gates/assess-deployment-risk.js.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/evaluate-quality-gate.d.ts +219 -0
- package/dist/mcp/tools/qe/quality-gates/evaluate-quality-gate.d.ts.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/evaluate-quality-gate.js +732 -0
- package/dist/mcp/tools/qe/quality-gates/evaluate-quality-gate.js.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/generate-quality-report.d.ts +447 -0
- package/dist/mcp/tools/qe/quality-gates/generate-quality-report.d.ts.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/generate-quality-report.js +551 -0
- package/dist/mcp/tools/qe/quality-gates/generate-quality-report.js.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/index.d.ts +40 -0
- package/dist/mcp/tools/qe/quality-gates/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/index.js +56 -0
- package/dist/mcp/tools/qe/quality-gates/index.js.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/validate-quality-metrics.d.ts +226 -0
- package/dist/mcp/tools/qe/quality-gates/validate-quality-metrics.d.ts.map +1 -0
- package/dist/mcp/tools/qe/quality-gates/validate-quality-metrics.js +603 -0
- package/dist/mcp/tools/qe/quality-gates/validate-quality-metrics.js.map +1 -0
- package/dist/mcp/tools/qe/regression/analyze-risk.d.ts +212 -0
- package/dist/mcp/tools/qe/regression/analyze-risk.d.ts.map +1 -0
- package/dist/mcp/tools/qe/regression/analyze-risk.js +617 -0
- package/dist/mcp/tools/qe/regression/analyze-risk.js.map +1 -0
- package/dist/mcp/tools/qe/regression/index.d.ts +36 -0
- package/dist/mcp/tools/qe/regression/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/regression/index.js +63 -0
- package/dist/mcp/tools/qe/regression/index.js.map +1 -0
- package/dist/mcp/tools/qe/regression/select-tests.d.ts +241 -0
- package/dist/mcp/tools/qe/regression/select-tests.d.ts.map +1 -0
- package/dist/mcp/tools/qe/regression/select-tests.js +601 -0
- package/dist/mcp/tools/qe/regression/select-tests.js.map +1 -0
- package/dist/mcp/tools/qe/requirements/generate-bdd-scenarios.d.ts +134 -0
- package/dist/mcp/tools/qe/requirements/generate-bdd-scenarios.d.ts.map +1 -0
- package/dist/mcp/tools/qe/requirements/generate-bdd-scenarios.js +737 -0
- package/dist/mcp/tools/qe/requirements/generate-bdd-scenarios.js.map +1 -0
- package/dist/mcp/tools/qe/requirements/index.d.ts +40 -0
- package/dist/mcp/tools/qe/requirements/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/requirements/index.js +84 -0
- package/dist/mcp/tools/qe/requirements/index.js.map +1 -0
- package/dist/mcp/tools/qe/requirements/validate-requirements.d.ts +196 -0
- package/dist/mcp/tools/qe/requirements/validate-requirements.d.ts.map +1 -0
- package/dist/mcp/tools/qe/requirements/validate-requirements.js +740 -0
- package/dist/mcp/tools/qe/requirements/validate-requirements.js.map +1 -0
- package/dist/mcp/tools/qe/security/detect-vulnerabilities.d.ts +300 -0
- package/dist/mcp/tools/qe/security/detect-vulnerabilities.d.ts.map +1 -0
- package/dist/mcp/tools/qe/security/detect-vulnerabilities.js +492 -0
- package/dist/mcp/tools/qe/security/detect-vulnerabilities.js.map +1 -0
- package/dist/mcp/tools/qe/security/index.d.ts +34 -0
- package/dist/mcp/tools/qe/security/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/security/index.js +44 -0
- package/dist/mcp/tools/qe/security/index.js.map +1 -0
- package/dist/mcp/tools/qe/security/scan-comprehensive.d.ts +240 -0
- package/dist/mcp/tools/qe/security/scan-comprehensive.d.ts.map +1 -0
- package/dist/mcp/tools/qe/security/scan-comprehensive.js +535 -0
- package/dist/mcp/tools/qe/security/scan-comprehensive.js.map +1 -0
- package/dist/mcp/tools/qe/security/validate-compliance.d.ts +299 -0
- package/dist/mcp/tools/qe/security/validate-compliance.d.ts.map +1 -0
- package/dist/mcp/tools/qe/security/validate-compliance.js +517 -0
- package/dist/mcp/tools/qe/security/validate-compliance.js.map +1 -0
- package/dist/mcp/tools/qe/shared/types.d.ts +840 -0
- package/dist/mcp/tools/qe/shared/types.d.ts.map +1 -0
- package/dist/mcp/tools/qe/shared/types.js +13 -0
- package/dist/mcp/tools/qe/shared/types.js.map +1 -0
- package/dist/mcp/tools/qe/test-data/analyze-schema.d.ts +264 -0
- package/dist/mcp/tools/qe/test-data/analyze-schema.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-data/analyze-schema.js +553 -0
- package/dist/mcp/tools/qe/test-data/analyze-schema.js.map +1 -0
- package/dist/mcp/tools/qe/test-data/generate-test-data.d.ts +167 -0
- package/dist/mcp/tools/qe/test-data/generate-test-data.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-data/generate-test-data.js +336 -0
- package/dist/mcp/tools/qe/test-data/generate-test-data.js.map +1 -0
- package/dist/mcp/tools/qe/test-data/index.d.ts +44 -0
- package/dist/mcp/tools/qe/test-data/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-data/index.js +90 -0
- package/dist/mcp/tools/qe/test-data/index.js.map +1 -0
- package/dist/mcp/tools/qe/test-data/mask-sensitive-data.d.ts +165 -0
- package/dist/mcp/tools/qe/test-data/mask-sensitive-data.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-data/mask-sensitive-data.js +342 -0
- package/dist/mcp/tools/qe/test-data/mask-sensitive-data.js.map +1 -0
- package/dist/mcp/tools/qe/test-generation/analyze-test-quality.d.ts +144 -0
- package/dist/mcp/tools/qe/test-generation/analyze-test-quality.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-generation/analyze-test-quality.js +432 -0
- package/dist/mcp/tools/qe/test-generation/analyze-test-quality.js.map +1 -0
- package/dist/mcp/tools/qe/test-generation/generate-integration-tests.d.ts +98 -0
- package/dist/mcp/tools/qe/test-generation/generate-integration-tests.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-generation/generate-integration-tests.js +459 -0
- package/dist/mcp/tools/qe/test-generation/generate-integration-tests.js.map +1 -0
- package/dist/mcp/tools/qe/test-generation/generate-unit-tests.d.ts +83 -0
- package/dist/mcp/tools/qe/test-generation/generate-unit-tests.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-generation/generate-unit-tests.js +483 -0
- package/dist/mcp/tools/qe/test-generation/generate-unit-tests.js.map +1 -0
- package/dist/mcp/tools/qe/test-generation/index.d.ts +56 -0
- package/dist/mcp/tools/qe/test-generation/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-generation/index.js +97 -0
- package/dist/mcp/tools/qe/test-generation/index.js.map +1 -0
- package/dist/mcp/tools/qe/test-generation/optimize-test-suite.d.ts +124 -0
- package/dist/mcp/tools/qe/test-generation/optimize-test-suite.d.ts.map +1 -0
- package/dist/mcp/tools/qe/test-generation/optimize-test-suite.js +362 -0
- package/dist/mcp/tools/qe/test-generation/optimize-test-suite.js.map +1 -0
- package/dist/mcp/tools/qe/visual/compare-screenshots.d.ts +119 -0
- package/dist/mcp/tools/qe/visual/compare-screenshots.d.ts.map +1 -0
- package/dist/mcp/tools/qe/visual/compare-screenshots.js +280 -0
- package/dist/mcp/tools/qe/visual/compare-screenshots.js.map +1 -0
- package/dist/mcp/tools/qe/visual/detect-regression.d.ts +138 -0
- package/dist/mcp/tools/qe/visual/detect-regression.d.ts.map +1 -0
- package/dist/mcp/tools/qe/visual/detect-regression.js +271 -0
- package/dist/mcp/tools/qe/visual/detect-regression.js.map +1 -0
- package/dist/mcp/tools/qe/visual/index.d.ts +16 -0
- package/dist/mcp/tools/qe/visual/index.d.ts.map +1 -0
- package/dist/mcp/tools/qe/visual/index.js +22 -0
- package/dist/mcp/tools/qe/visual/index.js.map +1 -0
- package/dist/mcp/tools/qe/visual/validate-accessibility.d.ts +276 -0
- package/dist/mcp/tools/qe/visual/validate-accessibility.d.ts.map +1 -0
- package/dist/mcp/tools/qe/visual/validate-accessibility.js +413 -0
- package/dist/mcp/tools/qe/visual/validate-accessibility.js.map +1 -0
- package/dist/mcp/tools.d.ts +44 -0
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +1980 -1
- package/dist/mcp/tools.js.map +1 -1
- package/package.json +2 -2
- package/dist/learning/__mocks__/LearningEngine.d.ts +0 -39
- package/dist/learning/__mocks__/LearningEngine.d.ts.map +0 -1
- package/dist/learning/__mocks__/LearningEngine.js +0 -116
- package/dist/learning/__mocks__/LearningEngine.js.map +0 -1
- package/dist/utils/__mocks__/Database.d.ts +0 -85
- package/dist/utils/__mocks__/Database.d.ts.map +0 -1
- package/dist/utils/__mocks__/Database.js +0 -125
- package/dist/utils/__mocks__/Database.js.map +0 -1
- package/dist/utils/__mocks__/Logger.d.ts +0 -26
- package/dist/utils/__mocks__/Logger.d.ts.map +0 -1
- package/dist/utils/__mocks__/Logger.js +0 -44
- package/dist/utils/__mocks__/Logger.js.map +0 -1
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Requirements Validation Tool - INVEST Criteria Analysis
|
|
4
|
+
*
|
|
5
|
+
* Validates requirements against INVEST criteria (Independent, Negotiable, Valuable,
|
|
6
|
+
* Estimable, Small, Testable) and SMART framework (Specific, Measurable, Achievable,
|
|
7
|
+
* Relevant, Time-bound) with detailed scoring and recommendations.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Multi-criteria validation with weighted scoring
|
|
11
|
+
* - Ambiguous language detection using NLP patterns
|
|
12
|
+
* - Testability analysis with clarity assessment
|
|
13
|
+
* - Acceptance criteria validation with SMART framework
|
|
14
|
+
* - Risk indicators and improvement recommendations
|
|
15
|
+
* - Detailed validation report generation
|
|
16
|
+
*
|
|
17
|
+
* @module tools/qe/requirements/validate-requirements
|
|
18
|
+
* @version 1.0.0
|
|
19
|
+
* @author Agentic QE Team - Phase 3
|
|
20
|
+
* @date 2025-11-09
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.validateRequirements = validateRequirements;
|
|
24
|
+
// ==================== Language Pattern Detection ====================
|
|
25
|
+
const VAGUE_TERMS = /\b(fast|slow|good|bad|nice|easy|hard|better|worse|large|small)\b/gi;
|
|
26
|
+
const AMBIGUOUS_MODALS = /\b(should|could|might|may|probably|possibly|perhaps)\b/gi;
|
|
27
|
+
const SUBJECTIVE_TERMS = /\b(user-friendly|intuitive|simple|complex|efficient|robust)\b/gi;
|
|
28
|
+
const PASSIVE_VOICE = /\b(is|are|was|were|be|been|being)\s+\w+ed\b/gi;
|
|
29
|
+
const PASSIVE_CONSTRUCTION = /\b(to be|to have been)\b/gi;
|
|
30
|
+
// ==================== Main Validation Function ====================
|
|
31
|
+
/**
|
|
32
|
+
* Validate requirements against INVEST criteria and SMART framework
|
|
33
|
+
*
|
|
34
|
+
* @param params - Validation parameters
|
|
35
|
+
* @returns Batch validation result for all requirements
|
|
36
|
+
*/
|
|
37
|
+
async function validateRequirements(params) {
|
|
38
|
+
const startTime = Date.now();
|
|
39
|
+
const requestId = generateRequestId();
|
|
40
|
+
try {
|
|
41
|
+
if (!params.requirements || params.requirements.length === 0) {
|
|
42
|
+
throw new Error('At least one requirement must be provided');
|
|
43
|
+
}
|
|
44
|
+
const results = [];
|
|
45
|
+
// Validate each requirement in parallel
|
|
46
|
+
const validationPromises = params.requirements.map((req) => validateSingleRequirement(req, params.strictMode ?? false));
|
|
47
|
+
const validatedResults = await Promise.all(validationPromises);
|
|
48
|
+
results.push(...validatedResults);
|
|
49
|
+
// Calculate summary statistics
|
|
50
|
+
const passCount = results.filter((r) => r.passed).length;
|
|
51
|
+
const failCount = results.length - passCount;
|
|
52
|
+
const criticalCount = results.filter((r) => r.riskLevel === 'critical').length;
|
|
53
|
+
const avgScore = results.reduce((sum, r) => sum + r.overallScore, 0) / results.length;
|
|
54
|
+
const avgInvest = results.reduce((sum, r) => sum +
|
|
55
|
+
(r.investCriteria.reduce((s, c) => s + c.score, 0) / r.investCriteria.length), 0) / results.length;
|
|
56
|
+
const avgSmart = results.reduce((sum, r) => sum + r.smartAnalysis.overallScore, 0) / results.length;
|
|
57
|
+
const avgTestability = results.reduce((sum, r) => sum + r.testabilityScore, 0) / results.length;
|
|
58
|
+
// Compile common issues
|
|
59
|
+
const issueCounts = new Map();
|
|
60
|
+
for (const result of results) {
|
|
61
|
+
for (const issue of result.keyIssues) {
|
|
62
|
+
issueCounts.set(issue, (issueCounts.get(issue) ?? 0) + 1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const commonIssues = Array.from(issueCounts.entries())
|
|
66
|
+
.sort((a, b) => b[1] - a[1])
|
|
67
|
+
.slice(0, 5)
|
|
68
|
+
.map((entry) => entry[0]);
|
|
69
|
+
// Compile top recommendations
|
|
70
|
+
const recCounts = new Map();
|
|
71
|
+
for (const result of results) {
|
|
72
|
+
for (const rec of result.recommendations) {
|
|
73
|
+
recCounts.set(rec, (recCounts.get(rec) ?? 0) + 1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const topRecommendations = Array.from(recCounts.entries())
|
|
77
|
+
.sort((a, b) => b[1] - a[1])
|
|
78
|
+
.slice(0, 5)
|
|
79
|
+
.map((entry) => entry[0]);
|
|
80
|
+
const batchResult = {
|
|
81
|
+
requirementsValidated: params.requirements.length,
|
|
82
|
+
passCount,
|
|
83
|
+
failCount,
|
|
84
|
+
criticalIssuesCount: criticalCount,
|
|
85
|
+
averageScore: Math.round(avgScore * 100) / 100,
|
|
86
|
+
results,
|
|
87
|
+
summary: {
|
|
88
|
+
passRate: Math.round((passCount / results.length) * 100),
|
|
89
|
+
avgInvestScore: Math.round(avgInvest * 100) / 100,
|
|
90
|
+
avgSmartScore: Math.round(avgSmart * 100) / 100,
|
|
91
|
+
avgTestabilityScore: Math.round(avgTestability * 100) / 100,
|
|
92
|
+
commonIssues,
|
|
93
|
+
topRecommendations
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return createSuccessResponse(batchResult, requestId, Date.now() - startTime);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return createErrorResponse(error, requestId, Date.now() - startTime);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// ==================== Single Requirement Validation ====================
|
|
103
|
+
/**
|
|
104
|
+
* Validate a single requirement
|
|
105
|
+
*/
|
|
106
|
+
async function validateSingleRequirement(requirement, strictMode) {
|
|
107
|
+
// Evaluate all criteria in parallel
|
|
108
|
+
const [investCriteria, smartAnalysis, acceptanceCriteria, languageClarity, testabilityScore] = await Promise.all([
|
|
109
|
+
evaluateInvestCriteria(requirement),
|
|
110
|
+
analyzeSmart(requirement),
|
|
111
|
+
analyzeAcceptanceCriteria(requirement),
|
|
112
|
+
assessLanguageClarity(requirement),
|
|
113
|
+
calculateTestability(requirement)
|
|
114
|
+
]);
|
|
115
|
+
// Compile key issues
|
|
116
|
+
const keyIssuesSet = new Set();
|
|
117
|
+
investCriteria.forEach((ic) => {
|
|
118
|
+
if (!ic.passed) {
|
|
119
|
+
ic.issues.forEach((issue) => keyIssuesSet.add(issue));
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
if (!smartAnalysis.specific.passed) {
|
|
123
|
+
smartAnalysis.specific.issues.forEach((issue) => keyIssuesSet.add(issue));
|
|
124
|
+
}
|
|
125
|
+
if (!acceptanceCriteria.present) {
|
|
126
|
+
keyIssuesSet.add('Missing acceptance criteria - requirement cannot be verified');
|
|
127
|
+
}
|
|
128
|
+
if (languageClarity.ambiguity > 0.5) {
|
|
129
|
+
keyIssuesSet.add('Significant ambiguity detected in requirement text');
|
|
130
|
+
}
|
|
131
|
+
// Calculate risk level
|
|
132
|
+
const investFailCount = investCriteria.filter((ic) => !ic.passed).length;
|
|
133
|
+
const smartFailCount = Object.values(smartAnalysis)
|
|
134
|
+
.filter((s) => typeof s === 'object' && 'passed' in s && !s.passed)
|
|
135
|
+
.length;
|
|
136
|
+
let riskLevel = 'low';
|
|
137
|
+
if (investFailCount >= 3 || smartFailCount >= 3 || testabilityScore < 4) {
|
|
138
|
+
riskLevel = 'critical';
|
|
139
|
+
}
|
|
140
|
+
else if (investFailCount >= 2 || smartFailCount >= 2 || testabilityScore < 5.5) {
|
|
141
|
+
riskLevel = 'high';
|
|
142
|
+
}
|
|
143
|
+
else if (investFailCount >= 1 || smartFailCount >= 1 || testabilityScore < 6.5) {
|
|
144
|
+
riskLevel = 'medium';
|
|
145
|
+
}
|
|
146
|
+
// Compile recommendations
|
|
147
|
+
const recommendationsSet = new Set();
|
|
148
|
+
investCriteria.forEach((ic) => {
|
|
149
|
+
ic.recommendations.forEach((rec) => recommendationsSet.add(rec));
|
|
150
|
+
});
|
|
151
|
+
smartAnalysis.specific.recommendations?.forEach((rec) => recommendationsSet.add(rec));
|
|
152
|
+
smartAnalysis.measurable.recommendations?.forEach((rec) => recommendationsSet.add(rec));
|
|
153
|
+
smartAnalysis.achievable.recommendations?.forEach((rec) => recommendationsSet.add(rec));
|
|
154
|
+
smartAnalysis.relevant.recommendations?.forEach((rec) => recommendationsSet.add(rec));
|
|
155
|
+
smartAnalysis.timeBound.recommendations?.forEach((rec) => recommendationsSet.add(rec));
|
|
156
|
+
if (!acceptanceCriteria.present) {
|
|
157
|
+
recommendationsSet.add('Define acceptance criteria using Given-When-Then format');
|
|
158
|
+
recommendationsSet.add('Ensure each criterion is independently verifiable');
|
|
159
|
+
}
|
|
160
|
+
if (languageClarity.clarity < 0.6) {
|
|
161
|
+
languageClarity.suggestions.forEach((s) => recommendationsSet.add(s));
|
|
162
|
+
}
|
|
163
|
+
// Calculate overall score
|
|
164
|
+
const investScore = investCriteria.reduce((sum, ic) => sum + ic.score, 0) / investCriteria.length;
|
|
165
|
+
const overallScore = Math.round((investScore + smartAnalysis.overallScore + testabilityScore) / 3 * 100) / 100;
|
|
166
|
+
const passed = investFailCount <= 1 && smartFailCount <= 1 && testabilityScore >= 6.0 && !strictMode;
|
|
167
|
+
return {
|
|
168
|
+
requirementId: requirement.id,
|
|
169
|
+
overallScore,
|
|
170
|
+
passed: passed && !strictMode ? true : !strictMode ? false : riskLevel === 'low',
|
|
171
|
+
investCriteria,
|
|
172
|
+
smartAnalysis,
|
|
173
|
+
acceptanceCriteria,
|
|
174
|
+
languageClarity,
|
|
175
|
+
testabilityScore,
|
|
176
|
+
riskLevel,
|
|
177
|
+
keyIssues: Array.from(keyIssuesSet),
|
|
178
|
+
recommendations: Array.from(recommendationsSet),
|
|
179
|
+
metadata: {
|
|
180
|
+
validatedAt: new Date().toISOString(),
|
|
181
|
+
duration: 0,
|
|
182
|
+
version: '1.0.0',
|
|
183
|
+
validationRules: ['INVEST', 'SMART', 'Acceptance-Criteria', 'Language-Clarity', 'Testability']
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// ==================== INVEST Criteria Evaluation ====================
|
|
188
|
+
/**
|
|
189
|
+
* Evaluate all INVEST criteria
|
|
190
|
+
*/
|
|
191
|
+
async function evaluateInvestCriteria(requirement) {
|
|
192
|
+
return [
|
|
193
|
+
evaluateIndependent(requirement),
|
|
194
|
+
evaluateNegotiable(requirement),
|
|
195
|
+
evaluateValuable(requirement),
|
|
196
|
+
evaluateEstimable(requirement),
|
|
197
|
+
evaluateSmall(requirement),
|
|
198
|
+
evaluateTestable(requirement)
|
|
199
|
+
];
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Evaluate Independent criterion
|
|
203
|
+
*/
|
|
204
|
+
function evaluateIndependent(requirement) {
|
|
205
|
+
const issues = [];
|
|
206
|
+
const recommendations = [];
|
|
207
|
+
let score = 2.0;
|
|
208
|
+
// Check for dependency indicators
|
|
209
|
+
const dependencyCount = requirement.dependencies?.length ?? 0;
|
|
210
|
+
if (dependencyCount > 3) {
|
|
211
|
+
score -= 0.5;
|
|
212
|
+
issues.push(`High dependency count (${dependencyCount}) - consider breaking into smaller requirements`);
|
|
213
|
+
recommendations.push('Identify and decouple interdependencies');
|
|
214
|
+
recommendations.push('Define clear separation of concerns for each requirement');
|
|
215
|
+
}
|
|
216
|
+
// Check if requirement can be developed independently
|
|
217
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
218
|
+
if (/(depends on|requires|after|before|prerequisite|only if)/i.test(text)) {
|
|
219
|
+
if (dependencyCount <= 1) {
|
|
220
|
+
score -= 0.3;
|
|
221
|
+
issues.push('Requirement text indicates dependencies not listed in dependencies field');
|
|
222
|
+
recommendations.push('Document all explicit dependencies');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
criterion: 'independent',
|
|
227
|
+
description: 'Requirement can be developed independently without blocking other work',
|
|
228
|
+
score: Math.max(0, score),
|
|
229
|
+
passed: score >= 1.5,
|
|
230
|
+
issues,
|
|
231
|
+
recommendations
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Evaluate Negotiable criterion
|
|
236
|
+
*/
|
|
237
|
+
function evaluateNegotiable(requirement) {
|
|
238
|
+
const issues = [];
|
|
239
|
+
const recommendations = [];
|
|
240
|
+
let score = 2.0;
|
|
241
|
+
// Check for flexibility - should not be too prescriptive
|
|
242
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
243
|
+
const prescriptiveTerms = /(must use|must implement|must follow|only via|only through)/gi;
|
|
244
|
+
const prescriptiveMatches = text.match(prescriptiveTerms) ?? [];
|
|
245
|
+
if (prescriptiveMatches.length > 2) {
|
|
246
|
+
score -= 0.5;
|
|
247
|
+
issues.push('Requirement is over-prescriptive, limiting negotiation space');
|
|
248
|
+
recommendations.push('Focus on "what" needs to be achieved, not "how" to achieve it');
|
|
249
|
+
recommendations.push('Allow team flexibility in implementation approach');
|
|
250
|
+
}
|
|
251
|
+
// Check for measurable acceptance without dictating approach
|
|
252
|
+
if (!requirement.acceptanceCriteria || requirement.acceptanceCriteria.length === 0) {
|
|
253
|
+
score -= 0.3;
|
|
254
|
+
issues.push('Without acceptance criteria, requirement details cannot be negotiated');
|
|
255
|
+
recommendations.push('Define clear acceptance criteria to enable discussion');
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
criterion: 'negotiable',
|
|
259
|
+
description: 'Details are negotiable; what is fixed is the acceptance criteria',
|
|
260
|
+
score: Math.max(0, score),
|
|
261
|
+
passed: score >= 1.5,
|
|
262
|
+
issues,
|
|
263
|
+
recommendations
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Evaluate Valuable criterion
|
|
268
|
+
*/
|
|
269
|
+
function evaluateValuable(requirement) {
|
|
270
|
+
const issues = [];
|
|
271
|
+
const recommendations = [];
|
|
272
|
+
let score = 2.0;
|
|
273
|
+
// Check for business value articulation
|
|
274
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
275
|
+
const valueKeywords = /(benefit|value|improve|increase|reduce|enable|allow|support|help)/gi;
|
|
276
|
+
const valueMatches = text.match(valueKeywords) ?? [];
|
|
277
|
+
if (valueMatches.length === 0) {
|
|
278
|
+
score -= 0.7;
|
|
279
|
+
issues.push('Business value or user benefit not articulated');
|
|
280
|
+
recommendations.push('Explain how this requirement benefits the user or business');
|
|
281
|
+
recommendations.push('Use "As a [user], I want [feature] so that [benefit]" format');
|
|
282
|
+
}
|
|
283
|
+
// Check if value is clear to stakeholders
|
|
284
|
+
const stakeholderKeywords = /(user|customer|stakeholder|client|team|organization)/gi;
|
|
285
|
+
const stakeholderMatches = text.match(stakeholderKeywords) ?? [];
|
|
286
|
+
if (stakeholderMatches.length === 0) {
|
|
287
|
+
score -= 0.3;
|
|
288
|
+
issues.push('Stakeholders for this requirement not clearly identified');
|
|
289
|
+
recommendations.push('Explicitly identify who benefits from this requirement');
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
criterion: 'valuable',
|
|
293
|
+
description: 'Requirement has clear business or user value',
|
|
294
|
+
score: Math.max(0, score),
|
|
295
|
+
passed: score >= 1.5,
|
|
296
|
+
issues,
|
|
297
|
+
recommendations
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Evaluate Estimable criterion
|
|
302
|
+
*/
|
|
303
|
+
function evaluateEstimable(requirement) {
|
|
304
|
+
const issues = [];
|
|
305
|
+
const recommendations = [];
|
|
306
|
+
let score = 2.0;
|
|
307
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
308
|
+
// Check if requirement is specific enough to estimate
|
|
309
|
+
const vagueTerms = /(vague|unclear|ambiguous|undefined|tbd|to be determined)/gi;
|
|
310
|
+
if (vagueTerms.test(text)) {
|
|
311
|
+
score -= 0.5;
|
|
312
|
+
issues.push('Requirement contains indicators of vagueness preventing estimation');
|
|
313
|
+
recommendations.push('Clarify ambiguous terms and provide specific examples');
|
|
314
|
+
}
|
|
315
|
+
// Check for scope indicators
|
|
316
|
+
const scopeKeywords = /(scope|boundary|boundary|constraint|limit)/gi;
|
|
317
|
+
if (!scopeKeywords.test(text)) {
|
|
318
|
+
score -= 0.3;
|
|
319
|
+
issues.push('Requirement scope or boundaries not clearly defined');
|
|
320
|
+
recommendations.push('Define what is included and excluded from the requirement');
|
|
321
|
+
}
|
|
322
|
+
// Check for complexity indicators
|
|
323
|
+
const complexKeywords = /(complex|complicated|difficult|challenging)/gi;
|
|
324
|
+
if (complexKeywords.test(text) && !requirement.acceptanceCriteria) {
|
|
325
|
+
score -= 0.4;
|
|
326
|
+
issues.push('Complex requirement without acceptance criteria for estimation');
|
|
327
|
+
recommendations.push('Break down complex requirements into smaller, estimable pieces');
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
criterion: 'estimable',
|
|
331
|
+
description: 'Developer can estimate the size and effort required',
|
|
332
|
+
score: Math.max(0, score),
|
|
333
|
+
passed: score >= 1.5,
|
|
334
|
+
issues,
|
|
335
|
+
recommendations
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Evaluate Small criterion
|
|
340
|
+
*/
|
|
341
|
+
function evaluateSmall(requirement) {
|
|
342
|
+
const issues = [];
|
|
343
|
+
const recommendations = [];
|
|
344
|
+
let score = 2.0;
|
|
345
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
346
|
+
// Check description length - very long descriptions indicate scope creep
|
|
347
|
+
if (requirement.description.length > 500) {
|
|
348
|
+
score -= 0.4;
|
|
349
|
+
issues.push('Requirement description is very long, indicating possible scope creep');
|
|
350
|
+
recommendations.push('Break requirement into smaller, focused stories');
|
|
351
|
+
}
|
|
352
|
+
// Check for "and" operators - typically indicates multiple requirements
|
|
353
|
+
const andCount = (requirement.description.match(/\band\b/gi) ?? []).length;
|
|
354
|
+
if (andCount > 3) {
|
|
355
|
+
score -= 0.5;
|
|
356
|
+
issues.push(`Multiple concerns detected (${andCount} "and" operators) - possible scope combining`);
|
|
357
|
+
recommendations.push('Split into separate requirements with single concerns');
|
|
358
|
+
}
|
|
359
|
+
// Check acceptance criteria count - too many indicates requirement is too large
|
|
360
|
+
if (requirement.acceptanceCriteria && requirement.acceptanceCriteria.length > 8) {
|
|
361
|
+
score -= 0.4;
|
|
362
|
+
issues.push(`Excessive acceptance criteria (${requirement.acceptanceCriteria.length}) - requirement too large`);
|
|
363
|
+
recommendations.push('Consolidate related criteria or split into smaller requirements');
|
|
364
|
+
}
|
|
365
|
+
// Check for "all users" or universal scope
|
|
366
|
+
if (/(all users|everyone|global|entire system)/i.test(text)) {
|
|
367
|
+
score -= 0.3;
|
|
368
|
+
issues.push('Requirement targets all users/systems, potentially too large');
|
|
369
|
+
recommendations.push('Consider phased rollout or user segment targeting');
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
criterion: 'small',
|
|
373
|
+
description: 'Requirement is small enough to complete in one iteration',
|
|
374
|
+
score: Math.max(0, score),
|
|
375
|
+
passed: score >= 1.5,
|
|
376
|
+
issues,
|
|
377
|
+
recommendations
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Evaluate Testable criterion
|
|
382
|
+
*/
|
|
383
|
+
function evaluateTestable(requirement) {
|
|
384
|
+
const issues = [];
|
|
385
|
+
const recommendations = [];
|
|
386
|
+
let score = 2.0;
|
|
387
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
388
|
+
// Check if requirement has acceptance criteria (testability indicator)
|
|
389
|
+
if (!requirement.acceptanceCriteria || requirement.acceptanceCriteria.length === 0) {
|
|
390
|
+
score -= 1.0;
|
|
391
|
+
issues.push('No acceptance criteria defined - requirement cannot be verified');
|
|
392
|
+
recommendations.push('Define explicit acceptance criteria for verification');
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
// Check if acceptance criteria are measurable
|
|
396
|
+
let measurableCount = 0;
|
|
397
|
+
for (const criterion of requirement.acceptanceCriteria) {
|
|
398
|
+
if (/\d+|success|fail|error|valid|invalid|complete|incorrect/i.test(criterion)) {
|
|
399
|
+
measurableCount++;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const measurablePercentage = measurableCount / requirement.acceptanceCriteria.length;
|
|
403
|
+
if (measurablePercentage < 0.5) {
|
|
404
|
+
score -= 0.4;
|
|
405
|
+
issues.push('Acceptance criteria lack measurable success conditions');
|
|
406
|
+
recommendations.push('Add specific, measurable success/failure conditions to criteria');
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// Check for vague/subjective language
|
|
410
|
+
const vagueMatches = text.match(VAGUE_TERMS) ?? [];
|
|
411
|
+
if (vagueMatches.length > 0) {
|
|
412
|
+
score -= 0.3;
|
|
413
|
+
const uniqueVague = Array.from(new Set(vagueMatches)).join(', ');
|
|
414
|
+
issues.push(`Vague terms found: ${uniqueVague}`);
|
|
415
|
+
recommendations.push('Replace vague terms with specific, measurable criteria');
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
criterion: 'testable',
|
|
419
|
+
description: 'Requirement has clear acceptance criteria for verification',
|
|
420
|
+
score: Math.max(0, score),
|
|
421
|
+
passed: score >= 1.5,
|
|
422
|
+
issues,
|
|
423
|
+
recommendations
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
// ==================== SMART Analysis ====================
|
|
427
|
+
/**
|
|
428
|
+
* Analyze requirement using SMART framework
|
|
429
|
+
*/
|
|
430
|
+
async function analyzeSmart(requirement) {
|
|
431
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
432
|
+
// Specific
|
|
433
|
+
const specificIssues = [];
|
|
434
|
+
const specificRecs = [];
|
|
435
|
+
let specificScore = 2.0;
|
|
436
|
+
if (text.length < 50) {
|
|
437
|
+
specificScore -= 0.5;
|
|
438
|
+
specificIssues.push('Description too brief for clear understanding');
|
|
439
|
+
specificRecs.push('Expand with concrete details and examples');
|
|
440
|
+
}
|
|
441
|
+
const vagueMatches = text.match(VAGUE_TERMS);
|
|
442
|
+
if (vagueMatches) {
|
|
443
|
+
specificScore -= 0.3;
|
|
444
|
+
const uniqueVague = Array.from(new Set(vagueMatches)).join(', ');
|
|
445
|
+
specificIssues.push(`Vague terms: ${uniqueVague}`);
|
|
446
|
+
specificRecs.push('Use precise, specific language');
|
|
447
|
+
}
|
|
448
|
+
specificScore = Math.max(0, specificScore);
|
|
449
|
+
// Measurable
|
|
450
|
+
const measurableIssues = [];
|
|
451
|
+
const measurableRecs = [];
|
|
452
|
+
const metrics = [];
|
|
453
|
+
let measurableScore = 2.0;
|
|
454
|
+
const numberMatches = text.match(/\d+/g) ?? [];
|
|
455
|
+
const metricMatches = text.match(/(ms|seconds?|minutes?|hours?|%|percent|users?|requests?|MB|GB|KB|throughput|latency|response time)/gi) ?? [];
|
|
456
|
+
if (numberMatches.length > 0) {
|
|
457
|
+
metrics.push(...numberMatches);
|
|
458
|
+
}
|
|
459
|
+
if (metricMatches.length > 0) {
|
|
460
|
+
metrics.push(...Array.from(new Set(metricMatches)));
|
|
461
|
+
}
|
|
462
|
+
if (metrics.length === 0 && (!requirement.acceptanceCriteria || requirement.acceptanceCriteria.length === 0)) {
|
|
463
|
+
measurableScore -= 0.8;
|
|
464
|
+
measurableIssues.push('No quantifiable metrics or acceptance criteria');
|
|
465
|
+
measurableRecs.push('Add specific, measurable metrics (response time, success rate, etc.)');
|
|
466
|
+
}
|
|
467
|
+
measurableScore = Math.max(0, measurableScore);
|
|
468
|
+
// Achievable
|
|
469
|
+
const achievableIssues = [];
|
|
470
|
+
const achievableRecs = [];
|
|
471
|
+
let achievableScore = 2.0;
|
|
472
|
+
let technicalFeasibility = 'Not evaluated';
|
|
473
|
+
let resourceEstimate = 'Not specified';
|
|
474
|
+
const complexIndicators = text.match(/(complex|difficult|challenging|requires significant|unprecedented)/gi);
|
|
475
|
+
if (complexIndicators && !requirement.acceptanceCriteria) {
|
|
476
|
+
achievableScore -= 0.3;
|
|
477
|
+
achievableIssues.push('Complex requirement without clear technical approach');
|
|
478
|
+
achievableRecs.push('Define technical approach or conduct POC');
|
|
479
|
+
technicalFeasibility = 'Unclear - requires feasibility study';
|
|
480
|
+
}
|
|
481
|
+
else if (complexIndicators) {
|
|
482
|
+
technicalFeasibility = 'Complex but with clear acceptance criteria';
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
technicalFeasibility = 'Appears technically achievable';
|
|
486
|
+
}
|
|
487
|
+
achievableScore = Math.max(0, achievableScore);
|
|
488
|
+
// Relevant
|
|
489
|
+
const relevantIssues = [];
|
|
490
|
+
const relevantRecs = [];
|
|
491
|
+
let relevantScore = 2.0;
|
|
492
|
+
let businessValue = 'Not articulated';
|
|
493
|
+
let stakeholderAlignment = 'Not specified';
|
|
494
|
+
const valueMatches = text.match(/(benefit|value|improve|increase|reduce|enable|allow)/gi);
|
|
495
|
+
if (valueMatches) {
|
|
496
|
+
const uniqueValue = Array.from(new Set(valueMatches)).join(', ');
|
|
497
|
+
businessValue = `Clear value: ${uniqueValue}`;
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
relevantScore -= 0.7;
|
|
501
|
+
relevantIssues.push('Business value not articulated');
|
|
502
|
+
relevantRecs.push('Explain business benefit and user value');
|
|
503
|
+
businessValue = 'Not clear';
|
|
504
|
+
}
|
|
505
|
+
if (requirement.type) {
|
|
506
|
+
stakeholderAlignment = `Typed as ${requirement.type}`;
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
relevantScore -= 0.2;
|
|
510
|
+
relevantIssues.push('Requirement type not specified');
|
|
511
|
+
stakeholderAlignment = 'Unknown';
|
|
512
|
+
}
|
|
513
|
+
relevantScore = Math.max(0, relevantScore);
|
|
514
|
+
// Time-bound
|
|
515
|
+
const timeBoundIssues = [];
|
|
516
|
+
const timeBoundRecs = [];
|
|
517
|
+
let timeBoundScore = 2.0;
|
|
518
|
+
let performanceTarget = 'Not specified';
|
|
519
|
+
let deadline = 'Not specified';
|
|
520
|
+
const timeMatches = text.match(/(sprint|release|v\d+|deadline|within|by|phase|iteration)/gi);
|
|
521
|
+
const perfMatches = text.match(/(response time|latency|timeout|duration|performance|throughput)/gi);
|
|
522
|
+
if (perfMatches) {
|
|
523
|
+
const uniquePerf = Array.from(new Set(perfMatches)).join(', ');
|
|
524
|
+
performanceTarget = `Performance expectations present: ${uniquePerf}`;
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
timeBoundScore -= 0.3;
|
|
528
|
+
timeBoundIssues.push('No performance or timing expectations');
|
|
529
|
+
timeBoundRecs.push('Define response time, timeout, or throughput requirements');
|
|
530
|
+
}
|
|
531
|
+
if (timeMatches) {
|
|
532
|
+
const uniqueTime = Array.from(new Set(timeMatches)).join(', ');
|
|
533
|
+
deadline = `Timeline indicators: ${uniqueTime}`;
|
|
534
|
+
}
|
|
535
|
+
timeBoundScore = Math.max(0, timeBoundScore);
|
|
536
|
+
const overallScore = Math.round(((specificScore + measurableScore + achievableScore + relevantScore + timeBoundScore) / 5) * 10) / 10;
|
|
537
|
+
return {
|
|
538
|
+
specific: {
|
|
539
|
+
score: Math.round(specificScore * 10) / 10,
|
|
540
|
+
passed: specificScore >= 1.5,
|
|
541
|
+
issues: specificIssues,
|
|
542
|
+
details: specificScore >= 1.5 ? 'Requirement is clearly defined' : 'Requirement needs clarification'
|
|
543
|
+
},
|
|
544
|
+
measurable: {
|
|
545
|
+
score: Math.round(measurableScore * 10) / 10,
|
|
546
|
+
passed: measurableScore >= 1.5,
|
|
547
|
+
issues: measurableIssues,
|
|
548
|
+
metrics,
|
|
549
|
+
details: metrics.length > 0 ? `${metrics.length} metrics identified` : 'No measurable metrics found'
|
|
550
|
+
},
|
|
551
|
+
achievable: {
|
|
552
|
+
score: Math.round(achievableScore * 10) / 10,
|
|
553
|
+
passed: achievableScore >= 1.5,
|
|
554
|
+
issues: achievableIssues,
|
|
555
|
+
technicalFeasibility,
|
|
556
|
+
resourceEstimate
|
|
557
|
+
},
|
|
558
|
+
relevant: {
|
|
559
|
+
score: Math.round(relevantScore * 10) / 10,
|
|
560
|
+
passed: relevantScore >= 1.5,
|
|
561
|
+
issues: relevantIssues,
|
|
562
|
+
businessValue,
|
|
563
|
+
stakeholderAlignment
|
|
564
|
+
},
|
|
565
|
+
timeBound: {
|
|
566
|
+
score: Math.round(timeBoundScore * 10) / 10,
|
|
567
|
+
passed: timeBoundScore >= 1.5,
|
|
568
|
+
issues: timeBoundIssues,
|
|
569
|
+
performanceTarget,
|
|
570
|
+
deadline
|
|
571
|
+
},
|
|
572
|
+
overallScore
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
// ==================== Acceptance Criteria Analysis ====================
|
|
576
|
+
/**
|
|
577
|
+
* Analyze acceptance criteria
|
|
578
|
+
*/
|
|
579
|
+
async function analyzeAcceptanceCriteria(requirement) {
|
|
580
|
+
if (!requirement.acceptanceCriteria || requirement.acceptanceCriteria.length === 0) {
|
|
581
|
+
return {
|
|
582
|
+
present: false,
|
|
583
|
+
count: 0,
|
|
584
|
+
validCount: 0,
|
|
585
|
+
issues: ['No acceptance criteria defined'],
|
|
586
|
+
enhancedCriteria: [],
|
|
587
|
+
score: 0
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const issues = [];
|
|
591
|
+
let validCount = 0;
|
|
592
|
+
const enhancedCriteria = [];
|
|
593
|
+
for (const criterion of requirement.acceptanceCriteria) {
|
|
594
|
+
const isValid = criterion.length > 10 && /(\d+|success|fail|complete|error)/i.test(criterion);
|
|
595
|
+
if (isValid) {
|
|
596
|
+
validCount++;
|
|
597
|
+
enhancedCriteria.push(criterion);
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
if (criterion.length <= 10) {
|
|
601
|
+
issues.push(`Criterion too brief: "${criterion}"`);
|
|
602
|
+
enhancedCriteria.push(`${criterion} (enhance with specific condition)`);
|
|
603
|
+
}
|
|
604
|
+
if (!/(\d+|success|fail|complete|error)/i.test(criterion)) {
|
|
605
|
+
issues.push(`Criterion lacks measurable condition: "${criterion}"`);
|
|
606
|
+
enhancedCriteria.push(`${criterion} (add specific success condition)`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
const score = Math.round((validCount / requirement.acceptanceCriteria.length) * 10);
|
|
611
|
+
return {
|
|
612
|
+
present: true,
|
|
613
|
+
count: requirement.acceptanceCriteria.length,
|
|
614
|
+
validCount,
|
|
615
|
+
issues,
|
|
616
|
+
enhancedCriteria,
|
|
617
|
+
score
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
// ==================== Language Clarity Assessment ====================
|
|
621
|
+
/**
|
|
622
|
+
* Assess language clarity and ambiguity
|
|
623
|
+
*/
|
|
624
|
+
async function assessLanguageClarity(requirement) {
|
|
625
|
+
const text = `${requirement.title} ${requirement.description}`;
|
|
626
|
+
const vagueMatches = text.match(VAGUE_TERMS) ?? [];
|
|
627
|
+
const ambiguousMatches = text.match(AMBIGUOUS_MODALS) ?? [];
|
|
628
|
+
const subjectiveMatches = text.match(SUBJECTIVE_TERMS) ?? [];
|
|
629
|
+
const passiveMatches = text.match(PASSIVE_VOICE) ?? [];
|
|
630
|
+
const totalClarity = text.length > 0
|
|
631
|
+
? 1 - ((vagueMatches.length + ambiguousMatches.length + subjectiveMatches.length + passiveMatches.length) / (text.length / 10))
|
|
632
|
+
: 0;
|
|
633
|
+
const clarity = Math.max(0, Math.min(1, totalClarity));
|
|
634
|
+
const vagueness = (vagueMatches.length / Math.max(1, text.length / 20));
|
|
635
|
+
const ambiguity = (ambiguousMatches.length / Math.max(1, text.length / 20));
|
|
636
|
+
const suggestions = [];
|
|
637
|
+
if (vagueMatches.length > 0) {
|
|
638
|
+
const uniqueVague = Array.from(new Set(vagueMatches)).join(', ');
|
|
639
|
+
suggestions.push(`Replace vague terms (${uniqueVague}) with specific metrics`);
|
|
640
|
+
}
|
|
641
|
+
if (ambiguousMatches.length > 0) {
|
|
642
|
+
const uniqueAmbiguous = Array.from(new Set(ambiguousMatches)).join(', ');
|
|
643
|
+
suggestions.push(`Use definitive language instead of ${uniqueAmbiguous}`);
|
|
644
|
+
}
|
|
645
|
+
if (subjectiveMatches.length > 0) {
|
|
646
|
+
const uniqueSubjective = Array.from(new Set(subjectiveMatches)).join(', ');
|
|
647
|
+
suggestions.push(`Replace subjective terms (${uniqueSubjective}) with objective criteria`);
|
|
648
|
+
}
|
|
649
|
+
if (passiveMatches.length > 0) {
|
|
650
|
+
suggestions.push('Use active voice instead of passive voice for clarity');
|
|
651
|
+
}
|
|
652
|
+
return {
|
|
653
|
+
vagueness: Math.round(Math.min(1, vagueness) * 100) / 100,
|
|
654
|
+
ambiguity: Math.round(Math.min(1, ambiguity) * 100) / 100,
|
|
655
|
+
clarity: Math.round(clarity * 100) / 100,
|
|
656
|
+
vagueTerms: Array.from(new Set(vagueMatches)),
|
|
657
|
+
ambiguousTerms: Array.from(new Set(ambiguousMatches)),
|
|
658
|
+
suggestions
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
// ==================== Testability Score ====================
|
|
662
|
+
/**
|
|
663
|
+
* Calculate overall testability score (0-10)
|
|
664
|
+
*/
|
|
665
|
+
async function calculateTestability(requirement) {
|
|
666
|
+
let score = 5.0;
|
|
667
|
+
// Acceptance criteria boost
|
|
668
|
+
if (requirement.acceptanceCriteria && requirement.acceptanceCriteria.length >= 3) {
|
|
669
|
+
score += 2.0;
|
|
670
|
+
}
|
|
671
|
+
else if (requirement.acceptanceCriteria && requirement.acceptanceCriteria.length > 0) {
|
|
672
|
+
score += 1.0;
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
score -= 2.0;
|
|
676
|
+
}
|
|
677
|
+
// Description quality
|
|
678
|
+
if (requirement.description.length > 100) {
|
|
679
|
+
score += 0.5;
|
|
680
|
+
}
|
|
681
|
+
// Clarity
|
|
682
|
+
const text = `${requirement.title} ${requirement.description}`.toLowerCase();
|
|
683
|
+
const vagueCount = (text.match(VAGUE_TERMS) ?? []).length;
|
|
684
|
+
const ambigCount = (text.match(AMBIGUOUS_MODALS) ?? []).length;
|
|
685
|
+
if (vagueCount > 2) {
|
|
686
|
+
score -= 1.0;
|
|
687
|
+
}
|
|
688
|
+
if (ambigCount > 2) {
|
|
689
|
+
score -= 1.0;
|
|
690
|
+
}
|
|
691
|
+
// Type specification
|
|
692
|
+
if (requirement.type) {
|
|
693
|
+
score += 0.5;
|
|
694
|
+
}
|
|
695
|
+
return Math.round(Math.max(0, Math.min(10, score)) * 100) / 100;
|
|
696
|
+
}
|
|
697
|
+
// ==================== Utility Functions ====================
|
|
698
|
+
/**
|
|
699
|
+
* Generate unique request ID
|
|
700
|
+
*/
|
|
701
|
+
function generateRequestId() {
|
|
702
|
+
return `req-val-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Create success response
|
|
706
|
+
*/
|
|
707
|
+
function createSuccessResponse(data, requestId, executionTime) {
|
|
708
|
+
return {
|
|
709
|
+
success: true,
|
|
710
|
+
data,
|
|
711
|
+
metadata: {
|
|
712
|
+
requestId,
|
|
713
|
+
timestamp: new Date().toISOString(),
|
|
714
|
+
executionTime,
|
|
715
|
+
agent: 'requirements-validator',
|
|
716
|
+
version: '1.0.0'
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Create error response
|
|
722
|
+
*/
|
|
723
|
+
function createErrorResponse(error, requestId, executionTime) {
|
|
724
|
+
return {
|
|
725
|
+
success: false,
|
|
726
|
+
error: {
|
|
727
|
+
code: 'VALIDATION_ERROR',
|
|
728
|
+
message: error.message,
|
|
729
|
+
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
|
730
|
+
},
|
|
731
|
+
metadata: {
|
|
732
|
+
requestId,
|
|
733
|
+
timestamp: new Date().toISOString(),
|
|
734
|
+
executionTime,
|
|
735
|
+
agent: 'requirements-validator',
|
|
736
|
+
version: '1.0.0'
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
//# sourceMappingURL=validate-requirements.js.map
|