substrate-ai 0.7.1 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +21 -8
- package/dist/{health-Dnx-FGva.js → health-C-VRJruD.js} +502 -23
- package/dist/{health-4fyhDU6T.js → health-DMbNP9bw.js} +1 -1
- package/dist/index.d.ts +55 -1
- package/dist/{run-CZokQlIi.js → run-C2dsqnZU.js} +2 -2
- package/dist/{run-BW8_vcTi.js → run-VMOBJZ7f.js} +490 -185
- package/package.json +1 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BMAD_BASELINE_TOKENS_FULL, DoltClient, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, initSchema, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-
|
|
1
|
+
import { BMAD_BASELINE_TOKENS_FULL, DoltClient, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, initSchema, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-C-VRJruD.js";
|
|
2
2
|
import { createLogger, deepMask } from "./logger-D2fS2ccL.js";
|
|
3
3
|
import { CURRENT_CONFIG_FORMAT_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "./config-migrator-CtGelIsG.js";
|
|
4
4
|
import { ConfigError, ConfigIncompatibleFormatError, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CpMs8VZX.js";
|
|
@@ -7,7 +7,7 @@ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, ge
|
|
|
7
7
|
import { ADVISORY_NOTES, ESCALATION_DIAGNOSIS, OPERATIONAL_FINDING, STORY_METRICS, STORY_OUTCOME, TEST_EXPANSION_FINDING, TEST_PLAN, aggregateTokenUsageForRun, aggregateTokenUsageForStory, getStoryMetricsForRun, writeRunMetrics, writeStoryMetrics } from "./operational-BdcdmDqS.js";
|
|
8
8
|
import { dirname, join, resolve } from "path";
|
|
9
9
|
import { access, mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
|
|
10
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
|
|
11
11
|
import yaml from "js-yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { execFile, execSync, spawn } from "node:child_process";
|
|
@@ -1588,6 +1588,34 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
1588
1588
|
}
|
|
1589
1589
|
]
|
|
1590
1590
|
},
|
|
1591
|
+
{
|
|
1592
|
+
type: "pipeline:phase-start",
|
|
1593
|
+
description: "A pipeline phase has started during full pipeline execution.",
|
|
1594
|
+
when: "When --from is used and a phase begins (analysis, planning, solutioning, implementation).",
|
|
1595
|
+
fields: [{
|
|
1596
|
+
name: "ts",
|
|
1597
|
+
type: "string",
|
|
1598
|
+
description: "Timestamp."
|
|
1599
|
+
}, {
|
|
1600
|
+
name: "phase",
|
|
1601
|
+
type: "string",
|
|
1602
|
+
description: "Phase name (e.g., analysis, implementation)."
|
|
1603
|
+
}]
|
|
1604
|
+
},
|
|
1605
|
+
{
|
|
1606
|
+
type: "pipeline:phase-complete",
|
|
1607
|
+
description: "A pipeline phase has completed during full pipeline execution.",
|
|
1608
|
+
when: "When --from is used and a phase finishes successfully.",
|
|
1609
|
+
fields: [{
|
|
1610
|
+
name: "ts",
|
|
1611
|
+
type: "string",
|
|
1612
|
+
description: "Timestamp."
|
|
1613
|
+
}, {
|
|
1614
|
+
name: "phase",
|
|
1615
|
+
type: "string",
|
|
1616
|
+
description: "Phase name (e.g., analysis, implementation)."
|
|
1617
|
+
}]
|
|
1618
|
+
},
|
|
1591
1619
|
{
|
|
1592
1620
|
type: "pipeline:pre-flight-failure",
|
|
1593
1621
|
description: "Pre-flight build check failed before any story was dispatched. Pipeline aborts immediately.",
|
|
@@ -13269,7 +13297,8 @@ function wgStatusForPhase(phase) {
|
|
|
13269
13297
|
case "IN_TEST_PLANNING":
|
|
13270
13298
|
case "IN_DEV":
|
|
13271
13299
|
case "IN_REVIEW":
|
|
13272
|
-
case "NEEDS_FIXES":
|
|
13300
|
+
case "NEEDS_FIXES":
|
|
13301
|
+
case "CHECKPOINT": return "in_progress";
|
|
13273
13302
|
case "COMPLETE": return "complete";
|
|
13274
13303
|
case "ESCALATED": return "escalated";
|
|
13275
13304
|
}
|
|
@@ -13358,6 +13387,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13358
13387
|
let _contractMismatches;
|
|
13359
13388
|
let _otlpEndpoint;
|
|
13360
13389
|
const _stateStoreCache = new Map();
|
|
13390
|
+
const _checkpoints = new Map();
|
|
13361
13391
|
const MEMORY_PRESSURE_BACKOFF_MS = [
|
|
13362
13392
|
3e4,
|
|
13363
13393
|
6e4,
|
|
@@ -13568,7 +13598,8 @@ function createImplementationOrchestrator(deps) {
|
|
|
13568
13598
|
lastVerdict: record.lastVerdict,
|
|
13569
13599
|
error: record.error,
|
|
13570
13600
|
startedAt: record.startedAt,
|
|
13571
|
-
completedAt: record.completedAt
|
|
13601
|
+
completedAt: record.completedAt,
|
|
13602
|
+
checkpointFilesCount: record.checkpointFilesCount
|
|
13572
13603
|
};
|
|
13573
13604
|
for (const [key, s] of _stories) stories[key] = { ...s };
|
|
13574
13605
|
const status = {
|
|
@@ -13641,7 +13672,8 @@ function createImplementationOrchestrator(deps) {
|
|
|
13641
13672
|
error: state.error,
|
|
13642
13673
|
startedAt: state.startedAt,
|
|
13643
13674
|
completedAt: state.completedAt,
|
|
13644
|
-
sprint: config.sprint
|
|
13675
|
+
sprint: config.sprint,
|
|
13676
|
+
checkpointFilesCount: state.checkpointFilesCount
|
|
13645
13677
|
};
|
|
13646
13678
|
await stateStore.setStoryState(storyKey, record);
|
|
13647
13679
|
} catch (err) {
|
|
@@ -14244,7 +14276,187 @@ function createImplementationOrchestrator(deps) {
|
|
|
14244
14276
|
result: devResult
|
|
14245
14277
|
});
|
|
14246
14278
|
await persistState();
|
|
14247
|
-
|
|
14279
|
+
let checkpointHandled = false;
|
|
14280
|
+
if (devResult.result === "failed" && devResult.error?.startsWith("dispatch_timeout")) {
|
|
14281
|
+
endPhase(storyKey, "dev-story");
|
|
14282
|
+
const timeoutFiles = checkGitDiffFiles(projectRoot ?? process.cwd());
|
|
14283
|
+
if (timeoutFiles.length === 0) {
|
|
14284
|
+
logger$25.warn({ storyKey }, "Dev-story timeout with zero modified files — escalating immediately (no checkpoint)");
|
|
14285
|
+
updateStory(storyKey, {
|
|
14286
|
+
phase: "ESCALATED",
|
|
14287
|
+
error: "timeout-no-files",
|
|
14288
|
+
completedAt: new Date().toISOString()
|
|
14289
|
+
});
|
|
14290
|
+
await writeStoryMetricsBestEffort(storyKey, "escalated", 0);
|
|
14291
|
+
await emitEscalation({
|
|
14292
|
+
storyKey,
|
|
14293
|
+
lastVerdict: "timeout-no-files",
|
|
14294
|
+
reviewCycles: 0,
|
|
14295
|
+
issues: ["dev-story timed out with no partial files — nothing to checkpoint"]
|
|
14296
|
+
});
|
|
14297
|
+
await persistState();
|
|
14298
|
+
return;
|
|
14299
|
+
}
|
|
14300
|
+
logger$25.info({
|
|
14301
|
+
storyKey,
|
|
14302
|
+
filesCount: timeoutFiles.length
|
|
14303
|
+
}, "Dev-story timeout with partial files — capturing checkpoint");
|
|
14304
|
+
let gitDiff = "";
|
|
14305
|
+
try {
|
|
14306
|
+
gitDiff = execSync(`git diff HEAD -- ${timeoutFiles.map((f) => `"${f}"`).join(" ")}`, {
|
|
14307
|
+
cwd: projectRoot ?? process.cwd(),
|
|
14308
|
+
encoding: "utf-8",
|
|
14309
|
+
timeout: 1e4,
|
|
14310
|
+
stdio: [
|
|
14311
|
+
"ignore",
|
|
14312
|
+
"pipe",
|
|
14313
|
+
"pipe"
|
|
14314
|
+
]
|
|
14315
|
+
}).trim();
|
|
14316
|
+
} catch (diffErr) {
|
|
14317
|
+
logger$25.warn({
|
|
14318
|
+
storyKey,
|
|
14319
|
+
error: diffErr instanceof Error ? diffErr.message : String(diffErr)
|
|
14320
|
+
}, "Failed to capture git diff for checkpoint — proceeding with empty diff");
|
|
14321
|
+
}
|
|
14322
|
+
_checkpoints.set(storyKey, {
|
|
14323
|
+
filesModified: timeoutFiles,
|
|
14324
|
+
gitDiff,
|
|
14325
|
+
partialOutput: devResult.error ?? ""
|
|
14326
|
+
});
|
|
14327
|
+
updateStory(storyKey, {
|
|
14328
|
+
phase: "CHECKPOINT",
|
|
14329
|
+
checkpointFilesCount: timeoutFiles.length
|
|
14330
|
+
});
|
|
14331
|
+
const diffSizeBytes = Buffer.byteLength(gitDiff, "utf-8");
|
|
14332
|
+
eventBus.emit("story:checkpoint-saved", {
|
|
14333
|
+
storyKey,
|
|
14334
|
+
filesCount: timeoutFiles.length,
|
|
14335
|
+
diffSizeBytes
|
|
14336
|
+
});
|
|
14337
|
+
if (stateStore !== void 0) stateStore.recordMetric({
|
|
14338
|
+
storyKey,
|
|
14339
|
+
taskType: "dev-story",
|
|
14340
|
+
result: "timeout",
|
|
14341
|
+
recordedAt: new Date().toISOString(),
|
|
14342
|
+
sprint: config.sprint
|
|
14343
|
+
}).catch((storeErr) => {
|
|
14344
|
+
logger$25.warn({
|
|
14345
|
+
err: storeErr,
|
|
14346
|
+
storyKey
|
|
14347
|
+
}, "Failed to record timeout metric to StateStore (best-effort)");
|
|
14348
|
+
});
|
|
14349
|
+
await persistState();
|
|
14350
|
+
eventBus.emit("story:checkpoint-retry", {
|
|
14351
|
+
storyKey,
|
|
14352
|
+
filesCount: timeoutFiles.length,
|
|
14353
|
+
attempt: 2
|
|
14354
|
+
});
|
|
14355
|
+
const checkpointData = _checkpoints.get(storyKey);
|
|
14356
|
+
let checkpointRetryPrompt;
|
|
14357
|
+
let checkpointRetryMaxTurns;
|
|
14358
|
+
try {
|
|
14359
|
+
const devStoryTemplate = await pack.getPrompt("dev-story");
|
|
14360
|
+
const storyContent = await readFile$1(storyFilePath ?? "", "utf-8");
|
|
14361
|
+
const complexity = computeStoryComplexity(storyContent);
|
|
14362
|
+
checkpointRetryMaxTurns = resolveDevStoryMaxTurns(complexity.complexityScore);
|
|
14363
|
+
logComplexityResult(storyKey, complexity, checkpointRetryMaxTurns);
|
|
14364
|
+
let archConstraints = "";
|
|
14365
|
+
try {
|
|
14366
|
+
const decisions = await getDecisionsByPhase(db, "solutioning");
|
|
14367
|
+
const constraints = decisions.filter((d) => d.category === "architecture");
|
|
14368
|
+
archConstraints = constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
14369
|
+
} catch {}
|
|
14370
|
+
const checkpointContext = [
|
|
14371
|
+
"Your prior attempt timed out. Here is the work you completed:",
|
|
14372
|
+
"",
|
|
14373
|
+
`Files modified (${checkpointData.filesModified.length}):`,
|
|
14374
|
+
...checkpointData.filesModified.map((f) => `- ${f}`),
|
|
14375
|
+
"",
|
|
14376
|
+
"```diff",
|
|
14377
|
+
checkpointData.gitDiff || "(no diff available)",
|
|
14378
|
+
"```",
|
|
14379
|
+
"",
|
|
14380
|
+
"Continue from where you left off. Do not redo completed work."
|
|
14381
|
+
].join("\n");
|
|
14382
|
+
const sections = [
|
|
14383
|
+
{
|
|
14384
|
+
name: "story_content",
|
|
14385
|
+
content: storyContent,
|
|
14386
|
+
priority: "required"
|
|
14387
|
+
},
|
|
14388
|
+
{
|
|
14389
|
+
name: "checkpoint_context",
|
|
14390
|
+
content: checkpointContext,
|
|
14391
|
+
priority: "required"
|
|
14392
|
+
},
|
|
14393
|
+
{
|
|
14394
|
+
name: "arch_constraints",
|
|
14395
|
+
content: archConstraints,
|
|
14396
|
+
priority: "optional"
|
|
14397
|
+
}
|
|
14398
|
+
];
|
|
14399
|
+
const assembled = assemblePrompt(devStoryTemplate, sections, 24e3);
|
|
14400
|
+
checkpointRetryPrompt = assembled.prompt;
|
|
14401
|
+
} catch {
|
|
14402
|
+
checkpointRetryPrompt = `Continue story ${storyKey} from checkpoint. Your prior attempt timed out. Do not redo completed work.`;
|
|
14403
|
+
logger$25.warn({ storyKey }, "Failed to assemble checkpoint retry prompt — using fallback");
|
|
14404
|
+
}
|
|
14405
|
+
logger$25.info({
|
|
14406
|
+
storyKey,
|
|
14407
|
+
filesCount: checkpointData.filesModified.length
|
|
14408
|
+
}, "Dispatching checkpoint retry for timed-out story");
|
|
14409
|
+
incrementDispatches(storyKey);
|
|
14410
|
+
updateStory(storyKey, { phase: "IN_DEV" });
|
|
14411
|
+
startPhase(storyKey, "dev-story-retry");
|
|
14412
|
+
const checkpointRetryHandle = dispatcher.dispatch({
|
|
14413
|
+
prompt: checkpointRetryPrompt,
|
|
14414
|
+
agent: "claude-code",
|
|
14415
|
+
taskType: "dev-story",
|
|
14416
|
+
outputSchema: DevStoryResultSchema,
|
|
14417
|
+
...checkpointRetryMaxTurns !== void 0 ? { maxTurns: checkpointRetryMaxTurns } : {},
|
|
14418
|
+
...projectRoot !== void 0 ? { workingDirectory: projectRoot } : {},
|
|
14419
|
+
..._otlpEndpoint !== void 0 ? { otlpEndpoint: _otlpEndpoint } : {},
|
|
14420
|
+
...config.perStoryContextCeilings?.[storyKey] !== void 0 ? { maxContextTokens: config.perStoryContextCeilings[storyKey] } : {},
|
|
14421
|
+
storyKey
|
|
14422
|
+
});
|
|
14423
|
+
const checkpointRetryResult = await checkpointRetryHandle.result;
|
|
14424
|
+
endPhase(storyKey, "dev-story-retry");
|
|
14425
|
+
eventBus.emit("orchestrator:story-phase-complete", {
|
|
14426
|
+
storyKey,
|
|
14427
|
+
phase: "IN_DEV",
|
|
14428
|
+
result: { tokenUsage: checkpointRetryResult.tokenEstimate ? {
|
|
14429
|
+
input: checkpointRetryResult.tokenEstimate.input,
|
|
14430
|
+
output: checkpointRetryResult.tokenEstimate.output
|
|
14431
|
+
} : void 0 }
|
|
14432
|
+
});
|
|
14433
|
+
if (checkpointRetryResult.status === "timeout") {
|
|
14434
|
+
logger$25.warn({ storyKey }, "Checkpoint retry dispatch timed out — escalating story");
|
|
14435
|
+
updateStory(storyKey, {
|
|
14436
|
+
phase: "ESCALATED",
|
|
14437
|
+
error: "checkpoint-retry-timeout",
|
|
14438
|
+
completedAt: new Date().toISOString()
|
|
14439
|
+
});
|
|
14440
|
+
await writeStoryMetricsBestEffort(storyKey, "escalated", 0);
|
|
14441
|
+
await emitEscalation({
|
|
14442
|
+
storyKey,
|
|
14443
|
+
lastVerdict: "checkpoint-retry-timeout",
|
|
14444
|
+
reviewCycles: 0,
|
|
14445
|
+
issues: ["checkpoint retry timed out — no infinite retry loop"]
|
|
14446
|
+
});
|
|
14447
|
+
await persistState();
|
|
14448
|
+
return;
|
|
14449
|
+
}
|
|
14450
|
+
const retryParsed = checkpointRetryResult.parsed;
|
|
14451
|
+
devFilesModified = retryParsed?.files_modified ?? checkGitDiffFiles(projectRoot ?? process.cwd());
|
|
14452
|
+
if (checkpointRetryResult.status === "completed" && retryParsed?.result === "success") devStoryWasSuccess = true;
|
|
14453
|
+
else logger$25.warn({
|
|
14454
|
+
storyKey,
|
|
14455
|
+
status: checkpointRetryResult.status
|
|
14456
|
+
}, "Checkpoint retry completed with failure — proceeding to code review");
|
|
14457
|
+
checkpointHandled = true;
|
|
14458
|
+
}
|
|
14459
|
+
if (!checkpointHandled) if (devResult.result === "success") devStoryWasSuccess = true;
|
|
14248
14460
|
else logger$25.warn({
|
|
14249
14461
|
storyKey,
|
|
14250
14462
|
error: devResult.error,
|
|
@@ -19794,6 +20006,189 @@ function mapInternalPhaseToEventPhase(internalPhase) {
|
|
|
19794
20006
|
default: return null;
|
|
19795
20007
|
}
|
|
19796
20008
|
}
|
|
20009
|
+
/**
|
|
20010
|
+
* Wire all NDJSON event subscriptions from the event bus to the emitter.
|
|
20011
|
+
* Shared helper called from both the implementation-only path and the full
|
|
20012
|
+
* pipeline path (AC2: shared event subscription logic).
|
|
20013
|
+
*/
|
|
20014
|
+
function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
|
|
20015
|
+
eventBus.on("orchestrator:story-phase-start", (payload) => {
|
|
20016
|
+
const phase = mapInternalPhaseToEventPhase(payload.phase);
|
|
20017
|
+
if (phase !== null) ndjsonEmitter.emit({
|
|
20018
|
+
type: "story:phase",
|
|
20019
|
+
ts: new Date().toISOString(),
|
|
20020
|
+
key: payload.storyKey,
|
|
20021
|
+
phase,
|
|
20022
|
+
status: "in_progress"
|
|
20023
|
+
});
|
|
20024
|
+
});
|
|
20025
|
+
eventBus.on("orchestrator:story-phase-complete", (payload) => {
|
|
20026
|
+
const phase = mapInternalPhaseToEventPhase(payload.phase);
|
|
20027
|
+
if (phase !== null) {
|
|
20028
|
+
const result = payload.result;
|
|
20029
|
+
ndjsonEmitter.emit({
|
|
20030
|
+
type: "story:phase",
|
|
20031
|
+
ts: new Date().toISOString(),
|
|
20032
|
+
key: payload.storyKey,
|
|
20033
|
+
phase,
|
|
20034
|
+
status: "complete",
|
|
20035
|
+
...phase === "code-review" && result?.verdict !== void 0 ? { verdict: result.verdict } : {},
|
|
20036
|
+
...phase === "create-story" && result?.story_file !== void 0 ? { file: result.story_file } : {}
|
|
20037
|
+
});
|
|
20038
|
+
}
|
|
20039
|
+
});
|
|
20040
|
+
eventBus.on("routing:model-selected", (payload) => {
|
|
20041
|
+
ndjsonEmitter.emit({
|
|
20042
|
+
type: "routing:model-selected",
|
|
20043
|
+
ts: new Date().toISOString(),
|
|
20044
|
+
dispatch_id: payload.dispatchId,
|
|
20045
|
+
task_type: payload.taskType,
|
|
20046
|
+
phase: payload.phase,
|
|
20047
|
+
model: payload.model,
|
|
20048
|
+
source: payload.source
|
|
20049
|
+
});
|
|
20050
|
+
});
|
|
20051
|
+
eventBus.on("orchestrator:story-complete", (payload) => {
|
|
20052
|
+
ndjsonEmitter.emit({
|
|
20053
|
+
type: "story:done",
|
|
20054
|
+
ts: new Date().toISOString(),
|
|
20055
|
+
key: payload.storyKey,
|
|
20056
|
+
result: "success",
|
|
20057
|
+
review_cycles: payload.reviewCycles
|
|
20058
|
+
});
|
|
20059
|
+
});
|
|
20060
|
+
eventBus.on("orchestrator:story-escalated", (payload) => {
|
|
20061
|
+
const rawIssues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
20062
|
+
const issues = rawIssues.map((issue) => {
|
|
20063
|
+
const iss = issue;
|
|
20064
|
+
return {
|
|
20065
|
+
severity: iss.severity ?? "unknown",
|
|
20066
|
+
file: iss.file ?? "",
|
|
20067
|
+
desc: iss.desc ?? iss.description ?? ""
|
|
20068
|
+
};
|
|
20069
|
+
});
|
|
20070
|
+
ndjsonEmitter.emit({
|
|
20071
|
+
type: "story:escalation",
|
|
20072
|
+
ts: new Date().toISOString(),
|
|
20073
|
+
key: payload.storyKey,
|
|
20074
|
+
reason: payload.lastVerdict ?? "escalated",
|
|
20075
|
+
cycles: payload.reviewCycles ?? 0,
|
|
20076
|
+
issues,
|
|
20077
|
+
...payload.diagnosis !== void 0 ? { diagnosis: payload.diagnosis } : {}
|
|
20078
|
+
});
|
|
20079
|
+
});
|
|
20080
|
+
eventBus.on("orchestrator:story-warn", (payload) => {
|
|
20081
|
+
ndjsonEmitter.emit({
|
|
20082
|
+
type: "story:warn",
|
|
20083
|
+
ts: new Date().toISOString(),
|
|
20084
|
+
key: payload.storyKey,
|
|
20085
|
+
msg: payload.msg
|
|
20086
|
+
});
|
|
20087
|
+
});
|
|
20088
|
+
eventBus.on("orchestrator:heartbeat", (payload) => {
|
|
20089
|
+
ndjsonEmitter.emit({
|
|
20090
|
+
type: "pipeline:heartbeat",
|
|
20091
|
+
ts: new Date().toISOString(),
|
|
20092
|
+
run_id: payload.runId,
|
|
20093
|
+
active_dispatches: payload.activeDispatches,
|
|
20094
|
+
completed_dispatches: payload.completedDispatches,
|
|
20095
|
+
queued_dispatches: payload.queuedDispatches
|
|
20096
|
+
});
|
|
20097
|
+
});
|
|
20098
|
+
eventBus.on("orchestrator:stall", (payload) => {
|
|
20099
|
+
ndjsonEmitter.emit({
|
|
20100
|
+
type: "story:stall",
|
|
20101
|
+
ts: new Date().toISOString(),
|
|
20102
|
+
run_id: payload.runId,
|
|
20103
|
+
story_key: payload.storyKey,
|
|
20104
|
+
phase: payload.phase,
|
|
20105
|
+
elapsed_ms: payload.elapsedMs,
|
|
20106
|
+
child_pids: payload.childPids,
|
|
20107
|
+
child_active: payload.childActive
|
|
20108
|
+
});
|
|
20109
|
+
});
|
|
20110
|
+
eventBus.on("orchestrator:zero-diff-escalation", (payload) => {
|
|
20111
|
+
ndjsonEmitter.emit({
|
|
20112
|
+
type: "story:zero-diff-escalation",
|
|
20113
|
+
ts: new Date().toISOString(),
|
|
20114
|
+
storyKey: payload.storyKey,
|
|
20115
|
+
reason: payload.reason
|
|
20116
|
+
});
|
|
20117
|
+
});
|
|
20118
|
+
eventBus.on("story:build-verification-passed", (payload) => {
|
|
20119
|
+
ndjsonEmitter.emit({
|
|
20120
|
+
type: "story:build-verification-passed",
|
|
20121
|
+
ts: new Date().toISOString(),
|
|
20122
|
+
storyKey: payload.storyKey
|
|
20123
|
+
});
|
|
20124
|
+
});
|
|
20125
|
+
eventBus.on("story:build-verification-failed", (payload) => {
|
|
20126
|
+
ndjsonEmitter.emit({
|
|
20127
|
+
type: "story:build-verification-failed",
|
|
20128
|
+
ts: new Date().toISOString(),
|
|
20129
|
+
storyKey: payload.storyKey,
|
|
20130
|
+
exitCode: payload.exitCode,
|
|
20131
|
+
output: payload.output
|
|
20132
|
+
});
|
|
20133
|
+
});
|
|
20134
|
+
eventBus.on("story:interface-change-warning", (payload) => {
|
|
20135
|
+
ndjsonEmitter.emit({
|
|
20136
|
+
type: "story:interface-change-warning",
|
|
20137
|
+
ts: new Date().toISOString(),
|
|
20138
|
+
storyKey: payload.storyKey,
|
|
20139
|
+
modifiedInterfaces: payload.modifiedInterfaces,
|
|
20140
|
+
potentiallyAffectedTests: payload.potentiallyAffectedTests
|
|
20141
|
+
});
|
|
20142
|
+
});
|
|
20143
|
+
eventBus.on("story:metrics", (payload) => {
|
|
20144
|
+
ndjsonEmitter.emit({
|
|
20145
|
+
type: "story:metrics",
|
|
20146
|
+
ts: new Date().toISOString(),
|
|
20147
|
+
storyKey: payload.storyKey,
|
|
20148
|
+
wallClockMs: payload.wallClockMs,
|
|
20149
|
+
phaseBreakdown: payload.phaseBreakdown,
|
|
20150
|
+
tokens: payload.tokens,
|
|
20151
|
+
reviewCycles: payload.reviewCycles,
|
|
20152
|
+
dispatches: payload.dispatches
|
|
20153
|
+
});
|
|
20154
|
+
});
|
|
20155
|
+
eventBus.on("pipeline:pre-flight-failure", (payload) => {
|
|
20156
|
+
ndjsonEmitter.emit({
|
|
20157
|
+
type: "pipeline:pre-flight-failure",
|
|
20158
|
+
ts: new Date().toISOString(),
|
|
20159
|
+
exitCode: payload.exitCode,
|
|
20160
|
+
output: payload.output + "\nTip: Use --skip-preflight to bypass, or check your build command in .substrate/project-profile.yaml"
|
|
20161
|
+
});
|
|
20162
|
+
});
|
|
20163
|
+
eventBus.on("pipeline:contract-mismatch", (payload) => {
|
|
20164
|
+
ndjsonEmitter.emit({
|
|
20165
|
+
type: "pipeline:contract-mismatch",
|
|
20166
|
+
ts: new Date().toISOString(),
|
|
20167
|
+
exporter: payload.exporter,
|
|
20168
|
+
importer: payload.importer,
|
|
20169
|
+
contractName: payload.contractName,
|
|
20170
|
+
mismatchDescription: payload.mismatchDescription
|
|
20171
|
+
});
|
|
20172
|
+
});
|
|
20173
|
+
eventBus.on("pipeline:contract-verification-summary", (payload) => {
|
|
20174
|
+
ndjsonEmitter.emit({
|
|
20175
|
+
type: "pipeline:contract-verification-summary",
|
|
20176
|
+
ts: new Date().toISOString(),
|
|
20177
|
+
verified: payload.verified,
|
|
20178
|
+
stalePruned: payload.stalePruned,
|
|
20179
|
+
mismatches: payload.mismatches,
|
|
20180
|
+
verdict: payload.verdict
|
|
20181
|
+
});
|
|
20182
|
+
});
|
|
20183
|
+
eventBus.on("pipeline:profile-stale", (payload) => {
|
|
20184
|
+
ndjsonEmitter.emit({
|
|
20185
|
+
type: "pipeline:profile-stale",
|
|
20186
|
+
ts: new Date().toISOString(),
|
|
20187
|
+
message: payload.message,
|
|
20188
|
+
indicators: payload.indicators
|
|
20189
|
+
});
|
|
20190
|
+
});
|
|
20191
|
+
}
|
|
19797
20192
|
async function runRunAction(options) {
|
|
19798
20193
|
const { pack: packName, from: startPhase, stopAfter, concept: conceptArg, conceptFile, stories: storiesArg, concurrency, outputFormat, projectRoot, events: eventsFlag, verbose: verboseFlag, tui: tuiFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, epic: epicNumber, dryRun, maxReviewCycles = 2, registry: injectedRegistry } = options;
|
|
19799
20194
|
if (startPhase !== void 0 && !VALID_PHASES.includes(startPhase)) {
|
|
@@ -19884,7 +20279,20 @@ async function runRunAction(options) {
|
|
|
19884
20279
|
}
|
|
19885
20280
|
}
|
|
19886
20281
|
let effectiveStartPhase = startPhase;
|
|
19887
|
-
if (effectiveStartPhase === void 0) {
|
|
20282
|
+
if (effectiveStartPhase === void 0) if (parsedStoryKeys.length > 0) {
|
|
20283
|
+
const artifactsDir = join(projectRoot, "_bmad-output", "implementation-artifacts");
|
|
20284
|
+
if (existsSync(artifactsDir)) {
|
|
20285
|
+
let files;
|
|
20286
|
+
try {
|
|
20287
|
+
const result = readdirSync(artifactsDir, { encoding: "utf-8" });
|
|
20288
|
+
if (Array.isArray(result)) files = result;
|
|
20289
|
+
} catch {}
|
|
20290
|
+
if (files !== void 0) {
|
|
20291
|
+
const missing = parsedStoryKeys.filter((key) => !files.some((f) => f.startsWith(`${key}-`) && f.endsWith(".md")));
|
|
20292
|
+
if (missing.length > 0) logger.info({ missing }, `Story files not found for ${missing.length} key(s) — create-story phase will generate them`);
|
|
20293
|
+
}
|
|
20294
|
+
}
|
|
20295
|
+
} else {
|
|
19888
20296
|
mkdirSync(dbDir, { recursive: true });
|
|
19889
20297
|
try {
|
|
19890
20298
|
const detectAdapter = createDatabaseAdapter({
|
|
@@ -20019,6 +20427,24 @@ async function runRunAction(options) {
|
|
|
20019
20427
|
...parsedStoryKeys.length > 0 ? { explicitStories: parsedStoryKeys } : {}
|
|
20020
20428
|
})
|
|
20021
20429
|
});
|
|
20430
|
+
const runIdFilePath = join(dbDir, "current-run-id");
|
|
20431
|
+
try {
|
|
20432
|
+
writeFileSync(runIdFilePath, pipelineRun.id, "utf-8");
|
|
20433
|
+
const cleanupRunIdFile = () => {
|
|
20434
|
+
try {
|
|
20435
|
+
unlinkSync(runIdFilePath);
|
|
20436
|
+
} catch {}
|
|
20437
|
+
};
|
|
20438
|
+
process.on("exit", cleanupRunIdFile);
|
|
20439
|
+
process.once("SIGTERM", () => {
|
|
20440
|
+
cleanupRunIdFile();
|
|
20441
|
+
process.exit(0);
|
|
20442
|
+
});
|
|
20443
|
+
process.once("SIGINT", () => {
|
|
20444
|
+
cleanupRunIdFile();
|
|
20445
|
+
process.exit(130);
|
|
20446
|
+
});
|
|
20447
|
+
} catch {}
|
|
20022
20448
|
const eventBus = createEventBus();
|
|
20023
20449
|
const contextCompiler = createContextCompiler({ db: adapter });
|
|
20024
20450
|
if (!injectedRegistry) throw new Error("AdapterRegistry is required — must be initialized at CLI startup");
|
|
@@ -20292,182 +20718,7 @@ async function runRunAction(options) {
|
|
|
20292
20718
|
stories: storyKeys,
|
|
20293
20719
|
concurrency
|
|
20294
20720
|
});
|
|
20295
|
-
eventBus
|
|
20296
|
-
const phase = mapInternalPhaseToEventPhase(payload.phase);
|
|
20297
|
-
if (phase !== null) ndjsonEmitter.emit({
|
|
20298
|
-
type: "story:phase",
|
|
20299
|
-
ts: new Date().toISOString(),
|
|
20300
|
-
key: payload.storyKey,
|
|
20301
|
-
phase,
|
|
20302
|
-
status: "in_progress"
|
|
20303
|
-
});
|
|
20304
|
-
});
|
|
20305
|
-
eventBus.on("orchestrator:story-phase-complete", (payload) => {
|
|
20306
|
-
const phase = mapInternalPhaseToEventPhase(payload.phase);
|
|
20307
|
-
if (phase !== null) {
|
|
20308
|
-
const result = payload.result;
|
|
20309
|
-
ndjsonEmitter.emit({
|
|
20310
|
-
type: "story:phase",
|
|
20311
|
-
ts: new Date().toISOString(),
|
|
20312
|
-
key: payload.storyKey,
|
|
20313
|
-
phase,
|
|
20314
|
-
status: "complete",
|
|
20315
|
-
...phase === "code-review" && result?.verdict !== void 0 ? { verdict: result.verdict } : {},
|
|
20316
|
-
...phase === "create-story" && result?.story_file !== void 0 ? { file: result.story_file } : {}
|
|
20317
|
-
});
|
|
20318
|
-
}
|
|
20319
|
-
});
|
|
20320
|
-
eventBus.on("routing:model-selected", (payload) => {
|
|
20321
|
-
ndjsonEmitter.emit({
|
|
20322
|
-
type: "routing:model-selected",
|
|
20323
|
-
ts: new Date().toISOString(),
|
|
20324
|
-
dispatch_id: payload.dispatchId,
|
|
20325
|
-
task_type: payload.taskType,
|
|
20326
|
-
phase: payload.phase,
|
|
20327
|
-
model: payload.model,
|
|
20328
|
-
source: payload.source
|
|
20329
|
-
});
|
|
20330
|
-
});
|
|
20331
|
-
eventBus.on("orchestrator:story-complete", (payload) => {
|
|
20332
|
-
ndjsonEmitter.emit({
|
|
20333
|
-
type: "story:done",
|
|
20334
|
-
ts: new Date().toISOString(),
|
|
20335
|
-
key: payload.storyKey,
|
|
20336
|
-
result: "success",
|
|
20337
|
-
review_cycles: payload.reviewCycles
|
|
20338
|
-
});
|
|
20339
|
-
});
|
|
20340
|
-
eventBus.on("orchestrator:story-escalated", (payload) => {
|
|
20341
|
-
const rawIssues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
20342
|
-
const issues = rawIssues.map((issue) => {
|
|
20343
|
-
const iss = issue;
|
|
20344
|
-
return {
|
|
20345
|
-
severity: iss.severity ?? "unknown",
|
|
20346
|
-
file: iss.file ?? "",
|
|
20347
|
-
desc: iss.desc ?? iss.description ?? ""
|
|
20348
|
-
};
|
|
20349
|
-
});
|
|
20350
|
-
ndjsonEmitter.emit({
|
|
20351
|
-
type: "story:escalation",
|
|
20352
|
-
ts: new Date().toISOString(),
|
|
20353
|
-
key: payload.storyKey,
|
|
20354
|
-
reason: payload.lastVerdict ?? "escalated",
|
|
20355
|
-
cycles: payload.reviewCycles ?? 0,
|
|
20356
|
-
issues,
|
|
20357
|
-
...payload.diagnosis !== void 0 ? { diagnosis: payload.diagnosis } : {}
|
|
20358
|
-
});
|
|
20359
|
-
});
|
|
20360
|
-
eventBus.on("orchestrator:story-warn", (payload) => {
|
|
20361
|
-
ndjsonEmitter.emit({
|
|
20362
|
-
type: "story:warn",
|
|
20363
|
-
ts: new Date().toISOString(),
|
|
20364
|
-
key: payload.storyKey,
|
|
20365
|
-
msg: payload.msg
|
|
20366
|
-
});
|
|
20367
|
-
});
|
|
20368
|
-
eventBus.on("orchestrator:heartbeat", (payload) => {
|
|
20369
|
-
ndjsonEmitter.emit({
|
|
20370
|
-
type: "pipeline:heartbeat",
|
|
20371
|
-
ts: new Date().toISOString(),
|
|
20372
|
-
run_id: payload.runId,
|
|
20373
|
-
active_dispatches: payload.activeDispatches,
|
|
20374
|
-
completed_dispatches: payload.completedDispatches,
|
|
20375
|
-
queued_dispatches: payload.queuedDispatches
|
|
20376
|
-
});
|
|
20377
|
-
});
|
|
20378
|
-
eventBus.on("orchestrator:stall", (payload) => {
|
|
20379
|
-
ndjsonEmitter.emit({
|
|
20380
|
-
type: "story:stall",
|
|
20381
|
-
ts: new Date().toISOString(),
|
|
20382
|
-
run_id: payload.runId,
|
|
20383
|
-
story_key: payload.storyKey,
|
|
20384
|
-
phase: payload.phase,
|
|
20385
|
-
elapsed_ms: payload.elapsedMs,
|
|
20386
|
-
child_pids: payload.childPids,
|
|
20387
|
-
child_active: payload.childActive
|
|
20388
|
-
});
|
|
20389
|
-
});
|
|
20390
|
-
eventBus.on("orchestrator:zero-diff-escalation", (payload) => {
|
|
20391
|
-
ndjsonEmitter.emit({
|
|
20392
|
-
type: "story:zero-diff-escalation",
|
|
20393
|
-
ts: new Date().toISOString(),
|
|
20394
|
-
storyKey: payload.storyKey,
|
|
20395
|
-
reason: payload.reason
|
|
20396
|
-
});
|
|
20397
|
-
});
|
|
20398
|
-
eventBus.on("story:build-verification-passed", (payload) => {
|
|
20399
|
-
ndjsonEmitter.emit({
|
|
20400
|
-
type: "story:build-verification-passed",
|
|
20401
|
-
ts: new Date().toISOString(),
|
|
20402
|
-
storyKey: payload.storyKey
|
|
20403
|
-
});
|
|
20404
|
-
});
|
|
20405
|
-
eventBus.on("story:build-verification-failed", (payload) => {
|
|
20406
|
-
ndjsonEmitter.emit({
|
|
20407
|
-
type: "story:build-verification-failed",
|
|
20408
|
-
ts: new Date().toISOString(),
|
|
20409
|
-
storyKey: payload.storyKey,
|
|
20410
|
-
exitCode: payload.exitCode,
|
|
20411
|
-
output: payload.output
|
|
20412
|
-
});
|
|
20413
|
-
});
|
|
20414
|
-
eventBus.on("story:interface-change-warning", (payload) => {
|
|
20415
|
-
ndjsonEmitter.emit({
|
|
20416
|
-
type: "story:interface-change-warning",
|
|
20417
|
-
ts: new Date().toISOString(),
|
|
20418
|
-
storyKey: payload.storyKey,
|
|
20419
|
-
modifiedInterfaces: payload.modifiedInterfaces,
|
|
20420
|
-
potentiallyAffectedTests: payload.potentiallyAffectedTests
|
|
20421
|
-
});
|
|
20422
|
-
});
|
|
20423
|
-
eventBus.on("story:metrics", (payload) => {
|
|
20424
|
-
ndjsonEmitter.emit({
|
|
20425
|
-
type: "story:metrics",
|
|
20426
|
-
ts: new Date().toISOString(),
|
|
20427
|
-
storyKey: payload.storyKey,
|
|
20428
|
-
wallClockMs: payload.wallClockMs,
|
|
20429
|
-
phaseBreakdown: payload.phaseBreakdown,
|
|
20430
|
-
tokens: payload.tokens,
|
|
20431
|
-
reviewCycles: payload.reviewCycles,
|
|
20432
|
-
dispatches: payload.dispatches
|
|
20433
|
-
});
|
|
20434
|
-
});
|
|
20435
|
-
eventBus.on("pipeline:pre-flight-failure", (payload) => {
|
|
20436
|
-
ndjsonEmitter.emit({
|
|
20437
|
-
type: "pipeline:pre-flight-failure",
|
|
20438
|
-
ts: new Date().toISOString(),
|
|
20439
|
-
exitCode: payload.exitCode,
|
|
20440
|
-
output: payload.output + "\nTip: Use --skip-preflight to bypass, or check your build command in .substrate/project-profile.yaml"
|
|
20441
|
-
});
|
|
20442
|
-
});
|
|
20443
|
-
eventBus.on("pipeline:contract-mismatch", (payload) => {
|
|
20444
|
-
ndjsonEmitter.emit({
|
|
20445
|
-
type: "pipeline:contract-mismatch",
|
|
20446
|
-
ts: new Date().toISOString(),
|
|
20447
|
-
exporter: payload.exporter,
|
|
20448
|
-
importer: payload.importer,
|
|
20449
|
-
contractName: payload.contractName,
|
|
20450
|
-
mismatchDescription: payload.mismatchDescription
|
|
20451
|
-
});
|
|
20452
|
-
});
|
|
20453
|
-
eventBus.on("pipeline:contract-verification-summary", (payload) => {
|
|
20454
|
-
ndjsonEmitter.emit({
|
|
20455
|
-
type: "pipeline:contract-verification-summary",
|
|
20456
|
-
ts: new Date().toISOString(),
|
|
20457
|
-
verified: payload.verified,
|
|
20458
|
-
stalePruned: payload.stalePruned,
|
|
20459
|
-
mismatches: payload.mismatches,
|
|
20460
|
-
verdict: payload.verdict
|
|
20461
|
-
});
|
|
20462
|
-
});
|
|
20463
|
-
eventBus.on("pipeline:profile-stale", (payload) => {
|
|
20464
|
-
ndjsonEmitter.emit({
|
|
20465
|
-
type: "pipeline:profile-stale",
|
|
20466
|
-
ts: new Date().toISOString(),
|
|
20467
|
-
message: payload.message,
|
|
20468
|
-
indicators: payload.indicators
|
|
20469
|
-
});
|
|
20470
|
-
});
|
|
20721
|
+
wireNdjsonEmitter(eventBus, ndjsonEmitter);
|
|
20471
20722
|
}
|
|
20472
20723
|
const ingestionServer = telemetryEnabled ? new IngestionServer({ port: telemetryPort }) : void 0;
|
|
20473
20724
|
if (ingestionServer !== void 0) {
|
|
@@ -20688,6 +20939,24 @@ async function runFullPipeline(options) {
|
|
|
20688
20939
|
});
|
|
20689
20940
|
const startedAt = Date.now();
|
|
20690
20941
|
const runId = await phaseOrchestrator.startRun(concept ?? "", startPhase);
|
|
20942
|
+
const runIdFilePath = join(dbDir, "current-run-id");
|
|
20943
|
+
try {
|
|
20944
|
+
writeFileSync(runIdFilePath, runId, "utf-8");
|
|
20945
|
+
const cleanupRunIdFile = () => {
|
|
20946
|
+
try {
|
|
20947
|
+
unlinkSync(runIdFilePath);
|
|
20948
|
+
} catch {}
|
|
20949
|
+
};
|
|
20950
|
+
process.on("exit", cleanupRunIdFile);
|
|
20951
|
+
process.once("SIGTERM", () => {
|
|
20952
|
+
cleanupRunIdFile();
|
|
20953
|
+
process.exit(0);
|
|
20954
|
+
});
|
|
20955
|
+
process.once("SIGINT", () => {
|
|
20956
|
+
cleanupRunIdFile();
|
|
20957
|
+
process.exit(130);
|
|
20958
|
+
});
|
|
20959
|
+
} catch {}
|
|
20691
20960
|
if (explicitStories !== void 0 && explicitStories.length > 0 || options.epic !== void 0) {
|
|
20692
20961
|
const existingRun = (await adapter.query("SELECT config_json FROM pipeline_runs WHERE id = ?", [runId]))[0];
|
|
20693
20962
|
const existing = JSON.parse(existingRun?.config_json ?? "{}");
|
|
@@ -20702,14 +20971,34 @@ async function runFullPipeline(options) {
|
|
|
20702
20971
|
process.stdout.write(`Starting full pipeline from phase: ${startPhase}\n`);
|
|
20703
20972
|
process.stdout.write(`Pipeline run ID: ${runId}\n`);
|
|
20704
20973
|
}
|
|
20974
|
+
let fullPipelineNdjsonEmitter;
|
|
20975
|
+
if (eventsFlag === true) {
|
|
20976
|
+
fullPipelineNdjsonEmitter = createEventEmitter(process.stdout);
|
|
20977
|
+
fullPipelineNdjsonEmitter.emit({
|
|
20978
|
+
type: "pipeline:start",
|
|
20979
|
+
ts: new Date().toISOString(),
|
|
20980
|
+
run_id: runId,
|
|
20981
|
+
stories: explicitStories ?? [],
|
|
20982
|
+
concurrency
|
|
20983
|
+
});
|
|
20984
|
+
wireNdjsonEmitter(eventBus, fullPipelineNdjsonEmitter);
|
|
20985
|
+
}
|
|
20705
20986
|
const phaseOrder = [];
|
|
20706
20987
|
if (effectiveResearch) phaseOrder.push("research");
|
|
20707
20988
|
phaseOrder.push("analysis", "planning");
|
|
20708
20989
|
if (effectiveUxDesign) phaseOrder.push("ux-design");
|
|
20709
20990
|
phaseOrder.push("solutioning", "implementation");
|
|
20710
20991
|
const startIdx = phaseOrder.indexOf(startPhase);
|
|
20992
|
+
const fpSucceededKeys = [];
|
|
20993
|
+
const fpFailedKeys = [];
|
|
20994
|
+
const fpEscalatedKeys = [];
|
|
20711
20995
|
for (let i = startIdx; i < phaseOrder.length; i++) {
|
|
20712
20996
|
const currentPhase = phaseOrder[i];
|
|
20997
|
+
if (fullPipelineNdjsonEmitter !== void 0) fullPipelineNdjsonEmitter.emit({
|
|
20998
|
+
type: "pipeline:phase-start",
|
|
20999
|
+
ts: new Date().toISOString(),
|
|
21000
|
+
phase: currentPhase
|
|
21001
|
+
});
|
|
20713
21002
|
if (outputFormat === "human") process.stdout.write(`\n[${currentPhase.toUpperCase()}] Starting...\n`);
|
|
20714
21003
|
if (currentPhase === "analysis") {
|
|
20715
21004
|
const result = await runAnalysisPhase(phaseDeps, {
|
|
@@ -20910,9 +21199,18 @@ async function runFullPipeline(options) {
|
|
|
20910
21199
|
});
|
|
20911
21200
|
if (storyKeys.length === 0 && outputFormat === "human") process.stdout.write("[IMPLEMENTATION] No stories found. Run solutioning first or pass --stories.\n");
|
|
20912
21201
|
if (outputFormat === "human") process.stdout.write(`[IMPLEMENTATION] Starting ${storyKeys.length} stories with concurrency=${concurrency}\n`);
|
|
20913
|
-
await orchestrator.run(storyKeys);
|
|
21202
|
+
const implStatus = await orchestrator.run(storyKeys);
|
|
20914
21203
|
if (outputFormat === "human") process.stdout.write("[IMPLEMENTATION] Complete\n");
|
|
21204
|
+
for (const [key, s] of Object.entries(implStatus.stories)) if (s.phase === "COMPLETE") fpSucceededKeys.push(key);
|
|
21205
|
+
else if (s.phase === "ESCALATED") if (s.error !== void 0) fpFailedKeys.push(key);
|
|
21206
|
+
else fpEscalatedKeys.push(key);
|
|
21207
|
+
else fpFailedKeys.push(key);
|
|
20915
21208
|
}
|
|
21209
|
+
if (fullPipelineNdjsonEmitter !== void 0) fullPipelineNdjsonEmitter.emit({
|
|
21210
|
+
type: "pipeline:phase-complete",
|
|
21211
|
+
ts: new Date().toISOString(),
|
|
21212
|
+
phase: currentPhase
|
|
21213
|
+
});
|
|
20916
21214
|
if (stopAfter !== void 0 && currentPhase === stopAfter) {
|
|
20917
21215
|
const gate = createStopAfterGate(stopAfter);
|
|
20918
21216
|
if (gate.shouldHalt()) {
|
|
@@ -20961,6 +21259,13 @@ async function runFullPipeline(options) {
|
|
|
20961
21259
|
process.stdout.write("\n");
|
|
20962
21260
|
process.stdout.write(formatTokenTelemetry(tokenSummary, BMAD_BASELINE_TOKENS_FULL) + "\n");
|
|
20963
21261
|
}
|
|
21262
|
+
if (fullPipelineNdjsonEmitter !== void 0) fullPipelineNdjsonEmitter.emit({
|
|
21263
|
+
type: "pipeline:complete",
|
|
21264
|
+
ts: new Date().toISOString(),
|
|
21265
|
+
succeeded: fpSucceededKeys,
|
|
21266
|
+
failed: fpFailedKeys,
|
|
21267
|
+
escalated: fpEscalatedKeys
|
|
21268
|
+
});
|
|
20964
21269
|
return 0;
|
|
20965
21270
|
} catch (err) {
|
|
20966
21271
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -21020,4 +21325,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
21020
21325
|
|
|
21021
21326
|
//#endregion
|
|
21022
21327
|
export { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createConfigSystem, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, registerRunCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
|
|
21023
|
-
//# sourceMappingURL=run-
|
|
21328
|
+
//# sourceMappingURL=run-VMOBJZ7f.js.map
|