musubi-sdd 5.0.0 → 5.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +164 -145
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +247 -125
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +83 -80
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +53 -44
- package/src/monitoring/incident-manager.js +123 -103
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +82 -59
- package/src/monitoring/quality-dashboard.js +51 -39
- package/src/monitoring/release-manager.js +70 -50
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OpenAPI Parser
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Convert OpenAPI/Swagger specifications to MUSUBI requirements
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
const fs = require('fs-extra');
|
|
10
|
-
const
|
|
10
|
+
const _path = require('path');
|
|
11
11
|
const yaml = require('js-yaml');
|
|
12
12
|
const { createEmptyProjectIR, createEmptyFeatureIR } = require('../ir/types');
|
|
13
13
|
|
|
@@ -18,47 +18,47 @@ const { createEmptyProjectIR, createEmptyFeatureIR } = require('../ir/types');
|
|
|
18
18
|
*/
|
|
19
19
|
async function parseOpenAPISpec(specPath) {
|
|
20
20
|
const content = await fs.readFile(specPath, 'utf-8');
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
let spec;
|
|
23
23
|
if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
|
|
24
24
|
spec = yaml.load(content);
|
|
25
25
|
} else {
|
|
26
26
|
spec = JSON.parse(content);
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
// Detect OpenAPI version
|
|
30
30
|
const version = spec.openapi || spec.swagger;
|
|
31
31
|
if (!version) {
|
|
32
32
|
throw new Error('Not a valid OpenAPI/Swagger specification');
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
const ir = createEmptyProjectIR();
|
|
36
36
|
ir.metadata.name = spec.info?.title || 'API Project';
|
|
37
37
|
ir.metadata.description = spec.info?.description || '';
|
|
38
38
|
ir.metadata.version = spec.info?.version || '1.0.0';
|
|
39
39
|
ir.metadata.sourceFormat = 'openapi';
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
// Group paths by tags
|
|
42
42
|
const tagGroups = groupPathsByTag(spec.paths, spec.tags);
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
// Convert each tag group to a feature
|
|
45
45
|
for (const [tag, endpoints] of Object.entries(tagGroups)) {
|
|
46
46
|
const feature = await createFeatureFromEndpoints(tag, endpoints, spec);
|
|
47
47
|
ir.features.push(feature);
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
// If no tags, create a single feature
|
|
51
51
|
if (ir.features.length === 0) {
|
|
52
52
|
const feature = await createFeatureFromEndpoints('api', spec.paths, spec);
|
|
53
53
|
ir.features.push(feature);
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
// Add security requirements
|
|
57
57
|
if (spec.security || spec.securityDefinitions || spec.components?.securitySchemes) {
|
|
58
58
|
const securityFeature = createSecurityFeature(spec);
|
|
59
59
|
ir.features.push(securityFeature);
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
return ir;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -68,14 +68,14 @@ async function parseOpenAPISpec(specPath) {
|
|
|
68
68
|
* @param {Array} tags - OpenAPI tags array
|
|
69
69
|
* @returns {Object} Grouped paths
|
|
70
70
|
*/
|
|
71
|
-
function groupPathsByTag(paths,
|
|
71
|
+
function groupPathsByTag(paths, _tags = []) {
|
|
72
72
|
const groups = {};
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
for (const [pathUrl, pathItem] of Object.entries(paths || {})) {
|
|
75
75
|
for (const [method, operation] of Object.entries(pathItem)) {
|
|
76
76
|
if (['get', 'post', 'put', 'patch', 'delete', 'head', 'options'].includes(method)) {
|
|
77
77
|
const operationTags = operation.tags || ['default'];
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
for (const tag of operationTags) {
|
|
80
80
|
if (!groups[tag]) {
|
|
81
81
|
groups[tag] = {};
|
|
@@ -88,7 +88,7 @@ function groupPathsByTag(paths, tags = []) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
return groups;
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -102,13 +102,13 @@ function groupPathsByTag(paths, tags = []) {
|
|
|
102
102
|
async function createFeatureFromEndpoints(tag, endpoints, spec) {
|
|
103
103
|
const featureId = tag.toLowerCase().replace(/\s+/g, '-');
|
|
104
104
|
const feature = createEmptyFeatureIR(featureId, tag);
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
feature.specification.description = getTagDescription(spec.tags, tag);
|
|
107
107
|
feature.design = [];
|
|
108
108
|
feature.tests = [];
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
let reqIndex = 1;
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
for (const [pathUrl, pathItem] of Object.entries(endpoints)) {
|
|
113
113
|
for (const [method, operation] of Object.entries(pathItem)) {
|
|
114
114
|
if (['get', 'post', 'put', 'patch', 'delete', 'head', 'options'].includes(method)) {
|
|
@@ -121,7 +121,7 @@ async function createFeatureFromEndpoints(tag, endpoints, spec) {
|
|
|
121
121
|
);
|
|
122
122
|
feature.specification.requirements.push(requirement);
|
|
123
123
|
reqIndex++;
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
// Create design decision for each operation
|
|
126
126
|
const decision = createDesignFromOperation(
|
|
127
127
|
`ADR-${featureId.toUpperCase()}-${String(feature.design.length + 1).padStart(3, '0')}`,
|
|
@@ -130,14 +130,14 @@ async function createFeatureFromEndpoints(tag, endpoints, spec) {
|
|
|
130
130
|
operation
|
|
131
131
|
);
|
|
132
132
|
feature.design.push(decision);
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
// Create test case
|
|
135
135
|
const testCase = createTestFromOperation(method, pathUrl, operation);
|
|
136
136
|
feature.tests.push(testCase);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
return feature;
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -161,18 +161,19 @@ function getTagDescription(tags, tagName) {
|
|
|
161
161
|
* @returns {Object} Requirement object
|
|
162
162
|
*/
|
|
163
163
|
function createRequirementFromOperation(id, method, path, operation) {
|
|
164
|
-
const methodVerb =
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
164
|
+
const methodVerb =
|
|
165
|
+
{
|
|
166
|
+
get: 'retrieves',
|
|
167
|
+
post: 'creates',
|
|
168
|
+
put: 'updates',
|
|
169
|
+
patch: 'partially updates',
|
|
170
|
+
delete: 'deletes',
|
|
171
|
+
head: 'checks',
|
|
172
|
+
options: 'returns options for',
|
|
173
|
+
}[method.toLowerCase()] || method;
|
|
174
|
+
|
|
174
175
|
const summary = operation.summary || operation.operationId || `${method.toUpperCase()} ${path}`;
|
|
175
|
-
|
|
176
|
+
|
|
176
177
|
// Generate EARS pattern based on method
|
|
177
178
|
let earsStatement;
|
|
178
179
|
if (operation.security?.length > 0) {
|
|
@@ -182,7 +183,7 @@ function createRequirementFromOperation(id, method, path, operation) {
|
|
|
182
183
|
// Ubiquitous
|
|
183
184
|
earsStatement = `The system shall provide a ${method.toUpperCase()} ${path} endpoint that ${methodVerb} ${getResourceFromPath(path)}.`;
|
|
184
185
|
}
|
|
185
|
-
|
|
186
|
+
|
|
186
187
|
return {
|
|
187
188
|
id,
|
|
188
189
|
type: 'functional',
|
|
@@ -222,26 +223,34 @@ function getResourceFromPath(path) {
|
|
|
222
223
|
*/
|
|
223
224
|
function generateAcceptanceCriteria(method, path, operation) {
|
|
224
225
|
const criteria = [];
|
|
225
|
-
|
|
226
|
+
|
|
226
227
|
// Add response status criteria
|
|
227
228
|
for (const [status, response] of Object.entries(operation.responses || {})) {
|
|
228
229
|
if (status === '200' || status === '201') {
|
|
229
|
-
criteria.push(
|
|
230
|
+
criteria.push(
|
|
231
|
+
`Given valid request, When ${method.toUpperCase()} ${path}, Then return ${status} with ${response.description || 'success response'}`
|
|
232
|
+
);
|
|
230
233
|
} else if (status.startsWith('4')) {
|
|
231
|
-
criteria.push(
|
|
234
|
+
criteria.push(
|
|
235
|
+
`Given invalid request, When ${method.toUpperCase()} ${path}, Then return ${status} with error details`
|
|
236
|
+
);
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
|
-
|
|
239
|
+
|
|
235
240
|
// Add parameter validation criteria
|
|
236
241
|
if (operation.parameters?.some(p => p.required)) {
|
|
237
|
-
criteria.push(
|
|
242
|
+
criteria.push(
|
|
243
|
+
`Given missing required parameters, When ${method.toUpperCase()} ${path}, Then return 400 Bad Request`
|
|
244
|
+
);
|
|
238
245
|
}
|
|
239
|
-
|
|
246
|
+
|
|
240
247
|
// Add security criteria
|
|
241
248
|
if (operation.security?.length > 0) {
|
|
242
|
-
criteria.push(
|
|
249
|
+
criteria.push(
|
|
250
|
+
`Given unauthenticated request, When ${method.toUpperCase()} ${path}, Then return 401 Unauthorized`
|
|
251
|
+
);
|
|
243
252
|
}
|
|
244
|
-
|
|
253
|
+
|
|
245
254
|
return criteria;
|
|
246
255
|
}
|
|
247
256
|
|
|
@@ -293,16 +302,24 @@ function createTestFromOperation(method, path, operation) {
|
|
|
293
302
|
status: Object.keys(operation.responses || {})[0] || '200',
|
|
294
303
|
description: operation.responses?.['200']?.description || 'Should succeed',
|
|
295
304
|
},
|
|
296
|
-
...(operation.responses?.['400']
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
305
|
+
...(operation.responses?.['400']
|
|
306
|
+
? [
|
|
307
|
+
{
|
|
308
|
+
name: 'Invalid request',
|
|
309
|
+
status: '400',
|
|
310
|
+
description: operation.responses['400'].description,
|
|
311
|
+
},
|
|
312
|
+
]
|
|
313
|
+
: []),
|
|
314
|
+
...(operation.security?.length > 0
|
|
315
|
+
? [
|
|
316
|
+
{
|
|
317
|
+
name: 'Unauthorized',
|
|
318
|
+
status: '401',
|
|
319
|
+
description: 'Should reject unauthenticated request',
|
|
320
|
+
},
|
|
321
|
+
]
|
|
322
|
+
: []),
|
|
306
323
|
],
|
|
307
324
|
};
|
|
308
325
|
}
|
|
@@ -315,9 +332,9 @@ function createTestFromOperation(method, path, operation) {
|
|
|
315
332
|
function createSecurityFeature(spec) {
|
|
316
333
|
const feature = createEmptyFeatureIR('security', 'Security');
|
|
317
334
|
feature.specification.description = 'API Security Requirements';
|
|
318
|
-
|
|
335
|
+
|
|
319
336
|
const schemes = spec.components?.securitySchemes || spec.securityDefinitions || {};
|
|
320
|
-
|
|
337
|
+
|
|
321
338
|
let reqIndex = 1;
|
|
322
339
|
for (const [name, scheme] of Object.entries(schemes)) {
|
|
323
340
|
const requirement = {
|
|
@@ -337,7 +354,7 @@ function createSecurityFeature(spec) {
|
|
|
337
354
|
feature.specification.requirements.push(requirement);
|
|
338
355
|
reqIndex++;
|
|
339
356
|
}
|
|
340
|
-
|
|
357
|
+
|
|
341
358
|
return feature;
|
|
342
359
|
}
|
|
343
360
|
|