substrate-ai 0.21.17 → 0.21.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +78 -15
- package/dist/{health-CI8pIygU.js → health-CzbtBIx0.js} +2 -2
- package/dist/{health-C1m6-7WH.js → health-Dn_4DY__.js} +2 -2
- package/dist/index.d.ts +33 -1
- package/dist/{interactive-prompt-BWdH9Lb9.js → interactive-prompt-DVX_J6Mp.js} +2 -2
- package/dist/{manifest-read-3cF8yP3_.js → manifest-read-B80k9pb_.js} +40 -4
- package/dist/modules/interactive-prompt/index.js +2 -2
- package/dist/{run-AKetuV82.js → run-BYySwmdu.js} +737 -553
- package/dist/{run-CvP_sgQ4.js → run-In1WjgGG.js} +4 -4
- package/package.json +1 -1
- package/packs/bmad/prompts/ux-step-3-journeys.md +18 -6
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-
|
|
1
|
+
import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-CzbtBIx0.js";
|
|
2
2
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
3
3
|
import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
|
|
4
4
|
import { ADVISORY_NOTES, BRANCH_PREFIX, CLAUDE_AUTH_FAILURE_HINT, CODEX_SANDBOX_BLOCK_HINT, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createGitWorktreeManager, createPipelineRun, createRequirement, detectClaudeAuthFailure, detectCodexSandboxBlock, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-BZGqn-XQ.js";
|
|
5
|
-
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, FindingsInjector, JOURNEY_DEFERRALS_PATH, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, checkRegistryStaleness, computeJourneyCoverage, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, effectiveAcceptanceMode, extractTargetFilesFromStoryContent, isProjectContainedPath, loadAcceptanceContractFromTrustedTree, loadJourneyDeferralsFromTrustedTree, loadJourneyRegistryFromTrustedTree, parseRuntimeProbes, parseStoryFrontmatter, readTrustedFileContent, recordCriticalFail, renderFindings, renderSurface, renderVerdictHtml, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery, summarizeCoverage } from "./manifest-read-
|
|
5
|
+
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, FindingsInjector, JOURNEY_CANDIDATE_PATH, JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, checkRegistryStaleness, computeJourneyCoverage, computeUndispositioned, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, effectiveAcceptanceMode, extractTargetFilesFromStoryContent, isProjectContainedPath, loadAcceptanceContractFromTrustedTree, loadJourneyDeferralsFromTrustedTree, loadJourneyRegistryFromTrustedTree, parseJourneyRegistry, parseRuntimeProbes, parseStoryFrontmatter, readTrustedFileContent, recordCriticalFail, renderFindings, renderSurface, renderVerdictHtml, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery, summarizeCoverage } from "./manifest-read-B80k9pb_.js";
|
|
6
6
|
import { CodeReviewResultSchema, CreateStoryResultSchema, DevStoryResultSchema, ProbeAuthorResultSchema, TestExpansionResultSchema, TestPlanResultSchema, assemblePrompt, countTokens, getTokenCeiling, runAcceptanceJudge, truncateToTokens } from "./acceptance-judge-COyOxhQ2.js";
|
|
7
7
|
import { WorkGraphRepository, detectCycles } from "./work-graph-repository-4cKsf8Lf.js";
|
|
8
8
|
import { deriveExitCode, routeDecision } from "./decision-router-Dyby0fUf.js";
|
|
9
|
-
import { runInteractivePrompt } from "./interactive-prompt-
|
|
9
|
+
import { runInteractivePrompt } from "./interactive-prompt-DVX_J6Mp.js";
|
|
10
10
|
import { runRecoveryEngine } from "./recovery-engine-dtLHyV4M.js";
|
|
11
11
|
import { basename, dirname, extname, join } from "path";
|
|
12
12
|
import { access, readFile, readdir, stat } from "fs/promises";
|
|
13
13
|
import { EventEmitter } from "node:events";
|
|
14
14
|
import * as yaml$1 from "js-yaml";
|
|
15
|
-
import yaml from "js-yaml";
|
|
15
|
+
import yaml, { dump } from "js-yaml";
|
|
16
16
|
import * as actualFS from "node:fs";
|
|
17
17
|
import { accessSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
|
|
18
18
|
import { exec, execFile, execFileSync, execSync, spawn } from "node:child_process";
|
|
@@ -68,7 +68,9 @@ const PackManifestSchema = z.object({
|
|
|
68
68
|
templates: z.record(z.string(), z.string()),
|
|
69
69
|
conflictGroups: z.record(z.string(), z.string()).optional(),
|
|
70
70
|
verifyCommand: z.union([z.string(), z.literal(false)]).optional(),
|
|
71
|
-
verifyTimeoutMs: z.number().optional()
|
|
71
|
+
verifyTimeoutMs: z.number().optional(),
|
|
72
|
+
uxDesign: z.boolean().optional(),
|
|
73
|
+
research: z.boolean().optional()
|
|
72
74
|
});
|
|
73
75
|
const ConstraintSeveritySchema = z.enum([
|
|
74
76
|
"required",
|
|
@@ -1091,10 +1093,47 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
1091
1093
|
}
|
|
1092
1094
|
]
|
|
1093
1095
|
},
|
|
1096
|
+
{
|
|
1097
|
+
type: "acceptance:derived",
|
|
1098
|
+
description: "Journey-registry CANDIDATE synthesized at solutioning close from structured UX journeys (RP4.2). Non-authoritative; promote via `substrate acceptance ratify` only.",
|
|
1099
|
+
when: "At solutioning close when structured user_journeys exist and no candidate is pending.",
|
|
1100
|
+
fields: [
|
|
1101
|
+
{
|
|
1102
|
+
name: "ts",
|
|
1103
|
+
type: "string",
|
|
1104
|
+
description: "Timestamp."
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
name: "candidate_path",
|
|
1108
|
+
type: "string",
|
|
1109
|
+
description: "Candidate path."
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
name: "journey_count",
|
|
1113
|
+
type: "number",
|
|
1114
|
+
description: "Journeys."
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
name: "critical_count",
|
|
1118
|
+
type: "number",
|
|
1119
|
+
description: "Critical."
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
name: "source_sha256",
|
|
1123
|
+
type: "string",
|
|
1124
|
+
description: "Snapshot hash."
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
name: "undispositioned",
|
|
1128
|
+
type: "string[]",
|
|
1129
|
+
description: "Ids a ratified registry neither covers nor excludes."
|
|
1130
|
+
}
|
|
1131
|
+
]
|
|
1132
|
+
},
|
|
1094
1133
|
{
|
|
1095
1134
|
type: "acceptance:registry-stale",
|
|
1096
|
-
description: "Registry staleness advisory (RP2.1): the
|
|
1097
|
-
when: "At coverage-audit boundaries when
|
|
1135
|
+
description: "Registry staleness advisory (RP2.1): the provenance source no longer hashes to its ratification baseline. Run continues; re-derive + re-ratify.",
|
|
1136
|
+
when: "At coverage-audit boundaries when the registry source diverged.",
|
|
1098
1137
|
fields: [
|
|
1099
1138
|
{
|
|
1100
1139
|
name: "ts",
|
|
@@ -1114,18 +1153,18 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
1114
1153
|
{
|
|
1115
1154
|
name: "derived_from",
|
|
1116
1155
|
type: "string",
|
|
1117
|
-
description: "
|
|
1156
|
+
description: "Source path."
|
|
1118
1157
|
},
|
|
1119
1158
|
{
|
|
1120
1159
|
name: "recorded_sha",
|
|
1121
1160
|
type: "string",
|
|
1122
|
-
description: "Baseline
|
|
1161
|
+
description: "Baseline sha (stale only).",
|
|
1123
1162
|
optional: true
|
|
1124
1163
|
},
|
|
1125
1164
|
{
|
|
1126
1165
|
name: "current_sha",
|
|
1127
1166
|
type: "string",
|
|
1128
|
-
description: "Current
|
|
1167
|
+
description: "Current sha (stale only).",
|
|
1129
1168
|
optional: true
|
|
1130
1169
|
}
|
|
1131
1170
|
]
|
|
@@ -2549,7 +2588,7 @@ async function runHelpAgent() {
|
|
|
2549
2588
|
|
|
2550
2589
|
//#endregion
|
|
2551
2590
|
//#region src/persistence/dolt-server.ts
|
|
2552
|
-
const logger$
|
|
2591
|
+
const logger$26 = createLogger("dolt-server");
|
|
2553
2592
|
/**
|
|
2554
2593
|
* Start a dolt sql-server for the given project, if Dolt is available and no
|
|
2555
2594
|
* server is already running (socket already exists).
|
|
@@ -2566,7 +2605,7 @@ async function startDoltServer(projectRoot) {
|
|
|
2566
2605
|
if (!existsSync(join$1(stateDir, ".dolt"))) return null;
|
|
2567
2606
|
try {
|
|
2568
2607
|
await access$1(socketPath);
|
|
2569
|
-
logger$
|
|
2608
|
+
logger$26.debug("Dolt socket already exists at %s — using existing server", socketPath);
|
|
2570
2609
|
return null;
|
|
2571
2610
|
} catch {}
|
|
2572
2611
|
try {
|
|
@@ -2575,10 +2614,10 @@ async function startDoltServer(projectRoot) {
|
|
|
2575
2614
|
stdio: "pipe"
|
|
2576
2615
|
});
|
|
2577
2616
|
} catch {
|
|
2578
|
-
logger$
|
|
2617
|
+
logger$26.debug("dolt binary not on PATH — cannot start server");
|
|
2579
2618
|
return null;
|
|
2580
2619
|
}
|
|
2581
|
-
logger$
|
|
2620
|
+
logger$26.debug("Starting dolt sql-server at %s", socketPath);
|
|
2582
2621
|
let proc$1;
|
|
2583
2622
|
try {
|
|
2584
2623
|
proc$1 = spawn("dolt", [
|
|
@@ -2599,26 +2638,26 @@ async function startDoltServer(projectRoot) {
|
|
|
2599
2638
|
detached: false
|
|
2600
2639
|
});
|
|
2601
2640
|
} catch (err) {
|
|
2602
|
-
logger$
|
|
2641
|
+
logger$26.debug("Failed to spawn dolt sql-server: %s", err instanceof Error ? err.message : String(err));
|
|
2603
2642
|
return null;
|
|
2604
2643
|
}
|
|
2605
2644
|
let failed = false;
|
|
2606
2645
|
proc$1.on("error", (err) => {
|
|
2607
|
-
logger$
|
|
2646
|
+
logger$26.debug("dolt sql-server error: %s", err.message);
|
|
2608
2647
|
failed = true;
|
|
2609
2648
|
});
|
|
2610
2649
|
proc$1.on("exit", (code) => {
|
|
2611
|
-
if (code !== null && code !== 0) logger$
|
|
2650
|
+
if (code !== null && code !== 0) logger$26.debug("dolt sql-server exited with code %d", code);
|
|
2612
2651
|
});
|
|
2613
2652
|
proc$1.stderr?.on("data", (chunk) => {
|
|
2614
2653
|
const line = chunk.toString().trim();
|
|
2615
|
-
if (line) logger$
|
|
2654
|
+
if (line) logger$26.debug("dolt-server: %s", line);
|
|
2616
2655
|
});
|
|
2617
2656
|
const deadline = Date.now() + 5e3;
|
|
2618
2657
|
while (Date.now() < deadline && !failed) try {
|
|
2619
2658
|
await access$1(socketPath);
|
|
2620
2659
|
const pid = proc$1.pid ?? 0;
|
|
2621
|
-
logger$
|
|
2660
|
+
logger$26.info("Auto-started dolt sql-server (pid=%d, socket=%s)", pid, socketPath);
|
|
2622
2661
|
let stopped = false;
|
|
2623
2662
|
return {
|
|
2624
2663
|
pid,
|
|
@@ -2626,14 +2665,14 @@ async function startDoltServer(projectRoot) {
|
|
|
2626
2665
|
stop: () => {
|
|
2627
2666
|
if (stopped) return;
|
|
2628
2667
|
stopped = true;
|
|
2629
|
-
logger$
|
|
2668
|
+
logger$26.debug("Stopping dolt sql-server (pid=%d)", pid);
|
|
2630
2669
|
proc$1.kill("SIGTERM");
|
|
2631
2670
|
}
|
|
2632
2671
|
};
|
|
2633
2672
|
} catch {
|
|
2634
2673
|
await new Promise((resolve$6) => setTimeout(resolve$6, 100));
|
|
2635
2674
|
}
|
|
2636
|
-
logger$
|
|
2675
|
+
logger$26.debug("dolt sql-server did not start within 5s — killing");
|
|
2637
2676
|
proc$1.kill("SIGTERM");
|
|
2638
2677
|
return null;
|
|
2639
2678
|
}
|
|
@@ -2649,7 +2688,7 @@ function registerServerCleanup(handle) {
|
|
|
2649
2688
|
|
|
2650
2689
|
//#endregion
|
|
2651
2690
|
//#region src/modules/context-compiler/context-compiler-impl.ts
|
|
2652
|
-
const logger$
|
|
2691
|
+
const logger$25 = createLogger("context-compiler");
|
|
2653
2692
|
/**
|
|
2654
2693
|
* Fraction of the original token budget that must remain (after required +
|
|
2655
2694
|
* important sections) before an optional section is included.
|
|
@@ -2710,7 +2749,7 @@ var ContextCompilerImpl = class {
|
|
|
2710
2749
|
}
|
|
2711
2750
|
_applyExclusionFilter(text, sectionName) {
|
|
2712
2751
|
for (const excludedPath of this._excludedPaths) if (text.includes(excludedPath)) {
|
|
2713
|
-
logger$
|
|
2752
|
+
logger$25.warn({
|
|
2714
2753
|
sectionName,
|
|
2715
2754
|
excludedPath
|
|
2716
2755
|
}, "ContextCompiler: section excluded — contains path from exclusion list");
|
|
@@ -2768,7 +2807,7 @@ var ContextCompilerImpl = class {
|
|
|
2768
2807
|
includedParts.push(truncated);
|
|
2769
2808
|
remainingBudget -= truncatedTokens;
|
|
2770
2809
|
anyTruncated = true;
|
|
2771
|
-
logger$
|
|
2810
|
+
logger$25.warn({
|
|
2772
2811
|
section: section.name,
|
|
2773
2812
|
originalTokens: tokens,
|
|
2774
2813
|
budgetTokens: truncatedTokens
|
|
@@ -2782,7 +2821,7 @@ var ContextCompilerImpl = class {
|
|
|
2782
2821
|
});
|
|
2783
2822
|
} else {
|
|
2784
2823
|
anyTruncated = true;
|
|
2785
|
-
logger$
|
|
2824
|
+
logger$25.warn({
|
|
2786
2825
|
section: section.name,
|
|
2787
2826
|
tokens
|
|
2788
2827
|
}, "Context compiler: omitted \"important\" section — no budget remaining");
|
|
@@ -2809,7 +2848,7 @@ var ContextCompilerImpl = class {
|
|
|
2809
2848
|
} else {
|
|
2810
2849
|
if (tokens > 0) {
|
|
2811
2850
|
anyTruncated = true;
|
|
2812
|
-
logger$
|
|
2851
|
+
logger$25.warn({
|
|
2813
2852
|
section: section.name,
|
|
2814
2853
|
tokens,
|
|
2815
2854
|
budgetFractionRemaining: budgetFractionRemaining.toFixed(2)
|
|
@@ -2903,8 +2942,8 @@ var GrammarLoader = class {
|
|
|
2903
2942
|
_extensionMap;
|
|
2904
2943
|
_cache = new Map();
|
|
2905
2944
|
_unavailable = false;
|
|
2906
|
-
constructor(logger$
|
|
2907
|
-
this._logger = logger$
|
|
2945
|
+
constructor(logger$27) {
|
|
2946
|
+
this._logger = logger$27;
|
|
2908
2947
|
this._extensionMap = new Map([
|
|
2909
2948
|
[".ts", "tree-sitter-typescript/typescript"],
|
|
2910
2949
|
[".tsx", "tree-sitter-typescript/tsx"],
|
|
@@ -2990,9 +3029,9 @@ const ERR_REPO_MAP_GIT_FAILED = "ERR_REPO_MAP_GIT_FAILED";
|
|
|
2990
3029
|
var SymbolParser = class {
|
|
2991
3030
|
_grammarLoader;
|
|
2992
3031
|
_logger;
|
|
2993
|
-
constructor(grammarLoader, logger$
|
|
3032
|
+
constructor(grammarLoader, logger$27) {
|
|
2994
3033
|
this._grammarLoader = grammarLoader;
|
|
2995
|
-
this._logger = logger$
|
|
3034
|
+
this._logger = logger$27;
|
|
2996
3035
|
}
|
|
2997
3036
|
async parseFile(filePath) {
|
|
2998
3037
|
const ext$2 = extname$1(filePath);
|
|
@@ -3137,9 +3176,9 @@ async function computeFileHash(filePath) {
|
|
|
3137
3176
|
var DoltSymbolRepository = class {
|
|
3138
3177
|
_client;
|
|
3139
3178
|
_logger;
|
|
3140
|
-
constructor(client, logger$
|
|
3179
|
+
constructor(client, logger$27) {
|
|
3141
3180
|
this._client = client;
|
|
3142
|
-
this._logger = logger$
|
|
3181
|
+
this._logger = logger$27;
|
|
3143
3182
|
}
|
|
3144
3183
|
/**
|
|
3145
3184
|
* Atomically replace all symbols for filePath.
|
|
@@ -3345,11 +3384,11 @@ var RepoMapStorage = class {
|
|
|
3345
3384
|
_metaRepo;
|
|
3346
3385
|
_gitClient;
|
|
3347
3386
|
_logger;
|
|
3348
|
-
constructor(symbolRepo, metaRepo, gitClient, logger$
|
|
3387
|
+
constructor(symbolRepo, metaRepo, gitClient, logger$27) {
|
|
3349
3388
|
this._symbolRepo = symbolRepo;
|
|
3350
3389
|
this._metaRepo = metaRepo;
|
|
3351
3390
|
this._gitClient = gitClient;
|
|
3352
|
-
this._logger = logger$
|
|
3391
|
+
this._logger = logger$27;
|
|
3353
3392
|
}
|
|
3354
3393
|
/**
|
|
3355
3394
|
* Returns true if the file's current content hash differs from the stored hash.
|
|
@@ -3466,8 +3505,8 @@ function runGit(args, cwd) {
|
|
|
3466
3505
|
*/
|
|
3467
3506
|
var GitClient = class {
|
|
3468
3507
|
_logger;
|
|
3469
|
-
constructor(logger$
|
|
3470
|
-
this._logger = logger$
|
|
3508
|
+
constructor(logger$27) {
|
|
3509
|
+
this._logger = logger$27;
|
|
3471
3510
|
}
|
|
3472
3511
|
/**
|
|
3473
3512
|
* Returns the current HEAD commit SHA.
|
|
@@ -4823,9 +4862,9 @@ var RepoMapQueryEngine = class {
|
|
|
4823
4862
|
repo;
|
|
4824
4863
|
logger;
|
|
4825
4864
|
telemetry;
|
|
4826
|
-
constructor(repo, logger$
|
|
4865
|
+
constructor(repo, logger$27, telemetry) {
|
|
4827
4866
|
this.repo = repo;
|
|
4828
|
-
this.logger = logger$
|
|
4867
|
+
this.logger = logger$27;
|
|
4829
4868
|
this.telemetry = telemetry;
|
|
4830
4869
|
}
|
|
4831
4870
|
async query(q) {
|
|
@@ -5045,9 +5084,9 @@ var RepoMapFormatter = class {
|
|
|
5045
5084
|
var RepoMapTelemetry = class {
|
|
5046
5085
|
_telemetry;
|
|
5047
5086
|
_logger;
|
|
5048
|
-
constructor(telemetry, logger$
|
|
5087
|
+
constructor(telemetry, logger$27) {
|
|
5049
5088
|
this._telemetry = telemetry;
|
|
5050
|
-
this._logger = logger$
|
|
5089
|
+
this._logger = logger$27;
|
|
5051
5090
|
}
|
|
5052
5091
|
/**
|
|
5053
5092
|
* Emit a `repo_map.query` span.
|
|
@@ -5072,9 +5111,9 @@ var RepoMapTelemetry = class {
|
|
|
5072
5111
|
var RepoMapModule = class {
|
|
5073
5112
|
_metaRepo;
|
|
5074
5113
|
_logger;
|
|
5075
|
-
constructor(metaRepo, logger$
|
|
5114
|
+
constructor(metaRepo, logger$27) {
|
|
5076
5115
|
this._metaRepo = metaRepo;
|
|
5077
|
-
this._logger = logger$
|
|
5116
|
+
this._logger = logger$27;
|
|
5078
5117
|
}
|
|
5079
5118
|
/**
|
|
5080
5119
|
* Check whether the stored repo-map is stale relative to the current HEAD commit.
|
|
@@ -5118,9 +5157,9 @@ var RepoMapModule = class {
|
|
|
5118
5157
|
var RepoMapInjector = class {
|
|
5119
5158
|
_queryEngine;
|
|
5120
5159
|
_logger;
|
|
5121
|
-
constructor(queryEngine, logger$
|
|
5160
|
+
constructor(queryEngine, logger$27) {
|
|
5122
5161
|
this._queryEngine = queryEngine;
|
|
5123
|
-
this._logger = logger$
|
|
5162
|
+
this._logger = logger$27;
|
|
5124
5163
|
}
|
|
5125
5164
|
/**
|
|
5126
5165
|
* Build repo-map context by extracting file references from the story content,
|
|
@@ -5202,7 +5241,7 @@ const DEFAULT_TIMEOUTS = {
|
|
|
5202
5241
|
|
|
5203
5242
|
//#endregion
|
|
5204
5243
|
//#region src/modules/agent-dispatch/dispatcher-impl.ts
|
|
5205
|
-
const logger$
|
|
5244
|
+
const logger$24 = createLogger("agent-dispatch");
|
|
5206
5245
|
/**
|
|
5207
5246
|
* Create a new Dispatcher instance.
|
|
5208
5247
|
*
|
|
@@ -5346,7 +5385,7 @@ function runBuildVerification(options) {
|
|
|
5346
5385
|
let cmd;
|
|
5347
5386
|
if (verifyCommand === void 0) {
|
|
5348
5387
|
const detection = detectPackageManager(projectRoot);
|
|
5349
|
-
logger$
|
|
5388
|
+
logger$24.info({
|
|
5350
5389
|
packageManager: detection.packageManager,
|
|
5351
5390
|
lockfile: detection.lockfile,
|
|
5352
5391
|
resolvedCommand: detection.command
|
|
@@ -5358,7 +5397,7 @@ function runBuildVerification(options) {
|
|
|
5358
5397
|
const filters = deriveTurboFilters(changedFiles, projectRoot);
|
|
5359
5398
|
if (filters.length > 0) {
|
|
5360
5399
|
cmd = `${cmd} ${filters.join(" ")}`;
|
|
5361
|
-
logger$
|
|
5400
|
+
logger$24.info({
|
|
5362
5401
|
filters,
|
|
5363
5402
|
originalCmd: options.verifyCommand ?? "(auto-detected)"
|
|
5364
5403
|
}, "Build verification: scoped turbo build to affected packages");
|
|
@@ -5401,7 +5440,7 @@ function runBuildVerification(options) {
|
|
|
5401
5440
|
};
|
|
5402
5441
|
const missingScriptPattern = /Missing script[:\s]|No script found|Command "build" not found/i;
|
|
5403
5442
|
if (missingScriptPattern.test(combinedOutput)) {
|
|
5404
|
-
logger$
|
|
5443
|
+
logger$24.warn("Build script not found — skipping pre-flight (greenfield repo)");
|
|
5405
5444
|
return {
|
|
5406
5445
|
status: "skipped",
|
|
5407
5446
|
exitCode,
|
|
@@ -5411,7 +5450,7 @@ function runBuildVerification(options) {
|
|
|
5411
5450
|
}
|
|
5412
5451
|
const pep668Pattern = /externally-managed-environment|This environment is externally managed/i;
|
|
5413
5452
|
if (pep668Pattern.test(combinedOutput)) {
|
|
5414
|
-
logger$
|
|
5453
|
+
logger$24.warn("PEP 668: pip blocked by externally-managed-environment — skipping pre-flight. Create a .venv to resolve.");
|
|
5415
5454
|
return {
|
|
5416
5455
|
status: "skipped",
|
|
5417
5456
|
exitCode,
|
|
@@ -5421,7 +5460,7 @@ function runBuildVerification(options) {
|
|
|
5421
5460
|
}
|
|
5422
5461
|
const pythonEnvNotProvisionedPattern = /\bpython3?:?\s*command not found|command not found:\s*python3?\b|\bpip3?:?\s*command not found|No module named pip\b/i;
|
|
5423
5462
|
if (pythonEnvNotProvisionedPattern.test(combinedOutput)) {
|
|
5424
|
-
logger$
|
|
5463
|
+
logger$24.warn("Python environment not provisioned (interpreter or pip missing) — skipping build pre-flight. Provide a venv (or a project-profile buildCommand that activates one) to verify Python packages.");
|
|
5425
5464
|
return {
|
|
5426
5465
|
status: "skipped",
|
|
5427
5466
|
exitCode,
|
|
@@ -5644,7 +5683,7 @@ function pickRecommendation(distribution, profile, totalIssues, reviewCycles, la
|
|
|
5644
5683
|
|
|
5645
5684
|
//#endregion
|
|
5646
5685
|
//#region src/modules/implementation-orchestrator/project-findings.ts
|
|
5647
|
-
const logger$
|
|
5686
|
+
const logger$23 = createLogger("project-findings");
|
|
5648
5687
|
/** Maximum character length for the findings summary */
|
|
5649
5688
|
const MAX_CHARS = 2e3;
|
|
5650
5689
|
/**
|
|
@@ -5717,7 +5756,7 @@ async function getProjectFindings(db) {
|
|
|
5717
5756
|
if (summary.length > MAX_CHARS) summary = summary.slice(0, MAX_CHARS - 3) + "...";
|
|
5718
5757
|
return summary;
|
|
5719
5758
|
} catch (err) {
|
|
5720
|
-
logger$
|
|
5759
|
+
logger$23.warn({ err }, "Failed to query project findings (graceful fallback)");
|
|
5721
5760
|
return "";
|
|
5722
5761
|
}
|
|
5723
5762
|
}
|
|
@@ -5798,7 +5837,7 @@ function resolveEpicsPathOverride(projectRoot) {
|
|
|
5798
5837
|
|
|
5799
5838
|
//#endregion
|
|
5800
5839
|
//#region src/modules/compiled-workflows/create-story.ts
|
|
5801
|
-
const logger$
|
|
5840
|
+
const logger$22 = createLogger("compiled-workflows:create-story");
|
|
5802
5841
|
/**
|
|
5803
5842
|
* Compute a hex SHA-256 of the normalized source AC section text.
|
|
5804
5843
|
*
|
|
@@ -5833,13 +5872,13 @@ function hashSourceAcSection(section) {
|
|
|
5833
5872
|
*/
|
|
5834
5873
|
async function runCreateStory(deps, params) {
|
|
5835
5874
|
const { epicId, storyKey, pipelineRunId, source_ac_hash, priorDriftFeedback } = params;
|
|
5836
|
-
logger$
|
|
5875
|
+
logger$22.debug({
|
|
5837
5876
|
epicId,
|
|
5838
5877
|
storyKey,
|
|
5839
5878
|
pipelineRunId
|
|
5840
5879
|
}, "Starting create-story workflow");
|
|
5841
5880
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("create-story", deps.tokenCeilings);
|
|
5842
|
-
logger$
|
|
5881
|
+
logger$22.info({
|
|
5843
5882
|
workflow: "create-story",
|
|
5844
5883
|
ceiling: TOKEN_CEILING,
|
|
5845
5884
|
source: tokenCeilingSource
|
|
@@ -5849,7 +5888,7 @@ async function runCreateStory(deps, params) {
|
|
|
5849
5888
|
template = await deps.pack.getPrompt("create-story");
|
|
5850
5889
|
} catch (err) {
|
|
5851
5890
|
const error = err instanceof Error ? err.message : String(err);
|
|
5852
|
-
logger$
|
|
5891
|
+
logger$22.error({ error }, "Failed to retrieve create-story prompt template");
|
|
5853
5892
|
return {
|
|
5854
5893
|
result: "failed",
|
|
5855
5894
|
error: `Failed to retrieve prompt template: ${error}`,
|
|
@@ -5866,7 +5905,7 @@ async function runCreateStory(deps, params) {
|
|
|
5866
5905
|
const storySection = extractStorySection(epicShardContent, storyKey);
|
|
5867
5906
|
if (storySection !== null) {
|
|
5868
5907
|
const computedHash = hashSourceAcSection(storySection);
|
|
5869
|
-
if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$
|
|
5908
|
+
if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$22.debug({
|
|
5870
5909
|
storyKey,
|
|
5871
5910
|
suppliedHash: source_ac_hash,
|
|
5872
5911
|
computedHash
|
|
@@ -5881,7 +5920,7 @@ async function runCreateStory(deps, params) {
|
|
|
5881
5920
|
const storyDef = storyDecisions.find((d) => d.category === "stories" && d.key === storyKey);
|
|
5882
5921
|
if (storyDef) {
|
|
5883
5922
|
storyDefinitionContent = storyDef.value;
|
|
5884
|
-
logger$
|
|
5923
|
+
logger$22.debug({ storyKey }, "Injected story definition from solutioning decisions");
|
|
5885
5924
|
}
|
|
5886
5925
|
} catch {}
|
|
5887
5926
|
const archConstraintsContent = await getArchConstraints$3(deps);
|
|
@@ -5891,11 +5930,11 @@ async function runCreateStory(deps, params) {
|
|
|
5891
5930
|
if (trustedRoot !== void 0) {
|
|
5892
5931
|
const registryLoad = await loadJourneyRegistryFromTrustedTree(trustedRoot);
|
|
5893
5932
|
if (registryLoad.status === "ok" && registryLoad.registry.journeys.length > 0) journeyRegistry = registryLoad.registry;
|
|
5894
|
-
else if (registryLoad.status === "invalid") logger$
|
|
5933
|
+
else if (registryLoad.status === "invalid") logger$22.warn({
|
|
5895
5934
|
storyKey,
|
|
5896
5935
|
issues: registryLoad.issues
|
|
5897
5936
|
}, "A0.2: journey registry present but invalid — stories will be untagged (registry validity is escalated at epic close)");
|
|
5898
|
-
else if (registryLoad.status === "error") logger$
|
|
5937
|
+
else if (registryLoad.status === "error") logger$22.warn({
|
|
5899
5938
|
storyKey,
|
|
5900
5939
|
error: registryLoad.message
|
|
5901
5940
|
}, "A0.2: journey registry read failed — stories will be untagged");
|
|
@@ -5956,7 +5995,7 @@ async function runCreateStory(deps, params) {
|
|
|
5956
5995
|
priority: "optional"
|
|
5957
5996
|
}]
|
|
5958
5997
|
], TOKEN_CEILING);
|
|
5959
|
-
logger$
|
|
5998
|
+
logger$22.debug({
|
|
5960
5999
|
tokenCount,
|
|
5961
6000
|
truncated,
|
|
5962
6001
|
tokenCeiling: TOKEN_CEILING
|
|
@@ -5976,7 +6015,7 @@ async function runCreateStory(deps, params) {
|
|
|
5976
6015
|
dispatchResult = await handle.result;
|
|
5977
6016
|
} catch (err) {
|
|
5978
6017
|
const error = err instanceof Error ? err.message : String(err);
|
|
5979
|
-
logger$
|
|
6018
|
+
logger$22.error({
|
|
5980
6019
|
epicId,
|
|
5981
6020
|
storyKey,
|
|
5982
6021
|
error
|
|
@@ -5997,7 +6036,7 @@ async function runCreateStory(deps, params) {
|
|
|
5997
6036
|
if (dispatchResult.status === "failed") {
|
|
5998
6037
|
const errorMsg = dispatchResult.parseError ?? `Dispatch failed with exit code ${dispatchResult.exitCode}`;
|
|
5999
6038
|
const stderrDetail = dispatchResult.output ? ` Output: ${dispatchResult.output}` : "";
|
|
6000
|
-
logger$
|
|
6039
|
+
logger$22.warn({
|
|
6001
6040
|
epicId,
|
|
6002
6041
|
storyKey,
|
|
6003
6042
|
exitCode: dispatchResult.exitCode,
|
|
@@ -6010,7 +6049,7 @@ async function runCreateStory(deps, params) {
|
|
|
6010
6049
|
};
|
|
6011
6050
|
}
|
|
6012
6051
|
if (dispatchResult.status === "timeout") {
|
|
6013
|
-
logger$
|
|
6052
|
+
logger$22.warn({
|
|
6014
6053
|
epicId,
|
|
6015
6054
|
storyKey
|
|
6016
6055
|
}, "Create-story dispatch timed out");
|
|
@@ -6025,7 +6064,7 @@ async function runCreateStory(deps, params) {
|
|
|
6025
6064
|
const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
|
|
6026
6065
|
const authSignature = detectClaudeAuthFailure(dispatchResult.output);
|
|
6027
6066
|
if (authSignature !== null) {
|
|
6028
|
-
logger$
|
|
6067
|
+
logger$22.error({
|
|
6029
6068
|
epicId,
|
|
6030
6069
|
storyKey,
|
|
6031
6070
|
authSignature,
|
|
@@ -6038,7 +6077,7 @@ async function runCreateStory(deps, params) {
|
|
|
6038
6077
|
tokenUsage
|
|
6039
6078
|
};
|
|
6040
6079
|
}
|
|
6041
|
-
logger$
|
|
6080
|
+
logger$22.warn({
|
|
6042
6081
|
epicId,
|
|
6043
6082
|
storyKey,
|
|
6044
6083
|
details,
|
|
@@ -6054,7 +6093,7 @@ async function runCreateStory(deps, params) {
|
|
|
6054
6093
|
const parseResult = CreateStoryResultSchema.safeParse(dispatchResult.parsed);
|
|
6055
6094
|
if (!parseResult.success) {
|
|
6056
6095
|
const details = parseResult.error.message;
|
|
6057
|
-
logger$
|
|
6096
|
+
logger$22.warn({
|
|
6058
6097
|
epicId,
|
|
6059
6098
|
storyKey,
|
|
6060
6099
|
details
|
|
@@ -6081,7 +6120,7 @@ async function runCreateStory(deps, params) {
|
|
|
6081
6120
|
const unknown = taggedJourneys.filter((id) => !knownIds.has(id));
|
|
6082
6121
|
if (unknown.length > 0) {
|
|
6083
6122
|
const details = `story artifact declares unknown journey id(s): ${unknown.join(", ")} — registry v${String(journeyRegistry.version)} defines: ${[...knownIds].join(", ")}`;
|
|
6084
|
-
logger$
|
|
6123
|
+
logger$22.warn({
|
|
6085
6124
|
epicId,
|
|
6086
6125
|
storyKey,
|
|
6087
6126
|
unknown
|
|
@@ -6094,7 +6133,7 @@ async function runCreateStory(deps, params) {
|
|
|
6094
6133
|
};
|
|
6095
6134
|
}
|
|
6096
6135
|
if (taggedJourneys.length > 0) {
|
|
6097
|
-
logger$
|
|
6136
|
+
logger$22.info({
|
|
6098
6137
|
epicId,
|
|
6099
6138
|
storyKey,
|
|
6100
6139
|
journeys: taggedJourneys
|
|
@@ -6103,7 +6142,7 @@ async function runCreateStory(deps, params) {
|
|
|
6103
6142
|
}
|
|
6104
6143
|
}
|
|
6105
6144
|
}
|
|
6106
|
-
logger$
|
|
6145
|
+
logger$22.info({
|
|
6107
6146
|
epicId,
|
|
6108
6147
|
storyKey,
|
|
6109
6148
|
storyFile: parsed.story_file,
|
|
@@ -6133,7 +6172,7 @@ async function getImplementationDecisions(deps, pipelineRunId) {
|
|
|
6133
6172
|
}
|
|
6134
6173
|
return await getDecisionsByPhase(deps.db, "implementation");
|
|
6135
6174
|
} catch (err) {
|
|
6136
|
-
logger$
|
|
6175
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
|
|
6137
6176
|
return [];
|
|
6138
6177
|
}
|
|
6139
6178
|
}
|
|
@@ -6431,7 +6470,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6431
6470
|
if (storyKey) {
|
|
6432
6471
|
const perStoryShard = decisions.find((d) => d.category === "epic-shard" && d.key === storyKey);
|
|
6433
6472
|
if (perStoryShard?.value) {
|
|
6434
|
-
logger$
|
|
6473
|
+
logger$22.debug({
|
|
6435
6474
|
epicId,
|
|
6436
6475
|
storyKey
|
|
6437
6476
|
}, "Found per-story epic shard (direct lookup)");
|
|
@@ -6443,13 +6482,13 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6443
6482
|
if (shardContent && storyKey) {
|
|
6444
6483
|
const storySection = extractStorySection(shardContent, storyKey);
|
|
6445
6484
|
if (storySection) {
|
|
6446
|
-
logger$
|
|
6485
|
+
logger$22.debug({
|
|
6447
6486
|
epicId,
|
|
6448
6487
|
storyKey
|
|
6449
6488
|
}, "Extracted per-story section from epic shard (pre-37-0 fallback)");
|
|
6450
6489
|
return storySection;
|
|
6451
6490
|
}
|
|
6452
|
-
logger$
|
|
6491
|
+
logger$22.info({
|
|
6453
6492
|
epicId,
|
|
6454
6493
|
storyKey
|
|
6455
6494
|
}, "Story section absent in decisions-store shard — attempting file-based fallback before returning stale shard");
|
|
@@ -6457,11 +6496,11 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6457
6496
|
if (projectRoot) {
|
|
6458
6497
|
const fallback = readEpicShardFromFile(projectRoot, epicId, storyKey);
|
|
6459
6498
|
if (fallback) {
|
|
6460
|
-
logger$
|
|
6499
|
+
logger$22.info({ epicId }, "Using file-based fallback for epic shard");
|
|
6461
6500
|
if (storyKey) {
|
|
6462
6501
|
const storySection = extractStorySection(fallback, storyKey);
|
|
6463
6502
|
if (storySection) {
|
|
6464
|
-
logger$
|
|
6503
|
+
logger$22.debug({
|
|
6465
6504
|
epicId,
|
|
6466
6505
|
storyKey
|
|
6467
6506
|
}, "Extracted per-story section from file-based epic shard");
|
|
@@ -6474,7 +6513,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6474
6513
|
if (shardContent) return shardContent;
|
|
6475
6514
|
return "";
|
|
6476
6515
|
} catch (err) {
|
|
6477
|
-
logger$
|
|
6516
|
+
logger$22.warn({
|
|
6478
6517
|
epicId,
|
|
6479
6518
|
error: err instanceof Error ? err.message : String(err)
|
|
6480
6519
|
}, "Failed to retrieve epic shard");
|
|
@@ -6491,7 +6530,7 @@ function getPrevDevNotes(decisions, epicId) {
|
|
|
6491
6530
|
if (devNotes.length === 0) return "";
|
|
6492
6531
|
return devNotes[devNotes.length - 1].value;
|
|
6493
6532
|
} catch (err) {
|
|
6494
|
-
logger$
|
|
6533
|
+
logger$22.warn({
|
|
6495
6534
|
epicId,
|
|
6496
6535
|
error: err instanceof Error ? err.message : String(err)
|
|
6497
6536
|
}, "Failed to retrieve prev dev notes");
|
|
@@ -6524,7 +6563,7 @@ async function getArchConstraints$3(deps) {
|
|
|
6524
6563
|
const truncatedBody = body.length > 300 ? body.slice(0, 297) + "..." : body;
|
|
6525
6564
|
return `${header}\n${truncatedBody}`;
|
|
6526
6565
|
}).join("\n\n");
|
|
6527
|
-
logger$
|
|
6566
|
+
logger$22.info({
|
|
6528
6567
|
fullLength: full.length,
|
|
6529
6568
|
summarizedLength: summarized.length,
|
|
6530
6569
|
decisions: constraints.length
|
|
@@ -6535,13 +6574,13 @@ async function getArchConstraints$3(deps) {
|
|
|
6535
6574
|
if (archRoot) {
|
|
6536
6575
|
const fallback = readArchConstraintsFromFile(archRoot);
|
|
6537
6576
|
if (fallback) {
|
|
6538
|
-
logger$
|
|
6577
|
+
logger$22.info("Using file-based fallback for architecture constraints (decisions table empty)");
|
|
6539
6578
|
return fallback.length > ARCH_CONSTRAINT_MAX_CHARS ? fallback.slice(0, ARCH_CONSTRAINT_MAX_CHARS) + "\n\n[truncated for token budget]" : fallback;
|
|
6540
6579
|
}
|
|
6541
6580
|
}
|
|
6542
6581
|
return "";
|
|
6543
6582
|
} catch (err) {
|
|
6544
|
-
logger$
|
|
6583
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
6545
6584
|
return "";
|
|
6546
6585
|
}
|
|
6547
6586
|
}
|
|
@@ -6605,7 +6644,7 @@ function readEpicShardFromFile(projectRoot, epicId, storyKey) {
|
|
|
6605
6644
|
}
|
|
6606
6645
|
return "";
|
|
6607
6646
|
} catch (err) {
|
|
6608
|
-
logger$
|
|
6647
|
+
logger$22.warn({
|
|
6609
6648
|
epicId,
|
|
6610
6649
|
error: err instanceof Error ? err.message : String(err)
|
|
6611
6650
|
}, "File-based epic shard fallback failed");
|
|
@@ -6628,7 +6667,7 @@ function readArchConstraintsFromFile(projectRoot) {
|
|
|
6628
6667
|
const content = readFileSync(archPath, "utf-8");
|
|
6629
6668
|
return content.slice(0, 1500);
|
|
6630
6669
|
} catch (err) {
|
|
6631
|
-
logger$
|
|
6670
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
|
|
6632
6671
|
return "";
|
|
6633
6672
|
}
|
|
6634
6673
|
}
|
|
@@ -6641,7 +6680,7 @@ async function getStoryTemplate(deps) {
|
|
|
6641
6680
|
try {
|
|
6642
6681
|
return await deps.pack.getTemplate("story");
|
|
6643
6682
|
} catch (err) {
|
|
6644
|
-
logger$
|
|
6683
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
|
|
6645
6684
|
return "";
|
|
6646
6685
|
}
|
|
6647
6686
|
}
|
|
@@ -6678,7 +6717,7 @@ async function isValidStoryFile(filePath) {
|
|
|
6678
6717
|
|
|
6679
6718
|
//#endregion
|
|
6680
6719
|
//#region src/modules/compiled-workflows/git-helpers.ts
|
|
6681
|
-
const logger$
|
|
6720
|
+
const logger$21 = createLogger("compiled-workflows:git-helpers");
|
|
6682
6721
|
/**
|
|
6683
6722
|
* Commit the agent's working-tree output for a dev-story dispatch.
|
|
6684
6723
|
*
|
|
@@ -6722,7 +6761,7 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
6722
6761
|
const abs = isAbsolute(p) ? p : resolve$1(workingDir, p);
|
|
6723
6762
|
const rel = relative(workingDir, abs);
|
|
6724
6763
|
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
6725
|
-
logger$
|
|
6764
|
+
logger$21.debug({
|
|
6726
6765
|
path: p,
|
|
6727
6766
|
abs,
|
|
6728
6767
|
workingDir
|
|
@@ -6731,7 +6770,7 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
6731
6770
|
}
|
|
6732
6771
|
const segments = rel.replace(/\\/g, "/").split("/");
|
|
6733
6772
|
if (segments.some((s$1) => COMMIT_DENY_SEGMENTS.includes(s$1))) {
|
|
6734
|
-
logger$
|
|
6773
|
+
logger$21.warn({
|
|
6735
6774
|
path: rel,
|
|
6736
6775
|
storyKey
|
|
6737
6776
|
}, "commitDevStoryOutput: denylisted dependency/artifact path excluded from substrate commit");
|
|
@@ -6816,12 +6855,12 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
6816
6855
|
timeout: 5e3
|
|
6817
6856
|
}).trim();
|
|
6818
6857
|
} catch (err) {
|
|
6819
|
-
logger$
|
|
6858
|
+
logger$21.warn({
|
|
6820
6859
|
storyKey,
|
|
6821
6860
|
err
|
|
6822
6861
|
}, "commitDevStoryOutput: commit succeeded but rev-parse HEAD failed");
|
|
6823
6862
|
}
|
|
6824
|
-
logger$
|
|
6863
|
+
logger$21.info({
|
|
6825
6864
|
storyKey,
|
|
6826
6865
|
sha,
|
|
6827
6866
|
fileCount: insideWorktree.length
|
|
@@ -6925,7 +6964,7 @@ async function checkpointStoryWorktree(storyKey, reason, workingDir) {
|
|
|
6925
6964
|
timeout: 5e3
|
|
6926
6965
|
}).trim();
|
|
6927
6966
|
} catch {}
|
|
6928
|
-
logger$
|
|
6967
|
+
logger$21.info({
|
|
6929
6968
|
storyKey,
|
|
6930
6969
|
sha,
|
|
6931
6970
|
reason: cleanReason
|
|
@@ -6971,7 +7010,7 @@ function hasCommits(cwd) {
|
|
|
6971
7010
|
*/
|
|
6972
7011
|
async function getGitDiffSummary(workingDirectory = process.cwd()) {
|
|
6973
7012
|
if (!hasCommits(workingDirectory)) {
|
|
6974
|
-
logger$
|
|
7013
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff");
|
|
6975
7014
|
return "";
|
|
6976
7015
|
}
|
|
6977
7016
|
return runGitCommand(["diff", "HEAD"], workingDirectory, "git-diff-summary");
|
|
@@ -6988,7 +7027,7 @@ async function getGitDiffSummary(workingDirectory = process.cwd()) {
|
|
|
6988
7027
|
*/
|
|
6989
7028
|
async function getGitDiffStatSummary(workingDirectory = process.cwd()) {
|
|
6990
7029
|
if (!hasCommits(workingDirectory)) {
|
|
6991
|
-
logger$
|
|
7030
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat");
|
|
6992
7031
|
return "";
|
|
6993
7032
|
}
|
|
6994
7033
|
return runGitCommand([
|
|
@@ -7037,7 +7076,7 @@ async function getGitDiffStatBetweenCommits(baseCommit, endCommit = "HEAD", work
|
|
|
7037
7076
|
async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
|
|
7038
7077
|
if (files.length === 0) return "";
|
|
7039
7078
|
if (!hasCommits(workingDirectory)) {
|
|
7040
|
-
logger$
|
|
7079
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff for files");
|
|
7041
7080
|
return "";
|
|
7042
7081
|
}
|
|
7043
7082
|
await stageIntentToAdd(files, workingDirectory);
|
|
@@ -7064,7 +7103,7 @@ async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
|
|
|
7064
7103
|
async function getGitDiffStatForFiles(files, workingDirectory = process.cwd()) {
|
|
7065
7104
|
if (files.length === 0) return "";
|
|
7066
7105
|
if (!hasCommits(workingDirectory)) {
|
|
7067
|
-
logger$
|
|
7106
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat for files");
|
|
7068
7107
|
return "";
|
|
7069
7108
|
}
|
|
7070
7109
|
return runGitCommand([
|
|
@@ -7113,7 +7152,7 @@ async function stageIntentToAdd(files, workingDirectory) {
|
|
|
7113
7152
|
if (files.length === 0) return;
|
|
7114
7153
|
const existing = files.filter((f$1) => {
|
|
7115
7154
|
const exists = existsSync(f$1);
|
|
7116
|
-
if (!exists) logger$
|
|
7155
|
+
if (!exists) logger$21.debug({ file: f$1 }, "Skipping nonexistent file in stageIntentToAdd");
|
|
7117
7156
|
return exists;
|
|
7118
7157
|
});
|
|
7119
7158
|
if (existing.length === 0) return;
|
|
@@ -7142,7 +7181,7 @@ async function stageIntentToAdd(files, workingDirectory) {
|
|
|
7142
7181
|
async function recoverStoryFileFromBranch(storyFilePath, workingDirectory) {
|
|
7143
7182
|
const rel = relative(workingDirectory, resolve$1(workingDirectory, storyFilePath));
|
|
7144
7183
|
if (rel.startsWith("..")) {
|
|
7145
|
-
logger$
|
|
7184
|
+
logger$21.warn({
|
|
7146
7185
|
storyFilePath,
|
|
7147
7186
|
workingDirectory
|
|
7148
7187
|
}, "recoverStoryFileFromBranch: path outside the worktree — not recoverable");
|
|
@@ -7154,9 +7193,9 @@ async function recoverStoryFileFromBranch(storyFilePath, workingDirectory) {
|
|
|
7154
7193
|
const abs = resolve$1(workingDirectory, rel);
|
|
7155
7194
|
await mkdir$1(dirname$1(abs), { recursive: true });
|
|
7156
7195
|
await writeFile$1(abs, content, "utf-8");
|
|
7157
|
-
logger$
|
|
7196
|
+
logger$21.warn({ storyFilePath: abs }, "H5.5: story file restored to the working tree from branch HEAD");
|
|
7158
7197
|
} catch (writeErr) {
|
|
7159
|
-
logger$
|
|
7198
|
+
logger$21.warn({
|
|
7160
7199
|
storyFilePath,
|
|
7161
7200
|
err: writeErr
|
|
7162
7201
|
}, "H5.5: recovered story content but could not restore the file (continuing with in-memory content)");
|
|
@@ -7182,7 +7221,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7182
7221
|
stderr += chunk.toString("utf-8");
|
|
7183
7222
|
});
|
|
7184
7223
|
proc$1.on("error", (err) => {
|
|
7185
|
-
logger$
|
|
7224
|
+
logger$21.warn({
|
|
7186
7225
|
label: logLabel,
|
|
7187
7226
|
cwd,
|
|
7188
7227
|
error: err.message
|
|
@@ -7191,7 +7230,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7191
7230
|
});
|
|
7192
7231
|
proc$1.on("close", (code) => {
|
|
7193
7232
|
if (code !== 0) {
|
|
7194
|
-
logger$
|
|
7233
|
+
logger$21.warn({
|
|
7195
7234
|
label: logLabel,
|
|
7196
7235
|
cwd,
|
|
7197
7236
|
code,
|
|
@@ -7207,7 +7246,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7207
7246
|
|
|
7208
7247
|
//#endregion
|
|
7209
7248
|
//#region src/modules/compiled-workflows/story-complexity.ts
|
|
7210
|
-
const logger$
|
|
7249
|
+
const logger$20 = createLogger("compiled-workflows:story-complexity");
|
|
7211
7250
|
/**
|
|
7212
7251
|
* Compute a complexity score from story markdown content.
|
|
7213
7252
|
*
|
|
@@ -7259,7 +7298,7 @@ function resolveFixStoryMaxTurns(complexityScore) {
|
|
|
7259
7298
|
* @param resolvedMaxTurns - Turn limit resolved for this dispatch
|
|
7260
7299
|
*/
|
|
7261
7300
|
function logComplexityResult(storyKey, complexity, resolvedMaxTurns) {
|
|
7262
|
-
logger$
|
|
7301
|
+
logger$20.info({
|
|
7263
7302
|
storyKey,
|
|
7264
7303
|
taskCount: complexity.taskCount,
|
|
7265
7304
|
subtaskCount: complexity.subtaskCount,
|
|
@@ -7532,7 +7571,7 @@ function resolveInstallCommand(projectRoot) {
|
|
|
7532
7571
|
|
|
7533
7572
|
//#endregion
|
|
7534
7573
|
//#region src/modules/compiled-workflows/dev-story.ts
|
|
7535
|
-
const logger$
|
|
7574
|
+
const logger$19 = createLogger("compiled-workflows:dev-story");
|
|
7536
7575
|
/** Default timeout for dev-story dispatches in milliseconds (30 min) */
|
|
7537
7576
|
const DEFAULT_TIMEOUT_MS$2 = 18e5;
|
|
7538
7577
|
/**
|
|
@@ -7544,12 +7583,12 @@ const DEFAULT_TIMEOUT_MS$2 = 18e5;
|
|
|
7544
7583
|
*/
|
|
7545
7584
|
async function runDevStory(deps, params) {
|
|
7546
7585
|
const { storyKey, storyFilePath, taskScope, priorFiles, findingsPrompt: handlerFindingsPrompt } = params;
|
|
7547
|
-
logger$
|
|
7586
|
+
logger$19.info({
|
|
7548
7587
|
storyKey,
|
|
7549
7588
|
storyFilePath
|
|
7550
7589
|
}, "Starting compiled dev-story workflow");
|
|
7551
7590
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("dev-story", deps.tokenCeilings);
|
|
7552
|
-
logger$
|
|
7591
|
+
logger$19.info({
|
|
7553
7592
|
workflow: "dev-story",
|
|
7554
7593
|
ceiling: TOKEN_CEILING,
|
|
7555
7594
|
source: tokenCeilingSource
|
|
@@ -7592,10 +7631,10 @@ async function runDevStory(deps, params) {
|
|
|
7592
7631
|
let template;
|
|
7593
7632
|
try {
|
|
7594
7633
|
template = await deps.pack.getPrompt("dev-story");
|
|
7595
|
-
logger$
|
|
7634
|
+
logger$19.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
|
|
7596
7635
|
} catch (err) {
|
|
7597
7636
|
const error = err instanceof Error ? err.message : String(err);
|
|
7598
|
-
logger$
|
|
7637
|
+
logger$19.error({
|
|
7599
7638
|
storyKey,
|
|
7600
7639
|
error
|
|
7601
7640
|
}, "Failed to retrieve dev-story prompt template");
|
|
@@ -7607,20 +7646,20 @@ async function runDevStory(deps, params) {
|
|
|
7607
7646
|
} catch (err) {
|
|
7608
7647
|
const recovered = await recoverStoryFileFromBranch(storyFilePath, deps.projectRoot ?? process.cwd());
|
|
7609
7648
|
if (recovered !== void 0) {
|
|
7610
|
-
logger$
|
|
7649
|
+
logger$19.warn({
|
|
7611
7650
|
storyKey,
|
|
7612
7651
|
storyFilePath
|
|
7613
7652
|
}, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
7614
7653
|
storyContent = recovered;
|
|
7615
7654
|
} else if (err.code === "ENOENT") {
|
|
7616
|
-
logger$
|
|
7655
|
+
logger$19.error({
|
|
7617
7656
|
storyKey,
|
|
7618
7657
|
storyFilePath
|
|
7619
7658
|
}, "Story file not found");
|
|
7620
7659
|
return makeFailureResult("story_file_not_found");
|
|
7621
7660
|
} else {
|
|
7622
7661
|
const error = err instanceof Error ? err.message : String(err);
|
|
7623
|
-
logger$
|
|
7662
|
+
logger$19.error({
|
|
7624
7663
|
storyKey,
|
|
7625
7664
|
storyFilePath,
|
|
7626
7665
|
error
|
|
@@ -7629,7 +7668,7 @@ async function runDevStory(deps, params) {
|
|
|
7629
7668
|
}
|
|
7630
7669
|
}
|
|
7631
7670
|
if (storyContent.trim().length === 0) {
|
|
7632
|
-
logger$
|
|
7671
|
+
logger$19.error({
|
|
7633
7672
|
storyKey,
|
|
7634
7673
|
storyFilePath
|
|
7635
7674
|
}, "Story file is empty");
|
|
@@ -7637,7 +7676,7 @@ async function runDevStory(deps, params) {
|
|
|
7637
7676
|
}
|
|
7638
7677
|
const staleStatus = detectDeprecatedStatusField(storyContent);
|
|
7639
7678
|
if (staleStatus !== null) {
|
|
7640
|
-
logger$
|
|
7679
|
+
logger$19.warn({
|
|
7641
7680
|
storyFilePath,
|
|
7642
7681
|
staleStatus
|
|
7643
7682
|
}, "Story spec contains deprecated Status field — stripped before dispatch (status is managed by Dolt work graph)");
|
|
@@ -7652,17 +7691,17 @@ async function runDevStory(deps, params) {
|
|
|
7652
7691
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
7653
7692
|
if (testPatternDecisions.length > 0) {
|
|
7654
7693
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
7655
|
-
logger$
|
|
7694
|
+
logger$19.debug({
|
|
7656
7695
|
storyKey,
|
|
7657
7696
|
count: testPatternDecisions.length
|
|
7658
7697
|
}, "Loaded test patterns from decision store");
|
|
7659
7698
|
} else {
|
|
7660
7699
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
7661
|
-
logger$
|
|
7700
|
+
logger$19.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
7662
7701
|
}
|
|
7663
7702
|
} catch (err) {
|
|
7664
7703
|
const error = err instanceof Error ? err.message : String(err);
|
|
7665
|
-
logger$
|
|
7704
|
+
logger$19.warn({
|
|
7666
7705
|
storyKey,
|
|
7667
7706
|
error
|
|
7668
7707
|
}, "Failed to load test patterns — using defaults");
|
|
@@ -7676,7 +7715,7 @@ async function runDevStory(deps, params) {
|
|
|
7676
7715
|
if (deps.repoMapInjector !== void 0) {
|
|
7677
7716
|
const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
|
|
7678
7717
|
repoContextContent = injection.text;
|
|
7679
|
-
logger$
|
|
7718
|
+
logger$19.info({
|
|
7680
7719
|
storyKey,
|
|
7681
7720
|
repoMapTokens: Math.ceil(injection.text.length / 4),
|
|
7682
7721
|
symbolCount: injection.symbolCount,
|
|
@@ -7686,7 +7725,7 @@ async function runDevStory(deps, params) {
|
|
|
7686
7725
|
let priorFindingsContent = "";
|
|
7687
7726
|
if (handlerFindingsPrompt !== void 0 && handlerFindingsPrompt.length > 0) {
|
|
7688
7727
|
priorFindingsContent = handlerFindingsPrompt;
|
|
7689
|
-
logger$
|
|
7728
|
+
logger$19.debug({
|
|
7690
7729
|
storyKey,
|
|
7691
7730
|
findingsLen: handlerFindingsPrompt.length
|
|
7692
7731
|
}, "Using pre-computed findings from handler (Story 53-8 AC2)");
|
|
@@ -7698,7 +7737,7 @@ async function runDevStory(deps, params) {
|
|
|
7698
7737
|
});
|
|
7699
7738
|
if (findings.length > 0) {
|
|
7700
7739
|
priorFindingsContent = findings;
|
|
7701
|
-
logger$
|
|
7740
|
+
logger$19.debug({
|
|
7702
7741
|
storyKey,
|
|
7703
7742
|
findingsLen: findings.length
|
|
7704
7743
|
}, "Injecting relevance-scored findings into dev-story prompt");
|
|
@@ -7718,7 +7757,7 @@ async function runDevStory(deps, params) {
|
|
|
7718
7757
|
if (plan.test_categories && plan.test_categories.length > 0) parts.push(`\n### Categories: ${plan.test_categories.join(", ")}`);
|
|
7719
7758
|
if (plan.coverage_notes) parts.push(`\n### Coverage Notes\n${plan.coverage_notes}`);
|
|
7720
7759
|
testPlanContent = parts.join("\n");
|
|
7721
|
-
logger$
|
|
7760
|
+
logger$19.debug({ storyKey }, "Injecting test plan into dev-story prompt");
|
|
7722
7761
|
}
|
|
7723
7762
|
} catch {}
|
|
7724
7763
|
const sections = [
|
|
@@ -7779,7 +7818,7 @@ async function runDevStory(deps, params) {
|
|
|
7779
7818
|
}
|
|
7780
7819
|
];
|
|
7781
7820
|
const { prompt, tokenCount, truncated } = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
7782
|
-
logger$
|
|
7821
|
+
logger$19.info({
|
|
7783
7822
|
storyKey,
|
|
7784
7823
|
tokenCount,
|
|
7785
7824
|
ceiling: TOKEN_CEILING,
|
|
@@ -7803,7 +7842,7 @@ async function runDevStory(deps, params) {
|
|
|
7803
7842
|
dispatchResult = await handle.result;
|
|
7804
7843
|
} catch (err) {
|
|
7805
7844
|
const error = err instanceof Error ? err.message : String(err);
|
|
7806
|
-
logger$
|
|
7845
|
+
logger$19.error({
|
|
7807
7846
|
storyKey,
|
|
7808
7847
|
error
|
|
7809
7848
|
}, "Dispatch threw an unexpected error");
|
|
@@ -7814,11 +7853,11 @@ async function runDevStory(deps, params) {
|
|
|
7814
7853
|
output: dispatchResult.tokenEstimate.output
|
|
7815
7854
|
};
|
|
7816
7855
|
if (dispatchResult.status === "timeout") {
|
|
7817
|
-
logger$
|
|
7856
|
+
logger$19.error({
|
|
7818
7857
|
storyKey,
|
|
7819
7858
|
durationMs: dispatchResult.durationMs
|
|
7820
7859
|
}, "Dev-story dispatch timed out");
|
|
7821
|
-
if (dispatchResult.output.length > 0) logger$
|
|
7860
|
+
if (dispatchResult.output.length > 0) logger$19.info({
|
|
7822
7861
|
storyKey,
|
|
7823
7862
|
partialOutput: dispatchResult.output.slice(0, 500)
|
|
7824
7863
|
}, "Partial output before timeout");
|
|
@@ -7828,12 +7867,12 @@ async function runDevStory(deps, params) {
|
|
|
7828
7867
|
};
|
|
7829
7868
|
}
|
|
7830
7869
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
7831
|
-
logger$
|
|
7870
|
+
logger$19.error({
|
|
7832
7871
|
storyKey,
|
|
7833
7872
|
exitCode: dispatchResult.exitCode,
|
|
7834
7873
|
status: dispatchResult.status
|
|
7835
7874
|
}, "Dev-story dispatch failed");
|
|
7836
|
-
if (dispatchResult.output.length > 0) logger$
|
|
7875
|
+
if (dispatchResult.output.length > 0) logger$19.info({
|
|
7837
7876
|
storyKey,
|
|
7838
7877
|
partialOutput: dispatchResult.output.slice(0, 500)
|
|
7839
7878
|
}, "Partial output from failed dispatch");
|
|
@@ -7845,7 +7884,7 @@ async function runDevStory(deps, params) {
|
|
|
7845
7884
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
7846
7885
|
const details = dispatchResult.parseError ?? "parsed result was null";
|
|
7847
7886
|
const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
|
|
7848
|
-
logger$
|
|
7887
|
+
logger$19.error({
|
|
7849
7888
|
storyKey,
|
|
7850
7889
|
parseError: details,
|
|
7851
7890
|
rawOutputSnippet: rawSnippet
|
|
@@ -7853,12 +7892,12 @@ async function runDevStory(deps, params) {
|
|
|
7853
7892
|
let filesModified = [];
|
|
7854
7893
|
try {
|
|
7855
7894
|
filesModified = await getGitChangedFiles(deps.projectRoot ?? process.cwd());
|
|
7856
|
-
if (filesModified.length > 0) logger$
|
|
7895
|
+
if (filesModified.length > 0) logger$19.info({
|
|
7857
7896
|
storyKey,
|
|
7858
7897
|
fileCount: filesModified.length
|
|
7859
7898
|
}, "Recovered files_modified from git status (YAML fallback)");
|
|
7860
7899
|
} catch (err) {
|
|
7861
|
-
logger$
|
|
7900
|
+
logger$19.warn({
|
|
7862
7901
|
storyKey,
|
|
7863
7902
|
error: err instanceof Error ? err.message : String(err)
|
|
7864
7903
|
}, "Failed to recover files_modified from git");
|
|
@@ -7875,7 +7914,7 @@ async function runDevStory(deps, params) {
|
|
|
7875
7914
|
};
|
|
7876
7915
|
}
|
|
7877
7916
|
const parsed = dispatchResult.parsed;
|
|
7878
|
-
logger$
|
|
7917
|
+
logger$19.info({
|
|
7879
7918
|
storyKey,
|
|
7880
7919
|
result: parsed.result,
|
|
7881
7920
|
acMet: parsed.ac_met.length
|
|
@@ -8289,7 +8328,7 @@ function resolvesIntoExpected(modifiedFilePath, relativePath, expectedFiles) {
|
|
|
8289
8328
|
|
|
8290
8329
|
//#endregion
|
|
8291
8330
|
//#region src/modules/compiled-workflows/code-review.ts
|
|
8292
|
-
const logger$
|
|
8331
|
+
const logger$18 = createLogger("compiled-workflows:code-review");
|
|
8293
8332
|
/**
|
|
8294
8333
|
* Default fallback result when dispatch fails or times out.
|
|
8295
8334
|
* Uses NEEDS_MINOR_FIXES (not NEEDS_MAJOR_REWORK) so a parse/schema failure
|
|
@@ -8364,14 +8403,14 @@ async function countTestMetrics(filesModified, cwd) {
|
|
|
8364
8403
|
async function runCodeReview(deps, params) {
|
|
8365
8404
|
const { storyKey, storyFilePath, workingDirectory, pipelineRunId, filesModified, previousIssues, buildPassed, baselineCommit } = params;
|
|
8366
8405
|
const cwd = workingDirectory ?? process.cwd();
|
|
8367
|
-
logger$
|
|
8406
|
+
logger$18.debug({
|
|
8368
8407
|
storyKey,
|
|
8369
8408
|
storyFilePath,
|
|
8370
8409
|
cwd,
|
|
8371
8410
|
pipelineRunId
|
|
8372
8411
|
}, "Starting code-review workflow");
|
|
8373
8412
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("code-review", deps.tokenCeilings);
|
|
8374
|
-
logger$
|
|
8413
|
+
logger$18.info({
|
|
8375
8414
|
workflow: "code-review",
|
|
8376
8415
|
ceiling: TOKEN_CEILING,
|
|
8377
8416
|
source: tokenCeilingSource
|
|
@@ -8381,7 +8420,7 @@ async function runCodeReview(deps, params) {
|
|
|
8381
8420
|
template = await deps.pack.getPrompt("code-review");
|
|
8382
8421
|
} catch (err) {
|
|
8383
8422
|
const error = err instanceof Error ? err.message : String(err);
|
|
8384
|
-
logger$
|
|
8423
|
+
logger$18.error({ error }, "Failed to retrieve code-review prompt template");
|
|
8385
8424
|
return defaultFailResult(`Failed to retrieve prompt template: ${error}`, {
|
|
8386
8425
|
input: 0,
|
|
8387
8426
|
output: 0
|
|
@@ -8394,10 +8433,10 @@ async function runCodeReview(deps, params) {
|
|
|
8394
8433
|
const error = err instanceof Error ? err.message : String(err);
|
|
8395
8434
|
const recovered = await recoverStoryFileFromBranch(storyFilePath, cwd);
|
|
8396
8435
|
if (recovered !== void 0) {
|
|
8397
|
-
logger$
|
|
8436
|
+
logger$18.warn({ storyFilePath }, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
8398
8437
|
storyContent = recovered;
|
|
8399
8438
|
} else {
|
|
8400
|
-
logger$
|
|
8439
|
+
logger$18.error({
|
|
8401
8440
|
storyFilePath,
|
|
8402
8441
|
error
|
|
8403
8442
|
}, "Failed to read story file (absent from working tree AND branch HEAD)");
|
|
@@ -8418,12 +8457,12 @@ async function runCodeReview(deps, params) {
|
|
|
8418
8457
|
const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
|
|
8419
8458
|
if (scopedTotal <= TOKEN_CEILING) {
|
|
8420
8459
|
gitDiffContent = scopedDiff;
|
|
8421
|
-
logger$
|
|
8460
|
+
logger$18.debug({
|
|
8422
8461
|
fileCount: filesModified.length,
|
|
8423
8462
|
tokenCount: scopedTotal
|
|
8424
8463
|
}, "Using scoped file diff");
|
|
8425
8464
|
} else {
|
|
8426
|
-
logger$
|
|
8465
|
+
logger$18.warn({
|
|
8427
8466
|
estimatedTotal: scopedTotal,
|
|
8428
8467
|
ceiling: TOKEN_CEILING,
|
|
8429
8468
|
fileCount: filesModified.length
|
|
@@ -8437,7 +8476,7 @@ async function runCodeReview(deps, params) {
|
|
|
8437
8476
|
const fullTotal = nonDiffTokens + countTokens(fullDiff);
|
|
8438
8477
|
if (fullTotal <= TOKEN_CEILING) gitDiffContent = fullDiff;
|
|
8439
8478
|
else {
|
|
8440
|
-
logger$
|
|
8479
|
+
logger$18.warn({
|
|
8441
8480
|
estimatedTotal: fullTotal,
|
|
8442
8481
|
ceiling: TOKEN_CEILING
|
|
8443
8482
|
}, "Full git diff would exceed token ceiling — using stat-only summary");
|
|
@@ -8445,7 +8484,7 @@ async function runCodeReview(deps, params) {
|
|
|
8445
8484
|
}
|
|
8446
8485
|
}
|
|
8447
8486
|
if (gitDiffContent.trim().length === 0 && baselineCommit) {
|
|
8448
|
-
logger$
|
|
8487
|
+
logger$18.info({
|
|
8449
8488
|
storyKey,
|
|
8450
8489
|
baselineCommit
|
|
8451
8490
|
}, "Working tree diff empty — diffing against baseline commit");
|
|
@@ -8453,7 +8492,7 @@ async function runCodeReview(deps, params) {
|
|
|
8453
8492
|
const commitTotal = nonDiffTokens + countTokens(commitDiff);
|
|
8454
8493
|
if (commitDiff.trim().length > 0) if (commitTotal <= TOKEN_CEILING) gitDiffContent = commitDiff;
|
|
8455
8494
|
else {
|
|
8456
|
-
logger$
|
|
8495
|
+
logger$18.warn({
|
|
8457
8496
|
estimatedTotal: commitTotal,
|
|
8458
8497
|
ceiling: TOKEN_CEILING
|
|
8459
8498
|
}, "Baseline..HEAD diff exceeds token ceiling — using stat-only summary");
|
|
@@ -8461,7 +8500,7 @@ async function runCodeReview(deps, params) {
|
|
|
8461
8500
|
}
|
|
8462
8501
|
}
|
|
8463
8502
|
if (gitDiffContent.trim().length === 0) {
|
|
8464
|
-
logger$
|
|
8503
|
+
logger$18.info({ storyKey }, "Empty git diff — skipping review with SHIP_IT");
|
|
8465
8504
|
return {
|
|
8466
8505
|
verdict: "SHIP_IT",
|
|
8467
8506
|
issues: 0,
|
|
@@ -8477,7 +8516,7 @@ async function runCodeReview(deps, params) {
|
|
|
8477
8516
|
if (deps.repoMapInjector !== void 0) {
|
|
8478
8517
|
const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
|
|
8479
8518
|
repoContextContent = injection.text;
|
|
8480
|
-
logger$
|
|
8519
|
+
logger$18.info({
|
|
8481
8520
|
storyKey,
|
|
8482
8521
|
repoMapTokens: Math.ceil(injection.text.length / 4),
|
|
8483
8522
|
symbolCount: injection.symbolCount,
|
|
@@ -8497,17 +8536,17 @@ async function runCodeReview(deps, params) {
|
|
|
8497
8536
|
const findings = await getProjectFindings(deps.db);
|
|
8498
8537
|
if (findings.length > 0) {
|
|
8499
8538
|
priorFindingsContent = "Previous reviews found these recurring patterns — pay special attention:\n\n" + findings;
|
|
8500
|
-
logger$
|
|
8539
|
+
logger$18.debug({
|
|
8501
8540
|
storyKey,
|
|
8502
8541
|
findingsLen: findings.length
|
|
8503
8542
|
}, "Injecting prior findings into code-review prompt");
|
|
8504
8543
|
}
|
|
8505
8544
|
} catch {}
|
|
8506
8545
|
const testMetricsContent = await countTestMetrics(filesModified, cwd);
|
|
8507
|
-
if (testMetricsContent) logger$
|
|
8546
|
+
if (testMetricsContent) logger$18.debug({ storyKey }, "Injecting verified test-count metrics into code-review context");
|
|
8508
8547
|
const fileDiffs = gitDiffContent ? parseDiffByFile(gitDiffContent) : void 0;
|
|
8509
8548
|
const scopeAnalysisContent = storyContent && filesModified ? ScopeGuardrail.buildAnalysis(storyContent, filesModified, fileDiffs) : "";
|
|
8510
|
-
if (scopeAnalysisContent) logger$
|
|
8549
|
+
if (scopeAnalysisContent) logger$18.debug({ storyKey }, "Scope analysis detected out-of-scope files");
|
|
8511
8550
|
const buildStatusPrefix = buildPassed === true ? "BUILD STATUS: PASSED — code compiles and passes build verification. Focus on logic correctness, style, and acceptance criteria rather than compilation errors.\n\n" : "";
|
|
8512
8551
|
const sections = [
|
|
8513
8552
|
{
|
|
@@ -8552,11 +8591,11 @@ async function runCodeReview(deps, params) {
|
|
|
8552
8591
|
}
|
|
8553
8592
|
];
|
|
8554
8593
|
const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
8555
|
-
if (assembleResult.truncated) logger$
|
|
8594
|
+
if (assembleResult.truncated) logger$18.warn({
|
|
8556
8595
|
storyKey,
|
|
8557
8596
|
tokenCount: assembleResult.tokenCount
|
|
8558
8597
|
}, "Code-review prompt truncated to fit token ceiling");
|
|
8559
|
-
logger$
|
|
8598
|
+
logger$18.debug({
|
|
8560
8599
|
storyKey,
|
|
8561
8600
|
tokenCount: assembleResult.tokenCount,
|
|
8562
8601
|
truncated: assembleResult.truncated
|
|
@@ -8577,7 +8616,7 @@ async function runCodeReview(deps, params) {
|
|
|
8577
8616
|
dispatchResult = await handle.result;
|
|
8578
8617
|
} catch (err) {
|
|
8579
8618
|
const error = err instanceof Error ? err.message : String(err);
|
|
8580
|
-
logger$
|
|
8619
|
+
logger$18.error({
|
|
8581
8620
|
storyKey,
|
|
8582
8621
|
error
|
|
8583
8622
|
}, "Code-review dispatch threw unexpected error");
|
|
@@ -8593,7 +8632,7 @@ async function runCodeReview(deps, params) {
|
|
|
8593
8632
|
const rawOutput = dispatchResult.output ?? void 0;
|
|
8594
8633
|
if (dispatchResult.status === "failed") {
|
|
8595
8634
|
const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""} ${dispatchResult.output ? `Stderr: ${dispatchResult.output}` : ""}`.trim();
|
|
8596
|
-
logger$
|
|
8635
|
+
logger$18.warn({
|
|
8597
8636
|
storyKey,
|
|
8598
8637
|
exitCode: dispatchResult.exitCode
|
|
8599
8638
|
}, "Code-review dispatch failed");
|
|
@@ -8603,7 +8642,7 @@ async function runCodeReview(deps, params) {
|
|
|
8603
8642
|
};
|
|
8604
8643
|
}
|
|
8605
8644
|
if (dispatchResult.status === "timeout") {
|
|
8606
|
-
logger$
|
|
8645
|
+
logger$18.warn({ storyKey }, "Code-review dispatch timed out");
|
|
8607
8646
|
return {
|
|
8608
8647
|
...defaultFailResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage),
|
|
8609
8648
|
rawOutput
|
|
@@ -8611,7 +8650,7 @@ async function runCodeReview(deps, params) {
|
|
|
8611
8650
|
}
|
|
8612
8651
|
if (dispatchResult.parsed === null) {
|
|
8613
8652
|
const details = dispatchResult.parseError ?? "No YAML block found in output";
|
|
8614
|
-
logger$
|
|
8653
|
+
logger$18.warn({
|
|
8615
8654
|
storyKey,
|
|
8616
8655
|
details
|
|
8617
8656
|
}, "Code-review output schema validation failed");
|
|
@@ -8629,7 +8668,7 @@ async function runCodeReview(deps, params) {
|
|
|
8629
8668
|
const parseResult = CodeReviewResultSchema.safeParse(dispatchResult.parsed);
|
|
8630
8669
|
if (!parseResult.success) {
|
|
8631
8670
|
const details = parseResult.error.message;
|
|
8632
|
-
logger$
|
|
8671
|
+
logger$18.warn({
|
|
8633
8672
|
storyKey,
|
|
8634
8673
|
details
|
|
8635
8674
|
}, "Code-review output failed schema validation");
|
|
@@ -8645,13 +8684,13 @@ async function runCodeReview(deps, params) {
|
|
|
8645
8684
|
};
|
|
8646
8685
|
}
|
|
8647
8686
|
const parsed = parseResult.data;
|
|
8648
|
-
if (parsed.agentVerdict !== parsed.verdict) logger$
|
|
8687
|
+
if (parsed.agentVerdict !== parsed.verdict) logger$18.info({
|
|
8649
8688
|
storyKey,
|
|
8650
8689
|
agentVerdict: parsed.agentVerdict,
|
|
8651
8690
|
pipelineVerdict: parsed.verdict,
|
|
8652
8691
|
issues: parsed.issues
|
|
8653
8692
|
}, "Pipeline overrode agent verdict based on issue severities");
|
|
8654
|
-
logger$
|
|
8693
|
+
logger$18.info({
|
|
8655
8694
|
storyKey,
|
|
8656
8695
|
verdict: parsed.verdict,
|
|
8657
8696
|
issues: parsed.issues
|
|
@@ -8677,14 +8716,14 @@ async function getArchConstraints$2(deps) {
|
|
|
8677
8716
|
if (constraints.length === 0) return "";
|
|
8678
8717
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
8679
8718
|
} catch (err) {
|
|
8680
|
-
logger$
|
|
8719
|
+
logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
8681
8720
|
return "";
|
|
8682
8721
|
}
|
|
8683
8722
|
}
|
|
8684
8723
|
|
|
8685
8724
|
//#endregion
|
|
8686
8725
|
//#region src/modules/compiled-workflows/merge-to-main.ts
|
|
8687
|
-
const logger$
|
|
8726
|
+
const logger$17 = createLogger("compiled-workflows:merge-to-main");
|
|
8688
8727
|
/**
|
|
8689
8728
|
* Execute the merge-to-main phase: merge the story branch into the base branch.
|
|
8690
8729
|
*
|
|
@@ -8704,7 +8743,7 @@ const logger$16 = createLogger("compiled-workflows:merge-to-main");
|
|
|
8704
8743
|
async function runMergeToMain(params) {
|
|
8705
8744
|
const { storyKey, branchName, startBranch, worktreeManager, eventBus, projectRoot } = params;
|
|
8706
8745
|
const mergeStrategy = params.mergeStrategy ?? "ff-only";
|
|
8707
|
-
logger$
|
|
8746
|
+
logger$17.info({
|
|
8708
8747
|
storyKey,
|
|
8709
8748
|
branchName,
|
|
8710
8749
|
startBranch,
|
|
@@ -8712,7 +8751,7 @@ async function runMergeToMain(params) {
|
|
|
8712
8751
|
}, "Starting merge-to-main phase");
|
|
8713
8752
|
const dirtiedFiles = listParentDirtyIntersection(branchName, startBranch, projectRoot);
|
|
8714
8753
|
if (dirtiedFiles.length > 0) {
|
|
8715
|
-
logger$
|
|
8754
|
+
logger$17.warn({
|
|
8716
8755
|
storyKey,
|
|
8717
8756
|
branchName,
|
|
8718
8757
|
dirtiedFiles
|
|
@@ -8725,7 +8764,7 @@ async function runMergeToMain(params) {
|
|
|
8725
8764
|
}
|
|
8726
8765
|
const ffSuccess = tryFfMerge(branchName, projectRoot);
|
|
8727
8766
|
if (ffSuccess) {
|
|
8728
|
-
logger$
|
|
8767
|
+
logger$17.info({
|
|
8729
8768
|
storyKey,
|
|
8730
8769
|
branchName
|
|
8731
8770
|
}, "Fast-forward merge succeeded");
|
|
@@ -8733,7 +8772,7 @@ async function runMergeToMain(params) {
|
|
|
8733
8772
|
return { success: true };
|
|
8734
8773
|
}
|
|
8735
8774
|
if (mergeStrategy === "ff-only") {
|
|
8736
|
-
logger$
|
|
8775
|
+
logger$17.warn({
|
|
8737
8776
|
storyKey,
|
|
8738
8777
|
branchName,
|
|
8739
8778
|
startBranch
|
|
@@ -8743,13 +8782,13 @@ async function runMergeToMain(params) {
|
|
|
8743
8782
|
reason: "ff-only-merge-not-possible"
|
|
8744
8783
|
};
|
|
8745
8784
|
}
|
|
8746
|
-
logger$
|
|
8785
|
+
logger$17.info({
|
|
8747
8786
|
storyKey,
|
|
8748
8787
|
branchName
|
|
8749
8788
|
}, "Fast-forward merge failed — attempting 3-way merge");
|
|
8750
8789
|
const threeWayResult = tryThreeWayMerge(branchName, projectRoot);
|
|
8751
8790
|
if (threeWayResult.success) {
|
|
8752
|
-
logger$
|
|
8791
|
+
logger$17.info({
|
|
8753
8792
|
storyKey,
|
|
8754
8793
|
branchName
|
|
8755
8794
|
}, "3-way merge succeeded");
|
|
@@ -8757,7 +8796,7 @@ async function runMergeToMain(params) {
|
|
|
8757
8796
|
return { success: true };
|
|
8758
8797
|
}
|
|
8759
8798
|
const { conflictingFiles } = threeWayResult;
|
|
8760
|
-
logger$
|
|
8799
|
+
logger$17.warn({
|
|
8761
8800
|
storyKey,
|
|
8762
8801
|
branchName,
|
|
8763
8802
|
conflictingFiles
|
|
@@ -8810,7 +8849,7 @@ function listParentDirtyIntersection(branchName, startBranch, projectRoot) {
|
|
|
8810
8849
|
});
|
|
8811
8850
|
return diffOut.split("\n").filter((f$1) => f$1.trim().length > 0).filter((f$1) => dirty.has(f$1));
|
|
8812
8851
|
} catch (err) {
|
|
8813
|
-
logger$
|
|
8852
|
+
logger$17.warn({ err }, "parent-clean precondition check failed (best-effort) — proceeding to merge");
|
|
8814
8853
|
return [];
|
|
8815
8854
|
}
|
|
8816
8855
|
}
|
|
@@ -8887,7 +8926,7 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
8887
8926
|
});
|
|
8888
8927
|
conflictingFiles = diffOutput.trim().split("\n").filter((line) => line.length > 0);
|
|
8889
8928
|
} catch (diffErr) {
|
|
8890
|
-
logger$
|
|
8929
|
+
logger$17.warn({ err: diffErr }, "Failed to list conflicting files (best-effort)");
|
|
8891
8930
|
}
|
|
8892
8931
|
try {
|
|
8893
8932
|
execFileSync("git", ["merge", "--abort"], {
|
|
@@ -8899,7 +8938,7 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
8899
8938
|
]
|
|
8900
8939
|
});
|
|
8901
8940
|
} catch (abortErr) {
|
|
8902
|
-
logger$
|
|
8941
|
+
logger$17.warn({ err: abortErr }, "Failed to abort merge (best-effort)");
|
|
8903
8942
|
}
|
|
8904
8943
|
return {
|
|
8905
8944
|
success: false,
|
|
@@ -8921,12 +8960,12 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
8921
8960
|
async function cleanupAfterSuccessfulMerge(storyKey, branchName, worktreeManager, _projectRoot) {
|
|
8922
8961
|
try {
|
|
8923
8962
|
await worktreeManager.cleanupWorktree(storyKey);
|
|
8924
|
-
logger$
|
|
8963
|
+
logger$17.info({
|
|
8925
8964
|
storyKey,
|
|
8926
8965
|
branchName
|
|
8927
8966
|
}, "Worktree + branch removed after successful merge");
|
|
8928
8967
|
} catch (worktreeErr) {
|
|
8929
|
-
logger$
|
|
8968
|
+
logger$17.warn({
|
|
8930
8969
|
storyKey,
|
|
8931
8970
|
err: worktreeErr
|
|
8932
8971
|
}, "Failed to remove worktree (best-effort)");
|
|
@@ -8955,7 +8994,7 @@ function createMergeQueue() {
|
|
|
8955
8994
|
|
|
8956
8995
|
//#endregion
|
|
8957
8996
|
//#region src/modules/compiled-workflows/test-plan.ts
|
|
8958
|
-
const logger$
|
|
8997
|
+
const logger$16 = createLogger("compiled-workflows:test-plan");
|
|
8959
8998
|
/** Default timeout for test-plan dispatches in milliseconds (5 min — lightweight call) */
|
|
8960
8999
|
const DEFAULT_TIMEOUT_MS$1 = 3e5;
|
|
8961
9000
|
/**
|
|
@@ -8967,12 +9006,12 @@ const DEFAULT_TIMEOUT_MS$1 = 3e5;
|
|
|
8967
9006
|
*/
|
|
8968
9007
|
async function runTestPlan(deps, params) {
|
|
8969
9008
|
const { storyKey, storyFilePath, pipelineRunId } = params;
|
|
8970
|
-
logger$
|
|
9009
|
+
logger$16.info({
|
|
8971
9010
|
storyKey,
|
|
8972
9011
|
storyFilePath
|
|
8973
9012
|
}, "Starting compiled test-plan workflow");
|
|
8974
9013
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-plan", deps.tokenCeilings);
|
|
8975
|
-
logger$
|
|
9014
|
+
logger$16.info({
|
|
8976
9015
|
workflow: "test-plan",
|
|
8977
9016
|
ceiling: TOKEN_CEILING,
|
|
8978
9017
|
source: tokenCeilingSource
|
|
@@ -8980,10 +9019,10 @@ async function runTestPlan(deps, params) {
|
|
|
8980
9019
|
let template;
|
|
8981
9020
|
try {
|
|
8982
9021
|
template = await deps.pack.getPrompt("test-plan");
|
|
8983
|
-
logger$
|
|
9022
|
+
logger$16.debug({ storyKey }, "Retrieved test-plan prompt template from pack");
|
|
8984
9023
|
} catch (err) {
|
|
8985
9024
|
const error = err instanceof Error ? err.message : String(err);
|
|
8986
|
-
logger$
|
|
9025
|
+
logger$16.warn({
|
|
8987
9026
|
storyKey,
|
|
8988
9027
|
error
|
|
8989
9028
|
}, "Failed to retrieve test-plan prompt template");
|
|
@@ -8994,14 +9033,14 @@ async function runTestPlan(deps, params) {
|
|
|
8994
9033
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
8995
9034
|
} catch (err) {
|
|
8996
9035
|
if (err.code === "ENOENT") {
|
|
8997
|
-
logger$
|
|
9036
|
+
logger$16.warn({
|
|
8998
9037
|
storyKey,
|
|
8999
9038
|
storyFilePath
|
|
9000
9039
|
}, "Story file not found for test planning");
|
|
9001
9040
|
return makeTestPlanFailureResult("story_file_not_found");
|
|
9002
9041
|
}
|
|
9003
9042
|
const error = err instanceof Error ? err.message : String(err);
|
|
9004
|
-
logger$
|
|
9043
|
+
logger$16.warn({
|
|
9005
9044
|
storyKey,
|
|
9006
9045
|
storyFilePath,
|
|
9007
9046
|
error
|
|
@@ -9015,13 +9054,13 @@ async function runTestPlan(deps, params) {
|
|
|
9015
9054
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
9016
9055
|
if (testPatternDecisions.length > 0) {
|
|
9017
9056
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
9018
|
-
logger$
|
|
9057
|
+
logger$16.debug({
|
|
9019
9058
|
storyKey,
|
|
9020
9059
|
count: testPatternDecisions.length
|
|
9021
9060
|
}, "Loaded test patterns from decision store");
|
|
9022
9061
|
} else {
|
|
9023
9062
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
9024
|
-
logger$
|
|
9063
|
+
logger$16.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
9025
9064
|
}
|
|
9026
9065
|
} catch {
|
|
9027
9066
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
@@ -9043,7 +9082,7 @@ async function runTestPlan(deps, params) {
|
|
|
9043
9082
|
priority: "optional"
|
|
9044
9083
|
}
|
|
9045
9084
|
], TOKEN_CEILING);
|
|
9046
|
-
logger$
|
|
9085
|
+
logger$16.info({
|
|
9047
9086
|
storyKey,
|
|
9048
9087
|
tokenCount,
|
|
9049
9088
|
ceiling: TOKEN_CEILING,
|
|
@@ -9064,7 +9103,7 @@ async function runTestPlan(deps, params) {
|
|
|
9064
9103
|
dispatchResult = await handle.result;
|
|
9065
9104
|
} catch (err) {
|
|
9066
9105
|
const error = err instanceof Error ? err.message : String(err);
|
|
9067
|
-
logger$
|
|
9106
|
+
logger$16.warn({
|
|
9068
9107
|
storyKey,
|
|
9069
9108
|
error
|
|
9070
9109
|
}, "Test-plan dispatch threw an unexpected error");
|
|
@@ -9075,7 +9114,7 @@ async function runTestPlan(deps, params) {
|
|
|
9075
9114
|
output: dispatchResult.tokenEstimate.output
|
|
9076
9115
|
};
|
|
9077
9116
|
if (dispatchResult.status === "timeout") {
|
|
9078
|
-
logger$
|
|
9117
|
+
logger$16.warn({
|
|
9079
9118
|
storyKey,
|
|
9080
9119
|
durationMs: dispatchResult.durationMs
|
|
9081
9120
|
}, "Test-plan dispatch timed out");
|
|
@@ -9085,7 +9124,7 @@ async function runTestPlan(deps, params) {
|
|
|
9085
9124
|
};
|
|
9086
9125
|
}
|
|
9087
9126
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
9088
|
-
logger$
|
|
9127
|
+
logger$16.warn({
|
|
9089
9128
|
storyKey,
|
|
9090
9129
|
exitCode: dispatchResult.exitCode,
|
|
9091
9130
|
status: dispatchResult.status
|
|
@@ -9097,7 +9136,7 @@ async function runTestPlan(deps, params) {
|
|
|
9097
9136
|
}
|
|
9098
9137
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
9099
9138
|
const details = dispatchResult.parseError ?? "parsed result was null";
|
|
9100
|
-
logger$
|
|
9139
|
+
logger$16.warn({
|
|
9101
9140
|
storyKey,
|
|
9102
9141
|
parseError: details
|
|
9103
9142
|
}, "Test-plan YAML schema validation failed");
|
|
@@ -9120,19 +9159,19 @@ async function runTestPlan(deps, params) {
|
|
|
9120
9159
|
}),
|
|
9121
9160
|
rationale: `Test plan for ${storyKey}: ${parsed.test_files.length} test files, categories: ${parsed.test_categories.join(", ")}`
|
|
9122
9161
|
});
|
|
9123
|
-
logger$
|
|
9162
|
+
logger$16.info({
|
|
9124
9163
|
storyKey,
|
|
9125
9164
|
fileCount: parsed.test_files.length,
|
|
9126
9165
|
categories: parsed.test_categories
|
|
9127
9166
|
}, "Test plan stored in decision store");
|
|
9128
9167
|
} catch (err) {
|
|
9129
9168
|
const error = err instanceof Error ? err.message : String(err);
|
|
9130
|
-
logger$
|
|
9169
|
+
logger$16.warn({
|
|
9131
9170
|
storyKey,
|
|
9132
9171
|
error
|
|
9133
9172
|
}, "Failed to store test plan in decision store — proceeding anyway");
|
|
9134
9173
|
}
|
|
9135
|
-
logger$
|
|
9174
|
+
logger$16.info({
|
|
9136
9175
|
storyKey,
|
|
9137
9176
|
result: parsed.result
|
|
9138
9177
|
}, "Test-plan workflow completed");
|
|
@@ -9172,14 +9211,14 @@ async function getArchConstraints$1(deps) {
|
|
|
9172
9211
|
if (constraints.length === 0) return "";
|
|
9173
9212
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
9174
9213
|
} catch (err) {
|
|
9175
|
-
logger$
|
|
9214
|
+
logger$16.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints for test-plan — proceeding without them");
|
|
9176
9215
|
return "";
|
|
9177
9216
|
}
|
|
9178
9217
|
}
|
|
9179
9218
|
|
|
9180
9219
|
//#endregion
|
|
9181
9220
|
//#region src/modules/implementation-orchestrator/probe-author-integration.ts
|
|
9182
|
-
const logger$
|
|
9221
|
+
const logger$15 = createLogger("implementation-orchestrator:probe-author");
|
|
9183
9222
|
/**
|
|
9184
9223
|
* Default timeout for probe-author dispatches (10 min).
|
|
9185
9224
|
* obs_2026-05-04_023 layer 2: raised from 300_000 → 600_000 after Story
|
|
@@ -9230,7 +9269,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9230
9269
|
};
|
|
9231
9270
|
const stateIntegratingActive = stateIntegratingEnabled !== false;
|
|
9232
9271
|
if (bypassGates !== true && !detectsEventDrivenAC(epicContent) && !(stateIntegratingActive && detectsStateIntegratingAC(epicContent))) {
|
|
9233
|
-
logger$
|
|
9272
|
+
logger$15.debug({ storyKey }, "probe-author: source AC neither event-driven nor state-integrating — skipping");
|
|
9234
9273
|
emitEvent?.("probe-author:skipped", {
|
|
9235
9274
|
storyKey,
|
|
9236
9275
|
runId: pipelineRunId,
|
|
@@ -9242,7 +9281,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9242
9281
|
try {
|
|
9243
9282
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
9244
9283
|
if (bypassGates !== true && /^## Runtime Probes/m.test(storyContent)) {
|
|
9245
|
-
logger$
|
|
9284
|
+
logger$15.info({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping");
|
|
9246
9285
|
emitEvent?.("probe-author:skipped", {
|
|
9247
9286
|
storyKey,
|
|
9248
9287
|
runId: pipelineRunId,
|
|
@@ -9252,7 +9291,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9252
9291
|
}
|
|
9253
9292
|
} catch (err) {
|
|
9254
9293
|
const error = err instanceof Error ? err.message : String(err);
|
|
9255
|
-
logger$
|
|
9294
|
+
logger$15.warn({
|
|
9256
9295
|
storyKey,
|
|
9257
9296
|
error
|
|
9258
9297
|
}, "probe-author: failed to read story file — falling through");
|
|
@@ -9267,10 +9306,10 @@ async function runProbeAuthor(deps, params) {
|
|
|
9267
9306
|
let template;
|
|
9268
9307
|
try {
|
|
9269
9308
|
template = await deps.pack.getPrompt("probe-author");
|
|
9270
|
-
logger$
|
|
9309
|
+
logger$15.debug({ storyKey }, "probe-author: retrieved prompt template");
|
|
9271
9310
|
} catch (err) {
|
|
9272
9311
|
const error = err instanceof Error ? err.message : String(err);
|
|
9273
|
-
logger$
|
|
9312
|
+
logger$15.warn({
|
|
9274
9313
|
storyKey,
|
|
9275
9314
|
error
|
|
9276
9315
|
}, "probe-author: failed to get prompt template — falling through");
|
|
@@ -9305,13 +9344,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9305
9344
|
};
|
|
9306
9345
|
let dispatchResult;
|
|
9307
9346
|
try {
|
|
9308
|
-
logger$
|
|
9347
|
+
logger$15.info({ storyKey }, "probe-author: dispatching probe-author agent");
|
|
9309
9348
|
dispatchResult = await doDispatch(basePrompt, DEFAULT_TIMEOUT_MS);
|
|
9310
9349
|
tokenUsage.input += dispatchResult.tokenEstimate.input;
|
|
9311
9350
|
tokenUsage.output += dispatchResult.tokenEstimate.output;
|
|
9312
9351
|
} catch (err) {
|
|
9313
9352
|
const error = err instanceof Error ? err.message : String(err);
|
|
9314
|
-
logger$
|
|
9353
|
+
logger$15.warn({
|
|
9315
9354
|
storyKey,
|
|
9316
9355
|
error
|
|
9317
9356
|
}, "probe-author: dispatch error — falling through to dev-story");
|
|
@@ -9324,7 +9363,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9324
9363
|
}
|
|
9325
9364
|
if (dispatchResult.status === "timeout") {
|
|
9326
9365
|
const elapsedMs = Date.now() - start;
|
|
9327
|
-
logger$
|
|
9366
|
+
logger$15.warn({
|
|
9328
9367
|
storyKey,
|
|
9329
9368
|
elapsedMs
|
|
9330
9369
|
}, "probe-author: dispatch timed out — retrying with 1.5× timeout");
|
|
@@ -9338,13 +9377,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9338
9377
|
tokenUsage.input += retryResult.tokenEstimate.input;
|
|
9339
9378
|
tokenUsage.output += retryResult.tokenEstimate.output;
|
|
9340
9379
|
if (retryResult.status === "timeout") {
|
|
9341
|
-
logger$
|
|
9380
|
+
logger$15.warn({ storyKey }, "probe-author: retry also timed out — falling through to dev-story");
|
|
9342
9381
|
return makeFailedResult("dispatch_timeout", tokenUsage, start);
|
|
9343
9382
|
}
|
|
9344
9383
|
dispatchResult = retryResult;
|
|
9345
9384
|
} catch (retryErr) {
|
|
9346
9385
|
const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
9347
|
-
logger$
|
|
9386
|
+
logger$15.warn({
|
|
9348
9387
|
storyKey,
|
|
9349
9388
|
error
|
|
9350
9389
|
}, "probe-author: retry dispatch error — falling through to dev-story");
|
|
@@ -9353,7 +9392,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9353
9392
|
}
|
|
9354
9393
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
9355
9394
|
const error = `dispatch_failed with exit_code=${dispatchResult.exitCode}`;
|
|
9356
|
-
logger$
|
|
9395
|
+
logger$15.warn({ storyKey }, `probe-author: ${error} — falling through to dev-story`);
|
|
9357
9396
|
emitEvent?.("probe-author:dispatch-error", {
|
|
9358
9397
|
storyKey,
|
|
9359
9398
|
runId: pipelineRunId,
|
|
@@ -9364,7 +9403,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9364
9403
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
9365
9404
|
const parseError = dispatchResult.parseError ?? "parsed result was null";
|
|
9366
9405
|
const rawOutputSnippet = dispatchResult.output.slice(0, 500);
|
|
9367
|
-
logger$
|
|
9406
|
+
logger$15.warn({
|
|
9368
9407
|
storyKey,
|
|
9369
9408
|
parseError,
|
|
9370
9409
|
rawOutputSnippet
|
|
@@ -9381,13 +9420,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9381
9420
|
tokenUsage.input += retryResult.tokenEstimate.input;
|
|
9382
9421
|
tokenUsage.output += retryResult.tokenEstimate.output;
|
|
9383
9422
|
if (retryResult.parseError !== null || retryResult.parsed === null) {
|
|
9384
|
-
logger$
|
|
9423
|
+
logger$15.warn({ storyKey }, "probe-author: retry still produced invalid YAML — falling through");
|
|
9385
9424
|
return makeFailedResult("invalid_yaml_after_retry", tokenUsage, start);
|
|
9386
9425
|
}
|
|
9387
9426
|
dispatchResult = retryResult;
|
|
9388
9427
|
} catch (retryErr) {
|
|
9389
9428
|
const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
9390
|
-
logger$
|
|
9429
|
+
logger$15.warn({
|
|
9391
9430
|
storyKey,
|
|
9392
9431
|
error
|
|
9393
9432
|
}, "probe-author: retry error after invalid YAML — falling through");
|
|
@@ -9398,7 +9437,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9398
9437
|
const probeValidation = RuntimeProbeListSchema.safeParse(parsedOutput.probes);
|
|
9399
9438
|
if (!probeValidation.success) {
|
|
9400
9439
|
const validationError = probeValidation.error.message;
|
|
9401
|
-
logger$
|
|
9440
|
+
logger$15.warn({
|
|
9402
9441
|
storyKey,
|
|
9403
9442
|
validationError
|
|
9404
9443
|
}, "probe-author: probes failed RuntimeProbeListSchema — falling through");
|
|
@@ -9414,7 +9453,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9414
9453
|
probesParsedCount: probes.length
|
|
9415
9454
|
});
|
|
9416
9455
|
if (probes.length === 0) {
|
|
9417
|
-
logger$
|
|
9456
|
+
logger$15.info({ storyKey }, "probe-author: authored empty probes list — no probes needed");
|
|
9418
9457
|
emitEvent?.("probe-author:no-probes-authored", {
|
|
9419
9458
|
storyKey,
|
|
9420
9459
|
runId: pipelineRunId
|
|
@@ -9429,7 +9468,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9429
9468
|
try {
|
|
9430
9469
|
const refreshedContent = await readFile$1(storyFilePath, "utf-8");
|
|
9431
9470
|
if (/^## Runtime Probes/m.test(refreshedContent)) {
|
|
9432
|
-
logger$
|
|
9471
|
+
logger$15.info({ storyKey }, "probe-author: ## Runtime Probes section appeared after dispatch — skipping append (idempotent)");
|
|
9433
9472
|
const dispatchDurationMs$1 = Date.now() - start;
|
|
9434
9473
|
emitEvent?.("probe-author:dispatched", {
|
|
9435
9474
|
storyKey,
|
|
@@ -9448,7 +9487,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9448
9487
|
const tmpPath = join$1(targetDir, `.probe-author-${Date.now()}.tmp.md`);
|
|
9449
9488
|
await writeFile$1(tmpPath, newContent, "utf-8");
|
|
9450
9489
|
await rename(tmpPath, storyFilePath);
|
|
9451
|
-
logger$
|
|
9490
|
+
logger$15.info({
|
|
9452
9491
|
storyKey,
|
|
9453
9492
|
probesCount: probes.length
|
|
9454
9493
|
}, "probe-author: appended ## Runtime Probes section");
|
|
@@ -9460,7 +9499,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9460
9499
|
});
|
|
9461
9500
|
} catch (err) {
|
|
9462
9501
|
const error = err instanceof Error ? err.message : String(err);
|
|
9463
|
-
logger$
|
|
9502
|
+
logger$15.warn({
|
|
9464
9503
|
storyKey,
|
|
9465
9504
|
error
|
|
9466
9505
|
}, "probe-author: failed to append probes — falling through to dev-story");
|
|
@@ -9482,7 +9521,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9482
9521
|
costUsd,
|
|
9483
9522
|
triggered_by: triggerClass ?? "event-driven"
|
|
9484
9523
|
});
|
|
9485
|
-
logger$
|
|
9524
|
+
logger$15.info({
|
|
9486
9525
|
storyKey,
|
|
9487
9526
|
probesAuthoredCount: probes.length
|
|
9488
9527
|
}, "probe-author: phase complete");
|
|
@@ -9517,7 +9556,7 @@ function estimateDispatchCost$1(input, output) {
|
|
|
9517
9556
|
|
|
9518
9557
|
//#endregion
|
|
9519
9558
|
//#region src/modules/compiled-workflows/test-expansion.ts
|
|
9520
|
-
const logger$
|
|
9559
|
+
const logger$14 = createLogger("compiled-workflows:test-expansion");
|
|
9521
9560
|
function defaultFallbackResult(error, tokenUsage) {
|
|
9522
9561
|
return {
|
|
9523
9562
|
expansion_priority: "low",
|
|
@@ -9547,14 +9586,14 @@ function defaultFallbackResult(error, tokenUsage) {
|
|
|
9547
9586
|
async function runTestExpansion(deps, params) {
|
|
9548
9587
|
const { storyKey, storyFilePath, pipelineRunId, filesModified, workingDirectory } = params;
|
|
9549
9588
|
const cwd = workingDirectory ?? process.cwd();
|
|
9550
|
-
logger$
|
|
9589
|
+
logger$14.debug({
|
|
9551
9590
|
storyKey,
|
|
9552
9591
|
storyFilePath,
|
|
9553
9592
|
cwd,
|
|
9554
9593
|
pipelineRunId
|
|
9555
9594
|
}, "Starting test-expansion workflow");
|
|
9556
9595
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-expansion", deps.tokenCeilings);
|
|
9557
|
-
logger$
|
|
9596
|
+
logger$14.info({
|
|
9558
9597
|
workflow: "test-expansion",
|
|
9559
9598
|
ceiling: TOKEN_CEILING,
|
|
9560
9599
|
source: tokenCeilingSource
|
|
@@ -9564,7 +9603,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9564
9603
|
template = await deps.pack.getPrompt("test-expansion");
|
|
9565
9604
|
} catch (err) {
|
|
9566
9605
|
const error = err instanceof Error ? err.message : String(err);
|
|
9567
|
-
logger$
|
|
9606
|
+
logger$14.warn({ error }, "Failed to retrieve test-expansion prompt template");
|
|
9568
9607
|
return defaultFallbackResult(`Failed to retrieve prompt template: ${error}`, {
|
|
9569
9608
|
input: 0,
|
|
9570
9609
|
output: 0
|
|
@@ -9575,7 +9614,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9575
9614
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
9576
9615
|
} catch (err) {
|
|
9577
9616
|
const error = err instanceof Error ? err.message : String(err);
|
|
9578
|
-
logger$
|
|
9617
|
+
logger$14.warn({
|
|
9579
9618
|
storyFilePath,
|
|
9580
9619
|
error
|
|
9581
9620
|
}, "Failed to read story file");
|
|
@@ -9591,13 +9630,13 @@ async function runTestExpansion(deps, params) {
|
|
|
9591
9630
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
9592
9631
|
if (testPatternDecisions.length > 0) {
|
|
9593
9632
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
9594
|
-
logger$
|
|
9633
|
+
logger$14.debug({
|
|
9595
9634
|
storyKey,
|
|
9596
9635
|
count: testPatternDecisions.length
|
|
9597
9636
|
}, "Loaded test patterns from decision store");
|
|
9598
9637
|
} else {
|
|
9599
9638
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
9600
|
-
logger$
|
|
9639
|
+
logger$14.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
9601
9640
|
}
|
|
9602
9641
|
} catch {
|
|
9603
9642
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
@@ -9612,12 +9651,12 @@ async function runTestExpansion(deps, params) {
|
|
|
9612
9651
|
const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
|
|
9613
9652
|
if (scopedTotal <= TOKEN_CEILING) {
|
|
9614
9653
|
gitDiffContent = scopedDiff;
|
|
9615
|
-
logger$
|
|
9654
|
+
logger$14.debug({
|
|
9616
9655
|
fileCount: filesModified.length,
|
|
9617
9656
|
tokenCount: scopedTotal
|
|
9618
9657
|
}, "Using scoped file diff");
|
|
9619
9658
|
} else {
|
|
9620
|
-
logger$
|
|
9659
|
+
logger$14.warn({
|
|
9621
9660
|
estimatedTotal: scopedTotal,
|
|
9622
9661
|
ceiling: TOKEN_CEILING,
|
|
9623
9662
|
fileCount: filesModified.length
|
|
@@ -9625,7 +9664,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9625
9664
|
gitDiffContent = await getGitDiffStatForFiles(filesModified, cwd);
|
|
9626
9665
|
}
|
|
9627
9666
|
} catch (err) {
|
|
9628
|
-
logger$
|
|
9667
|
+
logger$14.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to get git diff — proceeding with empty diff");
|
|
9629
9668
|
}
|
|
9630
9669
|
const sections = [
|
|
9631
9670
|
{
|
|
@@ -9650,11 +9689,11 @@ async function runTestExpansion(deps, params) {
|
|
|
9650
9689
|
}
|
|
9651
9690
|
];
|
|
9652
9691
|
const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
9653
|
-
if (assembleResult.truncated) logger$
|
|
9692
|
+
if (assembleResult.truncated) logger$14.warn({
|
|
9654
9693
|
storyKey,
|
|
9655
9694
|
tokenCount: assembleResult.tokenCount
|
|
9656
9695
|
}, "Test-expansion prompt truncated to fit token ceiling");
|
|
9657
|
-
logger$
|
|
9696
|
+
logger$14.debug({
|
|
9658
9697
|
storyKey,
|
|
9659
9698
|
tokenCount: assembleResult.tokenCount,
|
|
9660
9699
|
truncated: assembleResult.truncated
|
|
@@ -9674,7 +9713,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9674
9713
|
dispatchResult = await handle.result;
|
|
9675
9714
|
} catch (err) {
|
|
9676
9715
|
const error = err instanceof Error ? err.message : String(err);
|
|
9677
|
-
logger$
|
|
9716
|
+
logger$14.warn({
|
|
9678
9717
|
storyKey,
|
|
9679
9718
|
error
|
|
9680
9719
|
}, "Test-expansion dispatch threw unexpected error");
|
|
@@ -9689,19 +9728,19 @@ async function runTestExpansion(deps, params) {
|
|
|
9689
9728
|
};
|
|
9690
9729
|
if (dispatchResult.status === "failed") {
|
|
9691
9730
|
const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""}`.trim();
|
|
9692
|
-
logger$
|
|
9731
|
+
logger$14.warn({
|
|
9693
9732
|
storyKey,
|
|
9694
9733
|
exitCode: dispatchResult.exitCode
|
|
9695
9734
|
}, "Test-expansion dispatch failed");
|
|
9696
9735
|
return defaultFallbackResult(errorMsg, tokenUsage);
|
|
9697
9736
|
}
|
|
9698
9737
|
if (dispatchResult.status === "timeout") {
|
|
9699
|
-
logger$
|
|
9738
|
+
logger$14.warn({ storyKey }, "Test-expansion dispatch timed out");
|
|
9700
9739
|
return defaultFallbackResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage);
|
|
9701
9740
|
}
|
|
9702
9741
|
if (dispatchResult.parsed === null) {
|
|
9703
9742
|
const details = dispatchResult.parseError ?? "No YAML block found in output";
|
|
9704
|
-
logger$
|
|
9743
|
+
logger$14.warn({
|
|
9705
9744
|
storyKey,
|
|
9706
9745
|
details
|
|
9707
9746
|
}, "Test-expansion output has no parseable YAML");
|
|
@@ -9710,14 +9749,14 @@ async function runTestExpansion(deps, params) {
|
|
|
9710
9749
|
const parseResult = TestExpansionResultSchema.safeParse(dispatchResult.parsed);
|
|
9711
9750
|
if (!parseResult.success) {
|
|
9712
9751
|
const details = parseResult.error.message;
|
|
9713
|
-
logger$
|
|
9752
|
+
logger$14.warn({
|
|
9714
9753
|
storyKey,
|
|
9715
9754
|
details
|
|
9716
9755
|
}, "Test-expansion output failed schema validation");
|
|
9717
9756
|
return defaultFallbackResult(`schema_validation_failed: ${details}`, tokenUsage);
|
|
9718
9757
|
}
|
|
9719
9758
|
const parsed = parseResult.data;
|
|
9720
|
-
logger$
|
|
9759
|
+
logger$14.info({
|
|
9721
9760
|
storyKey,
|
|
9722
9761
|
expansion_priority: parsed.expansion_priority,
|
|
9723
9762
|
coverage_gaps: parsed.coverage_gaps.length,
|
|
@@ -9742,14 +9781,14 @@ async function getArchConstraints(deps) {
|
|
|
9742
9781
|
if (constraints.length === 0) return "";
|
|
9743
9782
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
9744
9783
|
} catch (err) {
|
|
9745
|
-
logger$
|
|
9784
|
+
logger$14.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
9746
9785
|
return "";
|
|
9747
9786
|
}
|
|
9748
9787
|
}
|
|
9749
9788
|
|
|
9750
9789
|
//#endregion
|
|
9751
9790
|
//#region src/modules/compiled-workflows/probe-author.ts
|
|
9752
|
-
const logger$
|
|
9791
|
+
const logger$13 = createLogger("compiled-workflows:probe-author");
|
|
9753
9792
|
/**
|
|
9754
9793
|
* Default initial timeout: 10 min. Override via SUBSTRATE_PROBE_AUTHOR_TIMEOUT_MS (ms).
|
|
9755
9794
|
* Story 65-7: raised from 300 s to 600 s to reduce infra-timeout false negatives.
|
|
@@ -10199,7 +10238,7 @@ function detectConflictGroupsWithContracts(storyKeys, config, declarations) {
|
|
|
10199
10238
|
|
|
10200
10239
|
//#endregion
|
|
10201
10240
|
//#region src/modules/implementation-orchestrator/seed-methodology-context.ts
|
|
10202
|
-
const logger$
|
|
10241
|
+
const logger$12 = createLogger("implementation-orchestrator:seed");
|
|
10203
10242
|
/** Max chars for the architecture summary seeded into decisions */
|
|
10204
10243
|
const MAX_ARCH_CHARS = 6e3;
|
|
10205
10244
|
/** Max chars per epic-shard decision value (per-story or per-epic fallback) */
|
|
@@ -10233,12 +10272,12 @@ async function seedMethodologyContext(db, projectRoot) {
|
|
|
10233
10272
|
const testCount = await seedTestPatterns(db, projectRoot);
|
|
10234
10273
|
if (testCount === -1) result.skippedCategories.push("test-patterns");
|
|
10235
10274
|
else result.decisionsCreated += testCount;
|
|
10236
|
-
logger$
|
|
10275
|
+
logger$12.info({
|
|
10237
10276
|
decisionsCreated: result.decisionsCreated,
|
|
10238
10277
|
skippedCategories: result.skippedCategories
|
|
10239
10278
|
}, "Methodology context seeding complete");
|
|
10240
10279
|
} catch (err) {
|
|
10241
|
-
logger$
|
|
10280
|
+
logger$12.warn({ error: err instanceof Error ? err.message : String(err) }, "Methodology context seeding failed (non-fatal)");
|
|
10242
10281
|
}
|
|
10243
10282
|
return result;
|
|
10244
10283
|
}
|
|
@@ -10282,7 +10321,7 @@ async function seedArchitecture(db, projectRoot) {
|
|
|
10282
10321
|
});
|
|
10283
10322
|
count = 1;
|
|
10284
10323
|
}
|
|
10285
|
-
logger$
|
|
10324
|
+
logger$12.debug({ count }, "Seeded architecture decisions");
|
|
10286
10325
|
return count;
|
|
10287
10326
|
}
|
|
10288
10327
|
/**
|
|
@@ -10306,11 +10345,11 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10306
10345
|
const storedHashDecision = implementationDecisions.find((d) => d.category === "epic-shard-hash" && d.key === "epics-file");
|
|
10307
10346
|
const storedHash = storedHashDecision?.value;
|
|
10308
10347
|
if (storedHash === currentHash) {
|
|
10309
|
-
logger$
|
|
10348
|
+
logger$12.debug({ hash: currentHash }, "Epic shards up-to-date (hash unchanged) — skipping re-seed");
|
|
10310
10349
|
return -1;
|
|
10311
10350
|
}
|
|
10312
10351
|
if (implementationDecisions.some((d) => d.category === "epic-shard")) {
|
|
10313
|
-
logger$
|
|
10352
|
+
logger$12.debug({
|
|
10314
10353
|
storedHash,
|
|
10315
10354
|
currentHash
|
|
10316
10355
|
}, "Epics file changed — deleting stale epic-shard decisions");
|
|
@@ -10322,7 +10361,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10322
10361
|
for (const shard of shards) {
|
|
10323
10362
|
const subsections = parseStorySubsections(shard.epicId, shard.content);
|
|
10324
10363
|
for (const subsection of subsections) {
|
|
10325
|
-
if (subsection.content.length > MAX_EPIC_SHARD_CHARS) logger$
|
|
10364
|
+
if (subsection.content.length > MAX_EPIC_SHARD_CHARS) logger$12.warn({
|
|
10326
10365
|
epicId: shard.epicId,
|
|
10327
10366
|
storyKey: subsection.key,
|
|
10328
10367
|
originalLength: subsection.content.length,
|
|
@@ -10330,7 +10369,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10330
10369
|
droppedChars: subsection.content.length - MAX_EPIC_SHARD_CHARS
|
|
10331
10370
|
}, `Epic shard for ${subsection.key} exceeded ${MAX_EPIC_SHARD_CHARS}-char cap and was truncated; tail content lost from decisions store. Consider splitting the story or raising MAX_EPIC_SHARD_CHARS.`);
|
|
10332
10371
|
if (seenKeys.has(subsection.key)) {
|
|
10333
|
-
logger$
|
|
10372
|
+
logger$12.warn({
|
|
10334
10373
|
epicId: shard.epicId,
|
|
10335
10374
|
storyKey: subsection.key,
|
|
10336
10375
|
droppedContentLength: subsection.content.length
|
|
@@ -10358,7 +10397,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10358
10397
|
value: currentHash,
|
|
10359
10398
|
rationale: "SHA-256 hash of epics file content for change detection"
|
|
10360
10399
|
});
|
|
10361
|
-
logger$
|
|
10400
|
+
logger$12.debug({
|
|
10362
10401
|
count,
|
|
10363
10402
|
hash: currentHash
|
|
10364
10403
|
}, "Seeded epic shard decisions");
|
|
@@ -10382,7 +10421,7 @@ async function seedTestPatterns(db, projectRoot) {
|
|
|
10382
10421
|
value: patterns.slice(0, MAX_TEST_PATTERNS_CHARS),
|
|
10383
10422
|
rationale: "Detected from project configuration at orchestrator startup"
|
|
10384
10423
|
});
|
|
10385
|
-
logger$
|
|
10424
|
+
logger$12.debug("Seeded test patterns decision");
|
|
10386
10425
|
return 1;
|
|
10387
10426
|
}
|
|
10388
10427
|
/**
|
|
@@ -10872,7 +10911,7 @@ function findArtifact(projectRoot, candidates) {
|
|
|
10872
10911
|
|
|
10873
10912
|
//#endregion
|
|
10874
10913
|
//#region src/modules/implementation-orchestrator/package-snapshot.ts
|
|
10875
|
-
const logger$
|
|
10914
|
+
const logger$11 = createLogger("package-snapshot");
|
|
10876
10915
|
/**
|
|
10877
10916
|
* Discover all package.json paths in a workspace monorepo.
|
|
10878
10917
|
* Checks the `workspaces` field in root package.json,
|
|
@@ -10964,7 +11003,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
10964
11003
|
writeFileSync(filePath, content, "utf-8");
|
|
10965
11004
|
filesRestored++;
|
|
10966
11005
|
} catch (err) {
|
|
10967
|
-
logger$
|
|
11006
|
+
logger$11.warn({
|
|
10968
11007
|
filePath,
|
|
10969
11008
|
err
|
|
10970
11009
|
}, "Failed to restore file from snapshot");
|
|
@@ -10975,7 +11014,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
10975
11014
|
encoding: "utf-8",
|
|
10976
11015
|
stdio: "pipe"
|
|
10977
11016
|
});
|
|
10978
|
-
logger$
|
|
11017
|
+
logger$11.info({
|
|
10979
11018
|
filesRestored,
|
|
10980
11019
|
installCommand: snapshot.installCommand
|
|
10981
11020
|
}, "Package snapshot restored successfully");
|
|
@@ -10986,7 +11025,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
10986
11025
|
};
|
|
10987
11026
|
} catch (err) {
|
|
10988
11027
|
const exitCode = err.status ?? 1;
|
|
10989
|
-
logger$
|
|
11028
|
+
logger$11.warn({
|
|
10990
11029
|
filesRestored,
|
|
10991
11030
|
exitCode,
|
|
10992
11031
|
err
|
|
@@ -11335,7 +11374,7 @@ const RecommendationSchema = z.object({
|
|
|
11335
11374
|
|
|
11336
11375
|
//#endregion
|
|
11337
11376
|
//#region src/modules/telemetry/adapter-persistence.ts
|
|
11338
|
-
const logger$
|
|
11377
|
+
const logger$10 = createLogger("telemetry:adapter-persistence");
|
|
11339
11378
|
/**
|
|
11340
11379
|
* Concrete DatabaseAdapter-backed telemetry persistence.
|
|
11341
11380
|
*
|
|
@@ -11389,7 +11428,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11389
11428
|
]);
|
|
11390
11429
|
}
|
|
11391
11430
|
});
|
|
11392
|
-
logger$
|
|
11431
|
+
logger$10.debug({
|
|
11393
11432
|
storyKey,
|
|
11394
11433
|
count: turns.length
|
|
11395
11434
|
}, "Stored turn analysis");
|
|
@@ -11461,7 +11500,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11461
11500
|
score.taskType ?? null,
|
|
11462
11501
|
score.phase ?? null
|
|
11463
11502
|
]);
|
|
11464
|
-
logger$
|
|
11503
|
+
logger$10.debug({
|
|
11465
11504
|
storyKey: score.storyKey,
|
|
11466
11505
|
compositeScore: score.compositeScore
|
|
11467
11506
|
}, "Stored efficiency score");
|
|
@@ -11529,7 +11568,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11529
11568
|
]);
|
|
11530
11569
|
}
|
|
11531
11570
|
});
|
|
11532
|
-
logger$
|
|
11571
|
+
logger$10.debug({
|
|
11533
11572
|
storyKey,
|
|
11534
11573
|
count: recs.length
|
|
11535
11574
|
}, "Saved recommendations");
|
|
@@ -11606,7 +11645,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11606
11645
|
stat$2.trend
|
|
11607
11646
|
]);
|
|
11608
11647
|
});
|
|
11609
|
-
logger$
|
|
11648
|
+
logger$10.debug({
|
|
11610
11649
|
storyKey,
|
|
11611
11650
|
count: stats.length
|
|
11612
11651
|
}, "Stored category stats");
|
|
@@ -11649,7 +11688,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11649
11688
|
JSON.stringify(consumer.topInvocations)
|
|
11650
11689
|
]);
|
|
11651
11690
|
});
|
|
11652
|
-
logger$
|
|
11691
|
+
logger$10.debug({
|
|
11653
11692
|
storyKey,
|
|
11654
11693
|
count: consumers.length
|
|
11655
11694
|
}, "Stored consumer stats");
|
|
@@ -11681,14 +11720,14 @@ var AdapterTelemetryPersistence = class {
|
|
|
11681
11720
|
await adapter.query("DELETE FROM category_stats WHERE story_key = ?", [storyKey]);
|
|
11682
11721
|
await adapter.query("DELETE FROM consumer_stats WHERE story_key = ?", [storyKey]);
|
|
11683
11722
|
});
|
|
11684
|
-
logger$
|
|
11723
|
+
logger$10.debug({ storyKey }, "Purged stale telemetry data for story");
|
|
11685
11724
|
}
|
|
11686
11725
|
/**
|
|
11687
11726
|
* Record a named span with arbitrary attributes.
|
|
11688
11727
|
* Currently logs the span at debug level; no DB persistence.
|
|
11689
11728
|
*/
|
|
11690
11729
|
recordSpan(span) {
|
|
11691
|
-
logger$
|
|
11730
|
+
logger$10.debug({ span }, "recordSpan");
|
|
11692
11731
|
}
|
|
11693
11732
|
};
|
|
11694
11733
|
|
|
@@ -11763,7 +11802,7 @@ var TelemetryPersistence = class {
|
|
|
11763
11802
|
|
|
11764
11803
|
//#endregion
|
|
11765
11804
|
//#region src/modules/telemetry/telemetry-advisor.ts
|
|
11766
|
-
const logger$
|
|
11805
|
+
const logger$9 = createLogger("telemetry-advisor");
|
|
11767
11806
|
/**
|
|
11768
11807
|
* Reads telemetry efficiency data to support retry gate decisions.
|
|
11769
11808
|
*/
|
|
@@ -11785,7 +11824,7 @@ var TelemetryAdvisor = class {
|
|
|
11785
11824
|
try {
|
|
11786
11825
|
const score = await this._persistence.getEfficiencyScore(storyKey);
|
|
11787
11826
|
if (score === null) {
|
|
11788
|
-
logger$
|
|
11827
|
+
logger$9.debug({ storyKey }, "No efficiency score found for story");
|
|
11789
11828
|
return null;
|
|
11790
11829
|
}
|
|
11791
11830
|
return {
|
|
@@ -11800,7 +11839,7 @@ var TelemetryAdvisor = class {
|
|
|
11800
11839
|
coldStartTurnsExcluded: score.coldStartTurnsExcluded ?? 0
|
|
11801
11840
|
};
|
|
11802
11841
|
} catch (err) {
|
|
11803
|
-
logger$
|
|
11842
|
+
logger$9.warn({
|
|
11804
11843
|
err,
|
|
11805
11844
|
storyKey
|
|
11806
11845
|
}, "Failed to retrieve efficiency score");
|
|
@@ -11837,7 +11876,7 @@ var TelemetryAdvisor = class {
|
|
|
11837
11876
|
merged.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));
|
|
11838
11877
|
return merged;
|
|
11839
11878
|
} catch (err) {
|
|
11840
|
-
logger$
|
|
11879
|
+
logger$9.warn({ err }, "Failed to retrieve recommendations for run — returning empty");
|
|
11841
11880
|
return [];
|
|
11842
11881
|
}
|
|
11843
11882
|
}
|
|
@@ -11867,7 +11906,7 @@ var TelemetryAdvisor = class {
|
|
|
11867
11906
|
const lines = actionable.map((r) => `OPTIMIZATION (${r.severity}): ${r.title}. ${r.description}`);
|
|
11868
11907
|
const full = lines.join("\n");
|
|
11869
11908
|
if (full.length <= MAX_CHARS$1) {
|
|
11870
|
-
logger$
|
|
11909
|
+
logger$9.debug({
|
|
11871
11910
|
count: actionable.length,
|
|
11872
11911
|
chars: full.length
|
|
11873
11912
|
}, "Formatting optimization directives");
|
|
@@ -11875,7 +11914,7 @@ var TelemetryAdvisor = class {
|
|
|
11875
11914
|
}
|
|
11876
11915
|
const cutAt = full.lastIndexOf(" ", MAX_CHARS$1);
|
|
11877
11916
|
const truncated = (cutAt > 0 ? full.slice(0, cutAt) : full.slice(0, MAX_CHARS$1)) + "…";
|
|
11878
|
-
logger$
|
|
11917
|
+
logger$9.debug({
|
|
11879
11918
|
count: actionable.length,
|
|
11880
11919
|
chars: truncated.length
|
|
11881
11920
|
}, "Optimization directives truncated to budget");
|
|
@@ -13194,7 +13233,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13194
13233
|
projectRoot,
|
|
13195
13234
|
...config.worktreeCopyFiles !== void 0 ? { copyFiles: config.worktreeCopyFiles } : {}
|
|
13196
13235
|
}) : void 0);
|
|
13197
|
-
const logger$
|
|
13236
|
+
const logger$27 = createLogger("implementation-orchestrator");
|
|
13198
13237
|
const telemetryAdvisor = db !== void 0 ? createTelemetryAdvisor({ db }) : void 0;
|
|
13199
13238
|
const wgRepo = new WorkGraphRepository(db);
|
|
13200
13239
|
const _wgInProgressWritten = new Set();
|
|
@@ -13302,7 +13341,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13302
13341
|
const existingCount = storyState?.retry_count ?? 0;
|
|
13303
13342
|
_storyRetryCount.set(storyKey, existingCount);
|
|
13304
13343
|
} catch (err) {
|
|
13305
|
-
logger$
|
|
13344
|
+
logger$27.warn({
|
|
13306
13345
|
err,
|
|
13307
13346
|
storyKey
|
|
13308
13347
|
}, "initRetryCount: failed to read manifest — starting at 0");
|
|
@@ -13316,7 +13355,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13316
13355
|
const current = _storyRetryCount.get(storyKey) ?? 0;
|
|
13317
13356
|
const next = current + 1;
|
|
13318
13357
|
_storyRetryCount.set(storyKey, next);
|
|
13319
|
-
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$
|
|
13358
|
+
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$27.warn({
|
|
13320
13359
|
err,
|
|
13321
13360
|
storyKey
|
|
13322
13361
|
}, "patchStoryState(retry_count) failed — pipeline continues"));
|
|
@@ -13329,7 +13368,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13329
13368
|
const nowMs = Date.now();
|
|
13330
13369
|
for (const [phase, startMs] of starts) {
|
|
13331
13370
|
const endMs = ends?.get(phase);
|
|
13332
|
-
if (endMs === void 0) logger$
|
|
13371
|
+
if (endMs === void 0) logger$27.warn({
|
|
13333
13372
|
storyKey,
|
|
13334
13373
|
phase
|
|
13335
13374
|
}, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
|
|
@@ -13346,7 +13385,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13346
13385
|
const wallClockSeconds = startedAt ? Math.round((new Date(completedAt).getTime() - new Date(startedAt).getTime()) / 1e3) : 0;
|
|
13347
13386
|
const wallClockMs = startedAt ? new Date(completedAt).getTime() - new Date(startedAt).getTime() : 0;
|
|
13348
13387
|
const tokenAgg = await aggregateTokenUsageForStory(db, config.pipelineRunId, storyKey);
|
|
13349
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$
|
|
13388
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$27.warn({
|
|
13350
13389
|
err,
|
|
13351
13390
|
storyKey
|
|
13352
13391
|
}, "patchStoryState(cost_usd) failed — pipeline continues"));
|
|
@@ -13385,7 +13424,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13385
13424
|
rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
|
|
13386
13425
|
});
|
|
13387
13426
|
} catch (decisionErr) {
|
|
13388
|
-
logger$
|
|
13427
|
+
logger$27.warn({
|
|
13389
13428
|
err: decisionErr,
|
|
13390
13429
|
storyKey
|
|
13391
13430
|
}, "Failed to write story-metrics decision (best-effort)");
|
|
@@ -13464,7 +13503,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13464
13503
|
const LOW_OUTPUT_TOKEN_THRESHOLD = 100;
|
|
13465
13504
|
const unverified = tokenAgg.output < LOW_OUTPUT_TOKEN_THRESHOLD;
|
|
13466
13505
|
if (unverified) {
|
|
13467
|
-
logger$
|
|
13506
|
+
logger$27.warn({
|
|
13468
13507
|
storyKey,
|
|
13469
13508
|
outputTokens: tokenAgg.output,
|
|
13470
13509
|
threshold: LOW_OUTPUT_TOKEN_THRESHOLD
|
|
@@ -13488,13 +13527,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
13488
13527
|
...unverified ? { unverified: true } : {}
|
|
13489
13528
|
});
|
|
13490
13529
|
} catch (emitErr) {
|
|
13491
|
-
logger$
|
|
13530
|
+
logger$27.warn({
|
|
13492
13531
|
err: emitErr,
|
|
13493
13532
|
storyKey
|
|
13494
13533
|
}, "Failed to emit story:metrics event (best-effort)");
|
|
13495
13534
|
}
|
|
13496
13535
|
} catch (err) {
|
|
13497
|
-
logger$
|
|
13536
|
+
logger$27.warn({
|
|
13498
13537
|
err,
|
|
13499
13538
|
storyKey
|
|
13500
13539
|
}, "Failed to write story metrics (best-effort)");
|
|
@@ -13523,7 +13562,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13523
13562
|
rationale: `Story ${storyKey} ${outcome} after ${reviewCycles} review cycle(s).`
|
|
13524
13563
|
});
|
|
13525
13564
|
} catch (err) {
|
|
13526
|
-
logger$
|
|
13565
|
+
logger$27.warn({
|
|
13527
13566
|
err,
|
|
13528
13567
|
storyKey
|
|
13529
13568
|
}, "Failed to write story-outcome decision (best-effort)");
|
|
@@ -13538,15 +13577,15 @@ function createImplementationOrchestrator(deps) {
|
|
|
13538
13577
|
if (escalationWorktree !== void 0) {
|
|
13539
13578
|
const cp = await checkpointStoryWorktree(payload.storyKey, `escalation: ${payload.escalationReason ?? payload.lastVerdict}`, escalationWorktree);
|
|
13540
13579
|
if (cp.status === "committed") {
|
|
13541
|
-
logger$
|
|
13580
|
+
logger$27.info({
|
|
13542
13581
|
storyKey: payload.storyKey,
|
|
13543
13582
|
sha: cp.sha
|
|
13544
13583
|
}, "escalation checkpoint: uncommitted worktree state preserved on story branch");
|
|
13545
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(payload.storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
13584
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(payload.storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$27.warn({
|
|
13546
13585
|
err,
|
|
13547
13586
|
storyKey: payload.storyKey
|
|
13548
13587
|
}, "patchStoryState(checkpoint_sha, escalation) failed — pipeline continues"));
|
|
13549
|
-
} else if (cp.status === "failed") logger$
|
|
13588
|
+
} else if (cp.status === "failed") logger$27.warn({
|
|
13550
13589
|
storyKey: payload.storyKey,
|
|
13551
13590
|
stderr: cp.stderr.slice(0, 500)
|
|
13552
13591
|
}, "escalation checkpoint failed — worktree state remains uncommitted (inspect before any cleanup)");
|
|
@@ -13560,7 +13599,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13560
13599
|
storyKey: payload.storyKey,
|
|
13561
13600
|
msg: leakMsg
|
|
13562
13601
|
});
|
|
13563
|
-
logger$
|
|
13602
|
+
logger$27.warn({
|
|
13564
13603
|
storyKey: payload.storyKey,
|
|
13565
13604
|
leakedFileCount: leakedFiles.length
|
|
13566
13605
|
}, "escalation parent-tree leak detected");
|
|
@@ -13577,7 +13616,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13577
13616
|
runManifest.patchStoryState(payload.storyKey, {
|
|
13578
13617
|
escalation_reason: escalationReason,
|
|
13579
13618
|
...escalationDetail !== void 0 ? { escalation_detail: escalationDetail } : {}
|
|
13580
|
-
}).catch((err) => logger$
|
|
13619
|
+
}).catch((err) => logger$27.warn({
|
|
13581
13620
|
err,
|
|
13582
13621
|
storyKey: payload.storyKey
|
|
13583
13622
|
}, "patchStoryState(escalation_reason/detail) failed — pipeline continues"));
|
|
@@ -13604,7 +13643,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13604
13643
|
rationale: `Escalation diagnosis for ${payload.storyKey}: ${diagnosis.recommendedAction} — ${diagnosis.rationale}`
|
|
13605
13644
|
});
|
|
13606
13645
|
} catch (err) {
|
|
13607
|
-
logger$
|
|
13646
|
+
logger$27.warn({
|
|
13608
13647
|
err,
|
|
13609
13648
|
storyKey: payload.storyKey
|
|
13610
13649
|
}, "Failed to persist escalation diagnosis (best-effort)");
|
|
@@ -13653,7 +13692,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13653
13692
|
...updates
|
|
13654
13693
|
};
|
|
13655
13694
|
const opts = targetStatus === "complete" || targetStatus === "escalated" ? { completedAt: fullUpdated.completedAt } : void 0;
|
|
13656
|
-
wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$
|
|
13695
|
+
wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$27.warn({
|
|
13657
13696
|
err,
|
|
13658
13697
|
storyKey
|
|
13659
13698
|
}, "wg_stories status update failed (best-effort)"));
|
|
@@ -13669,7 +13708,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13669
13708
|
status: "dispatched",
|
|
13670
13709
|
phase: String(updates.phase),
|
|
13671
13710
|
started_at: fullUpdated.startedAt ?? new Date().toISOString()
|
|
13672
|
-
}).catch((err) => logger$
|
|
13711
|
+
}).catch((err) => logger$27.warn({
|
|
13673
13712
|
err,
|
|
13674
13713
|
storyKey
|
|
13675
13714
|
}, "patchStoryState(dispatched) failed — pipeline continues"));
|
|
@@ -13681,13 +13720,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
13681
13720
|
completed_at: fullUpdated.completedAt ?? new Date().toISOString(),
|
|
13682
13721
|
review_cycles: fullUpdated.reviewCycles ?? 0,
|
|
13683
13722
|
dispatches: _storyDispatches.get(storyKey) ?? 0
|
|
13684
|
-
}).catch((err) => logger$
|
|
13723
|
+
}).catch((err) => logger$27.warn({
|
|
13685
13724
|
err,
|
|
13686
13725
|
storyKey
|
|
13687
13726
|
}, `patchStoryState(${manifestStatus}) failed — pipeline continues`));
|
|
13688
13727
|
} else {
|
|
13689
13728
|
const intermediatePhase = updates.phase;
|
|
13690
|
-
runManifest.patchStoryState(storyKey, { phase: String(intermediatePhase) }).catch((err) => logger$
|
|
13729
|
+
runManifest.patchStoryState(storyKey, { phase: String(intermediatePhase) }).catch((err) => logger$27.warn({
|
|
13691
13730
|
err,
|
|
13692
13731
|
storyKey,
|
|
13693
13732
|
phase: intermediatePhase
|
|
@@ -13706,7 +13745,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13706
13745
|
token_usage_json: serialized
|
|
13707
13746
|
});
|
|
13708
13747
|
} catch (err) {
|
|
13709
|
-
logger$
|
|
13748
|
+
logger$27.warn({ err }, "Failed to persist orchestrator state");
|
|
13710
13749
|
}
|
|
13711
13750
|
}
|
|
13712
13751
|
function recordProgress() {
|
|
@@ -13734,7 +13773,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13734
13773
|
if (registryLoad.status !== "ok") return outcomes;
|
|
13735
13774
|
const contractLoad = await loadAcceptanceContractFromTrustedTree(projectRoot, _runStartSha ?? "HEAD");
|
|
13736
13775
|
if (contractLoad.status !== "ok") {
|
|
13737
|
-
logger$
|
|
13776
|
+
logger$27.warn({
|
|
13738
13777
|
storyKey,
|
|
13739
13778
|
status: contractLoad.status
|
|
13740
13779
|
}, "A2.3: no usable acceptance contract — claimed journeys stay unwalked (acceptance-unrunnable at audit)");
|
|
@@ -13767,7 +13806,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13767
13806
|
}
|
|
13768
13807
|
const gamedTargets = [...changed].filter((f$1) => renderTokens.has(f$1) || [...renderTokens].some((t) => t.endsWith("/" + f$1) || f$1.endsWith("/" + t)));
|
|
13769
13808
|
if (gamedTargets.length > 0) {
|
|
13770
|
-
logger$
|
|
13809
|
+
logger$27.warn({
|
|
13771
13810
|
storyKey,
|
|
13772
13811
|
journeyId,
|
|
13773
13812
|
gamedTargets
|
|
@@ -13797,7 +13836,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13797
13836
|
});
|
|
13798
13837
|
if (res.status === "failed") {
|
|
13799
13838
|
renderFailed = true;
|
|
13800
|
-
logger$
|
|
13839
|
+
logger$27.warn({
|
|
13801
13840
|
storyKey,
|
|
13802
13841
|
journeyId,
|
|
13803
13842
|
surface,
|
|
@@ -13834,7 +13873,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13834
13873
|
storyKey,
|
|
13835
13874
|
journeyId
|
|
13836
13875
|
})
|
|
13837
|
-
})).catch((tokenErr) => logger$
|
|
13876
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
13838
13877
|
storyKey,
|
|
13839
13878
|
journeyId,
|
|
13840
13879
|
err: tokenErr
|
|
@@ -13853,7 +13892,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13853
13892
|
excerpt: v.evidence.excerpt
|
|
13854
13893
|
}))
|
|
13855
13894
|
});
|
|
13856
|
-
} else logger$
|
|
13895
|
+
} else logger$27.warn({
|
|
13857
13896
|
storyKey,
|
|
13858
13897
|
journeyId,
|
|
13859
13898
|
error: judge.error,
|
|
@@ -13872,7 +13911,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13872
13911
|
unrunnable: "journey registry is INVALID: " + registryLoad.issues.map((i) => `${i.path}: ${i.message}`).join("; ") + " — fix it (substrate acceptance validate) or the audit cannot run"
|
|
13873
13912
|
};
|
|
13874
13913
|
if (registryLoad.status !== "ok") {
|
|
13875
|
-
logger$
|
|
13914
|
+
logger$27.warn({ detail: registryLoad.message }, "A0.3: journey registry read failed — coverage audit skipped (environmental)");
|
|
13876
13915
|
return void 0;
|
|
13877
13916
|
}
|
|
13878
13917
|
{
|
|
@@ -13886,7 +13925,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13886
13925
|
const staleness = checkRegistryStaleness(registryLoad.registry, sourceContent);
|
|
13887
13926
|
if (staleness.status === "stale" || staleness.status === "source-missing" || staleness.status === "source-escapes-project") {
|
|
13888
13927
|
const scopeLabelStale = "final" in scope ? "final" : `epic-${String(scope.epic)}`;
|
|
13889
|
-
logger$
|
|
13928
|
+
logger$27.warn({
|
|
13890
13929
|
staleness,
|
|
13891
13930
|
scope: scopeLabelStale
|
|
13892
13931
|
}, `RP2.1: registry-stale advisory (${staleness.status}) — the registry's source document diverged from its ratification baseline; re-run \`substrate acceptance derive\` and review the diff`);
|
|
@@ -13906,9 +13945,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
13906
13945
|
const contractLoad = await loadAcceptanceContractFromTrustedTree(projectRoot, _runStartSha ?? "HEAD");
|
|
13907
13946
|
if (contractLoad.status === "absent") unrunnable = `journey registry exists but the committed project profile has no acceptance: contract block (${ACCEPTANCE_CONTRACT_PROFILE_PATH}) — claimed journeys can never be walked. Declare render commands per surface.`;
|
|
13908
13947
|
else if (contractLoad.status === "invalid") unrunnable = "acceptance: contract block is INVALID: " + contractLoad.issues.map((i) => `${i.path}: ${i.message}`).join("; ");
|
|
13909
|
-
else if (contractLoad.status === "error") logger$
|
|
13948
|
+
else if (contractLoad.status === "error") logger$27.warn({ detail: contractLoad.message }, "A1.1: acceptance contract read failed (environmental) — treating as absent for this audit");
|
|
13910
13949
|
const deferralsLoad = await loadJourneyDeferralsFromTrustedTree(projectRoot, _runStartSha ?? "HEAD");
|
|
13911
|
-
if (deferralsLoad.status !== "ok") logger$
|
|
13950
|
+
if (deferralsLoad.status !== "ok") logger$27.warn({ detail: deferralsLoad.status === "invalid" ? deferralsLoad.issues : deferralsLoad.message }, `A0.3: ${JOURNEY_DEFERRALS_PATH} unreadable/invalid — treating as no deferrals`);
|
|
13912
13951
|
const deferredJourneyIds = deferralsLoad.status === "ok" ? deferralsLoad.deferrals.map((d) => d.journey) : [];
|
|
13913
13952
|
const claims = [];
|
|
13914
13953
|
for (const [key, st] of _stories.entries()) for (const journeyId of st.journeys ?? []) claims.push({
|
|
@@ -13933,7 +13972,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13933
13972
|
entries,
|
|
13934
13973
|
summary: summarizeCoverage(entries)
|
|
13935
13974
|
});
|
|
13936
|
-
if (unrunnable !== void 0) logger$
|
|
13975
|
+
if (unrunnable !== void 0) logger$27.warn({ scope: scopeLabel }, `A1.1: acceptance gate unrunnable — ${unrunnable}`);
|
|
13937
13976
|
if (opts?.persist === true) {
|
|
13938
13977
|
const entriesWithVerdicts = entries.map((e) => {
|
|
13939
13978
|
const vs = _journeyVerdicts.get(e.journeyId);
|
|
@@ -13965,13 +14004,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
13965
14004
|
mkdirSync(dirname$1(reportPath), { recursive: true });
|
|
13966
14005
|
writeFileSync(reportPath, html, "utf-8");
|
|
13967
14006
|
} catch (err) {
|
|
13968
|
-
logger$
|
|
14007
|
+
logger$27.warn({ err }, "A2.2: verdict artifact write failed (best-effort)");
|
|
13969
14008
|
reportPath = void 0;
|
|
13970
14009
|
}
|
|
13971
14010
|
if (runManifest !== null) await runManifest.update({
|
|
13972
14011
|
journeys: entriesWithVerdicts,
|
|
13973
14012
|
...reportPath !== void 0 ? { acceptance_report_path: reportPath } : {}
|
|
13974
|
-
}).catch((err) => logger$
|
|
14013
|
+
}).catch((err) => logger$27.warn({ err }, "A0.3: manifest journeys ledger write failed — pipeline continues"));
|
|
13975
14014
|
}
|
|
13976
14015
|
return unrunnable !== void 0 ? {
|
|
13977
14016
|
entries,
|
|
@@ -14019,7 +14058,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14019
14058
|
...Object.keys(perStoryState).length > 0 ? { perStoryState } : {}
|
|
14020
14059
|
});
|
|
14021
14060
|
if (config.pipelineRunId !== void 0) updatePipelineRun(db, config.pipelineRunId, { current_phase: "implementation" }).catch((err) => {
|
|
14022
|
-
logger$
|
|
14061
|
+
logger$27.debug({ err }, "Heartbeat: failed to touch updated_at (non-fatal)");
|
|
14023
14062
|
});
|
|
14024
14063
|
const elapsed = Date.now() - _lastProgressTs;
|
|
14025
14064
|
let childPids = [];
|
|
@@ -14041,7 +14080,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14041
14080
|
}
|
|
14042
14081
|
if (childActive) {
|
|
14043
14082
|
_lastProgressTs = Date.now();
|
|
14044
|
-
logger$
|
|
14083
|
+
logger$27.debug({
|
|
14045
14084
|
storyKey: key,
|
|
14046
14085
|
phase: s$1.phase,
|
|
14047
14086
|
childPids
|
|
@@ -14050,7 +14089,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14050
14089
|
}
|
|
14051
14090
|
_stalledStories.add(key);
|
|
14052
14091
|
_storiesWithStall.add(key);
|
|
14053
|
-
logger$
|
|
14092
|
+
logger$27.warn({
|
|
14054
14093
|
storyKey: key,
|
|
14055
14094
|
phase: s$1.phase,
|
|
14056
14095
|
elapsedMs: elapsed,
|
|
@@ -14095,7 +14134,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14095
14134
|
for (let attempt = 0; attempt < MEMORY_PRESSURE_BACKOFF_MS.length; attempt++) {
|
|
14096
14135
|
const memState = dispatcher.getMemoryState();
|
|
14097
14136
|
if (!memState.isPressured) return true;
|
|
14098
|
-
logger$
|
|
14137
|
+
logger$27.warn({
|
|
14099
14138
|
storyKey,
|
|
14100
14139
|
freeMB: memState.freeMB,
|
|
14101
14140
|
thresholdMB: memState.thresholdMB,
|
|
@@ -14115,12 +14154,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
14115
14154
|
* exhausted retries the story is ESCALATED.
|
|
14116
14155
|
*/
|
|
14117
14156
|
async function processStory(storyKey, storyOptions) {
|
|
14118
|
-
logger$
|
|
14157
|
+
logger$27.info({ storyKey }, "Processing story");
|
|
14119
14158
|
await initRetryCount(storyKey);
|
|
14120
14159
|
{
|
|
14121
14160
|
const memoryOk = await checkMemoryPressure(storyKey);
|
|
14122
14161
|
if (!memoryOk) {
|
|
14123
|
-
logger$
|
|
14162
|
+
logger$27.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
|
|
14124
14163
|
const memPressureState = {
|
|
14125
14164
|
phase: "ESCALATED",
|
|
14126
14165
|
reviewCycles: 0,
|
|
@@ -14164,7 +14203,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14164
14203
|
if (match$2) {
|
|
14165
14204
|
const candidatePath = join$1(artifactsDir, match$2);
|
|
14166
14205
|
const validation = await isValidStoryFile(candidatePath);
|
|
14167
|
-
if (!validation.valid) logger$
|
|
14206
|
+
if (!validation.valid) logger$27.warn({
|
|
14168
14207
|
storyKey,
|
|
14169
14208
|
storyFilePath: candidatePath,
|
|
14170
14209
|
reason: validation.reason
|
|
@@ -14189,7 +14228,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14189
14228
|
storedHash,
|
|
14190
14229
|
currentHash
|
|
14191
14230
|
});
|
|
14192
|
-
logger$
|
|
14231
|
+
logger$27.info({
|
|
14193
14232
|
storyKey,
|
|
14194
14233
|
storedHash,
|
|
14195
14234
|
currentHash
|
|
@@ -14200,7 +14239,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14200
14239
|
} catch {}
|
|
14201
14240
|
if (!isDrift) {
|
|
14202
14241
|
storyFilePath = candidatePath;
|
|
14203
|
-
logger$
|
|
14242
|
+
logger$27.info({
|
|
14204
14243
|
storyKey,
|
|
14205
14244
|
storyFilePath
|
|
14206
14245
|
}, "Found existing story file — skipping create-story");
|
|
@@ -14225,12 +14264,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
14225
14264
|
const staleName = match$2.replace(/\.md$/, `.stale-${ts}.md`);
|
|
14226
14265
|
const stalePath = join$1(artifactsDir, staleName);
|
|
14227
14266
|
renameSync(candidatePath, stalePath);
|
|
14228
|
-
logger$
|
|
14267
|
+
logger$27.info({
|
|
14229
14268
|
storyKey,
|
|
14230
14269
|
staleName
|
|
14231
14270
|
}, `[orchestrator] story ${storyKey}: renamed drifted artifact to ${staleName} before re-dispatch`);
|
|
14232
14271
|
} catch (renameErr) {
|
|
14233
|
-
logger$
|
|
14272
|
+
logger$27.warn({
|
|
14234
14273
|
storyKey,
|
|
14235
14274
|
err: renameErr
|
|
14236
14275
|
}, "Failed to rename stale artifact before create-story re-dispatch; relying on 58-9d fraud-guard");
|
|
@@ -14239,7 +14278,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14239
14278
|
}
|
|
14240
14279
|
} catch {}
|
|
14241
14280
|
if (storyFilePath === void 0 && effectiveProjectRoot && isImplicitlyCovered(storyKey, effectiveProjectRoot)) {
|
|
14242
|
-
logger$
|
|
14281
|
+
logger$27.info({ storyKey }, `Story ${storyKey} appears implicitly covered — all expected new files already exist. Skipping create-story.`);
|
|
14243
14282
|
endPhase(storyKey, "create-story");
|
|
14244
14283
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
14245
14284
|
storyKey,
|
|
@@ -14294,7 +14333,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14294
14333
|
output_tokens: createResult.tokenUsage.output,
|
|
14295
14334
|
cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
|
|
14296
14335
|
metadata: JSON.stringify({ storyKey })
|
|
14297
|
-
})).catch((tokenErr) => logger$
|
|
14336
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
14298
14337
|
storyKey,
|
|
14299
14338
|
err: tokenErr
|
|
14300
14339
|
}, "Failed to record create-story token usage"));
|
|
@@ -14302,7 +14341,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14302
14341
|
if (createResult.result === "failed") {
|
|
14303
14342
|
const errMsg = createResult.error ?? "create-story failed";
|
|
14304
14343
|
const stderrSnippet = errMsg.includes("--- stderr ---") ? errMsg.slice(errMsg.indexOf("--- stderr ---") + 15, errMsg.indexOf("--- stderr ---") + 515) : errMsg.slice(0, 500);
|
|
14305
|
-
logger$
|
|
14344
|
+
logger$27.error({
|
|
14306
14345
|
storyKey,
|
|
14307
14346
|
stderrSnippet
|
|
14308
14347
|
}, `Create-story failed: ${stderrSnippet.split("\n")[0]}`);
|
|
@@ -14373,7 +14412,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14373
14412
|
const outsideWorktree = relToWorktree.startsWith("..") || isAbsolute(relToWorktree);
|
|
14374
14413
|
if (outsideWorktree) {
|
|
14375
14414
|
const errMsg = `create-story wrote its artifact OUTSIDE the story worktree: ${createResult.story_file} (resolved: ${resolvedStoryFile}) (worktree: ${effectiveProjectRoot}). The agent escaped its working directory — this is the parent/home-directory write-leak class (field finding #15). The stray file was NOT adopted; inspect and remove it.`;
|
|
14376
|
-
logger$
|
|
14415
|
+
logger$27.error({
|
|
14377
14416
|
storyKey,
|
|
14378
14417
|
storyFile: createResult.story_file,
|
|
14379
14418
|
worktree: effectiveProjectRoot
|
|
@@ -14401,7 +14440,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14401
14440
|
let claimedPath = createResult.story_file;
|
|
14402
14441
|
if (claimedPath.startsWith(escapedExpectedDir)) {
|
|
14403
14442
|
claimedPath = claimedPath.replace("/\\_bmad-output/", "/_bmad-output/");
|
|
14404
|
-
logger$
|
|
14443
|
+
logger$27.warn({
|
|
14405
14444
|
storyKey,
|
|
14406
14445
|
originalClaim: createResult.story_file,
|
|
14407
14446
|
normalizedClaim: claimedPath
|
|
@@ -14419,7 +14458,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14419
14458
|
if (escapedVariant !== claimedPath && existsSync(escapedVariant)) try {
|
|
14420
14459
|
renameSync(escapedVariant, claimedPath);
|
|
14421
14460
|
actualPath = claimedPath;
|
|
14422
|
-
logger$
|
|
14461
|
+
logger$27.warn({
|
|
14423
14462
|
storyKey,
|
|
14424
14463
|
escapedVariant,
|
|
14425
14464
|
canonicalPath: claimedPath
|
|
@@ -14430,7 +14469,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14430
14469
|
});
|
|
14431
14470
|
} catch (renameErr) {
|
|
14432
14471
|
actualPath = escapedVariant;
|
|
14433
|
-
logger$
|
|
14472
|
+
logger$27.warn({
|
|
14434
14473
|
storyKey,
|
|
14435
14474
|
escapedVariant,
|
|
14436
14475
|
canonicalPath: claimedPath,
|
|
@@ -14445,7 +14484,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14445
14484
|
if (actualPath === null) {
|
|
14446
14485
|
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
14447
14486
|
const errMsg = `create-story claimed success (story_file: ${createResult.story_file}) but the file does not exist on disk (output tokens: ${outputTokens})`;
|
|
14448
|
-
logger$
|
|
14487
|
+
logger$27.error({
|
|
14449
14488
|
storyKey,
|
|
14450
14489
|
claimedPath: createResult.story_file,
|
|
14451
14490
|
outputTokens
|
|
@@ -14473,7 +14512,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14473
14512
|
const mtimeISO = new Date(claimedStat.mtimeMs).toISOString();
|
|
14474
14513
|
const dispatchStartISO = new Date(dispatchStartMs).toISOString();
|
|
14475
14514
|
const errMsg = `create-story claimed success but did not rewrite ${actualPath} during this dispatch (file mtime ${mtimeISO} predates dispatch start ${dispatchStartISO}; output tokens: ${outputTokens})`;
|
|
14476
|
-
logger$
|
|
14515
|
+
logger$27.error({
|
|
14477
14516
|
storyKey,
|
|
14478
14517
|
claimedPath: actualPath,
|
|
14479
14518
|
mtimeISO,
|
|
@@ -14496,7 +14535,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14496
14535
|
return;
|
|
14497
14536
|
}
|
|
14498
14537
|
} catch (verifyErr) {
|
|
14499
|
-
logger$
|
|
14538
|
+
logger$27.warn({
|
|
14500
14539
|
storyKey,
|
|
14501
14540
|
err: verifyErr
|
|
14502
14541
|
}, "create-story post-dispatch file verification threw; proceeding with claimed path");
|
|
@@ -14505,7 +14544,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14505
14544
|
storyFilePath = createResult.story_file;
|
|
14506
14545
|
if (createResult.journeys !== void 0 && createResult.journeys.length > 0) {
|
|
14507
14546
|
updateStory(storyKey, { journeys: createResult.journeys });
|
|
14508
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { journeys: createResult.journeys }).catch((err) => logger$
|
|
14547
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { journeys: createResult.journeys }).catch((err) => logger$27.warn({
|
|
14509
14548
|
err,
|
|
14510
14549
|
storyKey
|
|
14511
14550
|
}, "A0.3: patchStoryState(journeys) failed — pipeline continues"));
|
|
@@ -14527,7 +14566,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14527
14566
|
const overlap = computeTitleOverlap(expectedTitle, createResult.story_title);
|
|
14528
14567
|
if (overlap < TITLE_OVERLAP_WARNING_THRESHOLD) {
|
|
14529
14568
|
const msg = `Story title mismatch: expected "${expectedTitle}" but got "${createResult.story_title}" (word overlap: ${Math.round(overlap * 100)}%). This may indicate the create-story agent received truncated context.`;
|
|
14530
|
-
logger$
|
|
14569
|
+
logger$27.warn({
|
|
14531
14570
|
storyKey,
|
|
14532
14571
|
expectedTitle,
|
|
14533
14572
|
generatedTitle: createResult.story_title,
|
|
@@ -14537,7 +14576,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14537
14576
|
storyKey,
|
|
14538
14577
|
msg
|
|
14539
14578
|
});
|
|
14540
|
-
} else logger$
|
|
14579
|
+
} else logger$27.debug({
|
|
14541
14580
|
storyKey,
|
|
14542
14581
|
expectedTitle,
|
|
14543
14582
|
generatedTitle: createResult.story_title,
|
|
@@ -14546,7 +14585,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14546
14585
|
}
|
|
14547
14586
|
}
|
|
14548
14587
|
} catch (titleValidationErr) {
|
|
14549
|
-
logger$
|
|
14588
|
+
logger$27.debug({
|
|
14550
14589
|
storyKey,
|
|
14551
14590
|
err: titleValidationErr
|
|
14552
14591
|
}, "Story title validation skipped due to error");
|
|
@@ -14587,7 +14626,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14587
14626
|
const pathDrift = pathFidelity?.drift ?? 0;
|
|
14588
14627
|
const clauseDrift = clauseFidelity.drift;
|
|
14589
14628
|
const overallDrift = Math.max(pathDrift, clauseDrift);
|
|
14590
|
-
logger$
|
|
14629
|
+
logger$27.debug({
|
|
14591
14630
|
storyKey,
|
|
14592
14631
|
pathDrift,
|
|
14593
14632
|
clauseDrift,
|
|
@@ -14609,7 +14648,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14609
14648
|
if (pathMissing.length > 0) reasons.push(`${pathMissing.length} named path(s) missing`);
|
|
14610
14649
|
if (numericMismatches.length > 0) reasons.push(`${numericMismatches.length} numeric quantifier mismatch(es) (e.g., "${numericMismatches[0].noun}" source=${numericMismatches[0].sourceCount} rendered=${numericMismatches[0].renderedCount})`);
|
|
14611
14650
|
if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall (rendered ${clauseFidelity.renderedClauseCount}/${clauseFidelity.sourceClauseCount} = ${Math.round(clauseFidelity.clauseRatio * 100)}%)`);
|
|
14612
|
-
logger$
|
|
14651
|
+
logger$27.warn({
|
|
14613
14652
|
storyKey,
|
|
14614
14653
|
pathDrift,
|
|
14615
14654
|
clauseDrift,
|
|
@@ -14652,7 +14691,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14652
14691
|
storyFilePath = void 0;
|
|
14653
14692
|
continue;
|
|
14654
14693
|
} catch (renameErr) {
|
|
14655
|
-
logger$
|
|
14694
|
+
logger$27.warn({
|
|
14656
14695
|
storyKey,
|
|
14657
14696
|
err: renameErr,
|
|
14658
14697
|
stalePath
|
|
@@ -14666,7 +14705,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14666
14705
|
if (numericMismatches.length > 0) reasons.push(`numeric mismatches: ${numericMismatches.map((m) => `${m.noun} (source=${m.sourceCount}, rendered=${m.renderedCount})`).join("; ")}`);
|
|
14667
14706
|
if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall: source=${clauseFidelity.sourceClauseCount}, rendered=${clauseFidelity.renderedClauseCount}`);
|
|
14668
14707
|
const errMsg = `create-story output drifted from source AC after ${MAX_FIDELITY_RETRIES} retries; ` + reasons.join("; ");
|
|
14669
|
-
logger$
|
|
14708
|
+
logger$27.error({
|
|
14670
14709
|
storyKey,
|
|
14671
14710
|
pathDrift,
|
|
14672
14711
|
clauseDrift,
|
|
@@ -14693,7 +14732,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14693
14732
|
}
|
|
14694
14733
|
}
|
|
14695
14734
|
} catch (fidelityErr) {
|
|
14696
|
-
logger$
|
|
14735
|
+
logger$27.warn({
|
|
14697
14736
|
storyKey,
|
|
14698
14737
|
err: fidelityErr
|
|
14699
14738
|
}, "fidelity gate threw; proceeding without retry");
|
|
@@ -14705,7 +14744,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14705
14744
|
probeRetries++;
|
|
14706
14745
|
const stalePath = storyFilePath.replace(/\.md$/, `.stale-probe-${Date.now()}.md`);
|
|
14707
14746
|
renameSync(storyFilePath, stalePath);
|
|
14708
|
-
logger$
|
|
14747
|
+
logger$27.warn({
|
|
14709
14748
|
storyKey,
|
|
14710
14749
|
error: probeParse.error,
|
|
14711
14750
|
retries: probeRetries,
|
|
@@ -14730,7 +14769,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14730
14769
|
continue;
|
|
14731
14770
|
}
|
|
14732
14771
|
} catch (probeGateErr) {
|
|
14733
|
-
logger$
|
|
14772
|
+
logger$27.warn({
|
|
14734
14773
|
storyKey,
|
|
14735
14774
|
err: probeGateErr
|
|
14736
14775
|
}, "probe-validity gate threw; proceeding without retry (verification backstop)");
|
|
@@ -14753,14 +14792,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
14753
14792
|
...contract.transport !== void 0 ? { transport: contract.transport } : {}
|
|
14754
14793
|
})
|
|
14755
14794
|
});
|
|
14756
|
-
logger$
|
|
14795
|
+
logger$27.info({
|
|
14757
14796
|
storyKey,
|
|
14758
14797
|
contractCount: contracts.length,
|
|
14759
14798
|
contracts
|
|
14760
14799
|
}, "Stored interface contract declarations");
|
|
14761
14800
|
}
|
|
14762
14801
|
} catch (err) {
|
|
14763
|
-
logger$
|
|
14802
|
+
logger$27.warn({
|
|
14764
14803
|
storyKey,
|
|
14765
14804
|
error: err instanceof Error ? err.message : String(err)
|
|
14766
14805
|
}, "Failed to parse interface contracts — continuing without contract declarations");
|
|
@@ -14778,7 +14817,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14778
14817
|
const isStateIntegrating = stateIntegratingEnabled && detectsStateIntegratingAC(probeAuthorEpicContent);
|
|
14779
14818
|
if (isEventDriven || isStateIntegrating) {
|
|
14780
14819
|
const triggerClass = isEventDriven && isStateIntegrating ? "both" : isStateIntegrating ? "state-integrating" : "event-driven";
|
|
14781
|
-
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { probe_author_triggered_by: triggerClass }).catch((err) => logger$
|
|
14820
|
+
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { probe_author_triggered_by: triggerClass }).catch((err) => logger$27.warn({
|
|
14782
14821
|
err,
|
|
14783
14822
|
storyKey
|
|
14784
14823
|
}, "patchStoryState(probe_author_triggered_by) failed — pipeline continues"));
|
|
@@ -14813,7 +14852,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14813
14852
|
});
|
|
14814
14853
|
}
|
|
14815
14854
|
});
|
|
14816
|
-
logger$
|
|
14855
|
+
logger$27.info({
|
|
14817
14856
|
storyKey,
|
|
14818
14857
|
result: probeAuthorResult.result,
|
|
14819
14858
|
probesAuthoredCount: probeAuthorResult.probesAuthoredCount
|
|
@@ -14825,14 +14864,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
14825
14864
|
output_tokens: probeAuthorResult.tokenUsage.output,
|
|
14826
14865
|
cost_usd: estimateDispatchCost(probeAuthorResult.tokenUsage.input, probeAuthorResult.tokenUsage.output),
|
|
14827
14866
|
metadata: JSON.stringify({ storyKey })
|
|
14828
|
-
})).catch((tokenErr) => logger$
|
|
14867
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
14829
14868
|
storyKey,
|
|
14830
14869
|
err: tokenErr
|
|
14831
14870
|
}, "Failed to record probe-author token usage"));
|
|
14832
|
-
} else logger$
|
|
14833
|
-
} else logger$
|
|
14871
|
+
} else logger$27.debug({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping gate");
|
|
14872
|
+
} else logger$27.debug({ storyKey }, "probe-author: source AC not event-driven — skipping gate");
|
|
14834
14873
|
} catch (probeAuthorErr) {
|
|
14835
|
-
logger$
|
|
14874
|
+
logger$27.warn({
|
|
14836
14875
|
storyKey,
|
|
14837
14876
|
err: probeAuthorErr
|
|
14838
14877
|
}, "probe-author gate threw unexpectedly; proceeding to test-plan without authored probes");
|
|
@@ -14862,10 +14901,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
14862
14901
|
});
|
|
14863
14902
|
testPlanPhaseResult = testPlanResult.result;
|
|
14864
14903
|
testPlanTokenUsage = testPlanResult.tokenUsage;
|
|
14865
|
-
if (testPlanResult.result === "success") logger$
|
|
14866
|
-
else logger$
|
|
14904
|
+
if (testPlanResult.result === "success") logger$27.info({ storyKey }, "Test plan generated successfully");
|
|
14905
|
+
else logger$27.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
|
|
14867
14906
|
} catch (err) {
|
|
14868
|
-
logger$
|
|
14907
|
+
logger$27.warn({
|
|
14869
14908
|
storyKey,
|
|
14870
14909
|
err
|
|
14871
14910
|
}, "Test planning failed — proceeding to dev-story without test plan");
|
|
@@ -14878,7 +14917,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14878
14917
|
output_tokens: testPlanTokenUsage.output,
|
|
14879
14918
|
cost_usd: estimateDispatchCost(testPlanTokenUsage.input, testPlanTokenUsage.output),
|
|
14880
14919
|
metadata: JSON.stringify({ storyKey })
|
|
14881
|
-
})).catch((tokenErr) => logger$
|
|
14920
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
14882
14921
|
storyKey,
|
|
14883
14922
|
err: tokenErr
|
|
14884
14923
|
}, "Failed to record test-plan token usage"));
|
|
@@ -14941,7 +14980,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14941
14980
|
]
|
|
14942
14981
|
}).trim();
|
|
14943
14982
|
} catch {}
|
|
14944
|
-
if (baselineHeadSha !== void 0 && runManifest !== null) runManifest.patchStoryState(storyKey, { baseline_sha: baselineHeadSha }).catch((err) => logger$
|
|
14983
|
+
if (baselineHeadSha !== void 0 && runManifest !== null) runManifest.patchStoryState(storyKey, { baseline_sha: baselineHeadSha }).catch((err) => logger$27.warn({
|
|
14945
14984
|
err,
|
|
14946
14985
|
storyKey
|
|
14947
14986
|
}, "patchStoryState(baseline_sha) failed — pipeline continues"));
|
|
@@ -14951,7 +14990,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14951
14990
|
storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
|
|
14952
14991
|
storyContentForVerification = storyContentForAnalysis;
|
|
14953
14992
|
} catch (err) {
|
|
14954
|
-
logger$
|
|
14993
|
+
logger$27.error({
|
|
14955
14994
|
storyKey,
|
|
14956
14995
|
storyFilePath,
|
|
14957
14996
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -14959,7 +14998,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14959
14998
|
}
|
|
14960
14999
|
const analysis = analyzeStoryComplexity(storyContentForAnalysis);
|
|
14961
15000
|
const batches = planTaskBatches(analysis);
|
|
14962
|
-
logger$
|
|
15001
|
+
logger$27.info({
|
|
14963
15002
|
storyKey,
|
|
14964
15003
|
estimatedScope: analysis.estimatedScope,
|
|
14965
15004
|
batchCount: batches.length,
|
|
@@ -14977,7 +15016,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14977
15016
|
if (_state !== "RUNNING") break;
|
|
14978
15017
|
const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
|
|
14979
15018
|
const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
|
|
14980
|
-
logger$
|
|
15019
|
+
logger$27.info({
|
|
14981
15020
|
storyKey,
|
|
14982
15021
|
batchIndex: batch.batchIndex,
|
|
14983
15022
|
taskCount: batch.taskIds.length
|
|
@@ -15009,7 +15048,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15009
15048
|
});
|
|
15010
15049
|
} catch (batchErr) {
|
|
15011
15050
|
const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
|
|
15012
|
-
logger$
|
|
15051
|
+
logger$27.warn({
|
|
15013
15052
|
storyKey,
|
|
15014
15053
|
batchIndex: batch.batchIndex,
|
|
15015
15054
|
error: errMsg
|
|
@@ -15031,7 +15070,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15031
15070
|
filesModified: batchFilesModified,
|
|
15032
15071
|
result: batchResult.result === "success" ? "success" : "failed"
|
|
15033
15072
|
};
|
|
15034
|
-
logger$
|
|
15073
|
+
logger$27.info(batchMetrics, "Batch dev-story metrics");
|
|
15035
15074
|
for (const f$1 of batchFilesModified) allFilesModified.add(f$1);
|
|
15036
15075
|
if (batchFilesModified.length > 0) batchFileGroups.push({
|
|
15037
15076
|
batchIndex: batch.batchIndex,
|
|
@@ -15050,13 +15089,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
15050
15089
|
durationMs: batchDurationMs,
|
|
15051
15090
|
result: batchMetrics.result
|
|
15052
15091
|
})
|
|
15053
|
-
})).catch((tokenErr) => logger$
|
|
15092
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
15054
15093
|
storyKey,
|
|
15055
15094
|
batchIndex: batch.batchIndex,
|
|
15056
15095
|
err: tokenErr
|
|
15057
15096
|
}, "Failed to record batch token usage"));
|
|
15058
15097
|
if (batchResult.tokenUsage?.output !== void 0) devOutputTokenCount = (devOutputTokenCount ?? 0) + batchResult.tokenUsage.output;
|
|
15059
|
-
if (batchResult.result === "failed") logger$
|
|
15098
|
+
if (batchResult.result === "failed") logger$27.warn({
|
|
15060
15099
|
storyKey,
|
|
15061
15100
|
batchIndex: batch.batchIndex,
|
|
15062
15101
|
error: batchResult.error
|
|
@@ -15101,7 +15140,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15101
15140
|
output_tokens: devResult.tokenUsage.output,
|
|
15102
15141
|
cost_usd: estimateDispatchCost(devResult.tokenUsage.input, devResult.tokenUsage.output),
|
|
15103
15142
|
metadata: JSON.stringify({ storyKey })
|
|
15104
|
-
})).catch((tokenErr) => logger$
|
|
15143
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
15105
15144
|
storyKey,
|
|
15106
15145
|
err: tokenErr
|
|
15107
15146
|
}, "Failed to record dev-story token usage"));
|
|
@@ -15116,7 +15155,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15116
15155
|
endPhase(storyKey, "dev-story", devStoryModel);
|
|
15117
15156
|
const timeoutFiles = checkGitDiffFiles(effectiveProjectRoot ?? process.cwd());
|
|
15118
15157
|
if (timeoutFiles.length === 0) {
|
|
15119
|
-
logger$
|
|
15158
|
+
logger$27.warn({ storyKey }, "Dev-story timeout with zero modified files — escalating immediately (no checkpoint)");
|
|
15120
15159
|
updateStory(storyKey, {
|
|
15121
15160
|
phase: "ESCALATED",
|
|
15122
15161
|
error: "timeout-no-files",
|
|
@@ -15132,7 +15171,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15132
15171
|
await persistState();
|
|
15133
15172
|
return;
|
|
15134
15173
|
}
|
|
15135
|
-
logger$
|
|
15174
|
+
logger$27.info({
|
|
15136
15175
|
storyKey,
|
|
15137
15176
|
filesCount: timeoutFiles.length
|
|
15138
15177
|
}, "Dev-story timeout with partial files — capturing checkpoint");
|
|
@@ -15149,7 +15188,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15149
15188
|
]
|
|
15150
15189
|
}).trim();
|
|
15151
15190
|
} catch (diffErr) {
|
|
15152
|
-
logger$
|
|
15191
|
+
logger$27.warn({
|
|
15153
15192
|
storyKey,
|
|
15154
15193
|
error: diffErr instanceof Error ? diffErr.message : String(diffErr)
|
|
15155
15194
|
}, "Failed to capture git diff for checkpoint — proceeding with empty diff");
|
|
@@ -15223,9 +15262,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
15223
15262
|
checkpointRetryPrompt = assembled.prompt;
|
|
15224
15263
|
} catch {
|
|
15225
15264
|
checkpointRetryPrompt = `Continue story ${storyKey} from checkpoint. Your prior attempt timed out. Do not redo completed work.`;
|
|
15226
|
-
logger$
|
|
15265
|
+
logger$27.warn({ storyKey }, "Failed to assemble checkpoint retry prompt — using fallback");
|
|
15227
15266
|
}
|
|
15228
|
-
logger$
|
|
15267
|
+
logger$27.info({
|
|
15229
15268
|
storyKey,
|
|
15230
15269
|
filesCount: checkpointData.filesModified.length
|
|
15231
15270
|
}, "Dispatching checkpoint retry for timed-out story");
|
|
@@ -15255,7 +15294,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15255
15294
|
outcome: checkpointRetryResult.status === "timeout" ? "escalated" : "retried",
|
|
15256
15295
|
cost_usd: 0,
|
|
15257
15296
|
timestamp: new Date().toISOString()
|
|
15258
|
-
}).catch((err) => logger$
|
|
15297
|
+
}).catch((err) => logger$27.warn({
|
|
15259
15298
|
err,
|
|
15260
15299
|
storyKey
|
|
15261
15300
|
}, "appendRecoveryEntry(checkpoint-retry) failed — pipeline continues"));
|
|
@@ -15268,7 +15307,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15268
15307
|
} : void 0 }
|
|
15269
15308
|
});
|
|
15270
15309
|
if (checkpointRetryResult.status === "timeout") {
|
|
15271
|
-
logger$
|
|
15310
|
+
logger$27.warn({ storyKey }, "Checkpoint retry dispatch timed out — escalating story");
|
|
15272
15311
|
updateStory(storyKey, {
|
|
15273
15312
|
phase: "ESCALATED",
|
|
15274
15313
|
error: "checkpoint-retry-timeout",
|
|
@@ -15288,7 +15327,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15288
15327
|
replaceDevStorySignals(retryParsed);
|
|
15289
15328
|
devFilesModified = retryParsed?.files_modified ?? checkGitDiffFiles(effectiveProjectRoot ?? process.cwd());
|
|
15290
15329
|
if (checkpointRetryResult.status === "completed" && retryParsed?.result === "success") devStoryWasSuccess = true;
|
|
15291
|
-
else logger$
|
|
15330
|
+
else logger$27.warn({
|
|
15292
15331
|
storyKey,
|
|
15293
15332
|
status: checkpointRetryResult.status
|
|
15294
15333
|
}, "Checkpoint retry completed with failure — proceeding to code review");
|
|
@@ -15298,13 +15337,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
15298
15337
|
replaceDevStorySignals(devResult);
|
|
15299
15338
|
if (devResult.result === "success") devStoryWasSuccess = true;
|
|
15300
15339
|
else {
|
|
15301
|
-
logger$
|
|
15340
|
+
logger$27.warn({
|
|
15302
15341
|
storyKey,
|
|
15303
15342
|
error: devResult.error,
|
|
15304
15343
|
filesModified: devFilesModified.length
|
|
15305
15344
|
}, "Dev-story reported failure, proceeding to code review");
|
|
15306
15345
|
if (!devResult.error?.startsWith("dispatch_timeout")) {
|
|
15307
|
-
logger$
|
|
15346
|
+
logger$27.warn({
|
|
15308
15347
|
storyKey,
|
|
15309
15348
|
error: devResult.error
|
|
15310
15349
|
}, "Agent process failure (non-timeout) — story will proceed to code review with partial work");
|
|
@@ -15385,7 +15424,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15385
15424
|
}).trim();
|
|
15386
15425
|
if (committedFiles.length > 0) gitDiffFiles = committedFiles.split("\n").filter(Boolean);
|
|
15387
15426
|
} catch {}
|
|
15388
|
-
logger$
|
|
15427
|
+
logger$27.info({
|
|
15389
15428
|
storyKey,
|
|
15390
15429
|
baselineHeadSha,
|
|
15391
15430
|
committedFileCount: gitDiffFiles?.length ?? 0
|
|
@@ -15393,7 +15432,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15393
15432
|
} else {
|
|
15394
15433
|
const outsideWorktreeFiles = detectWorkOutsideWorktree(effectiveProjectRoot, projectRoot, checkGitDiffFiles);
|
|
15395
15434
|
const misrouted = outsideWorktreeFiles.length > 0;
|
|
15396
|
-
logger$
|
|
15435
|
+
logger$27.warn({
|
|
15397
15436
|
storyKey,
|
|
15398
15437
|
misrouteSuspected: misrouted,
|
|
15399
15438
|
outsideWorktreeFileCount: outsideWorktreeFiles.length
|
|
@@ -15469,7 +15508,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15469
15508
|
}
|
|
15470
15509
|
}
|
|
15471
15510
|
if (implClassification.hasImplementation && implAddedLines === 0) {
|
|
15472
|
-
logger$
|
|
15511
|
+
logger$27.warn({
|
|
15473
15512
|
storyKey,
|
|
15474
15513
|
changed: gitDiffFiles.slice(0, 10)
|
|
15475
15514
|
}, "dev-story reported success but its implementation files added zero non-whitespace lines (empty stub / whitespace-only / pure deletion) — escalating no-implementation");
|
|
@@ -15491,7 +15530,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15491
15530
|
return;
|
|
15492
15531
|
}
|
|
15493
15532
|
if (!implClassification.hasImplementation) {
|
|
15494
|
-
logger$
|
|
15533
|
+
logger$27.warn({
|
|
15495
15534
|
storyKey,
|
|
15496
15535
|
artifactFiles: implClassification.artifactOnly.slice(0, 10)
|
|
15497
15536
|
}, "dev-story reported success but the diff contains only pipeline artifacts — no implementation was produced");
|
|
@@ -15520,24 +15559,24 @@ function createImplementationOrchestrator(deps) {
|
|
|
15520
15559
|
if (dirtyNow.length > 0) if (devStoryWasSuccess) {
|
|
15521
15560
|
const earlyCommit = await commitDevStoryOutput(storyKey, _capturedStoryTitle, dirtyNow, effectiveProjectRoot);
|
|
15522
15561
|
if (earlyCommit.status === "committed") {
|
|
15523
|
-
logger$
|
|
15562
|
+
logger$27.info({
|
|
15524
15563
|
storyKey,
|
|
15525
15564
|
sha: earlyCommit.sha,
|
|
15526
15565
|
fileCount: earlyCommit.filesStaged.length
|
|
15527
15566
|
}, "commit-first: dev-story output committed to story branch");
|
|
15528
|
-
if (runManifest !== null && earlyCommit.sha) runManifest.patchStoryState(storyKey, { commit_sha: earlyCommit.sha }).catch((err) => logger$
|
|
15567
|
+
if (runManifest !== null && earlyCommit.sha) runManifest.patchStoryState(storyKey, { commit_sha: earlyCommit.sha }).catch((err) => logger$27.warn({
|
|
15529
15568
|
err,
|
|
15530
15569
|
storyKey
|
|
15531
15570
|
}, "patchStoryState(commit_sha, commit-first) failed — pipeline continues"));
|
|
15532
15571
|
} else if (earlyCommit.status === "failed") {
|
|
15533
15572
|
_devOutputCommitHookFailure = earlyCommit.stderr;
|
|
15534
15573
|
const cp = await checkpointStoryWorktree(storyKey, "dev-story output (deliverable commit rejected by hooks)", effectiveProjectRoot);
|
|
15535
|
-
logger$
|
|
15574
|
+
logger$27.warn({
|
|
15536
15575
|
storyKey,
|
|
15537
15576
|
checkpoint: cp.status,
|
|
15538
15577
|
hookStderr: earlyCommit.stderr.slice(0, 500)
|
|
15539
15578
|
}, "commit-first: hooks rejected feat commit — work preserved as wip checkpoint");
|
|
15540
|
-
if (cp.status === "committed" && runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
15579
|
+
if (cp.status === "committed" && runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$27.warn({
|
|
15541
15580
|
err,
|
|
15542
15581
|
storyKey
|
|
15543
15582
|
}, "patchStoryState(checkpoint_sha) failed — pipeline continues"));
|
|
@@ -15545,11 +15584,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15545
15584
|
} else {
|
|
15546
15585
|
const cp = await checkpointStoryWorktree(storyKey, "dev-story partial output", effectiveProjectRoot);
|
|
15547
15586
|
if (cp.status === "committed") {
|
|
15548
|
-
logger$
|
|
15587
|
+
logger$27.info({
|
|
15549
15588
|
storyKey,
|
|
15550
15589
|
sha: cp.sha
|
|
15551
15590
|
}, "commit-first: partial dev-story output checkpointed");
|
|
15552
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
15591
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$27.warn({
|
|
15553
15592
|
err,
|
|
15554
15593
|
storyKey
|
|
15555
15594
|
}, "patchStoryState(checkpoint_sha) failed — pipeline continues"));
|
|
@@ -15583,10 +15622,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
15583
15622
|
"pipe"
|
|
15584
15623
|
]
|
|
15585
15624
|
});
|
|
15586
|
-
logger$
|
|
15625
|
+
logger$27.info({ storyKey }, "Secondary typecheck (tsc --noEmit) passed");
|
|
15587
15626
|
} catch (tscErr) {
|
|
15588
15627
|
const tscOutput = tscErr instanceof Error && "stdout" in tscErr ? String(tscErr.stdout ?? "").slice(0, 2e3) : "";
|
|
15589
|
-
logger$
|
|
15628
|
+
logger$27.warn({
|
|
15590
15629
|
storyKey,
|
|
15591
15630
|
tscOutput
|
|
15592
15631
|
}, "Secondary typecheck (tsc --noEmit) failed — treating as build failure");
|
|
@@ -15601,7 +15640,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15601
15640
|
if (buildVerifyResult.status === "passed") {
|
|
15602
15641
|
_buildPassed = true;
|
|
15603
15642
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15604
|
-
logger$
|
|
15643
|
+
logger$27.info({ storyKey }, "Build verification passed");
|
|
15605
15644
|
} else if (buildVerifyResult.status === "failed" || buildVerifyResult.status === "timeout") {
|
|
15606
15645
|
const truncatedOutput = (buildVerifyResult.output ?? "").slice(0, 2e3);
|
|
15607
15646
|
const reason = buildVerifyResult.reason ?? "build-verification-failed";
|
|
@@ -15610,7 +15649,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15610
15649
|
const resolvedRoot = effectiveProjectRoot ?? process.cwd();
|
|
15611
15650
|
const hasChanges = detectPackageChanges(_packageSnapshot, resolvedRoot);
|
|
15612
15651
|
if (hasChanges) {
|
|
15613
|
-
logger$
|
|
15652
|
+
logger$27.warn({ storyKey }, "Package files changed since snapshot — restoring to prevent cascade");
|
|
15614
15653
|
const restoreResult = restorePackageSnapshot(_packageSnapshot, { projectRoot: resolvedRoot });
|
|
15615
15654
|
if (restoreResult.restored) {
|
|
15616
15655
|
const retryAfterRestore = runBuildVerification({
|
|
@@ -15623,11 +15662,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15623
15662
|
retryPassed = true;
|
|
15624
15663
|
_buildPassed = true;
|
|
15625
15664
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15626
|
-
logger$
|
|
15665
|
+
logger$27.warn({
|
|
15627
15666
|
storyKey,
|
|
15628
15667
|
filesRestored: restoreResult.filesRestored
|
|
15629
15668
|
}, "Build passed after package snapshot restore — cross-story pollution detected and cleaned");
|
|
15630
|
-
} else logger$
|
|
15669
|
+
} else logger$27.warn({
|
|
15631
15670
|
storyKey,
|
|
15632
15671
|
filesRestored: restoreResult.filesRestored
|
|
15633
15672
|
}, "Build still fails after snapshot restore — story has its own build errors");
|
|
@@ -15639,7 +15678,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15639
15678
|
if (missingPkgMatch && buildVerifyResult.status !== "timeout") {
|
|
15640
15679
|
const missingPkg = missingPkgMatch[1].replace(/^(@[^/]+\/[^/]+)\/.*$/, "$1").replace(/^([^@][^/]*)\/.*$/, "$1");
|
|
15641
15680
|
const resolvedRoot = effectiveProjectRoot ?? process.cwd();
|
|
15642
|
-
logger$
|
|
15681
|
+
logger$27.warn({
|
|
15643
15682
|
storyKey,
|
|
15644
15683
|
missingPkg
|
|
15645
15684
|
}, "Build-fix retry: detected missing npm package — attempting npm install");
|
|
@@ -15650,7 +15689,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15650
15689
|
encoding: "utf-8",
|
|
15651
15690
|
stdio: "pipe"
|
|
15652
15691
|
});
|
|
15653
|
-
logger$
|
|
15692
|
+
logger$27.warn({
|
|
15654
15693
|
storyKey,
|
|
15655
15694
|
missingPkg
|
|
15656
15695
|
}, "Build-fix retry: npm install succeeded — retrying build verification");
|
|
@@ -15664,18 +15703,18 @@ function createImplementationOrchestrator(deps) {
|
|
|
15664
15703
|
retryPassed = true;
|
|
15665
15704
|
_buildPassed = true;
|
|
15666
15705
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15667
|
-
logger$
|
|
15706
|
+
logger$27.warn({
|
|
15668
15707
|
storyKey,
|
|
15669
15708
|
missingPkg
|
|
15670
15709
|
}, "Build-fix retry: build verification passed after installing missing package");
|
|
15671
|
-
} else logger$
|
|
15710
|
+
} else logger$27.warn({
|
|
15672
15711
|
storyKey,
|
|
15673
15712
|
missingPkg,
|
|
15674
15713
|
retryStatus: retryResult.status
|
|
15675
15714
|
}, "Build-fix retry: build still fails after installing missing package — escalating");
|
|
15676
15715
|
} catch (installErr) {
|
|
15677
15716
|
const installMsg = installErr instanceof Error ? installErr.message : String(installErr);
|
|
15678
|
-
logger$
|
|
15717
|
+
logger$27.warn({
|
|
15679
15718
|
storyKey,
|
|
15680
15719
|
missingPkg,
|
|
15681
15720
|
error: installMsg
|
|
@@ -15685,7 +15724,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15685
15724
|
if (!retryPassed) {
|
|
15686
15725
|
let buildFixPassed = false;
|
|
15687
15726
|
if (buildVerifyResult.status === "failed" && storyFilePath !== void 0) try {
|
|
15688
|
-
logger$
|
|
15727
|
+
logger$27.info({ storyKey }, "Dispatching build-fix agent");
|
|
15689
15728
|
startPhase(storyKey, "build-fix");
|
|
15690
15729
|
const storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
15691
15730
|
let buildFixTemplate;
|
|
@@ -15722,11 +15761,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15722
15761
|
buildFixPassed = true;
|
|
15723
15762
|
_buildPassed = true;
|
|
15724
15763
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15725
|
-
logger$
|
|
15726
|
-
} else logger$
|
|
15764
|
+
logger$27.info({ storyKey }, "Build passed after build-fix dispatch");
|
|
15765
|
+
} else logger$27.warn({ storyKey }, "Build still fails after build-fix dispatch — escalating");
|
|
15727
15766
|
} catch (fixErr) {
|
|
15728
15767
|
const fixMsg = fixErr instanceof Error ? fixErr.message : String(fixErr);
|
|
15729
|
-
logger$
|
|
15768
|
+
logger$27.warn({
|
|
15730
15769
|
storyKey,
|
|
15731
15770
|
error: fixMsg
|
|
15732
15771
|
}, "Build-fix dispatch failed — escalating");
|
|
@@ -15763,7 +15802,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15763
15802
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
15764
15803
|
}
|
|
15765
15804
|
}).catch((err) => {
|
|
15766
|
-
logger$
|
|
15805
|
+
logger$27.warn({
|
|
15767
15806
|
err,
|
|
15768
15807
|
storyKey
|
|
15769
15808
|
}, "interactive prompt failed — continuing with default action");
|
|
@@ -15780,7 +15819,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15780
15819
|
exitCode: buildVerifyResult.exitCode ?? 1,
|
|
15781
15820
|
output: truncatedOutput
|
|
15782
15821
|
});
|
|
15783
|
-
logger$
|
|
15822
|
+
logger$27.warn({
|
|
15784
15823
|
storyKey,
|
|
15785
15824
|
reason,
|
|
15786
15825
|
exitCode: buildVerifyResult.exitCode,
|
|
@@ -15814,7 +15853,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15814
15853
|
storyKey
|
|
15815
15854
|
});
|
|
15816
15855
|
if (icResult.potentiallyAffectedTests.length > 0) {
|
|
15817
|
-
logger$
|
|
15856
|
+
logger$27.warn({
|
|
15818
15857
|
storyKey,
|
|
15819
15858
|
modifiedInterfaces: icResult.modifiedInterfaces,
|
|
15820
15859
|
potentiallyAffectedTests: icResult.potentiallyAffectedTests
|
|
@@ -15917,14 +15956,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
15917
15956
|
adapter: db,
|
|
15918
15957
|
engine: "linear"
|
|
15919
15958
|
}).catch((recoveryErr) => {
|
|
15920
|
-
logger$
|
|
15959
|
+
logger$27.warn({
|
|
15921
15960
|
storyKey,
|
|
15922
15961
|
err: recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr)
|
|
15923
15962
|
}, "Recovery Engine invocation failed — falling through to VERIFICATION_FAILED (best-effort)");
|
|
15924
15963
|
return null;
|
|
15925
15964
|
});
|
|
15926
15965
|
if (recoveryResult?.action === "halt-entire-run") {
|
|
15927
|
-
logger$
|
|
15966
|
+
logger$27.error({
|
|
15928
15967
|
storyKey,
|
|
15929
15968
|
pendingProposalsCount: recoveryResult.pendingProposalsCount
|
|
15930
15969
|
}, "Recovery Engine safety valve: halting entire run due to >= 5 pending proposals");
|
|
@@ -15936,13 +15975,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
15936
15975
|
outcome: "escalated",
|
|
15937
15976
|
cost_usd: 0,
|
|
15938
15977
|
timestamp: new Date().toISOString()
|
|
15939
|
-
}).catch((err) => logger$
|
|
15978
|
+
}).catch((err) => logger$27.warn({
|
|
15940
15979
|
err,
|
|
15941
15980
|
storyKey
|
|
15942
15981
|
}, "appendRecoveryEntry(halt-entire-run) failed — pipeline continues"));
|
|
15943
15982
|
_budgetExhausted = true;
|
|
15944
15983
|
} else if (recoveryResult?.action === "retry") {
|
|
15945
|
-
logger$
|
|
15984
|
+
logger$27.info({
|
|
15946
15985
|
storyKey,
|
|
15947
15986
|
attempt: recoveryResult.attempt,
|
|
15948
15987
|
retryBudgetRemaining: recoveryResult.retryBudgetRemaining
|
|
@@ -15994,22 +16033,22 @@ function createImplementationOrchestrator(deps) {
|
|
|
15994
16033
|
outcome: tierARecovered ? "recovered" : "retried",
|
|
15995
16034
|
cost_usd: 0,
|
|
15996
16035
|
timestamp: new Date().toISOString()
|
|
15997
|
-
}).catch((err) => logger$
|
|
16036
|
+
}).catch((err) => logger$27.warn({
|
|
15998
16037
|
err,
|
|
15999
16038
|
storyKey
|
|
16000
16039
|
}, "appendRecoveryEntry(tier-a) failed — pipeline continues"));
|
|
16001
16040
|
if (tierARecovered) {
|
|
16002
|
-
logger$
|
|
16041
|
+
logger$27.info({ storyKey }, "Recovery Engine Tier A retry succeeded — story proceeding to COMPLETE");
|
|
16003
16042
|
shouldFallThroughToComplete = true;
|
|
16004
|
-
} else logger$
|
|
16043
|
+
} else logger$27.warn({ storyKey }, "Recovery Engine Tier A retry still failed — falling through to VERIFICATION_FAILED");
|
|
16005
16044
|
} catch (retryErr) {
|
|
16006
|
-
logger$
|
|
16045
|
+
logger$27.warn({
|
|
16007
16046
|
storyKey,
|
|
16008
16047
|
err: retryErr instanceof Error ? retryErr.message : String(retryErr)
|
|
16009
16048
|
}, "Recovery Engine Tier A re-dispatch threw — falling through to VERIFICATION_FAILED");
|
|
16010
16049
|
}
|
|
16011
16050
|
} else if (recoveryResult?.action === "propose") {
|
|
16012
|
-
logger$
|
|
16051
|
+
logger$27.info({ storyKey }, "Recovery Engine Tier B: proposal appended — marking story ESCALATED for operator re-scope");
|
|
16013
16052
|
if (runManifest) runManifest.appendRecoveryEntry({
|
|
16014
16053
|
story_key: storyKey,
|
|
16015
16054
|
attempt_number: finalReviewCycles + 1,
|
|
@@ -16018,7 +16057,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16018
16057
|
outcome: "escalated",
|
|
16019
16058
|
cost_usd: 0,
|
|
16020
16059
|
timestamp: new Date().toISOString()
|
|
16021
|
-
}).catch((err) => logger$
|
|
16060
|
+
}).catch((err) => logger$27.warn({
|
|
16022
16061
|
err,
|
|
16023
16062
|
storyKey
|
|
16024
16063
|
}, "appendRecoveryEntry(tier-b) failed — pipeline continues"));
|
|
@@ -16038,7 +16077,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16038
16077
|
await persistState();
|
|
16039
16078
|
return "verification-failed";
|
|
16040
16079
|
} else if (recoveryResult?.action === "halt") {
|
|
16041
|
-
logger$
|
|
16080
|
+
logger$27.warn({ storyKey }, "Recovery Engine Tier C: halt — invoking interactive prompt for operator decision");
|
|
16042
16081
|
const haltRunId = config.pipelineRunId ?? storyKey;
|
|
16043
16082
|
await runInteractivePrompt({
|
|
16044
16083
|
runId: haltRunId,
|
|
@@ -16055,7 +16094,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16055
16094
|
eventBus.emit("decision:halt-skipped-non-interactive", haltPayload);
|
|
16056
16095
|
}
|
|
16057
16096
|
}).catch((err) => {
|
|
16058
|
-
logger$
|
|
16097
|
+
logger$27.warn({
|
|
16059
16098
|
err,
|
|
16060
16099
|
storyKey
|
|
16061
16100
|
}, "Recovery Engine Tier C: interactive prompt failed — escalating anyway");
|
|
@@ -16068,7 +16107,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16068
16107
|
outcome: "escalated",
|
|
16069
16108
|
cost_usd: 0,
|
|
16070
16109
|
timestamp: new Date().toISOString()
|
|
16071
|
-
}).catch((err) => logger$
|
|
16110
|
+
}).catch((err) => logger$27.warn({
|
|
16072
16111
|
err,
|
|
16073
16112
|
storyKey
|
|
16074
16113
|
}, "appendRecoveryEntry(tier-c) failed — pipeline continues"));
|
|
@@ -16093,11 +16132,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
16093
16132
|
if (effectiveProjectRoot !== void 0 && effectiveProjectRoot !== projectRoot) {
|
|
16094
16133
|
const cp = await checkpointStoryWorktree(storyKey, `verification-failed: ${verificationFailReason ?? "tier-a-fail"}`, effectiveProjectRoot);
|
|
16095
16134
|
if (cp.status === "committed") {
|
|
16096
|
-
logger$
|
|
16135
|
+
logger$27.info({
|
|
16097
16136
|
storyKey,
|
|
16098
16137
|
sha: cp.sha
|
|
16099
16138
|
}, "verification-failed checkpoint: uncommitted worktree state preserved on story branch");
|
|
16100
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
16139
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$27.warn({
|
|
16101
16140
|
err,
|
|
16102
16141
|
storyKey
|
|
16103
16142
|
}, "patchStoryState(checkpoint_sha, verification-failed) failed — pipeline continues"));
|
|
@@ -16107,7 +16146,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16107
16146
|
phase: "VERIFICATION_FAILED",
|
|
16108
16147
|
completedAt: new Date().toISOString()
|
|
16109
16148
|
});
|
|
16110
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { escalation_reason: verificationFailReason }).catch((err) => logger$
|
|
16149
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { escalation_reason: verificationFailReason }).catch((err) => logger$27.warn({
|
|
16111
16150
|
err,
|
|
16112
16151
|
storyKey
|
|
16113
16152
|
}, "patchStoryState(escalation_reason, verification-failed) failed — pipeline continues"));
|
|
@@ -16133,7 +16172,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16133
16172
|
if (autoApprove?.downgradeLastVerdict !== void 0) completeUpdate.lastVerdict = autoApprove.downgradeLastVerdict;
|
|
16134
16173
|
updateStory(storyKey, completeUpdate);
|
|
16135
16174
|
if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
|
|
16136
|
-
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$
|
|
16175
|
+
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$27.warn({
|
|
16137
16176
|
storyKey,
|
|
16138
16177
|
category: "verification-result-missing"
|
|
16139
16178
|
}, "post-COMPLETE invariant: verification_result absent in manifest");
|
|
@@ -16156,7 +16195,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16156
16195
|
const commitResult = await commitDevStoryOutput(storyKey, _capturedStoryTitle, dirty, effectiveProjectRoot);
|
|
16157
16196
|
if (commitResult.status === "no-changes") {
|
|
16158
16197
|
if (_devOutputCommitHookFailure !== void 0) {
|
|
16159
|
-
logger$
|
|
16198
|
+
logger$27.error({
|
|
16160
16199
|
storyKey,
|
|
16161
16200
|
stderr: _devOutputCommitHookFailure
|
|
16162
16201
|
}, "deliverable commit was rejected by hooks at dev-story end and was never resolved — escalating");
|
|
@@ -16189,7 +16228,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16189
16228
|
branchAdvancedSinceBaseline = headNow !== baselineHeadSha;
|
|
16190
16229
|
} catch {}
|
|
16191
16230
|
if (!branchAdvancedSinceBaseline) {
|
|
16192
|
-
logger$
|
|
16231
|
+
logger$27.warn({
|
|
16193
16232
|
storyKey,
|
|
16194
16233
|
reason: commitResult.reason
|
|
16195
16234
|
}, "dev-story produced no committable changes — escalating instead of running merge-to-main on an unchanged branch");
|
|
@@ -16207,10 +16246,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
16207
16246
|
await persistState();
|
|
16208
16247
|
return "terminal";
|
|
16209
16248
|
}
|
|
16210
|
-
logger$
|
|
16249
|
+
logger$27.info({ storyKey }, "working tree clean at finalize but branch already advanced (commit-first) — proceeding to merge");
|
|
16211
16250
|
}
|
|
16212
16251
|
if (commitResult.status === "failed") {
|
|
16213
|
-
logger$
|
|
16252
|
+
logger$27.error({
|
|
16214
16253
|
storyKey,
|
|
16215
16254
|
stderr: commitResult.stderr
|
|
16216
16255
|
}, "substrate auto-commit failed — escalating story");
|
|
@@ -16231,7 +16270,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16231
16270
|
let finalizeCommitSha;
|
|
16232
16271
|
if (commitResult.status === "committed") {
|
|
16233
16272
|
finalizeCommitSha = commitResult.sha || void 0;
|
|
16234
|
-
logger$
|
|
16273
|
+
logger$27.info({
|
|
16235
16274
|
storyKey,
|
|
16236
16275
|
sha: commitResult.sha,
|
|
16237
16276
|
fileCount: commitResult.filesStaged.length
|
|
@@ -16259,7 +16298,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16259
16298
|
if (storyFilePath !== void 0) try {
|
|
16260
16299
|
Object.assign(statePatch, captureReconstructionInput(storyFilePath, storyKey, runManifest.baseDir, runManifest.runId, effectiveProjectRoot));
|
|
16261
16300
|
} catch (inputErr) {
|
|
16262
|
-
logger$
|
|
16301
|
+
logger$27.warn({
|
|
16263
16302
|
err: inputErr,
|
|
16264
16303
|
storyKey
|
|
16265
16304
|
}, "reconstruction phase-input capture failed — pipeline continues (commit_sha still recorded)");
|
|
@@ -16269,12 +16308,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
16269
16308
|
if (dispatchTelemetry.total_turns !== void 0) statePatch.total_turns = dispatchTelemetry.total_turns;
|
|
16270
16309
|
if (dispatchTelemetry.total_tokens !== void 0) statePatch.total_tokens = dispatchTelemetry.total_tokens;
|
|
16271
16310
|
} catch (telemetryErr) {
|
|
16272
|
-
logger$
|
|
16311
|
+
logger$27.warn({
|
|
16273
16312
|
err: telemetryErr,
|
|
16274
16313
|
storyKey
|
|
16275
16314
|
}, "aggregateStoryDispatchTelemetry failed — pipeline continues (commit_sha still recorded)");
|
|
16276
16315
|
}
|
|
16277
|
-
runManifest.patchStoryState(storyKey, statePatch).catch((err) => logger$
|
|
16316
|
+
runManifest.patchStoryState(storyKey, statePatch).catch((err) => logger$27.warn({
|
|
16278
16317
|
err,
|
|
16279
16318
|
storyKey
|
|
16280
16319
|
}, "patchStoryState(commit_sha/phase-input/telemetry) failed — pipeline continues"));
|
|
@@ -16302,7 +16341,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16302
16341
|
timeout: 5e3
|
|
16303
16342
|
}).trim();
|
|
16304
16343
|
if (branchSha === startSha) {
|
|
16305
|
-
logger$
|
|
16344
|
+
logger$27.warn({
|
|
16306
16345
|
storyKey,
|
|
16307
16346
|
branchSha,
|
|
16308
16347
|
startSha,
|
|
@@ -16323,7 +16362,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16323
16362
|
return "terminal";
|
|
16324
16363
|
}
|
|
16325
16364
|
} catch (gateErr) {
|
|
16326
|
-
logger$
|
|
16365
|
+
logger$27.warn({
|
|
16327
16366
|
storyKey,
|
|
16328
16367
|
err: gateErr instanceof Error ? gateErr.message : String(gateErr)
|
|
16329
16368
|
}, "merge-to-main pre-flight verification failed — proceeding with merge phase");
|
|
@@ -16341,7 +16380,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16341
16380
|
const artifactSet = new Set(artifactOnly.map(norm));
|
|
16342
16381
|
const undisclosed = mergedFiles.map(norm).filter((f$1) => !artifactSet.has(f$1) && !disclosed.has(f$1));
|
|
16343
16382
|
if (undisclosed.length > 0) {
|
|
16344
|
-
logger$
|
|
16383
|
+
logger$27.error({
|
|
16345
16384
|
storyKey,
|
|
16346
16385
|
undisclosed,
|
|
16347
16386
|
disclosed: [...disclosed]
|
|
@@ -16365,7 +16404,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16365
16404
|
try {
|
|
16366
16405
|
acceptanceOutcomes = await runAcceptanceStage(storyKey, effectiveProjectRoot ?? projectRoot ?? process.cwd(), recaptureChangedFiles(effectiveProjectRoot ?? projectRoot ?? process.cwd()));
|
|
16367
16406
|
} catch (stageErr) {
|
|
16368
|
-
logger$
|
|
16407
|
+
logger$27.warn({
|
|
16369
16408
|
storyKey,
|
|
16370
16409
|
err: stageErr
|
|
16371
16410
|
}, "A2.3: acceptance stage threw (best-effort) — claimed journeys stay unwalked");
|
|
@@ -16375,7 +16414,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16375
16414
|
const criticalFailed = acceptanceOutcomes.filter((o) => o.criticality === "critical" && o.judged && !o.pass);
|
|
16376
16415
|
if (criticalFailed.length > 0) {
|
|
16377
16416
|
const failedIds = criticalFailed.map((o) => o.journeyId);
|
|
16378
|
-
logger$
|
|
16417
|
+
logger$27.error({
|
|
16379
16418
|
storyKey,
|
|
16380
16419
|
journeys: failedIds
|
|
16381
16420
|
}, "A4.1: journey-critical acceptance FAIL — blocking integration; branch preserved");
|
|
@@ -16398,7 +16437,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16398
16437
|
}
|
|
16399
16438
|
const standardFailed = acceptanceOutcomes.filter((o) => o.criticality === "standard" && o.judged && !o.pass);
|
|
16400
16439
|
if (standardFailed.length > 0) {
|
|
16401
|
-
logger$
|
|
16440
|
+
logger$27.warn({
|
|
16402
16441
|
storyKey,
|
|
16403
16442
|
journeys: standardFailed.map((o) => o.journeyId)
|
|
16404
16443
|
}, "A4.1: standard-tier acceptance FAIL — run continues; fix-story proposal filed (best-effort)");
|
|
@@ -16408,7 +16447,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16408
16447
|
description: `standard-tier journey acceptance FAILED (${standardFailed.map((o) => o.journeyId).join(", ")}) — file a fix story to wire the journey end-states`,
|
|
16409
16448
|
type: "fix",
|
|
16410
16449
|
story_key: storyKey
|
|
16411
|
-
}).catch((err) => logger$
|
|
16450
|
+
}).catch((err) => logger$27.warn({
|
|
16412
16451
|
err,
|
|
16413
16452
|
storyKey
|
|
16414
16453
|
}, "A4.1: proposal append failed — pipeline continues"));
|
|
@@ -16416,7 +16455,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16416
16455
|
const critical = acceptanceOutcomes.filter((o) => o.criticality === "critical");
|
|
16417
16456
|
if (finalizationMode === "merge" && critical.length > 0 && critical.every((o) => o.judged && o.pass)) {
|
|
16418
16457
|
finalizationMode = config.acceptanceCriticalPassFinalization ?? "branch";
|
|
16419
|
-
logger$
|
|
16458
|
+
logger$27.info({
|
|
16420
16459
|
storyKey,
|
|
16421
16460
|
journeys: critical.map((o) => o.journeyId),
|
|
16422
16461
|
finalizationMode
|
|
@@ -16439,7 +16478,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16439
16478
|
if (audit?.unrunnable !== void 0) issueLines.push(audit.unrunnable);
|
|
16440
16479
|
if (acceptanceModeCfg === "blocking") {
|
|
16441
16480
|
const verdict = violations.some((v) => v.state === "unclaimed") ? "journey-unclaimed" : audit?.unrunnable !== void 0 ? "acceptance-unrunnable" : "journey-unwalked";
|
|
16442
|
-
logger$
|
|
16481
|
+
logger$27.error({
|
|
16443
16482
|
storyKey,
|
|
16444
16483
|
epicId: epicIdA,
|
|
16445
16484
|
verdict,
|
|
@@ -16463,7 +16502,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16463
16502
|
await persistState();
|
|
16464
16503
|
return "terminal";
|
|
16465
16504
|
}
|
|
16466
|
-
logger$
|
|
16505
|
+
logger$27.warn({
|
|
16467
16506
|
storyKey,
|
|
16468
16507
|
epicId: epicIdA,
|
|
16469
16508
|
violations: issueLines
|
|
@@ -16479,7 +16518,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16479
16518
|
const TERMINAL_PHASES = ["COMPLETE", "ESCALATED"];
|
|
16480
16519
|
const isLastOfEpic = [..._stories.entries()].filter(([key]) => key !== storyKey && epicOf(key) === epicId).every(([, st]) => TERMINAL_PHASES.includes(st.phase));
|
|
16481
16520
|
if (isLastOfEpic) {
|
|
16482
|
-
logger$
|
|
16521
|
+
logger$27.info({
|
|
16483
16522
|
storyKey,
|
|
16484
16523
|
epicId,
|
|
16485
16524
|
epicGateCommand
|
|
@@ -16504,7 +16543,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16504
16543
|
gateOutput = `${e.stdout ?? ""}${e.stderr ?? ""}`.trim() || (e.message ?? String(gateCmdErr));
|
|
16505
16544
|
}
|
|
16506
16545
|
if (!gatePassed) {
|
|
16507
|
-
logger$
|
|
16546
|
+
logger$27.error({
|
|
16508
16547
|
storyKey,
|
|
16509
16548
|
epicId,
|
|
16510
16549
|
output: gateOutput.slice(0, 500)
|
|
@@ -16523,7 +16562,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16523
16562
|
await persistState();
|
|
16524
16563
|
return "terminal";
|
|
16525
16564
|
}
|
|
16526
|
-
logger$
|
|
16565
|
+
logger$27.info({
|
|
16527
16566
|
storyKey,
|
|
16528
16567
|
epicId
|
|
16529
16568
|
}, "H3.4: epic gate passed");
|
|
@@ -16568,7 +16607,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16568
16607
|
}).trim();
|
|
16569
16608
|
prUrl = ghOutput === "" ? void 0 : ghOutput;
|
|
16570
16609
|
} catch (prErr) {
|
|
16571
|
-
logger$
|
|
16610
|
+
logger$27.warn({
|
|
16572
16611
|
storyKey,
|
|
16573
16612
|
branchName,
|
|
16574
16613
|
err: prErr instanceof Error ? prErr.message.slice(0, 300) : String(prErr)
|
|
@@ -16577,7 +16616,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16577
16616
|
try {
|
|
16578
16617
|
await _worktreeManager.cleanupWorktree(storyKey, { keepBranch: true });
|
|
16579
16618
|
} catch (cleanupErr) {
|
|
16580
|
-
logger$
|
|
16619
|
+
logger$27.warn({
|
|
16581
16620
|
storyKey,
|
|
16582
16621
|
err: cleanupErr
|
|
16583
16622
|
}, "worktree removal after branch/pr finalization failed (best-effort; branch intact)");
|
|
@@ -16594,11 +16633,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
16594
16633
|
branch: branchName,
|
|
16595
16634
|
...storyDeliverableSha ? { sha: storyDeliverableSha } : {},
|
|
16596
16635
|
...prUrl !== void 0 ? { pr_url: prUrl } : {}
|
|
16597
|
-
} }).catch((err) => logger$
|
|
16636
|
+
} }).catch((err) => logger$27.warn({
|
|
16598
16637
|
err,
|
|
16599
16638
|
storyKey
|
|
16600
16639
|
}, "patchStoryState(finalization) failed — pipeline continues"));
|
|
16601
|
-
logger$
|
|
16640
|
+
logger$27.info({
|
|
16602
16641
|
storyKey,
|
|
16603
16642
|
branchName,
|
|
16604
16643
|
mode: finalizationMode,
|
|
@@ -16606,7 +16645,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16606
16645
|
}, "story finalized without self-merge — branch is the deliverable");
|
|
16607
16646
|
return "finalized";
|
|
16608
16647
|
}
|
|
16609
|
-
logger$
|
|
16648
|
+
logger$27.info({
|
|
16610
16649
|
storyKey,
|
|
16611
16650
|
branchName,
|
|
16612
16651
|
startBranch: _orchestratorStartBranch
|
|
@@ -16624,7 +16663,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16624
16663
|
});
|
|
16625
16664
|
} catch (mergeErr) {
|
|
16626
16665
|
const errMsg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
16627
|
-
logger$
|
|
16666
|
+
logger$27.error({
|
|
16628
16667
|
storyKey,
|
|
16629
16668
|
err: mergeErr
|
|
16630
16669
|
}, "merge-to-main phase threw unexpectedly — escalating story");
|
|
@@ -16648,7 +16687,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16648
16687
|
if (failReason === "parent-tree-dirtied-by-run") issues.push(`parent working tree has uncommitted changes to ${mergeResult.dirtiedFiles?.length ?? 0} file(s) the story also modified: ${(mergeResult.dirtiedFiles ?? []).join(", ")} — merging would entangle unreviewed parent edits with verified story content. Commit or stash the parent changes, then merge ${branchName} manually.`);
|
|
16649
16688
|
else if (failReason === "ff-only-merge-not-possible") issues.push(`${_orchestratorStartBranch ?? "the start branch"} moved since ${branchName} was created and merge_strategy is ff-only — substrate will not synthesize a merge commit. Set finalization.merge_strategy: three-way (required for concurrent multi-story runs) or integrate the branch manually.`);
|
|
16650
16689
|
else issues.push(`merge conflict in ${mergeResult.conflictingFiles?.length ?? 0} file(s): ${(mergeResult.conflictingFiles ?? []).join(", ")}`);
|
|
16651
|
-
logger$
|
|
16690
|
+
logger$27.warn({
|
|
16652
16691
|
storyKey,
|
|
16653
16692
|
branchName,
|
|
16654
16693
|
reason: failReason,
|
|
@@ -16669,7 +16708,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16669
16708
|
await persistState();
|
|
16670
16709
|
return "terminal";
|
|
16671
16710
|
}
|
|
16672
|
-
logger$
|
|
16711
|
+
logger$27.info({
|
|
16673
16712
|
storyKey,
|
|
16674
16713
|
branchName
|
|
16675
16714
|
}, "merge-to-main phase completed successfully");
|
|
@@ -16688,7 +16727,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16688
16727
|
mode: "merge",
|
|
16689
16728
|
branch: branchName,
|
|
16690
16729
|
...storyDeliverableSha ? { sha: storyDeliverableSha } : {}
|
|
16691
|
-
} }).catch((err) => logger$
|
|
16730
|
+
} }).catch((err) => logger$27.warn({
|
|
16692
16731
|
err,
|
|
16693
16732
|
storyKey
|
|
16694
16733
|
}, "patchStoryState(finalization) failed — pipeline continues"));
|
|
@@ -16750,7 +16789,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16750
16789
|
"NEEDS_MAJOR_REWORK": 2
|
|
16751
16790
|
};
|
|
16752
16791
|
for (const group of batchFileGroups) {
|
|
16753
|
-
logger$
|
|
16792
|
+
logger$27.info({
|
|
16754
16793
|
storyKey,
|
|
16755
16794
|
batchIndex: group.batchIndex,
|
|
16756
16795
|
fileCount: group.files.length
|
|
@@ -16796,7 +16835,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16796
16835
|
rawOutput: lastRawOutput,
|
|
16797
16836
|
tokenUsage: aggregateTokens
|
|
16798
16837
|
};
|
|
16799
|
-
logger$
|
|
16838
|
+
logger$27.info({
|
|
16800
16839
|
storyKey,
|
|
16801
16840
|
batchCount: batchFileGroups.length,
|
|
16802
16841
|
verdict: worstVerdict,
|
|
@@ -16840,7 +16879,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16840
16879
|
storyKey,
|
|
16841
16880
|
reviewCycle: reviewCycles
|
|
16842
16881
|
})
|
|
16843
|
-
})).catch((tokenErr) => logger$
|
|
16882
|
+
})).catch((tokenErr) => logger$27.warn({
|
|
16844
16883
|
storyKey,
|
|
16845
16884
|
err: tokenErr
|
|
16846
16885
|
}, "Failed to record code-review token usage"));
|
|
@@ -16858,7 +16897,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16858
16897
|
...reviewResult.details !== void 0 ? { details: reviewResult.details } : {}
|
|
16859
16898
|
});
|
|
16860
16899
|
if (schemaValidationRetries <= MAX_SCHEMA_VALIDATION_RETRIES) {
|
|
16861
|
-
logger$
|
|
16900
|
+
logger$27.warn({
|
|
16862
16901
|
storyKey,
|
|
16863
16902
|
reviewCycles,
|
|
16864
16903
|
attempt: schemaValidationRetries,
|
|
@@ -16867,7 +16906,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16867
16906
|
previousIterationWasMalformed = true;
|
|
16868
16907
|
continue;
|
|
16869
16908
|
}
|
|
16870
|
-
logger$
|
|
16909
|
+
logger$27.warn({
|
|
16871
16910
|
storyKey,
|
|
16872
16911
|
reviewCycles,
|
|
16873
16912
|
schemaValidationRetries
|
|
@@ -16890,7 +16929,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16890
16929
|
}
|
|
16891
16930
|
if (isPhantomReview && !timeoutRetried) {
|
|
16892
16931
|
timeoutRetried = true;
|
|
16893
|
-
logger$
|
|
16932
|
+
logger$27.warn({
|
|
16894
16933
|
storyKey,
|
|
16895
16934
|
reviewCycles,
|
|
16896
16935
|
error: reviewResult.error
|
|
@@ -16920,7 +16959,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16920
16959
|
}
|
|
16921
16960
|
const isStoryFileMissing = (reviewResult.error ?? "").includes("story-file-missing");
|
|
16922
16961
|
const escalationReason = isStoryFileMissing ? "story-file-missing" : "consecutive-review-timeouts";
|
|
16923
|
-
logger$
|
|
16962
|
+
logger$27.warn({
|
|
16924
16963
|
storyKey,
|
|
16925
16964
|
reviewCycles,
|
|
16926
16965
|
error: reviewResult.error,
|
|
@@ -16945,7 +16984,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16945
16984
|
verdict = reviewResult.verdict;
|
|
16946
16985
|
issueList = reviewResult.issue_list ?? [];
|
|
16947
16986
|
if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
|
|
16948
|
-
logger$
|
|
16987
|
+
logger$27.info({
|
|
16949
16988
|
storyKey,
|
|
16950
16989
|
originalVerdict: verdict,
|
|
16951
16990
|
issuesBefore: previousIssueList.length,
|
|
@@ -16974,7 +17013,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16974
17013
|
await persistState();
|
|
16975
17014
|
if (runManifest !== null) {
|
|
16976
17015
|
const persistedVerdict = reviewResult.agentVerdict ?? verdict;
|
|
16977
|
-
runManifest.patchStoryState(storyKey, { verdict: persistedVerdict }).catch((err) => logger$
|
|
17016
|
+
runManifest.patchStoryState(storyKey, { verdict: persistedVerdict }).catch((err) => logger$27.warn({
|
|
16978
17017
|
err,
|
|
16979
17018
|
storyKey
|
|
16980
17019
|
}, "patchStoryState(verdict) failed — pipeline continues"));
|
|
@@ -16988,7 +17027,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16988
17027
|
if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
|
|
16989
17028
|
parts.push(`${fileCount} files`);
|
|
16990
17029
|
parts.push(`${totalTokensK} tokens`);
|
|
16991
|
-
logger$
|
|
17030
|
+
logger$27.info({
|
|
16992
17031
|
storyKey,
|
|
16993
17032
|
verdict,
|
|
16994
17033
|
agentVerdict: reviewResult.agentVerdict
|
|
@@ -17051,9 +17090,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
17051
17090
|
}),
|
|
17052
17091
|
rationale: `Advisory notes from LGTM_WITH_NOTES review of ${storyKey}`
|
|
17053
17092
|
});
|
|
17054
|
-
logger$
|
|
17093
|
+
logger$27.info({ storyKey }, "Advisory notes persisted to decision store");
|
|
17055
17094
|
} catch (advisoryErr) {
|
|
17056
|
-
logger$
|
|
17095
|
+
logger$27.warn({
|
|
17057
17096
|
storyKey,
|
|
17058
17097
|
error: advisoryErr instanceof Error ? advisoryErr.message : String(advisoryErr)
|
|
17059
17098
|
}, "Failed to persist advisory notes (best-effort)");
|
|
@@ -17061,27 +17100,27 @@ function createImplementationOrchestrator(deps) {
|
|
|
17061
17100
|
if (telemetryPersistence !== void 0) try {
|
|
17062
17101
|
const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
|
|
17063
17102
|
if (turns.length > 0) {
|
|
17064
|
-
const scorer = new EfficiencyScorer(logger$
|
|
17103
|
+
const scorer = new EfficiencyScorer(logger$27);
|
|
17065
17104
|
const effScore = scorer.score(storyKey, turns);
|
|
17066
17105
|
await telemetryPersistence.storeEfficiencyScore(effScore);
|
|
17067
|
-
logger$
|
|
17106
|
+
logger$27.info({
|
|
17068
17107
|
storyKey,
|
|
17069
17108
|
compositeScore: effScore.compositeScore,
|
|
17070
17109
|
modelCount: effScore.perModelBreakdown.length
|
|
17071
17110
|
}, "Efficiency score computed and persisted");
|
|
17072
|
-
} else logger$
|
|
17111
|
+
} else logger$27.debug({ storyKey }, "No turn analysis data available — skipping efficiency scoring");
|
|
17073
17112
|
} catch (effErr) {
|
|
17074
|
-
logger$
|
|
17113
|
+
logger$27.warn({
|
|
17075
17114
|
storyKey,
|
|
17076
17115
|
error: effErr instanceof Error ? effErr.message : String(effErr)
|
|
17077
17116
|
}, "Efficiency scoring failed — story verdict unchanged");
|
|
17078
17117
|
}
|
|
17079
17118
|
if (telemetryPersistence !== void 0) try {
|
|
17080
17119
|
const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
|
|
17081
|
-
if (turns.length === 0) logger$
|
|
17120
|
+
if (turns.length === 0) logger$27.debug({ storyKey }, "No turn analysis data for telemetry categorization — skipping");
|
|
17082
17121
|
else {
|
|
17083
|
-
const categorizer = new Categorizer(logger$
|
|
17084
|
-
const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$
|
|
17122
|
+
const categorizer = new Categorizer(logger$27);
|
|
17123
|
+
const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$27);
|
|
17085
17124
|
const categoryStats = categorizer.computeCategoryStatsFromTurns(turns);
|
|
17086
17125
|
const consumerStats = consumerAnalyzer.analyzeFromTurns(turns);
|
|
17087
17126
|
await telemetryPersistence.storeCategoryStats(storyKey, categoryStats);
|
|
@@ -17089,7 +17128,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17089
17128
|
const growingCount = categoryStats.filter((c) => c.trend === "growing").length;
|
|
17090
17129
|
const topCategory = categoryStats[0]?.category ?? "none";
|
|
17091
17130
|
const topConsumer = consumerStats[0]?.consumerKey ?? "none";
|
|
17092
|
-
logger$
|
|
17131
|
+
logger$27.info({
|
|
17093
17132
|
storyKey,
|
|
17094
17133
|
topCategory,
|
|
17095
17134
|
topConsumer,
|
|
@@ -17097,7 +17136,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17097
17136
|
}, "Semantic categorization and consumer analysis complete");
|
|
17098
17137
|
}
|
|
17099
17138
|
} catch (catErr) {
|
|
17100
|
-
logger$
|
|
17139
|
+
logger$27.warn({
|
|
17101
17140
|
storyKey,
|
|
17102
17141
|
error: catErr instanceof Error ? catErr.message : String(catErr)
|
|
17103
17142
|
}, "Semantic categorization failed — story verdict unchanged");
|
|
@@ -17120,7 +17159,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17120
17159
|
filesModified: devFilesModified,
|
|
17121
17160
|
workingDirectory: effectiveProjectRoot
|
|
17122
17161
|
});
|
|
17123
|
-
logger$
|
|
17162
|
+
logger$27.debug({
|
|
17124
17163
|
storyKey,
|
|
17125
17164
|
expansion_priority: expansionResult.expansion_priority,
|
|
17126
17165
|
coverage_gaps: expansionResult.coverage_gaps.length
|
|
@@ -17133,7 +17172,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17133
17172
|
value: JSON.stringify(expansionResult)
|
|
17134
17173
|
});
|
|
17135
17174
|
} catch (expansionErr) {
|
|
17136
|
-
logger$
|
|
17175
|
+
logger$27.warn({
|
|
17137
17176
|
storyKey,
|
|
17138
17177
|
error: expansionErr instanceof Error ? expansionErr.message : String(expansionErr)
|
|
17139
17178
|
}, "Test expansion failed — story verdict unchanged");
|
|
@@ -17162,7 +17201,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17162
17201
|
await persistState();
|
|
17163
17202
|
return;
|
|
17164
17203
|
}
|
|
17165
|
-
logger$
|
|
17204
|
+
logger$27.info({
|
|
17166
17205
|
storyKey,
|
|
17167
17206
|
reviewCycles: finalReviewCycles,
|
|
17168
17207
|
issueCount: issueList.length
|
|
@@ -17228,7 +17267,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17228
17267
|
fixPrompt = assembled.prompt;
|
|
17229
17268
|
} catch {
|
|
17230
17269
|
fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
|
|
17231
|
-
logger$
|
|
17270
|
+
logger$27.warn({ storyKey }, "Failed to assemble auto-approve fix prompt, using fallback");
|
|
17232
17271
|
}
|
|
17233
17272
|
const handle = dispatcher.dispatch({
|
|
17234
17273
|
prompt: fixPrompt,
|
|
@@ -17253,9 +17292,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
17253
17292
|
output: fixResult.tokenEstimate.output
|
|
17254
17293
|
} : void 0 }
|
|
17255
17294
|
});
|
|
17256
|
-
if (fixResult.status === "timeout") logger$
|
|
17295
|
+
if (fixResult.status === "timeout") logger$27.warn({ storyKey }, "Auto-approve fix timed out — approving anyway (issues were minor)");
|
|
17257
17296
|
} catch (err) {
|
|
17258
|
-
logger$
|
|
17297
|
+
logger$27.warn({
|
|
17259
17298
|
storyKey,
|
|
17260
17299
|
err
|
|
17261
17300
|
}, "Auto-approve fix dispatch failed — approving anyway (issues were minor)");
|
|
@@ -17284,7 +17323,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17284
17323
|
outcome: "retried",
|
|
17285
17324
|
cost_usd: 0,
|
|
17286
17325
|
timestamp: new Date().toISOString()
|
|
17287
|
-
}).catch((err) => logger$
|
|
17326
|
+
}).catch((err) => logger$27.warn({
|
|
17288
17327
|
err,
|
|
17289
17328
|
storyKey
|
|
17290
17329
|
}, "appendRecoveryEntry failed — pipeline continues"));
|
|
@@ -17424,7 +17463,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17424
17463
|
fixPrompt = assembled.prompt;
|
|
17425
17464
|
} catch {
|
|
17426
17465
|
fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
|
|
17427
|
-
logger$
|
|
17466
|
+
logger$27.warn({
|
|
17428
17467
|
storyKey,
|
|
17429
17468
|
taskType
|
|
17430
17469
|
}, "Failed to assemble fix prompt, using fallback");
|
|
@@ -17468,7 +17507,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17468
17507
|
if (taskType === "minor-fixes") {
|
|
17469
17508
|
const finalReviewCycles = reviewCycles + 1;
|
|
17470
17509
|
const downgradedVerdict = "LGTM_WITH_NOTES";
|
|
17471
|
-
logger$
|
|
17510
|
+
logger$27.warn({
|
|
17472
17511
|
storyKey,
|
|
17473
17512
|
reviewCycles: finalReviewCycles,
|
|
17474
17513
|
issueCount: issueList.length
|
|
@@ -17488,7 +17527,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17488
17527
|
keepReviewing = false;
|
|
17489
17528
|
return;
|
|
17490
17529
|
}
|
|
17491
|
-
logger$
|
|
17530
|
+
logger$27.warn({
|
|
17492
17531
|
storyKey,
|
|
17493
17532
|
taskType
|
|
17494
17533
|
}, "Fix dispatch timed out — escalating story");
|
|
@@ -17510,7 +17549,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17510
17549
|
}
|
|
17511
17550
|
if (fixResult.status === "failed") {
|
|
17512
17551
|
if (isMajorRework) {
|
|
17513
|
-
logger$
|
|
17552
|
+
logger$27.warn({
|
|
17514
17553
|
storyKey,
|
|
17515
17554
|
exitCode: fixResult.exitCode
|
|
17516
17555
|
}, "Major rework dispatch failed — escalating story");
|
|
@@ -17530,7 +17569,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17530
17569
|
await persistState();
|
|
17531
17570
|
return;
|
|
17532
17571
|
}
|
|
17533
|
-
logger$
|
|
17572
|
+
logger$27.warn({
|
|
17534
17573
|
storyKey,
|
|
17535
17574
|
taskType,
|
|
17536
17575
|
exitCode: fixResult.exitCode
|
|
@@ -17538,7 +17577,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17538
17577
|
}
|
|
17539
17578
|
if (isMajorRework) replaceDevStorySignals(fixResult.parsed);
|
|
17540
17579
|
} catch (err) {
|
|
17541
|
-
logger$
|
|
17580
|
+
logger$27.warn({
|
|
17542
17581
|
storyKey,
|
|
17543
17582
|
taskType,
|
|
17544
17583
|
err
|
|
@@ -17607,7 +17646,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17607
17646
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
17608
17647
|
}
|
|
17609
17648
|
}).catch((err) => {
|
|
17610
|
-
logger$
|
|
17649
|
+
logger$27.warn({ err }, "interactive prompt failed during auth-failure halt — halting anyway");
|
|
17611
17650
|
});
|
|
17612
17651
|
for (const [key, state] of _stories) if (state.phase === "PENDING" && key !== triggeredStoryKey) {
|
|
17613
17652
|
updateStory(key, {
|
|
@@ -17620,7 +17659,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17620
17659
|
escalation_reason: "auth-failure-halt"
|
|
17621
17660
|
}).catch(() => {});
|
|
17622
17661
|
}
|
|
17623
|
-
logger$
|
|
17662
|
+
logger$27.error({
|
|
17624
17663
|
runId,
|
|
17625
17664
|
triggeredStoryKey,
|
|
17626
17665
|
matchedSignature
|
|
@@ -17654,7 +17693,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17654
17693
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
17655
17694
|
}
|
|
17656
17695
|
}).catch((err) => {
|
|
17657
|
-
logger$
|
|
17696
|
+
logger$27.warn({ err }, "interactive prompt failed during cost-ceiling halt — continuing with default action");
|
|
17658
17697
|
});
|
|
17659
17698
|
} else eventBus.emit("decision:autonomous", {
|
|
17660
17699
|
runId,
|
|
@@ -17682,7 +17721,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17682
17721
|
severity: routeResult.severity
|
|
17683
17722
|
});
|
|
17684
17723
|
_budgetExhausted = true;
|
|
17685
|
-
logger$
|
|
17724
|
+
logger$27.warn({
|
|
17686
17725
|
skipped: allSkipped.length,
|
|
17687
17726
|
cumulative: result.cumulative,
|
|
17688
17727
|
ceiling: result.ceiling,
|
|
@@ -17701,7 +17740,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17701
17740
|
const completedStoryKeys = [];
|
|
17702
17741
|
for (const storyKey of group) {
|
|
17703
17742
|
if (_shutdownRequested) {
|
|
17704
|
-
logger$
|
|
17743
|
+
logger$27.info({ storyKey }, "shutdown requested — skipping dispatch");
|
|
17705
17744
|
return;
|
|
17706
17745
|
}
|
|
17707
17746
|
if (runManifest !== null && runManifest !== void 0) try {
|
|
@@ -17724,7 +17763,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17724
17763
|
}
|
|
17725
17764
|
}
|
|
17726
17765
|
} catch (err) {
|
|
17727
|
-
logger$
|
|
17766
|
+
logger$27.debug({ err }, "Cost ceiling check failed — proceeding without enforcement");
|
|
17728
17767
|
}
|
|
17729
17768
|
let optimizationDirectives;
|
|
17730
17769
|
if (telemetryAdvisor !== void 0 && completedStoryKeys.length > 0) try {
|
|
@@ -17732,13 +17771,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
17732
17771
|
const directives = telemetryAdvisor.formatOptimizationDirectives(recs);
|
|
17733
17772
|
if (directives.length > 0) {
|
|
17734
17773
|
optimizationDirectives = directives;
|
|
17735
|
-
logger$
|
|
17774
|
+
logger$27.debug({
|
|
17736
17775
|
storyKey,
|
|
17737
17776
|
directiveCount: recs.filter((r) => r.severity !== "info").length
|
|
17738
17777
|
}, "Optimization directives ready for dispatch");
|
|
17739
17778
|
}
|
|
17740
17779
|
} catch (err) {
|
|
17741
|
-
logger$
|
|
17780
|
+
logger$27.debug({
|
|
17742
17781
|
err,
|
|
17743
17782
|
storyKey
|
|
17744
17783
|
}, "Failed to fetch optimization directives — proceeding without");
|
|
@@ -17862,7 +17901,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17862
17901
|
recommendedAction: "serialize"
|
|
17863
17902
|
});
|
|
17864
17903
|
} catch {}
|
|
17865
|
-
logger$
|
|
17904
|
+
logger$27.info({
|
|
17866
17905
|
storyKeys: evt.storyKeys,
|
|
17867
17906
|
collisionPaths: evt.collisionPaths
|
|
17868
17907
|
}, "Cross-story file collision detected — serializing affected groups to prevent race conditions");
|
|
@@ -17875,7 +17914,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17875
17914
|
mergedGroupMap.set(root2, [...existing, ...group]);
|
|
17876
17915
|
}
|
|
17877
17916
|
const result = [...mergedGroupMap.values()];
|
|
17878
|
-
logger$
|
|
17917
|
+
logger$27.info({
|
|
17879
17918
|
originalGroupCount: batchGroups.length,
|
|
17880
17919
|
mergedGroupCount: result.length,
|
|
17881
17920
|
collisionCount
|
|
@@ -17919,7 +17958,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17919
17958
|
async function shutdownGracefully(reason, signal) {
|
|
17920
17959
|
if (_shutdownRequested) return;
|
|
17921
17960
|
_shutdownRequested = true;
|
|
17922
|
-
logger$
|
|
17961
|
+
logger$27.info({
|
|
17923
17962
|
reason,
|
|
17924
17963
|
signal
|
|
17925
17964
|
}, "Graceful shutdown initiated — stopping new dispatches");
|
|
@@ -17929,8 +17968,8 @@ function createImplementationOrchestrator(deps) {
|
|
|
17929
17968
|
run_status: "stopped",
|
|
17930
17969
|
stopped_reason: reason,
|
|
17931
17970
|
stopped_at: new Date().toISOString()
|
|
17932
|
-
}).catch((err) => logger$
|
|
17933
|
-
if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$
|
|
17971
|
+
}).catch((err) => logger$27.warn({ err }, "patchRunStatus failed during shutdown (best-effort)"));
|
|
17972
|
+
if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$27.warn({ err }, "updatePipelineRun(stopped) failed during shutdown (best-effort)"));
|
|
17934
17973
|
const activePhases = [
|
|
17935
17974
|
"PENDING",
|
|
17936
17975
|
"IN_STORY_CREATION",
|
|
@@ -17941,7 +17980,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17941
17980
|
"CHECKPOINT"
|
|
17942
17981
|
];
|
|
17943
17982
|
const cancellations = [];
|
|
17944
|
-
for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$
|
|
17983
|
+
for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$27.warn({
|
|
17945
17984
|
err,
|
|
17946
17985
|
storyKey
|
|
17947
17986
|
}, "wg_stories → cancelled failed during shutdown (best-effort)")));
|
|
@@ -17950,11 +17989,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
17950
17989
|
}
|
|
17951
17990
|
async function run(storyKeys) {
|
|
17952
17991
|
if (_state === "RUNNING" || _state === "PAUSED") {
|
|
17953
|
-
logger$
|
|
17992
|
+
logger$27.warn({ state: _state }, "run() called while orchestrator is already running or paused — ignoring");
|
|
17954
17993
|
return getStatus();
|
|
17955
17994
|
}
|
|
17956
17995
|
if (_state === "COMPLETE") {
|
|
17957
|
-
logger$
|
|
17996
|
+
logger$27.warn({ state: _state }, "run() called on a COMPLETE orchestrator — ignoring");
|
|
17958
17997
|
return getStatus();
|
|
17959
17998
|
}
|
|
17960
17999
|
_state = "RUNNING";
|
|
@@ -17969,7 +18008,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17969
18008
|
"pipe"
|
|
17970
18009
|
]
|
|
17971
18010
|
}).trim();
|
|
17972
|
-
logger$
|
|
18011
|
+
logger$27.info({ orchestratorStartBranch: _orchestratorStartBranch }, "Captured orchestrator start branch for merge-to-main");
|
|
17973
18012
|
if ((config.acceptanceMode ?? "advisory") === "blocking") try {
|
|
17974
18013
|
_runStartSha = execSync("git rev-parse HEAD", {
|
|
17975
18014
|
cwd: projectRoot,
|
|
@@ -17985,7 +18024,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17985
18024
|
}
|
|
17986
18025
|
if (config.noWorktree === true && (config.acceptanceMode ?? "advisory") === "blocking") {
|
|
17987
18026
|
const warnMsg = "acceptance-tamper-guard-disabled: --no-worktree + acceptance.mode blocking — the spec-tamper tripwire cannot function without worktree isolation (trusted == working tree). An agent can weaken journey specs undetected. Prefer worktree isolation for blocking-mode acceptance.";
|
|
17988
|
-
logger$
|
|
18027
|
+
logger$27.warn({ storyScope: storyKeys }, warnMsg);
|
|
17989
18028
|
eventBus.emit("orchestrator:story-warn", {
|
|
17990
18029
|
storyKey: "(run)",
|
|
17991
18030
|
msg: warnMsg
|
|
@@ -17993,12 +18032,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
17993
18032
|
}
|
|
17994
18033
|
} catch (branchErr) {
|
|
17995
18034
|
if (config.noWorktree !== true) {
|
|
17996
|
-
logger$
|
|
18035
|
+
logger$27.error({ err: branchErr }, "FATAL: failed to capture the orchestrator start branch (git rev-parse --abbrev-ref HEAD). Worktree finalization cannot work without it. Fix git in the project root or re-run with --no-worktree.");
|
|
17997
18036
|
_state = "FAILED";
|
|
17998
18037
|
_completedAt = new Date().toISOString();
|
|
17999
18038
|
return getStatus();
|
|
18000
18039
|
}
|
|
18001
|
-
logger$
|
|
18040
|
+
logger$27.warn({ err: branchErr }, "Failed to capture orchestrator start branch — merge-to-main will skip worktree integration (--no-worktree run)");
|
|
18002
18041
|
}
|
|
18003
18042
|
for (const key of storyKeys) {
|
|
18004
18043
|
const pendingState = {
|
|
@@ -18041,13 +18080,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
18041
18080
|
await persistState();
|
|
18042
18081
|
recordProgress();
|
|
18043
18082
|
if (config.enableHeartbeat) startHeartbeat();
|
|
18044
|
-
if (_orchestratorStartBranch !== void 0 && runManifest !== null) runManifest.patchRunStatus({ orchestrator_start_branch: _orchestratorStartBranch }).catch((err) => logger$
|
|
18083
|
+
if (_orchestratorStartBranch !== void 0 && runManifest !== null) runManifest.patchRunStatus({ orchestrator_start_branch: _orchestratorStartBranch }).catch((err) => logger$27.warn({ err }, "Failed to persist orchestrator_start_branch to manifest (best-effort)"));
|
|
18045
18084
|
const _startupTimings = {};
|
|
18046
18085
|
if (projectRoot !== void 0) {
|
|
18047
18086
|
const seedStart = Date.now();
|
|
18048
18087
|
const seedResult = await seedMethodologyContext(db, projectRoot);
|
|
18049
18088
|
_startupTimings.seedMethodologyMs = Date.now() - seedStart;
|
|
18050
|
-
if (seedResult.decisionsCreated > 0) logger$
|
|
18089
|
+
if (seedResult.decisionsCreated > 0) logger$27.info({
|
|
18051
18090
|
decisionsCreated: seedResult.decisionsCreated,
|
|
18052
18091
|
skippedCategories: seedResult.skippedCategories,
|
|
18053
18092
|
durationMs: _startupTimings.seedMethodologyMs
|
|
@@ -18057,12 +18096,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
18057
18096
|
const ingestStart = Date.now();
|
|
18058
18097
|
try {
|
|
18059
18098
|
const ingestResult = await autoIngestEpicsDependencies(db, projectRoot);
|
|
18060
|
-
if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$
|
|
18099
|
+
if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$27.info({
|
|
18061
18100
|
...ingestResult,
|
|
18062
18101
|
durationMs: Date.now() - ingestStart
|
|
18063
18102
|
}, "Auto-ingested stories and dependencies from epics document");
|
|
18064
18103
|
} catch (err) {
|
|
18065
|
-
logger$
|
|
18104
|
+
logger$27.debug({ err }, "Auto-ingest from epics document skipped — work graph may be unavailable");
|
|
18066
18105
|
}
|
|
18067
18106
|
}
|
|
18068
18107
|
const sigtermHandler = () => {
|
|
@@ -18076,7 +18115,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18076
18115
|
try {
|
|
18077
18116
|
if (ingestionServer !== void 0) {
|
|
18078
18117
|
if (telemetryPersistence !== void 0) try {
|
|
18079
|
-
const pipelineLogger = logger$
|
|
18118
|
+
const pipelineLogger = logger$27;
|
|
18080
18119
|
const telemetryPipeline = new TelemetryPipeline({
|
|
18081
18120
|
normalizer: new TelemetryNormalizer(pipelineLogger),
|
|
18082
18121
|
turnAnalyzer: new TurnAnalyzer(pipelineLogger),
|
|
@@ -18088,14 +18127,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
18088
18127
|
persistence: telemetryPersistence
|
|
18089
18128
|
});
|
|
18090
18129
|
ingestionServer.setPipeline(telemetryPipeline);
|
|
18091
|
-
logger$
|
|
18130
|
+
logger$27.info("TelemetryPipeline wired to IngestionServer");
|
|
18092
18131
|
} catch (pipelineErr) {
|
|
18093
|
-
logger$
|
|
18132
|
+
logger$27.warn({ err: pipelineErr }, "Failed to create TelemetryPipeline — continuing without analysis pipeline");
|
|
18094
18133
|
}
|
|
18095
|
-
await ingestionServer.start().catch((err) => logger$
|
|
18134
|
+
await ingestionServer.start().catch((err) => logger$27.warn({ err }, "IngestionServer.start() failed — continuing without telemetry (best-effort)"));
|
|
18096
18135
|
try {
|
|
18097
18136
|
_otlpEndpoint = ingestionServer.getOtlpEnvVars().OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
18098
|
-
logger$
|
|
18137
|
+
logger$27.info({ otlpEndpoint: _otlpEndpoint }, "OTLP telemetry ingestion active");
|
|
18099
18138
|
} catch {}
|
|
18100
18139
|
}
|
|
18101
18140
|
const interfaceContractDecisions = await getDecisionsByCategory(db, "interface-contract");
|
|
@@ -18121,12 +18160,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
18121
18160
|
const conflictDetectStart = Date.now();
|
|
18122
18161
|
const { batches, edges: contractEdges } = detectConflictGroupsWithContracts(storyKeys, { moduleMap: pack.manifest.conflictGroups }, contractDeclarations);
|
|
18123
18162
|
_startupTimings.conflictDetectMs = Date.now() - conflictDetectStart;
|
|
18124
|
-
if (contractEdges.length > 0) logger$
|
|
18163
|
+
if (contractEdges.length > 0) logger$27.info({
|
|
18125
18164
|
contractEdges,
|
|
18126
18165
|
edgeCount: contractEdges.length
|
|
18127
18166
|
}, "Contract dependency edges detected — applying contract-aware dispatch ordering");
|
|
18128
|
-
wgRepo.addContractDependencies(contractEdges).catch((err) => logger$
|
|
18129
|
-
logger$
|
|
18167
|
+
wgRepo.addContractDependencies(contractEdges).catch((err) => logger$27.warn({ err }, "contract dep persistence failed (best-effort)"));
|
|
18168
|
+
logger$27.info({
|
|
18130
18169
|
storyCount: storyKeys.length,
|
|
18131
18170
|
groupCount: batches.reduce((sum, b) => sum + b.length, 0),
|
|
18132
18171
|
batchCount: batches.length,
|
|
@@ -18136,7 +18175,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18136
18175
|
groups: batch.map((g) => g.join(","))
|
|
18137
18176
|
}))
|
|
18138
18177
|
}, "Orchestrator starting");
|
|
18139
|
-
logger$
|
|
18178
|
+
logger$27.info({
|
|
18140
18179
|
storyCount: storyKeys.length,
|
|
18141
18180
|
conflictGroups: batches.length,
|
|
18142
18181
|
maxConcurrency: config.maxConcurrency
|
|
@@ -18157,7 +18196,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18157
18196
|
exitCode,
|
|
18158
18197
|
output: truncatedOutput
|
|
18159
18198
|
});
|
|
18160
|
-
logger$
|
|
18199
|
+
logger$27.error({
|
|
18161
18200
|
exitCode,
|
|
18162
18201
|
reason: preFlightResult.reason
|
|
18163
18202
|
}, "Pre-flight build check failed — aborting pipeline before any story dispatch");
|
|
@@ -18166,19 +18205,19 @@ function createImplementationOrchestrator(deps) {
|
|
|
18166
18205
|
await persistState();
|
|
18167
18206
|
return getStatus();
|
|
18168
18207
|
}
|
|
18169
|
-
if (preFlightResult.status !== "skipped") logger$
|
|
18208
|
+
if (preFlightResult.status !== "skipped") logger$27.info("Pre-flight build check passed");
|
|
18170
18209
|
}
|
|
18171
|
-
logger$
|
|
18210
|
+
logger$27.info(_startupTimings, "Orchestrator startup timings (ms)");
|
|
18172
18211
|
const totalGroups = batches.reduce((sum, b) => sum + b.length, 0);
|
|
18173
18212
|
const actualConcurrency = Math.min(config.maxConcurrency, totalGroups);
|
|
18174
18213
|
if (actualConcurrency > 1 && projectRoot !== void 0) try {
|
|
18175
18214
|
_packageSnapshot = capturePackageSnapshot({ projectRoot });
|
|
18176
|
-
logger$
|
|
18215
|
+
logger$27.info({
|
|
18177
18216
|
fileCount: _packageSnapshot.files.size,
|
|
18178
18217
|
installCommand: _packageSnapshot.installCommand
|
|
18179
18218
|
}, "Package snapshot captured for concurrent story protection");
|
|
18180
18219
|
} catch (snapErr) {
|
|
18181
|
-
logger$
|
|
18220
|
+
logger$27.warn({ err: snapErr }, "Failed to capture package snapshot — continuing without protection");
|
|
18182
18221
|
}
|
|
18183
18222
|
try {
|
|
18184
18223
|
for (const rawBatchGroups of batches) {
|
|
@@ -18203,14 +18242,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
18203
18242
|
manifest: runManifest,
|
|
18204
18243
|
adapter: db
|
|
18205
18244
|
});
|
|
18206
|
-
if (!recoveryResult.noStale) logger$
|
|
18245
|
+
if (!recoveryResult.noStale) logger$27.info({
|
|
18207
18246
|
recovered: recoveryResult.recovered,
|
|
18208
18247
|
stillFailed: recoveryResult.stillFailed,
|
|
18209
18248
|
recoveredCount: recoveryResult.recovered.length,
|
|
18210
18249
|
stillFailedCount: recoveryResult.stillFailed.length
|
|
18211
18250
|
}, "Cross-story race recovery complete");
|
|
18212
18251
|
} catch (recoveryErr) {
|
|
18213
|
-
logger$
|
|
18252
|
+
logger$27.warn({ err: recoveryErr }, "Cross-story race recovery failed (non-fatal) — pipeline continues");
|
|
18214
18253
|
}
|
|
18215
18254
|
}
|
|
18216
18255
|
}
|
|
@@ -18219,7 +18258,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18219
18258
|
_state = "FAILED";
|
|
18220
18259
|
_completedAt = new Date().toISOString();
|
|
18221
18260
|
await persistState();
|
|
18222
|
-
logger$
|
|
18261
|
+
logger$27.error({ err }, "Orchestrator failed with unhandled error");
|
|
18223
18262
|
return getStatus();
|
|
18224
18263
|
}
|
|
18225
18264
|
stopHeartbeat();
|
|
@@ -18229,7 +18268,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18229
18268
|
const totalDeclarations = contractDeclarations.length;
|
|
18230
18269
|
const currentSprintDeclarations = contractDeclarations.filter((d) => storyKeys.includes(d.storyKey));
|
|
18231
18270
|
const stalePruned = totalDeclarations - currentSprintDeclarations.length;
|
|
18232
|
-
if (stalePruned > 0) logger$
|
|
18271
|
+
if (stalePruned > 0) logger$27.info({
|
|
18233
18272
|
stalePruned,
|
|
18234
18273
|
remaining: currentSprintDeclarations.length
|
|
18235
18274
|
}, "Pruned stale contract declarations from previous epics");
|
|
@@ -18243,11 +18282,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
18243
18282
|
contractName: mismatch.contractName,
|
|
18244
18283
|
mismatchDescription: mismatch.mismatchDescription
|
|
18245
18284
|
});
|
|
18246
|
-
logger$
|
|
18285
|
+
logger$27.warn({
|
|
18247
18286
|
mismatchCount: mismatches.length,
|
|
18248
18287
|
mismatches
|
|
18249
18288
|
}, "Post-sprint contract verification found mismatches — manual review required");
|
|
18250
|
-
} else if (currentSprintDeclarations.length > 0) logger$
|
|
18289
|
+
} else if (currentSprintDeclarations.length > 0) logger$27.info("Post-sprint contract verification passed — all declared contracts satisfied");
|
|
18251
18290
|
eventBus.emit("pipeline:contract-verification-summary", {
|
|
18252
18291
|
verified: currentSprintDeclarations.length,
|
|
18253
18292
|
stalePruned,
|
|
@@ -18255,7 +18294,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18255
18294
|
verdict: mismatches.length === 0 ? "pass" : "fail"
|
|
18256
18295
|
});
|
|
18257
18296
|
} catch (err) {
|
|
18258
|
-
logger$
|
|
18297
|
+
logger$27.error({ err }, "Post-sprint contract verification threw an error — skipping");
|
|
18259
18298
|
}
|
|
18260
18299
|
if (projectRoot !== void 0) try {
|
|
18261
18300
|
const indicators = checkProfileStaleness(projectRoot);
|
|
@@ -18265,10 +18304,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
18265
18304
|
message,
|
|
18266
18305
|
indicators
|
|
18267
18306
|
});
|
|
18268
|
-
logger$
|
|
18307
|
+
logger$27.warn({ indicators }, message);
|
|
18269
18308
|
}
|
|
18270
18309
|
} catch (err) {
|
|
18271
|
-
logger$
|
|
18310
|
+
logger$27.debug({ err }, "Profile staleness check failed (best-effort)");
|
|
18272
18311
|
}
|
|
18273
18312
|
try {
|
|
18274
18313
|
const finalAudit = await auditJourneyCoverage({ final: true }, { persist: true });
|
|
@@ -18276,7 +18315,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18276
18315
|
const criticalViolations = finalAudit.entries.filter((e) => e.criticality === "critical" && (e.state === "unclaimed" || e.state === "unwalked" || e.state === "walked-fail"));
|
|
18277
18316
|
if (criticalViolations.length > 0) {
|
|
18278
18317
|
const msg = `acceptance-coverage-violation (run end): ${String(criticalViolations.length)} journey-critical violation(s) survived to run end — ` + criticalViolations.map((v) => `${v.journeyId} [${v.state}]`).join(", ") + ". In blocking mode these should have been caught at epic close; a residual here indicates a concurrency race or an epic that never formally closed. Inspect the coverage ledger in `substrate report`.";
|
|
18279
|
-
logger$
|
|
18318
|
+
logger$27.error({ criticalViolations: criticalViolations.map((v) => v.journeyId) }, msg);
|
|
18280
18319
|
eventBus.emit("orchestrator:story-warn", {
|
|
18281
18320
|
storyKey: "(run)",
|
|
18282
18321
|
msg
|
|
@@ -18284,7 +18323,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18284
18323
|
}
|
|
18285
18324
|
}
|
|
18286
18325
|
} catch (err) {
|
|
18287
|
-
logger$
|
|
18326
|
+
logger$27.warn({ err }, "A0.3: run-end coverage sweep failed (best-effort)");
|
|
18288
18327
|
}
|
|
18289
18328
|
let completed = 0;
|
|
18290
18329
|
let escalated = 0;
|
|
@@ -18303,7 +18342,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18303
18342
|
} finally {
|
|
18304
18343
|
process.off("SIGTERM", sigtermHandler);
|
|
18305
18344
|
process.off("SIGINT", sigintHandler);
|
|
18306
|
-
if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$
|
|
18345
|
+
if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$27.warn({ err }, "IngestionServer.stop() failed (best-effort)"));
|
|
18307
18346
|
}
|
|
18308
18347
|
}
|
|
18309
18348
|
function pause() {
|
|
@@ -18312,7 +18351,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18312
18351
|
_pauseGate = createPauseGate();
|
|
18313
18352
|
_state = "PAUSED";
|
|
18314
18353
|
eventBus.emit("orchestrator:paused", {});
|
|
18315
|
-
logger$
|
|
18354
|
+
logger$27.info("Orchestrator paused");
|
|
18316
18355
|
}
|
|
18317
18356
|
function resume() {
|
|
18318
18357
|
if (_state !== "PAUSED") return;
|
|
@@ -18323,7 +18362,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18323
18362
|
}
|
|
18324
18363
|
_state = "RUNNING";
|
|
18325
18364
|
eventBus.emit("orchestrator:resumed", {});
|
|
18326
|
-
logger$
|
|
18365
|
+
logger$27.info("Orchestrator resumed");
|
|
18327
18366
|
}
|
|
18328
18367
|
return {
|
|
18329
18368
|
run,
|
|
@@ -19002,7 +19041,7 @@ const CritiqueOutputSchema = z.object({
|
|
|
19002
19041
|
|
|
19003
19042
|
//#endregion
|
|
19004
19043
|
//#region src/modules/phase-orchestrator/critique-loop.ts
|
|
19005
|
-
const logger$
|
|
19044
|
+
const logger$8 = createLogger("critique-loop");
|
|
19006
19045
|
/**
|
|
19007
19046
|
* Maps a phase name to the critique prompt template name.
|
|
19008
19047
|
* Falls back to `critique-${phase}` for unknown phases.
|
|
@@ -19056,7 +19095,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19056
19095
|
critiquePrompt = critiqueTemplate.replace("{{artifact_content}}", currentArtifact).replace("{{project_context}}", projectContext);
|
|
19057
19096
|
} catch (err) {
|
|
19058
19097
|
const message = err instanceof Error ? err.message : String(err);
|
|
19059
|
-
logger$
|
|
19098
|
+
logger$8.warn({
|
|
19060
19099
|
phaseId,
|
|
19061
19100
|
promptName: critiquePromptName,
|
|
19062
19101
|
err: message
|
|
@@ -19084,7 +19123,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19084
19123
|
critiqueTokens.output += result.tokenEstimate.output;
|
|
19085
19124
|
if (result.status !== "completed" || result.parsed === null) {
|
|
19086
19125
|
const errMsg = result.parseError ?? `Critique dispatch ended with status '${result.status}'`;
|
|
19087
|
-
logger$
|
|
19126
|
+
logger$8.warn({
|
|
19088
19127
|
phaseId,
|
|
19089
19128
|
iteration: i + 1,
|
|
19090
19129
|
err: errMsg
|
|
@@ -19103,7 +19142,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19103
19142
|
lastCritiqueOutput = critiqueOutput;
|
|
19104
19143
|
} catch (err) {
|
|
19105
19144
|
const message = err instanceof Error ? err.message : String(err);
|
|
19106
|
-
logger$
|
|
19145
|
+
logger$8.warn({
|
|
19107
19146
|
phaseId,
|
|
19108
19147
|
iteration: i + 1,
|
|
19109
19148
|
err: message
|
|
@@ -19143,14 +19182,14 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19143
19182
|
});
|
|
19144
19183
|
} catch (err) {
|
|
19145
19184
|
const message = err instanceof Error ? err.message : String(err);
|
|
19146
|
-
logger$
|
|
19185
|
+
logger$8.warn({
|
|
19147
19186
|
phaseId,
|
|
19148
19187
|
iteration: i + 1,
|
|
19149
19188
|
err: message
|
|
19150
19189
|
}, "Critique loop: failed to store critique decision — continuing");
|
|
19151
19190
|
}
|
|
19152
19191
|
if (critiqueOutput.verdict === "pass") {
|
|
19153
|
-
logger$
|
|
19192
|
+
logger$8.info({
|
|
19154
19193
|
phaseId,
|
|
19155
19194
|
iteration: i + 1
|
|
19156
19195
|
}, "Critique loop: artifact passed critique — loop complete");
|
|
@@ -19163,7 +19202,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19163
19202
|
totalMs: Date.now() - startMs
|
|
19164
19203
|
};
|
|
19165
19204
|
}
|
|
19166
|
-
logger$
|
|
19205
|
+
logger$8.info({
|
|
19167
19206
|
phaseId,
|
|
19168
19207
|
iteration: i + 1,
|
|
19169
19208
|
issueCount: critiqueOutput.issue_count
|
|
@@ -19176,7 +19215,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19176
19215
|
refinePrompt = refineTemplate.replace("{{original_artifact}}", currentArtifact).replace("{{critique_issues}}", issuesText).replace("{{phase_context}}", phaseContext);
|
|
19177
19216
|
} catch (err) {
|
|
19178
19217
|
const message = err instanceof Error ? err.message : String(err);
|
|
19179
|
-
logger$
|
|
19218
|
+
logger$8.warn({
|
|
19180
19219
|
phaseId,
|
|
19181
19220
|
iteration: i + 1,
|
|
19182
19221
|
err: message
|
|
@@ -19197,7 +19236,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19197
19236
|
const originalLength = currentArtifact.length;
|
|
19198
19237
|
const refinedLength = refineResult.output.length;
|
|
19199
19238
|
const delta = refinedLength - originalLength;
|
|
19200
|
-
logger$
|
|
19239
|
+
logger$8.info({
|
|
19201
19240
|
phaseId,
|
|
19202
19241
|
iteration: i + 1,
|
|
19203
19242
|
originalLength,
|
|
@@ -19206,7 +19245,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19206
19245
|
}, "Critique loop: refinement complete");
|
|
19207
19246
|
currentArtifact = refineResult.output;
|
|
19208
19247
|
} else {
|
|
19209
|
-
logger$
|
|
19248
|
+
logger$8.warn({
|
|
19210
19249
|
phaseId,
|
|
19211
19250
|
iteration: i + 1,
|
|
19212
19251
|
status: refineResult.status
|
|
@@ -19215,7 +19254,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19215
19254
|
}
|
|
19216
19255
|
} catch (err) {
|
|
19217
19256
|
const message = err instanceof Error ? err.message : String(err);
|
|
19218
|
-
logger$
|
|
19257
|
+
logger$8.warn({
|
|
19219
19258
|
phaseId,
|
|
19220
19259
|
iteration: i + 1,
|
|
19221
19260
|
err: message
|
|
@@ -19226,12 +19265,12 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19226
19265
|
}
|
|
19227
19266
|
const remainingIssues = lastCritiqueOutput?.issues ?? [];
|
|
19228
19267
|
if (remainingIssues.length > 0) {
|
|
19229
|
-
logger$
|
|
19268
|
+
logger$8.warn({
|
|
19230
19269
|
phaseId,
|
|
19231
19270
|
maxIterations,
|
|
19232
19271
|
issueCount: remainingIssues.length
|
|
19233
19272
|
}, "Critique loop: max iterations reached with unresolved issues");
|
|
19234
|
-
for (const issue of remainingIssues) logger$
|
|
19273
|
+
for (const issue of remainingIssues) logger$8.warn({
|
|
19235
19274
|
phaseId,
|
|
19236
19275
|
severity: issue.severity,
|
|
19237
19276
|
category: issue.category,
|
|
@@ -19250,7 +19289,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
|
|
|
19250
19289
|
|
|
19251
19290
|
//#endregion
|
|
19252
19291
|
//#region src/modules/phase-orchestrator/elicitation-selector.ts
|
|
19253
|
-
const logger$
|
|
19292
|
+
const logger$7 = createLogger("elicitation-selector");
|
|
19254
19293
|
/**
|
|
19255
19294
|
* Affinity scores (0.0–1.0) for each category per content type.
|
|
19256
19295
|
*
|
|
@@ -19372,10 +19411,10 @@ function loadElicitationMethods() {
|
|
|
19372
19411
|
try {
|
|
19373
19412
|
const content = readFileSync$1(csvPath, "utf-8");
|
|
19374
19413
|
const methods = parseMethodsCsv(content);
|
|
19375
|
-
logger$
|
|
19414
|
+
logger$7.debug({ count: methods.length }, "Loaded elicitation methods");
|
|
19376
19415
|
return methods;
|
|
19377
19416
|
} catch (err) {
|
|
19378
|
-
logger$
|
|
19417
|
+
logger$7.warn({
|
|
19379
19418
|
csvPath,
|
|
19380
19419
|
err
|
|
19381
19420
|
}, "Failed to load elicitation methods CSV");
|
|
@@ -19648,13 +19687,36 @@ const UxDesignSystemOutputSchema = z.object({
|
|
|
19648
19687
|
color_and_typography: z.string().optional()
|
|
19649
19688
|
});
|
|
19650
19689
|
/**
|
|
19690
|
+
* RP4.1 (registry-provenance): a STRUCTURED user journey emitted by the UX
|
|
19691
|
+
* phase — machine-shaped at the moment the planning lineage authors it, so
|
|
19692
|
+
* the solutioning-close hook can synthesize a journey-registry CANDIDATE
|
|
19693
|
+
* instead of the vision being discarded as prose and re-derived by hand
|
|
19694
|
+
* later (transcription loss).
|
|
19695
|
+
*/
|
|
19696
|
+
const StructuredUserJourneySchema = z.object({
|
|
19697
|
+
id: z.string().min(1),
|
|
19698
|
+
title: z.string().min(1),
|
|
19699
|
+
criticality: z.enum(["critical", "standard"]).default("standard"),
|
|
19700
|
+
surfaces: z.array(z.enum([
|
|
19701
|
+
"email",
|
|
19702
|
+
"cli",
|
|
19703
|
+
"file",
|
|
19704
|
+
"web"
|
|
19705
|
+
])).min(1),
|
|
19706
|
+
walk: z.string().min(1)
|
|
19707
|
+
});
|
|
19708
|
+
/**
|
|
19651
19709
|
* Step 3 output: User Journeys + Component Strategy + Accessibility.
|
|
19652
19710
|
* Covers user flows, component architecture, UX patterns, and a11y guidelines.
|
|
19653
19711
|
* Content fields are optional to allow `{result: 'failed'}` without Zod rejection.
|
|
19712
|
+
*
|
|
19713
|
+
* RP4.1: `user_journeys` entries are structured objects (preferred) or prose
|
|
19714
|
+
* strings (legacy fallback — always legal; prose journeys cannot feed the
|
|
19715
|
+
* candidate hook and derive to needs-elaboration by hand instead).
|
|
19654
19716
|
*/
|
|
19655
19717
|
const UxJourneysOutputSchema = z.object({
|
|
19656
19718
|
result: z.enum(["success", "failed"]),
|
|
19657
|
-
user_journeys: z.array(z.string().min(1)).optional(),
|
|
19719
|
+
user_journeys: z.array(z.union([z.string().min(1), StructuredUserJourneySchema])).optional(),
|
|
19658
19720
|
component_strategy: z.string().optional(),
|
|
19659
19721
|
ux_patterns: z.array(z.string()).default([]),
|
|
19660
19722
|
accessibility_guidelines: z.array(z.string()).default([])
|
|
@@ -19695,7 +19757,7 @@ const ElicitationOutputSchema = z.object({
|
|
|
19695
19757
|
|
|
19696
19758
|
//#endregion
|
|
19697
19759
|
//#region src/modules/phase-orchestrator/step-runner.ts
|
|
19698
|
-
const logger$
|
|
19760
|
+
const logger$6 = createLogger("step-runner");
|
|
19699
19761
|
/**
|
|
19700
19762
|
* Format an array of decision records into a markdown section for injection.
|
|
19701
19763
|
*
|
|
@@ -19802,7 +19864,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
19802
19864
|
if (estimatedTokens > budgetTokens) {
|
|
19803
19865
|
const decisionRefs = step.context.filter((ref) => ref.source.startsWith("decision:"));
|
|
19804
19866
|
if (decisionRefs.length > 0) {
|
|
19805
|
-
logger$
|
|
19867
|
+
logger$6.warn({
|
|
19806
19868
|
step: step.name,
|
|
19807
19869
|
estimatedTokens,
|
|
19808
19870
|
budgetTokens
|
|
@@ -19829,7 +19891,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
19829
19891
|
}
|
|
19830
19892
|
prompt = summarizedPrompt;
|
|
19831
19893
|
estimatedTokens = Math.ceil(prompt.length / 4);
|
|
19832
|
-
if (estimatedTokens <= budgetTokens) logger$
|
|
19894
|
+
if (estimatedTokens <= budgetTokens) logger$6.info({
|
|
19833
19895
|
step: step.name,
|
|
19834
19896
|
estimatedTokens,
|
|
19835
19897
|
budgetTokens
|
|
@@ -20010,7 +20072,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
20010
20072
|
const critiqueResult = await runCritiqueLoop(artifactContent, phase, runId, phase, deps);
|
|
20011
20073
|
totalInput += critiqueResult.critiqueTokens.input + critiqueResult.refinementTokens.input;
|
|
20012
20074
|
totalOutput += critiqueResult.critiqueTokens.output + critiqueResult.refinementTokens.output;
|
|
20013
|
-
logger$
|
|
20075
|
+
logger$6.info({
|
|
20014
20076
|
step: step.name,
|
|
20015
20077
|
verdict: critiqueResult.verdict,
|
|
20016
20078
|
iterations: critiqueResult.iterations,
|
|
@@ -20018,7 +20080,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
20018
20080
|
}, "Step critique loop complete");
|
|
20019
20081
|
} catch (critiqueErr) {
|
|
20020
20082
|
const critiqueMsg = critiqueErr instanceof Error ? critiqueErr.message : String(critiqueErr);
|
|
20021
|
-
logger$
|
|
20083
|
+
logger$6.warn({
|
|
20022
20084
|
step: step.name,
|
|
20023
20085
|
err: critiqueMsg
|
|
20024
20086
|
}, "Step critique loop threw an error — continuing without critique");
|
|
@@ -20028,7 +20090,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
20028
20090
|
const contentType = deriveContentType(phase, step.name);
|
|
20029
20091
|
const selectedMethods = selectMethods({ content_type: contentType }, usedElicitationMethods);
|
|
20030
20092
|
if (selectedMethods.length > 0) {
|
|
20031
|
-
logger$
|
|
20093
|
+
logger$6.info({
|
|
20032
20094
|
step: step.name,
|
|
20033
20095
|
methods: selectedMethods.map((m) => m.name),
|
|
20034
20096
|
contentType
|
|
@@ -20067,13 +20129,13 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
20067
20129
|
key: `${phase}-round-${roundIndex}-insights`,
|
|
20068
20130
|
value: elicitParsed.insights
|
|
20069
20131
|
});
|
|
20070
|
-
logger$
|
|
20132
|
+
logger$6.info({
|
|
20071
20133
|
step: step.name,
|
|
20072
20134
|
method: method.name,
|
|
20073
20135
|
roundIndex
|
|
20074
20136
|
}, "Elicitation insights stored in decision store");
|
|
20075
20137
|
}
|
|
20076
|
-
} else logger$
|
|
20138
|
+
} else logger$6.warn({
|
|
20077
20139
|
step: step.name,
|
|
20078
20140
|
method: method.name,
|
|
20079
20141
|
status: elicitResult.status
|
|
@@ -20089,7 +20151,7 @@ async function runSteps(steps, deps, runId, phase, params) {
|
|
|
20089
20151
|
}
|
|
20090
20152
|
} catch (elicitErr) {
|
|
20091
20153
|
const elicitMsg = elicitErr instanceof Error ? elicitErr.message : String(elicitErr);
|
|
20092
|
-
logger$
|
|
20154
|
+
logger$6.warn({
|
|
20093
20155
|
step: step.name,
|
|
20094
20156
|
err: elicitMsg
|
|
20095
20157
|
}, "Step elicitation threw an error — continuing without elicitation");
|
|
@@ -20457,7 +20519,7 @@ async function runAnalysisPhase(deps, params) {
|
|
|
20457
20519
|
|
|
20458
20520
|
//#endregion
|
|
20459
20521
|
//#region src/modules/phase-orchestrator/phases/planning.ts
|
|
20460
|
-
const logger$
|
|
20522
|
+
const logger$5 = createLogger("planning-phase");
|
|
20461
20523
|
/** Maximum total prompt length in tokens (3,500 tokens × 4 chars/token = 14,000 chars) */
|
|
20462
20524
|
const MAX_PROMPT_TOKENS = 3500;
|
|
20463
20525
|
const MAX_PROMPT_CHARS = MAX_PROMPT_TOKENS * 4;
|
|
@@ -20684,7 +20746,7 @@ async function runPlanningMultiStep(deps, params) {
|
|
|
20684
20746
|
const techConstraintDecisions = allAnalysisDecisions.filter((d) => d.category === "technology-constraints");
|
|
20685
20747
|
const violation = detectTechStackViolation(techStack, techConstraintDecisions);
|
|
20686
20748
|
if (violation) {
|
|
20687
|
-
logger$
|
|
20749
|
+
logger$5.warn({ violation }, "Tech stack constraint violation detected — retrying step 3 with correction");
|
|
20688
20750
|
const correctionPrefix = `CRITICAL CORRECTION: Your previous output was rejected because it violates the stated technology constraints.\n\nViolation: ${violation}\n\nYou MUST NOT use TypeScript, JavaScript, or Node.js for ANY backend service. Choose from Go, Kotlin/JVM, or Rust as stated in the technology constraints.\n\nRe-generate your output with a compliant tech stack. Everything else (NFRs, domain model, out-of-scope) can remain the same.\n\n---\n\n`;
|
|
20689
20751
|
const step3Template = await deps.pack.getPrompt("planning-step-3-nfrs");
|
|
20690
20752
|
const stepOutputs = new Map();
|
|
@@ -20711,10 +20773,10 @@ async function runPlanningMultiStep(deps, params) {
|
|
|
20711
20773
|
const retryTechStack = retryParsed.tech_stack;
|
|
20712
20774
|
const retryViolation = retryTechStack ? detectTechStackViolation(retryTechStack, techConstraintDecisions) : null;
|
|
20713
20775
|
if (!retryViolation) {
|
|
20714
|
-
logger$
|
|
20776
|
+
logger$5.info("Retry produced compliant tech stack — using corrected output");
|
|
20715
20777
|
nfrsOutput = retryParsed;
|
|
20716
|
-
} else logger$
|
|
20717
|
-
} else logger$
|
|
20778
|
+
} else logger$5.warn({ retryViolation }, "Retry still violates constraints — using original output");
|
|
20779
|
+
} else logger$5.warn("Retry dispatch failed — using original output");
|
|
20718
20780
|
}
|
|
20719
20781
|
}
|
|
20720
20782
|
const frs = frsOutput.functional_requirements;
|
|
@@ -20959,6 +21021,114 @@ async function runPlanningPhase(deps, params) {
|
|
|
20959
21021
|
}
|
|
20960
21022
|
}
|
|
20961
21023
|
|
|
21024
|
+
//#endregion
|
|
21025
|
+
//#region src/modules/phase-orchestrator/acceptance-candidate.ts
|
|
21026
|
+
const logger$4 = createLogger("phase-orchestrator:acceptance-candidate");
|
|
21027
|
+
/** Source snapshot the candidate's provenance points at (hashable, committable). */
|
|
21028
|
+
const PLANNING_JOURNEYS_PATH = ".substrate/acceptance/planning-journeys.yaml";
|
|
21029
|
+
/** Extract structured journeys from the persisted ux-design decision (prose entries are legal and skipped). */
|
|
21030
|
+
function extractStructuredJourneys(rawDecisionValue) {
|
|
21031
|
+
let parsed;
|
|
21032
|
+
try {
|
|
21033
|
+
parsed = JSON.parse(rawDecisionValue);
|
|
21034
|
+
} catch {
|
|
21035
|
+
return [];
|
|
21036
|
+
}
|
|
21037
|
+
if (!Array.isArray(parsed)) return [];
|
|
21038
|
+
const out = [];
|
|
21039
|
+
for (const entry of parsed) {
|
|
21040
|
+
const result = StructuredUserJourneySchema.safeParse(entry);
|
|
21041
|
+
if (result.success) out.push(result.data);
|
|
21042
|
+
}
|
|
21043
|
+
return out;
|
|
21044
|
+
}
|
|
21045
|
+
async function emitAcceptanceCandidateFromPlanning(deps, runId, projectRoot) {
|
|
21046
|
+
try {
|
|
21047
|
+
const decisions = await getDecisionsByPhaseForRun(deps.db, runId, "ux-design");
|
|
21048
|
+
const journeysDecision = decisions.find((d) => d.category === "ux-design" && d.key === "user_journeys");
|
|
21049
|
+
if (journeysDecision === void 0) return {
|
|
21050
|
+
status: "skipped",
|
|
21051
|
+
reason: "no ux-design user_journeys decision"
|
|
21052
|
+
};
|
|
21053
|
+
const structured = extractStructuredJourneys(journeysDecision.value);
|
|
21054
|
+
if (structured.length === 0) return {
|
|
21055
|
+
status: "skipped",
|
|
21056
|
+
reason: "user_journeys are prose-only (structured emission not available) — derive from the PRD by hand"
|
|
21057
|
+
};
|
|
21058
|
+
const candidateAbs = join$1(projectRoot, JOURNEY_CANDIDATE_PATH);
|
|
21059
|
+
try {
|
|
21060
|
+
await readFile$1(candidateAbs, "utf-8");
|
|
21061
|
+
logger$4.warn({ candidatePath: JOURNEY_CANDIDATE_PATH }, "RP4.2: a journey candidate already exists — leaving it untouched (review it, or delete it and re-run)");
|
|
21062
|
+
return {
|
|
21063
|
+
status: "skipped",
|
|
21064
|
+
reason: "candidate already exists"
|
|
21065
|
+
};
|
|
21066
|
+
} catch {}
|
|
21067
|
+
const snapshot = "# Structured user journeys emitted by the UX phase (RP4.1).\n# This file is the derivation SOURCE of journeys.candidate.yaml — its\n# hash is recorded at ratify time as the staleness baseline. COMMIT it.\n" + dump({
|
|
21068
|
+
source: "ux-design",
|
|
21069
|
+
run_id: runId,
|
|
21070
|
+
journeys: structured
|
|
21071
|
+
}, { lineWidth: 120 });
|
|
21072
|
+
const snapshotAbs = join$1(projectRoot, PLANNING_JOURNEYS_PATH);
|
|
21073
|
+
await mkdir$1(dirname$1(snapshotAbs), { recursive: true });
|
|
21074
|
+
await writeFile$1(snapshotAbs, snapshot, "utf-8");
|
|
21075
|
+
const sourceSha256 = createHash("sha256").update(snapshot, "utf-8").digest("hex");
|
|
21076
|
+
const candidateDoc = {
|
|
21077
|
+
candidate: true,
|
|
21078
|
+
derived_from: PLANNING_JOURNEYS_PATH,
|
|
21079
|
+
source_sha256: sourceSha256,
|
|
21080
|
+
derived_at: new Date().toISOString(),
|
|
21081
|
+
journeys: structured.map((j$1) => ({
|
|
21082
|
+
id: j$1.id,
|
|
21083
|
+
title: j$1.title,
|
|
21084
|
+
criticality: j$1.criticality,
|
|
21085
|
+
criticality_rationale: "as emitted by the UX planning phase (RP4.1 structured journey)",
|
|
21086
|
+
surfaces: j$1.surfaces,
|
|
21087
|
+
end_states: []
|
|
21088
|
+
}))
|
|
21089
|
+
};
|
|
21090
|
+
const header = "# CANDIDATE journey registry — NOT authoritative.\n# Synthesized at solutioning close from the UX phase's structured journeys;\n# the acceptance gate IGNORES this file. Elaborate end_states, then promote\n# via your explicit `substrate acceptance ratify` — nothing does it for you.\n";
|
|
21091
|
+
await writeFile$1(candidateAbs, header + dump(candidateDoc, { lineWidth: 120 }), "utf-8");
|
|
21092
|
+
let undispositioned = [];
|
|
21093
|
+
try {
|
|
21094
|
+
const registryContent = await readFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), "utf-8");
|
|
21095
|
+
const parsedRegistry = parseJourneyRegistry(registryContent);
|
|
21096
|
+
if (parsedRegistry.ok) {
|
|
21097
|
+
undispositioned = computeUndispositioned(structured.map((j$1) => j$1.id), parsedRegistry.registry).filter((d) => d.disposition === "undispositioned").map((d) => d.id);
|
|
21098
|
+
if (undispositioned.length > 0) logger$4.warn({ undispositioned }, "RP4.2: journey-undispositioned (advisory) — the planning lineage emitted journey(s) the ratified registry neither covers nor excludes; register them (ratify the new candidate) or exclude them with a reason");
|
|
21099
|
+
}
|
|
21100
|
+
} catch {}
|
|
21101
|
+
const criticalCount = structured.filter((j$1) => j$1.criticality === "critical").length;
|
|
21102
|
+
logger$4.info({
|
|
21103
|
+
candidatePath: JOURNEY_CANDIDATE_PATH,
|
|
21104
|
+
journeyCount: structured.length,
|
|
21105
|
+
criticalCount
|
|
21106
|
+
}, "RP4.2: journey candidate synthesized from planning artifacts — review + ratify to arm the acceptance gate");
|
|
21107
|
+
deps.eventBus?.emit("solutioning:acceptance-candidate", {
|
|
21108
|
+
runId,
|
|
21109
|
+
candidatePath: JOURNEY_CANDIDATE_PATH,
|
|
21110
|
+
journeyCount: structured.length,
|
|
21111
|
+
criticalCount,
|
|
21112
|
+
sourceSha256,
|
|
21113
|
+
undispositioned
|
|
21114
|
+
});
|
|
21115
|
+
return {
|
|
21116
|
+
status: "written",
|
|
21117
|
+
candidatePath: JOURNEY_CANDIDATE_PATH,
|
|
21118
|
+
journeyCount: structured.length,
|
|
21119
|
+
criticalCount,
|
|
21120
|
+
sourceSha256,
|
|
21121
|
+
undispositioned
|
|
21122
|
+
};
|
|
21123
|
+
} catch (err) {
|
|
21124
|
+
logger$4.warn({ err: err instanceof Error ? err.message : String(err) }, "RP4.2: acceptance-candidate hook failed (non-fatal)");
|
|
21125
|
+
return {
|
|
21126
|
+
status: "skipped",
|
|
21127
|
+
reason: `hook error: ${err instanceof Error ? err.message : String(err)}`
|
|
21128
|
+
};
|
|
21129
|
+
}
|
|
21130
|
+
}
|
|
21131
|
+
|
|
20962
21132
|
//#endregion
|
|
20963
21133
|
//#region src/modules/phase-orchestrator/schemas/readiness-output.ts
|
|
20964
21134
|
/**
|
|
@@ -21858,8 +22028,8 @@ async function runSolutioningPhase(deps, params) {
|
|
|
21858
22028
|
output: totalOutput
|
|
21859
22029
|
}
|
|
21860
22030
|
};
|
|
21861
|
-
|
|
21862
|
-
|
|
22031
|
+
const retryBlockers = retryReadiness.findings.filter((f$1) => f$1.severity === "blocker");
|
|
22032
|
+
if (retryReadiness.verdict === "NOT_READY" || retryBlockers.length > 0) {
|
|
21863
22033
|
logger$3.error({
|
|
21864
22034
|
runId: params.runId,
|
|
21865
22035
|
verdict: retryReadiness.verdict,
|
|
@@ -21883,6 +22053,7 @@ async function runSolutioningPhase(deps, params) {
|
|
|
21883
22053
|
};
|
|
21884
22054
|
}
|
|
21885
22055
|
const retryStories = retryResult.epics.reduce((sum, epic) => sum + epic.stories.length, 0);
|
|
22056
|
+
await emitAcceptanceCandidateFromPlanning(deps, params.runId, process.cwd());
|
|
21886
22057
|
const minorFindings$1 = retryReadiness.findings.filter((f$1) => f$1.severity === "minor");
|
|
21887
22058
|
if (minorFindings$1.length > 0) logger$3.warn({
|
|
21888
22059
|
runId: params.runId,
|
|
@@ -21890,7 +22061,7 @@ async function runSolutioningPhase(deps, params) {
|
|
|
21890
22061
|
}, "Readiness READY with minor findings after retry");
|
|
21891
22062
|
if (deps.eventBus) deps.eventBus.emit("solutioning:readiness-check", {
|
|
21892
22063
|
runId: params.runId,
|
|
21893
|
-
verdict:
|
|
22064
|
+
verdict: retryReadiness.verdict,
|
|
21894
22065
|
coverageScore: retryReadiness.coverageScore,
|
|
21895
22066
|
findingCount: retryReadiness.findings.length,
|
|
21896
22067
|
blockerCount: 0
|
|
@@ -21942,6 +22113,7 @@ async function runSolutioningPhase(deps, params) {
|
|
|
21942
22113
|
findingCount: readinessResult.findings.length,
|
|
21943
22114
|
blockerCount: 0
|
|
21944
22115
|
});
|
|
22116
|
+
await emitAcceptanceCandidateFromPlanning(deps, params.runId, process.cwd());
|
|
21945
22117
|
const totalStories = storyResult.epics.reduce((sum, epic) => sum + epic.stories.length, 0);
|
|
21946
22118
|
return {
|
|
21947
22119
|
result: "success",
|
|
@@ -35415,16 +35587,16 @@ var require_ajv = __commonJS({ "node_modules/ajv/lib/ajv.js"(exports, module) {
|
|
|
35415
35587
|
return metaOpts;
|
|
35416
35588
|
}
|
|
35417
35589
|
function setLogger(self) {
|
|
35418
|
-
var logger$
|
|
35419
|
-
if (logger$
|
|
35590
|
+
var logger$27 = self._opts.logger;
|
|
35591
|
+
if (logger$27 === false) self.logger = {
|
|
35420
35592
|
log: noop,
|
|
35421
35593
|
warn: noop,
|
|
35422
35594
|
error: noop
|
|
35423
35595
|
};
|
|
35424
35596
|
else {
|
|
35425
|
-
if (logger$
|
|
35426
|
-
if (!(typeof logger$
|
|
35427
|
-
self.logger = logger$
|
|
35597
|
+
if (logger$27 === void 0) logger$27 = console;
|
|
35598
|
+
if (!(typeof logger$27 == "object" && logger$27.log && logger$27.warn && logger$27.error)) throw new Error("logger must implement log, warn and error methods");
|
|
35599
|
+
self.logger = logger$27;
|
|
35428
35600
|
}
|
|
35429
35601
|
}
|
|
35430
35602
|
function noop() {}
|
|
@@ -46565,6 +46737,17 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
|
|
|
46565
46737
|
summary: payload.summary
|
|
46566
46738
|
});
|
|
46567
46739
|
});
|
|
46740
|
+
eventBus.on("solutioning:acceptance-candidate", (payload) => {
|
|
46741
|
+
ndjsonEmitter.emit({
|
|
46742
|
+
type: "acceptance:derived",
|
|
46743
|
+
ts: new Date().toISOString(),
|
|
46744
|
+
candidate_path: payload.candidatePath,
|
|
46745
|
+
journey_count: payload.journeyCount,
|
|
46746
|
+
critical_count: payload.criticalCount,
|
|
46747
|
+
source_sha256: payload.sourceSha256,
|
|
46748
|
+
undispositioned: payload.undispositioned
|
|
46749
|
+
});
|
|
46750
|
+
});
|
|
46568
46751
|
eventBus.on("orchestrator:acceptance-registry-stale", (payload) => {
|
|
46569
46752
|
ndjsonEmitter.emit({
|
|
46570
46753
|
type: "acceptance:registry-stale",
|
|
@@ -47891,7 +48074,8 @@ async function runFullPipeline(options) {
|
|
|
47891
48074
|
pack,
|
|
47892
48075
|
contextCompiler,
|
|
47893
48076
|
dispatcher,
|
|
47894
|
-
agentId
|
|
48077
|
+
agentId,
|
|
48078
|
+
eventBus
|
|
47895
48079
|
};
|
|
47896
48080
|
let effectiveResearch = pack.manifest.research === true;
|
|
47897
48081
|
if (researchFlag === true) effectiveResearch = true;
|
|
@@ -48435,4 +48619,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
|
|
|
48435
48619
|
|
|
48436
48620
|
//#endregion
|
|
48437
48621
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
|
|
48438
|
-
//# sourceMappingURL=run-
|
|
48622
|
+
//# sourceMappingURL=run-BYySwmdu.js.map
|