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.
Files changed (120) hide show
  1. package/.blueprint/agents/AGENT_BA_CASS.md +239 -0
  2. package/.blueprint/agents/AGENT_DEVELOPER_CODEY.md +308 -0
  3. package/.blueprint/agents/AGENT_SPECIFICATION_ALEX.md +183 -0
  4. package/.blueprint/agents/AGENT_TESTER_NIGEL.md +159 -0
  5. package/.blueprint/agents/GUARDRAILS.md +83 -0
  6. package/.blueprint/agents/TEAM_MANIFESTO.md +91 -0
  7. package/.blueprint/features/.gitkeep +0 -0
  8. package/.blueprint/features/feature_adaptive-retry/FEATURE_SPEC.md +239 -0
  9. package/.blueprint/features/feature_adaptive-retry/IMPLEMENTATION_PLAN.md +48 -0
  10. package/.blueprint/features/feature_adaptive-retry/story-prompt-modification.md +85 -0
  11. package/.blueprint/features/feature_adaptive-retry/story-retry-config.md +89 -0
  12. package/.blueprint/features/feature_adaptive-retry/story-should-retry.md +98 -0
  13. package/.blueprint/features/feature_adaptive-retry/story-strategy-recommendation.md +85 -0
  14. package/.blueprint/features/feature_agent-guardrails/FEATURE_SPEC.md +328 -0
  15. package/.blueprint/features/feature_agent-guardrails/IMPLEMENTATION_PLAN.md +90 -0
  16. package/.blueprint/features/feature_agent-guardrails/story-citation-requirements.md +50 -0
  17. package/.blueprint/features/feature_agent-guardrails/story-confidentiality.md +50 -0
  18. package/.blueprint/features/feature_agent-guardrails/story-escalation-protocol.md +55 -0
  19. package/.blueprint/features/feature_agent-guardrails/story-source-restrictions.md +50 -0
  20. package/.blueprint/features/feature_compressed-feedback/FEATURE_SPEC.md +136 -0
  21. package/.blueprint/features/feature_compressed-feedback/IMPLEMENTATION_PLAN.md +40 -0
  22. package/.blueprint/features/feature_feedback-loop/FEATURE_SPEC.md +347 -0
  23. package/.blueprint/features/feature_feedback-loop/IMPLEMENTATION_PLAN.md +71 -0
  24. package/.blueprint/features/feature_feedback-loop/story-feedback-collection.md +63 -0
  25. package/.blueprint/features/feature_feedback-loop/story-feedback-config.md +61 -0
  26. package/.blueprint/features/feature_feedback-loop/story-feedback-insights.md +63 -0
  27. package/.blueprint/features/feature_feedback-loop/story-quality-gates.md +57 -0
  28. package/.blueprint/features/feature_interactive-alex/FEATURE_SPEC.md +263 -0
  29. package/.blueprint/features/feature_interactive-alex/IMPLEMENTATION_PLAN.md +69 -0
  30. package/.blueprint/features/feature_interactive-alex/handoff-alex.md +19 -0
  31. package/.blueprint/features/feature_interactive-alex/handoff-cass.md +21 -0
  32. package/.blueprint/features/feature_interactive-alex/handoff-nigel.md +19 -0
  33. package/.blueprint/features/feature_interactive-alex/story-flag-routing.md +54 -0
  34. package/.blueprint/features/feature_interactive-alex/story-iterative-drafting.md +65 -0
  35. package/.blueprint/features/feature_interactive-alex/story-pipeline-integration.md +66 -0
  36. package/.blueprint/features/feature_interactive-alex/story-session-lifecycle.md +75 -0
  37. package/.blueprint/features/feature_interactive-alex/story-system-spec-creation.md +57 -0
  38. package/.blueprint/features/feature_lazy-business-context/FEATURE_SPEC.md +140 -0
  39. package/.blueprint/features/feature_lazy-business-context/IMPLEMENTATION_PLAN.md +54 -0
  40. package/.blueprint/features/feature_model-native-features/FEATURE_SPEC.md +174 -0
  41. package/.blueprint/features/feature_model-native-features/IMPLEMENTATION_PLAN.md +45 -0
  42. package/.blueprint/features/feature_parallel-abort/FEATURE_SPEC.md +117 -0
  43. package/.blueprint/features/feature_parallel-confirm/FEATURE_SPEC.md +90 -0
  44. package/.blueprint/features/feature_parallel-features/FEATURE_SPEC.md +291 -0
  45. package/.blueprint/features/feature_parallel-features/IMPLEMENTATION_PLAN.md +73 -0
  46. package/.blueprint/features/feature_parallel-lock/FEATURE_SPEC.md +119 -0
  47. package/.blueprint/features/feature_parallel-logging/FEATURE_SPEC.md +105 -0
  48. package/.blueprint/features/feature_parallel-preflight/FEATURE_SPEC.md +141 -0
  49. package/.blueprint/features/feature_pipeline-history/FEATURE_SPEC.md +239 -0
  50. package/.blueprint/features/feature_pipeline-history/IMPLEMENTATION_PLAN.md +71 -0
  51. package/.blueprint/features/feature_pipeline-history/story-clear-history.md +73 -0
  52. package/.blueprint/features/feature_pipeline-history/story-display-history.md +75 -0
  53. package/.blueprint/features/feature_pipeline-history/story-record-execution.md +76 -0
  54. package/.blueprint/features/feature_pipeline-history/story-show-statistics.md +85 -0
  55. package/.blueprint/features/feature_pipeline-insights/FEATURE_SPEC.md +288 -0
  56. package/.blueprint/features/feature_pipeline-insights/IMPLEMENTATION_PLAN.md +65 -0
  57. package/.blueprint/features/feature_pipeline-insights/story-anomaly-detection.md +71 -0
  58. package/.blueprint/features/feature_pipeline-insights/story-bottleneck-analysis.md +75 -0
  59. package/.blueprint/features/feature_pipeline-insights/story-failure-patterns.md +75 -0
  60. package/.blueprint/features/feature_pipeline-insights/story-json-output.md +75 -0
  61. package/.blueprint/features/feature_pipeline-insights/story-trend-analysis.md +78 -0
  62. package/.blueprint/features/feature_shared-guardrails/FEATURE_SPEC.md +119 -0
  63. package/.blueprint/features/feature_shared-guardrails/IMPLEMENTATION_PLAN.md +34 -0
  64. package/.blueprint/features/feature_shared-guardrails/story-extract-guardrails.md +60 -0
  65. package/.blueprint/features/feature_shared-guardrails/story-update-init-commands.md +63 -0
  66. package/.blueprint/features/feature_slim-agent-prompts/FEATURE_SPEC.md +145 -0
  67. package/.blueprint/features/feature_slim-agent-prompts/IMPLEMENTATION_PLAN.md +87 -0
  68. package/.blueprint/features/feature_slim-agent-prompts/story-create-runtime-prompt-template.md +59 -0
  69. package/.blueprint/features/feature_slim-agent-prompts/story-create-slim-agent-prompts.md +65 -0
  70. package/.blueprint/features/feature_slim-agent-prompts/story-skill-integration.md +53 -0
  71. package/.blueprint/features/feature_smart-story-routing/FEATURE_SPEC.md +147 -0
  72. package/.blueprint/features/feature_smart-story-routing/IMPLEMENTATION_PLAN.md +73 -0
  73. package/.blueprint/features/feature_template-extraction/FEATURE_SPEC.md +134 -0
  74. package/.blueprint/features/feature_template-extraction/IMPLEMENTATION_PLAN.md +46 -0
  75. package/.blueprint/features/feature_upstream-summaries/FEATURE_SPEC.md +150 -0
  76. package/.blueprint/features/feature_upstream-summaries/IMPLEMENTATION_PLAN.md +70 -0
  77. package/.blueprint/features/feature_validate-command/FEATURE_SPEC.md +209 -0
  78. package/.blueprint/features/feature_validate-command/IMPLEMENTATION_PLAN.md +59 -0
  79. package/.blueprint/features/feature_validate-command/story-failure-output.md +61 -0
  80. package/.blueprint/features/feature_validate-command/story-node-version-check.md +52 -0
  81. package/.blueprint/features/feature_validate-command/story-run-validation.md +59 -0
  82. package/.blueprint/features/feature_validate-command/story-success-output.md +50 -0
  83. package/.blueprint/prompts/TEMPLATE.md +65 -0
  84. package/.blueprint/prompts/alex-runtime.md +49 -0
  85. package/.blueprint/prompts/cass-runtime.md +46 -0
  86. package/.blueprint/prompts/codey-implement-runtime.md +52 -0
  87. package/.blueprint/prompts/codey-plan-runtime.md +47 -0
  88. package/.blueprint/prompts/nigel-runtime.md +47 -0
  89. package/.blueprint/system_specification/.gitkeep +0 -0
  90. package/.blueprint/system_specification/SYSTEM_SPEC.md +248 -0
  91. package/.blueprint/templates/FEATURE_SPEC.md +125 -0
  92. package/.blueprint/templates/STORY_TEMPLATE.md +96 -0
  93. package/.blueprint/templates/SYSTEM_SPEC.md +128 -0
  94. package/.blueprint/templates/TEST_TEMPLATE.md +76 -0
  95. package/.blueprint/ways_of_working/DEVELOPMENT_RITUAL.md +178 -0
  96. package/.business_context/README.md +27 -0
  97. package/LICENSE +21 -0
  98. package/README.md +564 -0
  99. package/SKILL.md +840 -0
  100. package/bin/cli.js +388 -0
  101. package/package.json +36 -0
  102. package/src/business-context.js +91 -0
  103. package/src/classifier.js +173 -0
  104. package/src/feedback.js +201 -0
  105. package/src/handoff.js +148 -0
  106. package/src/history.js +306 -0
  107. package/src/index.js +170 -0
  108. package/src/init.js +139 -0
  109. package/src/insights.js +504 -0
  110. package/src/interactive.js +338 -0
  111. package/src/orchestrator.js +217 -0
  112. package/src/parallel.js +1544 -0
  113. package/src/retry.js +274 -0
  114. package/src/stack.js +320 -0
  115. package/src/tools/index.js +27 -0
  116. package/src/tools/prompts.js +45 -0
  117. package/src/tools/schemas.js +38 -0
  118. package/src/tools/validation.js +83 -0
  119. package/src/update.js +112 -0
  120. package/src/validate.js +172 -0
@@ -0,0 +1,338 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const SESSION_STATES = {
5
+ IDLE: 'idle',
6
+ GATHERING: 'gathering',
7
+ QUESTIONING: 'questioning',
8
+ DRAFTING: 'drafting',
9
+ FINALIZING: 'finalizing'
10
+ };
11
+
12
+ const SECTION_ORDER = ['intent', 'scope', 'actors', 'behaviour', 'dependencies'];
13
+
14
+ const MIN_REQUIRED_SECTIONS = ['intent', 'scope', 'actors'];
15
+
16
+ const SYSTEM_SPEC_QUESTIONS = ['purpose', 'actors', 'boundaries', 'rules'];
17
+
18
+ function parseFlags(args) {
19
+ return {
20
+ interactive: args.includes('--interactive'),
21
+ pauseAfter: args.find(a => a.startsWith('--pause-after='))?.split('=')[1] || null
22
+ };
23
+ }
24
+
25
+ function shouldEnterInteractiveMode(flags, hasSystemSpec, hasFeatureSpec) {
26
+ if (flags.interactive) return { interactive: true, target: 'feature' };
27
+ if (!hasSystemSpec) return { interactive: true, target: 'system' };
28
+ if (!hasFeatureSpec) return { interactive: true, target: 'feature' };
29
+ return { interactive: false, target: null };
30
+ }
31
+
32
+ function createSession(target) {
33
+ const sections = target === 'system'
34
+ ? { purpose: null, actors: null, boundaries: null, rules: null }
35
+ : { intent: null, scope: null, actors: null, behaviour: null, dependencies: null };
36
+
37
+ return {
38
+ target,
39
+ state: SESSION_STATES.IDLE,
40
+ sections,
41
+ current: target === 'system' ? 'purpose' : 'intent',
42
+ revisionCount: 0,
43
+ questionCount: 0,
44
+ startedAt: new Date().toISOString(),
45
+ aborted: false,
46
+ specWritten: false,
47
+ context: {},
48
+ feedback: []
49
+ };
50
+ }
51
+
52
+ function getSessionProgress(session) {
53
+ const sectionList = Object.keys(session.sections);
54
+ const complete = Object.values(session.sections).filter(
55
+ s => s === 'complete' || s === 'TBD'
56
+ ).length;
57
+ const remaining = sectionList.length - complete;
58
+ return { complete, remaining, total: sectionList.length };
59
+ }
60
+
61
+ function handleCommand(session, command) {
62
+ const cmd = command.trim().toLowerCase();
63
+ const parts = command.trim().split(/\s+/);
64
+ const baseCmd = parts[0].toLowerCase();
65
+
66
+ if (baseCmd === '/approve' || baseCmd === 'yes') {
67
+ session.sections[session.current] = 'complete';
68
+ const nextSection = getNextSection(session);
69
+ if (nextSection) {
70
+ session.current = nextSection;
71
+ return { action: 'next', section: nextSection };
72
+ }
73
+ return { action: 'finalize' };
74
+ }
75
+
76
+ if (baseCmd === '/change') {
77
+ const feedback = parts.slice(1).join(' ');
78
+ session.revisionCount++;
79
+ session.feedback.push({ section: session.current, feedback });
80
+ return { action: 'revise', feedback };
81
+ }
82
+
83
+ if (baseCmd === '/skip') {
84
+ session.sections[session.current] = 'TBD';
85
+ const nextSection = getNextSection(session);
86
+ if (nextSection) {
87
+ session.current = nextSection;
88
+ return { action: 'next', section: nextSection };
89
+ }
90
+ return { action: 'finalize' };
91
+ }
92
+
93
+ if (baseCmd === '/restart') {
94
+ session.sections[session.current] = null;
95
+ return { action: 'restart', section: session.current };
96
+ }
97
+
98
+ if (baseCmd === '/abort') {
99
+ session.aborted = true;
100
+ return { action: 'abort' };
101
+ }
102
+
103
+ if (baseCmd === '/done') {
104
+ if (canFinalize(session)) {
105
+ return { action: 'finalize' };
106
+ }
107
+ return { action: 'incomplete', missing: getMissingSections(session) };
108
+ }
109
+
110
+ return { action: 'unknown', command: baseCmd };
111
+ }
112
+
113
+ function getNextSection(session) {
114
+ const order = session.target === 'system'
115
+ ? SYSTEM_SPEC_QUESTIONS
116
+ : SECTION_ORDER;
117
+
118
+ for (const section of order) {
119
+ const status = session.sections[section];
120
+ if (status !== 'complete' && status !== 'TBD') {
121
+ return section;
122
+ }
123
+ }
124
+ return null;
125
+ }
126
+
127
+ function markSectionComplete(session, section) {
128
+ if (section in session.sections) {
129
+ session.sections[section] = 'complete';
130
+ return true;
131
+ }
132
+ return false;
133
+ }
134
+
135
+ function markSectionTBD(session, section) {
136
+ if (section in session.sections) {
137
+ session.sections[section] = 'TBD';
138
+ return true;
139
+ }
140
+ return false;
141
+ }
142
+
143
+ function gatherContext(basePath = '.') {
144
+ const context = {
145
+ systemSpec: null,
146
+ businessContext: [],
147
+ templates: []
148
+ };
149
+
150
+ const systemSpecPath = path.join(basePath, '.blueprint/system_specification/SYSTEM_SPEC.md');
151
+ if (fs.existsSync(systemSpecPath)) {
152
+ context.systemSpec = fs.readFileSync(systemSpecPath, 'utf8');
153
+ }
154
+
155
+ const businessContextDir = path.join(basePath, '.business_context');
156
+ if (fs.existsSync(businessContextDir)) {
157
+ const files = fs.readdirSync(businessContextDir);
158
+ for (const file of files) {
159
+ if (file.endsWith('.md')) {
160
+ const content = fs.readFileSync(path.join(businessContextDir, file), 'utf8');
161
+ context.businessContext.push({ file, content });
162
+ }
163
+ }
164
+ }
165
+
166
+ const templatesDir = path.join(basePath, '.blueprint/templates');
167
+ if (fs.existsSync(templatesDir)) {
168
+ const files = fs.readdirSync(templatesDir);
169
+ for (const file of files) {
170
+ if (file.endsWith('.md')) {
171
+ const content = fs.readFileSync(path.join(templatesDir, file), 'utf8');
172
+ context.templates.push({ file, content });
173
+ }
174
+ }
175
+ }
176
+
177
+ return context;
178
+ }
179
+
180
+ function identifyGaps(session, userDescription) {
181
+ const gaps = [];
182
+ const sectionKeys = session.target === 'system'
183
+ ? SYSTEM_SPEC_QUESTIONS
184
+ : SECTION_ORDER;
185
+
186
+ for (const section of sectionKeys) {
187
+ const hasKey = `has${section.charAt(0).toUpperCase() + section.slice(1)}`;
188
+ if (!userDescription[hasKey]) {
189
+ gaps.push(section);
190
+ }
191
+ }
192
+
193
+ return gaps.slice(0, 4);
194
+ }
195
+
196
+ function generateQuestions(gaps) {
197
+ const questionTemplates = {
198
+ intent: 'What is the primary goal or purpose of this feature?',
199
+ scope: 'What boundaries define what is in scope vs out of scope?',
200
+ actors: 'Who are the users or systems that will interact with this?',
201
+ behaviour: 'What are the key behaviours or flows to support?',
202
+ dependencies: 'What does this depend on or what depends on it?',
203
+ purpose: 'What is the overall purpose of this system?',
204
+ boundaries: 'What are the system boundaries and integration points?',
205
+ rules: 'What business rules or constraints apply?'
206
+ };
207
+
208
+ return gaps.slice(0, 4).map(gap => ({
209
+ section: gap,
210
+ question: questionTemplates[gap] || `What information is needed for ${gap}?`
211
+ }));
212
+ }
213
+
214
+ function getMissingSections(session) {
215
+ const required = session.target === 'system'
216
+ ? ['purpose', 'actors', 'boundaries']
217
+ : MIN_REQUIRED_SECTIONS;
218
+
219
+ return required.filter(section => {
220
+ const status = session.sections[section];
221
+ return status !== 'complete' && status !== 'TBD';
222
+ });
223
+ }
224
+
225
+ function canFinalize(session) {
226
+ const required = session.target === 'system'
227
+ ? ['purpose', 'actors', 'boundaries']
228
+ : MIN_REQUIRED_SECTIONS;
229
+
230
+ return required.every(section => {
231
+ const status = session.sections[section];
232
+ return status === 'complete' || status === 'TBD';
233
+ });
234
+ }
235
+
236
+ function generateSpec(session) {
237
+ const sections = [];
238
+ const sectionOrder = session.target === 'system'
239
+ ? SYSTEM_SPEC_QUESTIONS
240
+ : SECTION_ORDER;
241
+
242
+ const title = session.target === 'system' ? 'System Spec' : 'Feature Spec';
243
+ sections.push(`# ${title}`);
244
+
245
+ for (const sectionName of sectionOrder) {
246
+ const status = session.sections[sectionName];
247
+ const heading = sectionName.charAt(0).toUpperCase() + sectionName.slice(1);
248
+ sections.push(`## ${heading}`);
249
+
250
+ if (status === 'TBD') {
251
+ sections.push('TBD');
252
+ } else if (status === 'complete') {
253
+ sections.push(`[Content for ${sectionName}]`);
254
+ } else {
255
+ sections.push('TBD');
256
+ }
257
+ }
258
+
259
+ sections.push('');
260
+ sections.push('_Created via interactive session_');
261
+
262
+ return sections.join('\n');
263
+ }
264
+
265
+ function writeSpec(session, outputPath) {
266
+ const content = generateSpec(session);
267
+ const dir = path.dirname(outputPath);
268
+
269
+ if (!fs.existsSync(dir)) {
270
+ fs.mkdirSync(dir, { recursive: true });
271
+ }
272
+
273
+ fs.writeFileSync(outputPath, content);
274
+ session.specWritten = true;
275
+ return outputPath;
276
+ }
277
+
278
+ function generateHandoff(session, slug) {
279
+ const progress = getSessionProgress(session);
280
+ const endedAt = new Date().toISOString();
281
+ const startedAt = new Date(session.startedAt);
282
+ const durationMs = new Date(endedAt) - startedAt;
283
+
284
+ const lines = [
285
+ '## Handoff Summary',
286
+ '**For:** Cass',
287
+ `**Feature:** ${slug}`,
288
+ '',
289
+ '### Key Decisions',
290
+ `- Interactive mode used for ${session.target} spec creation`,
291
+ `- ${progress.complete}/${progress.total} sections completed`,
292
+ session.revisionCount > 0 ? `- ${session.revisionCount} revision(s) made` : null,
293
+ '',
294
+ '### Files Created',
295
+ session.target === 'system'
296
+ ? '- .blueprint/system_specification/SYSTEM_SPEC.md'
297
+ : `- .blueprint/features/feature_${slug}/FEATURE_SPEC.md`,
298
+ '',
299
+ '### Open Questions',
300
+ progress.remaining > 0 ? `- ${progress.remaining} section(s) marked TBD` : '- None',
301
+ '',
302
+ '### Critical Context',
303
+ `Session duration: ${Math.round(durationMs / 1000)}s, Questions asked: ${session.questionCount}, Revisions: ${session.revisionCount}`
304
+ ].filter(line => line !== null);
305
+
306
+ return lines.join('\n');
307
+ }
308
+
309
+ function getOutputPath(session, slug, basePath = '.') {
310
+ if (session.target === 'system') {
311
+ return path.join(basePath, '.blueprint/system_specification/SYSTEM_SPEC.md');
312
+ }
313
+ return path.join(basePath, `.blueprint/features/feature_${slug}/FEATURE_SPEC.md`);
314
+ }
315
+
316
+ module.exports = {
317
+ SESSION_STATES,
318
+ SECTION_ORDER,
319
+ MIN_REQUIRED_SECTIONS,
320
+ SYSTEM_SPEC_QUESTIONS,
321
+ parseFlags,
322
+ shouldEnterInteractiveMode,
323
+ createSession,
324
+ getSessionProgress,
325
+ handleCommand,
326
+ getNextSection,
327
+ markSectionComplete,
328
+ markSectionTBD,
329
+ gatherContext,
330
+ identifyGaps,
331
+ generateQuestions,
332
+ getMissingSections,
333
+ canFinalize,
334
+ generateSpec,
335
+ writeSpec,
336
+ generateHandoff,
337
+ getOutputPath
338
+ };
@@ -0,0 +1,217 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const QUEUE_PATH = '.claude/implement-queue.json';
5
+
6
+ function ensureQueueDir() {
7
+ const dir = path.dirname(QUEUE_PATH);
8
+ if (!fs.existsSync(dir)) {
9
+ fs.mkdirSync(dir, { recursive: true });
10
+ }
11
+ }
12
+
13
+ function createEmptyQueue() {
14
+ return {
15
+ lastUpdated: new Date().toISOString(),
16
+ current: null,
17
+ alexQueue: [],
18
+ cassQueue: [],
19
+ nigelQueue: [],
20
+ codeyQueue: [],
21
+ completed: [],
22
+ failed: []
23
+ };
24
+ }
25
+
26
+ function readQueue() {
27
+ ensureQueueDir();
28
+ if (!fs.existsSync(QUEUE_PATH)) {
29
+ const queue = createEmptyQueue();
30
+ writeQueue(queue);
31
+ return queue;
32
+ }
33
+ const content = fs.readFileSync(QUEUE_PATH, 'utf8');
34
+ return JSON.parse(content);
35
+ }
36
+
37
+ function writeQueue(queue) {
38
+ ensureQueueDir();
39
+ queue.lastUpdated = new Date().toISOString();
40
+ fs.writeFileSync(QUEUE_PATH, JSON.stringify(queue, null, 2));
41
+ }
42
+
43
+ function updateQueue(updates) {
44
+ const queue = readQueue();
45
+ Object.assign(queue, updates);
46
+ writeQueue(queue);
47
+ return queue;
48
+ }
49
+
50
+ function setCurrent(slug, stage) {
51
+ const queue = readQueue();
52
+ queue.current = {
53
+ slug,
54
+ stage,
55
+ startedAt: new Date().toISOString()
56
+ };
57
+ writeQueue(queue);
58
+ return queue;
59
+ }
60
+
61
+ function clearCurrent() {
62
+ const queue = readQueue();
63
+ queue.current = null;
64
+ writeQueue(queue);
65
+ return queue;
66
+ }
67
+
68
+ function moveToNextStage(slug, fromStage, toStage) {
69
+ const queue = readQueue();
70
+ const fromQueueName = `${fromStage}Queue`;
71
+ const toQueueName = `${toStage}Queue`;
72
+
73
+ // Remove from source queue
74
+ if (queue[fromQueueName]) {
75
+ queue[fromQueueName] = queue[fromQueueName].filter(item => item.slug !== slug);
76
+ }
77
+
78
+ // Add to destination queue
79
+ if (!queue[toQueueName]) {
80
+ queue[toQueueName] = [];
81
+ }
82
+
83
+ const entry = { slug, movedAt: new Date().toISOString() };
84
+ queue[toQueueName].push(entry);
85
+
86
+ // Update current stage
87
+ if (queue.current && queue.current.slug === slug) {
88
+ queue.current.stage = toStage;
89
+ }
90
+
91
+ writeQueue(queue);
92
+ return queue;
93
+ }
94
+
95
+ function markCompleted(slug, metadata = {}) {
96
+ const queue = readQueue();
97
+
98
+ // Remove from codeyQueue
99
+ queue.codeyQueue = queue.codeyQueue.filter(item => item.slug !== slug);
100
+
101
+ // Add to completed
102
+ queue.completed.push({
103
+ slug,
104
+ completedAt: new Date().toISOString(),
105
+ ...metadata
106
+ });
107
+
108
+ // Clear current if this was it
109
+ if (queue.current && queue.current.slug === slug) {
110
+ queue.current = null;
111
+ }
112
+
113
+ writeQueue(queue);
114
+ return queue;
115
+ }
116
+
117
+ function markFailed(slug, stage, reason) {
118
+ const queue = readQueue();
119
+
120
+ // Remove from all stage queues
121
+ ['alexQueue', 'cassQueue', 'nigelQueue', 'codeyQueue'].forEach(queueName => {
122
+ if (queue[queueName]) {
123
+ queue[queueName] = queue[queueName].filter(item => item.slug !== slug);
124
+ }
125
+ });
126
+
127
+ // Add to failed
128
+ queue.failed.push({
129
+ slug,
130
+ stage,
131
+ reason,
132
+ failedAt: new Date().toISOString()
133
+ });
134
+
135
+ // Clear current if this was it
136
+ if (queue.current && queue.current.slug === slug) {
137
+ queue.current = null;
138
+ }
139
+
140
+ writeQueue(queue);
141
+ return queue;
142
+ }
143
+
144
+ function resetQueue() {
145
+ const queue = createEmptyQueue();
146
+ writeQueue(queue);
147
+ return queue;
148
+ }
149
+
150
+ function getQueueStatus() {
151
+ const queue = readQueue();
152
+ return {
153
+ current: queue.current,
154
+ pending: {
155
+ alex: queue.alexQueue.length,
156
+ cass: queue.cassQueue.length,
157
+ nigel: queue.nigelQueue.length,
158
+ codey: queue.codeyQueue.length
159
+ },
160
+ completed: queue.completed.length,
161
+ failed: queue.failed.length
162
+ };
163
+ }
164
+
165
+ function displayQueue() {
166
+ const queue = readQueue();
167
+
168
+ console.log('\nImplement Feature Queue Status');
169
+ console.log('==============================\n');
170
+
171
+ if (queue.current) {
172
+ console.log('Current:');
173
+ console.log(` ${queue.current.slug} (stage: ${queue.current.stage})`);
174
+ console.log(` Started: ${queue.current.startedAt}\n`);
175
+ } else {
176
+ console.log('Current: (none)\n');
177
+ }
178
+
179
+ console.log('Queues:');
180
+ console.log(` Alex: ${queue.alexQueue.length} pending`);
181
+ console.log(` Cass: ${queue.cassQueue.length} pending`);
182
+ console.log(` Nigel: ${queue.nigelQueue.length} pending`);
183
+ console.log(` Codey: ${queue.codeyQueue.length} pending\n`);
184
+
185
+ if (queue.completed.length > 0) {
186
+ console.log('Completed:');
187
+ queue.completed.forEach(item => {
188
+ console.log(` - ${item.slug} (${item.completedAt})`);
189
+ });
190
+ console.log('');
191
+ }
192
+
193
+ if (queue.failed.length > 0) {
194
+ console.log('Failed:');
195
+ queue.failed.forEach(item => {
196
+ console.log(` - ${item.slug} at ${item.stage}: ${item.reason}`);
197
+ });
198
+ console.log('');
199
+ }
200
+
201
+ console.log(`Last updated: ${queue.lastUpdated}`);
202
+ }
203
+
204
+ module.exports = {
205
+ QUEUE_PATH,
206
+ readQueue,
207
+ writeQueue,
208
+ updateQueue,
209
+ setCurrent,
210
+ clearCurrent,
211
+ moveToNextStage,
212
+ markCompleted,
213
+ markFailed,
214
+ resetQueue,
215
+ getQueueStatus,
216
+ displayQueue
217
+ };