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.
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 +164 -145
  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 +247 -125
  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 +83 -80
  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 +53 -44
  87. package/src/monitoring/incident-manager.js +123 -103
  88. package/src/monitoring/index.js +144 -134
  89. package/src/monitoring/observability.js +82 -59
  90. package/src/monitoring/quality-dashboard.js +51 -39
  91. package/src/monitoring/release-manager.js +70 -50
  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
@@ -2,7 +2,7 @@
2
2
  * @file steering-validator.js
3
3
  * @description Steering file validation and consistency checks
4
4
  * @version 1.0.0
5
- *
5
+ *
6
6
  * Part of MUSUBI v5.0.0 - Phase 5 Advanced Features
7
7
  */
8
8
 
@@ -20,7 +20,7 @@ const SEVERITY = {
20
20
  INFO: 'info',
21
21
  WARNING: 'warning',
22
22
  ERROR: 'error',
23
- CRITICAL: 'critical'
23
+ CRITICAL: 'critical',
24
24
  };
25
25
 
26
26
  /**
@@ -32,7 +32,7 @@ const RULE_TYPE = {
32
32
  FORMAT: 'format',
33
33
  CONSISTENCY: 'consistency',
34
34
  REFERENCE: 'reference',
35
- COMPLETENESS: 'completeness'
35
+ COMPLETENESS: 'completeness',
36
36
  };
37
37
 
38
38
  /**
@@ -65,86 +65,87 @@ const DEFAULT_VALIDATION_RULES = [
65
65
  file: 'structure.md',
66
66
  type: RULE_TYPE.REQUIRED,
67
67
  severity: SEVERITY.ERROR,
68
- check: (content) => content.includes('## Overview') || content.includes('# '),
69
- message: 'structure.md must have an Overview section'
68
+ check: content => content.includes('## Overview') || content.includes('# '),
69
+ message: 'structure.md must have an Overview section',
70
70
  },
71
71
  {
72
72
  id: 'structure-has-directories',
73
73
  file: 'structure.md',
74
74
  type: RULE_TYPE.REQUIRED,
75
75
  severity: SEVERITY.WARNING,
76
- check: (content) => content.includes('src/') || content.includes('lib/'),
77
- message: 'structure.md should document directory structure'
76
+ check: content => content.includes('src/') || content.includes('lib/'),
77
+ message: 'structure.md should document directory structure',
78
78
  },
79
-
79
+
80
80
  // Tech.md rules
81
81
  {
82
82
  id: 'tech-has-stack',
83
83
  file: 'tech.md',
84
84
  type: RULE_TYPE.REQUIRED,
85
85
  severity: SEVERITY.ERROR,
86
- check: (content) => content.includes('stack') || content.includes('technologies'),
86
+ check: content => content.includes('stack') || content.includes('technologies'),
87
87
  message: 'tech.md must document the technology stack',
88
- suggestion: 'Add a "Technology Stack" section'
88
+ suggestion: 'Add a "Technology Stack" section',
89
89
  },
90
90
  {
91
91
  id: 'tech-has-dependencies',
92
92
  file: 'tech.md',
93
93
  type: RULE_TYPE.REQUIRED,
94
94
  severity: SEVERITY.WARNING,
95
- check: (content) => content.includes('dependencies') || content.includes('package'),
96
- message: 'tech.md should document dependencies'
95
+ check: content => content.includes('dependencies') || content.includes('package'),
96
+ message: 'tech.md should document dependencies',
97
97
  },
98
-
98
+
99
99
  // Product.md rules
100
100
  {
101
101
  id: 'product-has-vision',
102
102
  file: 'product.md',
103
103
  type: RULE_TYPE.REQUIRED,
104
104
  severity: SEVERITY.ERROR,
105
- check: (content) => content.includes('vision') || content.includes('purpose') || content.includes('goal'),
106
- message: 'product.md must have a vision/purpose section'
105
+ check: content =>
106
+ content.includes('vision') || content.includes('purpose') || content.includes('goal'),
107
+ message: 'product.md must have a vision/purpose section',
107
108
  },
108
109
  {
109
110
  id: 'product-has-features',
110
111
  file: 'product.md',
111
112
  type: RULE_TYPE.REQUIRED,
112
113
  severity: SEVERITY.WARNING,
113
- check: (content) => content.includes('feature') || content.includes('capability'),
114
- message: 'product.md should list features or capabilities'
114
+ check: content => content.includes('feature') || content.includes('capability'),
115
+ message: 'product.md should list features or capabilities',
115
116
  },
116
-
117
+
117
118
  // Constitution rules
118
119
  {
119
120
  id: 'constitution-has-articles',
120
121
  file: 'rules/constitution.md',
121
122
  type: RULE_TYPE.REQUIRED,
122
123
  severity: SEVERITY.ERROR,
123
- check: (content) => content.includes('Article') || content.includes('Rule'),
124
- message: 'constitution.md must define governance articles'
124
+ check: content => content.includes('Article') || content.includes('Rule'),
125
+ message: 'constitution.md must define governance articles',
125
126
  },
126
-
127
+
127
128
  // Format rules
128
129
  {
129
130
  id: 'format-valid-markdown',
130
131
  file: '*',
131
132
  type: RULE_TYPE.FORMAT,
132
133
  severity: SEVERITY.WARNING,
133
- check: (content) => {
134
+ check: content => {
134
135
  // Check for broken links format
135
136
  const brokenLinks = content.match(/\[([^\]]*)\]\(\s*\)/g);
136
137
  return !brokenLinks || brokenLinks.length === 0;
137
138
  },
138
- message: 'File contains empty markdown links'
139
+ message: 'File contains empty markdown links',
139
140
  },
140
141
  {
141
142
  id: 'format-no-todo-in-production',
142
143
  file: '*',
143
144
  type: RULE_TYPE.COMPLETENESS,
144
145
  severity: SEVERITY.INFO,
145
- check: (content) => !content.includes('[TODO]') && !content.includes('[TBD]'),
146
- message: 'File contains TODO or TBD markers'
147
- }
146
+ check: content => !content.includes('[TODO]') && !content.includes('[TBD]'),
147
+ message: 'File contains TODO or TBD markers',
148
+ },
148
149
  ];
149
150
 
150
151
  /**
@@ -158,16 +159,16 @@ class SteeringValidator extends EventEmitter {
158
159
  */
159
160
  constructor(options = {}) {
160
161
  super();
161
-
162
+
162
163
  this.steeringPath = options.steeringPath || 'steering';
163
164
  this.rules = [...DEFAULT_VALIDATION_RULES, ...(options.rules || [])];
164
165
  this.strictMode = options.strictMode ?? false;
165
-
166
+
166
167
  // State
167
168
  this.validations = new Map();
168
169
  this.validationCounter = 0;
169
170
  }
170
-
171
+
171
172
  /**
172
173
  * Validate all steering files
173
174
  * @param {string} [basePath='.'] - Base path
@@ -176,22 +177,17 @@ class SteeringValidator extends EventEmitter {
176
177
  async validate(basePath = '.') {
177
178
  const id = `validation-${++this.validationCounter}`;
178
179
  this.emit('validation:start', { id, basePath });
179
-
180
+
180
181
  const steeringDir = path.join(basePath, this.steeringPath);
181
182
  const issues = [];
182
-
183
+
183
184
  // Define files to check
184
- const files = [
185
- 'structure.md',
186
- 'tech.md',
187
- 'product.md',
188
- 'rules/constitution.md'
189
- ];
190
-
185
+ const files = ['structure.md', 'tech.md', 'product.md', 'rules/constitution.md'];
186
+
191
187
  // Check each file
192
188
  for (const file of files) {
193
189
  const filePath = path.join(steeringDir, file);
194
-
190
+
195
191
  if (!fs.existsSync(filePath)) {
196
192
  issues.push({
197
193
  id: `issue-${issues.length + 1}`,
@@ -199,11 +195,11 @@ class SteeringValidator extends EventEmitter {
199
195
  type: RULE_TYPE.REQUIRED,
200
196
  severity: SEVERITY.ERROR,
201
197
  message: `Required steering file "${file}" not found`,
202
- suggestion: `Create ${file} with appropriate content`
198
+ suggestion: `Create ${file} with appropriate content`,
203
199
  });
204
200
  continue;
205
201
  }
206
-
202
+
207
203
  try {
208
204
  const content = fs.readFileSync(filePath, 'utf8');
209
205
  const fileIssues = await this.validateFile(file, content);
@@ -214,11 +210,11 @@ class SteeringValidator extends EventEmitter {
214
210
  file,
215
211
  type: RULE_TYPE.FORMAT,
216
212
  severity: SEVERITY.ERROR,
217
- message: `Error reading file: ${error.message}`
213
+ message: `Error reading file: ${error.message}`,
218
214
  });
219
215
  }
220
216
  }
221
-
217
+
222
218
  // Check custom steering files
223
219
  const customDir = path.join(steeringDir, 'custom');
224
220
  if (fs.existsSync(customDir)) {
@@ -230,30 +226,32 @@ class SteeringValidator extends EventEmitter {
230
226
  issues.push(...fileIssues);
231
227
  }
232
228
  }
233
-
229
+
234
230
  // Cross-file consistency checks
235
231
  const consistencyIssues = await this.checkConsistency(basePath);
236
232
  issues.push(...consistencyIssues);
237
-
233
+
238
234
  // Calculate score
239
235
  const score = this.calculateScore(issues);
240
-
236
+
241
237
  // Create result
242
238
  const result = {
243
239
  id,
244
- valid: issues.filter(i => i.severity === SEVERITY.ERROR || i.severity === SEVERITY.CRITICAL).length === 0,
240
+ valid:
241
+ issues.filter(i => i.severity === SEVERITY.ERROR || i.severity === SEVERITY.CRITICAL)
242
+ .length === 0,
245
243
  score,
246
244
  issues,
247
245
  summary: this.createSummary(issues),
248
- timestamp: Date.now()
246
+ timestamp: Date.now(),
249
247
  };
250
-
248
+
251
249
  this.validations.set(id, result);
252
250
  this.emit('validation:complete', { result });
253
-
251
+
254
252
  return result;
255
253
  }
256
-
254
+
257
255
  /**
258
256
  * Validate a single file
259
257
  * @param {string} file - File name
@@ -262,16 +260,14 @@ class SteeringValidator extends EventEmitter {
262
260
  */
263
261
  async validateFile(file, content) {
264
262
  const issues = [];
265
-
263
+
266
264
  // Get applicable rules
267
- const applicableRules = this.rules.filter(rule =>
268
- rule.file === file || rule.file === '*'
269
- );
270
-
265
+ const applicableRules = this.rules.filter(rule => rule.file === file || rule.file === '*');
266
+
271
267
  for (const rule of applicableRules) {
272
268
  try {
273
269
  const passes = rule.check(content);
274
-
270
+
275
271
  if (!passes) {
276
272
  issues.push({
277
273
  id: `issue-${Date.now()}-${Math.random().toString(36).substr(2, 4)}`,
@@ -280,17 +276,17 @@ class SteeringValidator extends EventEmitter {
280
276
  type: rule.type,
281
277
  severity: rule.severity,
282
278
  message: rule.message,
283
- suggestion: rule.suggestion
279
+ suggestion: rule.suggestion,
284
280
  });
285
281
  }
286
282
  } catch (error) {
287
283
  this.emit('rule:error', { rule: rule.id, error });
288
284
  }
289
285
  }
290
-
286
+
291
287
  return issues;
292
288
  }
293
-
289
+
294
290
  /**
295
291
  * Check cross-file consistency
296
292
  * @param {string} basePath - Base path
@@ -299,13 +295,13 @@ class SteeringValidator extends EventEmitter {
299
295
  async checkConsistency(basePath) {
300
296
  const issues = [];
301
297
  const steeringDir = path.join(basePath, this.steeringPath);
302
-
298
+
303
299
  try {
304
300
  // Load files
305
301
  const structurePath = path.join(steeringDir, 'structure.md');
306
302
  const techPath = path.join(steeringDir, 'tech.md');
307
303
  const productPath = path.join(steeringDir, 'product.md');
308
-
304
+
309
305
  const files = {};
310
306
  if (fs.existsSync(structurePath)) {
311
307
  files.structure = fs.readFileSync(structurePath, 'utf8');
@@ -316,7 +312,7 @@ class SteeringValidator extends EventEmitter {
316
312
  if (fs.existsSync(productPath)) {
317
313
  files.product = fs.readFileSync(productPath, 'utf8');
318
314
  }
319
-
315
+
320
316
  // Check project name consistency
321
317
  const projectNames = this.extractProjectNames(files);
322
318
  if (projectNames.size > 1) {
@@ -326,15 +322,15 @@ class SteeringValidator extends EventEmitter {
326
322
  type: RULE_TYPE.CONSISTENCY,
327
323
  severity: SEVERITY.WARNING,
328
324
  message: `Inconsistent project names found: ${Array.from(projectNames).join(', ')}`,
329
- suggestion: 'Use consistent project name across all steering files'
325
+ suggestion: 'Use consistent project name across all steering files',
330
326
  });
331
327
  }
332
-
328
+
333
329
  // Check language consistency
334
330
  if (files.structure && files.tech) {
335
331
  const structureLangs = this.extractLanguages(files.structure);
336
332
  const techLangs = this.extractLanguages(files.tech);
337
-
333
+
338
334
  const missingInTech = structureLangs.filter(l => !techLangs.includes(l));
339
335
  if (missingInTech.length > 0) {
340
336
  issues.push({
@@ -342,25 +338,24 @@ class SteeringValidator extends EventEmitter {
342
338
  file: 'tech.md',
343
339
  type: RULE_TYPE.CONSISTENCY,
344
340
  severity: SEVERITY.INFO,
345
- message: `Languages in structure.md not documented in tech.md: ${missingInTech.join(', ')}`
341
+ message: `Languages in structure.md not documented in tech.md: ${missingInTech.join(', ')}`,
346
342
  });
347
343
  }
348
344
  }
349
-
350
345
  } catch (error) {
351
346
  this.emit('consistency:error', { error });
352
347
  }
353
-
348
+
354
349
  return issues;
355
350
  }
356
-
351
+
357
352
  /**
358
353
  * Extract project names from files
359
354
  * @private
360
355
  */
361
356
  extractProjectNames(files) {
362
357
  const names = new Set();
363
-
358
+
364
359
  for (const [, content] of Object.entries(files)) {
365
360
  // Look for project name patterns
366
361
  const matches = content.match(/^#\s+([^\n]+)/m);
@@ -368,10 +363,10 @@ class SteeringValidator extends EventEmitter {
368
363
  names.add(matches[1].trim());
369
364
  }
370
365
  }
371
-
366
+
372
367
  return names;
373
368
  }
374
-
369
+
375
370
  /**
376
371
  * Extract languages from content
377
372
  * @private
@@ -385,39 +380,39 @@ class SteeringValidator extends EventEmitter {
385
380
  /java(?!script)/gi,
386
381
  /go(?:lang)?/gi,
387
382
  /rust/gi,
388
- /ruby/gi
383
+ /ruby/gi,
389
384
  ];
390
-
385
+
391
386
  for (const pattern of patterns) {
392
387
  if (pattern.test(content)) {
393
388
  langs.push(pattern.source.replace(/[^\w]/g, '').toLowerCase());
394
389
  }
395
390
  }
396
-
391
+
397
392
  return [...new Set(langs)];
398
393
  }
399
-
394
+
400
395
  /**
401
396
  * Calculate validation score
402
397
  * @private
403
398
  */
404
399
  calculateScore(issues) {
405
400
  let score = 100;
406
-
401
+
407
402
  const penalties = {
408
403
  [SEVERITY.INFO]: 1,
409
404
  [SEVERITY.WARNING]: 5,
410
405
  [SEVERITY.ERROR]: 15,
411
- [SEVERITY.CRITICAL]: 30
406
+ [SEVERITY.CRITICAL]: 30,
412
407
  };
413
-
408
+
414
409
  for (const issue of issues) {
415
410
  score -= penalties[issue.severity] || 0;
416
411
  }
417
-
412
+
418
413
  return Math.max(0, score);
419
414
  }
420
-
415
+
421
416
  /**
422
417
  * Create validation summary
423
418
  * @private
@@ -426,21 +421,21 @@ class SteeringValidator extends EventEmitter {
426
421
  const bySeverity = {};
427
422
  const byType = {};
428
423
  const byFile = {};
429
-
424
+
430
425
  for (const issue of issues) {
431
426
  bySeverity[issue.severity] = (bySeverity[issue.severity] || 0) + 1;
432
427
  byType[issue.type] = (byType[issue.type] || 0) + 1;
433
428
  byFile[issue.file] = (byFile[issue.file] || 0) + 1;
434
429
  }
435
-
430
+
436
431
  return {
437
432
  totalIssues: issues.length,
438
433
  bySeverity,
439
434
  byType,
440
- byFile
435
+ byFile,
441
436
  };
442
437
  }
443
-
438
+
444
439
  /**
445
440
  * Add custom rule
446
441
  * @param {Object} rule - Validation rule
@@ -449,23 +444,22 @@ class SteeringValidator extends EventEmitter {
449
444
  if (!rule.id || !rule.file || !rule.check) {
450
445
  throw new Error('Rule must have id, file, and check function');
451
446
  }
452
-
447
+
453
448
  this.rules.push({
454
449
  type: RULE_TYPE.COMPLETENESS,
455
450
  severity: SEVERITY.WARNING,
456
- ...rule
451
+ ...rule,
457
452
  });
458
453
  }
459
-
454
+
460
455
  /**
461
456
  * Get validation history
462
457
  * @returns {ValidationResult[]}
463
458
  */
464
459
  getHistory() {
465
- return Array.from(this.validations.values())
466
- .sort((a, b) => b.timestamp - a.timestamp);
460
+ return Array.from(this.validations.values()).sort((a, b) => b.timestamp - a.timestamp);
467
461
  }
468
-
462
+
469
463
  /**
470
464
  * Get statistics
471
465
  * @returns {Object}
@@ -473,18 +467,16 @@ class SteeringValidator extends EventEmitter {
473
467
  getStats() {
474
468
  const validations = Array.from(this.validations.values());
475
469
  const scores = validations.map(v => v.score);
476
-
470
+
477
471
  return {
478
472
  totalValidations: validations.length,
479
- averageScore: scores.length > 0
480
- ? scores.reduce((a, b) => a + b, 0) / scores.length
481
- : 0,
473
+ averageScore: scores.length > 0 ? scores.reduce((a, b) => a + b, 0) / scores.length : 0,
482
474
  passed: validations.filter(v => v.valid).length,
483
475
  failed: validations.filter(v => !v.valid).length,
484
- rulesCount: this.rules.length
476
+ rulesCount: this.rules.length,
485
477
  };
486
478
  }
487
-
479
+
488
480
  /**
489
481
  * Export validation report
490
482
  * @param {string} validationId - Validation ID
@@ -493,29 +485,29 @@ class SteeringValidator extends EventEmitter {
493
485
  exportReport(validationId) {
494
486
  const validation = this.validations.get(validationId);
495
487
  if (!validation) return '';
496
-
488
+
497
489
  let md = `# Steering Validation Report\n\n`;
498
490
  md += `**Status:** ${validation.valid ? '✅ Valid' : '❌ Invalid'}\n`;
499
491
  md += `**Score:** ${validation.score}/100\n`;
500
492
  md += `**Date:** ${new Date(validation.timestamp).toISOString()}\n\n`;
501
-
493
+
502
494
  md += `## Summary\n\n`;
503
495
  md += `- Total Issues: ${validation.issues.length}\n`;
504
496
  for (const [severity, count] of Object.entries(validation.summary.bySeverity)) {
505
497
  md += `- ${severity}: ${count}\n`;
506
498
  }
507
-
499
+
508
500
  if (validation.issues.length > 0) {
509
501
  md += `\n## Issues\n\n`;
510
-
502
+
511
503
  for (const issue of validation.issues) {
512
504
  const icon = {
513
505
  [SEVERITY.INFO]: 'ℹ️',
514
506
  [SEVERITY.WARNING]: '⚠️',
515
507
  [SEVERITY.ERROR]: '❌',
516
- [SEVERITY.CRITICAL]: '🚨'
508
+ [SEVERITY.CRITICAL]: '🚨',
517
509
  }[issue.severity];
518
-
510
+
519
511
  md += `### ${icon} ${issue.message}\n\n`;
520
512
  md += `- **File:** ${issue.file}\n`;
521
513
  md += `- **Type:** ${issue.type}\n`;
@@ -524,7 +516,7 @@ class SteeringValidator extends EventEmitter {
524
516
  md += `\n`;
525
517
  }
526
518
  }
527
-
519
+
528
520
  return md;
529
521
  }
530
522
  }
@@ -543,5 +535,5 @@ module.exports = {
543
535
  createSteeringValidator,
544
536
  SEVERITY,
545
537
  RULE_TYPE,
546
- DEFAULT_VALIDATION_RULES
538
+ DEFAULT_VALIDATION_RULES,
547
539
  };