agentic-qe 3.7.15 → 3.7.17
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/v3/qe-devils-advocate.md +20 -0
- package/.claude/agents/v3/qe-gap-detector.md +25 -0
- package/.claude/agents/v3/qe-quality-gate.md +8 -0
- package/.claude/agents/v3/qe-requirements-validator.md +25 -0
- package/.claude/agents/v3/subagents/qe-code-reviewer.md +11 -0
- package/.claude/agents/v3/subagents/qe-integration-reviewer.md +11 -0
- package/.claude/agents/v3/subagents/qe-performance-reviewer.md +11 -0
- package/.claude/agents/v3/subagents/qe-security-reviewer.md +11 -0
- package/.claude/helpers/adr-compliance.sh +10 -10
- package/.claude/helpers/auto-memory-hook.mjs +24 -9
- package/.claude/helpers/brain-checkpoint.cjs +55 -134
- package/.claude/helpers/ddd-tracker.sh +2 -2
- package/.claude/helpers/guidance-hooks.sh +2 -2
- package/.claude/helpers/hook-handler.cjs +57 -18
- package/.claude/helpers/statusline.cjs +414 -595
- package/.claude/helpers/v3/quality-criteria/evidence-classification.md +116 -116
- package/.claude/helpers/v3/quality-criteria/htsm-categories.md +139 -139
- package/.claude/skills/README.md +8 -11
- package/.claude/skills/brutal-honesty-review/SKILL.md +3 -0
- package/.claude/skills/code-review-quality/SKILL.md +3 -0
- package/.claude/skills/qcsd-cicd-swarm/SKILL.md +79 -2075
- package/.claude/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +62 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/02-core-agents.md +33 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/03-batch1-results.md +21 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/04-conditional-agents.md +23 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/05-decision-synthesis.md +30 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/06-report-generation.md +17 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +27 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/08-deployment-advisor.md +25 -0
- package/.claude/skills/qcsd-cicd-swarm/steps/09-final-output.md +16 -0
- package/.claude/skills/qcsd-development-swarm/SKILL.md +79 -2027
- package/.claude/skills/qcsd-development-swarm/steps/01-flag-detection.md +50 -0
- package/.claude/skills/qcsd-development-swarm/steps/02-core-agents.md +29 -0
- package/.claude/skills/qcsd-development-swarm/steps/03-batch1-results.md +14 -0
- package/.claude/skills/qcsd-development-swarm/steps/04-conditional-agents.md +23 -0
- package/.claude/skills/qcsd-development-swarm/steps/05-decision-synthesis.md +30 -0
- package/.claude/skills/qcsd-development-swarm/steps/06-report-generation.md +16 -0
- package/.claude/skills/qcsd-development-swarm/steps/07-learning-persistence.md +25 -0
- package/.claude/skills/qcsd-development-swarm/steps/08-defect-predictor.md +25 -0
- package/.claude/skills/qcsd-development-swarm/steps/09-final-output.md +16 -0
- package/.claude/skills/qcsd-ideation-swarm/SKILL.md +94 -1894
- package/.claude/skills/qcsd-ideation-swarm/steps/01-flag-detection.md +57 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/02-core-agents.md +29 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/03-batch1-results.md +15 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/04-conditional-agents.md +23 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/05-decision-synthesis.md +29 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/06-report-generation.md +18 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +29 -0
- package/.claude/skills/qcsd-ideation-swarm/steps/08-final-output.md +18 -0
- package/.claude/skills/qcsd-production-swarm/SKILL.md +88 -2663
- package/.claude/skills/qcsd-production-swarm/steps/01-flag-detection.md +206 -0
- package/.claude/skills/qcsd-production-swarm/steps/02-core-agents.md +428 -0
- package/.claude/skills/qcsd-production-swarm/steps/03-batch1-results.md +101 -0
- package/.claude/skills/qcsd-production-swarm/steps/04-conditional-agents.md +125 -0
- package/.claude/skills/qcsd-production-swarm/steps/05-decision-synthesis.md +136 -0
- package/.claude/skills/qcsd-production-swarm/steps/06-report-generation.md +181 -0
- package/.claude/skills/qcsd-production-swarm/steps/07-learning-persistence.md +185 -0
- package/.claude/skills/qcsd-production-swarm/steps/08-feedback-loop.md +122 -0
- package/.claude/skills/qcsd-production-swarm/steps/09-final-output.md +140 -0
- package/.claude/skills/qcsd-refinement-swarm/SKILL.md +59 -2312
- package/.claude/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +91 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/02-core-agents.md +40 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/03-batch1-results.md +40 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/04-conditional-agents.md +35 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/05-decision-synthesis.md +43 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/06-report-generation.md +42 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +53 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/08-transformation.md +36 -0
- package/.claude/skills/qcsd-refinement-swarm/steps/09-final-output.md +46 -0
- package/.claude/skills/sherlock-review/SKILL.md +3 -0
- package/.claude/skills/skill-builder/SKILL.md +103 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +44 -0
- package/assets/agents/v3/qe-devils-advocate.md +20 -0
- package/assets/agents/v3/qe-gap-detector.md +25 -0
- package/assets/agents/v3/qe-quality-gate.md +8 -0
- package/assets/agents/v3/qe-requirements-validator.md +25 -0
- package/assets/agents/v3/subagents/qe-code-reviewer.md +11 -0
- package/assets/agents/v3/subagents/qe-integration-reviewer.md +11 -0
- package/assets/agents/v3/subagents/qe-performance-reviewer.md +11 -0
- package/assets/agents/v3/subagents/qe-security-reviewer.md +11 -0
- package/assets/helpers/statusline-v3.cjs +693 -0
- package/assets/skills/brutal-honesty-review/SKILL.md +3 -0
- package/assets/skills/code-review-quality/SKILL.md +3 -0
- package/assets/skills/qcsd-cicd-swarm/SKILL.md +79 -2075
- package/assets/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +62 -0
- package/assets/skills/qcsd-cicd-swarm/steps/02-core-agents.md +33 -0
- package/assets/skills/qcsd-cicd-swarm/steps/03-batch1-results.md +21 -0
- package/assets/skills/qcsd-cicd-swarm/steps/04-conditional-agents.md +23 -0
- package/assets/skills/qcsd-cicd-swarm/steps/05-decision-synthesis.md +30 -0
- package/assets/skills/qcsd-cicd-swarm/steps/06-report-generation.md +17 -0
- package/assets/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +27 -0
- package/assets/skills/qcsd-cicd-swarm/steps/08-deployment-advisor.md +25 -0
- package/assets/skills/qcsd-cicd-swarm/steps/09-final-output.md +16 -0
- package/assets/skills/qcsd-development-swarm/SKILL.md +79 -2027
- package/assets/skills/qcsd-development-swarm/steps/01-flag-detection.md +50 -0
- package/assets/skills/qcsd-development-swarm/steps/02-core-agents.md +29 -0
- package/assets/skills/qcsd-development-swarm/steps/03-batch1-results.md +14 -0
- package/assets/skills/qcsd-development-swarm/steps/04-conditional-agents.md +23 -0
- package/assets/skills/qcsd-development-swarm/steps/05-decision-synthesis.md +30 -0
- package/assets/skills/qcsd-development-swarm/steps/06-report-generation.md +16 -0
- package/assets/skills/qcsd-development-swarm/steps/07-learning-persistence.md +25 -0
- package/assets/skills/qcsd-development-swarm/steps/08-defect-predictor.md +25 -0
- package/assets/skills/qcsd-development-swarm/steps/09-final-output.md +16 -0
- package/assets/skills/qcsd-ideation-swarm/SKILL.md +94 -1894
- package/assets/skills/qcsd-ideation-swarm/steps/01-flag-detection.md +57 -0
- package/assets/skills/qcsd-ideation-swarm/steps/02-core-agents.md +29 -0
- package/assets/skills/qcsd-ideation-swarm/steps/03-batch1-results.md +15 -0
- package/assets/skills/qcsd-ideation-swarm/steps/04-conditional-agents.md +23 -0
- package/assets/skills/qcsd-ideation-swarm/steps/05-decision-synthesis.md +29 -0
- package/assets/skills/qcsd-ideation-swarm/steps/06-report-generation.md +18 -0
- package/assets/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +29 -0
- package/assets/skills/qcsd-ideation-swarm/steps/08-final-output.md +18 -0
- package/assets/skills/qcsd-production-swarm/SKILL.md +88 -2663
- package/assets/skills/qcsd-production-swarm/steps/01-flag-detection.md +206 -0
- package/assets/skills/qcsd-production-swarm/steps/02-core-agents.md +428 -0
- package/assets/skills/qcsd-production-swarm/steps/03-batch1-results.md +101 -0
- package/assets/skills/qcsd-production-swarm/steps/04-conditional-agents.md +125 -0
- package/assets/skills/qcsd-production-swarm/steps/05-decision-synthesis.md +136 -0
- package/assets/skills/qcsd-production-swarm/steps/06-report-generation.md +181 -0
- package/assets/skills/qcsd-production-swarm/steps/07-learning-persistence.md +185 -0
- package/assets/skills/qcsd-production-swarm/steps/08-feedback-loop.md +122 -0
- package/assets/skills/qcsd-production-swarm/steps/09-final-output.md +140 -0
- package/assets/skills/qcsd-refinement-swarm/SKILL.md +59 -2312
- package/assets/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +91 -0
- package/assets/skills/qcsd-refinement-swarm/steps/02-core-agents.md +40 -0
- package/assets/skills/qcsd-refinement-swarm/steps/03-batch1-results.md +40 -0
- package/assets/skills/qcsd-refinement-swarm/steps/04-conditional-agents.md +35 -0
- package/assets/skills/qcsd-refinement-swarm/steps/05-decision-synthesis.md +43 -0
- package/assets/skills/qcsd-refinement-swarm/steps/06-report-generation.md +42 -0
- package/assets/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +53 -0
- package/assets/skills/qcsd-refinement-swarm/steps/08-transformation.md +36 -0
- package/assets/skills/qcsd-refinement-swarm/steps/09-final-output.md +46 -0
- package/assets/skills/sherlock-review/SKILL.md +3 -0
- package/assets/templates/agent-override-example.yaml +39 -0
- package/dist/agents/devils-advocate/agent.d.ts +25 -1
- package/dist/agents/devils-advocate/agent.js +108 -4
- package/dist/agents/devils-advocate/types.d.ts +54 -0
- package/dist/agents/devils-advocate/types.js +14 -0
- package/dist/agents/overlay-loader.d.ts +28 -0
- package/dist/agents/overlay-loader.js +232 -0
- package/dist/agents/overlay-schema.d.ts +56 -0
- package/dist/agents/overlay-schema.js +77 -0
- package/dist/analysis/branch-enumerator.d.ts +68 -0
- package/dist/analysis/branch-enumerator.js +393 -0
- package/dist/analysis/index.d.ts +2 -0
- package/dist/analysis/index.js +2 -0
- package/dist/cli/bundle.js +2469 -634
- package/dist/cli/commands/coverage.js +50 -0
- package/dist/cli/handlers/brain-handler.js +2 -1
- package/dist/context/compiler.d.ts +62 -0
- package/dist/context/compiler.js +143 -0
- package/dist/context/index.d.ts +8 -0
- package/dist/context/index.js +6 -0
- package/dist/context/sources/coverage-source.d.ts +15 -0
- package/dist/context/sources/coverage-source.js +77 -0
- package/dist/context/sources/git-source.d.ts +12 -0
- package/dist/context/sources/git-source.js +33 -0
- package/dist/context/sources/index.d.ts +6 -0
- package/dist/context/sources/index.js +5 -0
- package/dist/context/sources/memory-source.d.ts +17 -0
- package/dist/context/sources/memory-source.js +94 -0
- package/dist/context/sources/test-source.d.ts +13 -0
- package/dist/context/sources/test-source.js +53 -0
- package/dist/context/sources/types.d.ts +42 -0
- package/dist/context/sources/types.js +5 -0
- package/dist/domains/test-generation/coordinator.js +6 -4
- package/dist/feedback/feedback-loop.d.ts +5 -0
- package/dist/feedback/feedback-loop.js +12 -0
- package/dist/feedback/index.d.ts +1 -1
- package/dist/feedback/index.js +1 -1
- package/dist/init/agents-installer.d.ts +9 -0
- package/dist/init/agents-installer.js +72 -0
- package/dist/init/phases/07-hooks.d.ts +11 -0
- package/dist/init/phases/07-hooks.js +67 -0
- package/dist/init/phases/09-assets.js +3 -0
- package/dist/init/settings-merge.js +1 -1
- package/dist/kernel/hnsw-adapter.d.ts +3 -0
- package/dist/kernel/hnsw-adapter.js +11 -1
- package/dist/kernel/unified-memory-schemas.d.ts +1 -1
- package/dist/kernel/unified-memory-schemas.js +2 -0
- package/dist/kernel/unified-memory.js +25 -0
- package/dist/learning/experience-capture-middleware.js +24 -0
- package/dist/learning/sqlite-persistence.d.ts +3 -0
- package/dist/learning/sqlite-persistence.js +9 -0
- package/dist/learning/token-tracker.js +4 -0
- package/dist/mcp/bundle.js +3694 -3101
- package/dist/mcp/handlers/handler-factory.js +92 -11
- package/dist/mcp/services/task-router.d.ts +11 -0
- package/dist/mcp/services/task-router.js +26 -0
- package/dist/routing/qe-agent-registry.d.ts +11 -0
- package/dist/routing/qe-agent-registry.js +34 -0
- package/dist/routing/qe-task-router.d.ts +1 -0
- package/dist/routing/qe-task-router.js +34 -2
- package/dist/routing/routing-feedback.d.ts +5 -0
- package/dist/routing/routing-feedback.js +29 -3
- package/dist/routing/types.d.ts +2 -0
- package/dist/sync/pull-agent.js +2 -1
- package/dist/test-scheduling/pipeline.d.ts +7 -0
- package/dist/test-scheduling/pipeline.js +9 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.js +10 -0
- package/dist/validation/pipeline.d.ts +80 -0
- package/dist/validation/pipeline.js +173 -0
- package/dist/validation/steps/requirements.d.ts +32 -0
- package/dist/validation/steps/requirements.js +596 -0
- package/package.json +6 -6
- package/.claude/agents/consensus/README.md +0 -253
- package/.claude/agents/deprecated/qe-api-contract-validator.md.v2 +0 -162
- package/.claude/agents/deprecated/qe-coverage-analyzer.md.v2 +0 -208
- package/.claude/agents/deprecated/qe-test-generator.md.v2 +0 -212
- package/.claude/agents/deprecated/qe-visual-tester.md.v2 +0 -216
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -130
- package/.claude/agents/hive-mind/queen-coordinator.md +0 -203
- package/.claude/agents/hive-mind/scout-explorer.md +0 -242
- package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -193
- package/.claude/agents/hive-mind/worker-specialist.md +0 -217
- package/.claude/agents/neural/safla-neural.md +0 -74
- package/.claude/agents/optimization/README.md +0 -250
- package/.claude/agents/reasoning/agent.md +0 -816
- package/.claude/agents/reasoning/goal-planner.md +0 -73
- package/.claude/agents/subagents/qe-code-reviewer.md +0 -76
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +0 -76
- package/.claude/agents/subagents/qe-data-generator.md +0 -77
- package/.claude/agents/subagents/qe-flaky-investigator.md +0 -91
- package/.claude/agents/subagents/qe-integration-tester.md +0 -90
- package/.claude/agents/subagents/qe-performance-validator.md +0 -92
- package/.claude/agents/subagents/qe-security-auditor.md +0 -94
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +0 -93
- package/.claude/agents/subagents/qe-test-implementer.md +0 -106
- package/.claude/agents/subagents/qe-test-refactorer.md +0 -117
- package/.claude/agents/subagents/qe-test-writer.md +0 -112
- package/.claude/agents/swarm/README.md +0 -190
- package/.claude/agents/templates/migration-plan.md +0 -746
- package/.claude/agents/testing/unit/tdd-london-swarm.md +0 -244
- package/.claude/agents/testing/validation/production-validator.md +0 -395
- package/.claude/agents/v3/README.md +0 -39
- package/.claude/agents/v3/typescript-specialist.yaml +0 -21
- package/.claude/agents/v3/v3-memory-specialist.md +0 -318
- package/.claude/agents/v3/v3-performance-engineer.md +0 -397
- package/.claude/agents/v3/v3-queen-coordinator.md +0 -98
- package/.claude/agents/v3/v3-security-architect.md +0 -174
- package/.claude/commands/README.md +0 -106
- package/.claude/commands/agents/README.md +0 -10
- package/.claude/commands/agents/agent-capabilities.md +0 -21
- package/.claude/commands/agents/agent-coordination.md +0 -28
- package/.claude/commands/agents/agent-spawning.md +0 -28
- package/.claude/commands/agents/agent-types.md +0 -26
- package/.claude/commands/coordination/README.md +0 -9
- package/.claude/commands/coordination/agent-spawn.md +0 -25
- package/.claude/commands/coordination/init.md +0 -44
- package/.claude/commands/coordination/orchestrate.md +0 -43
- package/.claude/commands/coordination/spawn.md +0 -45
- package/.claude/commands/coordination/swarm-init.md +0 -85
- package/.claude/commands/coordination/task-orchestrate.md +0 -25
- package/.claude/commands/hive-mind/README.md +0 -17
- package/.claude/commands/hive-mind/hive-mind-consensus.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-init.md +0 -18
- package/.claude/commands/hive-mind/hive-mind-memory.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-spawn.md +0 -21
- package/.claude/commands/hive-mind/hive-mind-status.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-stop.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
- package/.claude/commands/hive-mind/hive-mind.md +0 -27
- package/.claude/commands/memory/README.md +0 -9
- package/.claude/commands/memory/memory-persist.md +0 -25
- package/.claude/commands/memory/memory-search.md +0 -25
- package/.claude/commands/memory/memory-usage.md +0 -25
- package/.claude/commands/memory/neural.md +0 -47
- package/.claude/commands/swarm/README.md +0 -15
- package/.claude/commands/swarm/swarm-analysis.md +0 -8
- package/.claude/commands/swarm/swarm-background.md +0 -8
- package/.claude/commands/swarm/swarm-init.md +0 -19
- package/.claude/commands/swarm/swarm-modes.md +0 -8
- package/.claude/commands/swarm/swarm-monitor.md +0 -8
- package/.claude/commands/swarm/swarm-spawn.md +0 -19
- package/.claude/commands/swarm/swarm-status.md +0 -8
- package/.claude/commands/swarm/swarm-strategies.md +0 -8
- package/.claude/commands/swarm/swarm.md +0 -27
- package/.claude/commands/training/README.md +0 -9
- package/.claude/commands/training/model-update.md +0 -25
- package/.claude/commands/training/neural-patterns.md +0 -74
- package/.claude/commands/training/neural-train.md +0 -25
- package/.claude/commands/training/pattern-learn.md +0 -25
- package/.claude/commands/training/specialization.md +0 -63
- package/.claude/commands/workflows/README.md +0 -9
- package/.claude/commands/workflows/development.md +0 -78
- package/.claude/commands/workflows/research.md +0 -63
- package/.claude/commands/workflows/workflow-create.md +0 -25
- package/.claude/commands/workflows/workflow-execute.md +0 -25
- package/.claude/commands/workflows/workflow-export.md +0 -25
- package/.claude/skills/agentic-jujutsu/SKILL.md +0 -645
- package/.claude/skills/hive-mind-advanced/SKILL.md +0 -712
- package/.claude/skills/iterative-loop/SKILL.md +0 -371
- package/.claude/skills/performance-analysis/SKILL.md +0 -569
- package/.claude/skills/performance-analysis/evals/performance-analysis.yaml +0 -144
- package/.claude/skills/performance-analysis/schemas/output.json +0 -588
- package/.claude/skills/performance-analysis/scripts/validate-config.json +0 -36
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements Validation Steps (BMAD-003)
|
|
3
|
+
*
|
|
4
|
+
* 13 structured validation steps for requirements documents,
|
|
5
|
+
* inspired by BMAD-METHOD's PRD validation.
|
|
6
|
+
*/
|
|
7
|
+
function createFinding(stepId, severity, title, description, opts) {
|
|
8
|
+
return {
|
|
9
|
+
id: `${stepId}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
10
|
+
stepId,
|
|
11
|
+
severity,
|
|
12
|
+
title,
|
|
13
|
+
description,
|
|
14
|
+
location: opts?.location,
|
|
15
|
+
suggestion: opts?.suggestion,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
// Step 1: Format Check
|
|
19
|
+
export const formatCheckStep = {
|
|
20
|
+
id: 'format-check',
|
|
21
|
+
name: 'Format & Structure Check',
|
|
22
|
+
category: 'format',
|
|
23
|
+
severity: 'blocking',
|
|
24
|
+
async execute(ctx) {
|
|
25
|
+
const findings = [];
|
|
26
|
+
const evidence = [];
|
|
27
|
+
const content = ctx.content;
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
// Check for headings
|
|
30
|
+
const headings = content.match(/^#{1,3}\s+.+$/gm) || [];
|
|
31
|
+
evidence.push(`Found ${headings.length} headings`);
|
|
32
|
+
if (headings.length === 0) {
|
|
33
|
+
findings.push(createFinding('format-check', 'critical', 'No headings found', 'Document lacks structure - no markdown headings detected'));
|
|
34
|
+
}
|
|
35
|
+
// Check for required sections
|
|
36
|
+
const requiredSections = ['overview', 'requirement', 'acceptance', 'scope'];
|
|
37
|
+
const contentLower = content.toLowerCase();
|
|
38
|
+
for (const section of requiredSections) {
|
|
39
|
+
if (!contentLower.includes(section)) {
|
|
40
|
+
findings.push(createFinding('format-check', 'high', `Missing "${section}" section`, `Expected a section containing "${section}" keyword`));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
evidence.push(`Checked for required sections: ${requiredSections.join(', ')}`);
|
|
44
|
+
// Check document length
|
|
45
|
+
const wordCount = content.split(/\s+/).length;
|
|
46
|
+
evidence.push(`Document word count: ${wordCount}`);
|
|
47
|
+
if (wordCount < 50) {
|
|
48
|
+
findings.push(createFinding('format-check', 'high', 'Document too short', `Only ${wordCount} words - requirements need more detail`, { suggestion: 'Expand requirements with acceptance criteria and context' }));
|
|
49
|
+
}
|
|
50
|
+
const score = Math.max(0, 100 - findings.length * 20);
|
|
51
|
+
return {
|
|
52
|
+
stepId: 'format-check',
|
|
53
|
+
stepName: 'Format & Structure Check',
|
|
54
|
+
status: findings.some(f => f.severity === 'critical') ? 'fail' : findings.length > 0 ? 'warn' : 'pass',
|
|
55
|
+
score,
|
|
56
|
+
findings,
|
|
57
|
+
evidence,
|
|
58
|
+
duration: Date.now() - start,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
// Step 2: Completeness Check
|
|
63
|
+
export const completenessCheckStep = {
|
|
64
|
+
id: 'completeness-check',
|
|
65
|
+
name: 'Completeness Check',
|
|
66
|
+
category: 'content',
|
|
67
|
+
severity: 'blocking',
|
|
68
|
+
async execute(ctx) {
|
|
69
|
+
const findings = [];
|
|
70
|
+
const evidence = [];
|
|
71
|
+
const start = Date.now();
|
|
72
|
+
const content = ctx.content.toLowerCase();
|
|
73
|
+
const requiredFields = [
|
|
74
|
+
{ field: 'description', keywords: ['description', 'overview', 'summary'] },
|
|
75
|
+
{ field: 'acceptance criteria', keywords: ['acceptance', 'criteria', 'given', 'when', 'then'] },
|
|
76
|
+
{ field: 'scope', keywords: ['scope', 'in scope', 'out of scope'] },
|
|
77
|
+
{ field: 'priority', keywords: ['priority', 'p0', 'p1', 'p2', 'critical', 'must have'] },
|
|
78
|
+
];
|
|
79
|
+
for (const { field, keywords } of requiredFields) {
|
|
80
|
+
const found = keywords.some(k => content.includes(k));
|
|
81
|
+
evidence.push(`${field}: ${found ? 'present' : 'missing'}`);
|
|
82
|
+
if (!found) {
|
|
83
|
+
findings.push(createFinding('completeness-check', 'high', `Missing: ${field}`, `No ${field} content found (checked: ${keywords.join(', ')})`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const score = Math.max(0, 100 - findings.length * 25);
|
|
87
|
+
return {
|
|
88
|
+
stepId: 'completeness-check',
|
|
89
|
+
stepName: 'Completeness Check',
|
|
90
|
+
status: findings.length > 2 ? 'fail' : findings.length > 0 ? 'warn' : 'pass',
|
|
91
|
+
score,
|
|
92
|
+
findings,
|
|
93
|
+
evidence,
|
|
94
|
+
duration: Date.now() - start,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
// Step 3: INVEST Criteria
|
|
99
|
+
export const investCriteriaStep = {
|
|
100
|
+
id: 'invest-criteria',
|
|
101
|
+
name: 'INVEST Criteria Analysis',
|
|
102
|
+
category: 'quality',
|
|
103
|
+
severity: 'warning',
|
|
104
|
+
async execute(ctx) {
|
|
105
|
+
const findings = [];
|
|
106
|
+
const evidence = [];
|
|
107
|
+
const start = Date.now();
|
|
108
|
+
const content = ctx.content;
|
|
109
|
+
// Independent - check for cross-references / dependencies
|
|
110
|
+
const depKeywords = ['depends on', 'requires', 'blocked by', 'prerequisite', 'after'];
|
|
111
|
+
const hasDeps = depKeywords.some(k => content.toLowerCase().includes(k));
|
|
112
|
+
evidence.push(`Independence: ${hasDeps ? 'has dependencies' : 'appears independent'}`);
|
|
113
|
+
if (hasDeps) {
|
|
114
|
+
findings.push(createFinding('invest-criteria', 'medium', 'Dependency detected', 'Requirement references dependencies - may not be independently deliverable', { suggestion: 'Consider splitting or documenting the dependency explicitly' }));
|
|
115
|
+
}
|
|
116
|
+
// Estimable - check for vague scope indicators
|
|
117
|
+
const vagueScope = ['many', 'several', 'various', 'lots of', 'comprehensive'];
|
|
118
|
+
const hasVagueScope = vagueScope.some(k => content.toLowerCase().includes(k));
|
|
119
|
+
evidence.push(`Estimability: ${hasVagueScope ? 'vague scope terms found' : 'scope appears estimable'}`);
|
|
120
|
+
if (hasVagueScope) {
|
|
121
|
+
findings.push(createFinding('invest-criteria', 'medium', 'Vague scope terms', 'Contains terms that make estimation difficult', { suggestion: 'Replace vague terms with specific quantities or bounds' }));
|
|
122
|
+
}
|
|
123
|
+
// Small - check size
|
|
124
|
+
const wordCount = content.split(/\s+/).length;
|
|
125
|
+
evidence.push(`Size: ${wordCount} words`);
|
|
126
|
+
if (wordCount > 2000) {
|
|
127
|
+
findings.push(createFinding('invest-criteria', 'medium', 'Requirement may be too large', `${wordCount} words - consider splitting into smaller requirements`, { suggestion: 'Split into focused, independent requirements of <1000 words each' }));
|
|
128
|
+
}
|
|
129
|
+
// Testable - check for acceptance criteria
|
|
130
|
+
const hasAcceptance = content.toLowerCase().includes('acceptance') || content.toLowerCase().includes('given') || content.toLowerCase().includes('then');
|
|
131
|
+
evidence.push(`Testability: ${hasAcceptance ? 'acceptance criteria found' : 'no acceptance criteria'}`);
|
|
132
|
+
if (!hasAcceptance) {
|
|
133
|
+
findings.push(createFinding('invest-criteria', 'high', 'No testable acceptance criteria', 'Requirement lacks Given/When/Then or acceptance criteria', { suggestion: 'Add specific, measurable acceptance criteria' }));
|
|
134
|
+
}
|
|
135
|
+
const score = Math.max(0, 100 - findings.length * 20);
|
|
136
|
+
return {
|
|
137
|
+
stepId: 'invest-criteria',
|
|
138
|
+
stepName: 'INVEST Criteria Analysis',
|
|
139
|
+
status: findings.length > 2 ? 'fail' : findings.length > 0 ? 'warn' : 'pass',
|
|
140
|
+
score,
|
|
141
|
+
findings,
|
|
142
|
+
evidence,
|
|
143
|
+
duration: Date.now() - start,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
// Step 4: SMART Acceptance
|
|
148
|
+
export const smartAcceptanceStep = {
|
|
149
|
+
id: 'smart-acceptance',
|
|
150
|
+
name: 'SMART Acceptance Criteria',
|
|
151
|
+
category: 'quality',
|
|
152
|
+
severity: 'warning',
|
|
153
|
+
async execute(ctx) {
|
|
154
|
+
const findings = [];
|
|
155
|
+
const evidence = [];
|
|
156
|
+
const start = Date.now();
|
|
157
|
+
const content = ctx.content.toLowerCase();
|
|
158
|
+
// Specific
|
|
159
|
+
const specificPatterns = /\b(specific|exact|precisely|must be|shall)\b/;
|
|
160
|
+
const isSpecific = specificPatterns.test(content);
|
|
161
|
+
evidence.push(`Specific: ${isSpecific ? 'yes' : 'no'}`);
|
|
162
|
+
if (!isSpecific) {
|
|
163
|
+
findings.push(createFinding('smart-acceptance', 'medium', 'Acceptance not specific', 'Criteria lack specificity (no "must be", "shall", "specific" language)'));
|
|
164
|
+
}
|
|
165
|
+
// Measurable
|
|
166
|
+
const measurablePatterns = /\b(\d+%|\d+ms|\d+\s*seconds?|\d+\s*users?|at least|no more than|maximum|minimum)\b/;
|
|
167
|
+
const isMeasurable = measurablePatterns.test(content);
|
|
168
|
+
evidence.push(`Measurable: ${isMeasurable ? 'yes' : 'no'}`);
|
|
169
|
+
if (!isMeasurable) {
|
|
170
|
+
findings.push(createFinding('smart-acceptance', 'medium', 'Acceptance not measurable', 'No numeric targets or measurable criteria found', { suggestion: 'Add specific metrics (response time, error rate, user count)' }));
|
|
171
|
+
}
|
|
172
|
+
// Time-bound
|
|
173
|
+
const timeBound = /\b(deadline|by|before|sprint|iteration|release|milestone|date)\b/;
|
|
174
|
+
const isTimeBound = timeBound.test(content);
|
|
175
|
+
evidence.push(`Time-bound: ${isTimeBound ? 'yes' : 'no'}`);
|
|
176
|
+
if (!isTimeBound) {
|
|
177
|
+
findings.push(createFinding('smart-acceptance', 'low', 'No time constraint', 'Requirement has no deadline or timeline reference'));
|
|
178
|
+
}
|
|
179
|
+
const score = Math.max(0, 100 - findings.length * 25);
|
|
180
|
+
return {
|
|
181
|
+
stepId: 'smart-acceptance',
|
|
182
|
+
stepName: 'SMART Acceptance Criteria',
|
|
183
|
+
status: findings.length > 2 ? 'fail' : findings.length > 0 ? 'warn' : 'pass',
|
|
184
|
+
score,
|
|
185
|
+
findings,
|
|
186
|
+
evidence,
|
|
187
|
+
duration: Date.now() - start,
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
// Step 5: Testability Score
|
|
192
|
+
export const testabilityScoreStep = {
|
|
193
|
+
id: 'testability-score',
|
|
194
|
+
name: 'Testability Score',
|
|
195
|
+
category: 'quality',
|
|
196
|
+
severity: 'warning',
|
|
197
|
+
async execute(ctx) {
|
|
198
|
+
const findings = [];
|
|
199
|
+
const evidence = [];
|
|
200
|
+
const start = Date.now();
|
|
201
|
+
const content = ctx.content.toLowerCase();
|
|
202
|
+
let testabilityPoints = 0;
|
|
203
|
+
const maxPoints = 5;
|
|
204
|
+
// Check for test-related content
|
|
205
|
+
if (content.includes('test') || content.includes('verify') || content.includes('validate')) {
|
|
206
|
+
testabilityPoints++;
|
|
207
|
+
evidence.push('Has test-related keywords');
|
|
208
|
+
}
|
|
209
|
+
if (/given\s.+when\s.+then/s.test(content)) {
|
|
210
|
+
testabilityPoints += 2;
|
|
211
|
+
evidence.push('Has Given/When/Then scenarios');
|
|
212
|
+
}
|
|
213
|
+
if (/\b(input|output|expected|actual)\b/.test(content)) {
|
|
214
|
+
testabilityPoints++;
|
|
215
|
+
evidence.push('Has input/output specifications');
|
|
216
|
+
}
|
|
217
|
+
if (/\b(error|exception|failure|edge case|boundary)\b/.test(content)) {
|
|
218
|
+
testabilityPoints++;
|
|
219
|
+
evidence.push('Mentions error/edge cases');
|
|
220
|
+
}
|
|
221
|
+
const score = Math.round((testabilityPoints / maxPoints) * 100);
|
|
222
|
+
evidence.push(`Testability score: ${testabilityPoints}/${maxPoints}`);
|
|
223
|
+
if (score < 40) {
|
|
224
|
+
findings.push(createFinding('testability-score', 'high', 'Low testability', `Score: ${score}/100 - requirement is hard to test`, { suggestion: 'Add concrete scenarios, expected inputs/outputs, and error cases' }));
|
|
225
|
+
}
|
|
226
|
+
else if (score < 70) {
|
|
227
|
+
findings.push(createFinding('testability-score', 'medium', 'Moderate testability', `Score: ${score}/100 - could be more testable`));
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
stepId: 'testability-score',
|
|
231
|
+
stepName: 'Testability Score',
|
|
232
|
+
status: score >= 70 ? 'pass' : score >= 40 ? 'warn' : 'fail',
|
|
233
|
+
score,
|
|
234
|
+
findings,
|
|
235
|
+
evidence,
|
|
236
|
+
duration: Date.now() - start,
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
// Step 6: Vague Term Detection
|
|
241
|
+
export const vagueTermStep = {
|
|
242
|
+
id: 'vague-term-detection',
|
|
243
|
+
name: 'Vague Term Detection',
|
|
244
|
+
category: 'quality',
|
|
245
|
+
severity: 'info',
|
|
246
|
+
async execute(ctx) {
|
|
247
|
+
const findings = [];
|
|
248
|
+
const evidence = [];
|
|
249
|
+
const start = Date.now();
|
|
250
|
+
const vagueTerms = [
|
|
251
|
+
'should', 'might', 'could', 'may', 'possibly', 'probably',
|
|
252
|
+
'various', 'several', 'many', 'some', 'few', 'etc.',
|
|
253
|
+
'appropriate', 'adequate', 'sufficient', 'reasonable',
|
|
254
|
+
'fast', 'slow', 'easy', 'simple', 'complex', 'good', 'better',
|
|
255
|
+
'as needed', 'if applicable', 'when necessary',
|
|
256
|
+
];
|
|
257
|
+
const lines = ctx.content.split('\n');
|
|
258
|
+
let vagueCount = 0;
|
|
259
|
+
for (let i = 0; i < lines.length; i++) {
|
|
260
|
+
const lineLower = lines[i].toLowerCase();
|
|
261
|
+
for (const term of vagueTerms) {
|
|
262
|
+
if (lineLower.includes(term)) {
|
|
263
|
+
vagueCount++;
|
|
264
|
+
if (vagueCount <= 10) { // Cap at 10 findings
|
|
265
|
+
findings.push(createFinding('vague-term-detection', 'low', `Vague term: "${term}"`, `Found on line ${i + 1}`, { location: `line ${i + 1}`, suggestion: `Replace "${term}" with a specific, measurable term` }));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
evidence.push(`Scanned ${lines.length} lines for ${vagueTerms.length} vague terms`);
|
|
271
|
+
evidence.push(`Found ${vagueCount} vague term occurrences`);
|
|
272
|
+
const score = Math.max(0, 100 - vagueCount * 5);
|
|
273
|
+
return {
|
|
274
|
+
stepId: 'vague-term-detection',
|
|
275
|
+
stepName: 'Vague Term Detection',
|
|
276
|
+
status: vagueCount > 10 ? 'warn' : 'pass',
|
|
277
|
+
score,
|
|
278
|
+
findings,
|
|
279
|
+
evidence,
|
|
280
|
+
duration: Date.now() - start,
|
|
281
|
+
};
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
// Step 7: Information Density
|
|
285
|
+
export const informationDensityStep = {
|
|
286
|
+
id: 'information-density',
|
|
287
|
+
name: 'Information Density',
|
|
288
|
+
category: 'content',
|
|
289
|
+
severity: 'info',
|
|
290
|
+
async execute(ctx) {
|
|
291
|
+
const findings = [];
|
|
292
|
+
const evidence = [];
|
|
293
|
+
const start = Date.now();
|
|
294
|
+
const content = ctx.content;
|
|
295
|
+
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);
|
|
296
|
+
const words = content.split(/\s+/).filter(w => w.length > 0);
|
|
297
|
+
const avgWordsPerSentence = sentences.length > 0 ? words.length / sentences.length : 0;
|
|
298
|
+
evidence.push(`Sentences: ${sentences.length}, Words: ${words.length}`);
|
|
299
|
+
evidence.push(`Avg words/sentence: ${avgWordsPerSentence.toFixed(1)}`);
|
|
300
|
+
if (avgWordsPerSentence > 30) {
|
|
301
|
+
findings.push(createFinding('information-density', 'medium', 'Sentences too long', `Average ${avgWordsPerSentence.toFixed(0)} words/sentence - hard to parse`, { suggestion: 'Split long sentences into shorter, focused statements' }));
|
|
302
|
+
}
|
|
303
|
+
// Check for filler phrases
|
|
304
|
+
const fillerPhrases = ['it is important to note that', 'in order to', 'at the end of the day', 'as a matter of fact', 'the fact that', 'it should be noted'];
|
|
305
|
+
for (const filler of fillerPhrases) {
|
|
306
|
+
if (content.toLowerCase().includes(filler)) {
|
|
307
|
+
findings.push(createFinding('information-density', 'low', `Filler phrase: "${filler}"`, 'Remove filler to increase information density', { suggestion: `Remove "${filler}" or replace with concise alternative` }));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const score = Math.max(0, 100 - findings.length * 10);
|
|
311
|
+
return {
|
|
312
|
+
stepId: 'information-density',
|
|
313
|
+
stepName: 'Information Density',
|
|
314
|
+
status: findings.length > 3 ? 'warn' : 'pass',
|
|
315
|
+
score,
|
|
316
|
+
findings,
|
|
317
|
+
evidence,
|
|
318
|
+
duration: Date.now() - start,
|
|
319
|
+
};
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
// Step 8: Traceability Check
|
|
323
|
+
export const traceabilityCheckStep = {
|
|
324
|
+
id: 'traceability-check',
|
|
325
|
+
name: 'Traceability Check',
|
|
326
|
+
category: 'traceability',
|
|
327
|
+
severity: 'warning',
|
|
328
|
+
async execute(ctx) {
|
|
329
|
+
const findings = [];
|
|
330
|
+
const evidence = [];
|
|
331
|
+
const start = Date.now();
|
|
332
|
+
const content = ctx.content.toLowerCase();
|
|
333
|
+
// Check for requirement IDs
|
|
334
|
+
const reqIds = ctx.content.match(/\b(REQ|US|FEAT|STORY|AC)-?\d+/gi) || [];
|
|
335
|
+
evidence.push(`Requirement IDs found: ${reqIds.length}`);
|
|
336
|
+
if (reqIds.length === 0) {
|
|
337
|
+
findings.push(createFinding('traceability-check', 'medium', 'No requirement IDs', 'Document lacks traceable requirement identifiers (REQ-*, US-*, FEAT-*)'));
|
|
338
|
+
}
|
|
339
|
+
// Check for test references
|
|
340
|
+
const hasTestRefs = content.includes('test case') || content.includes('test-') || content.includes('tc-') || /\btest\s+#?\d+/.test(content);
|
|
341
|
+
evidence.push(`Test references: ${hasTestRefs ? 'found' : 'none'}`);
|
|
342
|
+
if (!hasTestRefs) {
|
|
343
|
+
findings.push(createFinding('traceability-check', 'medium', 'No test references', 'Requirements are not linked to test cases'));
|
|
344
|
+
}
|
|
345
|
+
const score = Math.max(0, 100 - findings.length * 30);
|
|
346
|
+
return {
|
|
347
|
+
stepId: 'traceability-check',
|
|
348
|
+
stepName: 'Traceability Check',
|
|
349
|
+
status: findings.length > 0 ? 'warn' : 'pass',
|
|
350
|
+
score,
|
|
351
|
+
findings,
|
|
352
|
+
evidence,
|
|
353
|
+
duration: Date.now() - start,
|
|
354
|
+
};
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
// Step 9: Implementation Leakage
|
|
358
|
+
export const implementationLeakageStep = {
|
|
359
|
+
id: 'implementation-leakage',
|
|
360
|
+
name: 'Implementation Leakage Detection',
|
|
361
|
+
category: 'quality',
|
|
362
|
+
severity: 'warning',
|
|
363
|
+
async execute(ctx) {
|
|
364
|
+
const findings = [];
|
|
365
|
+
const evidence = [];
|
|
366
|
+
const start = Date.now();
|
|
367
|
+
const content = ctx.content.toLowerCase();
|
|
368
|
+
const implTerms = [
|
|
369
|
+
{ term: 'sql', desc: 'SQL query language' },
|
|
370
|
+
{ term: 'rest api', desc: 'specific API style' },
|
|
371
|
+
{ term: 'react', desc: 'specific framework' },
|
|
372
|
+
{ term: 'postgres', desc: 'specific database' },
|
|
373
|
+
{ term: 'mongodb', desc: 'specific database' },
|
|
374
|
+
{ term: 'docker', desc: 'specific container tech' },
|
|
375
|
+
{ term: 'kubernetes', desc: 'specific orchestration' },
|
|
376
|
+
{ term: 'lambda', desc: 'specific serverless' },
|
|
377
|
+
{ term: 'microservice', desc: 'specific architecture' },
|
|
378
|
+
{ term: 'redis', desc: 'specific cache' },
|
|
379
|
+
];
|
|
380
|
+
let leakCount = 0;
|
|
381
|
+
for (const { term, desc } of implTerms) {
|
|
382
|
+
if (content.includes(term)) {
|
|
383
|
+
leakCount++;
|
|
384
|
+
findings.push(createFinding('implementation-leakage', 'medium', `Implementation leakage: "${term}"`, `Requirement prescribes ${desc} — requirements should describe WHAT, not HOW`, { suggestion: `Describe the capability needed without specifying ${desc}` }));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
evidence.push(`Checked ${implTerms.length} implementation terms, found ${leakCount}`);
|
|
388
|
+
const score = Math.max(0, 100 - leakCount * 15);
|
|
389
|
+
return {
|
|
390
|
+
stepId: 'implementation-leakage',
|
|
391
|
+
stepName: 'Implementation Leakage Detection',
|
|
392
|
+
status: leakCount > 3 ? 'fail' : leakCount > 0 ? 'warn' : 'pass',
|
|
393
|
+
score,
|
|
394
|
+
findings,
|
|
395
|
+
evidence,
|
|
396
|
+
duration: Date.now() - start,
|
|
397
|
+
};
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
// Step 10: Domain Compliance
|
|
401
|
+
export const domainComplianceStep = {
|
|
402
|
+
id: 'domain-compliance',
|
|
403
|
+
name: 'Domain Compliance',
|
|
404
|
+
category: 'compliance',
|
|
405
|
+
severity: 'info',
|
|
406
|
+
async execute(ctx) {
|
|
407
|
+
const findings = [];
|
|
408
|
+
const evidence = [];
|
|
409
|
+
const start = Date.now();
|
|
410
|
+
// Check for domain-specific terminology consistency
|
|
411
|
+
const content = ctx.content;
|
|
412
|
+
// Detect domain from content
|
|
413
|
+
const domains = [
|
|
414
|
+
{ name: 'testing', keywords: ['test', 'coverage', 'assertion', 'fixture', 'mock'] },
|
|
415
|
+
{ name: 'security', keywords: ['auth', 'encrypt', 'permission', 'vulnerability', 'owasp'] },
|
|
416
|
+
{ name: 'api', keywords: ['endpoint', 'request', 'response', 'payload', 'header'] },
|
|
417
|
+
{ name: 'ui', keywords: ['component', 'render', 'layout', 'click', 'display'] },
|
|
418
|
+
];
|
|
419
|
+
const detectedDomains = domains.filter(d => d.keywords.some(k => content.toLowerCase().includes(k)));
|
|
420
|
+
evidence.push(`Detected domains: ${detectedDomains.map(d => d.name).join(', ') || 'none'}`);
|
|
421
|
+
if (detectedDomains.length === 0) {
|
|
422
|
+
findings.push(createFinding('domain-compliance', 'low', 'No clear domain', 'Requirements lack domain-specific terminology'));
|
|
423
|
+
}
|
|
424
|
+
else if (detectedDomains.length > 2) {
|
|
425
|
+
findings.push(createFinding('domain-compliance', 'medium', 'Multi-domain requirement', `Spans ${detectedDomains.length} domains — consider splitting`, { suggestion: 'Split into domain-specific requirements for clarity' }));
|
|
426
|
+
}
|
|
427
|
+
const score = findings.length === 0 ? 100 : 70;
|
|
428
|
+
return {
|
|
429
|
+
stepId: 'domain-compliance',
|
|
430
|
+
stepName: 'Domain Compliance',
|
|
431
|
+
status: findings.length > 0 ? 'warn' : 'pass',
|
|
432
|
+
score,
|
|
433
|
+
findings,
|
|
434
|
+
evidence,
|
|
435
|
+
duration: Date.now() - start,
|
|
436
|
+
};
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
// Step 11: Dependency Analysis
|
|
440
|
+
export const dependencyAnalysisStep = {
|
|
441
|
+
id: 'dependency-analysis',
|
|
442
|
+
name: 'Dependency Analysis',
|
|
443
|
+
category: 'traceability',
|
|
444
|
+
severity: 'info',
|
|
445
|
+
async execute(ctx) {
|
|
446
|
+
const findings = [];
|
|
447
|
+
const evidence = [];
|
|
448
|
+
const start = Date.now();
|
|
449
|
+
const content = ctx.content.toLowerCase();
|
|
450
|
+
const depIndicators = [
|
|
451
|
+
{ pattern: /depends\s+on/g, type: 'explicit dependency' },
|
|
452
|
+
{ pattern: /requires?\s/g, type: 'requirement reference' },
|
|
453
|
+
{ pattern: /blocked\s+by/g, type: 'blocker' },
|
|
454
|
+
{ pattern: /after\s+(?:completing|implementing)/g, type: 'sequencing' },
|
|
455
|
+
{ pattern: /prerequisite/g, type: 'prerequisite' },
|
|
456
|
+
];
|
|
457
|
+
let totalDeps = 0;
|
|
458
|
+
for (const { pattern, type } of depIndicators) {
|
|
459
|
+
const matches = content.match(pattern) || [];
|
|
460
|
+
if (matches.length > 0) {
|
|
461
|
+
totalDeps += matches.length;
|
|
462
|
+
evidence.push(`${type}: ${matches.length} occurrences`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (totalDeps === 0) {
|
|
466
|
+
evidence.push('No explicit dependencies detected');
|
|
467
|
+
}
|
|
468
|
+
else if (totalDeps > 5) {
|
|
469
|
+
findings.push(createFinding('dependency-analysis', 'medium', 'High dependency count', `${totalDeps} dependency references — high coupling risk`, { suggestion: 'Consider reducing dependencies or documenting a dependency graph' }));
|
|
470
|
+
}
|
|
471
|
+
const score = totalDeps > 5 ? 60 : totalDeps > 2 ? 80 : 100;
|
|
472
|
+
return {
|
|
473
|
+
stepId: 'dependency-analysis',
|
|
474
|
+
stepName: 'Dependency Analysis',
|
|
475
|
+
status: totalDeps > 5 ? 'warn' : 'pass',
|
|
476
|
+
score,
|
|
477
|
+
findings,
|
|
478
|
+
evidence,
|
|
479
|
+
duration: Date.now() - start,
|
|
480
|
+
};
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
// Step 12: BDD Scenario Generation
|
|
484
|
+
export const bddScenarioStep = {
|
|
485
|
+
id: 'bdd-scenario-generation',
|
|
486
|
+
name: 'BDD Scenario Potential',
|
|
487
|
+
category: 'quality',
|
|
488
|
+
severity: 'warning',
|
|
489
|
+
async execute(ctx) {
|
|
490
|
+
const findings = [];
|
|
491
|
+
const evidence = [];
|
|
492
|
+
const start = Date.now();
|
|
493
|
+
const content = ctx.content;
|
|
494
|
+
const contentLower = content.toLowerCase();
|
|
495
|
+
// Check for existing BDD scenarios
|
|
496
|
+
const hasBDD = /given\s.+when\s.+then/si.test(content);
|
|
497
|
+
evidence.push(`Existing BDD scenarios: ${hasBDD ? 'yes' : 'no'}`);
|
|
498
|
+
// Check if requirements can generate BDD
|
|
499
|
+
const actionVerbs = content.match(/\b(create|update|delete|display|calculate|validate|send|receive|login|logout|submit|upload|download|search|filter|sort)\b/gi) || [];
|
|
500
|
+
const uniqueActions = [...new Set(actionVerbs.map(v => v.toLowerCase()))];
|
|
501
|
+
evidence.push(`Action verbs found: ${uniqueActions.join(', ')}`);
|
|
502
|
+
// Use contentLower to suppress the unused variable lint error
|
|
503
|
+
const hasFeatureKeyword = contentLower.includes('feature');
|
|
504
|
+
evidence.push(`Feature keyword: ${hasFeatureKeyword ? 'yes' : 'no'}`);
|
|
505
|
+
if (uniqueActions.length === 0) {
|
|
506
|
+
findings.push(createFinding('bdd-scenario-generation', 'high', 'No actionable verbs', 'Requirements lack action verbs — cannot generate BDD scenarios', { suggestion: 'Add clear user actions (create, update, delete, etc.)' }));
|
|
507
|
+
}
|
|
508
|
+
else if (!hasBDD) {
|
|
509
|
+
findings.push(createFinding('bdd-scenario-generation', 'medium', 'BDD scenarios possible but missing', `Found ${uniqueActions.length} action verbs but no Given/When/Then`, { suggestion: 'Add BDD scenarios for each identified action' }));
|
|
510
|
+
}
|
|
511
|
+
const score = hasBDD ? 100 : uniqueActions.length > 0 ? 60 : 20;
|
|
512
|
+
return {
|
|
513
|
+
stepId: 'bdd-scenario-generation',
|
|
514
|
+
stepName: 'BDD Scenario Potential',
|
|
515
|
+
status: hasBDD ? 'pass' : uniqueActions.length > 0 ? 'warn' : 'fail',
|
|
516
|
+
score,
|
|
517
|
+
findings,
|
|
518
|
+
evidence,
|
|
519
|
+
duration: Date.now() - start,
|
|
520
|
+
};
|
|
521
|
+
},
|
|
522
|
+
};
|
|
523
|
+
// Step 13: Holistic Quality
|
|
524
|
+
export const holisticQualityStep = {
|
|
525
|
+
id: 'holistic-quality',
|
|
526
|
+
name: 'Holistic Quality Assessment',
|
|
527
|
+
category: 'content',
|
|
528
|
+
severity: 'blocking',
|
|
529
|
+
async execute(ctx) {
|
|
530
|
+
const findings = [];
|
|
531
|
+
const evidence = [];
|
|
532
|
+
const start = Date.now();
|
|
533
|
+
// Synthesize from previous step results
|
|
534
|
+
const prevResults = ctx.previousResults;
|
|
535
|
+
const failedSteps = prevResults.filter(r => r.status === 'fail');
|
|
536
|
+
const warnSteps = prevResults.filter(r => r.status === 'warn');
|
|
537
|
+
const avgScore = prevResults.length > 0
|
|
538
|
+
? prevResults.reduce((sum, r) => sum + r.score, 0) / prevResults.length
|
|
539
|
+
: 0;
|
|
540
|
+
evidence.push(`Previous steps: ${prevResults.length} completed`);
|
|
541
|
+
evidence.push(`Failed: ${failedSteps.length}, Warnings: ${warnSteps.length}`);
|
|
542
|
+
evidence.push(`Average score: ${avgScore.toFixed(1)}`);
|
|
543
|
+
if (failedSteps.length > 3) {
|
|
544
|
+
findings.push(createFinding('holistic-quality', 'critical', 'Multiple validation failures', `${failedSteps.length} steps failed — requirement needs significant rework`));
|
|
545
|
+
}
|
|
546
|
+
if (avgScore < 40) {
|
|
547
|
+
findings.push(createFinding('holistic-quality', 'critical', 'Overall quality below threshold', `Average score ${avgScore.toFixed(0)}/100 — below minimum 40`));
|
|
548
|
+
}
|
|
549
|
+
// Check for contradictions (simple heuristic: both "must" and "must not" for same term)
|
|
550
|
+
const content = ctx.content.toLowerCase();
|
|
551
|
+
const mustStatements = content.match(/must\s+\w+/g) || [];
|
|
552
|
+
const mustNotStatements = content.match(/must\s+not\s+\w+/g) || [];
|
|
553
|
+
evidence.push(`"Must" statements: ${mustStatements.length}, "Must not": ${mustNotStatements.length}`);
|
|
554
|
+
const score = Math.max(0, Math.round(avgScore - failedSteps.length * 5));
|
|
555
|
+
return {
|
|
556
|
+
stepId: 'holistic-quality',
|
|
557
|
+
stepName: 'Holistic Quality Assessment',
|
|
558
|
+
status: findings.some(f => f.severity === 'critical') ? 'fail' : findings.length > 0 ? 'warn' : 'pass',
|
|
559
|
+
score,
|
|
560
|
+
findings,
|
|
561
|
+
evidence,
|
|
562
|
+
duration: Date.now() - start,
|
|
563
|
+
};
|
|
564
|
+
},
|
|
565
|
+
};
|
|
566
|
+
/**
|
|
567
|
+
* All 13 requirements validation steps in order.
|
|
568
|
+
*/
|
|
569
|
+
export const REQUIREMENTS_VALIDATION_STEPS = [
|
|
570
|
+
formatCheckStep,
|
|
571
|
+
completenessCheckStep,
|
|
572
|
+
investCriteriaStep,
|
|
573
|
+
smartAcceptanceStep,
|
|
574
|
+
testabilityScoreStep,
|
|
575
|
+
vagueTermStep,
|
|
576
|
+
informationDensityStep,
|
|
577
|
+
traceabilityCheckStep,
|
|
578
|
+
implementationLeakageStep,
|
|
579
|
+
domainComplianceStep,
|
|
580
|
+
dependencyAnalysisStep,
|
|
581
|
+
bddScenarioStep,
|
|
582
|
+
holisticQualityStep,
|
|
583
|
+
];
|
|
584
|
+
/**
|
|
585
|
+
* Create a requirements validation pipeline config.
|
|
586
|
+
*/
|
|
587
|
+
export function createRequirementsPipeline(options) {
|
|
588
|
+
return {
|
|
589
|
+
id: 'requirements-validation',
|
|
590
|
+
name: 'Requirements Validation Pipeline',
|
|
591
|
+
steps: REQUIREMENTS_VALIDATION_STEPS,
|
|
592
|
+
continueOnFailure: options?.continueOnFailure,
|
|
593
|
+
stepFilter: options?.stepFilter,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
//# sourceMappingURL=requirements.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-qe",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.17",
|
|
4
4
|
"description": "Agentic Quality Engineering V3 - Domain-Driven Design Architecture with 13 Bounded Contexts, O(log n) coverage analysis, ReasoningBank learning, 60 specialized QE agents, mathematical Coherence verification, deep Claude Flow integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -128,6 +128,7 @@
|
|
|
128
128
|
"license": "MIT",
|
|
129
129
|
"dependencies": {
|
|
130
130
|
"@claude-flow/guidance": "^3.0.0-alpha.1",
|
|
131
|
+
"@faker-js/faker": "^10.2.0",
|
|
131
132
|
"@ruvector/attention": "0.1.3",
|
|
132
133
|
"@ruvector/gnn": "0.1.19",
|
|
133
134
|
"@ruvector/rvf-node": "^0.1.7",
|
|
@@ -148,23 +149,22 @@
|
|
|
148
149
|
"secure-json-parse": "^4.1.0",
|
|
149
150
|
"uuid": "^9.0.0",
|
|
150
151
|
"vibium": "^0.1.2",
|
|
151
|
-
"yaml": "^2.8.2"
|
|
152
|
-
"@faker-js/faker": "^10.2.0"
|
|
152
|
+
"yaml": "^2.8.2"
|
|
153
153
|
},
|
|
154
154
|
"optionalDependencies": {
|
|
155
155
|
"@claude-flow/browser": "^3.0.0-alpha.1",
|
|
156
156
|
"@ruvector/attention-darwin-arm64": "0.1.3",
|
|
157
157
|
"@ruvector/attention-darwin-x64": "0.1.3",
|
|
158
158
|
"@ruvector/attention-linux-arm64-gnu": "0.1.3",
|
|
159
|
+
"@ruvector/attention-linux-arm64-musl": "npm:@ruvector/attention-linux-arm64-gnu@0.1.3",
|
|
159
160
|
"@ruvector/attention-linux-x64-gnu": "0.1.3",
|
|
160
161
|
"@ruvector/attention-linux-x64-musl": "npm:@ruvector/attention-linux-x64-gnu@0.1.3",
|
|
161
|
-
"@ruvector/attention-linux-arm64-musl": "npm:@ruvector/attention-linux-arm64-gnu@0.1.3",
|
|
162
162
|
"@ruvector/gnn-darwin-arm64": "0.1.19",
|
|
163
163
|
"@ruvector/gnn-darwin-x64": "0.1.19",
|
|
164
164
|
"@ruvector/gnn-linux-arm64-gnu": "0.1.19",
|
|
165
|
+
"@ruvector/gnn-linux-arm64-musl": "npm:@ruvector/gnn-linux-arm64-gnu@0.1.19",
|
|
165
166
|
"@ruvector/gnn-linux-x64-gnu": "0.1.19",
|
|
166
|
-
"@ruvector/gnn-linux-x64-musl": "npm:@ruvector/gnn-linux-x64-gnu@0.1.19"
|
|
167
|
-
"@ruvector/gnn-linux-arm64-musl": "npm:@ruvector/gnn-linux-arm64-gnu@0.1.19"
|
|
167
|
+
"@ruvector/gnn-linux-x64-musl": "npm:@ruvector/gnn-linux-x64-gnu@0.1.19"
|
|
168
168
|
},
|
|
169
169
|
"resolutions": {
|
|
170
170
|
"graceful-fs": "^4.2.11",
|