musubi-sdd 5.1.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 +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- 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 +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- 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,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MUSUBI Critic System
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* SDDステージの品質評価システム
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* @module src/validators/critic-system
|
|
7
7
|
* @see REQ-P0-B005
|
|
8
8
|
* @inspired-by OpenHands openhands/critic/
|
|
@@ -15,10 +15,10 @@ const path = require('path');
|
|
|
15
15
|
* 評価グレード
|
|
16
16
|
*/
|
|
17
17
|
const Grade = {
|
|
18
|
-
A: 'A',
|
|
19
|
-
B: 'B',
|
|
20
|
-
C: 'C',
|
|
21
|
-
F: 'F',
|
|
18
|
+
A: 'A', // 0.8+
|
|
19
|
+
B: 'B', // 0.5-0.79
|
|
20
|
+
C: 'C', // 0.3-0.49
|
|
21
|
+
F: 'F', // < 0.3
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -97,13 +97,13 @@ class CriticResult {
|
|
|
97
97
|
md += `- **Grade**: ${this.grade}\n`;
|
|
98
98
|
md += `- **Status**: ${this.success ? '✅ Pass' : '❌ Fail'}\n\n`;
|
|
99
99
|
md += `### Summary\n\n${this.message}\n\n`;
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
if (Object.keys(this.details).length > 0) {
|
|
102
102
|
md += `### Details\n\n`;
|
|
103
103
|
md += `| Criterion | Score | Status |\n`;
|
|
104
104
|
md += `|-----------|-------|--------|\n`;
|
|
105
105
|
for (const [key, value] of Object.entries(this.details)) {
|
|
106
|
-
const score = typeof value === 'number' ? value :
|
|
106
|
+
const score = typeof value === 'number' ? value : value.score || 0;
|
|
107
107
|
const pct = Math.round(score * 100);
|
|
108
108
|
const status = score >= 0.5 ? '✅' : '❌';
|
|
109
109
|
md += `| ${key} | ${pct}% | ${status} |\n`;
|
|
@@ -131,7 +131,7 @@ class BaseCritic {
|
|
|
131
131
|
* @param {Object} context - 評価コンテキスト
|
|
132
132
|
* @returns {CriticResult}
|
|
133
133
|
*/
|
|
134
|
-
evaluate(
|
|
134
|
+
evaluate(_context = {}) {
|
|
135
135
|
throw new Error('Must implement evaluate()');
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -148,7 +148,7 @@ class BaseCritic {
|
|
|
148
148
|
let weightedSum = 0;
|
|
149
149
|
|
|
150
150
|
for (const [key, value] of entries) {
|
|
151
|
-
const score = typeof value === 'number' ? value :
|
|
151
|
+
const score = typeof value === 'number' ? value : value.score || 0;
|
|
152
152
|
const weight = this.weights[key] || 1;
|
|
153
153
|
weightedSum += score * weight;
|
|
154
154
|
totalWeight += weight;
|
|
@@ -159,7 +159,7 @@ class BaseCritic {
|
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
161
|
* ファイルが存在するかチェック
|
|
162
|
-
* @param {string} relativePath
|
|
162
|
+
* @param {string} relativePath
|
|
163
163
|
* @returns {boolean}
|
|
164
164
|
*/
|
|
165
165
|
fileExists(relativePath) {
|
|
@@ -168,7 +168,7 @@ class BaseCritic {
|
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* ファイル内容を読み込み
|
|
171
|
-
* @param {string} relativePath
|
|
171
|
+
* @param {string} relativePath
|
|
172
172
|
* @returns {string|null}
|
|
173
173
|
*/
|
|
174
174
|
readFile(relativePath) {
|
|
@@ -202,20 +202,17 @@ class RequirementsCritic extends BaseCritic {
|
|
|
202
202
|
};
|
|
203
203
|
|
|
204
204
|
const totalScore = this.calculateWeightedScore(scores);
|
|
205
|
-
|
|
206
|
-
return new CriticResult(
|
|
207
|
-
totalScore,
|
|
208
|
-
this._generateMessage(totalScore, scores),
|
|
209
|
-
scores
|
|
210
|
-
);
|
|
205
|
+
|
|
206
|
+
return new CriticResult(totalScore, this._generateMessage(totalScore, scores), scores);
|
|
211
207
|
}
|
|
212
208
|
|
|
213
209
|
/**
|
|
214
210
|
* EARS形式準拠チェック
|
|
215
211
|
*/
|
|
216
212
|
checkEarsFormat(context) {
|
|
217
|
-
const content =
|
|
218
|
-
|
|
213
|
+
const content =
|
|
214
|
+
context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
|
|
215
|
+
|
|
219
216
|
// EARS キーワードパターン
|
|
220
217
|
const earsPatterns = [
|
|
221
218
|
/\b(When|If|While|Where)\b.*\b(shall|should|must)\b/gi,
|
|
@@ -225,7 +222,7 @@ class RequirementsCritic extends BaseCritic {
|
|
|
225
222
|
|
|
226
223
|
const reqPattern = /REQ-[A-Z0-9]+-\d+/g;
|
|
227
224
|
const requirements = content.match(reqPattern) || [];
|
|
228
|
-
|
|
225
|
+
|
|
229
226
|
if (requirements.length === 0) return 0;
|
|
230
227
|
|
|
231
228
|
// EARS パターンの出現をカウント
|
|
@@ -243,8 +240,9 @@ class RequirementsCritic extends BaseCritic {
|
|
|
243
240
|
* 完全性チェック
|
|
244
241
|
*/
|
|
245
242
|
checkCompleteness(context) {
|
|
246
|
-
const content =
|
|
247
|
-
|
|
243
|
+
const content =
|
|
244
|
+
context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
|
|
245
|
+
|
|
248
246
|
const requiredSections = [
|
|
249
247
|
/## 機能要件|## Functional Requirements/i,
|
|
250
248
|
/## 非機能要件|## Non-Functional Requirements/i,
|
|
@@ -259,13 +257,14 @@ class RequirementsCritic extends BaseCritic {
|
|
|
259
257
|
* テスト可能性チェック
|
|
260
258
|
*/
|
|
261
259
|
checkTestability(context) {
|
|
262
|
-
const content =
|
|
263
|
-
|
|
260
|
+
const content =
|
|
261
|
+
context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
|
|
262
|
+
|
|
264
263
|
// 数値目標や測定可能な基準があるかチェック
|
|
265
264
|
const measurablePatterns = [
|
|
266
|
-
/\d+%/g,
|
|
267
|
-
/\d+\s*(秒|ms|ミリ秒|seconds?)/gi,
|
|
268
|
-
/\d+\s*(回|times?)/gi,
|
|
265
|
+
/\d+%/g, // パーセンテージ
|
|
266
|
+
/\d+\s*(秒|ms|ミリ秒|seconds?)/gi, // 時間
|
|
267
|
+
/\d+\s*(回|times?)/gi, // 回数
|
|
269
268
|
/less than|greater than|at least|最大|最小/gi,
|
|
270
269
|
];
|
|
271
270
|
|
|
@@ -284,14 +283,14 @@ class RequirementsCritic extends BaseCritic {
|
|
|
284
283
|
*/
|
|
285
284
|
checkTraceability(context) {
|
|
286
285
|
const content = context.content || '';
|
|
287
|
-
|
|
286
|
+
|
|
288
287
|
// 要件IDへの参照をチェック
|
|
289
288
|
const reqPattern = /REQ-[A-Z0-9]+-\d+/g;
|
|
290
289
|
const requirements = content.match(reqPattern) || [];
|
|
291
|
-
|
|
290
|
+
|
|
292
291
|
// 重複を除去してユニークな要件数をカウント
|
|
293
292
|
const uniqueReqs = [...new Set(requirements)];
|
|
294
|
-
|
|
293
|
+
|
|
295
294
|
// 5つ以上のユニーク要件があれば良好
|
|
296
295
|
return Math.min(1, uniqueReqs.length / 5);
|
|
297
296
|
}
|
|
@@ -333,25 +332,21 @@ class DesignCritic extends BaseCritic {
|
|
|
333
332
|
};
|
|
334
333
|
|
|
335
334
|
const totalScore = this.calculateWeightedScore(scores);
|
|
336
|
-
|
|
337
|
-
return new CriticResult(
|
|
338
|
-
totalScore,
|
|
339
|
-
this._generateMessage(totalScore, scores),
|
|
340
|
-
scores
|
|
341
|
-
);
|
|
335
|
+
|
|
336
|
+
return new CriticResult(totalScore, this._generateMessage(totalScore, scores), scores);
|
|
342
337
|
}
|
|
343
338
|
|
|
344
339
|
/**
|
|
345
340
|
* C4モデル準拠チェック
|
|
346
341
|
*/
|
|
347
|
-
checkC4Format(
|
|
342
|
+
checkC4Format(_context) {
|
|
348
343
|
const designDir = path.join(this.projectRoot, 'docs/design');
|
|
349
344
|
if (!fs.existsSync(designDir)) return 0;
|
|
350
345
|
|
|
351
346
|
// C4レベルのキーワードをチェック
|
|
352
347
|
const c4Keywords = ['Context', 'Container', 'Component', 'Code'];
|
|
353
348
|
const files = fs.readdirSync(designDir).filter(f => f.endsWith('.md'));
|
|
354
|
-
|
|
349
|
+
|
|
355
350
|
let c4Score = 0;
|
|
356
351
|
for (const file of files) {
|
|
357
352
|
const content = fs.readFileSync(path.join(designDir, file), 'utf-8');
|
|
@@ -366,13 +361,11 @@ class DesignCritic extends BaseCritic {
|
|
|
366
361
|
/**
|
|
367
362
|
* ADR存在チェック
|
|
368
363
|
*/
|
|
369
|
-
checkAdrPresence(
|
|
364
|
+
checkAdrPresence(_context) {
|
|
370
365
|
const adrDir = path.join(this.projectRoot, 'docs/design/adr');
|
|
371
366
|
if (!fs.existsSync(adrDir)) return 0;
|
|
372
367
|
|
|
373
|
-
const adrFiles = fs.readdirSync(adrDir).filter(f =>
|
|
374
|
-
f.startsWith('ADR-') && f.endsWith('.md')
|
|
375
|
-
);
|
|
368
|
+
const adrFiles = fs.readdirSync(adrDir).filter(f => f.startsWith('ADR-') && f.endsWith('.md'));
|
|
376
369
|
|
|
377
370
|
// 3つ以上のADRがあれば満点
|
|
378
371
|
return Math.min(1, adrFiles.length / 3);
|
|
@@ -381,7 +374,7 @@ class DesignCritic extends BaseCritic {
|
|
|
381
374
|
/**
|
|
382
375
|
* 要件カバレッジチェック
|
|
383
376
|
*/
|
|
384
|
-
checkRequirementCoverage(
|
|
377
|
+
checkRequirementCoverage(_context) {
|
|
385
378
|
const designDir = path.join(this.projectRoot, 'docs/design');
|
|
386
379
|
if (!fs.existsSync(designDir)) return 0;
|
|
387
380
|
|
|
@@ -435,18 +428,14 @@ class ImplementationCritic extends BaseCritic {
|
|
|
435
428
|
};
|
|
436
429
|
|
|
437
430
|
const totalScore = this.calculateWeightedScore(scores);
|
|
438
|
-
|
|
439
|
-
return new CriticResult(
|
|
440
|
-
totalScore,
|
|
441
|
-
this._generateMessage(totalScore, scores),
|
|
442
|
-
scores
|
|
443
|
-
);
|
|
431
|
+
|
|
432
|
+
return new CriticResult(totalScore, this._generateMessage(totalScore, scores), scores);
|
|
444
433
|
}
|
|
445
434
|
|
|
446
435
|
/**
|
|
447
436
|
* テストカバレッジチェック
|
|
448
437
|
*/
|
|
449
|
-
checkTestCoverage(
|
|
438
|
+
checkTestCoverage(_context) {
|
|
450
439
|
// coverage/lcov-report/index.html があればパース
|
|
451
440
|
const coveragePath = path.join(this.projectRoot, 'coverage/coverage-summary.json');
|
|
452
441
|
if (fs.existsSync(coveragePath)) {
|
|
@@ -476,7 +465,7 @@ class ImplementationCritic extends BaseCritic {
|
|
|
476
465
|
/**
|
|
477
466
|
* コード品質チェック
|
|
478
467
|
*/
|
|
479
|
-
checkCodeQuality(
|
|
468
|
+
checkCodeQuality(_context) {
|
|
480
469
|
let score = 0;
|
|
481
470
|
|
|
482
471
|
// ESLint設定の存在
|
|
@@ -511,7 +500,7 @@ class ImplementationCritic extends BaseCritic {
|
|
|
511
500
|
/**
|
|
512
501
|
* ドキュメントチェック
|
|
513
502
|
*/
|
|
514
|
-
checkDocumentation(
|
|
503
|
+
checkDocumentation(_context) {
|
|
515
504
|
let score = 0;
|
|
516
505
|
|
|
517
506
|
// README.md
|
|
@@ -570,8 +559,8 @@ class CriticSystem {
|
|
|
570
559
|
|
|
571
560
|
/**
|
|
572
561
|
* 特定ステージを評価
|
|
573
|
-
* @param {string} stage
|
|
574
|
-
* @param {Object} context
|
|
562
|
+
* @param {string} stage
|
|
563
|
+
* @param {Object} context
|
|
575
564
|
* @returns {CriticResult}
|
|
576
565
|
*/
|
|
577
566
|
evaluate(stage, context = {}) {
|
|
@@ -584,7 +573,7 @@ class CriticSystem {
|
|
|
584
573
|
|
|
585
574
|
/**
|
|
586
575
|
* 全ステージを評価
|
|
587
|
-
* @param {Object} context
|
|
576
|
+
* @param {Object} context
|
|
588
577
|
* @returns {Object}
|
|
589
578
|
*/
|
|
590
579
|
evaluateAll(context = {}) {
|
|
@@ -610,13 +599,13 @@ class CriticSystem {
|
|
|
610
599
|
|
|
611
600
|
/**
|
|
612
601
|
* レポートを生成
|
|
613
|
-
* @param {Object} results
|
|
602
|
+
* @param {Object} results
|
|
614
603
|
* @returns {string}
|
|
615
604
|
*/
|
|
616
605
|
generateReport(results) {
|
|
617
606
|
let md = `# MUSUBI Quality Report\n\n`;
|
|
618
607
|
md += `Generated: ${new Date().toISOString()}\n\n`;
|
|
619
|
-
|
|
608
|
+
|
|
620
609
|
if (results.overall) {
|
|
621
610
|
md += `## Overall Score\n\n`;
|
|
622
611
|
md += `- **Score**: ${results.overall.percentage}%\n`;
|
|
@@ -634,7 +623,8 @@ class CriticSystem {
|
|
|
634
623
|
}
|
|
635
624
|
|
|
636
625
|
_generateOverallMessage(results) {
|
|
637
|
-
const avgScore =
|
|
626
|
+
const avgScore =
|
|
627
|
+
Object.values(results).reduce((sum, r) => sum + r.score, 0) / Object.keys(results).length;
|
|
638
628
|
if (avgScore >= 0.8) {
|
|
639
629
|
return 'プロジェクトは全体的に高品質です。';
|
|
640
630
|
} else if (avgScore >= 0.5) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Delta Format Validator
|
|
3
3
|
* Validates delta specification format compliance
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* @module validators/delta-format
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -15,21 +15,21 @@ const { DeltaType } = require('../managers/delta-spec');
|
|
|
15
15
|
const ValidationRules = {
|
|
16
16
|
// ID format: PREFIX-IDENTIFIER (e.g., DELTA-AUTH-001, CHG-UI-002)
|
|
17
17
|
ID_PATTERN: /^[A-Z]+-[A-Z0-9]+-\d{3}$/,
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
// Delta marker in markdown: [TYPE] ID: Description
|
|
20
20
|
MARKER_PATTERN: /^\[([A-Z]+)\]\s+([A-Z]+-[A-Z0-9]+-\d{3}):\s+(.+)$/,
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
// Requirement reference: REQ-xxx-nnn
|
|
23
23
|
REQ_PATTERN: /REQ-[A-Z]+-\d{3}/g,
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
// Valid statuses
|
|
26
26
|
VALID_STATUSES: ['proposed', 'approved', 'rejected', 'implemented', 'archived'],
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
// Maximum description length
|
|
29
29
|
MAX_DESCRIPTION_LENGTH: 200,
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
// Required sections in delta markdown
|
|
32
|
-
REQUIRED_SECTIONS: ['Description']
|
|
32
|
+
REQUIRED_SECTIONS: ['Description'],
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
class DeltaFormatValidator {
|
|
@@ -61,7 +61,7 @@ class DeltaFormatValidator {
|
|
|
61
61
|
valid: this.errors.length === 0,
|
|
62
62
|
errors: this.errors,
|
|
63
63
|
warnings: this.warnings,
|
|
64
|
-
delta
|
|
64
|
+
delta,
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -73,7 +73,7 @@ class DeltaFormatValidator {
|
|
|
73
73
|
if (!id) {
|
|
74
74
|
this.errors.push({
|
|
75
75
|
rule: 'required-id',
|
|
76
|
-
message: 'Delta ID is required'
|
|
76
|
+
message: 'Delta ID is required',
|
|
77
77
|
});
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
@@ -82,7 +82,7 @@ class DeltaFormatValidator {
|
|
|
82
82
|
this.errors.push({
|
|
83
83
|
rule: 'id-format',
|
|
84
84
|
message: `Invalid ID format: "${id}". Expected: PREFIX-IDENTIFIER-NNN (e.g., DELTA-AUTH-001)`,
|
|
85
|
-
value: id
|
|
85
|
+
value: id,
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -95,7 +95,7 @@ class DeltaFormatValidator {
|
|
|
95
95
|
if (!type) {
|
|
96
96
|
this.errors.push({
|
|
97
97
|
rule: 'required-type',
|
|
98
|
-
message: 'Delta type is required'
|
|
98
|
+
message: 'Delta type is required',
|
|
99
99
|
});
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
@@ -104,7 +104,7 @@ class DeltaFormatValidator {
|
|
|
104
104
|
this.errors.push({
|
|
105
105
|
rule: 'invalid-type',
|
|
106
106
|
message: `Invalid delta type: "${type}". Must be one of: ${Object.values(DeltaType).join(', ')}`,
|
|
107
|
-
value: type
|
|
107
|
+
value: type,
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -117,7 +117,7 @@ class DeltaFormatValidator {
|
|
|
117
117
|
if (!target) {
|
|
118
118
|
this.errors.push({
|
|
119
119
|
rule: 'required-target',
|
|
120
|
-
message: 'Target is required'
|
|
120
|
+
message: 'Target is required',
|
|
121
121
|
});
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
@@ -127,7 +127,7 @@ class DeltaFormatValidator {
|
|
|
127
127
|
this.warnings.push({
|
|
128
128
|
rule: 'target-format',
|
|
129
129
|
message: `Target "${target}" doesn't match requirement ID format (REQ-XXX-NNN) or path format`,
|
|
130
|
-
value: target
|
|
130
|
+
value: target,
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -140,7 +140,7 @@ class DeltaFormatValidator {
|
|
|
140
140
|
if (!description) {
|
|
141
141
|
this.errors.push({
|
|
142
142
|
rule: 'required-description',
|
|
143
|
-
message: 'Description is required'
|
|
143
|
+
message: 'Description is required',
|
|
144
144
|
});
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
@@ -149,21 +149,19 @@ class DeltaFormatValidator {
|
|
|
149
149
|
this.warnings.push({
|
|
150
150
|
rule: 'description-length',
|
|
151
151
|
message: `Description exceeds ${ValidationRules.MAX_DESCRIPTION_LENGTH} characters`,
|
|
152
|
-
value: description.length
|
|
152
|
+
value: description.length,
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// Check for vague language
|
|
157
157
|
const vagueTerms = ['should', 'might', 'could', 'maybe', 'possibly'];
|
|
158
|
-
const foundVague = vagueTerms.filter(term =>
|
|
159
|
-
|
|
160
|
-
);
|
|
161
|
-
|
|
158
|
+
const foundVague = vagueTerms.filter(term => description.toLowerCase().includes(term));
|
|
159
|
+
|
|
162
160
|
if (foundVague.length > 0) {
|
|
163
161
|
this.warnings.push({
|
|
164
162
|
rule: 'vague-language',
|
|
165
163
|
message: `Description contains vague terms: ${foundVague.join(', ')}. Use definitive language.`,
|
|
166
|
-
value: foundVague
|
|
164
|
+
value: foundVague,
|
|
167
165
|
});
|
|
168
166
|
}
|
|
169
167
|
}
|
|
@@ -176,7 +174,7 @@ class DeltaFormatValidator {
|
|
|
176
174
|
if (!status) {
|
|
177
175
|
this.warnings.push({
|
|
178
176
|
rule: 'missing-status',
|
|
179
|
-
message: 'Status not specified, defaulting to "proposed"'
|
|
177
|
+
message: 'Status not specified, defaulting to "proposed"',
|
|
180
178
|
});
|
|
181
179
|
return;
|
|
182
180
|
}
|
|
@@ -185,7 +183,7 @@ class DeltaFormatValidator {
|
|
|
185
183
|
this.errors.push({
|
|
186
184
|
rule: 'invalid-status',
|
|
187
185
|
message: `Invalid status: "${status}". Must be one of: ${ValidationRules.VALID_STATUSES.join(', ')}`,
|
|
188
|
-
value: status
|
|
186
|
+
value: status,
|
|
189
187
|
});
|
|
190
188
|
}
|
|
191
189
|
}
|
|
@@ -202,13 +200,13 @@ class DeltaFormatValidator {
|
|
|
202
200
|
if (before) {
|
|
203
201
|
this.warnings.push({
|
|
204
202
|
rule: 'added-has-before',
|
|
205
|
-
message: 'ADDED delta should not have a "before" state'
|
|
203
|
+
message: 'ADDED delta should not have a "before" state',
|
|
206
204
|
});
|
|
207
205
|
}
|
|
208
206
|
if (!after && this.strict) {
|
|
209
207
|
this.errors.push({
|
|
210
208
|
rule: 'added-missing-after',
|
|
211
|
-
message: 'ADDED delta should specify the new state in "after"'
|
|
209
|
+
message: 'ADDED delta should specify the new state in "after"',
|
|
212
210
|
});
|
|
213
211
|
}
|
|
214
212
|
break;
|
|
@@ -217,13 +215,13 @@ class DeltaFormatValidator {
|
|
|
217
215
|
if (!before) {
|
|
218
216
|
this.warnings.push({
|
|
219
217
|
rule: 'modified-missing-before',
|
|
220
|
-
message: 'MODIFIED delta should have a "before" state for comparison'
|
|
218
|
+
message: 'MODIFIED delta should have a "before" state for comparison',
|
|
221
219
|
});
|
|
222
220
|
}
|
|
223
221
|
if (!after) {
|
|
224
222
|
this.warnings.push({
|
|
225
223
|
rule: 'modified-missing-after',
|
|
226
|
-
message: 'MODIFIED delta should have an "after" state'
|
|
224
|
+
message: 'MODIFIED delta should have an "after" state',
|
|
227
225
|
});
|
|
228
226
|
}
|
|
229
227
|
break;
|
|
@@ -232,13 +230,13 @@ class DeltaFormatValidator {
|
|
|
232
230
|
if (!before && this.strict) {
|
|
233
231
|
this.warnings.push({
|
|
234
232
|
rule: 'removed-missing-before',
|
|
235
|
-
message: 'REMOVED delta should document the removed state in "before"'
|
|
233
|
+
message: 'REMOVED delta should document the removed state in "before"',
|
|
236
234
|
});
|
|
237
235
|
}
|
|
238
236
|
if (after) {
|
|
239
237
|
this.warnings.push({
|
|
240
238
|
rule: 'removed-has-after',
|
|
241
|
-
message: 'REMOVED delta should not have an "after" state'
|
|
239
|
+
message: 'REMOVED delta should not have an "after" state',
|
|
242
240
|
});
|
|
243
241
|
}
|
|
244
242
|
break;
|
|
@@ -247,13 +245,13 @@ class DeltaFormatValidator {
|
|
|
247
245
|
if (!before) {
|
|
248
246
|
this.errors.push({
|
|
249
247
|
rule: 'renamed-missing-before',
|
|
250
|
-
message: 'RENAMED delta requires "before" state (original name)'
|
|
248
|
+
message: 'RENAMED delta requires "before" state (original name)',
|
|
251
249
|
});
|
|
252
250
|
}
|
|
253
251
|
if (!after) {
|
|
254
252
|
this.errors.push({
|
|
255
253
|
rule: 'renamed-missing-after',
|
|
256
|
-
message: 'RENAMED delta requires "after" state (new name)'
|
|
254
|
+
message: 'RENAMED delta requires "after" state (new name)',
|
|
257
255
|
});
|
|
258
256
|
}
|
|
259
257
|
break;
|
|
@@ -268,27 +266,33 @@ class DeltaFormatValidator {
|
|
|
268
266
|
if (!impactedAreas || impactedAreas.length === 0) {
|
|
269
267
|
this.warnings.push({
|
|
270
268
|
rule: 'missing-impact',
|
|
271
|
-
message: 'Impacted areas should be specified for change tracking'
|
|
269
|
+
message: 'Impacted areas should be specified for change tracking',
|
|
272
270
|
});
|
|
273
271
|
return;
|
|
274
272
|
}
|
|
275
273
|
|
|
276
274
|
// Known impact categories
|
|
277
275
|
const knownCategories = [
|
|
278
|
-
'api',
|
|
279
|
-
'
|
|
280
|
-
'
|
|
276
|
+
'api',
|
|
277
|
+
'database',
|
|
278
|
+
'ui',
|
|
279
|
+
'backend',
|
|
280
|
+
'frontend',
|
|
281
|
+
'security',
|
|
282
|
+
'performance',
|
|
283
|
+
'testing',
|
|
284
|
+
'documentation',
|
|
285
|
+
'infrastructure',
|
|
286
|
+
'configuration',
|
|
281
287
|
];
|
|
282
288
|
|
|
283
|
-
const unknown = impactedAreas.filter(area =>
|
|
284
|
-
!knownCategories.includes(area.toLowerCase())
|
|
285
|
-
);
|
|
289
|
+
const unknown = impactedAreas.filter(area => !knownCategories.includes(area.toLowerCase()));
|
|
286
290
|
|
|
287
291
|
if (unknown.length > 0 && this.strict) {
|
|
288
292
|
this.warnings.push({
|
|
289
293
|
rule: 'unknown-impact-area',
|
|
290
294
|
message: `Unknown impact areas: ${unknown.join(', ')}. Consider using: ${knownCategories.join(', ')}`,
|
|
291
|
-
value: unknown
|
|
295
|
+
value: unknown,
|
|
292
296
|
});
|
|
293
297
|
}
|
|
294
298
|
}
|
|
@@ -303,7 +307,7 @@ class DeltaFormatValidator {
|
|
|
303
307
|
this.errors.push({
|
|
304
308
|
rule: 'invalid-created-timestamp',
|
|
305
309
|
message: 'Invalid createdAt timestamp format',
|
|
306
|
-
value: delta.createdAt
|
|
310
|
+
value: delta.createdAt,
|
|
307
311
|
});
|
|
308
312
|
}
|
|
309
313
|
}
|
|
@@ -313,14 +317,14 @@ class DeltaFormatValidator {
|
|
|
313
317
|
this.errors.push({
|
|
314
318
|
rule: 'invalid-updated-timestamp',
|
|
315
319
|
message: 'Invalid updatedAt timestamp format',
|
|
316
|
-
value: delta.updatedAt
|
|
320
|
+
value: delta.updatedAt,
|
|
317
321
|
});
|
|
318
322
|
}
|
|
319
323
|
|
|
320
324
|
if (delta.createdAt && new Date(delta.updatedAt) < new Date(delta.createdAt)) {
|
|
321
325
|
this.warnings.push({
|
|
322
326
|
rule: 'timestamp-order',
|
|
323
|
-
message: 'updatedAt is before createdAt'
|
|
327
|
+
message: 'updatedAt is before createdAt',
|
|
324
328
|
});
|
|
325
329
|
}
|
|
326
330
|
}
|
|
@@ -342,12 +346,12 @@ class DeltaFormatValidator {
|
|
|
342
346
|
const match = line.match(ValidationRules.MARKER_PATTERN);
|
|
343
347
|
if (match) {
|
|
344
348
|
const [, type, id, description] = match;
|
|
345
|
-
|
|
349
|
+
|
|
346
350
|
const delta = {
|
|
347
351
|
type,
|
|
348
352
|
id,
|
|
349
353
|
description,
|
|
350
|
-
line: index + 1
|
|
354
|
+
line: index + 1,
|
|
351
355
|
};
|
|
352
356
|
|
|
353
357
|
// Validate each found delta marker
|
|
@@ -364,12 +368,12 @@ class DeltaFormatValidator {
|
|
|
364
368
|
// Check for duplicate IDs
|
|
365
369
|
const ids = deltas.map(d => d.id);
|
|
366
370
|
const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
|
|
367
|
-
|
|
371
|
+
|
|
368
372
|
if (duplicates.length > 0) {
|
|
369
373
|
this.errors.push({
|
|
370
374
|
rule: 'duplicate-id',
|
|
371
375
|
message: `Duplicate delta IDs found: ${[...new Set(duplicates)].join(', ')}`,
|
|
372
|
-
value: duplicates
|
|
376
|
+
value: duplicates,
|
|
373
377
|
});
|
|
374
378
|
}
|
|
375
379
|
|
|
@@ -377,7 +381,7 @@ class DeltaFormatValidator {
|
|
|
377
381
|
valid: this.errors.length === 0,
|
|
378
382
|
errors: this.errors,
|
|
379
383
|
warnings: this.warnings,
|
|
380
|
-
deltas
|
|
384
|
+
deltas,
|
|
381
385
|
};
|
|
382
386
|
}
|
|
383
387
|
|
|
@@ -391,7 +395,7 @@ class DeltaFormatValidator {
|
|
|
391
395
|
return {
|
|
392
396
|
valid: false,
|
|
393
397
|
errors: [{ rule: 'file-not-found', message: `File not found: ${filePath}` }],
|
|
394
|
-
warnings: []
|
|
398
|
+
warnings: [],
|
|
395
399
|
};
|
|
396
400
|
}
|
|
397
401
|
|
|
@@ -406,7 +410,7 @@ class DeltaFormatValidator {
|
|
|
406
410
|
return {
|
|
407
411
|
valid: false,
|
|
408
412
|
errors: [{ rule: 'invalid-json', message: `Invalid JSON: ${e.message}` }],
|
|
409
|
-
warnings: []
|
|
413
|
+
warnings: [],
|
|
410
414
|
};
|
|
411
415
|
}
|
|
412
416
|
} else if (ext === '.md') {
|
|
@@ -415,7 +419,7 @@ class DeltaFormatValidator {
|
|
|
415
419
|
return {
|
|
416
420
|
valid: false,
|
|
417
421
|
errors: [{ rule: 'unsupported-format', message: `Unsupported file format: ${ext}` }],
|
|
418
|
-
warnings: []
|
|
422
|
+
warnings: [],
|
|
419
423
|
};
|
|
420
424
|
}
|
|
421
425
|
}
|
|
@@ -430,7 +434,7 @@ class DeltaFormatValidator {
|
|
|
430
434
|
return {
|
|
431
435
|
valid: true,
|
|
432
436
|
results: [],
|
|
433
|
-
summary: { total: 0, valid: 0, invalid: 0 }
|
|
437
|
+
summary: { total: 0, valid: 0, invalid: 0 },
|
|
434
438
|
};
|
|
435
439
|
}
|
|
436
440
|
|
|
@@ -446,7 +450,7 @@ class DeltaFormatValidator {
|
|
|
446
450
|
const result = this.validateFile(jsonPath);
|
|
447
451
|
result.id = entry.name;
|
|
448
452
|
results.push(result);
|
|
449
|
-
|
|
453
|
+
|
|
450
454
|
if (result.valid) {
|
|
451
455
|
validCount++;
|
|
452
456
|
} else {
|
|
@@ -462,13 +466,13 @@ class DeltaFormatValidator {
|
|
|
462
466
|
summary: {
|
|
463
467
|
total: results.length,
|
|
464
468
|
valid: validCount,
|
|
465
|
-
invalid: invalidCount
|
|
466
|
-
}
|
|
469
|
+
invalid: invalidCount,
|
|
470
|
+
},
|
|
467
471
|
};
|
|
468
472
|
}
|
|
469
473
|
}
|
|
470
474
|
|
|
471
475
|
module.exports = {
|
|
472
476
|
DeltaFormatValidator,
|
|
473
|
-
ValidationRules
|
|
477
|
+
ValidationRules,
|
|
474
478
|
};
|