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
package/bin/cli.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { init } = require('../src/init');
|
|
4
|
+
const { update } = require('../src/update');
|
|
5
|
+
const { displayQueue, resetQueue } = require('../src/orchestrator');
|
|
6
|
+
const { validate, formatOutput } = require('../src/validate');
|
|
7
|
+
const { displayHistory, showStats, clearHistory } = require('../src/history');
|
|
8
|
+
const { displayInsights } = require('../src/insights');
|
|
9
|
+
const { displayConfig, setConfigValue, resetConfig } = require('../src/retry');
|
|
10
|
+
const {
|
|
11
|
+
displayConfig: displayFeedbackConfig,
|
|
12
|
+
setConfigValue: setFeedbackConfigValue,
|
|
13
|
+
resetConfig: resetFeedbackConfig
|
|
14
|
+
} = require('../src/feedback');
|
|
15
|
+
const {
|
|
16
|
+
displayStackConfig,
|
|
17
|
+
setStackConfigValue,
|
|
18
|
+
resetStackConfig
|
|
19
|
+
} = require('../src/stack');
|
|
20
|
+
const { displayFeedbackInsights } = require('../src/insights');
|
|
21
|
+
const {
|
|
22
|
+
formatStatus,
|
|
23
|
+
getDefaultConfig,
|
|
24
|
+
splitByLimit,
|
|
25
|
+
runParallel,
|
|
26
|
+
loadQueue,
|
|
27
|
+
cleanupWorktrees,
|
|
28
|
+
readParallelConfig,
|
|
29
|
+
writeParallelConfig,
|
|
30
|
+
getDefaultParallelConfig,
|
|
31
|
+
abortParallel,
|
|
32
|
+
getLockInfo,
|
|
33
|
+
getDetailedStatus,
|
|
34
|
+
formatDetailedStatus,
|
|
35
|
+
rollbackParallel
|
|
36
|
+
} = require('../src/parallel');
|
|
37
|
+
|
|
38
|
+
const args = process.argv.slice(2);
|
|
39
|
+
const command = args[0];
|
|
40
|
+
const subArg = args[1];
|
|
41
|
+
|
|
42
|
+
function parseFlags(args) {
|
|
43
|
+
const flags = {};
|
|
44
|
+
for (const arg of args) {
|
|
45
|
+
if (arg === '--all') flags.all = true;
|
|
46
|
+
if (arg === '--stats') flags.stats = true;
|
|
47
|
+
if (arg === '--force') flags.force = true;
|
|
48
|
+
if (arg === '--bottlenecks') flags.bottlenecks = true;
|
|
49
|
+
if (arg === '--failures') flags.failures = true;
|
|
50
|
+
if (arg === '--json') flags.json = true;
|
|
51
|
+
if (arg === '--feedback') flags.feedback = true;
|
|
52
|
+
}
|
|
53
|
+
return flags;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const commands = {
|
|
57
|
+
init: {
|
|
58
|
+
fn: init,
|
|
59
|
+
description: 'Initialize .blueprint directory in current project'
|
|
60
|
+
},
|
|
61
|
+
update: {
|
|
62
|
+
fn: update,
|
|
63
|
+
description: 'Update agents, templates, and rituals (preserves your content)'
|
|
64
|
+
},
|
|
65
|
+
queue: {
|
|
66
|
+
fn: () => {
|
|
67
|
+
if (subArg === 'reset') {
|
|
68
|
+
resetQueue();
|
|
69
|
+
console.log('Queue has been reset.');
|
|
70
|
+
} else {
|
|
71
|
+
displayQueue();
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
description: 'Show queue status (use "reset" to clear)'
|
|
75
|
+
},
|
|
76
|
+
validate: {
|
|
77
|
+
fn: async () => {
|
|
78
|
+
const result = await validate();
|
|
79
|
+
const useColor = process.stdout.isTTY || false;
|
|
80
|
+
console.log(formatOutput(result, useColor));
|
|
81
|
+
process.exit(result.exitCode);
|
|
82
|
+
},
|
|
83
|
+
description: 'Run pre-flight checks to validate project configuration'
|
|
84
|
+
},
|
|
85
|
+
history: {
|
|
86
|
+
fn: async () => {
|
|
87
|
+
const flags = parseFlags(args);
|
|
88
|
+
if (subArg === 'clear') {
|
|
89
|
+
await clearHistory({ force: flags.force });
|
|
90
|
+
} else if (flags.stats) {
|
|
91
|
+
showStats();
|
|
92
|
+
} else {
|
|
93
|
+
displayHistory({ all: flags.all });
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
description: 'View pipeline execution history'
|
|
97
|
+
},
|
|
98
|
+
insights: {
|
|
99
|
+
fn: () => {
|
|
100
|
+
const flags = parseFlags(args);
|
|
101
|
+
if (flags.feedback) {
|
|
102
|
+
displayFeedbackInsights({ json: flags.json });
|
|
103
|
+
} else {
|
|
104
|
+
displayInsights({
|
|
105
|
+
bottlenecks: flags.bottlenecks,
|
|
106
|
+
failures: flags.failures,
|
|
107
|
+
json: flags.json
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
description: 'Analyze pipeline history for bottlenecks, failures, and trends'
|
|
112
|
+
},
|
|
113
|
+
'retry-config': {
|
|
114
|
+
fn: () => {
|
|
115
|
+
if (subArg === 'set') {
|
|
116
|
+
const key = args[2];
|
|
117
|
+
const value = args[3];
|
|
118
|
+
if (!key || !value) {
|
|
119
|
+
console.error('Usage: retry-config set <key> <value>');
|
|
120
|
+
console.error('Valid keys: maxRetries, windowSize, highFailureThreshold');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
setConfigValue(key, value);
|
|
124
|
+
} else if (subArg === 'reset') {
|
|
125
|
+
resetConfig();
|
|
126
|
+
console.log('Retry configuration reset to defaults.');
|
|
127
|
+
} else {
|
|
128
|
+
displayConfig();
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
description: 'Manage retry configuration for adaptive retry logic'
|
|
132
|
+
},
|
|
133
|
+
'feedback-config': {
|
|
134
|
+
fn: () => {
|
|
135
|
+
if (subArg === 'set') {
|
|
136
|
+
const key = args[2];
|
|
137
|
+
const value = args[3];
|
|
138
|
+
if (!key || !value) {
|
|
139
|
+
console.error('Usage: feedback-config set <key> <value>');
|
|
140
|
+
console.error('Valid keys: minRatingThreshold, enabled');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
setFeedbackConfigValue(key, value);
|
|
144
|
+
} else if (subArg === 'reset') {
|
|
145
|
+
resetFeedbackConfig();
|
|
146
|
+
console.log('Feedback configuration reset to defaults.');
|
|
147
|
+
} else {
|
|
148
|
+
displayFeedbackConfig();
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
description: 'Manage feedback loop configuration'
|
|
152
|
+
},
|
|
153
|
+
'stack-config': {
|
|
154
|
+
fn: () => {
|
|
155
|
+
if (subArg === 'set') {
|
|
156
|
+
const key = args[2];
|
|
157
|
+
const value = args[3];
|
|
158
|
+
if (!key || !value) {
|
|
159
|
+
console.error('Usage: stack-config set <key> <value>');
|
|
160
|
+
console.error('Valid keys: language, runtime, packageManager, frameworks, testRunner, testCommand, linter, tools');
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
setStackConfigValue(key, value);
|
|
164
|
+
} else if (subArg === 'reset') {
|
|
165
|
+
resetStackConfig();
|
|
166
|
+
console.log('Stack configuration reset to defaults.');
|
|
167
|
+
} else {
|
|
168
|
+
displayStackConfig();
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
description: 'View or modify project tech stack configuration'
|
|
172
|
+
},
|
|
173
|
+
'parallel-config': {
|
|
174
|
+
fn: () => {
|
|
175
|
+
if (subArg === 'set') {
|
|
176
|
+
const key = args[2];
|
|
177
|
+
const value = args[3];
|
|
178
|
+
if (!key || !value) {
|
|
179
|
+
console.error('Usage: parallel-config set <key> <value>');
|
|
180
|
+
console.error('Valid keys: cli, skill, skillFlags, worktreeDir, maxConcurrency, queueFile');
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
const config = readParallelConfig();
|
|
184
|
+
if (key === 'maxConcurrency') {
|
|
185
|
+
config[key] = parseInt(value, 10);
|
|
186
|
+
} else {
|
|
187
|
+
config[key] = value;
|
|
188
|
+
}
|
|
189
|
+
writeParallelConfig(config);
|
|
190
|
+
console.log(`Set ${key} = ${value}`);
|
|
191
|
+
} else if (subArg === 'reset') {
|
|
192
|
+
writeParallelConfig(getDefaultParallelConfig());
|
|
193
|
+
console.log('Parallel configuration reset to defaults.');
|
|
194
|
+
} else {
|
|
195
|
+
const config = readParallelConfig();
|
|
196
|
+
console.log('Parallel Configuration\n');
|
|
197
|
+
console.log(` cli: ${config.cli}`);
|
|
198
|
+
console.log(` skill: ${config.skill}`);
|
|
199
|
+
console.log(` skillFlags: ${config.skillFlags}`);
|
|
200
|
+
console.log(` worktreeDir: ${config.worktreeDir}`);
|
|
201
|
+
console.log(` maxConcurrency: ${config.maxConcurrency}`);
|
|
202
|
+
console.log(` maxFeatures: ${config.maxFeatures}`);
|
|
203
|
+
console.log(` timeout: ${config.timeout} min`);
|
|
204
|
+
console.log(` minDiskSpaceMB: ${config.minDiskSpaceMB}`);
|
|
205
|
+
console.log(` queueFile: ${config.queueFile}`);
|
|
206
|
+
console.log('\nTo change: murmur8 parallel-config set <key> <value>');
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
description: 'View or modify parallel pipeline configuration'
|
|
210
|
+
},
|
|
211
|
+
parallel: {
|
|
212
|
+
fn: async () => {
|
|
213
|
+
if (subArg === 'status') {
|
|
214
|
+
const detailed = args.includes('--detailed') || args.includes('-d');
|
|
215
|
+
const lock = getLockInfo();
|
|
216
|
+
|
|
217
|
+
if (detailed) {
|
|
218
|
+
const details = getDetailedStatus();
|
|
219
|
+
console.log(formatDetailedStatus(details));
|
|
220
|
+
} else {
|
|
221
|
+
const queue = loadQueue();
|
|
222
|
+
|
|
223
|
+
if (!queue.features || queue.features.length === 0) {
|
|
224
|
+
if (lock) {
|
|
225
|
+
console.log(`Parallel execution in progress (PID: ${lock.pid})`);
|
|
226
|
+
console.log(`Started: ${lock.startedAt}`);
|
|
227
|
+
console.log(`Features: ${lock.features.join(', ')}`);
|
|
228
|
+
} else {
|
|
229
|
+
console.log('No parallel pipelines active.');
|
|
230
|
+
}
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log('Parallel Pipeline Status\n');
|
|
235
|
+
console.log(formatStatus(queue.features));
|
|
236
|
+
const summary = {
|
|
237
|
+
running: queue.features.filter(f => f.status === 'parallel_running').length,
|
|
238
|
+
pending: queue.features.filter(f => f.status === 'parallel_queued').length,
|
|
239
|
+
completed: queue.features.filter(f => f.status === 'parallel_complete').length,
|
|
240
|
+
failed: queue.features.filter(f => f.status === 'parallel_failed').length,
|
|
241
|
+
conflicts: queue.features.filter(f => f.status === 'merge_conflict').length
|
|
242
|
+
};
|
|
243
|
+
console.log(`\nRunning: ${summary.running} | Pending: ${summary.pending} | Completed: ${summary.completed} | Failed: ${summary.failed} | Conflicts: ${summary.conflicts}`);
|
|
244
|
+
|
|
245
|
+
// Show log paths for running/failed
|
|
246
|
+
const withLogs = queue.features.filter(f =>
|
|
247
|
+
f.logPath && (f.status === 'parallel_running' || f.status === 'parallel_failed')
|
|
248
|
+
);
|
|
249
|
+
if (withLogs.length > 0) {
|
|
250
|
+
console.log('\nLog files:');
|
|
251
|
+
withLogs.forEach(f => console.log(` ${f.slug}: ${f.logPath}`));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log('\nTip: Use --detailed for progress bars');
|
|
255
|
+
}
|
|
256
|
+
} else if (subArg === 'rollback') {
|
|
257
|
+
const dryRunFlag = args.includes('--dry-run');
|
|
258
|
+
const forceFlag = args.includes('--force');
|
|
259
|
+
await rollbackParallel({ dryRun: dryRunFlag, force: forceFlag });
|
|
260
|
+
} else if (subArg === 'cleanup') {
|
|
261
|
+
const cleaned = await cleanupWorktrees();
|
|
262
|
+
console.log(`Cleaned ${cleaned} worktree(s).`);
|
|
263
|
+
} else if (subArg === 'abort') {
|
|
264
|
+
const cleanupFlag = args.includes('--cleanup');
|
|
265
|
+
await abortParallel({ cleanup: cleanupFlag });
|
|
266
|
+
} else {
|
|
267
|
+
const slugs = args.slice(1).filter(a => !a.startsWith('--') && !a.startsWith('-'));
|
|
268
|
+
if (slugs.length === 0) {
|
|
269
|
+
console.error('Usage: murmur8 parallel <slug1> <slug2> ... [options]');
|
|
270
|
+
console.error('\nOptions:');
|
|
271
|
+
console.error(' --dry-run Preview execution plan without running');
|
|
272
|
+
console.error(' --yes, -y Skip confirmation prompt');
|
|
273
|
+
console.error(' --force Override existing lock');
|
|
274
|
+
console.error(' --verbose Stream output to console (not just logs)');
|
|
275
|
+
console.error(' --skip-preflight Skip feature validation checks');
|
|
276
|
+
console.error(' --max-concurrency=N Set max parallel pipelines (default: 3)');
|
|
277
|
+
console.error('\nSubcommands:');
|
|
278
|
+
console.error(' parallel status Show status of all pipelines');
|
|
279
|
+
console.error(' parallel abort Stop all running pipelines');
|
|
280
|
+
console.error(' parallel cleanup Remove completed/aborted worktrees');
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const maxFlag = args.find(a => a.startsWith('--max-concurrency='));
|
|
285
|
+
const options = {
|
|
286
|
+
dryRun: args.includes('--dry-run'),
|
|
287
|
+
yes: args.includes('--yes') || args.includes('-y'),
|
|
288
|
+
force: args.includes('--force'),
|
|
289
|
+
verbose: args.includes('--verbose'),
|
|
290
|
+
skipPreflight: args.includes('--skip-preflight')
|
|
291
|
+
};
|
|
292
|
+
if (maxFlag) {
|
|
293
|
+
options.maxConcurrency = parseInt(maxFlag.split('=')[1], 10);
|
|
294
|
+
}
|
|
295
|
+
const result = await runParallel(slugs, options);
|
|
296
|
+
process.exit(result.success ? 0 : 1);
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
description: 'Run multiple feature pipelines in parallel using git worktrees'
|
|
300
|
+
},
|
|
301
|
+
help: {
|
|
302
|
+
fn: showHelp,
|
|
303
|
+
description: 'Show this help message'
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
function showHelp() {
|
|
308
|
+
console.log(`
|
|
309
|
+
murmur8 - Multi-agent workflow framework
|
|
310
|
+
|
|
311
|
+
Usage: murmur8 <command> [options]
|
|
312
|
+
|
|
313
|
+
Commands:
|
|
314
|
+
init Initialize .blueprint directory in current project
|
|
315
|
+
update Update agents, templates, and rituals (preserves your content)
|
|
316
|
+
validate Run pre-flight checks to validate project configuration
|
|
317
|
+
queue Show current queue state for /implement-feature pipeline
|
|
318
|
+
queue reset Clear the queue and reset all state
|
|
319
|
+
history View recent pipeline runs (last 10 by default)
|
|
320
|
+
history --all View all pipeline runs
|
|
321
|
+
history --stats View aggregate statistics
|
|
322
|
+
history clear Clear all pipeline history (with confirmation)
|
|
323
|
+
history clear --force Clear all pipeline history (no confirmation)
|
|
324
|
+
insights Analyze pipeline for bottlenecks, failures, and trends
|
|
325
|
+
insights --bottlenecks Show only bottleneck analysis
|
|
326
|
+
insights --failures Show only failure patterns
|
|
327
|
+
insights --feedback Show feedback loop insights (calibration, correlations)
|
|
328
|
+
insights --json Output analysis as JSON
|
|
329
|
+
retry-config View current retry configuration
|
|
330
|
+
retry-config set <key> <value> Modify a config value (maxRetries, windowSize, highFailureThreshold)
|
|
331
|
+
retry-config reset Reset retry configuration to defaults
|
|
332
|
+
feedback-config View current feedback loop configuration
|
|
333
|
+
feedback-config set <key> <value> Modify a config value (minRatingThreshold, enabled)
|
|
334
|
+
feedback-config reset Reset feedback configuration to defaults
|
|
335
|
+
stack-config View current tech stack configuration
|
|
336
|
+
stack-config set <key> <value> Modify a config value (language, runtime, frameworks, etc.)
|
|
337
|
+
stack-config reset Reset tech stack configuration to defaults
|
|
338
|
+
parallel <slugs...> Run multiple feature pipelines in parallel
|
|
339
|
+
parallel <slugs...> --dry-run Show execution plan without running
|
|
340
|
+
parallel <slugs...> --yes Skip confirmation prompt
|
|
341
|
+
parallel <slugs...> --verbose Stream output to console
|
|
342
|
+
parallel <slugs...> --skip-preflight Skip feature validation checks
|
|
343
|
+
parallel status Show status of all parallel pipelines
|
|
344
|
+
parallel status --detailed Show progress bars and stage info
|
|
345
|
+
parallel abort Stop all running pipelines
|
|
346
|
+
parallel abort --cleanup Stop all and remove worktrees
|
|
347
|
+
parallel rollback Undo completed merges and cleanup failures
|
|
348
|
+
parallel rollback --dry-run Preview what would be rolled back
|
|
349
|
+
parallel cleanup Remove completed/aborted worktrees
|
|
350
|
+
parallel-config View parallel pipeline configuration
|
|
351
|
+
parallel-config set <key> <value> Modify config (cli, skill, skillFlags, etc.)
|
|
352
|
+
parallel-config reset Reset parallel configuration to defaults
|
|
353
|
+
help Show this help message
|
|
354
|
+
|
|
355
|
+
Examples:
|
|
356
|
+
npx murmur8 init
|
|
357
|
+
npx murmur8 update
|
|
358
|
+
npx murmur8 validate
|
|
359
|
+
npx murmur8 queue
|
|
360
|
+
npx murmur8 history
|
|
361
|
+
npx murmur8 history --stats
|
|
362
|
+
npx murmur8 insights --feedback
|
|
363
|
+
npx murmur8 feedback-config
|
|
364
|
+
`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
async function main() {
|
|
368
|
+
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
369
|
+
showHelp();
|
|
370
|
+
process.exit(0);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const cmd = commands[command];
|
|
374
|
+
if (!cmd) {
|
|
375
|
+
console.error(`Unknown command: ${command}`);
|
|
376
|
+
console.error('Run "agent-workflow help" for usage information.');
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
try {
|
|
381
|
+
await cmd.fn();
|
|
382
|
+
} catch (error) {
|
|
383
|
+
console.error(`Error: ${error.message}`);
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "murmur8",
|
|
3
|
+
"version": "3.5.0",
|
|
4
|
+
"description": "Multi-agent workflow framework for automated feature development",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"murmur8": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"agent",
|
|
14
|
+
"workflow",
|
|
15
|
+
"ai",
|
|
16
|
+
"automation",
|
|
17
|
+
"claude",
|
|
18
|
+
"feature-development"
|
|
19
|
+
],
|
|
20
|
+
"author": "NewmanJustice",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/NewmanJustice/agent-workflow.git"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin",
|
|
31
|
+
"src",
|
|
32
|
+
".blueprint",
|
|
33
|
+
".business_context",
|
|
34
|
+
"SKILL.md"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business context detection and conditional inclusion module.
|
|
3
|
+
*
|
|
4
|
+
* Implements lazy loading of business context by detecting references
|
|
5
|
+
* in feature specs and conditionally including the context directive
|
|
6
|
+
* based on agent name and detection results.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Detects if a feature spec content references business context.
|
|
11
|
+
* Matches '.business_context' or 'business_context/' patterns.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} featureSpecContent - The content of the feature spec
|
|
14
|
+
* @returns {boolean} True if business context references are found
|
|
15
|
+
*/
|
|
16
|
+
function needsBusinessContext(featureSpecContent) {
|
|
17
|
+
return featureSpecContent.includes('.business_context')
|
|
18
|
+
|| featureSpecContent.includes('business_context/');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Parses command arguments for the --include-business-context flag.
|
|
23
|
+
*
|
|
24
|
+
* @param {string[]} args - Array of command line arguments
|
|
25
|
+
* @returns {boolean} True if the flag is present
|
|
26
|
+
*/
|
|
27
|
+
function parseIncludeBusinessContextFlag(args) {
|
|
28
|
+
return args.includes('--include-business-context');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Determines if an agent should receive business context.
|
|
33
|
+
* Alex always gets business context (exception).
|
|
34
|
+
* Override flag forces inclusion for all agents.
|
|
35
|
+
* Otherwise, uses detection result.
|
|
36
|
+
*
|
|
37
|
+
* @param {string} agentName - Name of the agent (alex, cass, nigel, codey)
|
|
38
|
+
* @param {boolean} detected - Whether business context was detected in spec
|
|
39
|
+
* @param {boolean} overrideFlag - Whether --include-business-context flag is set
|
|
40
|
+
* @returns {boolean} True if agent should receive business context
|
|
41
|
+
*/
|
|
42
|
+
function shouldIncludeBusinessContext(agentName, detected, overrideFlag) {
|
|
43
|
+
// Alex always gets business context
|
|
44
|
+
if (agentName.toLowerCase() === 'alex') {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
// Override flag forces inclusion
|
|
48
|
+
if (overrideFlag) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
// Otherwise use detection result
|
|
52
|
+
return detected;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Builds queue state object with business context detection result.
|
|
57
|
+
*
|
|
58
|
+
* @param {string} featureSlug - The feature slug identifier
|
|
59
|
+
* @param {boolean} needsContext - Whether business context is needed
|
|
60
|
+
* @returns {object} Queue state object
|
|
61
|
+
*/
|
|
62
|
+
function buildQueueState(featureSlug, needsContext) {
|
|
63
|
+
return {
|
|
64
|
+
feature: featureSlug,
|
|
65
|
+
current: {
|
|
66
|
+
stage: 'pending',
|
|
67
|
+
needsBusinessContext: needsContext
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Generates the business context directive for agent prompts.
|
|
74
|
+
*
|
|
75
|
+
* @param {boolean} includeContext - Whether to include the directive
|
|
76
|
+
* @returns {string} The directive string or empty string
|
|
77
|
+
*/
|
|
78
|
+
function generateBusinessContextDirective(includeContext) {
|
|
79
|
+
if (includeContext) {
|
|
80
|
+
return 'Business Context: .business_context/';
|
|
81
|
+
}
|
|
82
|
+
return '';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
86
|
+
needsBusinessContext,
|
|
87
|
+
parseIncludeBusinessContextFlag,
|
|
88
|
+
shouldIncludeBusinessContext,
|
|
89
|
+
buildQueueState,
|
|
90
|
+
generateBusinessContextDirective
|
|
91
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Story Routing - Feature Classifier Module
|
|
3
|
+
*
|
|
4
|
+
* Classifies features as "technical" or "user-facing" to determine
|
|
5
|
+
* whether the Cass (story writing) stage should be included in the pipeline.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Technical keywords indicate infrastructure/internal work
|
|
9
|
+
const TECHNICAL_KEYWORDS = [
|
|
10
|
+
'refactor',
|
|
11
|
+
'token',
|
|
12
|
+
'performance',
|
|
13
|
+
'module',
|
|
14
|
+
'internal',
|
|
15
|
+
'infrastructure',
|
|
16
|
+
'optimization',
|
|
17
|
+
'extract',
|
|
18
|
+
'compress',
|
|
19
|
+
'cache',
|
|
20
|
+
'schema',
|
|
21
|
+
'validation',
|
|
22
|
+
'helper',
|
|
23
|
+
'utility',
|
|
24
|
+
'config'
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
// User-facing keywords indicate customer-visible features
|
|
28
|
+
const USER_FACING_KEYWORDS = [
|
|
29
|
+
'user',
|
|
30
|
+
'customer',
|
|
31
|
+
'ui',
|
|
32
|
+
'screen',
|
|
33
|
+
'journey',
|
|
34
|
+
'flow',
|
|
35
|
+
'experience',
|
|
36
|
+
'interface',
|
|
37
|
+
'form',
|
|
38
|
+
'button',
|
|
39
|
+
'login',
|
|
40
|
+
'signup',
|
|
41
|
+
'dashboard',
|
|
42
|
+
'notification',
|
|
43
|
+
'email'
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Classify a feature specification as technical or user-facing
|
|
48
|
+
* @param {string} content - The feature specification content
|
|
49
|
+
* @returns {Object} Classification result with type, counts, and reason
|
|
50
|
+
*/
|
|
51
|
+
function classifyFeature(content) {
|
|
52
|
+
const lowerContent = (content || '').toLowerCase();
|
|
53
|
+
|
|
54
|
+
let technicalCount = 0;
|
|
55
|
+
let userFacingCount = 0;
|
|
56
|
+
const technicalMatches = [];
|
|
57
|
+
const userFacingMatches = [];
|
|
58
|
+
|
|
59
|
+
// Count technical keyword matches
|
|
60
|
+
for (const keyword of TECHNICAL_KEYWORDS) {
|
|
61
|
+
const regex = new RegExp(`\\b${keyword}\\b`, 'gi');
|
|
62
|
+
const matches = lowerContent.match(regex);
|
|
63
|
+
if (matches) {
|
|
64
|
+
technicalCount += matches.length;
|
|
65
|
+
technicalMatches.push(keyword);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Count user-facing keyword matches
|
|
70
|
+
for (const keyword of USER_FACING_KEYWORDS) {
|
|
71
|
+
const regex = new RegExp(`\\b${keyword}\\b`, 'gi');
|
|
72
|
+
const matches = lowerContent.match(regex);
|
|
73
|
+
if (matches) {
|
|
74
|
+
userFacingCount += matches.length;
|
|
75
|
+
userFacingMatches.push(keyword);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Determine type - tie goes to user-facing (conservative default)
|
|
80
|
+
const type = technicalCount > userFacingCount ? 'technical' : 'user-facing';
|
|
81
|
+
|
|
82
|
+
// Build reason string
|
|
83
|
+
let reason;
|
|
84
|
+
if (technicalCount === 0 && userFacingCount === 0) {
|
|
85
|
+
reason = 'No keywords found, defaulting to user-facing';
|
|
86
|
+
} else if (technicalCount > userFacingCount) {
|
|
87
|
+
reason = `Technical keywords (${technicalMatches.join(', ')}) outweigh user-facing`;
|
|
88
|
+
} else if (userFacingCount > technicalCount) {
|
|
89
|
+
reason = `User-facing keywords (${userFacingMatches.join(', ')}) outweigh technical`;
|
|
90
|
+
} else {
|
|
91
|
+
reason = 'Tie between technical and user-facing, defaulting to user-facing';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
type,
|
|
96
|
+
technicalCount,
|
|
97
|
+
userFacingCount,
|
|
98
|
+
reason
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Parse story-related flags from command arguments
|
|
104
|
+
* @param {string[]} args - Array of command arguments
|
|
105
|
+
* @returns {Object} Parsed flags with override value
|
|
106
|
+
*/
|
|
107
|
+
function parseStoryFlags(args) {
|
|
108
|
+
const argList = args || [];
|
|
109
|
+
|
|
110
|
+
if (argList.includes('--with-stories')) {
|
|
111
|
+
return { override: 'include' };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (argList.includes('--skip-stories')) {
|
|
115
|
+
return { override: 'skip' };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { override: null };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Determine whether stories should be included in the pipeline
|
|
123
|
+
* @param {string} featureType - 'technical' or 'user-facing'
|
|
124
|
+
* @param {string|null} override - 'include', 'skip', or null
|
|
125
|
+
* @returns {boolean} Whether to include stories in the pipeline
|
|
126
|
+
*/
|
|
127
|
+
function shouldIncludeStories(featureType, override) {
|
|
128
|
+
// Override takes precedence
|
|
129
|
+
if (override === 'include') {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
if (override === 'skip') {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Default behavior based on classification
|
|
137
|
+
return featureType === 'user-facing';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Build queue state object with classification data
|
|
142
|
+
* @param {string} slug - Feature slug
|
|
143
|
+
* @param {string} featureType - 'technical' or 'user-facing'
|
|
144
|
+
* @param {boolean} includeStories - Whether stories are included
|
|
145
|
+
* @returns {Object} Queue state object with featureType and skippedCass fields
|
|
146
|
+
*/
|
|
147
|
+
function buildClassifiedQueueState(slug, featureType, includeStories) {
|
|
148
|
+
return {
|
|
149
|
+
slug,
|
|
150
|
+
featureType,
|
|
151
|
+
skippedCass: !includeStories
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Log classification result to console
|
|
157
|
+
* @param {Object} result - Classification result from classifyFeature
|
|
158
|
+
*/
|
|
159
|
+
function logClassification(result) {
|
|
160
|
+
console.log(`Feature classified as ${result.type}: ${result.reason}`);
|
|
161
|
+
console.log(` Technical indicators: ${result.technicalCount}`);
|
|
162
|
+
console.log(` User-facing indicators: ${result.userFacingCount}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
TECHNICAL_KEYWORDS,
|
|
167
|
+
USER_FACING_KEYWORDS,
|
|
168
|
+
classifyFeature,
|
|
169
|
+
parseStoryFlags,
|
|
170
|
+
shouldIncludeStories,
|
|
171
|
+
buildClassifiedQueueState,
|
|
172
|
+
logClassification
|
|
173
|
+
};
|