substrate-ai 0.16.6 → 0.16.8
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
CHANGED
|
@@ -4,7 +4,7 @@ import { createLogger } from "../logger-KeHncl-f.js";
|
|
|
4
4
|
import { createEventBus } from "../helpers-CElYrONe.js";
|
|
5
5
|
import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, EXPERIMENT_RESULT, GlobalSettingsSchema, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-CLvAwmT7.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-
|
|
7
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-Cw4fBjGQ.js";
|
|
8
8
|
import "../errors-D1LU8CZ9.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -4359,7 +4359,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
4359
4359
|
await initSchema(expAdapter);
|
|
4360
4360
|
const { runRunAction: runPipeline } = await import(
|
|
4361
4361
|
/* @vite-ignore */
|
|
4362
|
-
"../run-
|
|
4362
|
+
"../run-B88g-P-r.js"
|
|
4363
4363
|
);
|
|
4364
4364
|
const runStoryFn = async (opts) => {
|
|
4365
4365
|
const exitCode = await runPipeline({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDLC Pipeline DOT Graph Definition
|
|
3
|
+
*
|
|
4
|
+
* Encodes the existing linear SDLC pipeline topology so the graph executor
|
|
5
|
+
* can drive the same pipeline logic as an alternative to the linear orchestrator.
|
|
6
|
+
*
|
|
7
|
+
* Story 43-1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
digraph sdlc_pipeline {
|
|
11
|
+
graph [
|
|
12
|
+
goal="Implement SDLC pipeline stories end-to-end",
|
|
13
|
+
label="SDLC Pipeline"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
// ── Entry / exit terminals ─────────────────────────────────────────────────
|
|
17
|
+
start [shape=Mdiamond, label="Start"]
|
|
18
|
+
exit [shape=Msquare, label="Exit"]
|
|
19
|
+
|
|
20
|
+
// ── Phase nodes ────────────────────────────────────────────────────────────
|
|
21
|
+
analysis [type="sdlc.phase", label="Analysis Phase"]
|
|
22
|
+
planning [type="sdlc.phase", label="Planning Phase"]
|
|
23
|
+
solutioning [type="sdlc.phase", label="Solutioning Phase"]
|
|
24
|
+
|
|
25
|
+
// ── Story lifecycle nodes ──────────────────────────────────────────────────
|
|
26
|
+
create_story [type="sdlc.create-story", label="Create Story"]
|
|
27
|
+
dev_story [type="sdlc.dev-story", label="Dev Story",
|
|
28
|
+
goal_gate=true, retry_target=dev_story, max_retries=2]
|
|
29
|
+
code_review [type="sdlc.code-review", label="Code Review", shape=diamond]
|
|
30
|
+
|
|
31
|
+
// ── Linear happy-path edges ────────────────────────────────────────────────
|
|
32
|
+
start -> analysis
|
|
33
|
+
analysis -> planning
|
|
34
|
+
planning -> solutioning
|
|
35
|
+
solutioning -> create_story
|
|
36
|
+
create_story -> dev_story
|
|
37
|
+
dev_story -> code_review
|
|
38
|
+
|
|
39
|
+
// ── Conditional edges from code_review ────────────────────────────────────
|
|
40
|
+
code_review -> exit [condition="outcome=success"]
|
|
41
|
+
code_review -> dev_story [condition="outcome=fail"]
|
|
42
|
+
}
|
|
@@ -2,7 +2,7 @@ import "./health-DswaC1q5.js";
|
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-CLvAwmT7.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-Cw4fBjGQ.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|
|
@@ -16648,20 +16648,63 @@ function createSdlcPhaseHandler(deps) {
|
|
|
16648
16648
|
};
|
|
16649
16649
|
const runId = context.getString("runId");
|
|
16650
16650
|
const concept = phaseName === "analysis" ? context.getString("concept", "") : "";
|
|
16651
|
+
const PRE_IMPL_PHASES = [
|
|
16652
|
+
"analysis",
|
|
16653
|
+
"planning",
|
|
16654
|
+
"solutioning"
|
|
16655
|
+
];
|
|
16656
|
+
const storyKey = context.getString("storyKey", "");
|
|
16657
|
+
if (storyKey && PRE_IMPL_PHASES.includes(phaseName)) return {
|
|
16658
|
+
status: "SUCCESS",
|
|
16659
|
+
notes: `Phase ${phaseName} skipped — explicit story dispatch (storyKey=${storyKey})`
|
|
16660
|
+
};
|
|
16651
16661
|
const PHASE_ARTIFACT_TYPES = {
|
|
16652
|
-
analysis: "product-brief",
|
|
16653
|
-
planning: "prd",
|
|
16654
|
-
solutioning: "stories"
|
|
16662
|
+
analysis: ["product-brief"],
|
|
16663
|
+
planning: ["prd"],
|
|
16664
|
+
solutioning: ["architecture", "stories"]
|
|
16655
16665
|
};
|
|
16656
|
-
const
|
|
16657
|
-
if (
|
|
16666
|
+
const artifactTypes = PHASE_ARTIFACT_TYPES[phaseName];
|
|
16667
|
+
if (artifactTypes !== void 0) try {
|
|
16658
16668
|
const db = deps.phaseDeps.db;
|
|
16659
16669
|
if (db) {
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16670
|
+
let allExist = true;
|
|
16671
|
+
for (const at of artifactTypes) {
|
|
16672
|
+
const rows = await db.query("SELECT id, path, content_hash, summary FROM artifacts WHERE phase = ? AND type = ? ORDER BY created_at DESC LIMIT 1", [phaseName, at]);
|
|
16673
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
16674
|
+
allExist = false;
|
|
16675
|
+
break;
|
|
16676
|
+
}
|
|
16677
|
+
}
|
|
16678
|
+
if (allExist) {
|
|
16679
|
+
const pipelineRunId = context.getString("pipelineRunId", "");
|
|
16680
|
+
if (pipelineRunId) for (const at of artifactTypes) {
|
|
16681
|
+
const existing = await db.query("SELECT id, path, content_hash, summary FROM artifacts WHERE phase = ? AND type = ? ORDER BY created_at DESC LIMIT 1", [phaseName, at]);
|
|
16682
|
+
const src = existing[0];
|
|
16683
|
+
if (src) {
|
|
16684
|
+
const alreadyRegistered = await db.query("SELECT id FROM artifacts WHERE pipeline_run_id = ? AND phase = ? AND type = ? LIMIT 1", [
|
|
16685
|
+
pipelineRunId,
|
|
16686
|
+
phaseName,
|
|
16687
|
+
at
|
|
16688
|
+
]);
|
|
16689
|
+
if (!Array.isArray(alreadyRegistered) || alreadyRegistered.length === 0) {
|
|
16690
|
+
const newId = crypto.randomUUID();
|
|
16691
|
+
await db.query("INSERT INTO artifacts (id, pipeline_run_id, phase, type, path, content_hash, summary) VALUES (?, ?, ?, ?, ?, ?, ?)", [
|
|
16692
|
+
newId,
|
|
16693
|
+
pipelineRunId,
|
|
16694
|
+
phaseName,
|
|
16695
|
+
at,
|
|
16696
|
+
src.path,
|
|
16697
|
+
src.content_hash ?? null,
|
|
16698
|
+
src.summary ?? null
|
|
16699
|
+
]);
|
|
16700
|
+
}
|
|
16701
|
+
}
|
|
16702
|
+
}
|
|
16703
|
+
return {
|
|
16704
|
+
status: "SUCCESS",
|
|
16705
|
+
notes: `Phase ${phaseName} already complete — artifact(s) exist, skipping dispatch`
|
|
16706
|
+
};
|
|
16707
|
+
}
|
|
16665
16708
|
}
|
|
16666
16709
|
} catch {}
|
|
16667
16710
|
const params = phaseName === "analysis" ? {
|
|
@@ -17095,8 +17138,10 @@ function createGraphOrchestrator(config) {
|
|
|
17095
17138
|
if (!config.graph?.nodes || !config.graph?.edges) throw new GraphOrchestratorInitError("Invalid graph: missing nodes or edges arrays");
|
|
17096
17139
|
const gcPauseMs = config.gcPauseMs ?? 2e3;
|
|
17097
17140
|
async function runStoryGraph(storyKey, summary) {
|
|
17141
|
+
const epicId = storyKey.split("-")[0] ?? "";
|
|
17098
17142
|
const initialContext = {
|
|
17099
17143
|
storyKey,
|
|
17144
|
+
epicId,
|
|
17100
17145
|
projectRoot: config.projectRoot,
|
|
17101
17146
|
methodologyPack: config.methodologyPack,
|
|
17102
17147
|
...config.pipelineRunId !== void 0 ? {
|
|
@@ -17126,6 +17171,7 @@ function createGraphOrchestrator(config) {
|
|
|
17126
17171
|
});
|
|
17127
17172
|
} catch (err) {
|
|
17128
17173
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
17174
|
+
process.stderr.write(`[graph-orchestrator] Story ${storyKey} failed: ${errMsg}\n`);
|
|
17129
17175
|
summary.stories[storyKey] = {
|
|
17130
17176
|
outcome: escalated ? "ESCALATED" : "FAILED",
|
|
17131
17177
|
error: errMsg
|
|
@@ -17142,7 +17188,12 @@ function createGraphOrchestrator(config) {
|
|
|
17142
17188
|
summary.stories[storyKey] = { outcome: "ESCALATED" };
|
|
17143
17189
|
summary.f++;
|
|
17144
17190
|
} else {
|
|
17145
|
-
|
|
17191
|
+
const reason = result.failureReason ?? `status=${result.status}`;
|
|
17192
|
+
process.stderr.write(`[graph-orchestrator] Story ${storyKey} failed: ${reason}\n`);
|
|
17193
|
+
summary.stories[storyKey] = {
|
|
17194
|
+
outcome: "FAILED",
|
|
17195
|
+
error: reason
|
|
17196
|
+
};
|
|
17146
17197
|
summary.f++;
|
|
17147
17198
|
}
|
|
17148
17199
|
}
|
|
@@ -17199,6 +17250,7 @@ function applyConfigToGraph(graph, options) {
|
|
|
17199
17250
|
const devStoryNode = graph.nodes.get("dev_story");
|
|
17200
17251
|
if (!devStoryNode) throw new Error("applyConfigToGraph: graph does not contain a 'dev_story' node");
|
|
17201
17252
|
devStoryNode.maxRetries = options.maxReviewCycles;
|
|
17253
|
+
graph.defaultMaxRetries = options.maxReviewCycles;
|
|
17202
17254
|
}
|
|
17203
17255
|
|
|
17204
17256
|
//#endregion
|
|
@@ -22997,6 +23049,7 @@ function createGraphExecutor() {
|
|
|
22997
23049
|
let context = new GraphContext(config.initialContext);
|
|
22998
23050
|
let step = 0;
|
|
22999
23051
|
const visitCount = new Map();
|
|
23052
|
+
const failRouteCount = new Map();
|
|
23000
23053
|
let resumeCompletedSet = null;
|
|
23001
23054
|
let firstResumedFidelity = "";
|
|
23002
23055
|
let skipCycleCheck = false;
|
|
@@ -23254,6 +23307,7 @@ function createGraphExecutor() {
|
|
|
23254
23307
|
controller.recordOutcome(nodeToDispatch.id, controllerStatus);
|
|
23255
23308
|
}
|
|
23256
23309
|
if (outcome.contextUpdates) for (const [key, value] of Object.entries(outcome.contextUpdates)) context.set(key, value);
|
|
23310
|
+
context.set("outcome", outcome.status.toLowerCase());
|
|
23257
23311
|
const nodeCost = context.getNumber("factory.lastNodeCostUsd", 0);
|
|
23258
23312
|
if (nodeCost > 0) pipelineManager.addCost(nodeCost);
|
|
23259
23313
|
if (config.adapter) {
|
|
@@ -23297,11 +23351,24 @@ function createGraphExecutor() {
|
|
|
23297
23351
|
currentNode = retryNode;
|
|
23298
23352
|
continue;
|
|
23299
23353
|
}
|
|
23300
|
-
|
|
23301
|
-
|
|
23302
|
-
|
|
23303
|
-
|
|
23304
|
-
|
|
23354
|
+
const outgoing = graph.edges.filter((e) => e.fromNode === currentNode.id);
|
|
23355
|
+
const hasConditionalEdge = outgoing.some((e) => e.condition && e.condition.trim() !== "");
|
|
23356
|
+
if (!hasConditionalEdge) {
|
|
23357
|
+
await persistExit("failed", outcome.failureReason ?? "FAIL");
|
|
23358
|
+
return {
|
|
23359
|
+
status: "FAIL",
|
|
23360
|
+
...outcome.failureReason !== void 0 && { failureReason: outcome.failureReason }
|
|
23361
|
+
};
|
|
23362
|
+
}
|
|
23363
|
+
const routeCount = (failRouteCount.get(currentNode.id) ?? 0) + 1;
|
|
23364
|
+
failRouteCount.set(currentNode.id, routeCount);
|
|
23365
|
+
if (routeCount > Math.max(graph.defaultMaxRetries || 0, 3)) {
|
|
23366
|
+
await persistExit("failed", outcome.failureReason ?? "FAIL");
|
|
23367
|
+
return {
|
|
23368
|
+
status: "FAIL",
|
|
23369
|
+
...outcome.failureReason !== void 0 && { failureReason: outcome.failureReason }
|
|
23370
|
+
};
|
|
23371
|
+
}
|
|
23305
23372
|
}
|
|
23306
23373
|
const edge = selectEdge(currentNode, outcome, context, graph);
|
|
23307
23374
|
if (!edge) {
|
|
@@ -31041,4 +31108,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
31041
31108
|
|
|
31042
31109
|
//#endregion
|
|
31043
31110
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
|
|
31044
|
-
//# sourceMappingURL=run-
|
|
31111
|
+
//# sourceMappingURL=run-Cw4fBjGQ.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "substrate-ai",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.8",
|
|
4
4
|
"description": "Substrate — multi-agent orchestration daemon for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"dist/**/*.d.ts",
|
|
43
43
|
"dist/**/*.json",
|
|
44
44
|
"dist/**/*.sql",
|
|
45
|
+
"dist/**/*.dot",
|
|
45
46
|
"dist/cli/templates",
|
|
46
47
|
"packs",
|
|
47
48
|
"README.md"
|