murmur8 3.5.0
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/.blueprint/agents/AGENT_BA_CASS.md +239 -0
- package/.blueprint/agents/AGENT_DEVELOPER_CODEY.md +308 -0
- package/.blueprint/agents/AGENT_SPECIFICATION_ALEX.md +183 -0
- package/.blueprint/agents/AGENT_TESTER_NIGEL.md +159 -0
- package/.blueprint/agents/GUARDRAILS.md +83 -0
- package/.blueprint/agents/TEAM_MANIFESTO.md +91 -0
- package/.blueprint/features/.gitkeep +0 -0
- package/.blueprint/features/feature_adaptive-retry/FEATURE_SPEC.md +239 -0
- package/.blueprint/features/feature_adaptive-retry/IMPLEMENTATION_PLAN.md +48 -0
- package/.blueprint/features/feature_adaptive-retry/story-prompt-modification.md +85 -0
- package/.blueprint/features/feature_adaptive-retry/story-retry-config.md +89 -0
- package/.blueprint/features/feature_adaptive-retry/story-should-retry.md +98 -0
- package/.blueprint/features/feature_adaptive-retry/story-strategy-recommendation.md +85 -0
- package/.blueprint/features/feature_agent-guardrails/FEATURE_SPEC.md +328 -0
- package/.blueprint/features/feature_agent-guardrails/IMPLEMENTATION_PLAN.md +90 -0
- package/.blueprint/features/feature_agent-guardrails/story-citation-requirements.md +50 -0
- package/.blueprint/features/feature_agent-guardrails/story-confidentiality.md +50 -0
- package/.blueprint/features/feature_agent-guardrails/story-escalation-protocol.md +55 -0
- package/.blueprint/features/feature_agent-guardrails/story-source-restrictions.md +50 -0
- package/.blueprint/features/feature_compressed-feedback/FEATURE_SPEC.md +136 -0
- package/.blueprint/features/feature_compressed-feedback/IMPLEMENTATION_PLAN.md +40 -0
- package/.blueprint/features/feature_feedback-loop/FEATURE_SPEC.md +347 -0
- package/.blueprint/features/feature_feedback-loop/IMPLEMENTATION_PLAN.md +71 -0
- package/.blueprint/features/feature_feedback-loop/story-feedback-collection.md +63 -0
- package/.blueprint/features/feature_feedback-loop/story-feedback-config.md +61 -0
- package/.blueprint/features/feature_feedback-loop/story-feedback-insights.md +63 -0
- package/.blueprint/features/feature_feedback-loop/story-quality-gates.md +57 -0
- package/.blueprint/features/feature_interactive-alex/FEATURE_SPEC.md +263 -0
- package/.blueprint/features/feature_interactive-alex/IMPLEMENTATION_PLAN.md +69 -0
- package/.blueprint/features/feature_interactive-alex/handoff-alex.md +19 -0
- package/.blueprint/features/feature_interactive-alex/handoff-cass.md +21 -0
- package/.blueprint/features/feature_interactive-alex/handoff-nigel.md +19 -0
- package/.blueprint/features/feature_interactive-alex/story-flag-routing.md +54 -0
- package/.blueprint/features/feature_interactive-alex/story-iterative-drafting.md +65 -0
- package/.blueprint/features/feature_interactive-alex/story-pipeline-integration.md +66 -0
- package/.blueprint/features/feature_interactive-alex/story-session-lifecycle.md +75 -0
- package/.blueprint/features/feature_interactive-alex/story-system-spec-creation.md +57 -0
- package/.blueprint/features/feature_lazy-business-context/FEATURE_SPEC.md +140 -0
- package/.blueprint/features/feature_lazy-business-context/IMPLEMENTATION_PLAN.md +54 -0
- package/.blueprint/features/feature_model-native-features/FEATURE_SPEC.md +174 -0
- package/.blueprint/features/feature_model-native-features/IMPLEMENTATION_PLAN.md +45 -0
- package/.blueprint/features/feature_parallel-abort/FEATURE_SPEC.md +117 -0
- package/.blueprint/features/feature_parallel-confirm/FEATURE_SPEC.md +90 -0
- package/.blueprint/features/feature_parallel-features/FEATURE_SPEC.md +291 -0
- package/.blueprint/features/feature_parallel-features/IMPLEMENTATION_PLAN.md +73 -0
- package/.blueprint/features/feature_parallel-lock/FEATURE_SPEC.md +119 -0
- package/.blueprint/features/feature_parallel-logging/FEATURE_SPEC.md +105 -0
- package/.blueprint/features/feature_parallel-preflight/FEATURE_SPEC.md +141 -0
- package/.blueprint/features/feature_pipeline-history/FEATURE_SPEC.md +239 -0
- package/.blueprint/features/feature_pipeline-history/IMPLEMENTATION_PLAN.md +71 -0
- package/.blueprint/features/feature_pipeline-history/story-clear-history.md +73 -0
- package/.blueprint/features/feature_pipeline-history/story-display-history.md +75 -0
- package/.blueprint/features/feature_pipeline-history/story-record-execution.md +76 -0
- package/.blueprint/features/feature_pipeline-history/story-show-statistics.md +85 -0
- package/.blueprint/features/feature_pipeline-insights/FEATURE_SPEC.md +288 -0
- package/.blueprint/features/feature_pipeline-insights/IMPLEMENTATION_PLAN.md +65 -0
- package/.blueprint/features/feature_pipeline-insights/story-anomaly-detection.md +71 -0
- package/.blueprint/features/feature_pipeline-insights/story-bottleneck-analysis.md +75 -0
- package/.blueprint/features/feature_pipeline-insights/story-failure-patterns.md +75 -0
- package/.blueprint/features/feature_pipeline-insights/story-json-output.md +75 -0
- package/.blueprint/features/feature_pipeline-insights/story-trend-analysis.md +78 -0
- package/.blueprint/features/feature_shared-guardrails/FEATURE_SPEC.md +119 -0
- package/.blueprint/features/feature_shared-guardrails/IMPLEMENTATION_PLAN.md +34 -0
- package/.blueprint/features/feature_shared-guardrails/story-extract-guardrails.md +60 -0
- package/.blueprint/features/feature_shared-guardrails/story-update-init-commands.md +63 -0
- package/.blueprint/features/feature_slim-agent-prompts/FEATURE_SPEC.md +145 -0
- package/.blueprint/features/feature_slim-agent-prompts/IMPLEMENTATION_PLAN.md +87 -0
- package/.blueprint/features/feature_slim-agent-prompts/story-create-runtime-prompt-template.md +59 -0
- package/.blueprint/features/feature_slim-agent-prompts/story-create-slim-agent-prompts.md +65 -0
- package/.blueprint/features/feature_slim-agent-prompts/story-skill-integration.md +53 -0
- package/.blueprint/features/feature_smart-story-routing/FEATURE_SPEC.md +147 -0
- package/.blueprint/features/feature_smart-story-routing/IMPLEMENTATION_PLAN.md +73 -0
- package/.blueprint/features/feature_template-extraction/FEATURE_SPEC.md +134 -0
- package/.blueprint/features/feature_template-extraction/IMPLEMENTATION_PLAN.md +46 -0
- package/.blueprint/features/feature_upstream-summaries/FEATURE_SPEC.md +150 -0
- package/.blueprint/features/feature_upstream-summaries/IMPLEMENTATION_PLAN.md +70 -0
- package/.blueprint/features/feature_validate-command/FEATURE_SPEC.md +209 -0
- package/.blueprint/features/feature_validate-command/IMPLEMENTATION_PLAN.md +59 -0
- package/.blueprint/features/feature_validate-command/story-failure-output.md +61 -0
- package/.blueprint/features/feature_validate-command/story-node-version-check.md +52 -0
- package/.blueprint/features/feature_validate-command/story-run-validation.md +59 -0
- package/.blueprint/features/feature_validate-command/story-success-output.md +50 -0
- package/.blueprint/prompts/TEMPLATE.md +65 -0
- package/.blueprint/prompts/alex-runtime.md +49 -0
- package/.blueprint/prompts/cass-runtime.md +46 -0
- package/.blueprint/prompts/codey-implement-runtime.md +52 -0
- package/.blueprint/prompts/codey-plan-runtime.md +47 -0
- package/.blueprint/prompts/nigel-runtime.md +47 -0
- package/.blueprint/system_specification/.gitkeep +0 -0
- package/.blueprint/system_specification/SYSTEM_SPEC.md +248 -0
- package/.blueprint/templates/FEATURE_SPEC.md +125 -0
- package/.blueprint/templates/STORY_TEMPLATE.md +96 -0
- package/.blueprint/templates/SYSTEM_SPEC.md +128 -0
- package/.blueprint/templates/TEST_TEMPLATE.md +76 -0
- package/.blueprint/ways_of_working/DEVELOPMENT_RITUAL.md +178 -0
- package/.business_context/README.md +27 -0
- package/LICENSE +21 -0
- package/README.md +564 -0
- package/SKILL.md +840 -0
- package/bin/cli.js +388 -0
- package/package.json +36 -0
- package/src/business-context.js +91 -0
- package/src/classifier.js +173 -0
- package/src/feedback.js +201 -0
- package/src/handoff.js +148 -0
- package/src/history.js +306 -0
- package/src/index.js +170 -0
- package/src/init.js +139 -0
- package/src/insights.js +504 -0
- package/src/interactive.js +338 -0
- package/src/orchestrator.js +217 -0
- package/src/parallel.js +1544 -0
- package/src/retry.js +274 -0
- package/src/stack.js +320 -0
- package/src/tools/index.js +27 -0
- package/src/tools/prompts.js +45 -0
- package/src/tools/schemas.js +38 -0
- package/src/tools/validation.js +83 -0
- package/src/update.js +112 -0
- package/src/validate.js +172 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Input Validation Utilities
|
|
3
|
+
* Validates inputs against tool schema constraints
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Validate tool input against a schema
|
|
8
|
+
* @param {Object} schema - Tool schema with input_schema
|
|
9
|
+
* @param {Object} input - Input to validate
|
|
10
|
+
* @returns {{ valid: boolean, errors: string[] }}
|
|
11
|
+
*/
|
|
12
|
+
function validateToolInput(schema, input) {
|
|
13
|
+
const errors = [];
|
|
14
|
+
const props = schema.input_schema.properties;
|
|
15
|
+
const required = schema.input_schema.required || [];
|
|
16
|
+
|
|
17
|
+
// Check required fields
|
|
18
|
+
for (const field of required) {
|
|
19
|
+
if (!(field in input)) {
|
|
20
|
+
errors.push(`missing required field: ${field}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Validate each field
|
|
25
|
+
for (const [key, value] of Object.entries(input)) {
|
|
26
|
+
const propSchema = props[key];
|
|
27
|
+
if (!propSchema) continue;
|
|
28
|
+
|
|
29
|
+
// Type: number with bounds
|
|
30
|
+
if (propSchema.type === 'number') {
|
|
31
|
+
if (typeof value !== 'number') {
|
|
32
|
+
errors.push(`${key} must be number`);
|
|
33
|
+
} else {
|
|
34
|
+
if (propSchema.minimum !== undefined && value < propSchema.minimum) {
|
|
35
|
+
errors.push(`${key} below minimum ${propSchema.minimum}`);
|
|
36
|
+
}
|
|
37
|
+
if (propSchema.maximum !== undefined && value > propSchema.maximum) {
|
|
38
|
+
errors.push(`${key} above maximum ${propSchema.maximum}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Type: array
|
|
44
|
+
if (propSchema.type === 'array') {
|
|
45
|
+
if (!Array.isArray(value)) {
|
|
46
|
+
errors.push(`${key} must be array`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Type: string with maxLength
|
|
51
|
+
if (propSchema.type === 'string') {
|
|
52
|
+
if (typeof value !== 'string') {
|
|
53
|
+
errors.push(`${key} must be string`);
|
|
54
|
+
} else if (propSchema.maxLength && value.length > propSchema.maxLength) {
|
|
55
|
+
errors.push(`${key} exceeds maxLength ${propSchema.maxLength}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Enum constraint
|
|
60
|
+
if (propSchema.enum && !propSchema.enum.includes(value)) {
|
|
61
|
+
errors.push(`${key} must be one of: ${propSchema.enum.join(', ')}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return { valid: errors.length === 0, errors };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Normalize feedback input to handle "rec" shorthand for "recommendation"
|
|
70
|
+
* @param {Object} input - Raw feedback input
|
|
71
|
+
* @returns {Object} - Normalized input
|
|
72
|
+
*/
|
|
73
|
+
function normalizeFeedbackInput(input) {
|
|
74
|
+
if (input.rec && !input.recommendation) {
|
|
75
|
+
return { ...input, recommendation: input.rec };
|
|
76
|
+
}
|
|
77
|
+
return input;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
validateToolInput,
|
|
82
|
+
normalizeFeedbackInput
|
|
83
|
+
};
|
package/src/update.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
|
|
5
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
6
|
+
const TARGET_DIR = process.cwd();
|
|
7
|
+
|
|
8
|
+
// Directories that contain user content and should NOT be overwritten
|
|
9
|
+
const USER_CONTENT_DIRS = [
|
|
10
|
+
'features',
|
|
11
|
+
'system_specification'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// Directories/files that should be updated
|
|
15
|
+
const UPDATABLE = [
|
|
16
|
+
'agents',
|
|
17
|
+
'templates',
|
|
18
|
+
'ways_of_working'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
async function prompt(question) {
|
|
22
|
+
const rl = readline.createInterface({
|
|
23
|
+
input: process.stdin,
|
|
24
|
+
output: process.stdout
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
rl.question(question, (answer) => {
|
|
29
|
+
rl.close();
|
|
30
|
+
resolve(answer.toLowerCase().trim());
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function copyDir(src, dest) {
|
|
36
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
37
|
+
|
|
38
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
39
|
+
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
const srcPath = path.join(src, entry.name);
|
|
42
|
+
const destPath = path.join(dest, entry.name);
|
|
43
|
+
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
copyDir(srcPath, destPath);
|
|
46
|
+
} else {
|
|
47
|
+
fs.copyFileSync(srcPath, destPath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function update() {
|
|
53
|
+
const blueprintDest = path.join(TARGET_DIR, '.blueprint');
|
|
54
|
+
const blueprintSrc = path.join(PACKAGE_ROOT, '.blueprint');
|
|
55
|
+
const skillSrc = path.join(PACKAGE_ROOT, 'SKILL.md');
|
|
56
|
+
const skillDest = path.join(TARGET_DIR, 'SKILL.md');
|
|
57
|
+
|
|
58
|
+
// Check if .blueprint exists
|
|
59
|
+
if (!fs.existsSync(blueprintDest)) {
|
|
60
|
+
console.log('.blueprint directory not found. Run "agent-workflow init" first.');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('Updating agent-workflow...');
|
|
65
|
+
console.log('(Preserving: features/, system_specification/)\n');
|
|
66
|
+
|
|
67
|
+
// Update each updatable directory
|
|
68
|
+
for (const dir of UPDATABLE) {
|
|
69
|
+
const srcDir = path.join(blueprintSrc, dir);
|
|
70
|
+
const destDir = path.join(blueprintDest, dir);
|
|
71
|
+
|
|
72
|
+
if (fs.existsSync(srcDir)) {
|
|
73
|
+
if (fs.existsSync(destDir)) {
|
|
74
|
+
fs.rmSync(destDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
copyDir(srcDir, destDir);
|
|
77
|
+
console.log(`Updated .blueprint/${dir}/`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Update SKILL.md and .claude/commands/implement-feature.md
|
|
82
|
+
const answer = await prompt('\nUpdate SKILL.md and .claude/commands/implement-feature.md? (Y/n): ');
|
|
83
|
+
if (answer !== 'n' && answer !== 'no') {
|
|
84
|
+
fs.copyFileSync(skillSrc, skillDest);
|
|
85
|
+
console.log('Updated SKILL.md');
|
|
86
|
+
|
|
87
|
+
// Also update the Claude Code skill command
|
|
88
|
+
const skillCommandDest = path.join(TARGET_DIR, '.claude', 'commands', 'implement-feature.md');
|
|
89
|
+
if (fs.existsSync(path.dirname(skillCommandDest))) {
|
|
90
|
+
fs.copyFileSync(skillSrc, skillCommandDest);
|
|
91
|
+
console.log('Updated .claude/commands/implement-feature.md');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(`
|
|
96
|
+
Update complete!
|
|
97
|
+
|
|
98
|
+
Updated:
|
|
99
|
+
- .blueprint/agents/
|
|
100
|
+
- .blueprint/templates/
|
|
101
|
+
- .blueprint/ways_of_working/
|
|
102
|
+
- SKILL.md
|
|
103
|
+
- .claude/commands/implement-feature.md (if exists)
|
|
104
|
+
|
|
105
|
+
Preserved:
|
|
106
|
+
- .blueprint/features/
|
|
107
|
+
- .blueprint/system_specification/
|
|
108
|
+
- .business_context/
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { update };
|
package/src/validate.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const REQUIRED_DIRS = ['.blueprint', '.business_context', '.claude/commands'];
|
|
5
|
+
const AGENT_FILES = [
|
|
6
|
+
'AGENT_SPECIFICATION_ALEX.md',
|
|
7
|
+
'AGENT_BA_CASS.md',
|
|
8
|
+
'AGENT_TESTER_NIGEL.md',
|
|
9
|
+
'AGENT_DEVELOPER_CODEY.md'
|
|
10
|
+
];
|
|
11
|
+
const SYSTEM_SPEC_PATH = '.blueprint/system_specification/SYSTEM_SPEC.md';
|
|
12
|
+
const SKILL_PATH = '.claude/commands/implement-feature.md';
|
|
13
|
+
const MIN_NODE_VERSION = 18;
|
|
14
|
+
|
|
15
|
+
function checkDirectories() {
|
|
16
|
+
const missing = REQUIRED_DIRS.filter(dir => !fs.existsSync(dir));
|
|
17
|
+
const passed = missing.length === 0;
|
|
18
|
+
return {
|
|
19
|
+
name: 'Required directories',
|
|
20
|
+
passed,
|
|
21
|
+
message: passed
|
|
22
|
+
? 'All required directories exist'
|
|
23
|
+
: `Missing directories: ${missing.join(', ')}`,
|
|
24
|
+
fix: passed ? null : 'Run `murmur8 init` to initialize project'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function checkSystemSpec() {
|
|
29
|
+
const exists = fs.existsSync(SYSTEM_SPEC_PATH);
|
|
30
|
+
return {
|
|
31
|
+
name: 'System specification',
|
|
32
|
+
passed: exists,
|
|
33
|
+
message: exists
|
|
34
|
+
? 'System specification exists'
|
|
35
|
+
: `Missing: ${SYSTEM_SPEC_PATH}`,
|
|
36
|
+
fix: exists ? null : 'Run `murmur8 init` to create system specification'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function checkAgentSpecs() {
|
|
41
|
+
const agentsDir = '.blueprint/agents';
|
|
42
|
+
if (!fs.existsSync(agentsDir)) {
|
|
43
|
+
return {
|
|
44
|
+
name: 'agent specifications',
|
|
45
|
+
passed: false,
|
|
46
|
+
message: 'Missing: .blueprint/agents directory',
|
|
47
|
+
fix: 'Run `murmur8 init` to create agent specification files'
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const missing = AGENT_FILES.filter(f => !fs.existsSync(path.join(agentsDir, f)));
|
|
52
|
+
const passed = missing.length === 0;
|
|
53
|
+
return {
|
|
54
|
+
name: 'agent specifications',
|
|
55
|
+
passed,
|
|
56
|
+
message: passed
|
|
57
|
+
? 'All agent specifications exist'
|
|
58
|
+
: `Missing agent files: ${missing.join(', ')}`,
|
|
59
|
+
fix: passed ? null : 'Run `murmur8 init` to create agent specification files'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function checkBusinessContext() {
|
|
64
|
+
const dir = '.business_context';
|
|
65
|
+
if (!fs.existsSync(dir)) {
|
|
66
|
+
return {
|
|
67
|
+
name: 'business context',
|
|
68
|
+
passed: false,
|
|
69
|
+
message: 'Missing: .business_context directory',
|
|
70
|
+
fix: 'Run `murmur8 init` to create .business_context directory'
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let files;
|
|
75
|
+
try {
|
|
76
|
+
files = fs.readdirSync(dir).filter(f => !f.startsWith('.'));
|
|
77
|
+
} catch {
|
|
78
|
+
files = [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const passed = files.length > 0;
|
|
82
|
+
return {
|
|
83
|
+
name: 'business context',
|
|
84
|
+
passed,
|
|
85
|
+
message: passed
|
|
86
|
+
? 'Business context directory has content'
|
|
87
|
+
: 'Business context directory is empty',
|
|
88
|
+
fix: passed ? null : 'Add at least one file to `.business_context/` directory'
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function checkSkillsInstalled() {
|
|
93
|
+
const exists = fs.existsSync(SKILL_PATH);
|
|
94
|
+
return {
|
|
95
|
+
name: 'skills installed',
|
|
96
|
+
passed: exists,
|
|
97
|
+
message: exists
|
|
98
|
+
? 'Required skills are installed'
|
|
99
|
+
: `Missing: ${SKILL_PATH}`,
|
|
100
|
+
fix: exists ? null : 'Run `murmur8 init` to install required skills'
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function checkNodeVersion() {
|
|
105
|
+
const versionStr = process.version;
|
|
106
|
+
const majorVersion = parseInt(versionStr.slice(1).split('.')[0], 10);
|
|
107
|
+
const passed = majorVersion >= MIN_NODE_VERSION;
|
|
108
|
+
return {
|
|
109
|
+
name: 'Node.js version',
|
|
110
|
+
passed,
|
|
111
|
+
message: passed
|
|
112
|
+
? `Node.js ${majorVersion} meets minimum requirement (>=${MIN_NODE_VERSION})`
|
|
113
|
+
: `Node.js ${majorVersion} is below minimum requirement (>=${MIN_NODE_VERSION})`,
|
|
114
|
+
fix: passed ? null : `Upgrade Node.js to version ${MIN_NODE_VERSION} or higher`,
|
|
115
|
+
detectedVersion: versionStr
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function validate() {
|
|
120
|
+
const checks = [
|
|
121
|
+
checkDirectories(),
|
|
122
|
+
checkSystemSpec(),
|
|
123
|
+
checkAgentSpecs(),
|
|
124
|
+
checkBusinessContext(),
|
|
125
|
+
checkSkillsInstalled(),
|
|
126
|
+
checkNodeVersion()
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
const success = checks.every(c => c.passed);
|
|
130
|
+
const exitCode = success ? 0 : 1;
|
|
131
|
+
|
|
132
|
+
return { success, exitCode, checks };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function formatOutput(result, useColor = false) {
|
|
136
|
+
const lines = [];
|
|
137
|
+
|
|
138
|
+
const green = useColor ? '\x1b[32m' : '';
|
|
139
|
+
const red = useColor ? '\x1b[31m' : '';
|
|
140
|
+
const reset = useColor ? '\x1b[0m' : '';
|
|
141
|
+
|
|
142
|
+
const passIndicator = useColor ? `${green}\u2713${reset}` : '[PASS]';
|
|
143
|
+
const failIndicator = useColor ? `${red}\u2717${reset}` : '[FAIL]';
|
|
144
|
+
|
|
145
|
+
for (const check of result.checks) {
|
|
146
|
+
const indicator = check.passed ? passIndicator : failIndicator;
|
|
147
|
+
lines.push(`${indicator} ${check.name}: ${check.message}`);
|
|
148
|
+
if (!check.passed && check.fix) {
|
|
149
|
+
lines.push(` Fix: ${check.fix}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
lines.push('');
|
|
154
|
+
if (result.success) {
|
|
155
|
+
lines.push(useColor
|
|
156
|
+
? `${green}All checks passed. Project is ready.${reset}`
|
|
157
|
+
: 'All checks passed. Project is ready.');
|
|
158
|
+
} else {
|
|
159
|
+
const failedCount = result.checks.filter(c => !c.passed).length;
|
|
160
|
+
lines.push(useColor
|
|
161
|
+
? `${red}${failedCount} check(s) failed.${reset}`
|
|
162
|
+
: `${failedCount} check(s) failed.`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return lines.join('\n');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = {
|
|
169
|
+
validate,
|
|
170
|
+
formatOutput,
|
|
171
|
+
checkNodeVersion
|
|
172
|
+
};
|