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.
Files changed (232) hide show
  1. package/README.ja.md +106 -48
  2. package/README.md +110 -32
  3. package/bin/musubi-analyze.js +74 -67
  4. package/bin/musubi-browser.js +27 -26
  5. package/bin/musubi-change.js +48 -47
  6. package/bin/musubi-checkpoint.js +10 -7
  7. package/bin/musubi-convert.js +25 -25
  8. package/bin/musubi-costs.js +27 -10
  9. package/bin/musubi-gui.js +52 -46
  10. package/bin/musubi-init.js +1952 -10
  11. package/bin/musubi-orchestrate.js +327 -239
  12. package/bin/musubi-remember.js +69 -56
  13. package/bin/musubi-resolve.js +53 -45
  14. package/bin/musubi-trace.js +51 -22
  15. package/bin/musubi-validate.js +39 -30
  16. package/bin/musubi-workflow.js +33 -34
  17. package/bin/musubi.js +39 -2
  18. package/package.json +1 -1
  19. package/src/agents/agent-loop.js +94 -95
  20. package/src/agents/agentic/code-generator.js +119 -109
  21. package/src/agents/agentic/code-reviewer.js +105 -108
  22. package/src/agents/agentic/index.js +4 -4
  23. package/src/agents/browser/action-executor.js +13 -13
  24. package/src/agents/browser/ai-comparator.js +11 -10
  25. package/src/agents/browser/context-manager.js +6 -6
  26. package/src/agents/browser/index.js +5 -5
  27. package/src/agents/browser/nl-parser.js +31 -46
  28. package/src/agents/browser/screenshot.js +2 -2
  29. package/src/agents/browser/test-generator.js +6 -4
  30. package/src/agents/function-tool.js +71 -65
  31. package/src/agents/index.js +7 -7
  32. package/src/agents/schema-generator.js +98 -94
  33. package/src/analyzers/ast-extractor.js +158 -146
  34. package/src/analyzers/codegraph-auto-update.js +858 -0
  35. package/src/analyzers/complexity-analyzer.js +536 -0
  36. package/src/analyzers/context-optimizer.js +241 -126
  37. package/src/analyzers/impact-analyzer.js +1 -1
  38. package/src/analyzers/large-project-analyzer.js +766 -0
  39. package/src/analyzers/repository-map.js +77 -81
  40. package/src/analyzers/security-analyzer.js +19 -11
  41. package/src/analyzers/stuck-detector.js +19 -17
  42. package/src/converters/index.js +78 -57
  43. package/src/converters/ir/types.js +12 -12
  44. package/src/converters/parsers/musubi-parser.js +134 -126
  45. package/src/converters/parsers/openapi-parser.js +70 -53
  46. package/src/converters/parsers/speckit-parser.js +239 -175
  47. package/src/converters/writers/musubi-writer.js +123 -118
  48. package/src/converters/writers/speckit-writer.js +124 -113
  49. package/src/generators/rust-migration-generator.js +512 -0
  50. package/src/gui/public/index.html +1365 -1211
  51. package/src/gui/server.js +41 -40
  52. package/src/gui/services/file-watcher.js +23 -8
  53. package/src/gui/services/project-scanner.js +26 -20
  54. package/src/gui/services/replanning-service.js +27 -23
  55. package/src/gui/services/traceability-service.js +8 -8
  56. package/src/gui/services/workflow-service.js +14 -7
  57. package/src/index.js +151 -0
  58. package/src/integrations/cicd.js +90 -104
  59. package/src/integrations/codegraph-mcp.js +643 -0
  60. package/src/integrations/documentation.js +142 -103
  61. package/src/integrations/examples.js +95 -80
  62. package/src/integrations/github-client.js +17 -17
  63. package/src/integrations/index.js +5 -5
  64. package/src/integrations/mcp/index.js +21 -21
  65. package/src/integrations/mcp/mcp-context-provider.js +76 -78
  66. package/src/integrations/mcp/mcp-discovery.js +74 -72
  67. package/src/integrations/mcp/mcp-tool-registry.js +99 -94
  68. package/src/integrations/mcp-connector.js +70 -66
  69. package/src/integrations/platforms.js +50 -49
  70. package/src/integrations/tool-discovery.js +37 -31
  71. package/src/llm-providers/anthropic-provider.js +11 -11
  72. package/src/llm-providers/base-provider.js +16 -18
  73. package/src/llm-providers/copilot-provider.js +22 -19
  74. package/src/llm-providers/index.js +26 -25
  75. package/src/llm-providers/ollama-provider.js +11 -11
  76. package/src/llm-providers/openai-provider.js +12 -12
  77. package/src/managers/agent-memory.js +36 -24
  78. package/src/managers/checkpoint-manager.js +4 -8
  79. package/src/managers/delta-spec.js +19 -19
  80. package/src/managers/index.js +13 -4
  81. package/src/managers/memory-condenser.js +35 -45
  82. package/src/managers/repo-skill-manager.js +57 -31
  83. package/src/managers/skill-loader.js +25 -22
  84. package/src/managers/skill-tools.js +36 -72
  85. package/src/managers/workflow.js +30 -22
  86. package/src/monitoring/cost-tracker.js +48 -46
  87. package/src/monitoring/incident-manager.js +116 -106
  88. package/src/monitoring/index.js +144 -134
  89. package/src/monitoring/observability.js +75 -62
  90. package/src/monitoring/quality-dashboard.js +45 -41
  91. package/src/monitoring/release-manager.js +63 -53
  92. package/src/orchestration/agent-skill-binding.js +39 -47
  93. package/src/orchestration/error-handler.js +65 -107
  94. package/src/orchestration/guardrails/base-guardrail.js +26 -24
  95. package/src/orchestration/guardrails/guardrail-rules.js +50 -64
  96. package/src/orchestration/guardrails/index.js +5 -5
  97. package/src/orchestration/guardrails/input-guardrail.js +58 -45
  98. package/src/orchestration/guardrails/output-guardrail.js +104 -81
  99. package/src/orchestration/guardrails/safety-check.js +79 -79
  100. package/src/orchestration/index.js +38 -55
  101. package/src/orchestration/mcp-tool-adapters.js +96 -99
  102. package/src/orchestration/orchestration-engine.js +21 -21
  103. package/src/orchestration/pattern-registry.js +60 -45
  104. package/src/orchestration/patterns/auto.js +34 -47
  105. package/src/orchestration/patterns/group-chat.js +59 -65
  106. package/src/orchestration/patterns/handoff.js +67 -65
  107. package/src/orchestration/patterns/human-in-loop.js +51 -72
  108. package/src/orchestration/patterns/nested.js +25 -40
  109. package/src/orchestration/patterns/sequential.js +35 -34
  110. package/src/orchestration/patterns/swarm.js +63 -56
  111. package/src/orchestration/patterns/triage.js +150 -109
  112. package/src/orchestration/reasoning/index.js +9 -9
  113. package/src/orchestration/reasoning/planning-engine.js +143 -140
  114. package/src/orchestration/reasoning/reasoning-engine.js +206 -144
  115. package/src/orchestration/reasoning/self-correction.js +121 -128
  116. package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
  117. package/src/orchestration/replanning/alternative-generator.js +37 -42
  118. package/src/orchestration/replanning/config.js +63 -59
  119. package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
  120. package/src/orchestration/replanning/index.js +24 -20
  121. package/src/orchestration/replanning/plan-evaluator.js +49 -50
  122. package/src/orchestration/replanning/plan-monitor.js +32 -28
  123. package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
  124. package/src/orchestration/replanning/replan-history.js +33 -26
  125. package/src/orchestration/replanning/replanning-engine.js +106 -108
  126. package/src/orchestration/skill-executor.js +107 -109
  127. package/src/orchestration/skill-registry.js +85 -89
  128. package/src/orchestration/workflow-examples.js +228 -231
  129. package/src/orchestration/workflow-executor.js +65 -68
  130. package/src/orchestration/workflow-orchestrator.js +72 -73
  131. package/src/phase4-integration.js +47 -40
  132. package/src/phase5-integration.js +89 -30
  133. package/src/reporters/coverage-report.js +82 -30
  134. package/src/reporters/hierarchical-reporter.js +498 -0
  135. package/src/reporters/traceability-matrix-report.js +29 -20
  136. package/src/resolvers/issue-resolver.js +43 -31
  137. package/src/steering/advanced-validation.js +133 -124
  138. package/src/steering/auto-updater.js +60 -73
  139. package/src/steering/index.js +6 -6
  140. package/src/steering/quality-metrics.js +41 -35
  141. package/src/steering/steering-auto-update.js +83 -86
  142. package/src/steering/steering-validator.js +98 -106
  143. package/src/steering/template-constraints.js +53 -54
  144. package/src/templates/agents/claude-code/CLAUDE.md +32 -32
  145. package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
  146. package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
  147. package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
  148. package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
  149. package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
  150. package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
  151. package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
  152. package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
  153. package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
  154. package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
  155. package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
  156. package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
  157. package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
  158. package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
  159. package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
  160. package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
  161. package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
  162. package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
  163. package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
  164. package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
  165. package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
  166. package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
  167. package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
  168. package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
  169. package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
  170. package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
  171. package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
  172. package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
  173. package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
  174. package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
  175. package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
  176. package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
  177. package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
  178. package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
  179. package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
  180. package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
  181. package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
  182. package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
  183. package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
  184. package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
  185. package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
  186. package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
  187. package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
  188. package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
  189. package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
  190. package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
  191. package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
  192. package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
  193. package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
  194. package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
  195. package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
  196. package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
  197. package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
  198. package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
  199. package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
  200. package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
  201. package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
  202. package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
  203. package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
  204. package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
  205. package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
  206. package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
  207. package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
  208. package/src/templates/agents/codex/AGENTS.md +74 -42
  209. package/src/templates/agents/cursor/AGENTS.md +74 -42
  210. package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
  211. package/src/templates/agents/github-copilot/AGENTS.md +83 -51
  212. package/src/templates/agents/qwen-code/QWEN.md +74 -42
  213. package/src/templates/agents/windsurf/AGENTS.md +74 -42
  214. package/src/templates/architectures/README.md +41 -0
  215. package/src/templates/architectures/clean-architecture/README.md +113 -0
  216. package/src/templates/architectures/event-driven/README.md +162 -0
  217. package/src/templates/architectures/hexagonal/README.md +130 -0
  218. package/src/templates/index.js +6 -1
  219. package/src/templates/locale-manager.js +16 -16
  220. package/src/templates/shared/delta-spec-template.md +20 -13
  221. package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
  222. package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
  223. package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
  224. package/src/templates/shared/steering/structure.md +95 -0
  225. package/src/templates/skills/browser-agent.md +21 -16
  226. package/src/templates/skills/web-gui.md +8 -0
  227. package/src/templates/template-constraints.js +50 -53
  228. package/src/validators/advanced-validation.js +30 -36
  229. package/src/validators/constitutional-validator.js +77 -73
  230. package/src/validators/critic-system.js +49 -59
  231. package/src/validators/delta-format.js +59 -55
  232. 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', // 0.8+
19
- B: 'B', // 0.5-0.79
20
- C: 'C', // 0.3-0.49
21
- F: 'F', // < 0.3
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 : (value.score || 0);
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(context = {}) {
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 : (value.score || 0);
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 = context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
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 = context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
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 = context.content || this.readFile('docs/requirements/srs/srs-musubi-v3.0.0.ja.md') || '';
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(context) {
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(context) {
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(context) {
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(context) {
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(context) {
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(context) {
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 = Object.values(results).reduce((sum, r) => sum + r.score, 0) / Object.keys(results).length;
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
- description.toLowerCase().includes(term)
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', 'database', 'ui', 'backend', 'frontend',
279
- 'security', 'performance', 'testing', 'documentation',
280
- 'infrastructure', 'configuration'
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
  };