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
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
106
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
};
|