substrate-ai 0.21.13 → 0.21.15
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/{acceptance-judge-CKNJdq03.js → acceptance-judge-D5Iba2D_.js} +1 -1
- package/dist/{acceptance-judge-eIZZha1C.js → acceptance-judge-lAv5EvYA.js} +40 -3
- package/dist/cli/index.js +511 -156
- package/dist/{health-DAOWdkka.js → health-CvsH53bv.js} +2 -2
- package/dist/{health-DBBrM_te.js → health-kr5GC1SN.js} +2 -2
- package/dist/{interactive-prompt-CV9rLUNT.js → interactive-prompt-B5KE69I6.js} +2 -2
- package/dist/{manifest-read-Bq2_Ojbv.js → manifest-read-CcK_LIaI.js} +204 -2
- package/dist/modules/interactive-prompt/index.js +2 -2
- package/dist/{run-B31go5Ud.js → run-DR_D61vF.js} +5 -5
- package/dist/{run-CGuoRwXB.js → run-UilZoIOh.js} +5 -5
- package/package.json +1 -1
- package/packs/bmad/manifest.yaml +4 -0
- package/packs/bmad/prompts/acceptance-derive.md +63 -0
package/dist/cli/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-
|
|
2
|
+
import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-kr5GC1SN.js";
|
|
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, createGitWorktreeManager, createPipelineRun, createStderrLogger, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-BZGqn-XQ.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, clearGateDemotion, computePrecision, computeRecall, demoteGate, loadAcceptanceContractFromTrustedTree, loadJourneyRegistryFromFile, loadJourneyRegistryFromTrustedTree, parseAcceptanceContract, parseJourneyDeferrals, parseJourneyRegistry, parseRuntimeProbes, readAcceptanceMetrics, readCurrentRunId, readGateState, recordCanary, recordOverride, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runCanary } from "../manifest-read-
|
|
8
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-
|
|
7
|
+
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, JOURNEY_CANDIDATE_PATH, JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, clearGateDemotion, computePrecision, computeRecall, demoteGate, diffJourneySets, loadAcceptanceContractFromTrustedTree, loadJourneyRegistryFromFile, loadJourneyRegistryFromTrustedTree, parseAcceptanceContract, parseJourneyCandidate, parseJourneyDeferrals, parseJourneyRegistry, parseRuntimeProbes, ratifyCandidate, readAcceptanceMetrics, readCurrentRunId, readGateState, recordCanary, recordOverride, renderRegistryDiff, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runCanary } from "../manifest-read-CcK_LIaI.js";
|
|
8
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DR_D61vF.js";
|
|
9
9
|
import "../errors-xSeGw6pf.js";
|
|
10
|
-
import { runAcceptanceJudge } from "../acceptance-judge-
|
|
10
|
+
import { AcceptanceDeriveResultSchema, assemblePrompt, getTokenCeiling, runAcceptanceJudge } from "../acceptance-judge-lAv5EvYA.js";
|
|
11
11
|
import "../routing-DZT5PN3N.js";
|
|
12
12
|
import { WorkGraphRepository } from "../work-graph-repository-4cKsf8Lf.js";
|
|
13
13
|
import "../decisions-BAaxpVD0.js";
|
|
14
14
|
import "../decision-router-Dyby0fUf.js";
|
|
15
|
-
import "../interactive-prompt-
|
|
15
|
+
import "../interactive-prompt-B5KE69I6.js";
|
|
16
16
|
import "../recovery-engine-dtLHyV4M.js";
|
|
17
17
|
import "../version-manager-impl-DMTw551Q.js";
|
|
18
18
|
import { registerUpgradeCommand } from "../upgrade-CNGc12AV.js";
|
|
@@ -21,16 +21,16 @@ import { fileURLToPath } from "url";
|
|
|
21
21
|
import { dirname, join, resolve } from "path";
|
|
22
22
|
import { access, mkdir, readFile, readdir, unlink, writeFile } from "fs/promises";
|
|
23
23
|
import { EventEmitter } from "node:events";
|
|
24
|
-
import yaml from "js-yaml";
|
|
24
|
+
import yaml, { dump } from "js-yaml";
|
|
25
25
|
import * as actualFS from "node:fs";
|
|
26
26
|
import { existsSync, promises, readFileSync, writeFileSync } from "node:fs";
|
|
27
27
|
import { execFile, spawnSync } from "node:child_process";
|
|
28
28
|
import * as path$1 from "node:path";
|
|
29
29
|
import { basename as basename$1, dirname as dirname$1, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
|
|
30
|
-
import { randomUUID } from "node:crypto";
|
|
30
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
31
31
|
import { z } from "zod";
|
|
32
32
|
import * as fs from "node:fs/promises";
|
|
33
|
-
import { lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, writeFile as writeFile$1 } from "node:fs/promises";
|
|
33
|
+
import { lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
|
|
34
34
|
import { chmodSync, cpSync, existsSync as existsSync$1, lstatSync, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdir as readdir$2, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1, rmSync as rmSync$1, statSync as statSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
35
35
|
import { homedir } from "os";
|
|
36
36
|
import { createRequire } from "node:module";
|
|
@@ -39,6 +39,7 @@ import * as readline from "node:readline";
|
|
|
39
39
|
import { createInterface } from "node:readline";
|
|
40
40
|
import { randomUUID as randomUUID$1 } from "crypto";
|
|
41
41
|
import { createInterface as createInterface$1 } from "readline";
|
|
42
|
+
import { createInterface as createInterface$2 } from "node:readline/promises";
|
|
42
43
|
|
|
43
44
|
//#region packages/core/dist/monitor/recommendation-engine.js
|
|
44
45
|
var RecommendationEngine = class {
|
|
@@ -46,14 +47,14 @@ var RecommendationEngine = class {
|
|
|
46
47
|
_filters;
|
|
47
48
|
_historyDays;
|
|
48
49
|
_logger;
|
|
49
|
-
constructor(monitorDb, config = {}, logger$
|
|
50
|
+
constructor(monitorDb, config = {}, logger$20) {
|
|
50
51
|
this._monitorDb = monitorDb;
|
|
51
52
|
this._filters = {
|
|
52
53
|
threshold_percentage: config.recommendation_threshold_percentage ?? 5,
|
|
53
54
|
min_sample_size: config.min_sample_size ?? 10
|
|
54
55
|
};
|
|
55
56
|
this._historyDays = config.recommendation_history_days ?? 90;
|
|
56
|
-
this._logger = logger$
|
|
57
|
+
this._logger = logger$20 ?? createStderrLogger("monitor:recommendation-engine");
|
|
57
58
|
}
|
|
58
59
|
generateRecommendations() {
|
|
59
60
|
const sinceDate = new Date(Date.now() - this._historyDays * 24 * 60 * 60 * 1e3).toISOString();
|
|
@@ -1311,7 +1312,7 @@ function buildStackAwareDevNotes(profile) {
|
|
|
1311
1312
|
|
|
1312
1313
|
//#endregion
|
|
1313
1314
|
//#region src/cli/commands/init.ts
|
|
1314
|
-
const logger$
|
|
1315
|
+
const logger$19 = createLogger("init");
|
|
1315
1316
|
const __dirname = dirname(new URL(import.meta.url).pathname);
|
|
1316
1317
|
const SCAFFOLD_VERSION_REGEX = /<!-- substrate:version=([\d.]+) -->/;
|
|
1317
1318
|
/**
|
|
@@ -1352,7 +1353,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
|
|
|
1352
1353
|
const version = resolveBmadMethodVersion();
|
|
1353
1354
|
if (force && bmadExists) process.stderr.write(`Warning: Replacing existing _bmad/ framework with bmad-method@${version}\n`);
|
|
1354
1355
|
process.stdout.write(`Scaffolding BMAD framework from bmad-method@${version}\n`);
|
|
1355
|
-
logger$
|
|
1356
|
+
logger$19.info({
|
|
1356
1357
|
version,
|
|
1357
1358
|
dest: bmadDest
|
|
1358
1359
|
}, "Scaffolding BMAD framework");
|
|
@@ -1362,7 +1363,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
|
|
|
1362
1363
|
const destDir = join(bmadDest, dir);
|
|
1363
1364
|
mkdirSync$1(destDir, { recursive: true });
|
|
1364
1365
|
cpSync(srcDir, destDir, { recursive: true });
|
|
1365
|
-
logger$
|
|
1366
|
+
logger$19.info({
|
|
1366
1367
|
dir,
|
|
1367
1368
|
dest: destDir
|
|
1368
1369
|
}, "Scaffolded BMAD framework directory");
|
|
@@ -1381,7 +1382,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
|
|
|
1381
1382
|
"document_output_language: English"
|
|
1382
1383
|
].join("\n") + "\n";
|
|
1383
1384
|
await writeFile(configFile, configStub, "utf8");
|
|
1384
|
-
logger$
|
|
1385
|
+
logger$19.info({ configFile }, "Generated _bmad/_config/config.yaml stub");
|
|
1385
1386
|
}
|
|
1386
1387
|
}
|
|
1387
1388
|
const CLAUDE_MD_START_MARKER = "<!-- substrate:start -->";
|
|
@@ -1396,7 +1397,7 @@ async function scaffoldClaudeMd(projectRoot, profile) {
|
|
|
1396
1397
|
try {
|
|
1397
1398
|
sectionContent = await readFile(templatePath, "utf8");
|
|
1398
1399
|
} catch {
|
|
1399
|
-
logger$
|
|
1400
|
+
logger$19.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
|
|
1400
1401
|
return;
|
|
1401
1402
|
}
|
|
1402
1403
|
const substrateVersion = readSubstrateVersion(pkgRoot);
|
|
@@ -1432,7 +1433,7 @@ async function scaffoldClaudeMd(projectRoot, profile) {
|
|
|
1432
1433
|
else newContent = updatedExisting;
|
|
1433
1434
|
}
|
|
1434
1435
|
await writeFile(claudeMdPath, newContent, "utf8");
|
|
1435
|
-
logger$
|
|
1436
|
+
logger$19.info({ claudeMdPath }, "Wrote substrate section to CLAUDE.md");
|
|
1436
1437
|
}
|
|
1437
1438
|
async function scaffoldAgentsMd(projectRoot, profile) {
|
|
1438
1439
|
const agentsMdPath = join(projectRoot, "AGENTS.md");
|
|
@@ -1444,7 +1445,7 @@ async function scaffoldAgentsMd(projectRoot, profile) {
|
|
|
1444
1445
|
try {
|
|
1445
1446
|
sectionContent = await readFile(templatePath, "utf8");
|
|
1446
1447
|
} catch {
|
|
1447
|
-
logger$
|
|
1448
|
+
logger$19.warn({ templatePath }, "AGENTS.md substrate section template not found; skipping");
|
|
1448
1449
|
return;
|
|
1449
1450
|
}
|
|
1450
1451
|
const substrateVersion = readSubstrateVersion(pkgRoot);
|
|
@@ -1465,7 +1466,7 @@ async function scaffoldAgentsMd(projectRoot, profile) {
|
|
|
1465
1466
|
newContent = existingContent + separator + sectionContent;
|
|
1466
1467
|
}
|
|
1467
1468
|
await writeFile(agentsMdPath, newContent, "utf8");
|
|
1468
|
-
logger$
|
|
1469
|
+
logger$19.info({ agentsMdPath }, "Wrote substrate section to AGENTS.md");
|
|
1469
1470
|
}
|
|
1470
1471
|
async function scaffoldGeminiMd(projectRoot, profile) {
|
|
1471
1472
|
const geminiMdPath = join(projectRoot, "GEMINI.md");
|
|
@@ -1477,7 +1478,7 @@ async function scaffoldGeminiMd(projectRoot, profile) {
|
|
|
1477
1478
|
try {
|
|
1478
1479
|
sectionContent = await readFile(templatePath, "utf8");
|
|
1479
1480
|
} catch {
|
|
1480
|
-
logger$
|
|
1481
|
+
logger$19.warn({ templatePath }, "GEMINI.md substrate section template not found; skipping");
|
|
1481
1482
|
return;
|
|
1482
1483
|
}
|
|
1483
1484
|
const substrateVersion = readSubstrateVersion(pkgRoot);
|
|
@@ -1498,7 +1499,7 @@ async function scaffoldGeminiMd(projectRoot, profile) {
|
|
|
1498
1499
|
newContent = existingContent + separator + sectionContent;
|
|
1499
1500
|
}
|
|
1500
1501
|
await writeFile(geminiMdPath, newContent, "utf8");
|
|
1501
|
-
logger$
|
|
1502
|
+
logger$19.info({ geminiMdPath }, "Wrote substrate section to GEMINI.md");
|
|
1502
1503
|
}
|
|
1503
1504
|
async function scaffoldStatuslineScript(projectRoot) {
|
|
1504
1505
|
const pkgRoot = findPackageRoot(__dirname);
|
|
@@ -1509,7 +1510,7 @@ async function scaffoldStatuslineScript(projectRoot) {
|
|
|
1509
1510
|
try {
|
|
1510
1511
|
content = await readFile(templatePath, "utf8");
|
|
1511
1512
|
} catch {
|
|
1512
|
-
logger$
|
|
1513
|
+
logger$19.warn({ templatePath }, "statusline.sh template not found; skipping");
|
|
1513
1514
|
return;
|
|
1514
1515
|
}
|
|
1515
1516
|
const claudeDir = join(projectRoot, ".claude");
|
|
@@ -1517,7 +1518,7 @@ async function scaffoldStatuslineScript(projectRoot) {
|
|
|
1517
1518
|
mkdirSync$1(claudeDir, { recursive: true });
|
|
1518
1519
|
await writeFile(statuslinePath, content, "utf8");
|
|
1519
1520
|
chmodSync(statuslinePath, 493);
|
|
1520
|
-
logger$
|
|
1521
|
+
logger$19.info({ statuslinePath }, "Wrote .claude/statusline.sh");
|
|
1521
1522
|
}
|
|
1522
1523
|
async function scaffoldClaudeSettings(projectRoot) {
|
|
1523
1524
|
const claudeDir = join(projectRoot, ".claude");
|
|
@@ -1533,7 +1534,7 @@ async function scaffoldClaudeSettings(projectRoot) {
|
|
|
1533
1534
|
if (!merged["$schema"]) merged["$schema"] = "https://json.schemastore.org/claude-code-settings.json";
|
|
1534
1535
|
mkdirSync$1(claudeDir, { recursive: true });
|
|
1535
1536
|
await writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
1536
|
-
logger$
|
|
1537
|
+
logger$19.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
|
|
1537
1538
|
}
|
|
1538
1539
|
/**
|
|
1539
1540
|
* H5.2 (field finding #2): write substrate's own slash commands
|
|
@@ -1552,7 +1553,7 @@ function scaffoldSubstrateSlashCommands(projectRoot) {
|
|
|
1552
1553
|
let templatesDir = join(pkgRoot, "dist", "cli", "templates", "claude-commands");
|
|
1553
1554
|
if (!existsSync$1(templatesDir)) templatesDir = join(pkgRoot, "src", "cli", "templates", "claude-commands");
|
|
1554
1555
|
if (!existsSync$1(templatesDir)) {
|
|
1555
|
-
logger$
|
|
1556
|
+
logger$19.warn({ templatesDir }, "substrate slash-command templates not found; skipping");
|
|
1556
1557
|
return 0;
|
|
1557
1558
|
}
|
|
1558
1559
|
const commandsDir = join(projectRoot, ".claude", "commands");
|
|
@@ -1564,19 +1565,19 @@ function scaffoldSubstrateSlashCommands(projectRoot) {
|
|
|
1564
1565
|
writeFileSync$1(join(commandsDir, file), readFileSync$1(join(templatesDir, file), "utf8"));
|
|
1565
1566
|
written += 1;
|
|
1566
1567
|
} catch (err) {
|
|
1567
|
-
logger$
|
|
1568
|
+
logger$19.warn({
|
|
1568
1569
|
file,
|
|
1569
1570
|
err
|
|
1570
1571
|
}, "failed to write substrate slash command (init continues)");
|
|
1571
1572
|
}
|
|
1572
1573
|
}
|
|
1573
|
-
logger$
|
|
1574
|
+
logger$19.info({
|
|
1574
1575
|
written,
|
|
1575
1576
|
commandsDir
|
|
1576
1577
|
}, "Scaffolded substrate slash commands");
|
|
1577
1578
|
return written;
|
|
1578
1579
|
} catch (err) {
|
|
1579
|
-
logger$
|
|
1580
|
+
logger$19.warn({ err }, "scaffoldSubstrateSlashCommands failed; init continues");
|
|
1580
1581
|
return 0;
|
|
1581
1582
|
}
|
|
1582
1583
|
}
|
|
@@ -1650,7 +1651,7 @@ async function compileBmadAgents(bmadDir) {
|
|
|
1650
1651
|
writeFileSync$1(mdPath, result.xml, "utf-8");
|
|
1651
1652
|
compiled++;
|
|
1652
1653
|
} catch (compileErr) {
|
|
1653
|
-
logger$
|
|
1654
|
+
logger$19.debug({
|
|
1654
1655
|
err: compileErr,
|
|
1655
1656
|
file
|
|
1656
1657
|
}, "Failed to compile agent YAML");
|
|
@@ -1797,9 +1798,9 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1797
1798
|
const _require = createRequire(join(__dirname, "synthetic.js"));
|
|
1798
1799
|
try {
|
|
1799
1800
|
const compiledCount = await compileBmadAgents(bmadDir);
|
|
1800
|
-
if (compiledCount > 0) logger$
|
|
1801
|
+
if (compiledCount > 0) logger$19.info({ compiledCount }, "Compiled agent YAML files to MD");
|
|
1801
1802
|
} catch (compileErr) {
|
|
1802
|
-
logger$
|
|
1803
|
+
logger$19.warn({ err: compileErr }, "Agent compilation failed; agent commands may be incomplete");
|
|
1803
1804
|
}
|
|
1804
1805
|
const resolveExport = (mod, name) => {
|
|
1805
1806
|
if (typeof mod[name] === "function") return mod[name];
|
|
@@ -1813,7 +1814,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1813
1814
|
const manifestGenPath = join(installerLibPath, "core", "manifest-generator.js");
|
|
1814
1815
|
const pathUtilsPath = join(installerLibPath, "ide", "shared", "path-utils.js");
|
|
1815
1816
|
if (!existsSync$1(agentGenPath)) {
|
|
1816
|
-
logger$
|
|
1817
|
+
logger$19.info("bmad-method generators not available (requires bmad-method with agent/workflow/task-tool generators)");
|
|
1817
1818
|
return;
|
|
1818
1819
|
}
|
|
1819
1820
|
const agentMod = _require(agentGenPath);
|
|
@@ -1823,11 +1824,11 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1823
1824
|
if (existsSync$1(workflowGenPath)) {
|
|
1824
1825
|
const workflowMod = _require(workflowGenPath);
|
|
1825
1826
|
WorkflowCommandGenerator = resolveExport(workflowMod, "WorkflowCommandGenerator");
|
|
1826
|
-
} else logger$
|
|
1827
|
+
} else logger$19.info("bmad-method workflow-command-generator not available; will try skill-based installation");
|
|
1827
1828
|
if (existsSync$1(taskToolGenPath)) {
|
|
1828
1829
|
const taskToolMod = _require(taskToolGenPath);
|
|
1829
1830
|
TaskToolCommandGenerator = resolveExport(taskToolMod, "TaskToolCommandGenerator");
|
|
1830
|
-
} else logger$
|
|
1831
|
+
} else logger$19.info("bmad-method task-tool-command-generator not available; will try skill-based installation");
|
|
1831
1832
|
let ManifestGenerator = null;
|
|
1832
1833
|
if (existsSync$1(manifestGenPath)) {
|
|
1833
1834
|
const manifestMod = _require(manifestGenPath);
|
|
@@ -1859,7 +1860,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1859
1860
|
const manifestGen = new ManifestGenerator();
|
|
1860
1861
|
await manifestGen.generateManifests(bmadDir, allModules, [], { ides: ["claude-code"] });
|
|
1861
1862
|
} catch (manifestErr) {
|
|
1862
|
-
logger$
|
|
1863
|
+
logger$19.warn({ err: manifestErr }, "ManifestGenerator failed; workflow/task commands may be incomplete");
|
|
1863
1864
|
}
|
|
1864
1865
|
const commandsDir = join(projectRoot, ".claude", "commands");
|
|
1865
1866
|
mkdirSync$1(commandsDir, { recursive: true });
|
|
@@ -1887,7 +1888,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1887
1888
|
const total = agentCount + workflowCount + taskToolCount + skillCount;
|
|
1888
1889
|
if (outputFormat !== "json") if (skillCount > 0) process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(skillCount)} skills)\n`);
|
|
1889
1890
|
else process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(workflowCount)} workflows, ${String(taskToolCount)} tasks/tools)\n`);
|
|
1890
|
-
logger$
|
|
1891
|
+
logger$19.info({
|
|
1891
1892
|
agentCount,
|
|
1892
1893
|
workflowCount,
|
|
1893
1894
|
taskToolCount,
|
|
@@ -1898,7 +1899,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
1898
1899
|
} catch (err) {
|
|
1899
1900
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1900
1901
|
if (outputFormat !== "json") process.stderr.write(`Warning: .claude/commands/ generation failed: ${msg}\n`);
|
|
1901
|
-
logger$
|
|
1902
|
+
logger$19.warn({ err }, "scaffoldClaudeCommands failed; init continues");
|
|
1902
1903
|
}
|
|
1903
1904
|
}
|
|
1904
1905
|
/**
|
|
@@ -1927,7 +1928,7 @@ function syncCommandsAsPrompts(commandsDir, promptsDir, ownershipPrefixes, nameP
|
|
|
1927
1928
|
unlinkSync$1(join(promptsDir, entry.name));
|
|
1928
1929
|
}
|
|
1929
1930
|
} catch (err) {
|
|
1930
|
-
logger$
|
|
1931
|
+
logger$19.debug({
|
|
1931
1932
|
err,
|
|
1932
1933
|
promptsDir
|
|
1933
1934
|
}, "Failed to prune stale prompts");
|
|
@@ -1970,7 +1971,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
|
|
|
1970
1971
|
});
|
|
1971
1972
|
}
|
|
1972
1973
|
} catch (err) {
|
|
1973
|
-
logger$
|
|
1974
|
+
logger$19.debug({
|
|
1974
1975
|
err,
|
|
1975
1976
|
destSkillsDir
|
|
1976
1977
|
}, "Failed to prune stale skills");
|
|
@@ -1996,7 +1997,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
|
|
|
1996
1997
|
op: stage,
|
|
1997
1998
|
err: msg
|
|
1998
1999
|
});
|
|
1999
|
-
logger$
|
|
2000
|
+
logger$19.warn({
|
|
2000
2001
|
skill: entry.name,
|
|
2001
2002
|
dest,
|
|
2002
2003
|
stage,
|
|
@@ -2006,7 +2007,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
|
|
|
2006
2007
|
}
|
|
2007
2008
|
if (failures.length > 0 && count === 0) {
|
|
2008
2009
|
const first = failures[0];
|
|
2009
|
-
logger$
|
|
2010
|
+
logger$19.warn({
|
|
2010
2011
|
destSkillsDir,
|
|
2011
2012
|
attempted: failures.length,
|
|
2012
2013
|
dominantStage: first.op,
|
|
@@ -2033,7 +2034,7 @@ const PROJECT_OWNERSHIP_PREFIXES = ["bmad-", "substrate-"];
|
|
|
2033
2034
|
function scaffoldCodexProject(projectRoot, outputFormat) {
|
|
2034
2035
|
if (process.env["SUBSTRATE_NO_CODEX_SCAFFOLD"] === "1") {
|
|
2035
2036
|
if (outputFormat !== "json") process.stdout.write(" Skipping .codex/ scaffolding (SUBSTRATE_NO_CODEX_SCAFFOLD=1)\n");
|
|
2036
|
-
logger$
|
|
2037
|
+
logger$19.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping .codex/ scaffolding");
|
|
2037
2038
|
return;
|
|
2038
2039
|
}
|
|
2039
2040
|
const claudeCommandsDir = join(projectRoot, ".claude", "commands");
|
|
@@ -2046,16 +2047,16 @@ function scaffoldCodexProject(projectRoot, outputFormat) {
|
|
|
2046
2047
|
const skillCount = syncSkillsToTarget(claudeSkillsDir, codexSkillsDir, PROJECT_OWNERSHIP_PREFIXES, "");
|
|
2047
2048
|
const total = promptCount + skillCount;
|
|
2048
2049
|
if (outputFormat !== "json" && total > 0) process.stdout.write(`Generated ${String(total)} Codex artifacts (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
|
|
2049
|
-
if (total > 0) logger$
|
|
2050
|
+
if (total > 0) logger$19.info({
|
|
2050
2051
|
promptCount,
|
|
2051
2052
|
skillCount,
|
|
2052
2053
|
codexDir
|
|
2053
2054
|
}, "Generated .codex/");
|
|
2054
|
-
else logger$
|
|
2055
|
+
else logger$19.debug({ codexDir }, "No Codex artifacts generated; source Claude content not found");
|
|
2055
2056
|
} catch (err) {
|
|
2056
2057
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2057
2058
|
if (outputFormat !== "json") process.stderr.write(`Warning: .codex/ generation failed: ${msg}\n`);
|
|
2058
|
-
logger$
|
|
2059
|
+
logger$19.warn({ err }, "scaffoldCodexProject failed; init continues");
|
|
2059
2060
|
}
|
|
2060
2061
|
}
|
|
2061
2062
|
/**
|
|
@@ -2073,7 +2074,7 @@ function scaffoldCodexProject(projectRoot, outputFormat) {
|
|
|
2073
2074
|
function scaffoldCodexUser(projectRoot, homeDir, outputFormat) {
|
|
2074
2075
|
if (process.env["SUBSTRATE_NO_CODEX_SCAFFOLD"] === "1") {
|
|
2075
2076
|
if (outputFormat !== "json") process.stdout.write(" Skipping ~/.codex/ scaffolding (SUBSTRATE_NO_CODEX_SCAFFOLD=1)\n");
|
|
2076
|
-
logger$
|
|
2077
|
+
logger$19.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping ~/.codex/ scaffolding");
|
|
2077
2078
|
return;
|
|
2078
2079
|
}
|
|
2079
2080
|
const claudeCommandsDir = join(projectRoot, ".claude", "commands");
|
|
@@ -2086,16 +2087,16 @@ function scaffoldCodexUser(projectRoot, homeDir, outputFormat) {
|
|
|
2086
2087
|
const skillCount = syncSkillsToTarget(claudeSkillsDir, userSkillsDir, ["substrate-"], "substrate-");
|
|
2087
2088
|
const total = promptCount + skillCount;
|
|
2088
2089
|
if (outputFormat !== "json" && total > 0) process.stdout.write(`Installed ${String(total)} Codex artifacts to ${userCodexDir} (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
|
|
2089
|
-
if (total > 0) logger$
|
|
2090
|
+
if (total > 0) logger$19.info({
|
|
2090
2091
|
promptCount,
|
|
2091
2092
|
skillCount,
|
|
2092
2093
|
userCodexDir
|
|
2093
2094
|
}, "Installed user-scope Codex content");
|
|
2094
|
-
else logger$
|
|
2095
|
+
else logger$19.debug({ userCodexDir }, "No user-scope Codex content installed; source Claude content not found");
|
|
2095
2096
|
} catch (err) {
|
|
2096
2097
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2097
2098
|
if (outputFormat !== "json") process.stderr.write(`Warning: user-scope Codex install failed: ${msg}\n`);
|
|
2098
|
-
logger$
|
|
2099
|
+
logger$19.warn({ err }, "scaffoldCodexUser failed; init continues");
|
|
2099
2100
|
}
|
|
2100
2101
|
}
|
|
2101
2102
|
const PROVIDER_DEFAULTS = DEFAULT_CONFIG.providers;
|
|
@@ -2216,7 +2217,7 @@ async function runInitAction(options) {
|
|
|
2216
2217
|
discoveryReport = await registry.discoverAndRegister();
|
|
2217
2218
|
} catch (err) {
|
|
2218
2219
|
const message = err instanceof Error ? err.message : String(err);
|
|
2219
|
-
logger$
|
|
2220
|
+
logger$19.error({ err }, "Adapter discovery failed");
|
|
2220
2221
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, `Adapter discovery failed: ${message}`) + "\n");
|
|
2221
2222
|
else process.stderr.write(` Error: adapter discovery failed — ${message}\n`);
|
|
2222
2223
|
return INIT_EXIT_ERROR;
|
|
@@ -2265,7 +2266,7 @@ async function runInitAction(options) {
|
|
|
2265
2266
|
try {
|
|
2266
2267
|
detectedProfile = await detectProjectProfile(dbRoot);
|
|
2267
2268
|
} catch (err) {
|
|
2268
|
-
logger$
|
|
2269
|
+
logger$19.warn({ err }, "Project profile detection failed; skipping");
|
|
2269
2270
|
}
|
|
2270
2271
|
if (detectedProfile === null) {
|
|
2271
2272
|
if (outputFormat !== "json") process.stdout.write(" No project stack detected. Create .substrate/project-profile.yaml manually to enable polyglot support.\n");
|
|
@@ -2299,12 +2300,12 @@ async function runInitAction(options) {
|
|
|
2299
2300
|
return INIT_EXIT_ERROR;
|
|
2300
2301
|
}
|
|
2301
2302
|
if (force && existsSync$1(localManifest)) {
|
|
2302
|
-
logger$
|
|
2303
|
+
logger$19.info({ pack: packName }, "Replacing existing pack with bundled version");
|
|
2303
2304
|
process.stderr.write(`Warning: Replacing existing pack '${packName}' with bundled version\n`);
|
|
2304
2305
|
}
|
|
2305
2306
|
mkdirSync$1(dirname(packPath), { recursive: true });
|
|
2306
2307
|
cpSync(bundledPackPath, packPath, { recursive: true });
|
|
2307
|
-
logger$
|
|
2308
|
+
logger$19.info({
|
|
2308
2309
|
pack: packName,
|
|
2309
2310
|
dest: packPath
|
|
2310
2311
|
}, "Scaffolded methodology pack");
|
|
@@ -2346,10 +2347,10 @@ async function runInitAction(options) {
|
|
|
2346
2347
|
const { content, changed } = computeSubstrateGitignore(existing);
|
|
2347
2348
|
if (changed) {
|
|
2348
2349
|
writeFileSync$1(gitignorePath, content);
|
|
2349
|
-
logger$
|
|
2350
|
+
logger$19.info("Updated .gitignore: track only .substrate/config.yaml");
|
|
2350
2351
|
}
|
|
2351
2352
|
} catch (err) {
|
|
2352
|
-
logger$
|
|
2353
|
+
logger$19.debug({ err }, "Could not update .gitignore (non-fatal)");
|
|
2353
2354
|
}
|
|
2354
2355
|
const doltMode = options.doltMode ?? "auto";
|
|
2355
2356
|
let doltInitialized = false;
|
|
@@ -2363,7 +2364,7 @@ async function runInitAction(options) {
|
|
|
2363
2364
|
process.stderr.write(`${err.message}\n`);
|
|
2364
2365
|
return INIT_EXIT_ERROR;
|
|
2365
2366
|
}
|
|
2366
|
-
logger$
|
|
2367
|
+
logger$19.debug("Dolt not installed, skipping auto-init");
|
|
2367
2368
|
} else {
|
|
2368
2369
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2369
2370
|
if (doltMode === "force") {
|
|
@@ -2373,7 +2374,7 @@ async function runInitAction(options) {
|
|
|
2373
2374
|
process.stderr.write(`⚠ Dolt state store initialization failed: ${msg}\n Pipeline metrics, cost tracking, and health monitoring will not persist.\n Fix the issue and re-run: substrate init --dolt\n`);
|
|
2374
2375
|
}
|
|
2375
2376
|
}
|
|
2376
|
-
else logger$
|
|
2377
|
+
else logger$19.debug("Dolt step was skipped (--no-dolt)");
|
|
2377
2378
|
const successMsg = `Pack '${packName}' and database initialized successfully at ${dbPath}`;
|
|
2378
2379
|
if (outputFormat === "json") process.stdout.write(formatOutput({
|
|
2379
2380
|
pack: packName,
|
|
@@ -2411,7 +2412,7 @@ async function runInitAction(options) {
|
|
|
2411
2412
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2412
2413
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
2413
2414
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
2414
|
-
logger$
|
|
2415
|
+
logger$19.error({ err }, "init failed");
|
|
2415
2416
|
return INIT_EXIT_ERROR;
|
|
2416
2417
|
}
|
|
2417
2418
|
}
|
|
@@ -2435,7 +2436,7 @@ function registerInitCommand(program, _version, registry) {
|
|
|
2435
2436
|
|
|
2436
2437
|
//#endregion
|
|
2437
2438
|
//#region src/cli/commands/config.ts
|
|
2438
|
-
const logger$
|
|
2439
|
+
const logger$18 = createLogger("config-cmd");
|
|
2439
2440
|
const CONFIG_EXIT_SUCCESS = 0;
|
|
2440
2441
|
const CONFIG_EXIT_ERROR = 1;
|
|
2441
2442
|
const CONFIG_EXIT_INVALID = 2;
|
|
@@ -2461,7 +2462,7 @@ async function runConfigShow(opts = {}) {
|
|
|
2461
2462
|
return CONFIG_EXIT_INVALID;
|
|
2462
2463
|
}
|
|
2463
2464
|
const message = err instanceof Error ? err.message : String(err);
|
|
2464
|
-
logger$
|
|
2465
|
+
logger$18.error({ err }, "Failed to load configuration");
|
|
2465
2466
|
process.stderr.write(` Error loading configuration: ${message}\n`);
|
|
2466
2467
|
return CONFIG_EXIT_ERROR;
|
|
2467
2468
|
}
|
|
@@ -2535,7 +2536,7 @@ async function runConfigExport(opts = {}) {
|
|
|
2535
2536
|
return CONFIG_EXIT_INVALID;
|
|
2536
2537
|
}
|
|
2537
2538
|
const message = err instanceof Error ? err.message : String(err);
|
|
2538
|
-
logger$
|
|
2539
|
+
logger$18.error({ err }, "Failed to load configuration");
|
|
2539
2540
|
process.stderr.write(`Error loading configuration: ${message}\n`);
|
|
2540
2541
|
return CONFIG_EXIT_ERROR;
|
|
2541
2542
|
}
|
|
@@ -6455,7 +6456,7 @@ async function detectManifestDriftAgainstWorkingTree(manifest, projectRoot) {
|
|
|
6455
6456
|
|
|
6456
6457
|
//#endregion
|
|
6457
6458
|
//#region src/cli/commands/resume.ts
|
|
6458
|
-
const logger$
|
|
6459
|
+
const logger$17 = createLogger("resume-cmd");
|
|
6459
6460
|
/**
|
|
6460
6461
|
* Format a human-readable duration from an ISO-8601 timestamp to "now".
|
|
6461
6462
|
*/
|
|
@@ -6525,7 +6526,7 @@ async function runResumeAction(options) {
|
|
|
6525
6526
|
return 1;
|
|
6526
6527
|
}
|
|
6527
6528
|
} catch (driftErr) {
|
|
6528
|
-
logger$
|
|
6529
|
+
logger$17.debug({ err: driftErr }, "manifest drift check failed — proceeding with resume");
|
|
6529
6530
|
}
|
|
6530
6531
|
}
|
|
6531
6532
|
const doltDir = join(dbRoot, ".substrate", "state", ".dolt");
|
|
@@ -6595,15 +6596,15 @@ async function runResumeAction(options) {
|
|
|
6595
6596
|
const manifestStories = manifestData.cli_flags["stories"] ?? manifestData.story_scope;
|
|
6596
6597
|
if (Array.isArray(manifestStories) && manifestStories.length > 0) {
|
|
6597
6598
|
scopedStories = manifestStories;
|
|
6598
|
-
logger$
|
|
6599
|
+
logger$17.debug({
|
|
6599
6600
|
runId,
|
|
6600
6601
|
stories: scopedStories
|
|
6601
6602
|
}, "resume scope loaded from manifest");
|
|
6602
6603
|
}
|
|
6603
6604
|
} catch {
|
|
6604
|
-
logger$
|
|
6605
|
+
logger$17.debug({ runId }, "manifest read failed in resume — using legacy config_json scope");
|
|
6605
6606
|
}
|
|
6606
|
-
else logger$
|
|
6607
|
+
else logger$17.debug({ runId }, "Run manifest not found for scope preservation — using legacy config_json scope");
|
|
6607
6608
|
}
|
|
6608
6609
|
return runFullPipelineFromPhase({
|
|
6609
6610
|
packName,
|
|
@@ -6626,7 +6627,7 @@ async function runResumeAction(options) {
|
|
|
6626
6627
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6627
6628
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
6628
6629
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
6629
|
-
logger$
|
|
6630
|
+
logger$17.error({ err }, "auto resume failed");
|
|
6630
6631
|
return 1;
|
|
6631
6632
|
} finally {
|
|
6632
6633
|
try {
|
|
@@ -6879,11 +6880,11 @@ async function runFullPipelineFromPhase(options) {
|
|
|
6879
6880
|
output_tokens: output,
|
|
6880
6881
|
cost_usd: costUsd
|
|
6881
6882
|
}).catch((err) => {
|
|
6882
|
-
logger$
|
|
6883
|
+
logger$17.warn({ err }, "Failed to record token usage");
|
|
6883
6884
|
});
|
|
6884
6885
|
}
|
|
6885
6886
|
} catch (err) {
|
|
6886
|
-
logger$
|
|
6887
|
+
logger$17.warn({ err }, "Failed to record token usage");
|
|
6887
6888
|
}
|
|
6888
6889
|
});
|
|
6889
6890
|
const storyKeys = await resolveStoryKeys(adapter, projectRoot, {
|
|
@@ -6952,7 +6953,7 @@ async function runFullPipelineFromPhase(options) {
|
|
|
6952
6953
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6953
6954
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
6954
6955
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
6955
|
-
logger$
|
|
6956
|
+
logger$17.error({ err }, "pipeline from phase failed");
|
|
6956
6957
|
return 1;
|
|
6957
6958
|
} finally {
|
|
6958
6959
|
try {
|
|
@@ -6982,7 +6983,7 @@ function registerResumeCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
6982
6983
|
|
|
6983
6984
|
//#endregion
|
|
6984
6985
|
//#region src/cli/commands/status.ts
|
|
6985
|
-
const logger$
|
|
6986
|
+
const logger$16 = createLogger("status-cmd");
|
|
6986
6987
|
/**
|
|
6987
6988
|
* Map a manifest per-story status string to the appropriate WorkGraphCounts bucket.
|
|
6988
6989
|
* Unknown strings are treated as `inProgress` (safe default).
|
|
@@ -7094,9 +7095,9 @@ async function runStatusAction(options) {
|
|
|
7094
7095
|
const manifestData = await resolvedManifest.read();
|
|
7095
7096
|
manifestPerStoryState = manifestData.per_story_state;
|
|
7096
7097
|
workGraph = buildWorkGraphFromManifest(manifestData.per_story_state);
|
|
7097
|
-
logger$
|
|
7098
|
+
logger$16.debug({ runId: run?.id }, "status: workGraph built from manifest per_story_state");
|
|
7098
7099
|
} catch {
|
|
7099
|
-
logger$
|
|
7100
|
+
logger$16.debug({ runId: run?.id }, "status: manifest read failed — falling back to wg_stories");
|
|
7100
7101
|
}
|
|
7101
7102
|
if (workGraph === void 0) try {
|
|
7102
7103
|
const wgRepo = new WorkGraphRepository(adapter);
|
|
@@ -7133,10 +7134,10 @@ async function runStatusAction(options) {
|
|
|
7133
7134
|
};
|
|
7134
7135
|
}
|
|
7135
7136
|
} catch (err) {
|
|
7136
|
-
logger$
|
|
7137
|
+
logger$16.debug({ err }, "Work graph query failed, continuing without work graph data");
|
|
7137
7138
|
}
|
|
7138
7139
|
if (run === void 0) {
|
|
7139
|
-
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-
|
|
7140
|
+
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-CvsH53bv.js");
|
|
7140
7141
|
const substrateDirPath = join(projectRoot, ".substrate");
|
|
7141
7142
|
const processInfo = inspectProcessTree$1({
|
|
7142
7143
|
projectRoot,
|
|
@@ -7295,7 +7296,7 @@ async function runStatusAction(options) {
|
|
|
7295
7296
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7296
7297
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
7297
7298
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
7298
|
-
logger$
|
|
7299
|
+
logger$16.error({ err }, "status action failed");
|
|
7299
7300
|
return 1;
|
|
7300
7301
|
} finally {
|
|
7301
7302
|
try {
|
|
@@ -7639,7 +7640,7 @@ Analyze thoroughly and return ONLY the JSON array with no additional text.`;
|
|
|
7639
7640
|
|
|
7640
7641
|
//#endregion
|
|
7641
7642
|
//#region src/cli/commands/amend.ts
|
|
7642
|
-
const logger$
|
|
7643
|
+
const logger$15 = createLogger("amend-cmd");
|
|
7643
7644
|
/**
|
|
7644
7645
|
* Detect and apply supersessions after a phase completes in an amendment run.
|
|
7645
7646
|
*
|
|
@@ -7670,7 +7671,7 @@ async function runPostPhaseSupersessionDetection(adapter, amendmentRunId, curren
|
|
|
7670
7671
|
});
|
|
7671
7672
|
} catch (err) {
|
|
7672
7673
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7673
|
-
logger$
|
|
7674
|
+
logger$15.warn({
|
|
7674
7675
|
err,
|
|
7675
7676
|
originalId: parentMatch.id,
|
|
7676
7677
|
supersedingId: newDec.id
|
|
@@ -7807,7 +7808,7 @@ async function runAmendAction(options) {
|
|
|
7807
7808
|
for (let i = startIdx; i < phaseOrder.length; i++) {
|
|
7808
7809
|
const currentPhase = phaseOrder[i];
|
|
7809
7810
|
const amendmentContext = handler.loadContextForPhase(currentPhase);
|
|
7810
|
-
logger$
|
|
7811
|
+
logger$15.info({
|
|
7811
7812
|
phase: currentPhase,
|
|
7812
7813
|
amendmentContextLen: amendmentContext.length
|
|
7813
7814
|
}, "Amendment context loaded for phase");
|
|
@@ -7928,7 +7929,7 @@ async function runAmendAction(options) {
|
|
|
7928
7929
|
} catch (err) {
|
|
7929
7930
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7930
7931
|
process.stderr.write(`Error: ${msg}\n`);
|
|
7931
|
-
logger$
|
|
7932
|
+
logger$15.error({ err }, "amend failed");
|
|
7932
7933
|
return 1;
|
|
7933
7934
|
} finally {
|
|
7934
7935
|
try {
|
|
@@ -8665,7 +8666,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8665
8666
|
await initSchema(expAdapter);
|
|
8666
8667
|
const { runRunAction: runPipeline } = await import(
|
|
8667
8668
|
/* @vite-ignore */
|
|
8668
|
-
"../run-
|
|
8669
|
+
"../run-UilZoIOh.js"
|
|
8669
8670
|
);
|
|
8670
8671
|
const runStoryFn = async (opts) => {
|
|
8671
8672
|
const exitCode = await runPipeline({
|
|
@@ -8915,7 +8916,7 @@ function registerSupervisorCommand(program, _version = "0.0.0", projectRoot = pr
|
|
|
8915
8916
|
|
|
8916
8917
|
//#endregion
|
|
8917
8918
|
//#region src/cli/commands/metrics.ts
|
|
8918
|
-
const logger$
|
|
8919
|
+
const logger$14 = createLogger("metrics-cmd");
|
|
8919
8920
|
async function openTelemetryAdapter(basePath) {
|
|
8920
8921
|
try {
|
|
8921
8922
|
const adapter = createDatabaseAdapter({
|
|
@@ -9274,7 +9275,7 @@ async function runMetricsAction(options) {
|
|
|
9274
9275
|
}
|
|
9275
9276
|
}
|
|
9276
9277
|
} catch (err) {
|
|
9277
|
-
logger$
|
|
9278
|
+
logger$14.debug({ err }, "getScenarioResultsForRun failed");
|
|
9278
9279
|
}
|
|
9279
9280
|
if (rows.length === 0) {
|
|
9280
9281
|
const msg = `No factory run found with id: ${run}`;
|
|
@@ -9310,7 +9311,7 @@ async function runMetricsAction(options) {
|
|
|
9310
9311
|
}
|
|
9311
9312
|
}
|
|
9312
9313
|
} catch (err) {
|
|
9313
|
-
logger$
|
|
9314
|
+
logger$14.debug({ err }, "getTwinRunsForRun failed — twin_runs table may not exist yet");
|
|
9314
9315
|
}
|
|
9315
9316
|
}
|
|
9316
9317
|
return 0;
|
|
@@ -9320,7 +9321,7 @@ async function runMetricsAction(options) {
|
|
|
9320
9321
|
try {
|
|
9321
9322
|
factoryRuns$1 = await getFactoryRunSummaries(adapter, limit);
|
|
9322
9323
|
} catch (err) {
|
|
9323
|
-
logger$
|
|
9324
|
+
logger$14.debug({ err }, "getFactoryRunSummaries failed in factory-only mode");
|
|
9324
9325
|
}
|
|
9325
9326
|
if (outputFormat === "json") process.stdout.write(formatOutput({ graph_runs: factoryRuns$1 }, "json", true) + "\n");
|
|
9326
9327
|
else if (factoryRuns$1.length === 0) process.stdout.write("No factory runs recorded yet.\n");
|
|
@@ -9423,7 +9424,7 @@ async function runMetricsAction(options) {
|
|
|
9423
9424
|
try {
|
|
9424
9425
|
factoryRuns = await getFactoryRunSummaries(adapter, limit);
|
|
9425
9426
|
} catch (err) {
|
|
9426
|
-
logger$
|
|
9427
|
+
logger$14.debug({ err }, "getFactoryRunSummaries failed — table may not exist in older databases");
|
|
9427
9428
|
}
|
|
9428
9429
|
if (outputFormat === "json") {
|
|
9429
9430
|
const runsWithBreakdown = runs.map((run$1) => ({
|
|
@@ -9509,7 +9510,7 @@ async function runMetricsAction(options) {
|
|
|
9509
9510
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9510
9511
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
9511
9512
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
9512
|
-
logger$
|
|
9513
|
+
logger$14.error({ err }, "metrics action failed");
|
|
9513
9514
|
return 1;
|
|
9514
9515
|
} finally {
|
|
9515
9516
|
try {
|
|
@@ -9565,7 +9566,7 @@ function registerMetricsCommand(program, _version = "0.0.0", projectRoot = proce
|
|
|
9565
9566
|
function getLatestSessionId(_adapter) {
|
|
9566
9567
|
return null;
|
|
9567
9568
|
}
|
|
9568
|
-
const logger$
|
|
9569
|
+
const logger$13 = createLogger("cost-cmd");
|
|
9569
9570
|
const COST_EXIT_SUCCESS = 0;
|
|
9570
9571
|
const COST_EXIT_ERROR = 1;
|
|
9571
9572
|
/**
|
|
@@ -9809,7 +9810,7 @@ async function runCostAction(options) {
|
|
|
9809
9810
|
} catch (err) {
|
|
9810
9811
|
const message = err instanceof Error ? err.message : String(err);
|
|
9811
9812
|
process.stderr.write(`Error: ${message}\n`);
|
|
9812
|
-
logger$
|
|
9813
|
+
logger$13.error({ err }, "runCostAction failed");
|
|
9813
9814
|
return COST_EXIT_ERROR;
|
|
9814
9815
|
} finally {
|
|
9815
9816
|
if (adapter !== null) try {
|
|
@@ -9843,7 +9844,7 @@ function registerCostCommand(program, version = "0.0.0", projectRoot = process.c
|
|
|
9843
9844
|
|
|
9844
9845
|
//#endregion
|
|
9845
9846
|
//#region src/cli/commands/monitor.ts
|
|
9846
|
-
const logger$
|
|
9847
|
+
const logger$12 = createLogger("monitor-cmd");
|
|
9847
9848
|
const MONITOR_EXIT_SUCCESS = 0;
|
|
9848
9849
|
const MONITOR_EXIT_ERROR = 1;
|
|
9849
9850
|
/**
|
|
@@ -10046,7 +10047,7 @@ async function runMonitorReportAction(options) {
|
|
|
10046
10047
|
} catch (err) {
|
|
10047
10048
|
const message = err instanceof Error ? err.message : String(err);
|
|
10048
10049
|
process.stderr.write(`Error: ${message}\n`);
|
|
10049
|
-
logger$
|
|
10050
|
+
logger$12.error({ err }, "runMonitorReportAction failed");
|
|
10050
10051
|
return MONITOR_EXIT_ERROR;
|
|
10051
10052
|
} finally {
|
|
10052
10053
|
if (monitorDb !== null) try {
|
|
@@ -10108,7 +10109,7 @@ async function runMonitorStatusAction(options) {
|
|
|
10108
10109
|
} catch (err) {
|
|
10109
10110
|
const message = err instanceof Error ? err.message : String(err);
|
|
10110
10111
|
process.stderr.write(`Error: ${message}\n`);
|
|
10111
|
-
logger$
|
|
10112
|
+
logger$12.error({ err }, "runMonitorStatusAction failed");
|
|
10112
10113
|
return MONITOR_EXIT_ERROR;
|
|
10113
10114
|
} finally {
|
|
10114
10115
|
if (monitorDb !== null) try {
|
|
@@ -10143,7 +10144,7 @@ async function runMonitorResetAction(options) {
|
|
|
10143
10144
|
} catch (err) {
|
|
10144
10145
|
const message = err instanceof Error ? err.message : String(err);
|
|
10145
10146
|
process.stderr.write(`Error: ${message}\n`);
|
|
10146
|
-
logger$
|
|
10147
|
+
logger$12.error({ err }, "runMonitorResetAction failed");
|
|
10147
10148
|
return MONITOR_EXIT_ERROR;
|
|
10148
10149
|
} finally {
|
|
10149
10150
|
if (monitorDb !== null) try {
|
|
@@ -10191,7 +10192,7 @@ async function runMonitorRecommendationsAction(options) {
|
|
|
10191
10192
|
} catch (err) {
|
|
10192
10193
|
const message = err instanceof Error ? err.message : String(err);
|
|
10193
10194
|
process.stderr.write(`Error: ${message}\n`);
|
|
10194
|
-
logger$
|
|
10195
|
+
logger$12.error({ err }, "runMonitorRecommendationsAction failed");
|
|
10195
10196
|
return MONITOR_EXIT_ERROR;
|
|
10196
10197
|
} finally {
|
|
10197
10198
|
if (monitorDb !== null) try {
|
|
@@ -10269,7 +10270,7 @@ function registerMonitorCommand(program, version = "0.0.0", projectRoot = proces
|
|
|
10269
10270
|
|
|
10270
10271
|
//#endregion
|
|
10271
10272
|
//#region src/cli/commands/merge.ts
|
|
10272
|
-
const logger$
|
|
10273
|
+
const logger$11 = createLogger("merge-cmd");
|
|
10273
10274
|
const MERGE_EXIT_SUCCESS = 0;
|
|
10274
10275
|
const MERGE_EXIT_CONFLICT = 1;
|
|
10275
10276
|
const MERGE_EXIT_ERROR = 2;
|
|
@@ -10307,7 +10308,7 @@ async function mergeTask(taskId, targetBranch, projectRoot) {
|
|
|
10307
10308
|
projectRoot
|
|
10308
10309
|
});
|
|
10309
10310
|
try {
|
|
10310
|
-
logger$
|
|
10311
|
+
logger$11.info({
|
|
10311
10312
|
taskId,
|
|
10312
10313
|
targetBranch
|
|
10313
10314
|
}, "Running conflict detection...");
|
|
@@ -10329,7 +10330,7 @@ async function mergeTask(taskId, targetBranch, projectRoot) {
|
|
|
10329
10330
|
} catch (err) {
|
|
10330
10331
|
const message = err instanceof Error ? err.message : String(err);
|
|
10331
10332
|
console.error(`Error merging task "${taskId}": ${message}`);
|
|
10332
|
-
logger$
|
|
10333
|
+
logger$11.error({
|
|
10333
10334
|
taskId,
|
|
10334
10335
|
err
|
|
10335
10336
|
}, "merge --task failed");
|
|
@@ -10383,7 +10384,7 @@ async function mergeAll(targetBranch, projectRoot, taskIds) {
|
|
|
10383
10384
|
error: message
|
|
10384
10385
|
});
|
|
10385
10386
|
console.log(` Error for task "${taskId}": ${message}`);
|
|
10386
|
-
logger$
|
|
10387
|
+
logger$11.error({
|
|
10387
10388
|
taskId,
|
|
10388
10389
|
err
|
|
10389
10390
|
}, "merge --all: task failed");
|
|
@@ -10436,7 +10437,7 @@ function registerMergeCommand(program, projectRoot = process.cwd()) {
|
|
|
10436
10437
|
|
|
10437
10438
|
//#endregion
|
|
10438
10439
|
//#region src/cli/commands/worktrees.ts
|
|
10439
|
-
const logger$
|
|
10440
|
+
const logger$10 = createLogger("worktrees-cmd");
|
|
10440
10441
|
const WORKTREES_EXIT_SUCCESS = 0;
|
|
10441
10442
|
const WORKTREES_EXIT_ERROR = 1;
|
|
10442
10443
|
/** Valid task statuses for filtering */
|
|
@@ -10563,7 +10564,7 @@ async function listWorktreesAction(options) {
|
|
|
10563
10564
|
try {
|
|
10564
10565
|
worktreeInfos = await manager.listWorktrees();
|
|
10565
10566
|
} catch (err) {
|
|
10566
|
-
logger$
|
|
10567
|
+
logger$10.error({ err }, "Failed to list worktrees");
|
|
10567
10568
|
const message = err instanceof Error ? err.message : String(err);
|
|
10568
10569
|
process.stderr.write(`Error listing worktrees: ${message}\n`);
|
|
10569
10570
|
return WORKTREES_EXIT_ERROR;
|
|
@@ -10590,7 +10591,7 @@ async function listWorktreesAction(options) {
|
|
|
10590
10591
|
} catch (err) {
|
|
10591
10592
|
const message = err instanceof Error ? err.message : String(err);
|
|
10592
10593
|
process.stderr.write(`Error: ${message}\n`);
|
|
10593
|
-
logger$
|
|
10594
|
+
logger$10.error({ err }, "listWorktreesAction failed");
|
|
10594
10595
|
return WORKTREES_EXIT_ERROR;
|
|
10595
10596
|
}
|
|
10596
10597
|
}
|
|
@@ -10619,7 +10620,7 @@ async function cleanupWorktreesAction(options) {
|
|
|
10619
10620
|
} catch (err) {
|
|
10620
10621
|
const message = err instanceof Error ? err.message : String(err);
|
|
10621
10622
|
process.stderr.write(`Error cleaning up worktree for task "${taskId}": ${message}\n`);
|
|
10622
|
-
logger$
|
|
10623
|
+
logger$10.error({
|
|
10623
10624
|
err,
|
|
10624
10625
|
taskId
|
|
10625
10626
|
}, "cleanupWorktreesAction (single) failed");
|
|
@@ -10633,13 +10634,13 @@ async function cleanupWorktreesAction(options) {
|
|
|
10633
10634
|
} catch (err) {
|
|
10634
10635
|
const message = err instanceof Error ? err.message : String(err);
|
|
10635
10636
|
process.stderr.write(`Error during bulk cleanup: ${message}\n`);
|
|
10636
|
-
logger$
|
|
10637
|
+
logger$10.error({ err }, "cleanupWorktreesAction (bulk) failed");
|
|
10637
10638
|
return WORKTREES_EXIT_ERROR;
|
|
10638
10639
|
}
|
|
10639
10640
|
} catch (err) {
|
|
10640
10641
|
const message = err instanceof Error ? err.message : String(err);
|
|
10641
10642
|
process.stderr.write(`Error: ${message}\n`);
|
|
10642
|
-
logger$
|
|
10643
|
+
logger$10.error({ err }, "cleanupWorktreesAction failed");
|
|
10643
10644
|
return WORKTREES_EXIT_ERROR;
|
|
10644
10645
|
}
|
|
10645
10646
|
}
|
|
@@ -10690,7 +10691,7 @@ function registerWorktreesCommand(program, version = "0.0.0", projectRoot = proc
|
|
|
10690
10691
|
|
|
10691
10692
|
//#endregion
|
|
10692
10693
|
//#region src/cli/commands/brainstorm.ts
|
|
10693
|
-
const logger$
|
|
10694
|
+
const logger$9 = createLogger("brainstorm-cmd");
|
|
10694
10695
|
/**
|
|
10695
10696
|
* Detect whether the project has existing planning artifacts that indicate
|
|
10696
10697
|
* this is an amendment session (vs. a brand-new project brainstorm).
|
|
@@ -10736,13 +10737,13 @@ async function loadAmendmentContextDocuments(projectRoot) {
|
|
|
10736
10737
|
try {
|
|
10737
10738
|
brief = await readFile(briefPath, "utf-8");
|
|
10738
10739
|
} catch {
|
|
10739
|
-
logger$
|
|
10740
|
+
logger$9.warn({ briefPath }, "product-brief.md not found — continuing without brief context");
|
|
10740
10741
|
process.stderr.write(`Warning: product-brief.md not found at ${briefPath}\n`);
|
|
10741
10742
|
}
|
|
10742
10743
|
try {
|
|
10743
10744
|
prd = await readFile(prdPath, "utf-8");
|
|
10744
10745
|
} catch {
|
|
10745
|
-
logger$
|
|
10746
|
+
logger$9.warn({ prdPath }, "requirements.md not found — continuing without PRD context");
|
|
10746
10747
|
process.stderr.write(`Warning: requirements.md not found at ${prdPath}\n`);
|
|
10747
10748
|
}
|
|
10748
10749
|
return {
|
|
@@ -10951,7 +10952,7 @@ async function dispatchToPersonas(userPrompt, context, llmDispatch) {
|
|
|
10951
10952
|
}
|
|
10952
10953
|
];
|
|
10953
10954
|
const defaultDispatch = async (prompt, personaName) => {
|
|
10954
|
-
logger$
|
|
10955
|
+
logger$9.debug({
|
|
10955
10956
|
personaName,
|
|
10956
10957
|
promptLength: prompt.length
|
|
10957
10958
|
}, "Dispatching to persona (stub mode)");
|
|
@@ -10968,7 +10969,7 @@ async function dispatchToPersonas(userPrompt, context, llmDispatch) {
|
|
|
10968
10969
|
};
|
|
10969
10970
|
} catch (err) {
|
|
10970
10971
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10971
|
-
logger$
|
|
10972
|
+
logger$9.error({
|
|
10972
10973
|
err,
|
|
10973
10974
|
personaName: persona.name
|
|
10974
10975
|
}, "Persona dispatch failed");
|
|
@@ -11120,7 +11121,7 @@ async function runBrainstormSession(options, llmDispatch, rlInterface) {
|
|
|
11120
11121
|
}
|
|
11121
11122
|
});
|
|
11122
11123
|
rl.on("error", (err) => {
|
|
11123
|
-
logger$
|
|
11124
|
+
logger$9.error({ err }, "readline error");
|
|
11124
11125
|
if (!sessionEnded) endSession(false);
|
|
11125
11126
|
});
|
|
11126
11127
|
});
|
|
@@ -11161,7 +11162,7 @@ function registerBrainstormCommand(program, _version = "0.0.0", projectRoot = pr
|
|
|
11161
11162
|
|
|
11162
11163
|
//#endregion
|
|
11163
11164
|
//#region src/cli/commands/retry-escalated.ts
|
|
11164
|
-
const logger$
|
|
11165
|
+
const logger$8 = createLogger("retry-escalated-cmd");
|
|
11165
11166
|
async function runRetryEscalatedAction(options) {
|
|
11166
11167
|
const { runId, dryRun, force, outputFormat, projectRoot, concurrency, pack: packName, registry: injectedRegistry, agent: agentId, events: eventsFlag } = options;
|
|
11167
11168
|
const dbRoot = await resolveMainRepoRoot(projectRoot);
|
|
@@ -11202,7 +11203,7 @@ async function runRetryEscalatedAction(options) {
|
|
|
11202
11203
|
process.stdout.write(`[INFO] ${storyKey}: Context ceiling set to ${contextCeiling} tokens due to prior context spike pattern.\n`);
|
|
11203
11204
|
}
|
|
11204
11205
|
} catch (err) {
|
|
11205
|
-
logger$
|
|
11206
|
+
logger$8.warn({
|
|
11206
11207
|
err,
|
|
11207
11208
|
storyKey
|
|
11208
11209
|
}, "Failed to read efficiency profile — skipping gate");
|
|
@@ -11364,11 +11365,11 @@ async function runRetryEscalatedAction(options) {
|
|
|
11364
11365
|
output_tokens: output,
|
|
11365
11366
|
cost_usd: costUsd
|
|
11366
11367
|
}).catch((err) => {
|
|
11367
|
-
logger$
|
|
11368
|
+
logger$8.warn({ err }, "Failed to record token usage");
|
|
11368
11369
|
});
|
|
11369
11370
|
}
|
|
11370
11371
|
} catch (err) {
|
|
11371
|
-
logger$
|
|
11372
|
+
logger$8.warn({ err }, "Failed to record token usage");
|
|
11372
11373
|
}
|
|
11373
11374
|
});
|
|
11374
11375
|
if (outputFormat === "human") {
|
|
@@ -11397,7 +11398,7 @@ async function runRetryEscalatedAction(options) {
|
|
|
11397
11398
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11398
11399
|
if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
|
|
11399
11400
|
else process.stderr.write(`Error: ${msg}\n`);
|
|
11400
|
-
logger$
|
|
11401
|
+
logger$8.error({ err }, "retry-escalated failed");
|
|
11401
11402
|
return 1;
|
|
11402
11403
|
} finally {
|
|
11403
11404
|
try {
|
|
@@ -11430,7 +11431,7 @@ function registerRetryEscalatedCommand(program, _version = "0.0.0", projectRoot
|
|
|
11430
11431
|
|
|
11431
11432
|
//#endregion
|
|
11432
11433
|
//#region src/cli/commands/cancel.ts
|
|
11433
|
-
const logger$
|
|
11434
|
+
const logger$7 = createLogger("cancel-cmd");
|
|
11434
11435
|
async function runCancelAction(options) {
|
|
11435
11436
|
const { outputFormat, projectRoot, force } = options;
|
|
11436
11437
|
const dbRoot = await resolveMainRepoRoot(projectRoot);
|
|
@@ -11469,7 +11470,7 @@ async function runCancelAction(options) {
|
|
|
11469
11470
|
}
|
|
11470
11471
|
} catch (err) {
|
|
11471
11472
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11472
|
-
logger$
|
|
11473
|
+
logger$7.warn({
|
|
11473
11474
|
pid,
|
|
11474
11475
|
err: msg
|
|
11475
11476
|
}, "Failed to kill orchestrator");
|
|
@@ -11499,7 +11500,7 @@ async function runCancelAction(options) {
|
|
|
11499
11500
|
await adapter.close();
|
|
11500
11501
|
}
|
|
11501
11502
|
} catch (err) {
|
|
11502
|
-
logger$
|
|
11503
|
+
logger$7.warn({ err }, "Could not update pipeline run status (non-fatal)");
|
|
11503
11504
|
}
|
|
11504
11505
|
if (outputFormat === "json") process.stdout.write(formatOutput({
|
|
11505
11506
|
cancelled: true,
|
|
@@ -11652,7 +11653,7 @@ function emitDiff(diff, ctx) {
|
|
|
11652
11653
|
|
|
11653
11654
|
//#endregion
|
|
11654
11655
|
//#region src/cli/commands/probe-author.ts
|
|
11655
|
-
const logger$
|
|
11656
|
+
const logger$6 = createLogger("cli:probe-author");
|
|
11656
11657
|
/**
|
|
11657
11658
|
* A minimum-viable logger that routes everything to stderr. Used by the
|
|
11658
11659
|
* subcommand to keep stdout reserved for the JSON result payload.
|
|
@@ -11721,7 +11722,7 @@ async function runProbeAuthorDispatch(opts, projectRoot, registry) {
|
|
|
11721
11722
|
logger: stderrLogger
|
|
11722
11723
|
});
|
|
11723
11724
|
const workingDir = opts.workingDir !== void 0 ? resolve$1(opts.workingDir) : resolve$1(storyFilePath, "..");
|
|
11724
|
-
logger$
|
|
11725
|
+
logger$6.info({
|
|
11725
11726
|
storyKey: opts.storyKey,
|
|
11726
11727
|
storyFile: storyFilePath,
|
|
11727
11728
|
epicFile: epicFilePath,
|
|
@@ -11943,7 +11944,7 @@ function registerHistoryCommand(program) {
|
|
|
11943
11944
|
|
|
11944
11945
|
//#endregion
|
|
11945
11946
|
//#region src/cli/commands/repo-map.ts
|
|
11946
|
-
const logger$
|
|
11947
|
+
const logger$5 = createLogger("cli:repo-map");
|
|
11947
11948
|
/** Validate that a symbol name contains only safe identifier characters. */
|
|
11948
11949
|
function isValidSymbolName(name) {
|
|
11949
11950
|
return /^[a-zA-Z0-9_]+$/.test(name);
|
|
@@ -11978,15 +11979,15 @@ function registerRepoMapCommand(program) {
|
|
|
11978
11979
|
const colRows = await doltClient.query(`SHOW COLUMNS FROM repo_map_symbols LIKE 'dependencies'`);
|
|
11979
11980
|
if (colRows.length === 0) {
|
|
11980
11981
|
await doltClient.query(`ALTER TABLE repo_map_symbols ADD COLUMN dependencies JSON`);
|
|
11981
|
-
logger$
|
|
11982
|
+
logger$5.info("Applied migration: added dependencies column to repo_map_symbols");
|
|
11982
11983
|
}
|
|
11983
11984
|
} catch {
|
|
11984
|
-
logger$
|
|
11985
|
+
logger$5.debug("Skipping repo_map_symbols migration: table not yet created");
|
|
11985
11986
|
}
|
|
11986
|
-
const symbolRepo = new DoltSymbolRepository(doltClient, logger$
|
|
11987
|
+
const symbolRepo = new DoltSymbolRepository(doltClient, logger$5);
|
|
11987
11988
|
const metaRepo = new DoltRepoMapMetaRepository(doltClient);
|
|
11988
|
-
const repoMapModule = new RepoMapModule(metaRepo, logger$
|
|
11989
|
-
const queryEngine = new RepoMapQueryEngine(symbolRepo, logger$
|
|
11989
|
+
const repoMapModule = new RepoMapModule(metaRepo, logger$5);
|
|
11990
|
+
const queryEngine = new RepoMapQueryEngine(symbolRepo, logger$5);
|
|
11990
11991
|
if (options.show === true || !options.update && !options.query && !options.dryRun) {
|
|
11991
11992
|
const meta = await metaRepo.getMeta();
|
|
11992
11993
|
const staleResult = await repoMapModule.checkStaleness();
|
|
@@ -12012,9 +12013,9 @@ function registerRepoMapCommand(program) {
|
|
|
12012
12013
|
return;
|
|
12013
12014
|
}
|
|
12014
12015
|
if (options.update === true) {
|
|
12015
|
-
logger$
|
|
12016
|
-
const gitClient = new GitClient(logger$
|
|
12017
|
-
const grammarLoader = new GrammarLoader(logger$
|
|
12016
|
+
logger$5.info("repo-map --update: triggering incremental update");
|
|
12017
|
+
const gitClient = new GitClient(logger$5);
|
|
12018
|
+
const grammarLoader = new GrammarLoader(logger$5);
|
|
12018
12019
|
if (grammarLoader.getGrammar(".ts") === null) {
|
|
12019
12020
|
const msg = "tree-sitter grammars not installed. Run `npm install tree-sitter tree-sitter-typescript tree-sitter-javascript tree-sitter-python` in the substrate installation directory.";
|
|
12020
12021
|
if (options.outputFormat === "json") console.log(JSON.stringify({
|
|
@@ -12025,15 +12026,15 @@ function registerRepoMapCommand(program) {
|
|
|
12025
12026
|
process.exitCode = 1;
|
|
12026
12027
|
return;
|
|
12027
12028
|
}
|
|
12028
|
-
const parser = new SymbolParser(grammarLoader, logger$
|
|
12029
|
-
const storage = new RepoMapStorage(symbolRepo, metaRepo, gitClient, logger$
|
|
12029
|
+
const parser = new SymbolParser(grammarLoader, logger$5);
|
|
12030
|
+
const storage = new RepoMapStorage(symbolRepo, metaRepo, gitClient, logger$5);
|
|
12030
12031
|
let updateWarning;
|
|
12031
12032
|
try {
|
|
12032
12033
|
await storage.incrementalUpdate(dbRoot, parser);
|
|
12033
12034
|
} catch (err) {
|
|
12034
12035
|
if (err instanceof AppError && err.code === ERR_REPO_MAP_STORAGE_WRITE) {
|
|
12035
12036
|
updateWarning = err.message;
|
|
12036
|
-
logger$
|
|
12037
|
+
logger$5.warn({ err }, "repo-map --update: storage write error (partial update)");
|
|
12037
12038
|
} else throw err;
|
|
12038
12039
|
}
|
|
12039
12040
|
const meta = await metaRepo.getMeta();
|
|
@@ -12053,7 +12054,7 @@ function registerRepoMapCommand(program) {
|
|
|
12053
12054
|
return;
|
|
12054
12055
|
}
|
|
12055
12056
|
if (options.query !== void 0) {
|
|
12056
|
-
logger$
|
|
12057
|
+
logger$5.debug({ symbol: options.query }, "repo-map --query");
|
|
12057
12058
|
const result = await queryEngine.query({
|
|
12058
12059
|
symbols: [options.query],
|
|
12059
12060
|
maxTokens: 4e3
|
|
@@ -12075,7 +12076,7 @@ function registerRepoMapCommand(program) {
|
|
|
12075
12076
|
process.exitCode = 1;
|
|
12076
12077
|
return;
|
|
12077
12078
|
}
|
|
12078
|
-
const injector = new RepoMapInjector(queryEngine, logger$
|
|
12079
|
+
const injector = new RepoMapInjector(queryEngine, logger$5);
|
|
12079
12080
|
const injectionResult = await injector.buildContext(storyContent, 2e3);
|
|
12080
12081
|
console.log(JSON.stringify({
|
|
12081
12082
|
text: injectionResult.text,
|
|
@@ -12089,7 +12090,7 @@ function registerRepoMapCommand(program) {
|
|
|
12089
12090
|
|
|
12090
12091
|
//#endregion
|
|
12091
12092
|
//#region src/cli/commands/routing.ts
|
|
12092
|
-
const logger$
|
|
12093
|
+
const logger$4 = createLogger("cli:routing");
|
|
12093
12094
|
function registerRoutingCommand(program) {
|
|
12094
12095
|
program.command("routing").description("Show routing configuration and auto-tune history").option("--history", "Show the routing auto-tune log (model changes applied)").option("--output-format <format>", "Output format: text or json", "text").action(async (options) => {
|
|
12095
12096
|
const dbRoot = await resolveMainRepoRoot(process.cwd());
|
|
@@ -12097,7 +12098,7 @@ function registerRoutingCommand(program) {
|
|
|
12097
12098
|
try {
|
|
12098
12099
|
await store.initialize();
|
|
12099
12100
|
if (options.history === true) {
|
|
12100
|
-
logger$
|
|
12101
|
+
logger$4.debug("routing --history: fetching tune log");
|
|
12101
12102
|
const raw$1 = await store.getMetric("global", "routing_tune_log");
|
|
12102
12103
|
let entries = [];
|
|
12103
12104
|
if (Array.isArray(raw$1)) entries = raw$1.sort((a, b) => b.appliedAt.localeCompare(a.appliedAt));
|
|
@@ -12392,7 +12393,7 @@ function registerFactoryCommand$1(program) {
|
|
|
12392
12393
|
|
|
12393
12394
|
//#endregion
|
|
12394
12395
|
//#region src/cli/commands/reconcile-from-disk.ts
|
|
12395
|
-
const logger$
|
|
12396
|
+
const logger$3 = createLogger("reconcile-from-disk");
|
|
12396
12397
|
/**
|
|
12397
12398
|
* The reconcile write (obs_2026-05-26_031). Keyed on `story_key` ALONE —
|
|
12398
12399
|
* `wg_stories` has no `run_id` column (cols: story_key, epic, title, status,
|
|
@@ -12464,7 +12465,7 @@ async function readRunEntry(dbRoot, resolvedRunId) {
|
|
|
12464
12465
|
stories
|
|
12465
12466
|
};
|
|
12466
12467
|
} catch {
|
|
12467
|
-
logger$
|
|
12468
|
+
logger$3.debug({ runId: resolvedRunId }, "failed to read individual run manifest");
|
|
12468
12469
|
return null;
|
|
12469
12470
|
}
|
|
12470
12471
|
}
|
|
@@ -12599,7 +12600,7 @@ async function runReconcileFromDiskAction(options) {
|
|
|
12599
12600
|
const latestRun = await getLatestRun(probeAdapter);
|
|
12600
12601
|
if (latestRun?.id) resolvedRunId = latestRun.id;
|
|
12601
12602
|
} catch {
|
|
12602
|
-
logger$
|
|
12603
|
+
logger$3.debug("Dolt fallback failed during run-id resolution");
|
|
12603
12604
|
} finally {
|
|
12604
12605
|
await probeAdapter.close().catch(swallowDebug("reconcile-probe-close"));
|
|
12605
12606
|
}
|
|
@@ -12680,7 +12681,7 @@ async function runReconcileFromDiskAction(options) {
|
|
|
12680
12681
|
stdoutTail: failedGateResult?.stdoutTail,
|
|
12681
12682
|
durationMs: durationMs$1
|
|
12682
12683
|
});
|
|
12683
|
-
logger$
|
|
12684
|
+
logger$3.info({
|
|
12684
12685
|
runId: resolvedRunId,
|
|
12685
12686
|
failedGate: failedGateName,
|
|
12686
12687
|
exitCode: failedGateResult?.exitCode
|
|
@@ -12738,7 +12739,7 @@ async function runReconcileFromDiskAction(options) {
|
|
|
12738
12739
|
record.storyKey
|
|
12739
12740
|
]);
|
|
12740
12741
|
});
|
|
12741
|
-
logger$
|
|
12742
|
+
logger$3.info({
|
|
12742
12743
|
runId: resolvedRunId,
|
|
12743
12744
|
affectedStories: reconcilableRecords.map((r) => r.storyKey)
|
|
12744
12745
|
}, "reconcile-from-disk: Dolt update complete");
|
|
@@ -12793,7 +12794,7 @@ function registerReconcileFromDiskCommand(program, _version = "0.0.0", projectRo
|
|
|
12793
12794
|
|
|
12794
12795
|
//#endregion
|
|
12795
12796
|
//#region src/cli/commands/report.ts
|
|
12796
|
-
const logger$
|
|
12797
|
+
const logger$2 = createLogger("report");
|
|
12797
12798
|
/**
|
|
12798
12799
|
* v0.20.110: Minimum output_tokens for a verified/recovered story to be
|
|
12799
12800
|
* trusted as having actually produced work. Below this, the story is flagged
|
|
@@ -12948,7 +12949,7 @@ async function readNotificationsForRun(runId, dbRoot) {
|
|
|
12948
12949
|
const parsed = JSON.parse(raw);
|
|
12949
12950
|
notifications.push(parsed);
|
|
12950
12951
|
} catch (err) {
|
|
12951
|
-
if (err.code !== "ENOENT") logger$
|
|
12952
|
+
if (err.code !== "ENOENT") logger$2.warn({
|
|
12952
12953
|
err,
|
|
12953
12954
|
filePath
|
|
12954
12955
|
}, "failed to read notification file — skipping");
|
|
@@ -12957,7 +12958,7 @@ async function readNotificationsForRun(runId, dbRoot) {
|
|
|
12957
12958
|
try {
|
|
12958
12959
|
await unlink(filePath);
|
|
12959
12960
|
} catch (err) {
|
|
12960
|
-
if (err.code !== "ENOENT") logger$
|
|
12961
|
+
if (err.code !== "ENOENT") logger$2.warn({
|
|
12961
12962
|
err,
|
|
12962
12963
|
filePath
|
|
12963
12964
|
}, "failed to delete notification file — continuing");
|
|
@@ -13290,7 +13291,7 @@ async function resolveLatestRunId(dbRoot) {
|
|
|
13290
13291
|
const latest = await getLatestRun(probeAdapter);
|
|
13291
13292
|
return latest?.id ?? null;
|
|
13292
13293
|
} catch {
|
|
13293
|
-
logger$
|
|
13294
|
+
logger$2.debug("Dolt fallback failed during run-id resolution");
|
|
13294
13295
|
return null;
|
|
13295
13296
|
} finally {
|
|
13296
13297
|
await probeAdapter.close().catch(swallowDebug("report-probe-close"));
|
|
@@ -13301,7 +13302,7 @@ async function runReportAction(options) {
|
|
|
13301
13302
|
const effectiveProjectRoot = process.env["SUBSTRATE_PROJECT_ROOT"] ?? projectRoot;
|
|
13302
13303
|
const dbRoot = _dbRoot ?? await resolveMainRepoRoot(effectiveProjectRoot);
|
|
13303
13304
|
const runsDir = join(dbRoot, ".substrate", "runs");
|
|
13304
|
-
logger$
|
|
13305
|
+
logger$2.debug({
|
|
13305
13306
|
runArg,
|
|
13306
13307
|
effectiveProjectRoot,
|
|
13307
13308
|
dbRoot
|
|
@@ -13316,7 +13317,7 @@ async function runReportAction(options) {
|
|
|
13316
13317
|
const data = await canonical.manifest.read();
|
|
13317
13318
|
manifest = data;
|
|
13318
13319
|
} catch {
|
|
13319
|
-
logger$
|
|
13320
|
+
logger$2.debug({ runId: resolvedRunId }, "canonical manifest read failed — using raw shim");
|
|
13320
13321
|
}
|
|
13321
13322
|
if (!manifest) manifest = await readRawManifest(runsDir, resolvedRunId);
|
|
13322
13323
|
} else {
|
|
@@ -13327,7 +13328,7 @@ async function runReportAction(options) {
|
|
|
13327
13328
|
const data = await canonical.manifest.read();
|
|
13328
13329
|
manifest = data;
|
|
13329
13330
|
} catch {
|
|
13330
|
-
logger$
|
|
13331
|
+
logger$2.debug({ runId: canonical.runId }, "canonical manifest read failed — using raw shim");
|
|
13331
13332
|
manifest = null;
|
|
13332
13333
|
}
|
|
13333
13334
|
}
|
|
@@ -13339,7 +13340,7 @@ async function runReportAction(options) {
|
|
|
13339
13340
|
const data = await reread.manifest.read();
|
|
13340
13341
|
manifest = data;
|
|
13341
13342
|
} catch {
|
|
13342
|
-
logger$
|
|
13343
|
+
logger$2.debug({ runId: resolvedRunId }, "manifest read failed after Dolt resolution");
|
|
13343
13344
|
}
|
|
13344
13345
|
if (!manifest) manifest = await readRawManifest(runsDir, resolvedRunId);
|
|
13345
13346
|
}
|
|
@@ -13368,18 +13369,18 @@ async function runReportAction(options) {
|
|
|
13368
13369
|
const state = manifest.per_story_state[row.story_key];
|
|
13369
13370
|
if (state && !state.completed_at && row.completed_at) state.completed_at = row.completed_at;
|
|
13370
13371
|
}
|
|
13371
|
-
logger$
|
|
13372
|
+
logger$2.debug({ storyCount: rows.length }, "Dolt wg_stories enrichment applied");
|
|
13372
13373
|
}
|
|
13373
13374
|
} catch (err) {
|
|
13374
|
-
logger$
|
|
13375
|
+
logger$2.debug({ err }, "Dolt enrichment unavailable — using manifest-only data (degraded mode)");
|
|
13375
13376
|
} finally {
|
|
13376
13377
|
if (doltClient !== null) await doltClient.close().catch((err) => {
|
|
13377
|
-
logger$
|
|
13378
|
+
logger$2.debug({ err }, "DoltClient.close() failed — non-fatal");
|
|
13378
13379
|
});
|
|
13379
13380
|
}
|
|
13380
13381
|
}
|
|
13381
13382
|
const halts = await readNotificationsForRun(resolvedRunId, dbRoot).catch((err) => {
|
|
13382
|
-
logger$
|
|
13383
|
+
logger$2.debug({ err }, "notification read failed — continuing without halt data");
|
|
13383
13384
|
return [];
|
|
13384
13385
|
});
|
|
13385
13386
|
const storyOutputTokens = new Map();
|
|
@@ -13392,7 +13393,7 @@ async function runReportAction(options) {
|
|
|
13392
13393
|
const storyMetricsRows = await getStoryMetricsForRun(metricsAdapter, resolvedRunId);
|
|
13393
13394
|
for (const row of storyMetricsRows) if (typeof row.output_tokens === "number") storyOutputTokens.set(row.story_key, row.output_tokens);
|
|
13394
13395
|
} catch (err) {
|
|
13395
|
-
logger$
|
|
13396
|
+
logger$2.debug({ err }, "story_metrics read failed — low-output flagging unavailable");
|
|
13396
13397
|
} finally {
|
|
13397
13398
|
await metricsAdapter.close().catch(swallowDebug("report-metrics-close"));
|
|
13398
13399
|
}
|
|
@@ -13406,7 +13407,7 @@ async function runReportAction(options) {
|
|
|
13406
13407
|
const rmData = await rmForAc.read();
|
|
13407
13408
|
acPerStoryState = rmData.per_story_state;
|
|
13408
13409
|
} catch {
|
|
13409
|
-
logger$
|
|
13410
|
+
logger$2.debug({ runId: resolvedRunId }, "RunManifest.read() for --verify-ac failed — using raw manifest fallback");
|
|
13410
13411
|
}
|
|
13411
13412
|
const storyEntries = Object.entries(acPerStoryState);
|
|
13412
13413
|
for (const [storyKey, state] of storyEntries) {
|
|
@@ -13428,7 +13429,7 @@ async function runReportAction(options) {
|
|
|
13428
13429
|
confidence: result.confidence
|
|
13429
13430
|
};
|
|
13430
13431
|
} catch (err) {
|
|
13431
|
-
logger$
|
|
13432
|
+
logger$2.debug({
|
|
13432
13433
|
err,
|
|
13433
13434
|
storyKey
|
|
13434
13435
|
}, "ac traceability check failed for story (skipping)");
|
|
@@ -13461,6 +13462,141 @@ function registerReportCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
13461
13462
|
});
|
|
13462
13463
|
}
|
|
13463
13464
|
|
|
13465
|
+
//#endregion
|
|
13466
|
+
//#region src/modules/compiled-workflows/acceptance-derive.ts
|
|
13467
|
+
const logger$1 = createLogger("compiled-workflows:acceptance-derive");
|
|
13468
|
+
/** Cap on injected source-document content (chars) — PRDs can be book-length. */
|
|
13469
|
+
const SOURCE_CONTENT_CAP = 12e4;
|
|
13470
|
+
/** Shape problems the schema can't express: duplicate ids, id/end-state prefix drift. */
|
|
13471
|
+
function validateDerivedJourneys(journeys) {
|
|
13472
|
+
if (journeys.length === 0) return "derive produced zero journeys — a PRD with no identifiable user journeys should be reported via result: failed with an error, not an empty success";
|
|
13473
|
+
const seen = new Set();
|
|
13474
|
+
for (const j of journeys) {
|
|
13475
|
+
if (seen.has(j.id)) return `duplicate journey id "${j.id}"`;
|
|
13476
|
+
seen.add(j.id);
|
|
13477
|
+
for (const es of j.end_states) if (!es.id.startsWith(`${j.id}.`)) return `end-state "${es.id}" of journey "${j.id}" must use the "<journey-id>.<letter>" convention`;
|
|
13478
|
+
}
|
|
13479
|
+
return void 0;
|
|
13480
|
+
}
|
|
13481
|
+
async function runAcceptanceDerive(deps, params) {
|
|
13482
|
+
const { prdRelPath, prdContent, uxJourneysContent, existingRegistryYaml } = params;
|
|
13483
|
+
let template;
|
|
13484
|
+
try {
|
|
13485
|
+
template = await deps.pack.getPrompt("acceptance-derive");
|
|
13486
|
+
} catch (err) {
|
|
13487
|
+
return {
|
|
13488
|
+
result: "failed",
|
|
13489
|
+
error: `Failed to retrieve acceptance-derive prompt: ${err instanceof Error ? err.message : String(err)}`,
|
|
13490
|
+
tokenUsage: {
|
|
13491
|
+
input: 0,
|
|
13492
|
+
output: 0
|
|
13493
|
+
}
|
|
13494
|
+
};
|
|
13495
|
+
}
|
|
13496
|
+
const truncated = prdContent.length > SOURCE_CONTENT_CAP;
|
|
13497
|
+
const buildPrompt = (correctivePreamble) => {
|
|
13498
|
+
const { prompt } = assemblePrompt(template, [
|
|
13499
|
+
{
|
|
13500
|
+
name: "source_path",
|
|
13501
|
+
content: prdRelPath,
|
|
13502
|
+
priority: "required"
|
|
13503
|
+
},
|
|
13504
|
+
{
|
|
13505
|
+
name: "source_content",
|
|
13506
|
+
content: (truncated ? `(truncated to first ${String(SOURCE_CONTENT_CAP)} chars)\n` : "") + prdContent.slice(0, SOURCE_CONTENT_CAP),
|
|
13507
|
+
priority: "required"
|
|
13508
|
+
},
|
|
13509
|
+
{
|
|
13510
|
+
name: "ux_journeys",
|
|
13511
|
+
content: uxJourneysContent ?? "(no UX journey artifact provided)",
|
|
13512
|
+
priority: "required"
|
|
13513
|
+
},
|
|
13514
|
+
{
|
|
13515
|
+
name: "existing_registry",
|
|
13516
|
+
content: existingRegistryYaml ?? "(no existing registry — this is a first derivation)",
|
|
13517
|
+
priority: "required"
|
|
13518
|
+
}
|
|
13519
|
+
], getTokenCeiling("acceptance-derive", deps.tokenCeilings).ceiling);
|
|
13520
|
+
return correctivePreamble !== void 0 ? `${correctivePreamble}\n\n${prompt}` : prompt;
|
|
13521
|
+
};
|
|
13522
|
+
let totalTokens = {
|
|
13523
|
+
input: 0,
|
|
13524
|
+
output: 0
|
|
13525
|
+
};
|
|
13526
|
+
let lastProblem = "unknown";
|
|
13527
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
13528
|
+
const prompt = attempt === 0 ? buildPrompt() : buildPrompt(`PREVIOUS ATTEMPT REJECTED: ${lastProblem}. Emit ONLY the YAML block per the Output Contract — unique journey ids, end-state ids prefixed "<journey-id>.", surfaces from the enum.`);
|
|
13529
|
+
const handle = deps.dispatcher.dispatch({
|
|
13530
|
+
prompt,
|
|
13531
|
+
agent: deps.agentId ?? "claude-code",
|
|
13532
|
+
taskType: "acceptance-derive",
|
|
13533
|
+
outputSchema: AcceptanceDeriveResultSchema,
|
|
13534
|
+
maxTurns: 30,
|
|
13535
|
+
...deps.otlpEndpoint !== void 0 ? { otlpEndpoint: deps.otlpEndpoint } : {}
|
|
13536
|
+
});
|
|
13537
|
+
let dispatchResult;
|
|
13538
|
+
try {
|
|
13539
|
+
dispatchResult = await handle.result;
|
|
13540
|
+
} catch (err) {
|
|
13541
|
+
return {
|
|
13542
|
+
result: "failed",
|
|
13543
|
+
error: `Dispatch error: ${err instanceof Error ? err.message : String(err)}`,
|
|
13544
|
+
tokenUsage: totalTokens
|
|
13545
|
+
};
|
|
13546
|
+
}
|
|
13547
|
+
totalTokens = {
|
|
13548
|
+
input: totalTokens.input + dispatchResult.tokenEstimate.input,
|
|
13549
|
+
output: totalTokens.output + dispatchResult.tokenEstimate.output
|
|
13550
|
+
};
|
|
13551
|
+
if (dispatchResult.status === "failed" || dispatchResult.status === "timeout") return {
|
|
13552
|
+
result: "failed",
|
|
13553
|
+
error: `Dispatch status: ${dispatchResult.status}. ${dispatchResult.parseError ?? ""}`.trim(),
|
|
13554
|
+
tokenUsage: totalTokens
|
|
13555
|
+
};
|
|
13556
|
+
const parsed = AcceptanceDeriveResultSchema.safeParse(dispatchResult.parsed);
|
|
13557
|
+
if (!parsed.success) {
|
|
13558
|
+
lastProblem = `output failed schema validation (${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 500)})`;
|
|
13559
|
+
logger$1.warn({
|
|
13560
|
+
prdRelPath,
|
|
13561
|
+
attempt,
|
|
13562
|
+
lastProblem
|
|
13563
|
+
}, "RP1.1: derive output invalid");
|
|
13564
|
+
continue;
|
|
13565
|
+
}
|
|
13566
|
+
if (parsed.data.result === "failed") return {
|
|
13567
|
+
result: "failed",
|
|
13568
|
+
error: "acceptance-derive-refused",
|
|
13569
|
+
details: parsed.data.error ?? "derive agent reported failure without a reason",
|
|
13570
|
+
tokenUsage: totalTokens
|
|
13571
|
+
};
|
|
13572
|
+
const shapeProblem = validateDerivedJourneys(parsed.data.journeys);
|
|
13573
|
+
if (shapeProblem !== void 0) {
|
|
13574
|
+
lastProblem = shapeProblem;
|
|
13575
|
+
logger$1.warn({
|
|
13576
|
+
prdRelPath,
|
|
13577
|
+
attempt,
|
|
13578
|
+
shapeProblem
|
|
13579
|
+
}, "RP1.1: derived journeys malformed");
|
|
13580
|
+
continue;
|
|
13581
|
+
}
|
|
13582
|
+
logger$1.info({
|
|
13583
|
+
prdRelPath,
|
|
13584
|
+
journeys: parsed.data.journeys.map((j) => `${j.id}[${j.criticality}]`)
|
|
13585
|
+
}, "RP1.1: derive candidates accepted");
|
|
13586
|
+
return {
|
|
13587
|
+
result: "success",
|
|
13588
|
+
journeys: parsed.data.journeys,
|
|
13589
|
+
tokenUsage: totalTokens
|
|
13590
|
+
};
|
|
13591
|
+
}
|
|
13592
|
+
return {
|
|
13593
|
+
result: "failed",
|
|
13594
|
+
error: "acceptance-derive-invalid",
|
|
13595
|
+
details: `derive agent produced invalid output twice — last problem: ${lastProblem}`,
|
|
13596
|
+
tokenUsage: totalTokens
|
|
13597
|
+
};
|
|
13598
|
+
}
|
|
13599
|
+
|
|
13464
13600
|
//#endregion
|
|
13465
13601
|
//#region src/cli/commands/acceptance.ts
|
|
13466
13602
|
const ACCEPTANCE_EXIT_SUCCESS = 0;
|
|
@@ -13673,6 +13809,225 @@ function registerAcceptanceCommand(program, version, registry) {
|
|
|
13673
13809
|
process.stdout.write(JSON.stringify(output, null, 2) + "\n");
|
|
13674
13810
|
process.exit(result.result === "success" ? ACCEPTANCE_EXIT_SUCCESS : ACCEPTANCE_EXIT_ERROR);
|
|
13675
13811
|
});
|
|
13812
|
+
acceptanceCmd.command("derive").description("Derive a journey-registry CANDIDATE from a PRD (planning-lineage agent). Writes journeys.candidate.yaml — non-authoritative, ignored by the gate, promoted only by your explicit ratify action.").requiredOption("--prd <path>", "source document (PRD) to derive from — project-relative").option("--ux <path>", "optional UX journey artifact to derive alongside the PRD").option("--out <path>", `candidate output path (default: ${JOURNEY_CANDIDATE_PATH})`).option("--force", "overwrite an existing candidate file", false).option("--agent <id>", "agent adapter id", "claude-code").option("--pack <name>", "methodology pack carrying the derive prompt", "bmad").action(async (opts) => {
|
|
13813
|
+
if (process.env.LOG_LEVEL === void 0) process.env.LOG_LEVEL = "silent";
|
|
13814
|
+
if (registry === void 0) {
|
|
13815
|
+
process.stdout.write("acceptance derive: adapter registry unavailable in this invocation context\n");
|
|
13816
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13817
|
+
}
|
|
13818
|
+
const projectRoot = process.cwd();
|
|
13819
|
+
const prdAbs = resolve$1(projectRoot, opts.prd);
|
|
13820
|
+
const prdRel = relative(projectRoot, prdAbs);
|
|
13821
|
+
if (prdRel.startsWith("..") || prdRel === "") {
|
|
13822
|
+
process.stdout.write(`acceptance derive: --prd must resolve inside the project root (got ${prdAbs})\n`);
|
|
13823
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13824
|
+
}
|
|
13825
|
+
let prdContent;
|
|
13826
|
+
try {
|
|
13827
|
+
prdContent = await readFile$1(prdAbs, "utf-8");
|
|
13828
|
+
} catch (err) {
|
|
13829
|
+
process.stdout.write(`acceptance derive: cannot read PRD at ${prdAbs}: ${String(err)}\n`);
|
|
13830
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13831
|
+
return;
|
|
13832
|
+
}
|
|
13833
|
+
let uxContent;
|
|
13834
|
+
if (opts.ux !== void 0) try {
|
|
13835
|
+
uxContent = await readFile$1(resolve$1(projectRoot, opts.ux), "utf-8");
|
|
13836
|
+
} catch (err) {
|
|
13837
|
+
process.stdout.write(`acceptance derive: cannot read UX artifact at ${opts.ux}: ${String(err)}\n`);
|
|
13838
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13839
|
+
return;
|
|
13840
|
+
}
|
|
13841
|
+
let existingRegistryYaml;
|
|
13842
|
+
try {
|
|
13843
|
+
existingRegistryYaml = await readFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), "utf-8");
|
|
13844
|
+
} catch {
|
|
13845
|
+
existingRegistryYaml = void 0;
|
|
13846
|
+
}
|
|
13847
|
+
const outPath = opts.out !== void 0 ? resolve$1(projectRoot, opts.out) : join$1(projectRoot, JOURNEY_CANDIDATE_PATH);
|
|
13848
|
+
if (!opts.force) try {
|
|
13849
|
+
await readFile$1(outPath, "utf-8");
|
|
13850
|
+
process.stdout.write(`acceptance derive: candidate already exists at ${outPath} — review it, or re-run with --force to overwrite\n`);
|
|
13851
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13852
|
+
} catch {}
|
|
13853
|
+
const eventBus = createEventBus();
|
|
13854
|
+
const adapter = new InMemoryDatabaseAdapter();
|
|
13855
|
+
const packLoader = createPackLoader();
|
|
13856
|
+
let pack;
|
|
13857
|
+
try {
|
|
13858
|
+
pack = await packLoader.load(join$1(projectRoot, "packs", opts.pack));
|
|
13859
|
+
} catch (err) {
|
|
13860
|
+
process.stdout.write(`acceptance derive: failed to load pack '${opts.pack}': ${String(err)}\n`);
|
|
13861
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13862
|
+
return;
|
|
13863
|
+
}
|
|
13864
|
+
const contextCompiler = createContextCompiler({ db: adapter });
|
|
13865
|
+
const dispatcher = createDispatcher({
|
|
13866
|
+
eventBus,
|
|
13867
|
+
adapterRegistry: registry,
|
|
13868
|
+
logger: {
|
|
13869
|
+
debug: () => {},
|
|
13870
|
+
info: () => {},
|
|
13871
|
+
warn: () => {},
|
|
13872
|
+
error: () => {}
|
|
13873
|
+
}
|
|
13874
|
+
});
|
|
13875
|
+
process.stderr.write(`deriving journey candidates from ${prdRel} (real agent dispatch — may take a few minutes)…\n`);
|
|
13876
|
+
const result = await runAcceptanceDerive({
|
|
13877
|
+
db: adapter,
|
|
13878
|
+
pack,
|
|
13879
|
+
contextCompiler,
|
|
13880
|
+
dispatcher,
|
|
13881
|
+
agentId: opts.agent
|
|
13882
|
+
}, {
|
|
13883
|
+
prdRelPath: prdRel,
|
|
13884
|
+
prdContent,
|
|
13885
|
+
...uxContent !== void 0 ? { uxJourneysContent: uxContent } : {},
|
|
13886
|
+
...existingRegistryYaml !== void 0 ? { existingRegistryYaml } : {}
|
|
13887
|
+
});
|
|
13888
|
+
await dispatcher.shutdown();
|
|
13889
|
+
if (result.result !== "success" || result.journeys === void 0) {
|
|
13890
|
+
process.stdout.write(`acceptance derive: FAILED — ${result.error ?? "unknown"}${result.details !== void 0 ? `: ${result.details}` : ""}\n`);
|
|
13891
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13892
|
+
return;
|
|
13893
|
+
}
|
|
13894
|
+
const sourceSha = createHash("sha256").update(prdContent, "utf-8").digest("hex");
|
|
13895
|
+
const candidateDoc = {
|
|
13896
|
+
candidate: true,
|
|
13897
|
+
derived_from: prdRel,
|
|
13898
|
+
source_sha256: sourceSha,
|
|
13899
|
+
derived_at: new Date().toISOString(),
|
|
13900
|
+
journeys: result.journeys
|
|
13901
|
+
};
|
|
13902
|
+
const header = "# CANDIDATE journey registry — NOT authoritative.\n# Derived by `substrate acceptance derive`; the acceptance gate IGNORES this file.\n# Review (edit freely), then promote to journeys.yaml via your explicit ratify action.\n";
|
|
13903
|
+
try {
|
|
13904
|
+
await mkdir$1(dirname$1(outPath), { recursive: true });
|
|
13905
|
+
await writeFile$1(outPath, header + dump(candidateDoc, { lineWidth: 120 }), "utf-8");
|
|
13906
|
+
} catch (err) {
|
|
13907
|
+
process.stdout.write(`acceptance derive: failed to write candidate at ${outPath}: ${String(err)}\n`);
|
|
13908
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13909
|
+
return;
|
|
13910
|
+
}
|
|
13911
|
+
const needsElaboration = result.journeys.filter((j) => j.end_states.length === 0);
|
|
13912
|
+
process.stdout.write(`candidate written: ${relative(projectRoot, outPath)}\n ${String(result.journeys.length)} journeys (${String(result.journeys.filter((j) => j.criticality === "critical").length)} critical), ${String(result.journeys.reduce((n, j) => n + j.end_states.length, 0))} end-states` + (needsElaboration.length > 0 ? `, ${String(needsElaboration.length)} journey(s) need end-state elaboration: ${needsElaboration.map((j) => j.id).join(", ")}` : "") + `
|
|
13913
|
+
derived from ${prdRel} (sha256 ${sourceSha.slice(0, 12)}…)\n`);
|
|
13914
|
+
if (existingRegistryYaml !== void 0) {
|
|
13915
|
+
const parsedExisting = parseJourneyRegistry(existingRegistryYaml);
|
|
13916
|
+
if (parsedExisting.ok) process.stdout.write(`delta vs ratified registry v${String(parsedExisting.registry.version)}:\n${renderRegistryDiff(diffJourneySets(parsedExisting.registry.journeys, result.journeys))}\n`);
|
|
13917
|
+
}
|
|
13918
|
+
process.stdout.write("This candidate is NOT authoritative and the gate ignores it. Review every journey against the PRD — a journey missing here is invisible to the whole acceptance machinery.\n");
|
|
13919
|
+
process.exit(ACCEPTANCE_EXIT_SUCCESS);
|
|
13920
|
+
});
|
|
13921
|
+
acceptanceCmd.command("ratify").description(`Promote ${JOURNEY_CANDIDATE_PATH} to ${JOURNEY_REGISTRY_PATH} with a recorded provenance block. Interactive confirm unless --yes. The candidate file is deleted on success.`).option("--exclude <spec>", "exclude a candidate journey: \"UJ-2: reason text\" (repeatable; reason mandatory)", (v, acc) => [...acc, v], []).option("--epic <spec>", "assign an epic at ratify time: \"UJ-1=2\" (repeatable; critical journeys require one)", (v, acc) => [...acc, v], []).option("--ratified-by <name>", "who is ratifying (recorded in provenance)", "operator").option("--yes", "skip the interactive confirmation", false).action(async (opts) => {
|
|
13922
|
+
const projectRoot = process.cwd();
|
|
13923
|
+
const candidatePath = join$1(projectRoot, JOURNEY_CANDIDATE_PATH);
|
|
13924
|
+
let candidateContent;
|
|
13925
|
+
try {
|
|
13926
|
+
candidateContent = await readFile$1(candidatePath, "utf-8");
|
|
13927
|
+
} catch {
|
|
13928
|
+
process.stdout.write(`acceptance ratify: no candidate at ${JOURNEY_CANDIDATE_PATH} — run \`substrate acceptance derive --prd <path>\` first\n`);
|
|
13929
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13930
|
+
return;
|
|
13931
|
+
}
|
|
13932
|
+
const parsedCandidate = parseJourneyCandidate(candidateContent);
|
|
13933
|
+
if (!parsedCandidate.ok) {
|
|
13934
|
+
process.stdout.write(`acceptance ratify: candidate invalid:\n${parsedCandidate.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n")}\n`);
|
|
13935
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13936
|
+
return;
|
|
13937
|
+
}
|
|
13938
|
+
const candidate = parsedCandidate.candidate;
|
|
13939
|
+
const excludes = [];
|
|
13940
|
+
for (const spec of opts.exclude) {
|
|
13941
|
+
const sep = spec.indexOf(":");
|
|
13942
|
+
const id = sep >= 0 ? spec.slice(0, sep).trim() : spec.trim();
|
|
13943
|
+
const reason = sep >= 0 ? spec.slice(sep + 1).trim() : "";
|
|
13944
|
+
if (reason === "") {
|
|
13945
|
+
process.stdout.write(`acceptance ratify: --exclude "${spec}" has no reason — use "ID: reason" (reasonless exclusions are unauditable)\n`);
|
|
13946
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13947
|
+
return;
|
|
13948
|
+
}
|
|
13949
|
+
excludes.push({
|
|
13950
|
+
candidate: id,
|
|
13951
|
+
reason
|
|
13952
|
+
});
|
|
13953
|
+
}
|
|
13954
|
+
const epicAssignments = {};
|
|
13955
|
+
for (const spec of opts.epic) {
|
|
13956
|
+
const sep = spec.indexOf("=");
|
|
13957
|
+
const id = sep >= 0 ? spec.slice(0, sep).trim() : "";
|
|
13958
|
+
const n = sep >= 0 ? Number(spec.slice(sep + 1).trim()) : NaN;
|
|
13959
|
+
if (id === "" || !Number.isInteger(n) || n <= 0) {
|
|
13960
|
+
process.stdout.write(`acceptance ratify: --epic "${spec}" must be "JOURNEY-ID=<positive integer>"\n`);
|
|
13961
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13962
|
+
return;
|
|
13963
|
+
}
|
|
13964
|
+
epicAssignments[id] = n;
|
|
13965
|
+
}
|
|
13966
|
+
let existingRegistry;
|
|
13967
|
+
try {
|
|
13968
|
+
const existingContent = await readFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), "utf-8");
|
|
13969
|
+
const parsedExisting = parseJourneyRegistry(existingContent);
|
|
13970
|
+
if (!parsedExisting.ok) {
|
|
13971
|
+
process.stdout.write(`acceptance ratify: existing ${JOURNEY_REGISTRY_PATH} is INVALID — fix or remove it before re-ratifying:\n${parsedExisting.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n")}\n`);
|
|
13972
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13973
|
+
return;
|
|
13974
|
+
}
|
|
13975
|
+
existingRegistry = parsedExisting.registry;
|
|
13976
|
+
} catch {
|
|
13977
|
+
existingRegistry = void 0;
|
|
13978
|
+
}
|
|
13979
|
+
let sourceContent;
|
|
13980
|
+
try {
|
|
13981
|
+
sourceContent = await readFile$1(join$1(projectRoot, candidate.derived_from), "utf-8");
|
|
13982
|
+
} catch (err) {
|
|
13983
|
+
process.stdout.write(`acceptance ratify: cannot read source ${candidate.derived_from} (recorded in the candidate): ${String(err)}\n`);
|
|
13984
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13985
|
+
return;
|
|
13986
|
+
}
|
|
13987
|
+
const result = ratifyCandidate(candidate, {
|
|
13988
|
+
excludes,
|
|
13989
|
+
ratifiedBy: opts.ratifiedBy,
|
|
13990
|
+
sourceContent,
|
|
13991
|
+
now: new Date().toISOString(),
|
|
13992
|
+
...existingRegistry !== void 0 ? { existingRegistry } : {},
|
|
13993
|
+
epicAssignments
|
|
13994
|
+
});
|
|
13995
|
+
if (!result.ok) {
|
|
13996
|
+
process.stdout.write(`acceptance ratify: the candidate would not ratify into a VALID registry — edit ${JOURNEY_CANDIDATE_PATH} (it is editable by design), assign epics via --epic, or exclude journeys via --exclude:\n` + result.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n") + "\n");
|
|
13997
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13998
|
+
return;
|
|
13999
|
+
}
|
|
14000
|
+
const reg = result.registry;
|
|
14001
|
+
process.stdout.write(`ratifying → ${JOURNEY_REGISTRY_PATH} v${String(reg.version)}${existingRegistry !== void 0 ? ` (replacing v${String(existingRegistry.version)})` : ""}\n` + reg.journeys.map((j) => ` ${j.id} [${j.criticality}${j.epic !== void 0 ? ` epic ${String(j.epic)}` : ""}] ${j.title} — ${String(j.end_states.length)} end-state(s)\n`).join("") + (reg.provenance?.excluded !== void 0 ? reg.provenance.excluded.map((e) => ` excluded: ${e.candidate} — ${e.reason}\n`).join("") : ""));
|
|
14002
|
+
if (existingRegistry !== void 0) process.stdout.write(`delta vs v${String(existingRegistry.version)}:\n${renderRegistryDiff(diffJourneySets(existingRegistry.journeys, candidate.journeys))}\n`);
|
|
14003
|
+
for (const w of result.warnings) process.stdout.write(`WARNING: ${w}\n`);
|
|
14004
|
+
if (!opts.yes) {
|
|
14005
|
+
const rl = createInterface$2({
|
|
14006
|
+
input: process.stdin,
|
|
14007
|
+
output: process.stderr
|
|
14008
|
+
});
|
|
14009
|
+
const answer = await rl.question("ratify? [y/N] ");
|
|
14010
|
+
rl.close();
|
|
14011
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
14012
|
+
process.stdout.write("aborted — candidate left in place\n");
|
|
14013
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
14014
|
+
return;
|
|
14015
|
+
}
|
|
14016
|
+
}
|
|
14017
|
+
const registryHeader = "# Journey registry — ratified via `substrate acceptance ratify`.\n# The acceptance gate reads THIS file from the trusted tree. COMMIT it.\n";
|
|
14018
|
+
try {
|
|
14019
|
+
await mkdir$1(dirname$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH)), { recursive: true });
|
|
14020
|
+
await writeFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), registryHeader + dump(reg, { lineWidth: 120 }), "utf-8");
|
|
14021
|
+
await unlink$1(candidatePath);
|
|
14022
|
+
} catch (err) {
|
|
14023
|
+
process.stdout.write(`acceptance ratify: write failed: ${String(err)}\n`);
|
|
14024
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
14025
|
+
return;
|
|
14026
|
+
}
|
|
14027
|
+
process.stdout.write(`ratified: ${JOURNEY_REGISTRY_PATH} v${String(reg.version)} (provenance recorded, ratified_by: ${opts.ratifiedBy}; candidate deleted)\nCOMMIT the registry — the gate reads the trusted (committed) tree.
|
|
14028
|
+
`);
|
|
14029
|
+
process.exit(ACCEPTANCE_EXIT_SUCCESS);
|
|
14030
|
+
});
|
|
13676
14031
|
acceptanceCmd.command("canary <journeyId>").description("Self-test the gate: revert a journey's wiring commit(s), re-judge, require the verdict to flip. A miss auto-demotes the gate to advisory. Set LOG_LEVEL=silent for clean JSON.").requiredOption("--wiring-commit <sha...>", "commit SHA(s) that wired the journey (reverted in a scratch clone)").option("--registry-file <path>", `registry YAML (default: ${JOURNEY_REGISTRY_PATH} in cwd)`).option("--agent <id>", "agent adapter id", "claude-code").option("--pack <name>", "methodology pack carrying the judge prompt", "bmad").action(async (journeyId, opts) => {
|
|
13677
14032
|
if (process.env.LOG_LEVEL === void 0) process.env.LOG_LEVEL = "silent";
|
|
13678
14033
|
if (registry === void 0) {
|
|
@@ -13707,7 +14062,7 @@ function registerAcceptanceCommand(program, version, registry) {
|
|
|
13707
14062
|
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13708
14063
|
return;
|
|
13709
14064
|
}
|
|
13710
|
-
const { runAcceptanceJudge: runAcceptanceJudge$1 } = await import("../acceptance-judge-
|
|
14065
|
+
const { runAcceptanceJudge: runAcceptanceJudge$1 } = await import("../acceptance-judge-D5Iba2D_.js");
|
|
13711
14066
|
const eventBus = createEventBus();
|
|
13712
14067
|
const adapter = new InMemoryDatabaseAdapter();
|
|
13713
14068
|
const packLoader = createPackLoader();
|