substrate-ai 0.20.85 → 0.20.86
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
|
@@ -3,7 +3,7 @@ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipel
|
|
|
3
3
|
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, GlobalSettingsSchema, InMemoryDatabaseAdapter, 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, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-DCBSXUiX.js";
|
|
6
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-
|
|
6
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DtkAIssJ.js";
|
|
7
7
|
import "../adapter-registry-DIcrxjH8.js";
|
|
8
8
|
import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-Boipz5aP.js";
|
|
9
9
|
import "../errors-D7xD-utp.js";
|
|
@@ -8436,7 +8436,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8436
8436
|
await initSchema(expAdapter);
|
|
8437
8437
|
const { runRunAction: runPipeline } = await import(
|
|
8438
8438
|
/* @vite-ignore */
|
|
8439
|
-
"../run-
|
|
8439
|
+
"../run-DmnPDKr3.js"
|
|
8440
8440
|
);
|
|
8441
8441
|
const runStoryFn = async (opts) => {
|
|
8442
8442
|
const exitCode = await runPipeline({
|
|
@@ -2,7 +2,7 @@ import "./health-CuKzY0Fn.js";
|
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-DCBSXUiX.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-DtkAIssJ.js";
|
|
6
6
|
import "./manifest-read-Boipz5aP.js";
|
|
7
7
|
import "./routing-DFxoKHDt.js";
|
|
8
8
|
import "./work-graph-repository-DZyJv5pV.js";
|
|
@@ -17,7 +17,7 @@ import { exec, execFile, execFileSync, execSync, spawn } from "node:child_proces
|
|
|
17
17
|
import * as path$5 from "node:path";
|
|
18
18
|
import * as path$4 from "node:path";
|
|
19
19
|
import * as path$2 from "node:path";
|
|
20
|
-
import path, { basename as basename$1, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, posix, resolve as resolve$1, win32 } from "node:path";
|
|
20
|
+
import path, { basename as basename$1, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
import { createHash, randomUUID } from "node:crypto";
|
|
23
23
|
import { z } from "zod";
|
|
@@ -7275,6 +7275,137 @@ async function isValidStoryFile(filePath) {
|
|
|
7275
7275
|
//#region src/modules/compiled-workflows/git-helpers.ts
|
|
7276
7276
|
const logger$20 = createLogger("compiled-workflows:git-helpers");
|
|
7277
7277
|
/**
|
|
7278
|
+
* Commit the agent's working-tree output for a dev-story dispatch.
|
|
7279
|
+
*
|
|
7280
|
+
* Path E Bug #5 (post-v0.20.85): substrate's per-story worktree flow assumed
|
|
7281
|
+
* the dispatched agent would run `git commit` itself. Empirical audit across
|
|
7282
|
+
* substrate + 4 consumer projects (strata, agent-mesh, boardgame-sandbox,
|
|
7283
|
+
* lucky-numbers) found 1 `feat(story-X-Y)` commit total in 2 months — agents
|
|
7284
|
+
* don't reliably commit. Path E's merge-to-main has been a silent no-op
|
|
7285
|
+
* since v0.20.79 because the branch never advanced past the orchestrator's
|
|
7286
|
+
* start commit. Result: pipelines reported succeeded, work was lost on
|
|
7287
|
+
* worktree cleanup.
|
|
7288
|
+
*
|
|
7289
|
+
* Fix: substrate commits programmatically before merge-to-main fires. The
|
|
7290
|
+
* commit captures every uncommitted file under the worktree that isn't
|
|
7291
|
+
* `.gitignored` (git add respects ignore rules) and isn't outside the
|
|
7292
|
+
* worktree boundary (absolute paths to /tmp/... are filtered out so they
|
|
7293
|
+
* don't trip 'fatal: outside repository'). Pre-commit hooks are NOT
|
|
7294
|
+
* bypassed — they exist in the operator's repo for a reason and should
|
|
7295
|
+
* gate substrate-generated commits too. A hook failure surfaces as a
|
|
7296
|
+
* dev-story-no-commit escalation with the hook output as evidence.
|
|
7297
|
+
*
|
|
7298
|
+
* @param storyKey Story key (e.g. "10-2") for the canonical commit-msg pattern
|
|
7299
|
+
* @param storyTitle Title from create-story result (or fallback string)
|
|
7300
|
+
* @param filesModified Files the agent declared (or recovered via git-status fallback)
|
|
7301
|
+
* @param workingDir The worktree path (or projectRoot when --no-worktree)
|
|
7302
|
+
* @returns Structured result for the orchestrator to inspect
|
|
7303
|
+
*/
|
|
7304
|
+
async function commitDevStoryOutput(storyKey, storyTitle, filesModified, workingDir) {
|
|
7305
|
+
const insideWorktree = [];
|
|
7306
|
+
for (const p of filesModified) {
|
|
7307
|
+
const abs = isAbsolute(p) ? p : resolve$1(workingDir, p);
|
|
7308
|
+
const rel = relative(workingDir, abs);
|
|
7309
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
7310
|
+
logger$20.debug({
|
|
7311
|
+
path: p,
|
|
7312
|
+
abs,
|
|
7313
|
+
workingDir
|
|
7314
|
+
}, "commitDevStoryOutput: filtered out path outside worktree");
|
|
7315
|
+
continue;
|
|
7316
|
+
}
|
|
7317
|
+
insideWorktree.push(rel);
|
|
7318
|
+
}
|
|
7319
|
+
if (insideWorktree.length === 0) return {
|
|
7320
|
+
status: "no-changes",
|
|
7321
|
+
reason: "no-files-inside-worktree"
|
|
7322
|
+
};
|
|
7323
|
+
try {
|
|
7324
|
+
execSync(`git add ${insideWorktree.map((p) => JSON.stringify(p)).join(" ")}`, {
|
|
7325
|
+
cwd: workingDir,
|
|
7326
|
+
stdio: [
|
|
7327
|
+
"ignore",
|
|
7328
|
+
"pipe",
|
|
7329
|
+
"pipe"
|
|
7330
|
+
],
|
|
7331
|
+
timeout: 3e4
|
|
7332
|
+
});
|
|
7333
|
+
} catch (err) {
|
|
7334
|
+
const stderr = err instanceof Error && "stderr" in err ? String(err.stderr ?? err.message) : err instanceof Error ? err.message : String(err);
|
|
7335
|
+
return {
|
|
7336
|
+
status: "failed",
|
|
7337
|
+
stderr: `git add failed: ${stderr}`
|
|
7338
|
+
};
|
|
7339
|
+
}
|
|
7340
|
+
const cachedCheck = spawn("git", [
|
|
7341
|
+
"diff",
|
|
7342
|
+
"--cached",
|
|
7343
|
+
"--quiet"
|
|
7344
|
+
], {
|
|
7345
|
+
cwd: workingDir,
|
|
7346
|
+
stdio: [
|
|
7347
|
+
"ignore",
|
|
7348
|
+
"pipe",
|
|
7349
|
+
"pipe"
|
|
7350
|
+
]
|
|
7351
|
+
});
|
|
7352
|
+
const cachedStatus = await new Promise((res) => {
|
|
7353
|
+
cachedCheck.on("close", (code) => res(code ?? 0));
|
|
7354
|
+
cachedCheck.on("error", () => res(0));
|
|
7355
|
+
});
|
|
7356
|
+
if (cachedStatus === 0) return {
|
|
7357
|
+
status: "no-changes",
|
|
7358
|
+
reason: "staging-produced-no-diff"
|
|
7359
|
+
};
|
|
7360
|
+
const title = storyTitle ?? "implementation";
|
|
7361
|
+
const message = `feat(story-${storyKey}): ${title}`;
|
|
7362
|
+
try {
|
|
7363
|
+
execSync(`git commit -m ${JSON.stringify(message)}`, {
|
|
7364
|
+
cwd: workingDir,
|
|
7365
|
+
stdio: [
|
|
7366
|
+
"ignore",
|
|
7367
|
+
"pipe",
|
|
7368
|
+
"pipe"
|
|
7369
|
+
],
|
|
7370
|
+
timeout: 12e4
|
|
7371
|
+
});
|
|
7372
|
+
} catch (err) {
|
|
7373
|
+
const stderr = err instanceof Error && "stderr" in err ? String(err.stderr ?? err.message) : err instanceof Error ? err.message : String(err);
|
|
7374
|
+
return {
|
|
7375
|
+
status: "failed",
|
|
7376
|
+
stderr: `git commit failed: ${stderr}`
|
|
7377
|
+
};
|
|
7378
|
+
}
|
|
7379
|
+
let sha = "";
|
|
7380
|
+
try {
|
|
7381
|
+
sha = execSync("git rev-parse HEAD", {
|
|
7382
|
+
cwd: workingDir,
|
|
7383
|
+
encoding: "utf-8",
|
|
7384
|
+
stdio: [
|
|
7385
|
+
"ignore",
|
|
7386
|
+
"pipe",
|
|
7387
|
+
"pipe"
|
|
7388
|
+
],
|
|
7389
|
+
timeout: 5e3
|
|
7390
|
+
}).trim();
|
|
7391
|
+
} catch (err) {
|
|
7392
|
+
logger$20.warn({
|
|
7393
|
+
storyKey,
|
|
7394
|
+
err
|
|
7395
|
+
}, "commitDevStoryOutput: commit succeeded but rev-parse HEAD failed");
|
|
7396
|
+
}
|
|
7397
|
+
logger$20.info({
|
|
7398
|
+
storyKey,
|
|
7399
|
+
sha,
|
|
7400
|
+
fileCount: insideWorktree.length
|
|
7401
|
+
}, "commitDevStoryOutput: committed dev-story output");
|
|
7402
|
+
return {
|
|
7403
|
+
status: "committed",
|
|
7404
|
+
sha,
|
|
7405
|
+
filesStaged: insideWorktree
|
|
7406
|
+
};
|
|
7407
|
+
}
|
|
7408
|
+
/**
|
|
7278
7409
|
* Check whether the repo at `cwd` has at least one commit (HEAD resolves).
|
|
7279
7410
|
* Returns false for fresh repos with no commits, avoiding `fatal: bad revision 'HEAD'`.
|
|
7280
7411
|
* Synchronous (execSync) to keep it simple — this is a fast local check.
|
|
@@ -13995,6 +14126,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13995
14126
|
const wt = await _worktreeManager.createWorktree(storyKey);
|
|
13996
14127
|
effectiveProjectRoot = wt.worktreePath;
|
|
13997
14128
|
}
|
|
14129
|
+
let _capturedStoryTitle;
|
|
13998
14130
|
await waitIfPaused();
|
|
13999
14131
|
if (_state !== "RUNNING") return;
|
|
14000
14132
|
stateStore?.branchForStory(storyKey).catch((err) => logger$27.warn({
|
|
@@ -14291,6 +14423,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14291
14423
|
}
|
|
14292
14424
|
}
|
|
14293
14425
|
storyFilePath = createResult.story_file;
|
|
14426
|
+
_capturedStoryTitle = createResult.story_title;
|
|
14294
14427
|
if (createResult.story_title) try {
|
|
14295
14428
|
const epicId = storyKey.split("-")[0] ?? storyKey;
|
|
14296
14429
|
const implDecisions = await getDecisionsByPhase(db, "implementation");
|
|
@@ -16045,6 +16178,101 @@ function createImplementationOrchestrator(deps) {
|
|
|
16045
16178
|
}
|
|
16046
16179
|
if (!noWorktree && _worktreeManager !== void 0 && _orchestratorStartBranch !== void 0 && projectRoot !== void 0) {
|
|
16047
16180
|
const branchName = `${BRANCH_PREFIX}${storyKey}`;
|
|
16181
|
+
if (effectiveProjectRoot !== void 0) {
|
|
16182
|
+
const dirty = await getGitChangedFiles(effectiveProjectRoot);
|
|
16183
|
+
const commitResult = await commitDevStoryOutput(storyKey, _capturedStoryTitle, dirty, effectiveProjectRoot);
|
|
16184
|
+
if (commitResult.status === "no-changes") {
|
|
16185
|
+
logger$27.warn({
|
|
16186
|
+
storyKey,
|
|
16187
|
+
reason: commitResult.reason
|
|
16188
|
+
}, "dev-story produced no committable changes — escalating instead of running merge-to-main on an unchanged branch");
|
|
16189
|
+
updateStory(storyKey, {
|
|
16190
|
+
phase: "ESCALATED",
|
|
16191
|
+
error: `dev-story-no-commit: ${commitResult.reason}`,
|
|
16192
|
+
completedAt: new Date().toISOString()
|
|
16193
|
+
});
|
|
16194
|
+
await emitEscalation({
|
|
16195
|
+
storyKey,
|
|
16196
|
+
lastVerdict: "dev-story-no-commit",
|
|
16197
|
+
reviewCycles: completedReviewCycles,
|
|
16198
|
+
issues: [`dev-story phase completed with verdict ${reviewVerdict} but produced no committable changes (reason: ${commitResult.reason})`]
|
|
16199
|
+
});
|
|
16200
|
+
await persistState();
|
|
16201
|
+
return;
|
|
16202
|
+
}
|
|
16203
|
+
if (commitResult.status === "failed") {
|
|
16204
|
+
logger$27.error({
|
|
16205
|
+
storyKey,
|
|
16206
|
+
stderr: commitResult.stderr
|
|
16207
|
+
}, "substrate auto-commit failed — escalating story");
|
|
16208
|
+
updateStory(storyKey, {
|
|
16209
|
+
phase: "ESCALATED",
|
|
16210
|
+
error: "dev-story-commit-failed",
|
|
16211
|
+
completedAt: new Date().toISOString()
|
|
16212
|
+
});
|
|
16213
|
+
await emitEscalation({
|
|
16214
|
+
storyKey,
|
|
16215
|
+
lastVerdict: "dev-story-commit-failed",
|
|
16216
|
+
reviewCycles: completedReviewCycles,
|
|
16217
|
+
issues: [`substrate auto-commit failed: ${commitResult.stderr}`]
|
|
16218
|
+
});
|
|
16219
|
+
await persistState();
|
|
16220
|
+
return;
|
|
16221
|
+
}
|
|
16222
|
+
logger$27.info({
|
|
16223
|
+
storyKey,
|
|
16224
|
+
sha: commitResult.sha,
|
|
16225
|
+
fileCount: commitResult.filesStaged.length
|
|
16226
|
+
}, "substrate auto-committed dev-story output before merge-to-main");
|
|
16227
|
+
}
|
|
16228
|
+
try {
|
|
16229
|
+
const branchSha = execSync(`git rev-parse ${branchName}`, {
|
|
16230
|
+
cwd: effectiveProjectRoot ?? projectRoot,
|
|
16231
|
+
encoding: "utf-8",
|
|
16232
|
+
stdio: [
|
|
16233
|
+
"ignore",
|
|
16234
|
+
"pipe",
|
|
16235
|
+
"pipe"
|
|
16236
|
+
],
|
|
16237
|
+
timeout: 5e3
|
|
16238
|
+
}).trim();
|
|
16239
|
+
const startSha = execSync(`git rev-parse ${_orchestratorStartBranch}`, {
|
|
16240
|
+
cwd: projectRoot,
|
|
16241
|
+
encoding: "utf-8",
|
|
16242
|
+
stdio: [
|
|
16243
|
+
"ignore",
|
|
16244
|
+
"pipe",
|
|
16245
|
+
"pipe"
|
|
16246
|
+
],
|
|
16247
|
+
timeout: 5e3
|
|
16248
|
+
}).trim();
|
|
16249
|
+
if (branchSha === startSha) {
|
|
16250
|
+
logger$27.warn({
|
|
16251
|
+
storyKey,
|
|
16252
|
+
branchSha,
|
|
16253
|
+
startSha,
|
|
16254
|
+
branchName
|
|
16255
|
+
}, "merge-to-main gate: branch did not advance from start commit — escalating instead of running a no-op merge");
|
|
16256
|
+
updateStory(storyKey, {
|
|
16257
|
+
phase: "ESCALATED",
|
|
16258
|
+
error: "dev-story-no-commit",
|
|
16259
|
+
completedAt: new Date().toISOString()
|
|
16260
|
+
});
|
|
16261
|
+
await emitEscalation({
|
|
16262
|
+
storyKey,
|
|
16263
|
+
lastVerdict: "dev-story-no-commit",
|
|
16264
|
+
reviewCycles: completedReviewCycles,
|
|
16265
|
+
issues: [`branch ${branchName} did not advance past start commit ${startSha} — merge-to-main would be a no-op`]
|
|
16266
|
+
});
|
|
16267
|
+
await persistState();
|
|
16268
|
+
return;
|
|
16269
|
+
}
|
|
16270
|
+
} catch (gateErr) {
|
|
16271
|
+
logger$27.warn({
|
|
16272
|
+
storyKey,
|
|
16273
|
+
err: gateErr instanceof Error ? gateErr.message : String(gateErr)
|
|
16274
|
+
}, "merge-to-main pre-flight verification failed — proceeding with merge phase");
|
|
16275
|
+
}
|
|
16048
16276
|
logger$27.info({
|
|
16049
16277
|
storyKey,
|
|
16050
16278
|
branchName,
|
|
@@ -47154,4 +47382,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
|
|
|
47154
47382
|
|
|
47155
47383
|
//#endregion
|
|
47156
47384
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
|
|
47157
|
-
//# sourceMappingURL=run-
|
|
47385
|
+
//# sourceMappingURL=run-DtkAIssJ.js.map
|