specsmd 0.1.9 → 0.1.10
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.
|
@@ -248,25 +248,22 @@ function completeCurrentItem(rootPath, runId, params = {}) {
|
|
|
248
248
|
const { statePath, runLogPath } = validateFireProject(rootPath, runId);
|
|
249
249
|
const state = readState(statePath);
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
// Find run in active runs list
|
|
252
|
+
const activeRuns = state.runs?.active || [];
|
|
253
|
+
const runIndex = activeRuns.findIndex(r => r.id === runId);
|
|
254
|
+
|
|
255
|
+
if (runIndex === -1) {
|
|
252
256
|
throw fireError(
|
|
253
|
-
|
|
257
|
+
`Run "${runId}" not found in active runs.`,
|
|
254
258
|
'COMPLETE_040',
|
|
255
259
|
'The run may have already been completed or was never started.'
|
|
256
260
|
);
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
|
|
260
|
-
throw fireError(
|
|
261
|
-
`Run ID mismatch. Active run is "${state.active_run.id}" but trying to complete "${runId}".`,
|
|
262
|
-
'COMPLETE_041',
|
|
263
|
-
`Complete the active run "${state.active_run.id}" first.`
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
263
|
+
const activeRun = activeRuns[runIndex];
|
|
267
264
|
const completedTime = new Date().toISOString();
|
|
268
|
-
const workItems =
|
|
269
|
-
const currentItemId =
|
|
265
|
+
const workItems = activeRun.work_items || [];
|
|
266
|
+
const currentItemId = activeRun.current_item;
|
|
270
267
|
|
|
271
268
|
// Find and mark current item as completed
|
|
272
269
|
let currentItemIndex = -1;
|
|
@@ -297,12 +294,13 @@ function completeCurrentItem(rootPath, runId, params = {}) {
|
|
|
297
294
|
}
|
|
298
295
|
}
|
|
299
296
|
|
|
300
|
-
// Update
|
|
301
|
-
|
|
302
|
-
|
|
297
|
+
// Update active run in list
|
|
298
|
+
activeRun.work_items = workItems;
|
|
299
|
+
activeRun.current_item = nextItem ? nextItem.id : null;
|
|
300
|
+
state.runs.active[runIndex] = activeRun;
|
|
303
301
|
|
|
304
302
|
// Update run log
|
|
305
|
-
updateRunLog(runLogPath,
|
|
303
|
+
updateRunLog(runLogPath, activeRun, completionParams, completedTime, false);
|
|
306
304
|
|
|
307
305
|
// Save state
|
|
308
306
|
writeState(statePath, state);
|
|
@@ -335,25 +333,32 @@ function completeRun(rootPath, runId, params = {}) {
|
|
|
335
333
|
const { statePath, runLogPath } = validateFireProject(rootPath, runId);
|
|
336
334
|
const state = readState(statePath);
|
|
337
335
|
|
|
338
|
-
if
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
336
|
+
// Initialize runs structure if needed
|
|
337
|
+
if (!state.runs) {
|
|
338
|
+
state.runs = { active: [], completed: [] };
|
|
339
|
+
}
|
|
340
|
+
if (!Array.isArray(state.runs.active)) {
|
|
341
|
+
state.runs.active = [];
|
|
342
|
+
}
|
|
343
|
+
if (!Array.isArray(state.runs.completed)) {
|
|
344
|
+
state.runs.completed = [];
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
|
|
347
|
+
// Find run in active runs list
|
|
348
|
+
const runIndex = state.runs.active.findIndex(r => r.id === runId);
|
|
349
|
+
|
|
350
|
+
if (runIndex === -1) {
|
|
347
351
|
throw fireError(
|
|
348
|
-
`Run
|
|
349
|
-
'
|
|
350
|
-
|
|
352
|
+
`Run "${runId}" not found in active runs.`,
|
|
353
|
+
'COMPLETE_040',
|
|
354
|
+
'The run may have already been completed or was never started.'
|
|
351
355
|
);
|
|
352
356
|
}
|
|
353
357
|
|
|
358
|
+
const activeRun = state.runs.active[runIndex];
|
|
354
359
|
const completedTime = new Date().toISOString();
|
|
355
|
-
const workItems =
|
|
356
|
-
const scope =
|
|
360
|
+
const workItems = activeRun.work_items || [];
|
|
361
|
+
const scope = activeRun.scope || 'single';
|
|
357
362
|
|
|
358
363
|
// Mark all items as completed
|
|
359
364
|
for (const item of workItems) {
|
|
@@ -363,11 +368,11 @@ function completeRun(rootPath, runId, params = {}) {
|
|
|
363
368
|
}
|
|
364
369
|
}
|
|
365
370
|
|
|
366
|
-
|
|
367
|
-
|
|
371
|
+
activeRun.work_items = workItems;
|
|
372
|
+
activeRun.current_item = null;
|
|
368
373
|
|
|
369
374
|
// Update run log
|
|
370
|
-
updateRunLog(runLogPath,
|
|
375
|
+
updateRunLog(runLogPath, activeRun, completionParams, completedTime, true);
|
|
371
376
|
|
|
372
377
|
// Build completed run record
|
|
373
378
|
const completedRun = {
|
|
@@ -378,15 +383,12 @@ function completeRun(rootPath, runId, params = {}) {
|
|
|
378
383
|
intent: i.intent,
|
|
379
384
|
mode: i.mode,
|
|
380
385
|
})),
|
|
386
|
+
started: activeRun.started,
|
|
381
387
|
completed: completedTime,
|
|
382
388
|
};
|
|
383
389
|
|
|
384
|
-
// Get existing runs history or initialize
|
|
385
|
-
const existingRuns = state.runs || { completed: [] };
|
|
386
|
-
const existingCompleted = Array.isArray(existingRuns.completed) ? existingRuns.completed : [];
|
|
387
|
-
|
|
388
390
|
// Check for duplicate (idempotency)
|
|
389
|
-
const alreadyRecorded =
|
|
391
|
+
const alreadyRecorded = state.runs.completed.some(r => r.id === runId);
|
|
390
392
|
|
|
391
393
|
// Update work item status in intents
|
|
392
394
|
if (Array.isArray(state.intents)) {
|
|
@@ -405,11 +407,11 @@ function completeRun(rootPath, runId, params = {}) {
|
|
|
405
407
|
}
|
|
406
408
|
}
|
|
407
409
|
|
|
408
|
-
//
|
|
409
|
-
state.
|
|
410
|
-
|
|
411
|
-
completed
|
|
412
|
-
}
|
|
410
|
+
// Remove from active runs and add to completed
|
|
411
|
+
state.runs.active.splice(runIndex, 1);
|
|
412
|
+
if (!alreadyRecorded) {
|
|
413
|
+
state.runs.completed.push(completedRun);
|
|
414
|
+
}
|
|
413
415
|
|
|
414
416
|
// Save state
|
|
415
417
|
writeState(statePath, state);
|
|
@@ -317,13 +317,15 @@ function initRun(rootPath, workItems, scope) {
|
|
|
317
317
|
// Read state
|
|
318
318
|
const state = readState(statePath);
|
|
319
319
|
|
|
320
|
-
//
|
|
321
|
-
if (state.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
320
|
+
// Initialize runs structure if needed
|
|
321
|
+
if (!state.runs) {
|
|
322
|
+
state.runs = { active: [], completed: [] };
|
|
323
|
+
}
|
|
324
|
+
if (!Array.isArray(state.runs.active)) {
|
|
325
|
+
state.runs.active = [];
|
|
326
|
+
}
|
|
327
|
+
if (!Array.isArray(state.runs.completed)) {
|
|
328
|
+
state.runs.completed = [];
|
|
327
329
|
}
|
|
328
330
|
|
|
329
331
|
// Generate run ID (checks both history AND file system)
|
|
@@ -345,14 +347,14 @@ function initRun(rootPath, workItems, scope) {
|
|
|
345
347
|
status: index === 0 ? 'in_progress' : 'pending',
|
|
346
348
|
}));
|
|
347
349
|
|
|
348
|
-
//
|
|
349
|
-
state.
|
|
350
|
+
// Add to active runs list (supports multiple parallel runs)
|
|
351
|
+
state.runs.active.push({
|
|
350
352
|
id: runId,
|
|
351
353
|
scope: detectedScope,
|
|
352
354
|
work_items: stateWorkItems,
|
|
353
355
|
current_item: workItems[0].id,
|
|
354
356
|
started: startTime,
|
|
355
|
-
};
|
|
357
|
+
});
|
|
356
358
|
|
|
357
359
|
// Save state
|
|
358
360
|
writeState(statePath, state);
|
|
@@ -55,14 +55,16 @@ state:
|
|
|
55
55
|
- title: "Intent title"
|
|
56
56
|
- status: "pending | in_progress | completed"
|
|
57
57
|
- work_items: "List of work items"
|
|
58
|
-
active_run:
|
|
59
|
-
- id: "Current run ID"
|
|
60
|
-
- scope: "single | batch | wide"
|
|
61
|
-
- work_items: "List of work items in this run"
|
|
62
|
-
- current_item: "Work item currently being executed"
|
|
63
|
-
- started: "ISO 8601 timestamp"
|
|
64
58
|
runs:
|
|
59
|
+
- active: "List of currently active runs (supports multiple parallel runs)"
|
|
65
60
|
- completed: "List of completed runs with id, work_item, intent, completed timestamp"
|
|
61
|
+
# Each run (active or completed) has:
|
|
62
|
+
# - id: "Run ID (e.g., run-001)"
|
|
63
|
+
# - scope: "single | batch | wide"
|
|
64
|
+
# - work_items: "List of work items in this run"
|
|
65
|
+
# - current_item: "Work item currently being executed (active runs only)"
|
|
66
|
+
# - started: "ISO 8601 timestamp"
|
|
67
|
+
# - completed: "ISO 8601 timestamp (completed runs only)"
|
|
66
68
|
|
|
67
69
|
# Data Conventions
|
|
68
70
|
conventions:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|