substrate-ai 0.21.5 → 0.21.7
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/adapter-registry-Csta1uJX.js +4 -0
- package/dist/cli/index.js +32 -16
- package/dist/{decisions-lxU14pNh.js → decisions-Blw6BzGL.js} +1 -1
- package/dist/{dist-CpnLJuVw.js → dist-DeyV_vqU.js} +3 -2
- package/dist/{errors-8tVEwG6v.js → errors-BgV6pqUZ.js} +2 -2
- package/dist/{experimenter-C7swe92R.js → experimenter-DDuRR16z.js} +1 -1
- package/dist/{health-hYMxKqAH.js → health-B1UtVXWb.js} +3 -3
- package/dist/{health-BdYZpCP1.js → health-CmY5G4PV.js} +3 -3
- package/dist/index.d.ts +57 -1
- package/dist/index.js +2 -2
- package/dist/{interactive-prompt-BvY2FKsl.js → interactive-prompt-CELNI8nZ.js} +2 -2
- package/dist/{manifest-read-C0N7b9nH.js → manifest-read-Ce5Y-iNu.js} +286 -4
- package/dist/modules/interactive-prompt/index.js +3 -3
- package/dist/{routing-CGO2UZyA.js → routing-uZdhcjzV.js} +1 -1
- package/dist/{run-CHMwDPRx.js → run-BCrwTBDr.js} +5 -5
- package/dist/{run-C7PLGWT0.js → run-DsjRvAd4.js} +973 -507
- package/dist/src/modules/recovery-engine/index.d.ts +9 -0
- package/dist/{upgrade-M0UkDCeg.js → upgrade-BkP-yFWV.js} +2 -2
- package/dist/{upgrade-BUSzXgnd.js → upgrade-lE_GIvWv.js} +2 -2
- package/dist/{version-manager-impl-DeEPhQlA.js → version-manager-impl-Cc7yx4i5.js} +1 -1
- package/package.json +1 -1
- package/packs/bmad/manifest.yaml +3 -0
- package/packs/bmad/prompts/acceptance-judge.md +58 -0
- package/dist/adapter-registry-BSig1zpx.js +0 -4
|
@@ -1,11 +1,11 @@
|
|
|
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-B1UtVXWb.js";
|
|
2
2
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
3
3
|
import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
|
|
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-
|
|
5
|
-
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, FindingsInjector, JOURNEY_DEFERRALS_PATH, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, computeJourneyCoverage, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, loadAcceptanceContractFromTrustedTree, loadJourneyDeferralsFromTrustedTree, loadJourneyRegistryFromTrustedTree, parseRuntimeProbes, parseStoryFrontmatter, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery, summarizeCoverage } from "./manifest-read-
|
|
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-DeyV_vqU.js";
|
|
5
|
+
import { ACCEPTANCE_CONTRACT_PROFILE_PATH, FindingsInjector, JOURNEY_DEFERRALS_PATH, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, computeJourneyCoverage, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, loadAcceptanceContractFromTrustedTree, loadJourneyDeferralsFromTrustedTree, loadJourneyRegistryFromTrustedTree, parseRuntimeProbes, parseStoryFrontmatter, renderFindings, renderSurface, renderVerdictHtml, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery, summarizeCoverage } from "./manifest-read-Ce5Y-iNu.js";
|
|
6
6
|
import { WorkGraphRepository, detectCycles } from "./work-graph-repository-DZyJv5pV.js";
|
|
7
7
|
import { deriveExitCode, routeDecision } from "./decision-router-BAPpON_C.js";
|
|
8
|
-
import { runInteractivePrompt } from "./interactive-prompt-
|
|
8
|
+
import { runInteractivePrompt } from "./interactive-prompt-CELNI8nZ.js";
|
|
9
9
|
import { runRecoveryEngine } from "./recovery-engine-BKGBeBnW.js";
|
|
10
10
|
import { basename, dirname, extname, join } from "path";
|
|
11
11
|
import { access, readFile, readdir, stat } from "fs/promises";
|
|
@@ -17,7 +17,7 @@ import { accessSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathS
|
|
|
17
17
|
import { exec, execFile, execFileSync, execSync, spawn } from "node:child_process";
|
|
18
18
|
import * as path$2 from "node:path";
|
|
19
19
|
import path, { basename as basename$1, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
|
|
20
|
-
import { tmpdir } from "node:os";
|
|
20
|
+
import { homedir, tmpdir } from "node:os";
|
|
21
21
|
import { createHash, randomUUID } from "node:crypto";
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
import { access as access$1, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, rename, stat as stat$1, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
|
|
@@ -933,6 +933,98 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
933
933
|
}
|
|
934
934
|
]
|
|
935
935
|
},
|
|
936
|
+
{
|
|
937
|
+
type: "acceptance:started",
|
|
938
|
+
description: "Acceptance stage began for a story with journey tags (A2.2).",
|
|
939
|
+
when: "Once per tagged story, post-verification.",
|
|
940
|
+
fields: [
|
|
941
|
+
{
|
|
942
|
+
name: "ts",
|
|
943
|
+
type: "string",
|
|
944
|
+
description: "Timestamp."
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
name: "key",
|
|
948
|
+
type: "string",
|
|
949
|
+
description: "Story key."
|
|
950
|
+
},
|
|
951
|
+
{
|
|
952
|
+
name: "journeys",
|
|
953
|
+
type: "string[]",
|
|
954
|
+
description: "Journey ids the story claims."
|
|
955
|
+
}
|
|
956
|
+
]
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
type: "acceptance:rendered",
|
|
960
|
+
description: "One user-facing surface rendered (or failed to render) via the declared acceptance contract (A2.2).",
|
|
961
|
+
when: "Once per surface per acceptance stage run.",
|
|
962
|
+
fields: [
|
|
963
|
+
{
|
|
964
|
+
name: "ts",
|
|
965
|
+
type: "string",
|
|
966
|
+
description: "Timestamp."
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
name: "key",
|
|
970
|
+
type: "string",
|
|
971
|
+
description: "Story key."
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
name: "surface",
|
|
975
|
+
type: "string",
|
|
976
|
+
description: "email | cli | file."
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
name: "status",
|
|
980
|
+
type: "rendered|failed",
|
|
981
|
+
description: "Render outcome."
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
name: "artifacts_dir",
|
|
985
|
+
type: "string",
|
|
986
|
+
description: "External artifacts directory."
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
name: "artifacts",
|
|
990
|
+
type: "string[]",
|
|
991
|
+
description: "Relative artifact paths produced."
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
name: "error",
|
|
995
|
+
type: "string",
|
|
996
|
+
description: "Named failure reason.",
|
|
997
|
+
optional: true
|
|
998
|
+
}
|
|
999
|
+
]
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
type: "acceptance:verdict",
|
|
1003
|
+
description: "Per-end-state judge verdicts for one journey, evidence included. UNREACHABLE = the walk could not even be attempted (the never-wired shape) (A2.2).",
|
|
1004
|
+
when: "Once per journey judged.",
|
|
1005
|
+
fields: [
|
|
1006
|
+
{
|
|
1007
|
+
name: "ts",
|
|
1008
|
+
type: "string",
|
|
1009
|
+
description: "Timestamp."
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
name: "key",
|
|
1013
|
+
type: "string",
|
|
1014
|
+
description: "Story key."
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
name: "journey",
|
|
1018
|
+
type: "string",
|
|
1019
|
+
description: "Journey id."
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
name: "verdicts",
|
|
1023
|
+
type: "array",
|
|
1024
|
+
description: "Per-end-state {end_state_id, verdict: PASS|FAIL|UNREACHABLE, artifact, excerpt}."
|
|
1025
|
+
}
|
|
1026
|
+
]
|
|
1027
|
+
},
|
|
936
1028
|
{
|
|
937
1029
|
type: "acceptance:coverage",
|
|
938
1030
|
description: "Journey coverage audit result (acceptance gate, A0.3). Every registered journey in scope lands in exactly one state: walked-pass, walked-fail, deferred, unclaimed (NO story claims it — the never-wired-journey class), or unwalked (claimed but never walked). Advisory mode warns; blocking mode escalates the last story of the epic.",
|
|
@@ -2384,7 +2476,7 @@ async function runHelpAgent() {
|
|
|
2384
2476
|
|
|
2385
2477
|
//#endregion
|
|
2386
2478
|
//#region src/persistence/dolt-server.ts
|
|
2387
|
-
const logger$
|
|
2479
|
+
const logger$27 = createLogger("dolt-server");
|
|
2388
2480
|
/**
|
|
2389
2481
|
* Start a dolt sql-server for the given project, if Dolt is available and no
|
|
2390
2482
|
* server is already running (socket already exists).
|
|
@@ -2401,7 +2493,7 @@ async function startDoltServer(projectRoot) {
|
|
|
2401
2493
|
if (!existsSync(join$1(stateDir, ".dolt"))) return null;
|
|
2402
2494
|
try {
|
|
2403
2495
|
await access$1(socketPath);
|
|
2404
|
-
logger$
|
|
2496
|
+
logger$27.debug("Dolt socket already exists at %s — using existing server", socketPath);
|
|
2405
2497
|
return null;
|
|
2406
2498
|
} catch {}
|
|
2407
2499
|
try {
|
|
@@ -2410,10 +2502,10 @@ async function startDoltServer(projectRoot) {
|
|
|
2410
2502
|
stdio: "pipe"
|
|
2411
2503
|
});
|
|
2412
2504
|
} catch {
|
|
2413
|
-
logger$
|
|
2505
|
+
logger$27.debug("dolt binary not on PATH — cannot start server");
|
|
2414
2506
|
return null;
|
|
2415
2507
|
}
|
|
2416
|
-
logger$
|
|
2508
|
+
logger$27.debug("Starting dolt sql-server at %s", socketPath);
|
|
2417
2509
|
let proc$1;
|
|
2418
2510
|
try {
|
|
2419
2511
|
proc$1 = spawn("dolt", [
|
|
@@ -2434,26 +2526,26 @@ async function startDoltServer(projectRoot) {
|
|
|
2434
2526
|
detached: false
|
|
2435
2527
|
});
|
|
2436
2528
|
} catch (err) {
|
|
2437
|
-
logger$
|
|
2529
|
+
logger$27.debug("Failed to spawn dolt sql-server: %s", err instanceof Error ? err.message : String(err));
|
|
2438
2530
|
return null;
|
|
2439
2531
|
}
|
|
2440
2532
|
let failed = false;
|
|
2441
2533
|
proc$1.on("error", (err) => {
|
|
2442
|
-
logger$
|
|
2534
|
+
logger$27.debug("dolt sql-server error: %s", err.message);
|
|
2443
2535
|
failed = true;
|
|
2444
2536
|
});
|
|
2445
2537
|
proc$1.on("exit", (code) => {
|
|
2446
|
-
if (code !== null && code !== 0) logger$
|
|
2538
|
+
if (code !== null && code !== 0) logger$27.debug("dolt sql-server exited with code %d", code);
|
|
2447
2539
|
});
|
|
2448
2540
|
proc$1.stderr?.on("data", (chunk) => {
|
|
2449
2541
|
const line = chunk.toString().trim();
|
|
2450
|
-
if (line) logger$
|
|
2542
|
+
if (line) logger$27.debug("dolt-server: %s", line);
|
|
2451
2543
|
});
|
|
2452
2544
|
const deadline = Date.now() + 5e3;
|
|
2453
2545
|
while (Date.now() < deadline && !failed) try {
|
|
2454
2546
|
await access$1(socketPath);
|
|
2455
2547
|
const pid = proc$1.pid ?? 0;
|
|
2456
|
-
logger$
|
|
2548
|
+
logger$27.info("Auto-started dolt sql-server (pid=%d, socket=%s)", pid, socketPath);
|
|
2457
2549
|
let stopped = false;
|
|
2458
2550
|
return {
|
|
2459
2551
|
pid,
|
|
@@ -2461,14 +2553,14 @@ async function startDoltServer(projectRoot) {
|
|
|
2461
2553
|
stop: () => {
|
|
2462
2554
|
if (stopped) return;
|
|
2463
2555
|
stopped = true;
|
|
2464
|
-
logger$
|
|
2556
|
+
logger$27.debug("Stopping dolt sql-server (pid=%d)", pid);
|
|
2465
2557
|
proc$1.kill("SIGTERM");
|
|
2466
2558
|
}
|
|
2467
2559
|
};
|
|
2468
2560
|
} catch {
|
|
2469
2561
|
await new Promise((resolve$6) => setTimeout(resolve$6, 100));
|
|
2470
2562
|
}
|
|
2471
|
-
logger$
|
|
2563
|
+
logger$27.debug("dolt sql-server did not start within 5s — killing");
|
|
2472
2564
|
proc$1.kill("SIGTERM");
|
|
2473
2565
|
return null;
|
|
2474
2566
|
}
|
|
@@ -2538,7 +2630,7 @@ function truncateToTokens(text, maxTokens) {
|
|
|
2538
2630
|
|
|
2539
2631
|
//#endregion
|
|
2540
2632
|
//#region src/modules/context-compiler/context-compiler-impl.ts
|
|
2541
|
-
const logger$
|
|
2633
|
+
const logger$26 = createLogger("context-compiler");
|
|
2542
2634
|
/**
|
|
2543
2635
|
* Fraction of the original token budget that must remain (after required +
|
|
2544
2636
|
* important sections) before an optional section is included.
|
|
@@ -2599,7 +2691,7 @@ var ContextCompilerImpl = class {
|
|
|
2599
2691
|
}
|
|
2600
2692
|
_applyExclusionFilter(text, sectionName) {
|
|
2601
2693
|
for (const excludedPath of this._excludedPaths) if (text.includes(excludedPath)) {
|
|
2602
|
-
logger$
|
|
2694
|
+
logger$26.warn({
|
|
2603
2695
|
sectionName,
|
|
2604
2696
|
excludedPath
|
|
2605
2697
|
}, "ContextCompiler: section excluded — contains path from exclusion list");
|
|
@@ -2657,7 +2749,7 @@ var ContextCompilerImpl = class {
|
|
|
2657
2749
|
includedParts.push(truncated);
|
|
2658
2750
|
remainingBudget -= truncatedTokens;
|
|
2659
2751
|
anyTruncated = true;
|
|
2660
|
-
logger$
|
|
2752
|
+
logger$26.warn({
|
|
2661
2753
|
section: section.name,
|
|
2662
2754
|
originalTokens: tokens,
|
|
2663
2755
|
budgetTokens: truncatedTokens
|
|
@@ -2671,7 +2763,7 @@ var ContextCompilerImpl = class {
|
|
|
2671
2763
|
});
|
|
2672
2764
|
} else {
|
|
2673
2765
|
anyTruncated = true;
|
|
2674
|
-
logger$
|
|
2766
|
+
logger$26.warn({
|
|
2675
2767
|
section: section.name,
|
|
2676
2768
|
tokens
|
|
2677
2769
|
}, "Context compiler: omitted \"important\" section — no budget remaining");
|
|
@@ -2698,7 +2790,7 @@ var ContextCompilerImpl = class {
|
|
|
2698
2790
|
} else {
|
|
2699
2791
|
if (tokens > 0) {
|
|
2700
2792
|
anyTruncated = true;
|
|
2701
|
-
logger$
|
|
2793
|
+
logger$26.warn({
|
|
2702
2794
|
section: section.name,
|
|
2703
2795
|
tokens,
|
|
2704
2796
|
budgetFractionRemaining: budgetFractionRemaining.toFixed(2)
|
|
@@ -2792,8 +2884,8 @@ var GrammarLoader = class {
|
|
|
2792
2884
|
_extensionMap;
|
|
2793
2885
|
_cache = new Map();
|
|
2794
2886
|
_unavailable = false;
|
|
2795
|
-
constructor(logger$
|
|
2796
|
-
this._logger = logger$
|
|
2887
|
+
constructor(logger$28) {
|
|
2888
|
+
this._logger = logger$28;
|
|
2797
2889
|
this._extensionMap = new Map([
|
|
2798
2890
|
[".ts", "tree-sitter-typescript/typescript"],
|
|
2799
2891
|
[".tsx", "tree-sitter-typescript/tsx"],
|
|
@@ -2879,9 +2971,9 @@ const ERR_REPO_MAP_GIT_FAILED = "ERR_REPO_MAP_GIT_FAILED";
|
|
|
2879
2971
|
var SymbolParser = class {
|
|
2880
2972
|
_grammarLoader;
|
|
2881
2973
|
_logger;
|
|
2882
|
-
constructor(grammarLoader, logger$
|
|
2974
|
+
constructor(grammarLoader, logger$28) {
|
|
2883
2975
|
this._grammarLoader = grammarLoader;
|
|
2884
|
-
this._logger = logger$
|
|
2976
|
+
this._logger = logger$28;
|
|
2885
2977
|
}
|
|
2886
2978
|
async parseFile(filePath) {
|
|
2887
2979
|
const ext$2 = extname$1(filePath);
|
|
@@ -3026,9 +3118,9 @@ async function computeFileHash(filePath) {
|
|
|
3026
3118
|
var DoltSymbolRepository = class {
|
|
3027
3119
|
_client;
|
|
3028
3120
|
_logger;
|
|
3029
|
-
constructor(client, logger$
|
|
3121
|
+
constructor(client, logger$28) {
|
|
3030
3122
|
this._client = client;
|
|
3031
|
-
this._logger = logger$
|
|
3123
|
+
this._logger = logger$28;
|
|
3032
3124
|
}
|
|
3033
3125
|
/**
|
|
3034
3126
|
* Atomically replace all symbols for filePath.
|
|
@@ -3234,11 +3326,11 @@ var RepoMapStorage = class {
|
|
|
3234
3326
|
_metaRepo;
|
|
3235
3327
|
_gitClient;
|
|
3236
3328
|
_logger;
|
|
3237
|
-
constructor(symbolRepo, metaRepo, gitClient, logger$
|
|
3329
|
+
constructor(symbolRepo, metaRepo, gitClient, logger$28) {
|
|
3238
3330
|
this._symbolRepo = symbolRepo;
|
|
3239
3331
|
this._metaRepo = metaRepo;
|
|
3240
3332
|
this._gitClient = gitClient;
|
|
3241
|
-
this._logger = logger$
|
|
3333
|
+
this._logger = logger$28;
|
|
3242
3334
|
}
|
|
3243
3335
|
/**
|
|
3244
3336
|
* Returns true if the file's current content hash differs from the stored hash.
|
|
@@ -3355,8 +3447,8 @@ function runGit(args, cwd) {
|
|
|
3355
3447
|
*/
|
|
3356
3448
|
var GitClient = class {
|
|
3357
3449
|
_logger;
|
|
3358
|
-
constructor(logger$
|
|
3359
|
-
this._logger = logger$
|
|
3450
|
+
constructor(logger$28) {
|
|
3451
|
+
this._logger = logger$28;
|
|
3360
3452
|
}
|
|
3361
3453
|
/**
|
|
3362
3454
|
* Returns the current HEAD commit SHA.
|
|
@@ -4712,9 +4804,9 @@ var RepoMapQueryEngine = class {
|
|
|
4712
4804
|
repo;
|
|
4713
4805
|
logger;
|
|
4714
4806
|
telemetry;
|
|
4715
|
-
constructor(repo, logger$
|
|
4807
|
+
constructor(repo, logger$28, telemetry) {
|
|
4716
4808
|
this.repo = repo;
|
|
4717
|
-
this.logger = logger$
|
|
4809
|
+
this.logger = logger$28;
|
|
4718
4810
|
this.telemetry = telemetry;
|
|
4719
4811
|
}
|
|
4720
4812
|
async query(q) {
|
|
@@ -4934,9 +5026,9 @@ var RepoMapFormatter = class {
|
|
|
4934
5026
|
var RepoMapTelemetry = class {
|
|
4935
5027
|
_telemetry;
|
|
4936
5028
|
_logger;
|
|
4937
|
-
constructor(telemetry, logger$
|
|
5029
|
+
constructor(telemetry, logger$28) {
|
|
4938
5030
|
this._telemetry = telemetry;
|
|
4939
|
-
this._logger = logger$
|
|
5031
|
+
this._logger = logger$28;
|
|
4940
5032
|
}
|
|
4941
5033
|
/**
|
|
4942
5034
|
* Emit a `repo_map.query` span.
|
|
@@ -4961,9 +5053,9 @@ var RepoMapTelemetry = class {
|
|
|
4961
5053
|
var RepoMapModule = class {
|
|
4962
5054
|
_metaRepo;
|
|
4963
5055
|
_logger;
|
|
4964
|
-
constructor(metaRepo, logger$
|
|
5056
|
+
constructor(metaRepo, logger$28) {
|
|
4965
5057
|
this._metaRepo = metaRepo;
|
|
4966
|
-
this._logger = logger$
|
|
5058
|
+
this._logger = logger$28;
|
|
4967
5059
|
}
|
|
4968
5060
|
/**
|
|
4969
5061
|
* Check whether the stored repo-map is stale relative to the current HEAD commit.
|
|
@@ -5007,9 +5099,9 @@ var RepoMapModule = class {
|
|
|
5007
5099
|
var RepoMapInjector = class {
|
|
5008
5100
|
_queryEngine;
|
|
5009
5101
|
_logger;
|
|
5010
|
-
constructor(queryEngine, logger$
|
|
5102
|
+
constructor(queryEngine, logger$28) {
|
|
5011
5103
|
this._queryEngine = queryEngine;
|
|
5012
|
-
this._logger = logger$
|
|
5104
|
+
this._logger = logger$28;
|
|
5013
5105
|
}
|
|
5014
5106
|
/**
|
|
5015
5107
|
* Build repo-map context by extracting file references from the story content,
|
|
@@ -5091,7 +5183,7 @@ const DEFAULT_TIMEOUTS = {
|
|
|
5091
5183
|
|
|
5092
5184
|
//#endregion
|
|
5093
5185
|
//#region src/modules/agent-dispatch/dispatcher-impl.ts
|
|
5094
|
-
const logger$
|
|
5186
|
+
const logger$25 = createLogger("agent-dispatch");
|
|
5095
5187
|
/**
|
|
5096
5188
|
* Create a new Dispatcher instance.
|
|
5097
5189
|
*
|
|
@@ -5235,7 +5327,7 @@ function runBuildVerification(options) {
|
|
|
5235
5327
|
let cmd;
|
|
5236
5328
|
if (verifyCommand === void 0) {
|
|
5237
5329
|
const detection = detectPackageManager(projectRoot);
|
|
5238
|
-
logger$
|
|
5330
|
+
logger$25.info({
|
|
5239
5331
|
packageManager: detection.packageManager,
|
|
5240
5332
|
lockfile: detection.lockfile,
|
|
5241
5333
|
resolvedCommand: detection.command
|
|
@@ -5247,7 +5339,7 @@ function runBuildVerification(options) {
|
|
|
5247
5339
|
const filters = deriveTurboFilters(changedFiles, projectRoot);
|
|
5248
5340
|
if (filters.length > 0) {
|
|
5249
5341
|
cmd = `${cmd} ${filters.join(" ")}`;
|
|
5250
|
-
logger$
|
|
5342
|
+
logger$25.info({
|
|
5251
5343
|
filters,
|
|
5252
5344
|
originalCmd: options.verifyCommand ?? "(auto-detected)"
|
|
5253
5345
|
}, "Build verification: scoped turbo build to affected packages");
|
|
@@ -5290,7 +5382,7 @@ function runBuildVerification(options) {
|
|
|
5290
5382
|
};
|
|
5291
5383
|
const missingScriptPattern = /Missing script[:\s]|No script found|Command "build" not found/i;
|
|
5292
5384
|
if (missingScriptPattern.test(combinedOutput)) {
|
|
5293
|
-
logger$
|
|
5385
|
+
logger$25.warn("Build script not found — skipping pre-flight (greenfield repo)");
|
|
5294
5386
|
return {
|
|
5295
5387
|
status: "skipped",
|
|
5296
5388
|
exitCode,
|
|
@@ -5300,7 +5392,7 @@ function runBuildVerification(options) {
|
|
|
5300
5392
|
}
|
|
5301
5393
|
const pep668Pattern = /externally-managed-environment|This environment is externally managed/i;
|
|
5302
5394
|
if (pep668Pattern.test(combinedOutput)) {
|
|
5303
|
-
logger$
|
|
5395
|
+
logger$25.warn("PEP 668: pip blocked by externally-managed-environment — skipping pre-flight. Create a .venv to resolve.");
|
|
5304
5396
|
return {
|
|
5305
5397
|
status: "skipped",
|
|
5306
5398
|
exitCode,
|
|
@@ -5310,7 +5402,7 @@ function runBuildVerification(options) {
|
|
|
5310
5402
|
}
|
|
5311
5403
|
const pythonEnvNotProvisionedPattern = /\bpython3?:?\s*command not found|command not found:\s*python3?\b|\bpip3?:?\s*command not found|No module named pip\b/i;
|
|
5312
5404
|
if (pythonEnvNotProvisionedPattern.test(combinedOutput)) {
|
|
5313
|
-
logger$
|
|
5405
|
+
logger$25.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.");
|
|
5314
5406
|
return {
|
|
5315
5407
|
status: "skipped",
|
|
5316
5408
|
exitCode,
|
|
@@ -5533,7 +5625,7 @@ function pickRecommendation(distribution, profile, totalIssues, reviewCycles, la
|
|
|
5533
5625
|
|
|
5534
5626
|
//#endregion
|
|
5535
5627
|
//#region src/modules/implementation-orchestrator/project-findings.ts
|
|
5536
|
-
const logger$
|
|
5628
|
+
const logger$24 = createLogger("project-findings");
|
|
5537
5629
|
/** Maximum character length for the findings summary */
|
|
5538
5630
|
const MAX_CHARS = 2e3;
|
|
5539
5631
|
/**
|
|
@@ -5606,7 +5698,7 @@ async function getProjectFindings(db) {
|
|
|
5606
5698
|
if (summary.length > MAX_CHARS) summary = summary.slice(0, MAX_CHARS - 3) + "...";
|
|
5607
5699
|
return summary;
|
|
5608
5700
|
} catch (err) {
|
|
5609
|
-
logger$
|
|
5701
|
+
logger$24.warn({ err }, "Failed to query project findings (graceful fallback)");
|
|
5610
5702
|
return "";
|
|
5611
5703
|
}
|
|
5612
5704
|
}
|
|
@@ -5629,7 +5721,7 @@ function extractRecurringPatterns(outcomes) {
|
|
|
5629
5721
|
|
|
5630
5722
|
//#endregion
|
|
5631
5723
|
//#region src/modules/compiled-workflows/prompt-assembler.ts
|
|
5632
|
-
const logger$
|
|
5724
|
+
const logger$23 = createLogger("compiled-workflows:prompt-assembler");
|
|
5633
5725
|
/**
|
|
5634
5726
|
* Assemble a final prompt from a template and sections map.
|
|
5635
5727
|
*
|
|
@@ -5654,7 +5746,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
|
|
|
5654
5746
|
tokenCount,
|
|
5655
5747
|
truncated: false
|
|
5656
5748
|
};
|
|
5657
|
-
logger$
|
|
5749
|
+
logger$23.warn({
|
|
5658
5750
|
tokenCount,
|
|
5659
5751
|
ceiling: tokenCeiling
|
|
5660
5752
|
}, "Prompt exceeds token ceiling — truncating optional sections");
|
|
@@ -5670,10 +5762,10 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
|
|
|
5670
5762
|
const targetSectionTokens = Math.max(0, currentSectionTokens - overBy);
|
|
5671
5763
|
if (targetSectionTokens === 0) {
|
|
5672
5764
|
contentMap[section.name] = "";
|
|
5673
|
-
logger$
|
|
5765
|
+
logger$23.warn({ sectionName: section.name }, "Section eliminated to fit token budget");
|
|
5674
5766
|
} else {
|
|
5675
5767
|
contentMap[section.name] = truncateToTokens(section.content, targetSectionTokens);
|
|
5676
|
-
logger$
|
|
5768
|
+
logger$23.warn({
|
|
5677
5769
|
sectionName: section.name,
|
|
5678
5770
|
targetSectionTokens
|
|
5679
5771
|
}, "Section truncated to fit token budget");
|
|
@@ -5684,7 +5776,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
|
|
|
5684
5776
|
}
|
|
5685
5777
|
if (tokenCount <= tokenCeiling) break;
|
|
5686
5778
|
}
|
|
5687
|
-
if (tokenCount > tokenCeiling) logger$
|
|
5779
|
+
if (tokenCount > tokenCeiling) logger$23.warn({
|
|
5688
5780
|
tokenCount,
|
|
5689
5781
|
ceiling: tokenCeiling
|
|
5690
5782
|
}, "Required sections alone exceed token ceiling — returning over-budget prompt");
|
|
@@ -5982,6 +6074,37 @@ const ProbeAuthorResultSchema = z.object({
|
|
|
5982
6074
|
result: z.preprocess((val) => val === "failure" ? "failed" : val, z.enum(["success", "failed"])),
|
|
5983
6075
|
probes: InlineRuntimeProbeListSchema
|
|
5984
6076
|
});
|
|
6077
|
+
/**
|
|
6078
|
+
* Per-end-state verdict from the acceptance judge.
|
|
6079
|
+
*
|
|
6080
|
+
* UNREACHABLE is first-class and distinct from FAIL: the walk could not even
|
|
6081
|
+
* be attempted because the affordance does not exist in the rendered surface
|
|
6082
|
+
* — it is what the income-sources UJ-2 failure WAS. Evidence is MANDATORY:
|
|
6083
|
+
* a verdict that cannot cite the artifact region it grounds on is
|
|
6084
|
+
* schema-invalid (naive prose judging is banned by construction — the
|
|
6085
|
+
* documented LLM-judge biases make ungrounded verdicts worthless).
|
|
6086
|
+
*/
|
|
6087
|
+
const AcceptanceJudgeVerdictSchema = z.object({
|
|
6088
|
+
end_state_id: z.string().min(1),
|
|
6089
|
+
verdict: z.preprocess((val) => typeof val === "string" ? val.toUpperCase() : val, z.enum([
|
|
6090
|
+
"PASS",
|
|
6091
|
+
"FAIL",
|
|
6092
|
+
"UNREACHABLE"
|
|
6093
|
+
])),
|
|
6094
|
+
evidence: z.object({
|
|
6095
|
+
artifact: z.string().min(1),
|
|
6096
|
+
excerpt: z.string().min(1)
|
|
6097
|
+
}),
|
|
6098
|
+
reasoning: z.string().optional()
|
|
6099
|
+
});
|
|
6100
|
+
/**
|
|
6101
|
+
* Schema for the YAML output contract of the acceptance-judge sub-agent.
|
|
6102
|
+
*/
|
|
6103
|
+
const AcceptanceJudgeResultSchema = z.object({
|
|
6104
|
+
result: z.preprocess((val) => val === "failure" ? "failed" : val, z.enum(["success", "failed"])),
|
|
6105
|
+
verdicts: z.array(AcceptanceJudgeVerdictSchema).default([]),
|
|
6106
|
+
error: z.string().optional()
|
|
6107
|
+
});
|
|
5985
6108
|
|
|
5986
6109
|
//#endregion
|
|
5987
6110
|
//#region src/modules/implementation-orchestrator/epic-paths.ts
|
|
@@ -6053,7 +6176,8 @@ const TOKEN_CEILING_DEFAULTS = {
|
|
|
6053
6176
|
"code-review": 5e5,
|
|
6054
6177
|
"test-plan": 1e5,
|
|
6055
6178
|
"test-expansion": 2e5,
|
|
6056
|
-
"probe-author": 5e4
|
|
6179
|
+
"probe-author": 5e4,
|
|
6180
|
+
"acceptance-judge": 1e5
|
|
6057
6181
|
};
|
|
6058
6182
|
/**
|
|
6059
6183
|
* Resolve the effective token ceiling for a workflow type.
|
|
@@ -6082,7 +6206,7 @@ function getTokenCeiling(workflowType, tokenCeilings) {
|
|
|
6082
6206
|
|
|
6083
6207
|
//#endregion
|
|
6084
6208
|
//#region src/modules/compiled-workflows/create-story.ts
|
|
6085
|
-
const logger$
|
|
6209
|
+
const logger$22 = createLogger("compiled-workflows:create-story");
|
|
6086
6210
|
/**
|
|
6087
6211
|
* Compute a hex SHA-256 of the normalized source AC section text.
|
|
6088
6212
|
*
|
|
@@ -6117,13 +6241,13 @@ function hashSourceAcSection(section) {
|
|
|
6117
6241
|
*/
|
|
6118
6242
|
async function runCreateStory(deps, params) {
|
|
6119
6243
|
const { epicId, storyKey, pipelineRunId, source_ac_hash, priorDriftFeedback } = params;
|
|
6120
|
-
logger$
|
|
6244
|
+
logger$22.debug({
|
|
6121
6245
|
epicId,
|
|
6122
6246
|
storyKey,
|
|
6123
6247
|
pipelineRunId
|
|
6124
6248
|
}, "Starting create-story workflow");
|
|
6125
6249
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("create-story", deps.tokenCeilings);
|
|
6126
|
-
logger$
|
|
6250
|
+
logger$22.info({
|
|
6127
6251
|
workflow: "create-story",
|
|
6128
6252
|
ceiling: TOKEN_CEILING,
|
|
6129
6253
|
source: tokenCeilingSource
|
|
@@ -6133,7 +6257,7 @@ async function runCreateStory(deps, params) {
|
|
|
6133
6257
|
template = await deps.pack.getPrompt("create-story");
|
|
6134
6258
|
} catch (err) {
|
|
6135
6259
|
const error = err instanceof Error ? err.message : String(err);
|
|
6136
|
-
logger$
|
|
6260
|
+
logger$22.error({ error }, "Failed to retrieve create-story prompt template");
|
|
6137
6261
|
return {
|
|
6138
6262
|
result: "failed",
|
|
6139
6263
|
error: `Failed to retrieve prompt template: ${error}`,
|
|
@@ -6150,7 +6274,7 @@ async function runCreateStory(deps, params) {
|
|
|
6150
6274
|
const storySection = extractStorySection(epicShardContent, storyKey);
|
|
6151
6275
|
if (storySection !== null) {
|
|
6152
6276
|
const computedHash = hashSourceAcSection(storySection);
|
|
6153
|
-
if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$
|
|
6277
|
+
if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$22.debug({
|
|
6154
6278
|
storyKey,
|
|
6155
6279
|
suppliedHash: source_ac_hash,
|
|
6156
6280
|
computedHash
|
|
@@ -6165,7 +6289,7 @@ async function runCreateStory(deps, params) {
|
|
|
6165
6289
|
const storyDef = storyDecisions.find((d) => d.category === "stories" && d.key === storyKey);
|
|
6166
6290
|
if (storyDef) {
|
|
6167
6291
|
storyDefinitionContent = storyDef.value;
|
|
6168
|
-
logger$
|
|
6292
|
+
logger$22.debug({ storyKey }, "Injected story definition from solutioning decisions");
|
|
6169
6293
|
}
|
|
6170
6294
|
} catch {}
|
|
6171
6295
|
const archConstraintsContent = await getArchConstraints$3(deps);
|
|
@@ -6175,11 +6299,11 @@ async function runCreateStory(deps, params) {
|
|
|
6175
6299
|
if (trustedRoot !== void 0) {
|
|
6176
6300
|
const registryLoad = await loadJourneyRegistryFromTrustedTree(trustedRoot);
|
|
6177
6301
|
if (registryLoad.status === "ok" && registryLoad.registry.journeys.length > 0) journeyRegistry = registryLoad.registry;
|
|
6178
|
-
else if (registryLoad.status === "invalid") logger$
|
|
6302
|
+
else if (registryLoad.status === "invalid") logger$22.warn({
|
|
6179
6303
|
storyKey,
|
|
6180
6304
|
issues: registryLoad.issues
|
|
6181
6305
|
}, "A0.2: journey registry present but invalid — stories will be untagged (registry validity is escalated at epic close)");
|
|
6182
|
-
else if (registryLoad.status === "error") logger$
|
|
6306
|
+
else if (registryLoad.status === "error") logger$22.warn({
|
|
6183
6307
|
storyKey,
|
|
6184
6308
|
error: registryLoad.message
|
|
6185
6309
|
}, "A0.2: journey registry read failed — stories will be untagged");
|
|
@@ -6240,7 +6364,7 @@ async function runCreateStory(deps, params) {
|
|
|
6240
6364
|
priority: "optional"
|
|
6241
6365
|
}]
|
|
6242
6366
|
], TOKEN_CEILING);
|
|
6243
|
-
logger$
|
|
6367
|
+
logger$22.debug({
|
|
6244
6368
|
tokenCount,
|
|
6245
6369
|
truncated,
|
|
6246
6370
|
tokenCeiling: TOKEN_CEILING
|
|
@@ -6260,7 +6384,7 @@ async function runCreateStory(deps, params) {
|
|
|
6260
6384
|
dispatchResult = await handle.result;
|
|
6261
6385
|
} catch (err) {
|
|
6262
6386
|
const error = err instanceof Error ? err.message : String(err);
|
|
6263
|
-
logger$
|
|
6387
|
+
logger$22.error({
|
|
6264
6388
|
epicId,
|
|
6265
6389
|
storyKey,
|
|
6266
6390
|
error
|
|
@@ -6281,7 +6405,7 @@ async function runCreateStory(deps, params) {
|
|
|
6281
6405
|
if (dispatchResult.status === "failed") {
|
|
6282
6406
|
const errorMsg = dispatchResult.parseError ?? `Dispatch failed with exit code ${dispatchResult.exitCode}`;
|
|
6283
6407
|
const stderrDetail = dispatchResult.output ? ` Output: ${dispatchResult.output}` : "";
|
|
6284
|
-
logger$
|
|
6408
|
+
logger$22.warn({
|
|
6285
6409
|
epicId,
|
|
6286
6410
|
storyKey,
|
|
6287
6411
|
exitCode: dispatchResult.exitCode,
|
|
@@ -6294,7 +6418,7 @@ async function runCreateStory(deps, params) {
|
|
|
6294
6418
|
};
|
|
6295
6419
|
}
|
|
6296
6420
|
if (dispatchResult.status === "timeout") {
|
|
6297
|
-
logger$
|
|
6421
|
+
logger$22.warn({
|
|
6298
6422
|
epicId,
|
|
6299
6423
|
storyKey
|
|
6300
6424
|
}, "Create-story dispatch timed out");
|
|
@@ -6309,7 +6433,7 @@ async function runCreateStory(deps, params) {
|
|
|
6309
6433
|
const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
|
|
6310
6434
|
const authSignature = detectClaudeAuthFailure(dispatchResult.output);
|
|
6311
6435
|
if (authSignature !== null) {
|
|
6312
|
-
logger$
|
|
6436
|
+
logger$22.error({
|
|
6313
6437
|
epicId,
|
|
6314
6438
|
storyKey,
|
|
6315
6439
|
authSignature,
|
|
@@ -6322,7 +6446,7 @@ async function runCreateStory(deps, params) {
|
|
|
6322
6446
|
tokenUsage
|
|
6323
6447
|
};
|
|
6324
6448
|
}
|
|
6325
|
-
logger$
|
|
6449
|
+
logger$22.warn({
|
|
6326
6450
|
epicId,
|
|
6327
6451
|
storyKey,
|
|
6328
6452
|
details,
|
|
@@ -6338,7 +6462,7 @@ async function runCreateStory(deps, params) {
|
|
|
6338
6462
|
const parseResult = CreateStoryResultSchema.safeParse(dispatchResult.parsed);
|
|
6339
6463
|
if (!parseResult.success) {
|
|
6340
6464
|
const details = parseResult.error.message;
|
|
6341
|
-
logger$
|
|
6465
|
+
logger$22.warn({
|
|
6342
6466
|
epicId,
|
|
6343
6467
|
storyKey,
|
|
6344
6468
|
details
|
|
@@ -6365,7 +6489,7 @@ async function runCreateStory(deps, params) {
|
|
|
6365
6489
|
const unknown = taggedJourneys.filter((id) => !knownIds.has(id));
|
|
6366
6490
|
if (unknown.length > 0) {
|
|
6367
6491
|
const details = `story artifact declares unknown journey id(s): ${unknown.join(", ")} — registry v${String(journeyRegistry.version)} defines: ${[...knownIds].join(", ")}`;
|
|
6368
|
-
logger$
|
|
6492
|
+
logger$22.warn({
|
|
6369
6493
|
epicId,
|
|
6370
6494
|
storyKey,
|
|
6371
6495
|
unknown
|
|
@@ -6378,7 +6502,7 @@ async function runCreateStory(deps, params) {
|
|
|
6378
6502
|
};
|
|
6379
6503
|
}
|
|
6380
6504
|
if (taggedJourneys.length > 0) {
|
|
6381
|
-
logger$
|
|
6505
|
+
logger$22.info({
|
|
6382
6506
|
epicId,
|
|
6383
6507
|
storyKey,
|
|
6384
6508
|
journeys: taggedJourneys
|
|
@@ -6387,7 +6511,7 @@ async function runCreateStory(deps, params) {
|
|
|
6387
6511
|
}
|
|
6388
6512
|
}
|
|
6389
6513
|
}
|
|
6390
|
-
logger$
|
|
6514
|
+
logger$22.info({
|
|
6391
6515
|
epicId,
|
|
6392
6516
|
storyKey,
|
|
6393
6517
|
storyFile: parsed.story_file,
|
|
@@ -6417,7 +6541,7 @@ async function getImplementationDecisions(deps, pipelineRunId) {
|
|
|
6417
6541
|
}
|
|
6418
6542
|
return await getDecisionsByPhase(deps.db, "implementation");
|
|
6419
6543
|
} catch (err) {
|
|
6420
|
-
logger$
|
|
6544
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
|
|
6421
6545
|
return [];
|
|
6422
6546
|
}
|
|
6423
6547
|
}
|
|
@@ -6715,7 +6839,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6715
6839
|
if (storyKey) {
|
|
6716
6840
|
const perStoryShard = decisions.find((d) => d.category === "epic-shard" && d.key === storyKey);
|
|
6717
6841
|
if (perStoryShard?.value) {
|
|
6718
|
-
logger$
|
|
6842
|
+
logger$22.debug({
|
|
6719
6843
|
epicId,
|
|
6720
6844
|
storyKey
|
|
6721
6845
|
}, "Found per-story epic shard (direct lookup)");
|
|
@@ -6727,13 +6851,13 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6727
6851
|
if (shardContent && storyKey) {
|
|
6728
6852
|
const storySection = extractStorySection(shardContent, storyKey);
|
|
6729
6853
|
if (storySection) {
|
|
6730
|
-
logger$
|
|
6854
|
+
logger$22.debug({
|
|
6731
6855
|
epicId,
|
|
6732
6856
|
storyKey
|
|
6733
6857
|
}, "Extracted per-story section from epic shard (pre-37-0 fallback)");
|
|
6734
6858
|
return storySection;
|
|
6735
6859
|
}
|
|
6736
|
-
logger$
|
|
6860
|
+
logger$22.info({
|
|
6737
6861
|
epicId,
|
|
6738
6862
|
storyKey
|
|
6739
6863
|
}, "Story section absent in decisions-store shard — attempting file-based fallback before returning stale shard");
|
|
@@ -6741,11 +6865,11 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6741
6865
|
if (projectRoot) {
|
|
6742
6866
|
const fallback = readEpicShardFromFile(projectRoot, epicId, storyKey);
|
|
6743
6867
|
if (fallback) {
|
|
6744
|
-
logger$
|
|
6868
|
+
logger$22.info({ epicId }, "Using file-based fallback for epic shard");
|
|
6745
6869
|
if (storyKey) {
|
|
6746
6870
|
const storySection = extractStorySection(fallback, storyKey);
|
|
6747
6871
|
if (storySection) {
|
|
6748
|
-
logger$
|
|
6872
|
+
logger$22.debug({
|
|
6749
6873
|
epicId,
|
|
6750
6874
|
storyKey
|
|
6751
6875
|
}, "Extracted per-story section from file-based epic shard");
|
|
@@ -6758,7 +6882,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
|
|
|
6758
6882
|
if (shardContent) return shardContent;
|
|
6759
6883
|
return "";
|
|
6760
6884
|
} catch (err) {
|
|
6761
|
-
logger$
|
|
6885
|
+
logger$22.warn({
|
|
6762
6886
|
epicId,
|
|
6763
6887
|
error: err instanceof Error ? err.message : String(err)
|
|
6764
6888
|
}, "Failed to retrieve epic shard");
|
|
@@ -6775,7 +6899,7 @@ function getPrevDevNotes(decisions, epicId) {
|
|
|
6775
6899
|
if (devNotes.length === 0) return "";
|
|
6776
6900
|
return devNotes[devNotes.length - 1].value;
|
|
6777
6901
|
} catch (err) {
|
|
6778
|
-
logger$
|
|
6902
|
+
logger$22.warn({
|
|
6779
6903
|
epicId,
|
|
6780
6904
|
error: err instanceof Error ? err.message : String(err)
|
|
6781
6905
|
}, "Failed to retrieve prev dev notes");
|
|
@@ -6808,7 +6932,7 @@ async function getArchConstraints$3(deps) {
|
|
|
6808
6932
|
const truncatedBody = body.length > 300 ? body.slice(0, 297) + "..." : body;
|
|
6809
6933
|
return `${header}\n${truncatedBody}`;
|
|
6810
6934
|
}).join("\n\n");
|
|
6811
|
-
logger$
|
|
6935
|
+
logger$22.info({
|
|
6812
6936
|
fullLength: full.length,
|
|
6813
6937
|
summarizedLength: summarized.length,
|
|
6814
6938
|
decisions: constraints.length
|
|
@@ -6819,13 +6943,13 @@ async function getArchConstraints$3(deps) {
|
|
|
6819
6943
|
if (archRoot) {
|
|
6820
6944
|
const fallback = readArchConstraintsFromFile(archRoot);
|
|
6821
6945
|
if (fallback) {
|
|
6822
|
-
logger$
|
|
6946
|
+
logger$22.info("Using file-based fallback for architecture constraints (decisions table empty)");
|
|
6823
6947
|
return fallback.length > ARCH_CONSTRAINT_MAX_CHARS ? fallback.slice(0, ARCH_CONSTRAINT_MAX_CHARS) + "\n\n[truncated for token budget]" : fallback;
|
|
6824
6948
|
}
|
|
6825
6949
|
}
|
|
6826
6950
|
return "";
|
|
6827
6951
|
} catch (err) {
|
|
6828
|
-
logger$
|
|
6952
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
6829
6953
|
return "";
|
|
6830
6954
|
}
|
|
6831
6955
|
}
|
|
@@ -6889,7 +7013,7 @@ function readEpicShardFromFile(projectRoot, epicId, storyKey) {
|
|
|
6889
7013
|
}
|
|
6890
7014
|
return "";
|
|
6891
7015
|
} catch (err) {
|
|
6892
|
-
logger$
|
|
7016
|
+
logger$22.warn({
|
|
6893
7017
|
epicId,
|
|
6894
7018
|
error: err instanceof Error ? err.message : String(err)
|
|
6895
7019
|
}, "File-based epic shard fallback failed");
|
|
@@ -6912,7 +7036,7 @@ function readArchConstraintsFromFile(projectRoot) {
|
|
|
6912
7036
|
const content = readFileSync(archPath, "utf-8");
|
|
6913
7037
|
return content.slice(0, 1500);
|
|
6914
7038
|
} catch (err) {
|
|
6915
|
-
logger$
|
|
7039
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
|
|
6916
7040
|
return "";
|
|
6917
7041
|
}
|
|
6918
7042
|
}
|
|
@@ -6925,7 +7049,7 @@ async function getStoryTemplate(deps) {
|
|
|
6925
7049
|
try {
|
|
6926
7050
|
return await deps.pack.getTemplate("story");
|
|
6927
7051
|
} catch (err) {
|
|
6928
|
-
logger$
|
|
7052
|
+
logger$22.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
|
|
6929
7053
|
return "";
|
|
6930
7054
|
}
|
|
6931
7055
|
}
|
|
@@ -6962,7 +7086,7 @@ async function isValidStoryFile(filePath) {
|
|
|
6962
7086
|
|
|
6963
7087
|
//#endregion
|
|
6964
7088
|
//#region src/modules/compiled-workflows/git-helpers.ts
|
|
6965
|
-
const logger$
|
|
7089
|
+
const logger$21 = createLogger("compiled-workflows:git-helpers");
|
|
6966
7090
|
/**
|
|
6967
7091
|
* Commit the agent's working-tree output for a dev-story dispatch.
|
|
6968
7092
|
*
|
|
@@ -7006,7 +7130,7 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
7006
7130
|
const abs = isAbsolute(p) ? p : resolve$1(workingDir, p);
|
|
7007
7131
|
const rel = relative(workingDir, abs);
|
|
7008
7132
|
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
7009
|
-
logger$
|
|
7133
|
+
logger$21.debug({
|
|
7010
7134
|
path: p,
|
|
7011
7135
|
abs,
|
|
7012
7136
|
workingDir
|
|
@@ -7015,7 +7139,7 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
7015
7139
|
}
|
|
7016
7140
|
const segments = rel.replace(/\\/g, "/").split("/");
|
|
7017
7141
|
if (segments.some((s$1) => COMMIT_DENY_SEGMENTS.includes(s$1))) {
|
|
7018
|
-
logger$
|
|
7142
|
+
logger$21.warn({
|
|
7019
7143
|
path: rel,
|
|
7020
7144
|
storyKey
|
|
7021
7145
|
}, "commitDevStoryOutput: denylisted dependency/artifact path excluded from substrate commit");
|
|
@@ -7100,12 +7224,12 @@ async function commitDevStoryOutput(storyKey, storyTitle, filesModified, working
|
|
|
7100
7224
|
timeout: 5e3
|
|
7101
7225
|
}).trim();
|
|
7102
7226
|
} catch (err) {
|
|
7103
|
-
logger$
|
|
7227
|
+
logger$21.warn({
|
|
7104
7228
|
storyKey,
|
|
7105
7229
|
err
|
|
7106
7230
|
}, "commitDevStoryOutput: commit succeeded but rev-parse HEAD failed");
|
|
7107
7231
|
}
|
|
7108
|
-
logger$
|
|
7232
|
+
logger$21.info({
|
|
7109
7233
|
storyKey,
|
|
7110
7234
|
sha,
|
|
7111
7235
|
fileCount: insideWorktree.length
|
|
@@ -7209,7 +7333,7 @@ async function checkpointStoryWorktree(storyKey, reason, workingDir) {
|
|
|
7209
7333
|
timeout: 5e3
|
|
7210
7334
|
}).trim();
|
|
7211
7335
|
} catch {}
|
|
7212
|
-
logger$
|
|
7336
|
+
logger$21.info({
|
|
7213
7337
|
storyKey,
|
|
7214
7338
|
sha,
|
|
7215
7339
|
reason: cleanReason
|
|
@@ -7255,7 +7379,7 @@ function hasCommits(cwd) {
|
|
|
7255
7379
|
*/
|
|
7256
7380
|
async function getGitDiffSummary(workingDirectory = process.cwd()) {
|
|
7257
7381
|
if (!hasCommits(workingDirectory)) {
|
|
7258
|
-
logger$
|
|
7382
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff");
|
|
7259
7383
|
return "";
|
|
7260
7384
|
}
|
|
7261
7385
|
return runGitCommand(["diff", "HEAD"], workingDirectory, "git-diff-summary");
|
|
@@ -7272,7 +7396,7 @@ async function getGitDiffSummary(workingDirectory = process.cwd()) {
|
|
|
7272
7396
|
*/
|
|
7273
7397
|
async function getGitDiffStatSummary(workingDirectory = process.cwd()) {
|
|
7274
7398
|
if (!hasCommits(workingDirectory)) {
|
|
7275
|
-
logger$
|
|
7399
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat");
|
|
7276
7400
|
return "";
|
|
7277
7401
|
}
|
|
7278
7402
|
return runGitCommand([
|
|
@@ -7321,7 +7445,7 @@ async function getGitDiffStatBetweenCommits(baseCommit, endCommit = "HEAD", work
|
|
|
7321
7445
|
async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
|
|
7322
7446
|
if (files.length === 0) return "";
|
|
7323
7447
|
if (!hasCommits(workingDirectory)) {
|
|
7324
|
-
logger$
|
|
7448
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff for files");
|
|
7325
7449
|
return "";
|
|
7326
7450
|
}
|
|
7327
7451
|
await stageIntentToAdd(files, workingDirectory);
|
|
@@ -7348,7 +7472,7 @@ async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
|
|
|
7348
7472
|
async function getGitDiffStatForFiles(files, workingDirectory = process.cwd()) {
|
|
7349
7473
|
if (files.length === 0) return "";
|
|
7350
7474
|
if (!hasCommits(workingDirectory)) {
|
|
7351
|
-
logger$
|
|
7475
|
+
logger$21.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat for files");
|
|
7352
7476
|
return "";
|
|
7353
7477
|
}
|
|
7354
7478
|
return runGitCommand([
|
|
@@ -7397,7 +7521,7 @@ async function stageIntentToAdd(files, workingDirectory) {
|
|
|
7397
7521
|
if (files.length === 0) return;
|
|
7398
7522
|
const existing = files.filter((f$1) => {
|
|
7399
7523
|
const exists = existsSync(f$1);
|
|
7400
|
-
if (!exists) logger$
|
|
7524
|
+
if (!exists) logger$21.debug({ file: f$1 }, "Skipping nonexistent file in stageIntentToAdd");
|
|
7401
7525
|
return exists;
|
|
7402
7526
|
});
|
|
7403
7527
|
if (existing.length === 0) return;
|
|
@@ -7426,7 +7550,7 @@ async function stageIntentToAdd(files, workingDirectory) {
|
|
|
7426
7550
|
async function recoverStoryFileFromBranch(storyFilePath, workingDirectory) {
|
|
7427
7551
|
const rel = relative(workingDirectory, resolve$1(workingDirectory, storyFilePath));
|
|
7428
7552
|
if (rel.startsWith("..")) {
|
|
7429
|
-
logger$
|
|
7553
|
+
logger$21.warn({
|
|
7430
7554
|
storyFilePath,
|
|
7431
7555
|
workingDirectory
|
|
7432
7556
|
}, "recoverStoryFileFromBranch: path outside the worktree — not recoverable");
|
|
@@ -7438,9 +7562,9 @@ async function recoverStoryFileFromBranch(storyFilePath, workingDirectory) {
|
|
|
7438
7562
|
const abs = resolve$1(workingDirectory, rel);
|
|
7439
7563
|
await mkdir$1(dirname$1(abs), { recursive: true });
|
|
7440
7564
|
await writeFile$1(abs, content, "utf-8");
|
|
7441
|
-
logger$
|
|
7565
|
+
logger$21.warn({ storyFilePath: abs }, "H5.5: story file restored to the working tree from branch HEAD");
|
|
7442
7566
|
} catch (writeErr) {
|
|
7443
|
-
logger$
|
|
7567
|
+
logger$21.warn({
|
|
7444
7568
|
storyFilePath,
|
|
7445
7569
|
err: writeErr
|
|
7446
7570
|
}, "H5.5: recovered story content but could not restore the file (continuing with in-memory content)");
|
|
@@ -7466,7 +7590,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7466
7590
|
stderr += chunk.toString("utf-8");
|
|
7467
7591
|
});
|
|
7468
7592
|
proc$1.on("error", (err) => {
|
|
7469
|
-
logger$
|
|
7593
|
+
logger$21.warn({
|
|
7470
7594
|
label: logLabel,
|
|
7471
7595
|
cwd,
|
|
7472
7596
|
error: err.message
|
|
@@ -7475,7 +7599,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7475
7599
|
});
|
|
7476
7600
|
proc$1.on("close", (code) => {
|
|
7477
7601
|
if (code !== 0) {
|
|
7478
|
-
logger$
|
|
7602
|
+
logger$21.warn({
|
|
7479
7603
|
label: logLabel,
|
|
7480
7604
|
cwd,
|
|
7481
7605
|
code,
|
|
@@ -7491,7 +7615,7 @@ async function runGitCommand(args, cwd, logLabel) {
|
|
|
7491
7615
|
|
|
7492
7616
|
//#endregion
|
|
7493
7617
|
//#region src/modules/compiled-workflows/story-complexity.ts
|
|
7494
|
-
const logger$
|
|
7618
|
+
const logger$20 = createLogger("compiled-workflows:story-complexity");
|
|
7495
7619
|
/**
|
|
7496
7620
|
* Compute a complexity score from story markdown content.
|
|
7497
7621
|
*
|
|
@@ -7543,7 +7667,7 @@ function resolveFixStoryMaxTurns(complexityScore) {
|
|
|
7543
7667
|
* @param resolvedMaxTurns - Turn limit resolved for this dispatch
|
|
7544
7668
|
*/
|
|
7545
7669
|
function logComplexityResult(storyKey, complexity, resolvedMaxTurns) {
|
|
7546
|
-
logger$
|
|
7670
|
+
logger$20.info({
|
|
7547
7671
|
storyKey,
|
|
7548
7672
|
taskCount: complexity.taskCount,
|
|
7549
7673
|
subtaskCount: complexity.subtaskCount,
|
|
@@ -7816,7 +7940,7 @@ function resolveInstallCommand(projectRoot) {
|
|
|
7816
7940
|
|
|
7817
7941
|
//#endregion
|
|
7818
7942
|
//#region src/modules/compiled-workflows/dev-story.ts
|
|
7819
|
-
const logger$
|
|
7943
|
+
const logger$19 = createLogger("compiled-workflows:dev-story");
|
|
7820
7944
|
/** Default timeout for dev-story dispatches in milliseconds (30 min) */
|
|
7821
7945
|
const DEFAULT_TIMEOUT_MS$2 = 18e5;
|
|
7822
7946
|
/**
|
|
@@ -7828,12 +7952,12 @@ const DEFAULT_TIMEOUT_MS$2 = 18e5;
|
|
|
7828
7952
|
*/
|
|
7829
7953
|
async function runDevStory(deps, params) {
|
|
7830
7954
|
const { storyKey, storyFilePath, taskScope, priorFiles, findingsPrompt: handlerFindingsPrompt } = params;
|
|
7831
|
-
logger$
|
|
7955
|
+
logger$19.info({
|
|
7832
7956
|
storyKey,
|
|
7833
7957
|
storyFilePath
|
|
7834
7958
|
}, "Starting compiled dev-story workflow");
|
|
7835
7959
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("dev-story", deps.tokenCeilings);
|
|
7836
|
-
logger$
|
|
7960
|
+
logger$19.info({
|
|
7837
7961
|
workflow: "dev-story",
|
|
7838
7962
|
ceiling: TOKEN_CEILING,
|
|
7839
7963
|
source: tokenCeilingSource
|
|
@@ -7876,10 +8000,10 @@ async function runDevStory(deps, params) {
|
|
|
7876
8000
|
let template;
|
|
7877
8001
|
try {
|
|
7878
8002
|
template = await deps.pack.getPrompt("dev-story");
|
|
7879
|
-
logger$
|
|
8003
|
+
logger$19.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
|
|
7880
8004
|
} catch (err) {
|
|
7881
8005
|
const error = err instanceof Error ? err.message : String(err);
|
|
7882
|
-
logger$
|
|
8006
|
+
logger$19.error({
|
|
7883
8007
|
storyKey,
|
|
7884
8008
|
error
|
|
7885
8009
|
}, "Failed to retrieve dev-story prompt template");
|
|
@@ -7891,20 +8015,20 @@ async function runDevStory(deps, params) {
|
|
|
7891
8015
|
} catch (err) {
|
|
7892
8016
|
const recovered = await recoverStoryFileFromBranch(storyFilePath, deps.projectRoot ?? process.cwd());
|
|
7893
8017
|
if (recovered !== void 0) {
|
|
7894
|
-
logger$
|
|
8018
|
+
logger$19.warn({
|
|
7895
8019
|
storyKey,
|
|
7896
8020
|
storyFilePath
|
|
7897
8021
|
}, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
7898
8022
|
storyContent = recovered;
|
|
7899
8023
|
} else if (err.code === "ENOENT") {
|
|
7900
|
-
logger$
|
|
8024
|
+
logger$19.error({
|
|
7901
8025
|
storyKey,
|
|
7902
8026
|
storyFilePath
|
|
7903
8027
|
}, "Story file not found");
|
|
7904
8028
|
return makeFailureResult("story_file_not_found");
|
|
7905
8029
|
} else {
|
|
7906
8030
|
const error = err instanceof Error ? err.message : String(err);
|
|
7907
|
-
logger$
|
|
8031
|
+
logger$19.error({
|
|
7908
8032
|
storyKey,
|
|
7909
8033
|
storyFilePath,
|
|
7910
8034
|
error
|
|
@@ -7913,7 +8037,7 @@ async function runDevStory(deps, params) {
|
|
|
7913
8037
|
}
|
|
7914
8038
|
}
|
|
7915
8039
|
if (storyContent.trim().length === 0) {
|
|
7916
|
-
logger$
|
|
8040
|
+
logger$19.error({
|
|
7917
8041
|
storyKey,
|
|
7918
8042
|
storyFilePath
|
|
7919
8043
|
}, "Story file is empty");
|
|
@@ -7921,7 +8045,7 @@ async function runDevStory(deps, params) {
|
|
|
7921
8045
|
}
|
|
7922
8046
|
const staleStatus = detectDeprecatedStatusField(storyContent);
|
|
7923
8047
|
if (staleStatus !== null) {
|
|
7924
|
-
logger$
|
|
8048
|
+
logger$19.warn({
|
|
7925
8049
|
storyFilePath,
|
|
7926
8050
|
staleStatus
|
|
7927
8051
|
}, "Story spec contains deprecated Status field — stripped before dispatch (status is managed by Dolt work graph)");
|
|
@@ -7936,17 +8060,17 @@ async function runDevStory(deps, params) {
|
|
|
7936
8060
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
7937
8061
|
if (testPatternDecisions.length > 0) {
|
|
7938
8062
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
7939
|
-
logger$
|
|
8063
|
+
logger$19.debug({
|
|
7940
8064
|
storyKey,
|
|
7941
8065
|
count: testPatternDecisions.length
|
|
7942
8066
|
}, "Loaded test patterns from decision store");
|
|
7943
8067
|
} else {
|
|
7944
8068
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
7945
|
-
logger$
|
|
8069
|
+
logger$19.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
7946
8070
|
}
|
|
7947
8071
|
} catch (err) {
|
|
7948
8072
|
const error = err instanceof Error ? err.message : String(err);
|
|
7949
|
-
logger$
|
|
8073
|
+
logger$19.warn({
|
|
7950
8074
|
storyKey,
|
|
7951
8075
|
error
|
|
7952
8076
|
}, "Failed to load test patterns — using defaults");
|
|
@@ -7960,7 +8084,7 @@ async function runDevStory(deps, params) {
|
|
|
7960
8084
|
if (deps.repoMapInjector !== void 0) {
|
|
7961
8085
|
const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
|
|
7962
8086
|
repoContextContent = injection.text;
|
|
7963
|
-
logger$
|
|
8087
|
+
logger$19.info({
|
|
7964
8088
|
storyKey,
|
|
7965
8089
|
repoMapTokens: Math.ceil(injection.text.length / 4),
|
|
7966
8090
|
symbolCount: injection.symbolCount,
|
|
@@ -7970,7 +8094,7 @@ async function runDevStory(deps, params) {
|
|
|
7970
8094
|
let priorFindingsContent = "";
|
|
7971
8095
|
if (handlerFindingsPrompt !== void 0 && handlerFindingsPrompt.length > 0) {
|
|
7972
8096
|
priorFindingsContent = handlerFindingsPrompt;
|
|
7973
|
-
logger$
|
|
8097
|
+
logger$19.debug({
|
|
7974
8098
|
storyKey,
|
|
7975
8099
|
findingsLen: handlerFindingsPrompt.length
|
|
7976
8100
|
}, "Using pre-computed findings from handler (Story 53-8 AC2)");
|
|
@@ -7982,7 +8106,7 @@ async function runDevStory(deps, params) {
|
|
|
7982
8106
|
});
|
|
7983
8107
|
if (findings.length > 0) {
|
|
7984
8108
|
priorFindingsContent = findings;
|
|
7985
|
-
logger$
|
|
8109
|
+
logger$19.debug({
|
|
7986
8110
|
storyKey,
|
|
7987
8111
|
findingsLen: findings.length
|
|
7988
8112
|
}, "Injecting relevance-scored findings into dev-story prompt");
|
|
@@ -8002,7 +8126,7 @@ async function runDevStory(deps, params) {
|
|
|
8002
8126
|
if (plan.test_categories && plan.test_categories.length > 0) parts.push(`\n### Categories: ${plan.test_categories.join(", ")}`);
|
|
8003
8127
|
if (plan.coverage_notes) parts.push(`\n### Coverage Notes\n${plan.coverage_notes}`);
|
|
8004
8128
|
testPlanContent = parts.join("\n");
|
|
8005
|
-
logger$
|
|
8129
|
+
logger$19.debug({ storyKey }, "Injecting test plan into dev-story prompt");
|
|
8006
8130
|
}
|
|
8007
8131
|
} catch {}
|
|
8008
8132
|
const sections = [
|
|
@@ -8063,7 +8187,7 @@ async function runDevStory(deps, params) {
|
|
|
8063
8187
|
}
|
|
8064
8188
|
];
|
|
8065
8189
|
const { prompt, tokenCount, truncated } = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
8066
|
-
logger$
|
|
8190
|
+
logger$19.info({
|
|
8067
8191
|
storyKey,
|
|
8068
8192
|
tokenCount,
|
|
8069
8193
|
ceiling: TOKEN_CEILING,
|
|
@@ -8087,7 +8211,7 @@ async function runDevStory(deps, params) {
|
|
|
8087
8211
|
dispatchResult = await handle.result;
|
|
8088
8212
|
} catch (err) {
|
|
8089
8213
|
const error = err instanceof Error ? err.message : String(err);
|
|
8090
|
-
logger$
|
|
8214
|
+
logger$19.error({
|
|
8091
8215
|
storyKey,
|
|
8092
8216
|
error
|
|
8093
8217
|
}, "Dispatch threw an unexpected error");
|
|
@@ -8098,11 +8222,11 @@ async function runDevStory(deps, params) {
|
|
|
8098
8222
|
output: dispatchResult.tokenEstimate.output
|
|
8099
8223
|
};
|
|
8100
8224
|
if (dispatchResult.status === "timeout") {
|
|
8101
|
-
logger$
|
|
8225
|
+
logger$19.error({
|
|
8102
8226
|
storyKey,
|
|
8103
8227
|
durationMs: dispatchResult.durationMs
|
|
8104
8228
|
}, "Dev-story dispatch timed out");
|
|
8105
|
-
if (dispatchResult.output.length > 0) logger$
|
|
8229
|
+
if (dispatchResult.output.length > 0) logger$19.info({
|
|
8106
8230
|
storyKey,
|
|
8107
8231
|
partialOutput: dispatchResult.output.slice(0, 500)
|
|
8108
8232
|
}, "Partial output before timeout");
|
|
@@ -8112,12 +8236,12 @@ async function runDevStory(deps, params) {
|
|
|
8112
8236
|
};
|
|
8113
8237
|
}
|
|
8114
8238
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
8115
|
-
logger$
|
|
8239
|
+
logger$19.error({
|
|
8116
8240
|
storyKey,
|
|
8117
8241
|
exitCode: dispatchResult.exitCode,
|
|
8118
8242
|
status: dispatchResult.status
|
|
8119
8243
|
}, "Dev-story dispatch failed");
|
|
8120
|
-
if (dispatchResult.output.length > 0) logger$
|
|
8244
|
+
if (dispatchResult.output.length > 0) logger$19.info({
|
|
8121
8245
|
storyKey,
|
|
8122
8246
|
partialOutput: dispatchResult.output.slice(0, 500)
|
|
8123
8247
|
}, "Partial output from failed dispatch");
|
|
@@ -8129,7 +8253,7 @@ async function runDevStory(deps, params) {
|
|
|
8129
8253
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
8130
8254
|
const details = dispatchResult.parseError ?? "parsed result was null";
|
|
8131
8255
|
const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
|
|
8132
|
-
logger$
|
|
8256
|
+
logger$19.error({
|
|
8133
8257
|
storyKey,
|
|
8134
8258
|
parseError: details,
|
|
8135
8259
|
rawOutputSnippet: rawSnippet
|
|
@@ -8137,12 +8261,12 @@ async function runDevStory(deps, params) {
|
|
|
8137
8261
|
let filesModified = [];
|
|
8138
8262
|
try {
|
|
8139
8263
|
filesModified = await getGitChangedFiles(deps.projectRoot ?? process.cwd());
|
|
8140
|
-
if (filesModified.length > 0) logger$
|
|
8264
|
+
if (filesModified.length > 0) logger$19.info({
|
|
8141
8265
|
storyKey,
|
|
8142
8266
|
fileCount: filesModified.length
|
|
8143
8267
|
}, "Recovered files_modified from git status (YAML fallback)");
|
|
8144
8268
|
} catch (err) {
|
|
8145
|
-
logger$
|
|
8269
|
+
logger$19.warn({
|
|
8146
8270
|
storyKey,
|
|
8147
8271
|
error: err instanceof Error ? err.message : String(err)
|
|
8148
8272
|
}, "Failed to recover files_modified from git");
|
|
@@ -8159,7 +8283,7 @@ async function runDevStory(deps, params) {
|
|
|
8159
8283
|
};
|
|
8160
8284
|
}
|
|
8161
8285
|
const parsed = dispatchResult.parsed;
|
|
8162
|
-
logger$
|
|
8286
|
+
logger$19.info({
|
|
8163
8287
|
storyKey,
|
|
8164
8288
|
result: parsed.result,
|
|
8165
8289
|
acMet: parsed.ac_met.length
|
|
@@ -8573,7 +8697,7 @@ function resolvesIntoExpected(modifiedFilePath, relativePath, expectedFiles) {
|
|
|
8573
8697
|
|
|
8574
8698
|
//#endregion
|
|
8575
8699
|
//#region src/modules/compiled-workflows/code-review.ts
|
|
8576
|
-
const logger$
|
|
8700
|
+
const logger$18 = createLogger("compiled-workflows:code-review");
|
|
8577
8701
|
/**
|
|
8578
8702
|
* Default fallback result when dispatch fails or times out.
|
|
8579
8703
|
* Uses NEEDS_MINOR_FIXES (not NEEDS_MAJOR_REWORK) so a parse/schema failure
|
|
@@ -8648,14 +8772,14 @@ async function countTestMetrics(filesModified, cwd) {
|
|
|
8648
8772
|
async function runCodeReview(deps, params) {
|
|
8649
8773
|
const { storyKey, storyFilePath, workingDirectory, pipelineRunId, filesModified, previousIssues, buildPassed, baselineCommit } = params;
|
|
8650
8774
|
const cwd = workingDirectory ?? process.cwd();
|
|
8651
|
-
logger$
|
|
8775
|
+
logger$18.debug({
|
|
8652
8776
|
storyKey,
|
|
8653
8777
|
storyFilePath,
|
|
8654
8778
|
cwd,
|
|
8655
8779
|
pipelineRunId
|
|
8656
8780
|
}, "Starting code-review workflow");
|
|
8657
8781
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("code-review", deps.tokenCeilings);
|
|
8658
|
-
logger$
|
|
8782
|
+
logger$18.info({
|
|
8659
8783
|
workflow: "code-review",
|
|
8660
8784
|
ceiling: TOKEN_CEILING,
|
|
8661
8785
|
source: tokenCeilingSource
|
|
@@ -8665,7 +8789,7 @@ async function runCodeReview(deps, params) {
|
|
|
8665
8789
|
template = await deps.pack.getPrompt("code-review");
|
|
8666
8790
|
} catch (err) {
|
|
8667
8791
|
const error = err instanceof Error ? err.message : String(err);
|
|
8668
|
-
logger$
|
|
8792
|
+
logger$18.error({ error }, "Failed to retrieve code-review prompt template");
|
|
8669
8793
|
return defaultFailResult(`Failed to retrieve prompt template: ${error}`, {
|
|
8670
8794
|
input: 0,
|
|
8671
8795
|
output: 0
|
|
@@ -8678,10 +8802,10 @@ async function runCodeReview(deps, params) {
|
|
|
8678
8802
|
const error = err instanceof Error ? err.message : String(err);
|
|
8679
8803
|
const recovered = await recoverStoryFileFromBranch(storyFilePath, cwd);
|
|
8680
8804
|
if (recovered !== void 0) {
|
|
8681
|
-
logger$
|
|
8805
|
+
logger$18.warn({ storyFilePath }, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
8682
8806
|
storyContent = recovered;
|
|
8683
8807
|
} else {
|
|
8684
|
-
logger$
|
|
8808
|
+
logger$18.error({
|
|
8685
8809
|
storyFilePath,
|
|
8686
8810
|
error
|
|
8687
8811
|
}, "Failed to read story file (absent from working tree AND branch HEAD)");
|
|
@@ -8702,12 +8826,12 @@ async function runCodeReview(deps, params) {
|
|
|
8702
8826
|
const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
|
|
8703
8827
|
if (scopedTotal <= TOKEN_CEILING) {
|
|
8704
8828
|
gitDiffContent = scopedDiff;
|
|
8705
|
-
logger$
|
|
8829
|
+
logger$18.debug({
|
|
8706
8830
|
fileCount: filesModified.length,
|
|
8707
8831
|
tokenCount: scopedTotal
|
|
8708
8832
|
}, "Using scoped file diff");
|
|
8709
8833
|
} else {
|
|
8710
|
-
logger$
|
|
8834
|
+
logger$18.warn({
|
|
8711
8835
|
estimatedTotal: scopedTotal,
|
|
8712
8836
|
ceiling: TOKEN_CEILING,
|
|
8713
8837
|
fileCount: filesModified.length
|
|
@@ -8721,7 +8845,7 @@ async function runCodeReview(deps, params) {
|
|
|
8721
8845
|
const fullTotal = nonDiffTokens + countTokens(fullDiff);
|
|
8722
8846
|
if (fullTotal <= TOKEN_CEILING) gitDiffContent = fullDiff;
|
|
8723
8847
|
else {
|
|
8724
|
-
logger$
|
|
8848
|
+
logger$18.warn({
|
|
8725
8849
|
estimatedTotal: fullTotal,
|
|
8726
8850
|
ceiling: TOKEN_CEILING
|
|
8727
8851
|
}, "Full git diff would exceed token ceiling — using stat-only summary");
|
|
@@ -8729,7 +8853,7 @@ async function runCodeReview(deps, params) {
|
|
|
8729
8853
|
}
|
|
8730
8854
|
}
|
|
8731
8855
|
if (gitDiffContent.trim().length === 0 && baselineCommit) {
|
|
8732
|
-
logger$
|
|
8856
|
+
logger$18.info({
|
|
8733
8857
|
storyKey,
|
|
8734
8858
|
baselineCommit
|
|
8735
8859
|
}, "Working tree diff empty — diffing against baseline commit");
|
|
@@ -8737,7 +8861,7 @@ async function runCodeReview(deps, params) {
|
|
|
8737
8861
|
const commitTotal = nonDiffTokens + countTokens(commitDiff);
|
|
8738
8862
|
if (commitDiff.trim().length > 0) if (commitTotal <= TOKEN_CEILING) gitDiffContent = commitDiff;
|
|
8739
8863
|
else {
|
|
8740
|
-
logger$
|
|
8864
|
+
logger$18.warn({
|
|
8741
8865
|
estimatedTotal: commitTotal,
|
|
8742
8866
|
ceiling: TOKEN_CEILING
|
|
8743
8867
|
}, "Baseline..HEAD diff exceeds token ceiling — using stat-only summary");
|
|
@@ -8745,7 +8869,7 @@ async function runCodeReview(deps, params) {
|
|
|
8745
8869
|
}
|
|
8746
8870
|
}
|
|
8747
8871
|
if (gitDiffContent.trim().length === 0) {
|
|
8748
|
-
logger$
|
|
8872
|
+
logger$18.info({ storyKey }, "Empty git diff — skipping review with SHIP_IT");
|
|
8749
8873
|
return {
|
|
8750
8874
|
verdict: "SHIP_IT",
|
|
8751
8875
|
issues: 0,
|
|
@@ -8761,7 +8885,7 @@ async function runCodeReview(deps, params) {
|
|
|
8761
8885
|
if (deps.repoMapInjector !== void 0) {
|
|
8762
8886
|
const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
|
|
8763
8887
|
repoContextContent = injection.text;
|
|
8764
|
-
logger$
|
|
8888
|
+
logger$18.info({
|
|
8765
8889
|
storyKey,
|
|
8766
8890
|
repoMapTokens: Math.ceil(injection.text.length / 4),
|
|
8767
8891
|
symbolCount: injection.symbolCount,
|
|
@@ -8781,17 +8905,17 @@ async function runCodeReview(deps, params) {
|
|
|
8781
8905
|
const findings = await getProjectFindings(deps.db);
|
|
8782
8906
|
if (findings.length > 0) {
|
|
8783
8907
|
priorFindingsContent = "Previous reviews found these recurring patterns — pay special attention:\n\n" + findings;
|
|
8784
|
-
logger$
|
|
8908
|
+
logger$18.debug({
|
|
8785
8909
|
storyKey,
|
|
8786
8910
|
findingsLen: findings.length
|
|
8787
8911
|
}, "Injecting prior findings into code-review prompt");
|
|
8788
8912
|
}
|
|
8789
8913
|
} catch {}
|
|
8790
8914
|
const testMetricsContent = await countTestMetrics(filesModified, cwd);
|
|
8791
|
-
if (testMetricsContent) logger$
|
|
8915
|
+
if (testMetricsContent) logger$18.debug({ storyKey }, "Injecting verified test-count metrics into code-review context");
|
|
8792
8916
|
const fileDiffs = gitDiffContent ? parseDiffByFile(gitDiffContent) : void 0;
|
|
8793
8917
|
const scopeAnalysisContent = storyContent && filesModified ? ScopeGuardrail.buildAnalysis(storyContent, filesModified, fileDiffs) : "";
|
|
8794
|
-
if (scopeAnalysisContent) logger$
|
|
8918
|
+
if (scopeAnalysisContent) logger$18.debug({ storyKey }, "Scope analysis detected out-of-scope files");
|
|
8795
8919
|
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" : "";
|
|
8796
8920
|
const sections = [
|
|
8797
8921
|
{
|
|
@@ -8836,11 +8960,11 @@ async function runCodeReview(deps, params) {
|
|
|
8836
8960
|
}
|
|
8837
8961
|
];
|
|
8838
8962
|
const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
8839
|
-
if (assembleResult.truncated) logger$
|
|
8963
|
+
if (assembleResult.truncated) logger$18.warn({
|
|
8840
8964
|
storyKey,
|
|
8841
8965
|
tokenCount: assembleResult.tokenCount
|
|
8842
8966
|
}, "Code-review prompt truncated to fit token ceiling");
|
|
8843
|
-
logger$
|
|
8967
|
+
logger$18.debug({
|
|
8844
8968
|
storyKey,
|
|
8845
8969
|
tokenCount: assembleResult.tokenCount,
|
|
8846
8970
|
truncated: assembleResult.truncated
|
|
@@ -8861,7 +8985,7 @@ async function runCodeReview(deps, params) {
|
|
|
8861
8985
|
dispatchResult = await handle.result;
|
|
8862
8986
|
} catch (err) {
|
|
8863
8987
|
const error = err instanceof Error ? err.message : String(err);
|
|
8864
|
-
logger$
|
|
8988
|
+
logger$18.error({
|
|
8865
8989
|
storyKey,
|
|
8866
8990
|
error
|
|
8867
8991
|
}, "Code-review dispatch threw unexpected error");
|
|
@@ -8877,7 +9001,7 @@ async function runCodeReview(deps, params) {
|
|
|
8877
9001
|
const rawOutput = dispatchResult.output ?? void 0;
|
|
8878
9002
|
if (dispatchResult.status === "failed") {
|
|
8879
9003
|
const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""} ${dispatchResult.output ? `Stderr: ${dispatchResult.output}` : ""}`.trim();
|
|
8880
|
-
logger$
|
|
9004
|
+
logger$18.warn({
|
|
8881
9005
|
storyKey,
|
|
8882
9006
|
exitCode: dispatchResult.exitCode
|
|
8883
9007
|
}, "Code-review dispatch failed");
|
|
@@ -8887,7 +9011,7 @@ async function runCodeReview(deps, params) {
|
|
|
8887
9011
|
};
|
|
8888
9012
|
}
|
|
8889
9013
|
if (dispatchResult.status === "timeout") {
|
|
8890
|
-
logger$
|
|
9014
|
+
logger$18.warn({ storyKey }, "Code-review dispatch timed out");
|
|
8891
9015
|
return {
|
|
8892
9016
|
...defaultFailResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage),
|
|
8893
9017
|
rawOutput
|
|
@@ -8895,7 +9019,7 @@ async function runCodeReview(deps, params) {
|
|
|
8895
9019
|
}
|
|
8896
9020
|
if (dispatchResult.parsed === null) {
|
|
8897
9021
|
const details = dispatchResult.parseError ?? "No YAML block found in output";
|
|
8898
|
-
logger$
|
|
9022
|
+
logger$18.warn({
|
|
8899
9023
|
storyKey,
|
|
8900
9024
|
details
|
|
8901
9025
|
}, "Code-review output schema validation failed");
|
|
@@ -8913,7 +9037,7 @@ async function runCodeReview(deps, params) {
|
|
|
8913
9037
|
const parseResult = CodeReviewResultSchema.safeParse(dispatchResult.parsed);
|
|
8914
9038
|
if (!parseResult.success) {
|
|
8915
9039
|
const details = parseResult.error.message;
|
|
8916
|
-
logger$
|
|
9040
|
+
logger$18.warn({
|
|
8917
9041
|
storyKey,
|
|
8918
9042
|
details
|
|
8919
9043
|
}, "Code-review output failed schema validation");
|
|
@@ -8929,13 +9053,13 @@ async function runCodeReview(deps, params) {
|
|
|
8929
9053
|
};
|
|
8930
9054
|
}
|
|
8931
9055
|
const parsed = parseResult.data;
|
|
8932
|
-
if (parsed.agentVerdict !== parsed.verdict) logger$
|
|
9056
|
+
if (parsed.agentVerdict !== parsed.verdict) logger$18.info({
|
|
8933
9057
|
storyKey,
|
|
8934
9058
|
agentVerdict: parsed.agentVerdict,
|
|
8935
9059
|
pipelineVerdict: parsed.verdict,
|
|
8936
9060
|
issues: parsed.issues
|
|
8937
9061
|
}, "Pipeline overrode agent verdict based on issue severities");
|
|
8938
|
-
logger$
|
|
9062
|
+
logger$18.info({
|
|
8939
9063
|
storyKey,
|
|
8940
9064
|
verdict: parsed.verdict,
|
|
8941
9065
|
issues: parsed.issues
|
|
@@ -8961,14 +9085,14 @@ async function getArchConstraints$2(deps) {
|
|
|
8961
9085
|
if (constraints.length === 0) return "";
|
|
8962
9086
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
8963
9087
|
} catch (err) {
|
|
8964
|
-
logger$
|
|
9088
|
+
logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
8965
9089
|
return "";
|
|
8966
9090
|
}
|
|
8967
9091
|
}
|
|
8968
9092
|
|
|
8969
9093
|
//#endregion
|
|
8970
9094
|
//#region src/modules/compiled-workflows/merge-to-main.ts
|
|
8971
|
-
const logger$
|
|
9095
|
+
const logger$17 = createLogger("compiled-workflows:merge-to-main");
|
|
8972
9096
|
/**
|
|
8973
9097
|
* Execute the merge-to-main phase: merge the story branch into the base branch.
|
|
8974
9098
|
*
|
|
@@ -8988,7 +9112,7 @@ const logger$16 = createLogger("compiled-workflows:merge-to-main");
|
|
|
8988
9112
|
async function runMergeToMain(params) {
|
|
8989
9113
|
const { storyKey, branchName, startBranch, worktreeManager, eventBus, projectRoot } = params;
|
|
8990
9114
|
const mergeStrategy = params.mergeStrategy ?? "ff-only";
|
|
8991
|
-
logger$
|
|
9115
|
+
logger$17.info({
|
|
8992
9116
|
storyKey,
|
|
8993
9117
|
branchName,
|
|
8994
9118
|
startBranch,
|
|
@@ -8996,7 +9120,7 @@ async function runMergeToMain(params) {
|
|
|
8996
9120
|
}, "Starting merge-to-main phase");
|
|
8997
9121
|
const dirtiedFiles = listParentDirtyIntersection(branchName, startBranch, projectRoot);
|
|
8998
9122
|
if (dirtiedFiles.length > 0) {
|
|
8999
|
-
logger$
|
|
9123
|
+
logger$17.warn({
|
|
9000
9124
|
storyKey,
|
|
9001
9125
|
branchName,
|
|
9002
9126
|
dirtiedFiles
|
|
@@ -9009,7 +9133,7 @@ async function runMergeToMain(params) {
|
|
|
9009
9133
|
}
|
|
9010
9134
|
const ffSuccess = tryFfMerge(branchName, projectRoot);
|
|
9011
9135
|
if (ffSuccess) {
|
|
9012
|
-
logger$
|
|
9136
|
+
logger$17.info({
|
|
9013
9137
|
storyKey,
|
|
9014
9138
|
branchName
|
|
9015
9139
|
}, "Fast-forward merge succeeded");
|
|
@@ -9017,7 +9141,7 @@ async function runMergeToMain(params) {
|
|
|
9017
9141
|
return { success: true };
|
|
9018
9142
|
}
|
|
9019
9143
|
if (mergeStrategy === "ff-only") {
|
|
9020
|
-
logger$
|
|
9144
|
+
logger$17.warn({
|
|
9021
9145
|
storyKey,
|
|
9022
9146
|
branchName,
|
|
9023
9147
|
startBranch
|
|
@@ -9027,13 +9151,13 @@ async function runMergeToMain(params) {
|
|
|
9027
9151
|
reason: "ff-only-merge-not-possible"
|
|
9028
9152
|
};
|
|
9029
9153
|
}
|
|
9030
|
-
logger$
|
|
9154
|
+
logger$17.info({
|
|
9031
9155
|
storyKey,
|
|
9032
9156
|
branchName
|
|
9033
9157
|
}, "Fast-forward merge failed — attempting 3-way merge");
|
|
9034
9158
|
const threeWayResult = tryThreeWayMerge(branchName, projectRoot);
|
|
9035
9159
|
if (threeWayResult.success) {
|
|
9036
|
-
logger$
|
|
9160
|
+
logger$17.info({
|
|
9037
9161
|
storyKey,
|
|
9038
9162
|
branchName
|
|
9039
9163
|
}, "3-way merge succeeded");
|
|
@@ -9041,7 +9165,7 @@ async function runMergeToMain(params) {
|
|
|
9041
9165
|
return { success: true };
|
|
9042
9166
|
}
|
|
9043
9167
|
const { conflictingFiles } = threeWayResult;
|
|
9044
|
-
logger$
|
|
9168
|
+
logger$17.warn({
|
|
9045
9169
|
storyKey,
|
|
9046
9170
|
branchName,
|
|
9047
9171
|
conflictingFiles
|
|
@@ -9094,7 +9218,7 @@ function listParentDirtyIntersection(branchName, startBranch, projectRoot) {
|
|
|
9094
9218
|
});
|
|
9095
9219
|
return diffOut.split("\n").filter((f$1) => f$1.trim().length > 0).filter((f$1) => dirty.has(f$1));
|
|
9096
9220
|
} catch (err) {
|
|
9097
|
-
logger$
|
|
9221
|
+
logger$17.warn({ err }, "parent-clean precondition check failed (best-effort) — proceeding to merge");
|
|
9098
9222
|
return [];
|
|
9099
9223
|
}
|
|
9100
9224
|
}
|
|
@@ -9171,7 +9295,7 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
9171
9295
|
});
|
|
9172
9296
|
conflictingFiles = diffOutput.trim().split("\n").filter((line) => line.length > 0);
|
|
9173
9297
|
} catch (diffErr) {
|
|
9174
|
-
logger$
|
|
9298
|
+
logger$17.warn({ err: diffErr }, "Failed to list conflicting files (best-effort)");
|
|
9175
9299
|
}
|
|
9176
9300
|
try {
|
|
9177
9301
|
execFileSync("git", ["merge", "--abort"], {
|
|
@@ -9183,7 +9307,7 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
9183
9307
|
]
|
|
9184
9308
|
});
|
|
9185
9309
|
} catch (abortErr) {
|
|
9186
|
-
logger$
|
|
9310
|
+
logger$17.warn({ err: abortErr }, "Failed to abort merge (best-effort)");
|
|
9187
9311
|
}
|
|
9188
9312
|
return {
|
|
9189
9313
|
success: false,
|
|
@@ -9205,12 +9329,12 @@ function tryThreeWayMerge(branchName, projectRoot) {
|
|
|
9205
9329
|
async function cleanupAfterSuccessfulMerge(storyKey, branchName, worktreeManager, _projectRoot) {
|
|
9206
9330
|
try {
|
|
9207
9331
|
await worktreeManager.cleanupWorktree(storyKey);
|
|
9208
|
-
logger$
|
|
9332
|
+
logger$17.info({
|
|
9209
9333
|
storyKey,
|
|
9210
9334
|
branchName
|
|
9211
9335
|
}, "Worktree + branch removed after successful merge");
|
|
9212
9336
|
} catch (worktreeErr) {
|
|
9213
|
-
logger$
|
|
9337
|
+
logger$17.warn({
|
|
9214
9338
|
storyKey,
|
|
9215
9339
|
err: worktreeErr
|
|
9216
9340
|
}, "Failed to remove worktree (best-effort)");
|
|
@@ -9239,7 +9363,7 @@ function createMergeQueue() {
|
|
|
9239
9363
|
|
|
9240
9364
|
//#endregion
|
|
9241
9365
|
//#region src/modules/compiled-workflows/test-plan.ts
|
|
9242
|
-
const logger$
|
|
9366
|
+
const logger$16 = createLogger("compiled-workflows:test-plan");
|
|
9243
9367
|
/** Default timeout for test-plan dispatches in milliseconds (5 min — lightweight call) */
|
|
9244
9368
|
const DEFAULT_TIMEOUT_MS$1 = 3e5;
|
|
9245
9369
|
/**
|
|
@@ -9251,12 +9375,12 @@ const DEFAULT_TIMEOUT_MS$1 = 3e5;
|
|
|
9251
9375
|
*/
|
|
9252
9376
|
async function runTestPlan(deps, params) {
|
|
9253
9377
|
const { storyKey, storyFilePath, pipelineRunId } = params;
|
|
9254
|
-
logger$
|
|
9378
|
+
logger$16.info({
|
|
9255
9379
|
storyKey,
|
|
9256
9380
|
storyFilePath
|
|
9257
9381
|
}, "Starting compiled test-plan workflow");
|
|
9258
9382
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-plan", deps.tokenCeilings);
|
|
9259
|
-
logger$
|
|
9383
|
+
logger$16.info({
|
|
9260
9384
|
workflow: "test-plan",
|
|
9261
9385
|
ceiling: TOKEN_CEILING,
|
|
9262
9386
|
source: tokenCeilingSource
|
|
@@ -9264,10 +9388,10 @@ async function runTestPlan(deps, params) {
|
|
|
9264
9388
|
let template;
|
|
9265
9389
|
try {
|
|
9266
9390
|
template = await deps.pack.getPrompt("test-plan");
|
|
9267
|
-
logger$
|
|
9391
|
+
logger$16.debug({ storyKey }, "Retrieved test-plan prompt template from pack");
|
|
9268
9392
|
} catch (err) {
|
|
9269
9393
|
const error = err instanceof Error ? err.message : String(err);
|
|
9270
|
-
logger$
|
|
9394
|
+
logger$16.warn({
|
|
9271
9395
|
storyKey,
|
|
9272
9396
|
error
|
|
9273
9397
|
}, "Failed to retrieve test-plan prompt template");
|
|
@@ -9278,14 +9402,14 @@ async function runTestPlan(deps, params) {
|
|
|
9278
9402
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
9279
9403
|
} catch (err) {
|
|
9280
9404
|
if (err.code === "ENOENT") {
|
|
9281
|
-
logger$
|
|
9405
|
+
logger$16.warn({
|
|
9282
9406
|
storyKey,
|
|
9283
9407
|
storyFilePath
|
|
9284
9408
|
}, "Story file not found for test planning");
|
|
9285
9409
|
return makeTestPlanFailureResult("story_file_not_found");
|
|
9286
9410
|
}
|
|
9287
9411
|
const error = err instanceof Error ? err.message : String(err);
|
|
9288
|
-
logger$
|
|
9412
|
+
logger$16.warn({
|
|
9289
9413
|
storyKey,
|
|
9290
9414
|
storyFilePath,
|
|
9291
9415
|
error
|
|
@@ -9299,13 +9423,13 @@ async function runTestPlan(deps, params) {
|
|
|
9299
9423
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
9300
9424
|
if (testPatternDecisions.length > 0) {
|
|
9301
9425
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
9302
|
-
logger$
|
|
9426
|
+
logger$16.debug({
|
|
9303
9427
|
storyKey,
|
|
9304
9428
|
count: testPatternDecisions.length
|
|
9305
9429
|
}, "Loaded test patterns from decision store");
|
|
9306
9430
|
} else {
|
|
9307
9431
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
9308
|
-
logger$
|
|
9432
|
+
logger$16.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
9309
9433
|
}
|
|
9310
9434
|
} catch {
|
|
9311
9435
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
@@ -9327,7 +9451,7 @@ async function runTestPlan(deps, params) {
|
|
|
9327
9451
|
priority: "optional"
|
|
9328
9452
|
}
|
|
9329
9453
|
], TOKEN_CEILING);
|
|
9330
|
-
logger$
|
|
9454
|
+
logger$16.info({
|
|
9331
9455
|
storyKey,
|
|
9332
9456
|
tokenCount,
|
|
9333
9457
|
ceiling: TOKEN_CEILING,
|
|
@@ -9348,7 +9472,7 @@ async function runTestPlan(deps, params) {
|
|
|
9348
9472
|
dispatchResult = await handle.result;
|
|
9349
9473
|
} catch (err) {
|
|
9350
9474
|
const error = err instanceof Error ? err.message : String(err);
|
|
9351
|
-
logger$
|
|
9475
|
+
logger$16.warn({
|
|
9352
9476
|
storyKey,
|
|
9353
9477
|
error
|
|
9354
9478
|
}, "Test-plan dispatch threw an unexpected error");
|
|
@@ -9359,7 +9483,7 @@ async function runTestPlan(deps, params) {
|
|
|
9359
9483
|
output: dispatchResult.tokenEstimate.output
|
|
9360
9484
|
};
|
|
9361
9485
|
if (dispatchResult.status === "timeout") {
|
|
9362
|
-
logger$
|
|
9486
|
+
logger$16.warn({
|
|
9363
9487
|
storyKey,
|
|
9364
9488
|
durationMs: dispatchResult.durationMs
|
|
9365
9489
|
}, "Test-plan dispatch timed out");
|
|
@@ -9369,7 +9493,7 @@ async function runTestPlan(deps, params) {
|
|
|
9369
9493
|
};
|
|
9370
9494
|
}
|
|
9371
9495
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
9372
|
-
logger$
|
|
9496
|
+
logger$16.warn({
|
|
9373
9497
|
storyKey,
|
|
9374
9498
|
exitCode: dispatchResult.exitCode,
|
|
9375
9499
|
status: dispatchResult.status
|
|
@@ -9381,7 +9505,7 @@ async function runTestPlan(deps, params) {
|
|
|
9381
9505
|
}
|
|
9382
9506
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
9383
9507
|
const details = dispatchResult.parseError ?? "parsed result was null";
|
|
9384
|
-
logger$
|
|
9508
|
+
logger$16.warn({
|
|
9385
9509
|
storyKey,
|
|
9386
9510
|
parseError: details
|
|
9387
9511
|
}, "Test-plan YAML schema validation failed");
|
|
@@ -9404,19 +9528,19 @@ async function runTestPlan(deps, params) {
|
|
|
9404
9528
|
}),
|
|
9405
9529
|
rationale: `Test plan for ${storyKey}: ${parsed.test_files.length} test files, categories: ${parsed.test_categories.join(", ")}`
|
|
9406
9530
|
});
|
|
9407
|
-
logger$
|
|
9531
|
+
logger$16.info({
|
|
9408
9532
|
storyKey,
|
|
9409
9533
|
fileCount: parsed.test_files.length,
|
|
9410
9534
|
categories: parsed.test_categories
|
|
9411
9535
|
}, "Test plan stored in decision store");
|
|
9412
9536
|
} catch (err) {
|
|
9413
9537
|
const error = err instanceof Error ? err.message : String(err);
|
|
9414
|
-
logger$
|
|
9538
|
+
logger$16.warn({
|
|
9415
9539
|
storyKey,
|
|
9416
9540
|
error
|
|
9417
9541
|
}, "Failed to store test plan in decision store — proceeding anyway");
|
|
9418
9542
|
}
|
|
9419
|
-
logger$
|
|
9543
|
+
logger$16.info({
|
|
9420
9544
|
storyKey,
|
|
9421
9545
|
result: parsed.result
|
|
9422
9546
|
}, "Test-plan workflow completed");
|
|
@@ -9456,14 +9580,14 @@ async function getArchConstraints$1(deps) {
|
|
|
9456
9580
|
if (constraints.length === 0) return "";
|
|
9457
9581
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
9458
9582
|
} catch (err) {
|
|
9459
|
-
logger$
|
|
9583
|
+
logger$16.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints for test-plan — proceeding without them");
|
|
9460
9584
|
return "";
|
|
9461
9585
|
}
|
|
9462
9586
|
}
|
|
9463
9587
|
|
|
9464
9588
|
//#endregion
|
|
9465
9589
|
//#region src/modules/implementation-orchestrator/probe-author-integration.ts
|
|
9466
|
-
const logger$
|
|
9590
|
+
const logger$15 = createLogger("implementation-orchestrator:probe-author");
|
|
9467
9591
|
/**
|
|
9468
9592
|
* Default timeout for probe-author dispatches (10 min).
|
|
9469
9593
|
* obs_2026-05-04_023 layer 2: raised from 300_000 → 600_000 after Story
|
|
@@ -9514,7 +9638,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9514
9638
|
};
|
|
9515
9639
|
const stateIntegratingActive = stateIntegratingEnabled !== false;
|
|
9516
9640
|
if (bypassGates !== true && !detectsEventDrivenAC(epicContent) && !(stateIntegratingActive && detectsStateIntegratingAC(epicContent))) {
|
|
9517
|
-
logger$
|
|
9641
|
+
logger$15.debug({ storyKey }, "probe-author: source AC neither event-driven nor state-integrating — skipping");
|
|
9518
9642
|
emitEvent?.("probe-author:skipped", {
|
|
9519
9643
|
storyKey,
|
|
9520
9644
|
runId: pipelineRunId,
|
|
@@ -9526,7 +9650,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9526
9650
|
try {
|
|
9527
9651
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
9528
9652
|
if (bypassGates !== true && /^## Runtime Probes/m.test(storyContent)) {
|
|
9529
|
-
logger$
|
|
9653
|
+
logger$15.info({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping");
|
|
9530
9654
|
emitEvent?.("probe-author:skipped", {
|
|
9531
9655
|
storyKey,
|
|
9532
9656
|
runId: pipelineRunId,
|
|
@@ -9536,7 +9660,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9536
9660
|
}
|
|
9537
9661
|
} catch (err) {
|
|
9538
9662
|
const error = err instanceof Error ? err.message : String(err);
|
|
9539
|
-
logger$
|
|
9663
|
+
logger$15.warn({
|
|
9540
9664
|
storyKey,
|
|
9541
9665
|
error
|
|
9542
9666
|
}, "probe-author: failed to read story file — falling through");
|
|
@@ -9551,10 +9675,10 @@ async function runProbeAuthor(deps, params) {
|
|
|
9551
9675
|
let template;
|
|
9552
9676
|
try {
|
|
9553
9677
|
template = await deps.pack.getPrompt("probe-author");
|
|
9554
|
-
logger$
|
|
9678
|
+
logger$15.debug({ storyKey }, "probe-author: retrieved prompt template");
|
|
9555
9679
|
} catch (err) {
|
|
9556
9680
|
const error = err instanceof Error ? err.message : String(err);
|
|
9557
|
-
logger$
|
|
9681
|
+
logger$15.warn({
|
|
9558
9682
|
storyKey,
|
|
9559
9683
|
error
|
|
9560
9684
|
}, "probe-author: failed to get prompt template — falling through");
|
|
@@ -9589,13 +9713,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9589
9713
|
};
|
|
9590
9714
|
let dispatchResult;
|
|
9591
9715
|
try {
|
|
9592
|
-
logger$
|
|
9716
|
+
logger$15.info({ storyKey }, "probe-author: dispatching probe-author agent");
|
|
9593
9717
|
dispatchResult = await doDispatch(basePrompt, DEFAULT_TIMEOUT_MS);
|
|
9594
9718
|
tokenUsage.input += dispatchResult.tokenEstimate.input;
|
|
9595
9719
|
tokenUsage.output += dispatchResult.tokenEstimate.output;
|
|
9596
9720
|
} catch (err) {
|
|
9597
9721
|
const error = err instanceof Error ? err.message : String(err);
|
|
9598
|
-
logger$
|
|
9722
|
+
logger$15.warn({
|
|
9599
9723
|
storyKey,
|
|
9600
9724
|
error
|
|
9601
9725
|
}, "probe-author: dispatch error — falling through to dev-story");
|
|
@@ -9608,7 +9732,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9608
9732
|
}
|
|
9609
9733
|
if (dispatchResult.status === "timeout") {
|
|
9610
9734
|
const elapsedMs = Date.now() - start;
|
|
9611
|
-
logger$
|
|
9735
|
+
logger$15.warn({
|
|
9612
9736
|
storyKey,
|
|
9613
9737
|
elapsedMs
|
|
9614
9738
|
}, "probe-author: dispatch timed out — retrying with 1.5× timeout");
|
|
@@ -9622,13 +9746,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9622
9746
|
tokenUsage.input += retryResult.tokenEstimate.input;
|
|
9623
9747
|
tokenUsage.output += retryResult.tokenEstimate.output;
|
|
9624
9748
|
if (retryResult.status === "timeout") {
|
|
9625
|
-
logger$
|
|
9749
|
+
logger$15.warn({ storyKey }, "probe-author: retry also timed out — falling through to dev-story");
|
|
9626
9750
|
return makeFailedResult("dispatch_timeout", tokenUsage, start);
|
|
9627
9751
|
}
|
|
9628
9752
|
dispatchResult = retryResult;
|
|
9629
9753
|
} catch (retryErr) {
|
|
9630
9754
|
const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
9631
|
-
logger$
|
|
9755
|
+
logger$15.warn({
|
|
9632
9756
|
storyKey,
|
|
9633
9757
|
error
|
|
9634
9758
|
}, "probe-author: retry dispatch error — falling through to dev-story");
|
|
@@ -9637,7 +9761,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9637
9761
|
}
|
|
9638
9762
|
if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
|
|
9639
9763
|
const error = `dispatch_failed with exit_code=${dispatchResult.exitCode}`;
|
|
9640
|
-
logger$
|
|
9764
|
+
logger$15.warn({ storyKey }, `probe-author: ${error} — falling through to dev-story`);
|
|
9641
9765
|
emitEvent?.("probe-author:dispatch-error", {
|
|
9642
9766
|
storyKey,
|
|
9643
9767
|
runId: pipelineRunId,
|
|
@@ -9648,7 +9772,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9648
9772
|
if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
|
|
9649
9773
|
const parseError = dispatchResult.parseError ?? "parsed result was null";
|
|
9650
9774
|
const rawOutputSnippet = dispatchResult.output.slice(0, 500);
|
|
9651
|
-
logger$
|
|
9775
|
+
logger$15.warn({
|
|
9652
9776
|
storyKey,
|
|
9653
9777
|
parseError,
|
|
9654
9778
|
rawOutputSnippet
|
|
@@ -9665,13 +9789,13 @@ async function runProbeAuthor(deps, params) {
|
|
|
9665
9789
|
tokenUsage.input += retryResult.tokenEstimate.input;
|
|
9666
9790
|
tokenUsage.output += retryResult.tokenEstimate.output;
|
|
9667
9791
|
if (retryResult.parseError !== null || retryResult.parsed === null) {
|
|
9668
|
-
logger$
|
|
9792
|
+
logger$15.warn({ storyKey }, "probe-author: retry still produced invalid YAML — falling through");
|
|
9669
9793
|
return makeFailedResult("invalid_yaml_after_retry", tokenUsage, start);
|
|
9670
9794
|
}
|
|
9671
9795
|
dispatchResult = retryResult;
|
|
9672
9796
|
} catch (retryErr) {
|
|
9673
9797
|
const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
9674
|
-
logger$
|
|
9798
|
+
logger$15.warn({
|
|
9675
9799
|
storyKey,
|
|
9676
9800
|
error
|
|
9677
9801
|
}, "probe-author: retry error after invalid YAML — falling through");
|
|
@@ -9682,7 +9806,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9682
9806
|
const probeValidation = RuntimeProbeListSchema.safeParse(parsedOutput.probes);
|
|
9683
9807
|
if (!probeValidation.success) {
|
|
9684
9808
|
const validationError = probeValidation.error.message;
|
|
9685
|
-
logger$
|
|
9809
|
+
logger$15.warn({
|
|
9686
9810
|
storyKey,
|
|
9687
9811
|
validationError
|
|
9688
9812
|
}, "probe-author: probes failed RuntimeProbeListSchema — falling through");
|
|
@@ -9698,7 +9822,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9698
9822
|
probesParsedCount: probes.length
|
|
9699
9823
|
});
|
|
9700
9824
|
if (probes.length === 0) {
|
|
9701
|
-
logger$
|
|
9825
|
+
logger$15.info({ storyKey }, "probe-author: authored empty probes list — no probes needed");
|
|
9702
9826
|
emitEvent?.("probe-author:no-probes-authored", {
|
|
9703
9827
|
storyKey,
|
|
9704
9828
|
runId: pipelineRunId
|
|
@@ -9713,7 +9837,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9713
9837
|
try {
|
|
9714
9838
|
const refreshedContent = await readFile$1(storyFilePath, "utf-8");
|
|
9715
9839
|
if (/^## Runtime Probes/m.test(refreshedContent)) {
|
|
9716
|
-
logger$
|
|
9840
|
+
logger$15.info({ storyKey }, "probe-author: ## Runtime Probes section appeared after dispatch — skipping append (idempotent)");
|
|
9717
9841
|
const dispatchDurationMs$1 = Date.now() - start;
|
|
9718
9842
|
emitEvent?.("probe-author:dispatched", {
|
|
9719
9843
|
storyKey,
|
|
@@ -9732,7 +9856,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9732
9856
|
const tmpPath = join$1(targetDir, `.probe-author-${Date.now()}.tmp.md`);
|
|
9733
9857
|
await writeFile$1(tmpPath, newContent, "utf-8");
|
|
9734
9858
|
await rename(tmpPath, storyFilePath);
|
|
9735
|
-
logger$
|
|
9859
|
+
logger$15.info({
|
|
9736
9860
|
storyKey,
|
|
9737
9861
|
probesCount: probes.length
|
|
9738
9862
|
}, "probe-author: appended ## Runtime Probes section");
|
|
@@ -9744,7 +9868,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9744
9868
|
});
|
|
9745
9869
|
} catch (err) {
|
|
9746
9870
|
const error = err instanceof Error ? err.message : String(err);
|
|
9747
|
-
logger$
|
|
9871
|
+
logger$15.warn({
|
|
9748
9872
|
storyKey,
|
|
9749
9873
|
error
|
|
9750
9874
|
}, "probe-author: failed to append probes — falling through to dev-story");
|
|
@@ -9766,7 +9890,7 @@ async function runProbeAuthor(deps, params) {
|
|
|
9766
9890
|
costUsd,
|
|
9767
9891
|
triggered_by: triggerClass ?? "event-driven"
|
|
9768
9892
|
});
|
|
9769
|
-
logger$
|
|
9893
|
+
logger$15.info({
|
|
9770
9894
|
storyKey,
|
|
9771
9895
|
probesAuthoredCount: probes.length
|
|
9772
9896
|
}, "probe-author: phase complete");
|
|
@@ -9801,7 +9925,7 @@ function estimateDispatchCost$1(input, output) {
|
|
|
9801
9925
|
|
|
9802
9926
|
//#endregion
|
|
9803
9927
|
//#region src/modules/compiled-workflows/test-expansion.ts
|
|
9804
|
-
const logger$
|
|
9928
|
+
const logger$14 = createLogger("compiled-workflows:test-expansion");
|
|
9805
9929
|
function defaultFallbackResult(error, tokenUsage) {
|
|
9806
9930
|
return {
|
|
9807
9931
|
expansion_priority: "low",
|
|
@@ -9831,14 +9955,14 @@ function defaultFallbackResult(error, tokenUsage) {
|
|
|
9831
9955
|
async function runTestExpansion(deps, params) {
|
|
9832
9956
|
const { storyKey, storyFilePath, pipelineRunId, filesModified, workingDirectory } = params;
|
|
9833
9957
|
const cwd = workingDirectory ?? process.cwd();
|
|
9834
|
-
logger$
|
|
9958
|
+
logger$14.debug({
|
|
9835
9959
|
storyKey,
|
|
9836
9960
|
storyFilePath,
|
|
9837
9961
|
cwd,
|
|
9838
9962
|
pipelineRunId
|
|
9839
9963
|
}, "Starting test-expansion workflow");
|
|
9840
9964
|
const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-expansion", deps.tokenCeilings);
|
|
9841
|
-
logger$
|
|
9965
|
+
logger$14.info({
|
|
9842
9966
|
workflow: "test-expansion",
|
|
9843
9967
|
ceiling: TOKEN_CEILING,
|
|
9844
9968
|
source: tokenCeilingSource
|
|
@@ -9848,7 +9972,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9848
9972
|
template = await deps.pack.getPrompt("test-expansion");
|
|
9849
9973
|
} catch (err) {
|
|
9850
9974
|
const error = err instanceof Error ? err.message : String(err);
|
|
9851
|
-
logger$
|
|
9975
|
+
logger$14.warn({ error }, "Failed to retrieve test-expansion prompt template");
|
|
9852
9976
|
return defaultFallbackResult(`Failed to retrieve prompt template: ${error}`, {
|
|
9853
9977
|
input: 0,
|
|
9854
9978
|
output: 0
|
|
@@ -9859,7 +9983,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9859
9983
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
9860
9984
|
} catch (err) {
|
|
9861
9985
|
const error = err instanceof Error ? err.message : String(err);
|
|
9862
|
-
logger$
|
|
9986
|
+
logger$14.warn({
|
|
9863
9987
|
storyFilePath,
|
|
9864
9988
|
error
|
|
9865
9989
|
}, "Failed to read story file");
|
|
@@ -9875,13 +9999,13 @@ async function runTestExpansion(deps, params) {
|
|
|
9875
9999
|
const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
|
|
9876
10000
|
if (testPatternDecisions.length > 0) {
|
|
9877
10001
|
testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
|
|
9878
|
-
logger$
|
|
10002
|
+
logger$14.debug({
|
|
9879
10003
|
storyKey,
|
|
9880
10004
|
count: testPatternDecisions.length
|
|
9881
10005
|
}, "Loaded test patterns from decision store");
|
|
9882
10006
|
} else {
|
|
9883
10007
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
9884
|
-
logger$
|
|
10008
|
+
logger$14.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
|
|
9885
10009
|
}
|
|
9886
10010
|
} catch {
|
|
9887
10011
|
testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
|
|
@@ -9896,12 +10020,12 @@ async function runTestExpansion(deps, params) {
|
|
|
9896
10020
|
const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
|
|
9897
10021
|
if (scopedTotal <= TOKEN_CEILING) {
|
|
9898
10022
|
gitDiffContent = scopedDiff;
|
|
9899
|
-
logger$
|
|
10023
|
+
logger$14.debug({
|
|
9900
10024
|
fileCount: filesModified.length,
|
|
9901
10025
|
tokenCount: scopedTotal
|
|
9902
10026
|
}, "Using scoped file diff");
|
|
9903
10027
|
} else {
|
|
9904
|
-
logger$
|
|
10028
|
+
logger$14.warn({
|
|
9905
10029
|
estimatedTotal: scopedTotal,
|
|
9906
10030
|
ceiling: TOKEN_CEILING,
|
|
9907
10031
|
fileCount: filesModified.length
|
|
@@ -9909,7 +10033,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9909
10033
|
gitDiffContent = await getGitDiffStatForFiles(filesModified, cwd);
|
|
9910
10034
|
}
|
|
9911
10035
|
} catch (err) {
|
|
9912
|
-
logger$
|
|
10036
|
+
logger$14.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to get git diff — proceeding with empty diff");
|
|
9913
10037
|
}
|
|
9914
10038
|
const sections = [
|
|
9915
10039
|
{
|
|
@@ -9934,11 +10058,11 @@ async function runTestExpansion(deps, params) {
|
|
|
9934
10058
|
}
|
|
9935
10059
|
];
|
|
9936
10060
|
const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
|
|
9937
|
-
if (assembleResult.truncated) logger$
|
|
10061
|
+
if (assembleResult.truncated) logger$14.warn({
|
|
9938
10062
|
storyKey,
|
|
9939
10063
|
tokenCount: assembleResult.tokenCount
|
|
9940
10064
|
}, "Test-expansion prompt truncated to fit token ceiling");
|
|
9941
|
-
logger$
|
|
10065
|
+
logger$14.debug({
|
|
9942
10066
|
storyKey,
|
|
9943
10067
|
tokenCount: assembleResult.tokenCount,
|
|
9944
10068
|
truncated: assembleResult.truncated
|
|
@@ -9958,7 +10082,7 @@ async function runTestExpansion(deps, params) {
|
|
|
9958
10082
|
dispatchResult = await handle.result;
|
|
9959
10083
|
} catch (err) {
|
|
9960
10084
|
const error = err instanceof Error ? err.message : String(err);
|
|
9961
|
-
logger$
|
|
10085
|
+
logger$14.warn({
|
|
9962
10086
|
storyKey,
|
|
9963
10087
|
error
|
|
9964
10088
|
}, "Test-expansion dispatch threw unexpected error");
|
|
@@ -9973,19 +10097,19 @@ async function runTestExpansion(deps, params) {
|
|
|
9973
10097
|
};
|
|
9974
10098
|
if (dispatchResult.status === "failed") {
|
|
9975
10099
|
const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""}`.trim();
|
|
9976
|
-
logger$
|
|
10100
|
+
logger$14.warn({
|
|
9977
10101
|
storyKey,
|
|
9978
10102
|
exitCode: dispatchResult.exitCode
|
|
9979
10103
|
}, "Test-expansion dispatch failed");
|
|
9980
10104
|
return defaultFallbackResult(errorMsg, tokenUsage);
|
|
9981
10105
|
}
|
|
9982
10106
|
if (dispatchResult.status === "timeout") {
|
|
9983
|
-
logger$
|
|
10107
|
+
logger$14.warn({ storyKey }, "Test-expansion dispatch timed out");
|
|
9984
10108
|
return defaultFallbackResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage);
|
|
9985
10109
|
}
|
|
9986
10110
|
if (dispatchResult.parsed === null) {
|
|
9987
10111
|
const details = dispatchResult.parseError ?? "No YAML block found in output";
|
|
9988
|
-
logger$
|
|
10112
|
+
logger$14.warn({
|
|
9989
10113
|
storyKey,
|
|
9990
10114
|
details
|
|
9991
10115
|
}, "Test-expansion output has no parseable YAML");
|
|
@@ -9994,14 +10118,14 @@ async function runTestExpansion(deps, params) {
|
|
|
9994
10118
|
const parseResult = TestExpansionResultSchema.safeParse(dispatchResult.parsed);
|
|
9995
10119
|
if (!parseResult.success) {
|
|
9996
10120
|
const details = parseResult.error.message;
|
|
9997
|
-
logger$
|
|
10121
|
+
logger$14.warn({
|
|
9998
10122
|
storyKey,
|
|
9999
10123
|
details
|
|
10000
10124
|
}, "Test-expansion output failed schema validation");
|
|
10001
10125
|
return defaultFallbackResult(`schema_validation_failed: ${details}`, tokenUsage);
|
|
10002
10126
|
}
|
|
10003
10127
|
const parsed = parseResult.data;
|
|
10004
|
-
logger$
|
|
10128
|
+
logger$14.info({
|
|
10005
10129
|
storyKey,
|
|
10006
10130
|
expansion_priority: parsed.expansion_priority,
|
|
10007
10131
|
coverage_gaps: parsed.coverage_gaps.length,
|
|
@@ -10026,14 +10150,14 @@ async function getArchConstraints(deps) {
|
|
|
10026
10150
|
if (constraints.length === 0) return "";
|
|
10027
10151
|
return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
10028
10152
|
} catch (err) {
|
|
10029
|
-
logger$
|
|
10153
|
+
logger$14.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
|
|
10030
10154
|
return "";
|
|
10031
10155
|
}
|
|
10032
10156
|
}
|
|
10033
10157
|
|
|
10034
10158
|
//#endregion
|
|
10035
10159
|
//#region src/modules/compiled-workflows/probe-author.ts
|
|
10036
|
-
const logger$
|
|
10160
|
+
const logger$13 = createLogger("compiled-workflows:probe-author");
|
|
10037
10161
|
/**
|
|
10038
10162
|
* Default initial timeout: 10 min. Override via SUBSTRATE_PROBE_AUTHOR_TIMEOUT_MS (ms).
|
|
10039
10163
|
* Story 65-7: raised from 300 s to 600 s to reduce infra-timeout false negatives.
|
|
@@ -10483,7 +10607,7 @@ function detectConflictGroupsWithContracts(storyKeys, config, declarations) {
|
|
|
10483
10607
|
|
|
10484
10608
|
//#endregion
|
|
10485
10609
|
//#region src/modules/implementation-orchestrator/seed-methodology-context.ts
|
|
10486
|
-
const logger$
|
|
10610
|
+
const logger$12 = createLogger("implementation-orchestrator:seed");
|
|
10487
10611
|
/** Max chars for the architecture summary seeded into decisions */
|
|
10488
10612
|
const MAX_ARCH_CHARS = 6e3;
|
|
10489
10613
|
/** Max chars per epic-shard decision value (per-story or per-epic fallback) */
|
|
@@ -10517,12 +10641,12 @@ async function seedMethodologyContext(db, projectRoot) {
|
|
|
10517
10641
|
const testCount = await seedTestPatterns(db, projectRoot);
|
|
10518
10642
|
if (testCount === -1) result.skippedCategories.push("test-patterns");
|
|
10519
10643
|
else result.decisionsCreated += testCount;
|
|
10520
|
-
logger$
|
|
10644
|
+
logger$12.info({
|
|
10521
10645
|
decisionsCreated: result.decisionsCreated,
|
|
10522
10646
|
skippedCategories: result.skippedCategories
|
|
10523
10647
|
}, "Methodology context seeding complete");
|
|
10524
10648
|
} catch (err) {
|
|
10525
|
-
logger$
|
|
10649
|
+
logger$12.warn({ error: err instanceof Error ? err.message : String(err) }, "Methodology context seeding failed (non-fatal)");
|
|
10526
10650
|
}
|
|
10527
10651
|
return result;
|
|
10528
10652
|
}
|
|
@@ -10566,7 +10690,7 @@ async function seedArchitecture(db, projectRoot) {
|
|
|
10566
10690
|
});
|
|
10567
10691
|
count = 1;
|
|
10568
10692
|
}
|
|
10569
|
-
logger$
|
|
10693
|
+
logger$12.debug({ count }, "Seeded architecture decisions");
|
|
10570
10694
|
return count;
|
|
10571
10695
|
}
|
|
10572
10696
|
/**
|
|
@@ -10590,11 +10714,11 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10590
10714
|
const storedHashDecision = implementationDecisions.find((d) => d.category === "epic-shard-hash" && d.key === "epics-file");
|
|
10591
10715
|
const storedHash = storedHashDecision?.value;
|
|
10592
10716
|
if (storedHash === currentHash) {
|
|
10593
|
-
logger$
|
|
10717
|
+
logger$12.debug({ hash: currentHash }, "Epic shards up-to-date (hash unchanged) — skipping re-seed");
|
|
10594
10718
|
return -1;
|
|
10595
10719
|
}
|
|
10596
10720
|
if (implementationDecisions.some((d) => d.category === "epic-shard")) {
|
|
10597
|
-
logger$
|
|
10721
|
+
logger$12.debug({
|
|
10598
10722
|
storedHash,
|
|
10599
10723
|
currentHash
|
|
10600
10724
|
}, "Epics file changed — deleting stale epic-shard decisions");
|
|
@@ -10606,7 +10730,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10606
10730
|
for (const shard of shards) {
|
|
10607
10731
|
const subsections = parseStorySubsections(shard.epicId, shard.content);
|
|
10608
10732
|
for (const subsection of subsections) {
|
|
10609
|
-
if (subsection.content.length > MAX_EPIC_SHARD_CHARS) logger$
|
|
10733
|
+
if (subsection.content.length > MAX_EPIC_SHARD_CHARS) logger$12.warn({
|
|
10610
10734
|
epicId: shard.epicId,
|
|
10611
10735
|
storyKey: subsection.key,
|
|
10612
10736
|
originalLength: subsection.content.length,
|
|
@@ -10614,7 +10738,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10614
10738
|
droppedChars: subsection.content.length - MAX_EPIC_SHARD_CHARS
|
|
10615
10739
|
}, `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.`);
|
|
10616
10740
|
if (seenKeys.has(subsection.key)) {
|
|
10617
|
-
logger$
|
|
10741
|
+
logger$12.warn({
|
|
10618
10742
|
epicId: shard.epicId,
|
|
10619
10743
|
storyKey: subsection.key,
|
|
10620
10744
|
droppedContentLength: subsection.content.length
|
|
@@ -10642,7 +10766,7 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
10642
10766
|
value: currentHash,
|
|
10643
10767
|
rationale: "SHA-256 hash of epics file content for change detection"
|
|
10644
10768
|
});
|
|
10645
|
-
logger$
|
|
10769
|
+
logger$12.debug({
|
|
10646
10770
|
count,
|
|
10647
10771
|
hash: currentHash
|
|
10648
10772
|
}, "Seeded epic shard decisions");
|
|
@@ -10666,7 +10790,7 @@ async function seedTestPatterns(db, projectRoot) {
|
|
|
10666
10790
|
value: patterns.slice(0, MAX_TEST_PATTERNS_CHARS),
|
|
10667
10791
|
rationale: "Detected from project configuration at orchestrator startup"
|
|
10668
10792
|
});
|
|
10669
|
-
logger$
|
|
10793
|
+
logger$12.debug("Seeded test patterns decision");
|
|
10670
10794
|
return 1;
|
|
10671
10795
|
}
|
|
10672
10796
|
/**
|
|
@@ -11156,7 +11280,7 @@ function findArtifact(projectRoot, candidates) {
|
|
|
11156
11280
|
|
|
11157
11281
|
//#endregion
|
|
11158
11282
|
//#region src/modules/implementation-orchestrator/package-snapshot.ts
|
|
11159
|
-
const logger$
|
|
11283
|
+
const logger$11 = createLogger("package-snapshot");
|
|
11160
11284
|
/**
|
|
11161
11285
|
* Discover all package.json paths in a workspace monorepo.
|
|
11162
11286
|
* Checks the `workspaces` field in root package.json,
|
|
@@ -11248,7 +11372,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
11248
11372
|
writeFileSync(filePath, content, "utf-8");
|
|
11249
11373
|
filesRestored++;
|
|
11250
11374
|
} catch (err) {
|
|
11251
|
-
logger$
|
|
11375
|
+
logger$11.warn({
|
|
11252
11376
|
filePath,
|
|
11253
11377
|
err
|
|
11254
11378
|
}, "Failed to restore file from snapshot");
|
|
@@ -11259,7 +11383,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
11259
11383
|
encoding: "utf-8",
|
|
11260
11384
|
stdio: "pipe"
|
|
11261
11385
|
});
|
|
11262
|
-
logger$
|
|
11386
|
+
logger$11.info({
|
|
11263
11387
|
filesRestored,
|
|
11264
11388
|
installCommand: snapshot.installCommand
|
|
11265
11389
|
}, "Package snapshot restored successfully");
|
|
@@ -11270,7 +11394,7 @@ function restorePackageSnapshot(snapshot, options) {
|
|
|
11270
11394
|
};
|
|
11271
11395
|
} catch (err) {
|
|
11272
11396
|
const exitCode = err.status ?? 1;
|
|
11273
|
-
logger$
|
|
11397
|
+
logger$11.warn({
|
|
11274
11398
|
filesRestored,
|
|
11275
11399
|
exitCode,
|
|
11276
11400
|
err
|
|
@@ -11619,7 +11743,7 @@ const RecommendationSchema = z.object({
|
|
|
11619
11743
|
|
|
11620
11744
|
//#endregion
|
|
11621
11745
|
//#region src/modules/telemetry/adapter-persistence.ts
|
|
11622
|
-
const logger$
|
|
11746
|
+
const logger$10 = createLogger("telemetry:adapter-persistence");
|
|
11623
11747
|
/**
|
|
11624
11748
|
* Concrete DatabaseAdapter-backed telemetry persistence.
|
|
11625
11749
|
*
|
|
@@ -11673,7 +11797,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11673
11797
|
]);
|
|
11674
11798
|
}
|
|
11675
11799
|
});
|
|
11676
|
-
logger$
|
|
11800
|
+
logger$10.debug({
|
|
11677
11801
|
storyKey,
|
|
11678
11802
|
count: turns.length
|
|
11679
11803
|
}, "Stored turn analysis");
|
|
@@ -11745,7 +11869,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11745
11869
|
score.taskType ?? null,
|
|
11746
11870
|
score.phase ?? null
|
|
11747
11871
|
]);
|
|
11748
|
-
logger$
|
|
11872
|
+
logger$10.debug({
|
|
11749
11873
|
storyKey: score.storyKey,
|
|
11750
11874
|
compositeScore: score.compositeScore
|
|
11751
11875
|
}, "Stored efficiency score");
|
|
@@ -11813,7 +11937,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11813
11937
|
]);
|
|
11814
11938
|
}
|
|
11815
11939
|
});
|
|
11816
|
-
logger$
|
|
11940
|
+
logger$10.debug({
|
|
11817
11941
|
storyKey,
|
|
11818
11942
|
count: recs.length
|
|
11819
11943
|
}, "Saved recommendations");
|
|
@@ -11890,7 +12014,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11890
12014
|
stat$2.trend
|
|
11891
12015
|
]);
|
|
11892
12016
|
});
|
|
11893
|
-
logger$
|
|
12017
|
+
logger$10.debug({
|
|
11894
12018
|
storyKey,
|
|
11895
12019
|
count: stats.length
|
|
11896
12020
|
}, "Stored category stats");
|
|
@@ -11933,7 +12057,7 @@ var AdapterTelemetryPersistence = class {
|
|
|
11933
12057
|
JSON.stringify(consumer.topInvocations)
|
|
11934
12058
|
]);
|
|
11935
12059
|
});
|
|
11936
|
-
logger$
|
|
12060
|
+
logger$10.debug({
|
|
11937
12061
|
storyKey,
|
|
11938
12062
|
count: consumers.length
|
|
11939
12063
|
}, "Stored consumer stats");
|
|
@@ -11965,14 +12089,14 @@ var AdapterTelemetryPersistence = class {
|
|
|
11965
12089
|
await adapter.query("DELETE FROM category_stats WHERE story_key = ?", [storyKey]);
|
|
11966
12090
|
await adapter.query("DELETE FROM consumer_stats WHERE story_key = ?", [storyKey]);
|
|
11967
12091
|
});
|
|
11968
|
-
logger$
|
|
12092
|
+
logger$10.debug({ storyKey }, "Purged stale telemetry data for story");
|
|
11969
12093
|
}
|
|
11970
12094
|
/**
|
|
11971
12095
|
* Record a named span with arbitrary attributes.
|
|
11972
12096
|
* Currently logs the span at debug level; no DB persistence.
|
|
11973
12097
|
*/
|
|
11974
12098
|
recordSpan(span) {
|
|
11975
|
-
logger$
|
|
12099
|
+
logger$10.debug({ span }, "recordSpan");
|
|
11976
12100
|
}
|
|
11977
12101
|
};
|
|
11978
12102
|
|
|
@@ -12047,7 +12171,7 @@ var TelemetryPersistence = class {
|
|
|
12047
12171
|
|
|
12048
12172
|
//#endregion
|
|
12049
12173
|
//#region src/modules/telemetry/telemetry-advisor.ts
|
|
12050
|
-
const logger$
|
|
12174
|
+
const logger$9 = createLogger("telemetry-advisor");
|
|
12051
12175
|
/**
|
|
12052
12176
|
* Reads telemetry efficiency data to support retry gate decisions.
|
|
12053
12177
|
*/
|
|
@@ -12069,7 +12193,7 @@ var TelemetryAdvisor = class {
|
|
|
12069
12193
|
try {
|
|
12070
12194
|
const score = await this._persistence.getEfficiencyScore(storyKey);
|
|
12071
12195
|
if (score === null) {
|
|
12072
|
-
logger$
|
|
12196
|
+
logger$9.debug({ storyKey }, "No efficiency score found for story");
|
|
12073
12197
|
return null;
|
|
12074
12198
|
}
|
|
12075
12199
|
return {
|
|
@@ -12084,7 +12208,7 @@ var TelemetryAdvisor = class {
|
|
|
12084
12208
|
coldStartTurnsExcluded: score.coldStartTurnsExcluded ?? 0
|
|
12085
12209
|
};
|
|
12086
12210
|
} catch (err) {
|
|
12087
|
-
logger$
|
|
12211
|
+
logger$9.warn({
|
|
12088
12212
|
err,
|
|
12089
12213
|
storyKey
|
|
12090
12214
|
}, "Failed to retrieve efficiency score");
|
|
@@ -12121,7 +12245,7 @@ var TelemetryAdvisor = class {
|
|
|
12121
12245
|
merged.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));
|
|
12122
12246
|
return merged;
|
|
12123
12247
|
} catch (err) {
|
|
12124
|
-
logger$
|
|
12248
|
+
logger$9.warn({ err }, "Failed to retrieve recommendations for run — returning empty");
|
|
12125
12249
|
return [];
|
|
12126
12250
|
}
|
|
12127
12251
|
}
|
|
@@ -12151,7 +12275,7 @@ var TelemetryAdvisor = class {
|
|
|
12151
12275
|
const lines = actionable.map((r) => `OPTIMIZATION (${r.severity}): ${r.title}. ${r.description}`);
|
|
12152
12276
|
const full = lines.join("\n");
|
|
12153
12277
|
if (full.length <= MAX_CHARS$1) {
|
|
12154
|
-
logger$
|
|
12278
|
+
logger$9.debug({
|
|
12155
12279
|
count: actionable.length,
|
|
12156
12280
|
chars: full.length
|
|
12157
12281
|
}, "Formatting optimization directives");
|
|
@@ -12159,7 +12283,7 @@ var TelemetryAdvisor = class {
|
|
|
12159
12283
|
}
|
|
12160
12284
|
const cutAt = full.lastIndexOf(" ", MAX_CHARS$1);
|
|
12161
12285
|
const truncated = (cutAt > 0 ? full.slice(0, cutAt) : full.slice(0, MAX_CHARS$1)) + "…";
|
|
12162
|
-
logger$
|
|
12286
|
+
logger$9.debug({
|
|
12163
12287
|
count: actionable.length,
|
|
12164
12288
|
chars: truncated.length
|
|
12165
12289
|
}, "Optimization directives truncated to budget");
|
|
@@ -12173,6 +12297,171 @@ function createTelemetryAdvisor(deps) {
|
|
|
12173
12297
|
return new TelemetryAdvisor(deps);
|
|
12174
12298
|
}
|
|
12175
12299
|
|
|
12300
|
+
//#endregion
|
|
12301
|
+
//#region src/modules/compiled-workflows/acceptance-judge.ts
|
|
12302
|
+
const logger$8 = createLogger("compiled-workflows:acceptance-judge");
|
|
12303
|
+
/** Cap per-artifact content injected into the prompt (chars). */
|
|
12304
|
+
const ARTIFACT_CONTENT_CAP = 16e3;
|
|
12305
|
+
function renderEndStates(journey) {
|
|
12306
|
+
return journey.end_states.map((es) => `- id: ${es.id}\n given: ${es.given}\n walk: ${es.walk}\n then: ${es.then}`).join("\n");
|
|
12307
|
+
}
|
|
12308
|
+
async function renderArtifactContents(artifactsDir, artifacts) {
|
|
12309
|
+
const blocks = [];
|
|
12310
|
+
for (const rel of artifacts) {
|
|
12311
|
+
let content;
|
|
12312
|
+
try {
|
|
12313
|
+
content = await readFile$1(join$1(artifactsDir, rel), "utf-8");
|
|
12314
|
+
} catch {
|
|
12315
|
+
blocks.push(`--- ${rel} ---\n(unreadable or binary — judge from the other artifacts)`);
|
|
12316
|
+
continue;
|
|
12317
|
+
}
|
|
12318
|
+
const truncated = content.length > ARTIFACT_CONTENT_CAP;
|
|
12319
|
+
blocks.push(`--- ${rel}${truncated ? ` (truncated to first ${String(ARTIFACT_CONTENT_CAP)} chars)` : ""} ---\n` + content.slice(0, ARTIFACT_CONTENT_CAP));
|
|
12320
|
+
}
|
|
12321
|
+
return blocks.join("\n\n");
|
|
12322
|
+
}
|
|
12323
|
+
/** Validate verdict completeness: every end-state exactly once, no unknown ids. */
|
|
12324
|
+
function validateVerdictCoverage(journey, verdicts) {
|
|
12325
|
+
const expected = new Set(journey.end_states.map((es) => es.id));
|
|
12326
|
+
const seen = new Set();
|
|
12327
|
+
for (const v of verdicts) {
|
|
12328
|
+
if (!expected.has(v.end_state_id)) return `verdict for unknown end-state id "${v.end_state_id}"`;
|
|
12329
|
+
if (seen.has(v.end_state_id)) return `duplicate verdict for end-state "${v.end_state_id}"`;
|
|
12330
|
+
seen.add(v.end_state_id);
|
|
12331
|
+
}
|
|
12332
|
+
const missing = [...expected].filter((id) => !seen.has(id));
|
|
12333
|
+
if (missing.length > 0) return `missing verdict(s) for end-state(s): ${missing.join(", ")}`;
|
|
12334
|
+
return void 0;
|
|
12335
|
+
}
|
|
12336
|
+
async function runAcceptanceJudge(deps, params) {
|
|
12337
|
+
const { journey, artifactsDir, artifacts, storyKey } = params;
|
|
12338
|
+
let template;
|
|
12339
|
+
try {
|
|
12340
|
+
template = await deps.pack.getPrompt("acceptance-judge");
|
|
12341
|
+
} catch (err) {
|
|
12342
|
+
return {
|
|
12343
|
+
result: "failed",
|
|
12344
|
+
error: `Failed to retrieve acceptance-judge prompt: ${err instanceof Error ? err.message : String(err)}`,
|
|
12345
|
+
tokenUsage: {
|
|
12346
|
+
input: 0,
|
|
12347
|
+
output: 0
|
|
12348
|
+
}
|
|
12349
|
+
};
|
|
12350
|
+
}
|
|
12351
|
+
const artifactContents = await renderArtifactContents(artifactsDir, artifacts);
|
|
12352
|
+
const buildPrompt = (correctivePreamble) => {
|
|
12353
|
+
const { prompt } = assemblePrompt(template, [
|
|
12354
|
+
{
|
|
12355
|
+
name: "journey_id",
|
|
12356
|
+
content: journey.id,
|
|
12357
|
+
priority: "required"
|
|
12358
|
+
},
|
|
12359
|
+
{
|
|
12360
|
+
name: "journey_title",
|
|
12361
|
+
content: journey.title,
|
|
12362
|
+
priority: "required"
|
|
12363
|
+
},
|
|
12364
|
+
{
|
|
12365
|
+
name: "end_states",
|
|
12366
|
+
content: renderEndStates(journey),
|
|
12367
|
+
priority: "required"
|
|
12368
|
+
},
|
|
12369
|
+
{
|
|
12370
|
+
name: "artifact_manifest",
|
|
12371
|
+
content: artifacts.length > 0 ? artifacts.map((a) => `- ${a}`).join("\n") : "(no artifacts)",
|
|
12372
|
+
priority: "required"
|
|
12373
|
+
},
|
|
12374
|
+
{
|
|
12375
|
+
name: "artifact_contents",
|
|
12376
|
+
content: artifactContents,
|
|
12377
|
+
priority: "required"
|
|
12378
|
+
}
|
|
12379
|
+
], getTokenCeiling("acceptance-judge", deps.tokenCeilings).ceiling);
|
|
12380
|
+
return correctivePreamble !== void 0 ? `${correctivePreamble}\n\n${prompt}` : prompt;
|
|
12381
|
+
};
|
|
12382
|
+
let totalTokens = {
|
|
12383
|
+
input: 0,
|
|
12384
|
+
output: 0
|
|
12385
|
+
};
|
|
12386
|
+
let lastProblem = "unknown";
|
|
12387
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
12388
|
+
const prompt = attempt === 0 ? buildPrompt() : buildPrompt(`PREVIOUS ATTEMPT REJECTED: ${lastProblem}. Emit ONLY the YAML block per the Output Contract — every end-state exactly once, every verdict with evidence {artifact, excerpt}.`);
|
|
12389
|
+
const handle = deps.dispatcher.dispatch({
|
|
12390
|
+
prompt,
|
|
12391
|
+
agent: deps.agentId ?? "claude-code",
|
|
12392
|
+
taskType: "acceptance-judge",
|
|
12393
|
+
outputSchema: AcceptanceJudgeResultSchema,
|
|
12394
|
+
maxTurns: 20,
|
|
12395
|
+
workingDirectory: artifactsDir,
|
|
12396
|
+
...deps.otlpEndpoint !== void 0 ? { otlpEndpoint: deps.otlpEndpoint } : {},
|
|
12397
|
+
...storyKey !== void 0 ? { storyKey } : {}
|
|
12398
|
+
});
|
|
12399
|
+
let dispatchResult;
|
|
12400
|
+
try {
|
|
12401
|
+
dispatchResult = await handle.result;
|
|
12402
|
+
} catch (err) {
|
|
12403
|
+
return {
|
|
12404
|
+
result: "failed",
|
|
12405
|
+
error: `Dispatch error: ${err instanceof Error ? err.message : String(err)}`,
|
|
12406
|
+
tokenUsage: totalTokens
|
|
12407
|
+
};
|
|
12408
|
+
}
|
|
12409
|
+
totalTokens = {
|
|
12410
|
+
input: totalTokens.input + dispatchResult.tokenEstimate.input,
|
|
12411
|
+
output: totalTokens.output + dispatchResult.tokenEstimate.output
|
|
12412
|
+
};
|
|
12413
|
+
if (dispatchResult.status === "failed" || dispatchResult.status === "timeout") return {
|
|
12414
|
+
result: "failed",
|
|
12415
|
+
error: `Dispatch status: ${dispatchResult.status}. ${dispatchResult.parseError ?? ""}`.trim(),
|
|
12416
|
+
tokenUsage: totalTokens
|
|
12417
|
+
};
|
|
12418
|
+
const parsed = AcceptanceJudgeResultSchema.safeParse(dispatchResult.parsed);
|
|
12419
|
+
if (!parsed.success) {
|
|
12420
|
+
lastProblem = `output failed schema validation (${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 500)})`;
|
|
12421
|
+
logger$8.warn({
|
|
12422
|
+
journeyId: journey.id,
|
|
12423
|
+
storyKey,
|
|
12424
|
+
attempt,
|
|
12425
|
+
lastProblem
|
|
12426
|
+
}, "A2.1: judge output invalid");
|
|
12427
|
+
continue;
|
|
12428
|
+
}
|
|
12429
|
+
if (parsed.data.result === "failed") return {
|
|
12430
|
+
result: "failed",
|
|
12431
|
+
error: "acceptance-judge-refused",
|
|
12432
|
+
details: parsed.data.error ?? "judge reported failure without a reason",
|
|
12433
|
+
tokenUsage: totalTokens
|
|
12434
|
+
};
|
|
12435
|
+
const coverageProblem = validateVerdictCoverage(journey, parsed.data.verdicts);
|
|
12436
|
+
if (coverageProblem !== void 0) {
|
|
12437
|
+
lastProblem = coverageProblem;
|
|
12438
|
+
logger$8.warn({
|
|
12439
|
+
journeyId: journey.id,
|
|
12440
|
+
storyKey,
|
|
12441
|
+
attempt,
|
|
12442
|
+
coverageProblem
|
|
12443
|
+
}, "A2.1: judge verdicts incomplete");
|
|
12444
|
+
continue;
|
|
12445
|
+
}
|
|
12446
|
+
logger$8.info({
|
|
12447
|
+
journeyId: journey.id,
|
|
12448
|
+
storyKey,
|
|
12449
|
+
verdicts: parsed.data.verdicts.map((v) => `${v.end_state_id}=${v.verdict}`)
|
|
12450
|
+
}, "A2.1: acceptance judge verdicts accepted");
|
|
12451
|
+
return {
|
|
12452
|
+
result: "success",
|
|
12453
|
+
verdicts: parsed.data.verdicts,
|
|
12454
|
+
tokenUsage: totalTokens
|
|
12455
|
+
};
|
|
12456
|
+
}
|
|
12457
|
+
return {
|
|
12458
|
+
result: "failed",
|
|
12459
|
+
error: "acceptance-judge-invalid",
|
|
12460
|
+
details: `judge produced invalid output twice — last problem: ${lastProblem}`,
|
|
12461
|
+
tokenUsage: totalTokens
|
|
12462
|
+
};
|
|
12463
|
+
}
|
|
12464
|
+
|
|
12176
12465
|
//#endregion
|
|
12177
12466
|
//#region src/modules/implementation-orchestrator/verification-integration.ts
|
|
12178
12467
|
const _logger = createLogger("verification-integration");
|
|
@@ -13478,7 +13767,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13478
13767
|
projectRoot,
|
|
13479
13768
|
...config.worktreeCopyFiles !== void 0 ? { copyFiles: config.worktreeCopyFiles } : {}
|
|
13480
13769
|
}) : void 0);
|
|
13481
|
-
const logger$
|
|
13770
|
+
const logger$28 = createLogger("implementation-orchestrator");
|
|
13482
13771
|
const telemetryAdvisor = db !== void 0 ? createTelemetryAdvisor({ db }) : void 0;
|
|
13483
13772
|
const wgRepo = new WorkGraphRepository(db);
|
|
13484
13773
|
const _wgInProgressWritten = new Set();
|
|
@@ -13585,7 +13874,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13585
13874
|
const existingCount = storyState?.retry_count ?? 0;
|
|
13586
13875
|
_storyRetryCount.set(storyKey, existingCount);
|
|
13587
13876
|
} catch (err) {
|
|
13588
|
-
logger$
|
|
13877
|
+
logger$28.warn({
|
|
13589
13878
|
err,
|
|
13590
13879
|
storyKey
|
|
13591
13880
|
}, "initRetryCount: failed to read manifest — starting at 0");
|
|
@@ -13599,7 +13888,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13599
13888
|
const current = _storyRetryCount.get(storyKey) ?? 0;
|
|
13600
13889
|
const next = current + 1;
|
|
13601
13890
|
_storyRetryCount.set(storyKey, next);
|
|
13602
|
-
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$
|
|
13891
|
+
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$28.warn({
|
|
13603
13892
|
err,
|
|
13604
13893
|
storyKey
|
|
13605
13894
|
}, "patchStoryState(retry_count) failed — pipeline continues"));
|
|
@@ -13612,7 +13901,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13612
13901
|
const nowMs = Date.now();
|
|
13613
13902
|
for (const [phase, startMs] of starts) {
|
|
13614
13903
|
const endMs = ends?.get(phase);
|
|
13615
|
-
if (endMs === void 0) logger$
|
|
13904
|
+
if (endMs === void 0) logger$28.warn({
|
|
13616
13905
|
storyKey,
|
|
13617
13906
|
phase
|
|
13618
13907
|
}, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
|
|
@@ -13629,7 +13918,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13629
13918
|
const wallClockSeconds = startedAt ? Math.round((new Date(completedAt).getTime() - new Date(startedAt).getTime()) / 1e3) : 0;
|
|
13630
13919
|
const wallClockMs = startedAt ? new Date(completedAt).getTime() - new Date(startedAt).getTime() : 0;
|
|
13631
13920
|
const tokenAgg = await aggregateTokenUsageForStory(db, config.pipelineRunId, storyKey);
|
|
13632
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$
|
|
13921
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$28.warn({
|
|
13633
13922
|
err,
|
|
13634
13923
|
storyKey
|
|
13635
13924
|
}, "patchStoryState(cost_usd) failed — pipeline continues"));
|
|
@@ -13668,7 +13957,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13668
13957
|
rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
|
|
13669
13958
|
});
|
|
13670
13959
|
} catch (decisionErr) {
|
|
13671
|
-
logger$
|
|
13960
|
+
logger$28.warn({
|
|
13672
13961
|
err: decisionErr,
|
|
13673
13962
|
storyKey
|
|
13674
13963
|
}, "Failed to write story-metrics decision (best-effort)");
|
|
@@ -13747,7 +14036,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13747
14036
|
const LOW_OUTPUT_TOKEN_THRESHOLD = 100;
|
|
13748
14037
|
const unverified = tokenAgg.output < LOW_OUTPUT_TOKEN_THRESHOLD;
|
|
13749
14038
|
if (unverified) {
|
|
13750
|
-
logger$
|
|
14039
|
+
logger$28.warn({
|
|
13751
14040
|
storyKey,
|
|
13752
14041
|
outputTokens: tokenAgg.output,
|
|
13753
14042
|
threshold: LOW_OUTPUT_TOKEN_THRESHOLD
|
|
@@ -13771,13 +14060,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
13771
14060
|
...unverified ? { unverified: true } : {}
|
|
13772
14061
|
});
|
|
13773
14062
|
} catch (emitErr) {
|
|
13774
|
-
logger$
|
|
14063
|
+
logger$28.warn({
|
|
13775
14064
|
err: emitErr,
|
|
13776
14065
|
storyKey
|
|
13777
14066
|
}, "Failed to emit story:metrics event (best-effort)");
|
|
13778
14067
|
}
|
|
13779
14068
|
} catch (err) {
|
|
13780
|
-
logger$
|
|
14069
|
+
logger$28.warn({
|
|
13781
14070
|
err,
|
|
13782
14071
|
storyKey
|
|
13783
14072
|
}, "Failed to write story metrics (best-effort)");
|
|
@@ -13806,7 +14095,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13806
14095
|
rationale: `Story ${storyKey} ${outcome} after ${reviewCycles} review cycle(s).`
|
|
13807
14096
|
});
|
|
13808
14097
|
} catch (err) {
|
|
13809
|
-
logger$
|
|
14098
|
+
logger$28.warn({
|
|
13810
14099
|
err,
|
|
13811
14100
|
storyKey
|
|
13812
14101
|
}, "Failed to write story-outcome decision (best-effort)");
|
|
@@ -13821,15 +14110,15 @@ function createImplementationOrchestrator(deps) {
|
|
|
13821
14110
|
if (escalationWorktree !== void 0) {
|
|
13822
14111
|
const cp = await checkpointStoryWorktree(payload.storyKey, `escalation: ${payload.escalationReason ?? payload.lastVerdict}`, escalationWorktree);
|
|
13823
14112
|
if (cp.status === "committed") {
|
|
13824
|
-
logger$
|
|
14113
|
+
logger$28.info({
|
|
13825
14114
|
storyKey: payload.storyKey,
|
|
13826
14115
|
sha: cp.sha
|
|
13827
14116
|
}, "escalation checkpoint: uncommitted worktree state preserved on story branch");
|
|
13828
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(payload.storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
14117
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(payload.storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$28.warn({
|
|
13829
14118
|
err,
|
|
13830
14119
|
storyKey: payload.storyKey
|
|
13831
14120
|
}, "patchStoryState(checkpoint_sha, escalation) failed — pipeline continues"));
|
|
13832
|
-
} else if (cp.status === "failed") logger$
|
|
14121
|
+
} else if (cp.status === "failed") logger$28.warn({
|
|
13833
14122
|
storyKey: payload.storyKey,
|
|
13834
14123
|
stderr: cp.stderr.slice(0, 500)
|
|
13835
14124
|
}, "escalation checkpoint failed — worktree state remains uncommitted (inspect before any cleanup)");
|
|
@@ -13843,7 +14132,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13843
14132
|
storyKey: payload.storyKey,
|
|
13844
14133
|
msg: leakMsg
|
|
13845
14134
|
});
|
|
13846
|
-
logger$
|
|
14135
|
+
logger$28.warn({
|
|
13847
14136
|
storyKey: payload.storyKey,
|
|
13848
14137
|
leakedFileCount: leakedFiles.length
|
|
13849
14138
|
}, "escalation parent-tree leak detected");
|
|
@@ -13860,7 +14149,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13860
14149
|
runManifest.patchStoryState(payload.storyKey, {
|
|
13861
14150
|
escalation_reason: escalationReason,
|
|
13862
14151
|
...escalationDetail !== void 0 ? { escalation_detail: escalationDetail } : {}
|
|
13863
|
-
}).catch((err) => logger$
|
|
14152
|
+
}).catch((err) => logger$28.warn({
|
|
13864
14153
|
err,
|
|
13865
14154
|
storyKey: payload.storyKey
|
|
13866
14155
|
}, "patchStoryState(escalation_reason/detail) failed — pipeline continues"));
|
|
@@ -13887,7 +14176,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13887
14176
|
rationale: `Escalation diagnosis for ${payload.storyKey}: ${diagnosis.recommendedAction} — ${diagnosis.rationale}`
|
|
13888
14177
|
});
|
|
13889
14178
|
} catch (err) {
|
|
13890
|
-
logger$
|
|
14179
|
+
logger$28.warn({
|
|
13891
14180
|
err,
|
|
13892
14181
|
storyKey: payload.storyKey
|
|
13893
14182
|
}, "Failed to persist escalation diagnosis (best-effort)");
|
|
@@ -13936,7 +14225,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13936
14225
|
...updates
|
|
13937
14226
|
};
|
|
13938
14227
|
const opts = targetStatus === "complete" || targetStatus === "escalated" ? { completedAt: fullUpdated.completedAt } : void 0;
|
|
13939
|
-
wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$
|
|
14228
|
+
wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$28.warn({
|
|
13940
14229
|
err,
|
|
13941
14230
|
storyKey
|
|
13942
14231
|
}, "wg_stories status update failed (best-effort)"));
|
|
@@ -13952,7 +14241,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13952
14241
|
status: "dispatched",
|
|
13953
14242
|
phase: String(updates.phase),
|
|
13954
14243
|
started_at: fullUpdated.startedAt ?? new Date().toISOString()
|
|
13955
|
-
}).catch((err) => logger$
|
|
14244
|
+
}).catch((err) => logger$28.warn({
|
|
13956
14245
|
err,
|
|
13957
14246
|
storyKey
|
|
13958
14247
|
}, "patchStoryState(dispatched) failed — pipeline continues"));
|
|
@@ -13964,13 +14253,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
13964
14253
|
completed_at: fullUpdated.completedAt ?? new Date().toISOString(),
|
|
13965
14254
|
review_cycles: fullUpdated.reviewCycles ?? 0,
|
|
13966
14255
|
dispatches: _storyDispatches.get(storyKey) ?? 0
|
|
13967
|
-
}).catch((err) => logger$
|
|
14256
|
+
}).catch((err) => logger$28.warn({
|
|
13968
14257
|
err,
|
|
13969
14258
|
storyKey
|
|
13970
14259
|
}, `patchStoryState(${manifestStatus}) failed — pipeline continues`));
|
|
13971
14260
|
} else {
|
|
13972
14261
|
const intermediatePhase = updates.phase;
|
|
13973
|
-
runManifest.patchStoryState(storyKey, { phase: String(intermediatePhase) }).catch((err) => logger$
|
|
14262
|
+
runManifest.patchStoryState(storyKey, { phase: String(intermediatePhase) }).catch((err) => logger$28.warn({
|
|
13974
14263
|
err,
|
|
13975
14264
|
storyKey,
|
|
13976
14265
|
phase: intermediatePhase
|
|
@@ -13989,13 +14278,111 @@ function createImplementationOrchestrator(deps) {
|
|
|
13989
14278
|
token_usage_json: serialized
|
|
13990
14279
|
});
|
|
13991
14280
|
} catch (err) {
|
|
13992
|
-
logger$
|
|
14281
|
+
logger$28.warn({ err }, "Failed to persist orchestrator state");
|
|
13993
14282
|
}
|
|
13994
14283
|
}
|
|
13995
14284
|
function recordProgress() {
|
|
13996
14285
|
_lastProgressTs = Date.now();
|
|
13997
14286
|
_stalledStories.clear();
|
|
13998
14287
|
}
|
|
14288
|
+
const _journeyVerdicts = new Map();
|
|
14289
|
+
/** External artifacts base: ~/.substrate/acceptance/<name>-<hash8>/<run>/ (H4.2 symmetry). */
|
|
14290
|
+
function acceptanceArtifactsBase() {
|
|
14291
|
+
const root = projectRoot ?? process.cwd();
|
|
14292
|
+
const hash = createHash("sha256").update(resolve$1(root)).digest("hex").slice(0, 8);
|
|
14293
|
+
return join$1(homedir(), ".substrate", "acceptance", `${basename$1(root)}-${hash}`, config.pipelineRunId ?? "adhoc");
|
|
14294
|
+
}
|
|
14295
|
+
async function runAcceptanceStage(storyKey, worktreeDir) {
|
|
14296
|
+
const mode = config.acceptanceMode ?? "advisory";
|
|
14297
|
+
if (mode === "off" || projectRoot === void 0) return;
|
|
14298
|
+
const journeyIds = _stories.get(storyKey)?.journeys ?? [];
|
|
14299
|
+
if (journeyIds.length === 0) return;
|
|
14300
|
+
const registryLoad = await loadJourneyRegistryFromTrustedTree(projectRoot);
|
|
14301
|
+
if (registryLoad.status !== "ok") return;
|
|
14302
|
+
const contractLoad = await loadAcceptanceContractFromTrustedTree(projectRoot);
|
|
14303
|
+
if (contractLoad.status !== "ok") {
|
|
14304
|
+
logger$28.warn({
|
|
14305
|
+
storyKey,
|
|
14306
|
+
status: contractLoad.status
|
|
14307
|
+
}, "A2.3: no usable acceptance contract — claimed journeys stay unwalked (acceptance-unrunnable at audit)");
|
|
14308
|
+
return;
|
|
14309
|
+
}
|
|
14310
|
+
const contract = contractLoad.contract;
|
|
14311
|
+
eventBus.emit("orchestrator:acceptance-started", {
|
|
14312
|
+
storyKey,
|
|
14313
|
+
journeys: journeyIds
|
|
14314
|
+
});
|
|
14315
|
+
for (const journeyId of journeyIds) {
|
|
14316
|
+
const journey = registryLoad.registry.journeys.find((j$1) => j$1.id === journeyId);
|
|
14317
|
+
if (journey === void 0) continue;
|
|
14318
|
+
const journeyDir = join$1(acceptanceArtifactsBase(), storyKey, journeyId);
|
|
14319
|
+
const artifacts = [];
|
|
14320
|
+
let renderFailed = false;
|
|
14321
|
+
for (const surface of journey.surfaces) {
|
|
14322
|
+
if (surface === "web") continue;
|
|
14323
|
+
const res = await renderSurface({
|
|
14324
|
+
surface,
|
|
14325
|
+
contract,
|
|
14326
|
+
workingDirectory: worktreeDir,
|
|
14327
|
+
artifactsDir: join$1(journeyDir, surface)
|
|
14328
|
+
});
|
|
14329
|
+
eventBus.emit("orchestrator:acceptance-rendered", {
|
|
14330
|
+
storyKey,
|
|
14331
|
+
surface,
|
|
14332
|
+
status: res.status,
|
|
14333
|
+
artifactsDir: res.artifactsDir,
|
|
14334
|
+
artifacts: res.artifacts,
|
|
14335
|
+
...res.error !== void 0 ? { error: res.error } : {}
|
|
14336
|
+
});
|
|
14337
|
+
if (res.status === "failed") {
|
|
14338
|
+
renderFailed = true;
|
|
14339
|
+
logger$28.warn({
|
|
14340
|
+
storyKey,
|
|
14341
|
+
journeyId,
|
|
14342
|
+
surface,
|
|
14343
|
+
error: res.error,
|
|
14344
|
+
exitCode: res.exitCode,
|
|
14345
|
+
stderrTail: res.stderrTail?.slice(0, 500)
|
|
14346
|
+
}, "A2.3: surface render failed — journey stays unwalked");
|
|
14347
|
+
} else artifacts.push(...res.artifacts.map((a) => join$1(surface, a)));
|
|
14348
|
+
}
|
|
14349
|
+
if (renderFailed || artifacts.length === 0) continue;
|
|
14350
|
+
const judge = await runAcceptanceJudge({
|
|
14351
|
+
db,
|
|
14352
|
+
pack,
|
|
14353
|
+
contextCompiler,
|
|
14354
|
+
dispatcher,
|
|
14355
|
+
projectRoot: journeyDir,
|
|
14356
|
+
parentProjectRoot: projectRoot,
|
|
14357
|
+
tokenCeilings,
|
|
14358
|
+
otlpEndpoint: _otlpEndpoint,
|
|
14359
|
+
agentId
|
|
14360
|
+
}, {
|
|
14361
|
+
journey,
|
|
14362
|
+
artifactsDir: journeyDir,
|
|
14363
|
+
artifacts,
|
|
14364
|
+
storyKey
|
|
14365
|
+
});
|
|
14366
|
+
if (judge.result === "success" && judge.verdicts !== void 0) {
|
|
14367
|
+
_journeyVerdicts.set(journeyId, judge.verdicts);
|
|
14368
|
+
eventBus.emit("orchestrator:acceptance-verdict", {
|
|
14369
|
+
storyKey,
|
|
14370
|
+
journeyId,
|
|
14371
|
+
verdicts: judge.verdicts.map((v) => ({
|
|
14372
|
+
end_state_id: v.end_state_id,
|
|
14373
|
+
verdict: v.verdict,
|
|
14374
|
+
artifact: v.evidence.artifact,
|
|
14375
|
+
excerpt: v.evidence.excerpt
|
|
14376
|
+
}))
|
|
14377
|
+
});
|
|
14378
|
+
} else logger$28.warn({
|
|
14379
|
+
storyKey,
|
|
14380
|
+
journeyId,
|
|
14381
|
+
error: judge.error,
|
|
14382
|
+
details: judge.details
|
|
14383
|
+
}, "A2.3: judge failed — journey stays unwalked");
|
|
14384
|
+
}
|
|
14385
|
+
}
|
|
13999
14386
|
async function auditJourneyCoverage(scope, opts) {
|
|
14000
14387
|
const mode = config.acceptanceMode ?? "advisory";
|
|
14001
14388
|
if (mode === "off" || projectRoot === void 0) return void 0;
|
|
@@ -14006,26 +14393,30 @@ function createImplementationOrchestrator(deps) {
|
|
|
14006
14393
|
unrunnable: "journey registry is INVALID: " + registryLoad.issues.map((i) => `${i.path}: ${i.message}`).join("; ") + " — fix it (substrate acceptance validate) or the audit cannot run"
|
|
14007
14394
|
};
|
|
14008
14395
|
if (registryLoad.status !== "ok") {
|
|
14009
|
-
logger$
|
|
14396
|
+
logger$28.warn({ detail: registryLoad.message }, "A0.3: journey registry read failed — coverage audit skipped (environmental)");
|
|
14010
14397
|
return void 0;
|
|
14011
14398
|
}
|
|
14012
14399
|
let unrunnable;
|
|
14013
14400
|
const contractLoad = await loadAcceptanceContractFromTrustedTree(projectRoot);
|
|
14014
14401
|
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.`;
|
|
14015
14402
|
else if (contractLoad.status === "invalid") unrunnable = "acceptance: contract block is INVALID: " + contractLoad.issues.map((i) => `${i.path}: ${i.message}`).join("; ");
|
|
14016
|
-
else if (contractLoad.status === "error") logger$
|
|
14403
|
+
else if (contractLoad.status === "error") logger$28.warn({ detail: contractLoad.message }, "A1.1: acceptance contract read failed (environmental) — treating as absent for this audit");
|
|
14017
14404
|
const deferralsLoad = await loadJourneyDeferralsFromTrustedTree(projectRoot);
|
|
14018
|
-
if (deferralsLoad.status !== "ok") logger$
|
|
14405
|
+
if (deferralsLoad.status !== "ok") logger$28.warn({ detail: deferralsLoad.status === "invalid" ? deferralsLoad.issues : deferralsLoad.message }, `A0.3: ${JOURNEY_DEFERRALS_PATH} unreadable/invalid — treating as no deferrals`);
|
|
14019
14406
|
const deferredJourneyIds = deferralsLoad.status === "ok" ? deferralsLoad.deferrals.map((d) => d.journey) : [];
|
|
14020
14407
|
const claims = [];
|
|
14021
14408
|
for (const [key, st] of _stories.entries()) for (const journeyId of st.journeys ?? []) claims.push({
|
|
14022
14409
|
journeyId,
|
|
14023
14410
|
storyKey: key
|
|
14024
14411
|
});
|
|
14412
|
+
const verdicts = [..._journeyVerdicts.entries()].map(([journeyId, vs]) => ({
|
|
14413
|
+
journeyId,
|
|
14414
|
+
verdict: vs.every((v) => v.verdict === "PASS") ? "pass" : "fail"
|
|
14415
|
+
}));
|
|
14025
14416
|
const entries = computeJourneyCoverage({
|
|
14026
14417
|
registry: registryLoad.registry,
|
|
14027
14418
|
claims,
|
|
14028
|
-
verdicts
|
|
14419
|
+
verdicts,
|
|
14029
14420
|
deferredJourneyIds,
|
|
14030
14421
|
scope
|
|
14031
14422
|
});
|
|
@@ -14036,8 +14427,46 @@ function createImplementationOrchestrator(deps) {
|
|
|
14036
14427
|
entries,
|
|
14037
14428
|
summary: summarizeCoverage(entries)
|
|
14038
14429
|
});
|
|
14039
|
-
if (unrunnable !== void 0) logger$
|
|
14040
|
-
if (opts?.persist === true
|
|
14430
|
+
if (unrunnable !== void 0) logger$28.warn({ scope: scopeLabel }, `A1.1: acceptance gate unrunnable — ${unrunnable}`);
|
|
14431
|
+
if (opts?.persist === true) {
|
|
14432
|
+
const entriesWithVerdicts = entries.map((e) => {
|
|
14433
|
+
const vs = _journeyVerdicts.get(e.journeyId);
|
|
14434
|
+
return vs !== void 0 ? {
|
|
14435
|
+
...e,
|
|
14436
|
+
verdicts: vs.map((v) => ({
|
|
14437
|
+
end_state_id: v.end_state_id,
|
|
14438
|
+
verdict: v.verdict,
|
|
14439
|
+
artifact: v.evidence.artifact,
|
|
14440
|
+
excerpt: v.evidence.excerpt
|
|
14441
|
+
}))
|
|
14442
|
+
} : e;
|
|
14443
|
+
});
|
|
14444
|
+
let reportPath;
|
|
14445
|
+
try {
|
|
14446
|
+
const html = renderVerdictHtml({
|
|
14447
|
+
scope: `${config.pipelineRunId ?? "run"} ${scopeLabel}`,
|
|
14448
|
+
generatedAt: new Date().toISOString(),
|
|
14449
|
+
journeys: entriesWithVerdicts.map((e) => ({
|
|
14450
|
+
journeyId: e.journeyId,
|
|
14451
|
+
title: e.title,
|
|
14452
|
+
criticality: e.criticality,
|
|
14453
|
+
state: e.state,
|
|
14454
|
+
ownerStories: e.ownerStories,
|
|
14455
|
+
verdicts: e.verdicts ?? []
|
|
14456
|
+
}))
|
|
14457
|
+
});
|
|
14458
|
+
reportPath = join$1(acceptanceArtifactsBase(), "acceptance-verdicts.html");
|
|
14459
|
+
mkdirSync(dirname$1(reportPath), { recursive: true });
|
|
14460
|
+
writeFileSync(reportPath, html, "utf-8");
|
|
14461
|
+
} catch (err) {
|
|
14462
|
+
logger$28.warn({ err }, "A2.2: verdict artifact write failed (best-effort)");
|
|
14463
|
+
reportPath = void 0;
|
|
14464
|
+
}
|
|
14465
|
+
if (runManifest !== null) await runManifest.update({
|
|
14466
|
+
journeys: entriesWithVerdicts,
|
|
14467
|
+
...reportPath !== void 0 ? { acceptance_report_path: reportPath } : {}
|
|
14468
|
+
}).catch((err) => logger$28.warn({ err }, "A0.3: manifest journeys ledger write failed — pipeline continues"));
|
|
14469
|
+
}
|
|
14041
14470
|
return unrunnable !== void 0 ? {
|
|
14042
14471
|
entries,
|
|
14043
14472
|
unrunnable
|
|
@@ -14084,7 +14513,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14084
14513
|
...Object.keys(perStoryState).length > 0 ? { perStoryState } : {}
|
|
14085
14514
|
});
|
|
14086
14515
|
if (config.pipelineRunId !== void 0) updatePipelineRun(db, config.pipelineRunId, { current_phase: "implementation" }).catch((err) => {
|
|
14087
|
-
logger$
|
|
14516
|
+
logger$28.debug({ err }, "Heartbeat: failed to touch updated_at (non-fatal)");
|
|
14088
14517
|
});
|
|
14089
14518
|
const elapsed = Date.now() - _lastProgressTs;
|
|
14090
14519
|
let childPids = [];
|
|
@@ -14106,7 +14535,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14106
14535
|
}
|
|
14107
14536
|
if (childActive) {
|
|
14108
14537
|
_lastProgressTs = Date.now();
|
|
14109
|
-
logger$
|
|
14538
|
+
logger$28.debug({
|
|
14110
14539
|
storyKey: key,
|
|
14111
14540
|
phase: s$1.phase,
|
|
14112
14541
|
childPids
|
|
@@ -14115,7 +14544,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14115
14544
|
}
|
|
14116
14545
|
_stalledStories.add(key);
|
|
14117
14546
|
_storiesWithStall.add(key);
|
|
14118
|
-
logger$
|
|
14547
|
+
logger$28.warn({
|
|
14119
14548
|
storyKey: key,
|
|
14120
14549
|
phase: s$1.phase,
|
|
14121
14550
|
elapsedMs: elapsed,
|
|
@@ -14160,7 +14589,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14160
14589
|
for (let attempt = 0; attempt < MEMORY_PRESSURE_BACKOFF_MS.length; attempt++) {
|
|
14161
14590
|
const memState = dispatcher.getMemoryState();
|
|
14162
14591
|
if (!memState.isPressured) return true;
|
|
14163
|
-
logger$
|
|
14592
|
+
logger$28.warn({
|
|
14164
14593
|
storyKey,
|
|
14165
14594
|
freeMB: memState.freeMB,
|
|
14166
14595
|
thresholdMB: memState.thresholdMB,
|
|
@@ -14180,12 +14609,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
14180
14609
|
* exhausted retries the story is ESCALATED.
|
|
14181
14610
|
*/
|
|
14182
14611
|
async function processStory(storyKey, storyOptions) {
|
|
14183
|
-
logger$
|
|
14612
|
+
logger$28.info({ storyKey }, "Processing story");
|
|
14184
14613
|
await initRetryCount(storyKey);
|
|
14185
14614
|
{
|
|
14186
14615
|
const memoryOk = await checkMemoryPressure(storyKey);
|
|
14187
14616
|
if (!memoryOk) {
|
|
14188
|
-
logger$
|
|
14617
|
+
logger$28.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
|
|
14189
14618
|
const memPressureState = {
|
|
14190
14619
|
phase: "ESCALATED",
|
|
14191
14620
|
reviewCycles: 0,
|
|
@@ -14229,7 +14658,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14229
14658
|
if (match$2) {
|
|
14230
14659
|
const candidatePath = join$1(artifactsDir, match$2);
|
|
14231
14660
|
const validation = await isValidStoryFile(candidatePath);
|
|
14232
|
-
if (!validation.valid) logger$
|
|
14661
|
+
if (!validation.valid) logger$28.warn({
|
|
14233
14662
|
storyKey,
|
|
14234
14663
|
storyFilePath: candidatePath,
|
|
14235
14664
|
reason: validation.reason
|
|
@@ -14254,7 +14683,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14254
14683
|
storedHash,
|
|
14255
14684
|
currentHash
|
|
14256
14685
|
});
|
|
14257
|
-
logger$
|
|
14686
|
+
logger$28.info({
|
|
14258
14687
|
storyKey,
|
|
14259
14688
|
storedHash,
|
|
14260
14689
|
currentHash
|
|
@@ -14265,7 +14694,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14265
14694
|
} catch {}
|
|
14266
14695
|
if (!isDrift) {
|
|
14267
14696
|
storyFilePath = candidatePath;
|
|
14268
|
-
logger$
|
|
14697
|
+
logger$28.info({
|
|
14269
14698
|
storyKey,
|
|
14270
14699
|
storyFilePath
|
|
14271
14700
|
}, "Found existing story file — skipping create-story");
|
|
@@ -14290,12 +14719,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
14290
14719
|
const staleName = match$2.replace(/\.md$/, `.stale-${ts}.md`);
|
|
14291
14720
|
const stalePath = join$1(artifactsDir, staleName);
|
|
14292
14721
|
renameSync(candidatePath, stalePath);
|
|
14293
|
-
logger$
|
|
14722
|
+
logger$28.info({
|
|
14294
14723
|
storyKey,
|
|
14295
14724
|
staleName
|
|
14296
14725
|
}, `[orchestrator] story ${storyKey}: renamed drifted artifact to ${staleName} before re-dispatch`);
|
|
14297
14726
|
} catch (renameErr) {
|
|
14298
|
-
logger$
|
|
14727
|
+
logger$28.warn({
|
|
14299
14728
|
storyKey,
|
|
14300
14729
|
err: renameErr
|
|
14301
14730
|
}, "Failed to rename stale artifact before create-story re-dispatch; relying on 58-9d fraud-guard");
|
|
@@ -14304,7 +14733,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14304
14733
|
}
|
|
14305
14734
|
} catch {}
|
|
14306
14735
|
if (storyFilePath === void 0 && effectiveProjectRoot && isImplicitlyCovered(storyKey, effectiveProjectRoot)) {
|
|
14307
|
-
logger$
|
|
14736
|
+
logger$28.info({ storyKey }, `Story ${storyKey} appears implicitly covered — all expected new files already exist. Skipping create-story.`);
|
|
14308
14737
|
endPhase(storyKey, "create-story");
|
|
14309
14738
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
14310
14739
|
storyKey,
|
|
@@ -14359,7 +14788,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14359
14788
|
output_tokens: createResult.tokenUsage.output,
|
|
14360
14789
|
cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
|
|
14361
14790
|
metadata: JSON.stringify({ storyKey })
|
|
14362
|
-
})).catch((tokenErr) => logger$
|
|
14791
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
14363
14792
|
storyKey,
|
|
14364
14793
|
err: tokenErr
|
|
14365
14794
|
}, "Failed to record create-story token usage"));
|
|
@@ -14367,7 +14796,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14367
14796
|
if (createResult.result === "failed") {
|
|
14368
14797
|
const errMsg = createResult.error ?? "create-story failed";
|
|
14369
14798
|
const stderrSnippet = errMsg.includes("--- stderr ---") ? errMsg.slice(errMsg.indexOf("--- stderr ---") + 15, errMsg.indexOf("--- stderr ---") + 515) : errMsg.slice(0, 500);
|
|
14370
|
-
logger$
|
|
14799
|
+
logger$28.error({
|
|
14371
14800
|
storyKey,
|
|
14372
14801
|
stderrSnippet
|
|
14373
14802
|
}, `Create-story failed: ${stderrSnippet.split("\n")[0]}`);
|
|
@@ -14438,7 +14867,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14438
14867
|
const outsideWorktree = relToWorktree.startsWith("..") || isAbsolute(relToWorktree);
|
|
14439
14868
|
if (outsideWorktree) {
|
|
14440
14869
|
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.`;
|
|
14441
|
-
logger$
|
|
14870
|
+
logger$28.error({
|
|
14442
14871
|
storyKey,
|
|
14443
14872
|
storyFile: createResult.story_file,
|
|
14444
14873
|
worktree: effectiveProjectRoot
|
|
@@ -14466,7 +14895,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14466
14895
|
let claimedPath = createResult.story_file;
|
|
14467
14896
|
if (claimedPath.startsWith(escapedExpectedDir)) {
|
|
14468
14897
|
claimedPath = claimedPath.replace("/\\_bmad-output/", "/_bmad-output/");
|
|
14469
|
-
logger$
|
|
14898
|
+
logger$28.warn({
|
|
14470
14899
|
storyKey,
|
|
14471
14900
|
originalClaim: createResult.story_file,
|
|
14472
14901
|
normalizedClaim: claimedPath
|
|
@@ -14484,7 +14913,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14484
14913
|
if (escapedVariant !== claimedPath && existsSync(escapedVariant)) try {
|
|
14485
14914
|
renameSync(escapedVariant, claimedPath);
|
|
14486
14915
|
actualPath = claimedPath;
|
|
14487
|
-
logger$
|
|
14916
|
+
logger$28.warn({
|
|
14488
14917
|
storyKey,
|
|
14489
14918
|
escapedVariant,
|
|
14490
14919
|
canonicalPath: claimedPath
|
|
@@ -14495,7 +14924,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14495
14924
|
});
|
|
14496
14925
|
} catch (renameErr) {
|
|
14497
14926
|
actualPath = escapedVariant;
|
|
14498
|
-
logger$
|
|
14927
|
+
logger$28.warn({
|
|
14499
14928
|
storyKey,
|
|
14500
14929
|
escapedVariant,
|
|
14501
14930
|
canonicalPath: claimedPath,
|
|
@@ -14510,7 +14939,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14510
14939
|
if (actualPath === null) {
|
|
14511
14940
|
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
14512
14941
|
const errMsg = `create-story claimed success (story_file: ${createResult.story_file}) but the file does not exist on disk (output tokens: ${outputTokens})`;
|
|
14513
|
-
logger$
|
|
14942
|
+
logger$28.error({
|
|
14514
14943
|
storyKey,
|
|
14515
14944
|
claimedPath: createResult.story_file,
|
|
14516
14945
|
outputTokens
|
|
@@ -14538,7 +14967,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14538
14967
|
const mtimeISO = new Date(claimedStat.mtimeMs).toISOString();
|
|
14539
14968
|
const dispatchStartISO = new Date(dispatchStartMs).toISOString();
|
|
14540
14969
|
const errMsg = `create-story claimed success but did not rewrite ${actualPath} during this dispatch (file mtime ${mtimeISO} predates dispatch start ${dispatchStartISO}; output tokens: ${outputTokens})`;
|
|
14541
|
-
logger$
|
|
14970
|
+
logger$28.error({
|
|
14542
14971
|
storyKey,
|
|
14543
14972
|
claimedPath: actualPath,
|
|
14544
14973
|
mtimeISO,
|
|
@@ -14561,7 +14990,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14561
14990
|
return;
|
|
14562
14991
|
}
|
|
14563
14992
|
} catch (verifyErr) {
|
|
14564
|
-
logger$
|
|
14993
|
+
logger$28.warn({
|
|
14565
14994
|
storyKey,
|
|
14566
14995
|
err: verifyErr
|
|
14567
14996
|
}, "create-story post-dispatch file verification threw; proceeding with claimed path");
|
|
@@ -14570,7 +14999,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14570
14999
|
storyFilePath = createResult.story_file;
|
|
14571
15000
|
if (createResult.journeys !== void 0 && createResult.journeys.length > 0) {
|
|
14572
15001
|
updateStory(storyKey, { journeys: createResult.journeys });
|
|
14573
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { journeys: createResult.journeys }).catch((err) => logger$
|
|
15002
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { journeys: createResult.journeys }).catch((err) => logger$28.warn({
|
|
14574
15003
|
err,
|
|
14575
15004
|
storyKey
|
|
14576
15005
|
}, "A0.3: patchStoryState(journeys) failed — pipeline continues"));
|
|
@@ -14592,7 +15021,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14592
15021
|
const overlap = computeTitleOverlap(expectedTitle, createResult.story_title);
|
|
14593
15022
|
if (overlap < TITLE_OVERLAP_WARNING_THRESHOLD) {
|
|
14594
15023
|
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.`;
|
|
14595
|
-
logger$
|
|
15024
|
+
logger$28.warn({
|
|
14596
15025
|
storyKey,
|
|
14597
15026
|
expectedTitle,
|
|
14598
15027
|
generatedTitle: createResult.story_title,
|
|
@@ -14602,7 +15031,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14602
15031
|
storyKey,
|
|
14603
15032
|
msg
|
|
14604
15033
|
});
|
|
14605
|
-
} else logger$
|
|
15034
|
+
} else logger$28.debug({
|
|
14606
15035
|
storyKey,
|
|
14607
15036
|
expectedTitle,
|
|
14608
15037
|
generatedTitle: createResult.story_title,
|
|
@@ -14611,7 +15040,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14611
15040
|
}
|
|
14612
15041
|
}
|
|
14613
15042
|
} catch (titleValidationErr) {
|
|
14614
|
-
logger$
|
|
15043
|
+
logger$28.debug({
|
|
14615
15044
|
storyKey,
|
|
14616
15045
|
err: titleValidationErr
|
|
14617
15046
|
}, "Story title validation skipped due to error");
|
|
@@ -14652,7 +15081,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14652
15081
|
const pathDrift = pathFidelity?.drift ?? 0;
|
|
14653
15082
|
const clauseDrift = clauseFidelity.drift;
|
|
14654
15083
|
const overallDrift = Math.max(pathDrift, clauseDrift);
|
|
14655
|
-
logger$
|
|
15084
|
+
logger$28.debug({
|
|
14656
15085
|
storyKey,
|
|
14657
15086
|
pathDrift,
|
|
14658
15087
|
clauseDrift,
|
|
@@ -14674,7 +15103,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14674
15103
|
if (pathMissing.length > 0) reasons.push(`${pathMissing.length} named path(s) missing`);
|
|
14675
15104
|
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})`);
|
|
14676
15105
|
if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall (rendered ${clauseFidelity.renderedClauseCount}/${clauseFidelity.sourceClauseCount} = ${Math.round(clauseFidelity.clauseRatio * 100)}%)`);
|
|
14677
|
-
logger$
|
|
15106
|
+
logger$28.warn({
|
|
14678
15107
|
storyKey,
|
|
14679
15108
|
pathDrift,
|
|
14680
15109
|
clauseDrift,
|
|
@@ -14717,7 +15146,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14717
15146
|
storyFilePath = void 0;
|
|
14718
15147
|
continue;
|
|
14719
15148
|
} catch (renameErr) {
|
|
14720
|
-
logger$
|
|
15149
|
+
logger$28.warn({
|
|
14721
15150
|
storyKey,
|
|
14722
15151
|
err: renameErr,
|
|
14723
15152
|
stalePath
|
|
@@ -14731,7 +15160,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14731
15160
|
if (numericMismatches.length > 0) reasons.push(`numeric mismatches: ${numericMismatches.map((m) => `${m.noun} (source=${m.sourceCount}, rendered=${m.renderedCount})`).join("; ")}`);
|
|
14732
15161
|
if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall: source=${clauseFidelity.sourceClauseCount}, rendered=${clauseFidelity.renderedClauseCount}`);
|
|
14733
15162
|
const errMsg = `create-story output drifted from source AC after ${MAX_FIDELITY_RETRIES} retries; ` + reasons.join("; ");
|
|
14734
|
-
logger$
|
|
15163
|
+
logger$28.error({
|
|
14735
15164
|
storyKey,
|
|
14736
15165
|
pathDrift,
|
|
14737
15166
|
clauseDrift,
|
|
@@ -14758,7 +15187,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14758
15187
|
}
|
|
14759
15188
|
}
|
|
14760
15189
|
} catch (fidelityErr) {
|
|
14761
|
-
logger$
|
|
15190
|
+
logger$28.warn({
|
|
14762
15191
|
storyKey,
|
|
14763
15192
|
err: fidelityErr
|
|
14764
15193
|
}, "fidelity gate threw; proceeding without retry");
|
|
@@ -14770,7 +15199,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14770
15199
|
probeRetries++;
|
|
14771
15200
|
const stalePath = storyFilePath.replace(/\.md$/, `.stale-probe-${Date.now()}.md`);
|
|
14772
15201
|
renameSync(storyFilePath, stalePath);
|
|
14773
|
-
logger$
|
|
15202
|
+
logger$28.warn({
|
|
14774
15203
|
storyKey,
|
|
14775
15204
|
error: probeParse.error,
|
|
14776
15205
|
retries: probeRetries,
|
|
@@ -14795,7 +15224,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14795
15224
|
continue;
|
|
14796
15225
|
}
|
|
14797
15226
|
} catch (probeGateErr) {
|
|
14798
|
-
logger$
|
|
15227
|
+
logger$28.warn({
|
|
14799
15228
|
storyKey,
|
|
14800
15229
|
err: probeGateErr
|
|
14801
15230
|
}, "probe-validity gate threw; proceeding without retry (verification backstop)");
|
|
@@ -14818,14 +15247,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
14818
15247
|
...contract.transport !== void 0 ? { transport: contract.transport } : {}
|
|
14819
15248
|
})
|
|
14820
15249
|
});
|
|
14821
|
-
logger$
|
|
15250
|
+
logger$28.info({
|
|
14822
15251
|
storyKey,
|
|
14823
15252
|
contractCount: contracts.length,
|
|
14824
15253
|
contracts
|
|
14825
15254
|
}, "Stored interface contract declarations");
|
|
14826
15255
|
}
|
|
14827
15256
|
} catch (err) {
|
|
14828
|
-
logger$
|
|
15257
|
+
logger$28.warn({
|
|
14829
15258
|
storyKey,
|
|
14830
15259
|
error: err instanceof Error ? err.message : String(err)
|
|
14831
15260
|
}, "Failed to parse interface contracts — continuing without contract declarations");
|
|
@@ -14843,7 +15272,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14843
15272
|
const isStateIntegrating = stateIntegratingEnabled && detectsStateIntegratingAC(probeAuthorEpicContent);
|
|
14844
15273
|
if (isEventDriven || isStateIntegrating) {
|
|
14845
15274
|
const triggerClass = isEventDriven && isStateIntegrating ? "both" : isStateIntegrating ? "state-integrating" : "event-driven";
|
|
14846
|
-
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { probe_author_triggered_by: triggerClass }).catch((err) => logger$
|
|
15275
|
+
if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { probe_author_triggered_by: triggerClass }).catch((err) => logger$28.warn({
|
|
14847
15276
|
err,
|
|
14848
15277
|
storyKey
|
|
14849
15278
|
}, "patchStoryState(probe_author_triggered_by) failed — pipeline continues"));
|
|
@@ -14878,7 +15307,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14878
15307
|
});
|
|
14879
15308
|
}
|
|
14880
15309
|
});
|
|
14881
|
-
logger$
|
|
15310
|
+
logger$28.info({
|
|
14882
15311
|
storyKey,
|
|
14883
15312
|
result: probeAuthorResult.result,
|
|
14884
15313
|
probesAuthoredCount: probeAuthorResult.probesAuthoredCount
|
|
@@ -14890,14 +15319,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
14890
15319
|
output_tokens: probeAuthorResult.tokenUsage.output,
|
|
14891
15320
|
cost_usd: estimateDispatchCost(probeAuthorResult.tokenUsage.input, probeAuthorResult.tokenUsage.output),
|
|
14892
15321
|
metadata: JSON.stringify({ storyKey })
|
|
14893
|
-
})).catch((tokenErr) => logger$
|
|
15322
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
14894
15323
|
storyKey,
|
|
14895
15324
|
err: tokenErr
|
|
14896
15325
|
}, "Failed to record probe-author token usage"));
|
|
14897
|
-
} else logger$
|
|
14898
|
-
} else logger$
|
|
15326
|
+
} else logger$28.debug({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping gate");
|
|
15327
|
+
} else logger$28.debug({ storyKey }, "probe-author: source AC not event-driven — skipping gate");
|
|
14899
15328
|
} catch (probeAuthorErr) {
|
|
14900
|
-
logger$
|
|
15329
|
+
logger$28.warn({
|
|
14901
15330
|
storyKey,
|
|
14902
15331
|
err: probeAuthorErr
|
|
14903
15332
|
}, "probe-author gate threw unexpectedly; proceeding to test-plan without authored probes");
|
|
@@ -14927,10 +15356,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
14927
15356
|
});
|
|
14928
15357
|
testPlanPhaseResult = testPlanResult.result;
|
|
14929
15358
|
testPlanTokenUsage = testPlanResult.tokenUsage;
|
|
14930
|
-
if (testPlanResult.result === "success") logger$
|
|
14931
|
-
else logger$
|
|
15359
|
+
if (testPlanResult.result === "success") logger$28.info({ storyKey }, "Test plan generated successfully");
|
|
15360
|
+
else logger$28.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
|
|
14932
15361
|
} catch (err) {
|
|
14933
|
-
logger$
|
|
15362
|
+
logger$28.warn({
|
|
14934
15363
|
storyKey,
|
|
14935
15364
|
err
|
|
14936
15365
|
}, "Test planning failed — proceeding to dev-story without test plan");
|
|
@@ -14943,7 +15372,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14943
15372
|
output_tokens: testPlanTokenUsage.output,
|
|
14944
15373
|
cost_usd: estimateDispatchCost(testPlanTokenUsage.input, testPlanTokenUsage.output),
|
|
14945
15374
|
metadata: JSON.stringify({ storyKey })
|
|
14946
|
-
})).catch((tokenErr) => logger$
|
|
15375
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
14947
15376
|
storyKey,
|
|
14948
15377
|
err: tokenErr
|
|
14949
15378
|
}, "Failed to record test-plan token usage"));
|
|
@@ -15006,7 +15435,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15006
15435
|
]
|
|
15007
15436
|
}).trim();
|
|
15008
15437
|
} catch {}
|
|
15009
|
-
if (baselineHeadSha !== void 0 && runManifest !== null) runManifest.patchStoryState(storyKey, { baseline_sha: baselineHeadSha }).catch((err) => logger$
|
|
15438
|
+
if (baselineHeadSha !== void 0 && runManifest !== null) runManifest.patchStoryState(storyKey, { baseline_sha: baselineHeadSha }).catch((err) => logger$28.warn({
|
|
15010
15439
|
err,
|
|
15011
15440
|
storyKey
|
|
15012
15441
|
}, "patchStoryState(baseline_sha) failed — pipeline continues"));
|
|
@@ -15016,7 +15445,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15016
15445
|
storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
|
|
15017
15446
|
storyContentForVerification = storyContentForAnalysis;
|
|
15018
15447
|
} catch (err) {
|
|
15019
|
-
logger$
|
|
15448
|
+
logger$28.error({
|
|
15020
15449
|
storyKey,
|
|
15021
15450
|
storyFilePath,
|
|
15022
15451
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -15024,7 +15453,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15024
15453
|
}
|
|
15025
15454
|
const analysis = analyzeStoryComplexity(storyContentForAnalysis);
|
|
15026
15455
|
const batches = planTaskBatches(analysis);
|
|
15027
|
-
logger$
|
|
15456
|
+
logger$28.info({
|
|
15028
15457
|
storyKey,
|
|
15029
15458
|
estimatedScope: analysis.estimatedScope,
|
|
15030
15459
|
batchCount: batches.length,
|
|
@@ -15042,7 +15471,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15042
15471
|
if (_state !== "RUNNING") break;
|
|
15043
15472
|
const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
|
|
15044
15473
|
const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
|
|
15045
|
-
logger$
|
|
15474
|
+
logger$28.info({
|
|
15046
15475
|
storyKey,
|
|
15047
15476
|
batchIndex: batch.batchIndex,
|
|
15048
15477
|
taskCount: batch.taskIds.length
|
|
@@ -15074,7 +15503,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15074
15503
|
});
|
|
15075
15504
|
} catch (batchErr) {
|
|
15076
15505
|
const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
|
|
15077
|
-
logger$
|
|
15506
|
+
logger$28.warn({
|
|
15078
15507
|
storyKey,
|
|
15079
15508
|
batchIndex: batch.batchIndex,
|
|
15080
15509
|
error: errMsg
|
|
@@ -15096,7 +15525,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15096
15525
|
filesModified: batchFilesModified,
|
|
15097
15526
|
result: batchResult.result === "success" ? "success" : "failed"
|
|
15098
15527
|
};
|
|
15099
|
-
logger$
|
|
15528
|
+
logger$28.info(batchMetrics, "Batch dev-story metrics");
|
|
15100
15529
|
for (const f$1 of batchFilesModified) allFilesModified.add(f$1);
|
|
15101
15530
|
if (batchFilesModified.length > 0) batchFileGroups.push({
|
|
15102
15531
|
batchIndex: batch.batchIndex,
|
|
@@ -15115,13 +15544,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
15115
15544
|
durationMs: batchDurationMs,
|
|
15116
15545
|
result: batchMetrics.result
|
|
15117
15546
|
})
|
|
15118
|
-
})).catch((tokenErr) => logger$
|
|
15547
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
15119
15548
|
storyKey,
|
|
15120
15549
|
batchIndex: batch.batchIndex,
|
|
15121
15550
|
err: tokenErr
|
|
15122
15551
|
}, "Failed to record batch token usage"));
|
|
15123
15552
|
if (batchResult.tokenUsage?.output !== void 0) devOutputTokenCount = (devOutputTokenCount ?? 0) + batchResult.tokenUsage.output;
|
|
15124
|
-
if (batchResult.result === "failed") logger$
|
|
15553
|
+
if (batchResult.result === "failed") logger$28.warn({
|
|
15125
15554
|
storyKey,
|
|
15126
15555
|
batchIndex: batch.batchIndex,
|
|
15127
15556
|
error: batchResult.error
|
|
@@ -15166,7 +15595,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15166
15595
|
output_tokens: devResult.tokenUsage.output,
|
|
15167
15596
|
cost_usd: estimateDispatchCost(devResult.tokenUsage.input, devResult.tokenUsage.output),
|
|
15168
15597
|
metadata: JSON.stringify({ storyKey })
|
|
15169
|
-
})).catch((tokenErr) => logger$
|
|
15598
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
15170
15599
|
storyKey,
|
|
15171
15600
|
err: tokenErr
|
|
15172
15601
|
}, "Failed to record dev-story token usage"));
|
|
@@ -15181,7 +15610,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15181
15610
|
endPhase(storyKey, "dev-story", devStoryModel);
|
|
15182
15611
|
const timeoutFiles = checkGitDiffFiles(effectiveProjectRoot ?? process.cwd());
|
|
15183
15612
|
if (timeoutFiles.length === 0) {
|
|
15184
|
-
logger$
|
|
15613
|
+
logger$28.warn({ storyKey }, "Dev-story timeout with zero modified files — escalating immediately (no checkpoint)");
|
|
15185
15614
|
updateStory(storyKey, {
|
|
15186
15615
|
phase: "ESCALATED",
|
|
15187
15616
|
error: "timeout-no-files",
|
|
@@ -15197,7 +15626,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15197
15626
|
await persistState();
|
|
15198
15627
|
return;
|
|
15199
15628
|
}
|
|
15200
|
-
logger$
|
|
15629
|
+
logger$28.info({
|
|
15201
15630
|
storyKey,
|
|
15202
15631
|
filesCount: timeoutFiles.length
|
|
15203
15632
|
}, "Dev-story timeout with partial files — capturing checkpoint");
|
|
@@ -15214,7 +15643,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15214
15643
|
]
|
|
15215
15644
|
}).trim();
|
|
15216
15645
|
} catch (diffErr) {
|
|
15217
|
-
logger$
|
|
15646
|
+
logger$28.warn({
|
|
15218
15647
|
storyKey,
|
|
15219
15648
|
error: diffErr instanceof Error ? diffErr.message : String(diffErr)
|
|
15220
15649
|
}, "Failed to capture git diff for checkpoint — proceeding with empty diff");
|
|
@@ -15288,9 +15717,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
15288
15717
|
checkpointRetryPrompt = assembled.prompt;
|
|
15289
15718
|
} catch {
|
|
15290
15719
|
checkpointRetryPrompt = `Continue story ${storyKey} from checkpoint. Your prior attempt timed out. Do not redo completed work.`;
|
|
15291
|
-
logger$
|
|
15720
|
+
logger$28.warn({ storyKey }, "Failed to assemble checkpoint retry prompt — using fallback");
|
|
15292
15721
|
}
|
|
15293
|
-
logger$
|
|
15722
|
+
logger$28.info({
|
|
15294
15723
|
storyKey,
|
|
15295
15724
|
filesCount: checkpointData.filesModified.length
|
|
15296
15725
|
}, "Dispatching checkpoint retry for timed-out story");
|
|
@@ -15320,7 +15749,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15320
15749
|
outcome: checkpointRetryResult.status === "timeout" ? "escalated" : "retried",
|
|
15321
15750
|
cost_usd: 0,
|
|
15322
15751
|
timestamp: new Date().toISOString()
|
|
15323
|
-
}).catch((err) => logger$
|
|
15752
|
+
}).catch((err) => logger$28.warn({
|
|
15324
15753
|
err,
|
|
15325
15754
|
storyKey
|
|
15326
15755
|
}, "appendRecoveryEntry(checkpoint-retry) failed — pipeline continues"));
|
|
@@ -15333,7 +15762,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15333
15762
|
} : void 0 }
|
|
15334
15763
|
});
|
|
15335
15764
|
if (checkpointRetryResult.status === "timeout") {
|
|
15336
|
-
logger$
|
|
15765
|
+
logger$28.warn({ storyKey }, "Checkpoint retry dispatch timed out — escalating story");
|
|
15337
15766
|
updateStory(storyKey, {
|
|
15338
15767
|
phase: "ESCALATED",
|
|
15339
15768
|
error: "checkpoint-retry-timeout",
|
|
@@ -15353,7 +15782,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15353
15782
|
replaceDevStorySignals(retryParsed);
|
|
15354
15783
|
devFilesModified = retryParsed?.files_modified ?? checkGitDiffFiles(effectiveProjectRoot ?? process.cwd());
|
|
15355
15784
|
if (checkpointRetryResult.status === "completed" && retryParsed?.result === "success") devStoryWasSuccess = true;
|
|
15356
|
-
else logger$
|
|
15785
|
+
else logger$28.warn({
|
|
15357
15786
|
storyKey,
|
|
15358
15787
|
status: checkpointRetryResult.status
|
|
15359
15788
|
}, "Checkpoint retry completed with failure — proceeding to code review");
|
|
@@ -15363,13 +15792,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
15363
15792
|
replaceDevStorySignals(devResult);
|
|
15364
15793
|
if (devResult.result === "success") devStoryWasSuccess = true;
|
|
15365
15794
|
else {
|
|
15366
|
-
logger$
|
|
15795
|
+
logger$28.warn({
|
|
15367
15796
|
storyKey,
|
|
15368
15797
|
error: devResult.error,
|
|
15369
15798
|
filesModified: devFilesModified.length
|
|
15370
15799
|
}, "Dev-story reported failure, proceeding to code review");
|
|
15371
15800
|
if (!devResult.error?.startsWith("dispatch_timeout")) {
|
|
15372
|
-
logger$
|
|
15801
|
+
logger$28.warn({
|
|
15373
15802
|
storyKey,
|
|
15374
15803
|
error: devResult.error
|
|
15375
15804
|
}, "Agent process failure (non-timeout) — story will proceed to code review with partial work");
|
|
@@ -15450,7 +15879,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15450
15879
|
}).trim();
|
|
15451
15880
|
if (committedFiles.length > 0) gitDiffFiles = committedFiles.split("\n").filter(Boolean);
|
|
15452
15881
|
} catch {}
|
|
15453
|
-
logger$
|
|
15882
|
+
logger$28.info({
|
|
15454
15883
|
storyKey,
|
|
15455
15884
|
baselineHeadSha,
|
|
15456
15885
|
committedFileCount: gitDiffFiles?.length ?? 0
|
|
@@ -15458,7 +15887,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15458
15887
|
} else {
|
|
15459
15888
|
const outsideWorktreeFiles = detectWorkOutsideWorktree(effectiveProjectRoot, projectRoot, checkGitDiffFiles);
|
|
15460
15889
|
const misrouted = outsideWorktreeFiles.length > 0;
|
|
15461
|
-
logger$
|
|
15890
|
+
logger$28.warn({
|
|
15462
15891
|
storyKey,
|
|
15463
15892
|
misrouteSuspected: misrouted,
|
|
15464
15893
|
outsideWorktreeFileCount: outsideWorktreeFiles.length
|
|
@@ -15534,7 +15963,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15534
15963
|
}
|
|
15535
15964
|
}
|
|
15536
15965
|
if (implClassification.hasImplementation && implAddedLines === 0) {
|
|
15537
|
-
logger$
|
|
15966
|
+
logger$28.warn({
|
|
15538
15967
|
storyKey,
|
|
15539
15968
|
changed: gitDiffFiles.slice(0, 10)
|
|
15540
15969
|
}, "dev-story reported success but its implementation files added zero non-whitespace lines (empty stub / whitespace-only / pure deletion) — escalating no-implementation");
|
|
@@ -15556,7 +15985,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15556
15985
|
return;
|
|
15557
15986
|
}
|
|
15558
15987
|
if (!implClassification.hasImplementation) {
|
|
15559
|
-
logger$
|
|
15988
|
+
logger$28.warn({
|
|
15560
15989
|
storyKey,
|
|
15561
15990
|
artifactFiles: implClassification.artifactOnly.slice(0, 10)
|
|
15562
15991
|
}, "dev-story reported success but the diff contains only pipeline artifacts — no implementation was produced");
|
|
@@ -15585,24 +16014,24 @@ function createImplementationOrchestrator(deps) {
|
|
|
15585
16014
|
if (dirtyNow.length > 0) if (devStoryWasSuccess) {
|
|
15586
16015
|
const earlyCommit = await commitDevStoryOutput(storyKey, _capturedStoryTitle, dirtyNow, effectiveProjectRoot);
|
|
15587
16016
|
if (earlyCommit.status === "committed") {
|
|
15588
|
-
logger$
|
|
16017
|
+
logger$28.info({
|
|
15589
16018
|
storyKey,
|
|
15590
16019
|
sha: earlyCommit.sha,
|
|
15591
16020
|
fileCount: earlyCommit.filesStaged.length
|
|
15592
16021
|
}, "commit-first: dev-story output committed to story branch");
|
|
15593
|
-
if (runManifest !== null && earlyCommit.sha) runManifest.patchStoryState(storyKey, { commit_sha: earlyCommit.sha }).catch((err) => logger$
|
|
16022
|
+
if (runManifest !== null && earlyCommit.sha) runManifest.patchStoryState(storyKey, { commit_sha: earlyCommit.sha }).catch((err) => logger$28.warn({
|
|
15594
16023
|
err,
|
|
15595
16024
|
storyKey
|
|
15596
16025
|
}, "patchStoryState(commit_sha, commit-first) failed — pipeline continues"));
|
|
15597
16026
|
} else if (earlyCommit.status === "failed") {
|
|
15598
16027
|
_devOutputCommitHookFailure = earlyCommit.stderr;
|
|
15599
16028
|
const cp = await checkpointStoryWorktree(storyKey, "dev-story output (deliverable commit rejected by hooks)", effectiveProjectRoot);
|
|
15600
|
-
logger$
|
|
16029
|
+
logger$28.warn({
|
|
15601
16030
|
storyKey,
|
|
15602
16031
|
checkpoint: cp.status,
|
|
15603
16032
|
hookStderr: earlyCommit.stderr.slice(0, 500)
|
|
15604
16033
|
}, "commit-first: hooks rejected feat commit — work preserved as wip checkpoint");
|
|
15605
|
-
if (cp.status === "committed" && runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
16034
|
+
if (cp.status === "committed" && runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$28.warn({
|
|
15606
16035
|
err,
|
|
15607
16036
|
storyKey
|
|
15608
16037
|
}, "patchStoryState(checkpoint_sha) failed — pipeline continues"));
|
|
@@ -15610,11 +16039,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15610
16039
|
} else {
|
|
15611
16040
|
const cp = await checkpointStoryWorktree(storyKey, "dev-story partial output", effectiveProjectRoot);
|
|
15612
16041
|
if (cp.status === "committed") {
|
|
15613
|
-
logger$
|
|
16042
|
+
logger$28.info({
|
|
15614
16043
|
storyKey,
|
|
15615
16044
|
sha: cp.sha
|
|
15616
16045
|
}, "commit-first: partial dev-story output checkpointed");
|
|
15617
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
16046
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$28.warn({
|
|
15618
16047
|
err,
|
|
15619
16048
|
storyKey
|
|
15620
16049
|
}, "patchStoryState(checkpoint_sha) failed — pipeline continues"));
|
|
@@ -15648,10 +16077,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
15648
16077
|
"pipe"
|
|
15649
16078
|
]
|
|
15650
16079
|
});
|
|
15651
|
-
logger$
|
|
16080
|
+
logger$28.info({ storyKey }, "Secondary typecheck (tsc --noEmit) passed");
|
|
15652
16081
|
} catch (tscErr) {
|
|
15653
16082
|
const tscOutput = tscErr instanceof Error && "stdout" in tscErr ? String(tscErr.stdout ?? "").slice(0, 2e3) : "";
|
|
15654
|
-
logger$
|
|
16083
|
+
logger$28.warn({
|
|
15655
16084
|
storyKey,
|
|
15656
16085
|
tscOutput
|
|
15657
16086
|
}, "Secondary typecheck (tsc --noEmit) failed — treating as build failure");
|
|
@@ -15666,7 +16095,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15666
16095
|
if (buildVerifyResult.status === "passed") {
|
|
15667
16096
|
_buildPassed = true;
|
|
15668
16097
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15669
|
-
logger$
|
|
16098
|
+
logger$28.info({ storyKey }, "Build verification passed");
|
|
15670
16099
|
} else if (buildVerifyResult.status === "failed" || buildVerifyResult.status === "timeout") {
|
|
15671
16100
|
const truncatedOutput = (buildVerifyResult.output ?? "").slice(0, 2e3);
|
|
15672
16101
|
const reason = buildVerifyResult.reason ?? "build-verification-failed";
|
|
@@ -15675,7 +16104,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15675
16104
|
const resolvedRoot = effectiveProjectRoot ?? process.cwd();
|
|
15676
16105
|
const hasChanges = detectPackageChanges(_packageSnapshot, resolvedRoot);
|
|
15677
16106
|
if (hasChanges) {
|
|
15678
|
-
logger$
|
|
16107
|
+
logger$28.warn({ storyKey }, "Package files changed since snapshot — restoring to prevent cascade");
|
|
15679
16108
|
const restoreResult = restorePackageSnapshot(_packageSnapshot, { projectRoot: resolvedRoot });
|
|
15680
16109
|
if (restoreResult.restored) {
|
|
15681
16110
|
const retryAfterRestore = runBuildVerification({
|
|
@@ -15688,11 +16117,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15688
16117
|
retryPassed = true;
|
|
15689
16118
|
_buildPassed = true;
|
|
15690
16119
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15691
|
-
logger$
|
|
16120
|
+
logger$28.warn({
|
|
15692
16121
|
storyKey,
|
|
15693
16122
|
filesRestored: restoreResult.filesRestored
|
|
15694
16123
|
}, "Build passed after package snapshot restore — cross-story pollution detected and cleaned");
|
|
15695
|
-
} else logger$
|
|
16124
|
+
} else logger$28.warn({
|
|
15696
16125
|
storyKey,
|
|
15697
16126
|
filesRestored: restoreResult.filesRestored
|
|
15698
16127
|
}, "Build still fails after snapshot restore — story has its own build errors");
|
|
@@ -15704,7 +16133,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15704
16133
|
if (missingPkgMatch && buildVerifyResult.status !== "timeout") {
|
|
15705
16134
|
const missingPkg = missingPkgMatch[1].replace(/^(@[^/]+\/[^/]+)\/.*$/, "$1").replace(/^([^@][^/]*)\/.*$/, "$1");
|
|
15706
16135
|
const resolvedRoot = effectiveProjectRoot ?? process.cwd();
|
|
15707
|
-
logger$
|
|
16136
|
+
logger$28.warn({
|
|
15708
16137
|
storyKey,
|
|
15709
16138
|
missingPkg
|
|
15710
16139
|
}, "Build-fix retry: detected missing npm package — attempting npm install");
|
|
@@ -15715,7 +16144,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15715
16144
|
encoding: "utf-8",
|
|
15716
16145
|
stdio: "pipe"
|
|
15717
16146
|
});
|
|
15718
|
-
logger$
|
|
16147
|
+
logger$28.warn({
|
|
15719
16148
|
storyKey,
|
|
15720
16149
|
missingPkg
|
|
15721
16150
|
}, "Build-fix retry: npm install succeeded — retrying build verification");
|
|
@@ -15729,18 +16158,18 @@ function createImplementationOrchestrator(deps) {
|
|
|
15729
16158
|
retryPassed = true;
|
|
15730
16159
|
_buildPassed = true;
|
|
15731
16160
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15732
|
-
logger$
|
|
16161
|
+
logger$28.warn({
|
|
15733
16162
|
storyKey,
|
|
15734
16163
|
missingPkg
|
|
15735
16164
|
}, "Build-fix retry: build verification passed after installing missing package");
|
|
15736
|
-
} else logger$
|
|
16165
|
+
} else logger$28.warn({
|
|
15737
16166
|
storyKey,
|
|
15738
16167
|
missingPkg,
|
|
15739
16168
|
retryStatus: retryResult.status
|
|
15740
16169
|
}, "Build-fix retry: build still fails after installing missing package — escalating");
|
|
15741
16170
|
} catch (installErr) {
|
|
15742
16171
|
const installMsg = installErr instanceof Error ? installErr.message : String(installErr);
|
|
15743
|
-
logger$
|
|
16172
|
+
logger$28.warn({
|
|
15744
16173
|
storyKey,
|
|
15745
16174
|
missingPkg,
|
|
15746
16175
|
error: installMsg
|
|
@@ -15750,7 +16179,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15750
16179
|
if (!retryPassed) {
|
|
15751
16180
|
let buildFixPassed = false;
|
|
15752
16181
|
if (buildVerifyResult.status === "failed" && storyFilePath !== void 0) try {
|
|
15753
|
-
logger$
|
|
16182
|
+
logger$28.info({ storyKey }, "Dispatching build-fix agent");
|
|
15754
16183
|
startPhase(storyKey, "build-fix");
|
|
15755
16184
|
const storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
15756
16185
|
let buildFixTemplate;
|
|
@@ -15787,11 +16216,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
15787
16216
|
buildFixPassed = true;
|
|
15788
16217
|
_buildPassed = true;
|
|
15789
16218
|
eventBus.emit("story:build-verification-passed", { storyKey });
|
|
15790
|
-
logger$
|
|
15791
|
-
} else logger$
|
|
16219
|
+
logger$28.info({ storyKey }, "Build passed after build-fix dispatch");
|
|
16220
|
+
} else logger$28.warn({ storyKey }, "Build still fails after build-fix dispatch — escalating");
|
|
15792
16221
|
} catch (fixErr) {
|
|
15793
16222
|
const fixMsg = fixErr instanceof Error ? fixErr.message : String(fixErr);
|
|
15794
|
-
logger$
|
|
16223
|
+
logger$28.warn({
|
|
15795
16224
|
storyKey,
|
|
15796
16225
|
error: fixMsg
|
|
15797
16226
|
}, "Build-fix dispatch failed — escalating");
|
|
@@ -15828,7 +16257,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15828
16257
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
15829
16258
|
}
|
|
15830
16259
|
}).catch((err) => {
|
|
15831
|
-
logger$
|
|
16260
|
+
logger$28.warn({
|
|
15832
16261
|
err,
|
|
15833
16262
|
storyKey
|
|
15834
16263
|
}, "interactive prompt failed — continuing with default action");
|
|
@@ -15845,7 +16274,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15845
16274
|
exitCode: buildVerifyResult.exitCode ?? 1,
|
|
15846
16275
|
output: truncatedOutput
|
|
15847
16276
|
});
|
|
15848
|
-
logger$
|
|
16277
|
+
logger$28.warn({
|
|
15849
16278
|
storyKey,
|
|
15850
16279
|
reason,
|
|
15851
16280
|
exitCode: buildVerifyResult.exitCode,
|
|
@@ -15879,7 +16308,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15879
16308
|
storyKey
|
|
15880
16309
|
});
|
|
15881
16310
|
if (icResult.potentiallyAffectedTests.length > 0) {
|
|
15882
|
-
logger$
|
|
16311
|
+
logger$28.warn({
|
|
15883
16312
|
storyKey,
|
|
15884
16313
|
modifiedInterfaces: icResult.modifiedInterfaces,
|
|
15885
16314
|
potentiallyAffectedTests: icResult.potentiallyAffectedTests
|
|
@@ -15982,14 +16411,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
15982
16411
|
adapter: db,
|
|
15983
16412
|
engine: "linear"
|
|
15984
16413
|
}).catch((recoveryErr) => {
|
|
15985
|
-
logger$
|
|
16414
|
+
logger$28.warn({
|
|
15986
16415
|
storyKey,
|
|
15987
16416
|
err: recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr)
|
|
15988
16417
|
}, "Recovery Engine invocation failed — falling through to VERIFICATION_FAILED (best-effort)");
|
|
15989
16418
|
return null;
|
|
15990
16419
|
});
|
|
15991
16420
|
if (recoveryResult?.action === "halt-entire-run") {
|
|
15992
|
-
logger$
|
|
16421
|
+
logger$28.error({
|
|
15993
16422
|
storyKey,
|
|
15994
16423
|
pendingProposalsCount: recoveryResult.pendingProposalsCount
|
|
15995
16424
|
}, "Recovery Engine safety valve: halting entire run due to >= 5 pending proposals");
|
|
@@ -16001,13 +16430,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
16001
16430
|
outcome: "escalated",
|
|
16002
16431
|
cost_usd: 0,
|
|
16003
16432
|
timestamp: new Date().toISOString()
|
|
16004
|
-
}).catch((err) => logger$
|
|
16433
|
+
}).catch((err) => logger$28.warn({
|
|
16005
16434
|
err,
|
|
16006
16435
|
storyKey
|
|
16007
16436
|
}, "appendRecoveryEntry(halt-entire-run) failed — pipeline continues"));
|
|
16008
16437
|
_budgetExhausted = true;
|
|
16009
16438
|
} else if (recoveryResult?.action === "retry") {
|
|
16010
|
-
logger$
|
|
16439
|
+
logger$28.info({
|
|
16011
16440
|
storyKey,
|
|
16012
16441
|
attempt: recoveryResult.attempt,
|
|
16013
16442
|
retryBudgetRemaining: recoveryResult.retryBudgetRemaining
|
|
@@ -16059,22 +16488,22 @@ function createImplementationOrchestrator(deps) {
|
|
|
16059
16488
|
outcome: tierARecovered ? "recovered" : "retried",
|
|
16060
16489
|
cost_usd: 0,
|
|
16061
16490
|
timestamp: new Date().toISOString()
|
|
16062
|
-
}).catch((err) => logger$
|
|
16491
|
+
}).catch((err) => logger$28.warn({
|
|
16063
16492
|
err,
|
|
16064
16493
|
storyKey
|
|
16065
16494
|
}, "appendRecoveryEntry(tier-a) failed — pipeline continues"));
|
|
16066
16495
|
if (tierARecovered) {
|
|
16067
|
-
logger$
|
|
16496
|
+
logger$28.info({ storyKey }, "Recovery Engine Tier A retry succeeded — story proceeding to COMPLETE");
|
|
16068
16497
|
shouldFallThroughToComplete = true;
|
|
16069
|
-
} else logger$
|
|
16498
|
+
} else logger$28.warn({ storyKey }, "Recovery Engine Tier A retry still failed — falling through to VERIFICATION_FAILED");
|
|
16070
16499
|
} catch (retryErr) {
|
|
16071
|
-
logger$
|
|
16500
|
+
logger$28.warn({
|
|
16072
16501
|
storyKey,
|
|
16073
16502
|
err: retryErr instanceof Error ? retryErr.message : String(retryErr)
|
|
16074
16503
|
}, "Recovery Engine Tier A re-dispatch threw — falling through to VERIFICATION_FAILED");
|
|
16075
16504
|
}
|
|
16076
16505
|
} else if (recoveryResult?.action === "propose") {
|
|
16077
|
-
logger$
|
|
16506
|
+
logger$28.info({ storyKey }, "Recovery Engine Tier B: proposal appended — marking story ESCALATED for operator re-scope");
|
|
16078
16507
|
if (runManifest) runManifest.appendRecoveryEntry({
|
|
16079
16508
|
story_key: storyKey,
|
|
16080
16509
|
attempt_number: finalReviewCycles + 1,
|
|
@@ -16083,7 +16512,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16083
16512
|
outcome: "escalated",
|
|
16084
16513
|
cost_usd: 0,
|
|
16085
16514
|
timestamp: new Date().toISOString()
|
|
16086
|
-
}).catch((err) => logger$
|
|
16515
|
+
}).catch((err) => logger$28.warn({
|
|
16087
16516
|
err,
|
|
16088
16517
|
storyKey
|
|
16089
16518
|
}, "appendRecoveryEntry(tier-b) failed — pipeline continues"));
|
|
@@ -16103,7 +16532,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16103
16532
|
await persistState();
|
|
16104
16533
|
return "verification-failed";
|
|
16105
16534
|
} else if (recoveryResult?.action === "halt") {
|
|
16106
|
-
logger$
|
|
16535
|
+
logger$28.warn({ storyKey }, "Recovery Engine Tier C: halt — invoking interactive prompt for operator decision");
|
|
16107
16536
|
const haltRunId = config.pipelineRunId ?? storyKey;
|
|
16108
16537
|
await runInteractivePrompt({
|
|
16109
16538
|
runId: haltRunId,
|
|
@@ -16120,7 +16549,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16120
16549
|
eventBus.emit("decision:halt-skipped-non-interactive", haltPayload);
|
|
16121
16550
|
}
|
|
16122
16551
|
}).catch((err) => {
|
|
16123
|
-
logger$
|
|
16552
|
+
logger$28.warn({
|
|
16124
16553
|
err,
|
|
16125
16554
|
storyKey
|
|
16126
16555
|
}, "Recovery Engine Tier C: interactive prompt failed — escalating anyway");
|
|
@@ -16133,7 +16562,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16133
16562
|
outcome: "escalated",
|
|
16134
16563
|
cost_usd: 0,
|
|
16135
16564
|
timestamp: new Date().toISOString()
|
|
16136
|
-
}).catch((err) => logger$
|
|
16565
|
+
}).catch((err) => logger$28.warn({
|
|
16137
16566
|
err,
|
|
16138
16567
|
storyKey
|
|
16139
16568
|
}, "appendRecoveryEntry(tier-c) failed — pipeline continues"));
|
|
@@ -16158,11 +16587,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
16158
16587
|
if (effectiveProjectRoot !== void 0 && effectiveProjectRoot !== projectRoot) {
|
|
16159
16588
|
const cp = await checkpointStoryWorktree(storyKey, `verification-failed: ${verificationFailReason ?? "tier-a-fail"}`, effectiveProjectRoot);
|
|
16160
16589
|
if (cp.status === "committed") {
|
|
16161
|
-
logger$
|
|
16590
|
+
logger$28.info({
|
|
16162
16591
|
storyKey,
|
|
16163
16592
|
sha: cp.sha
|
|
16164
16593
|
}, "verification-failed checkpoint: uncommitted worktree state preserved on story branch");
|
|
16165
|
-
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$
|
|
16594
|
+
if (runManifest !== null && cp.sha) runManifest.patchStoryState(storyKey, { checkpoint_sha: cp.sha }).catch((err) => logger$28.warn({
|
|
16166
16595
|
err,
|
|
16167
16596
|
storyKey
|
|
16168
16597
|
}, "patchStoryState(checkpoint_sha, verification-failed) failed — pipeline continues"));
|
|
@@ -16172,7 +16601,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16172
16601
|
phase: "VERIFICATION_FAILED",
|
|
16173
16602
|
completedAt: new Date().toISOString()
|
|
16174
16603
|
});
|
|
16175
|
-
if (runManifest !== null) runManifest.patchStoryState(storyKey, { escalation_reason: verificationFailReason }).catch((err) => logger$
|
|
16604
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { escalation_reason: verificationFailReason }).catch((err) => logger$28.warn({
|
|
16176
16605
|
err,
|
|
16177
16606
|
storyKey
|
|
16178
16607
|
}, "patchStoryState(escalation_reason, verification-failed) failed — pipeline continues"));
|
|
@@ -16198,7 +16627,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16198
16627
|
if (autoApprove?.downgradeLastVerdict !== void 0) completeUpdate.lastVerdict = autoApprove.downgradeLastVerdict;
|
|
16199
16628
|
updateStory(storyKey, completeUpdate);
|
|
16200
16629
|
if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
|
|
16201
|
-
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$
|
|
16630
|
+
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$28.warn({
|
|
16202
16631
|
storyKey,
|
|
16203
16632
|
category: "verification-result-missing"
|
|
16204
16633
|
}, "post-COMPLETE invariant: verification_result absent in manifest");
|
|
@@ -16221,7 +16650,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16221
16650
|
const commitResult = await commitDevStoryOutput(storyKey, _capturedStoryTitle, dirty, effectiveProjectRoot);
|
|
16222
16651
|
if (commitResult.status === "no-changes") {
|
|
16223
16652
|
if (_devOutputCommitHookFailure !== void 0) {
|
|
16224
|
-
logger$
|
|
16653
|
+
logger$28.error({
|
|
16225
16654
|
storyKey,
|
|
16226
16655
|
stderr: _devOutputCommitHookFailure
|
|
16227
16656
|
}, "deliverable commit was rejected by hooks at dev-story end and was never resolved — escalating");
|
|
@@ -16254,7 +16683,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16254
16683
|
branchAdvancedSinceBaseline = headNow !== baselineHeadSha;
|
|
16255
16684
|
} catch {}
|
|
16256
16685
|
if (!branchAdvancedSinceBaseline) {
|
|
16257
|
-
logger$
|
|
16686
|
+
logger$28.warn({
|
|
16258
16687
|
storyKey,
|
|
16259
16688
|
reason: commitResult.reason
|
|
16260
16689
|
}, "dev-story produced no committable changes — escalating instead of running merge-to-main on an unchanged branch");
|
|
@@ -16272,10 +16701,10 @@ function createImplementationOrchestrator(deps) {
|
|
|
16272
16701
|
await persistState();
|
|
16273
16702
|
return "terminal";
|
|
16274
16703
|
}
|
|
16275
|
-
logger$
|
|
16704
|
+
logger$28.info({ storyKey }, "working tree clean at finalize but branch already advanced (commit-first) — proceeding to merge");
|
|
16276
16705
|
}
|
|
16277
16706
|
if (commitResult.status === "failed") {
|
|
16278
|
-
logger$
|
|
16707
|
+
logger$28.error({
|
|
16279
16708
|
storyKey,
|
|
16280
16709
|
stderr: commitResult.stderr
|
|
16281
16710
|
}, "substrate auto-commit failed — escalating story");
|
|
@@ -16296,7 +16725,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16296
16725
|
let finalizeCommitSha;
|
|
16297
16726
|
if (commitResult.status === "committed") {
|
|
16298
16727
|
finalizeCommitSha = commitResult.sha || void 0;
|
|
16299
|
-
logger$
|
|
16728
|
+
logger$28.info({
|
|
16300
16729
|
storyKey,
|
|
16301
16730
|
sha: commitResult.sha,
|
|
16302
16731
|
fileCount: commitResult.filesStaged.length
|
|
@@ -16324,7 +16753,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16324
16753
|
if (storyFilePath !== void 0) try {
|
|
16325
16754
|
Object.assign(statePatch, captureReconstructionInput(storyFilePath, storyKey, runManifest.baseDir, runManifest.runId, effectiveProjectRoot));
|
|
16326
16755
|
} catch (inputErr) {
|
|
16327
|
-
logger$
|
|
16756
|
+
logger$28.warn({
|
|
16328
16757
|
err: inputErr,
|
|
16329
16758
|
storyKey
|
|
16330
16759
|
}, "reconstruction phase-input capture failed — pipeline continues (commit_sha still recorded)");
|
|
@@ -16334,12 +16763,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
16334
16763
|
if (dispatchTelemetry.total_turns !== void 0) statePatch.total_turns = dispatchTelemetry.total_turns;
|
|
16335
16764
|
if (dispatchTelemetry.total_tokens !== void 0) statePatch.total_tokens = dispatchTelemetry.total_tokens;
|
|
16336
16765
|
} catch (telemetryErr) {
|
|
16337
|
-
logger$
|
|
16766
|
+
logger$28.warn({
|
|
16338
16767
|
err: telemetryErr,
|
|
16339
16768
|
storyKey
|
|
16340
16769
|
}, "aggregateStoryDispatchTelemetry failed — pipeline continues (commit_sha still recorded)");
|
|
16341
16770
|
}
|
|
16342
|
-
runManifest.patchStoryState(storyKey, statePatch).catch((err) => logger$
|
|
16771
|
+
runManifest.patchStoryState(storyKey, statePatch).catch((err) => logger$28.warn({
|
|
16343
16772
|
err,
|
|
16344
16773
|
storyKey
|
|
16345
16774
|
}, "patchStoryState(commit_sha/phase-input/telemetry) failed — pipeline continues"));
|
|
@@ -16367,7 +16796,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16367
16796
|
timeout: 5e3
|
|
16368
16797
|
}).trim();
|
|
16369
16798
|
if (branchSha === startSha) {
|
|
16370
|
-
logger$
|
|
16799
|
+
logger$28.warn({
|
|
16371
16800
|
storyKey,
|
|
16372
16801
|
branchSha,
|
|
16373
16802
|
startSha,
|
|
@@ -16388,7 +16817,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16388
16817
|
return "terminal";
|
|
16389
16818
|
}
|
|
16390
16819
|
} catch (gateErr) {
|
|
16391
|
-
logger$
|
|
16820
|
+
logger$28.warn({
|
|
16392
16821
|
storyKey,
|
|
16393
16822
|
err: gateErr instanceof Error ? gateErr.message : String(gateErr)
|
|
16394
16823
|
}, "merge-to-main pre-flight verification failed — proceeding with merge phase");
|
|
@@ -16406,7 +16835,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16406
16835
|
const artifactSet = new Set(artifactOnly.map(norm));
|
|
16407
16836
|
const undisclosed = mergedFiles.map(norm).filter((f$1) => !artifactSet.has(f$1) && !disclosed.has(f$1));
|
|
16408
16837
|
if (undisclosed.length > 0) {
|
|
16409
|
-
logger$
|
|
16838
|
+
logger$28.error({
|
|
16410
16839
|
storyKey,
|
|
16411
16840
|
undisclosed,
|
|
16412
16841
|
disclosed: [...disclosed]
|
|
@@ -16426,6 +16855,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
16426
16855
|
return "terminal";
|
|
16427
16856
|
}
|
|
16428
16857
|
}
|
|
16858
|
+
try {
|
|
16859
|
+
await runAcceptanceStage(storyKey, effectiveProjectRoot ?? projectRoot ?? process.cwd());
|
|
16860
|
+
} catch (stageErr) {
|
|
16861
|
+
logger$28.warn({
|
|
16862
|
+
storyKey,
|
|
16863
|
+
err: stageErr
|
|
16864
|
+
}, "A2.3: acceptance stage threw (best-effort) — claimed journeys stay unwalked");
|
|
16865
|
+
}
|
|
16429
16866
|
const finalizationMode = config.finalizationMode ?? "merge";
|
|
16430
16867
|
{
|
|
16431
16868
|
const acceptanceModeCfg = config.acceptanceMode ?? "advisory";
|
|
@@ -16443,7 +16880,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16443
16880
|
if (audit?.unrunnable !== void 0) issueLines.push(audit.unrunnable);
|
|
16444
16881
|
if (acceptanceModeCfg === "blocking") {
|
|
16445
16882
|
const verdict = violations.some((v) => v.state === "unclaimed") ? "journey-unclaimed" : audit?.unrunnable !== void 0 ? "acceptance-unrunnable" : "journey-unwalked";
|
|
16446
|
-
logger$
|
|
16883
|
+
logger$28.error({
|
|
16447
16884
|
storyKey,
|
|
16448
16885
|
epicId: epicIdA,
|
|
16449
16886
|
verdict,
|
|
@@ -16467,7 +16904,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16467
16904
|
await persistState();
|
|
16468
16905
|
return "terminal";
|
|
16469
16906
|
}
|
|
16470
|
-
logger$
|
|
16907
|
+
logger$28.warn({
|
|
16471
16908
|
storyKey,
|
|
16472
16909
|
epicId: epicIdA,
|
|
16473
16910
|
violations: issueLines
|
|
@@ -16483,7 +16920,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16483
16920
|
const TERMINAL_PHASES = ["COMPLETE", "ESCALATED"];
|
|
16484
16921
|
const isLastOfEpic = [..._stories.entries()].filter(([key]) => key !== storyKey && epicOf(key) === epicId).every(([, st]) => TERMINAL_PHASES.includes(st.phase));
|
|
16485
16922
|
if (isLastOfEpic) {
|
|
16486
|
-
logger$
|
|
16923
|
+
logger$28.info({
|
|
16487
16924
|
storyKey,
|
|
16488
16925
|
epicId,
|
|
16489
16926
|
epicGateCommand
|
|
@@ -16508,7 +16945,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16508
16945
|
gateOutput = `${e.stdout ?? ""}${e.stderr ?? ""}`.trim() || (e.message ?? String(gateCmdErr));
|
|
16509
16946
|
}
|
|
16510
16947
|
if (!gatePassed) {
|
|
16511
|
-
logger$
|
|
16948
|
+
logger$28.error({
|
|
16512
16949
|
storyKey,
|
|
16513
16950
|
epicId,
|
|
16514
16951
|
output: gateOutput.slice(0, 500)
|
|
@@ -16527,7 +16964,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16527
16964
|
await persistState();
|
|
16528
16965
|
return "terminal";
|
|
16529
16966
|
}
|
|
16530
|
-
logger$
|
|
16967
|
+
logger$28.info({
|
|
16531
16968
|
storyKey,
|
|
16532
16969
|
epicId
|
|
16533
16970
|
}, "H3.4: epic gate passed");
|
|
@@ -16572,7 +17009,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16572
17009
|
}).trim();
|
|
16573
17010
|
prUrl = ghOutput === "" ? void 0 : ghOutput;
|
|
16574
17011
|
} catch (prErr) {
|
|
16575
|
-
logger$
|
|
17012
|
+
logger$28.warn({
|
|
16576
17013
|
storyKey,
|
|
16577
17014
|
branchName,
|
|
16578
17015
|
err: prErr instanceof Error ? prErr.message.slice(0, 300) : String(prErr)
|
|
@@ -16581,7 +17018,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16581
17018
|
try {
|
|
16582
17019
|
await _worktreeManager.cleanupWorktree(storyKey, { keepBranch: true });
|
|
16583
17020
|
} catch (cleanupErr) {
|
|
16584
|
-
logger$
|
|
17021
|
+
logger$28.warn({
|
|
16585
17022
|
storyKey,
|
|
16586
17023
|
err: cleanupErr
|
|
16587
17024
|
}, "worktree removal after branch/pr finalization failed (best-effort; branch intact)");
|
|
@@ -16598,11 +17035,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
16598
17035
|
branch: branchName,
|
|
16599
17036
|
...storyDeliverableSha ? { sha: storyDeliverableSha } : {},
|
|
16600
17037
|
...prUrl !== void 0 ? { pr_url: prUrl } : {}
|
|
16601
|
-
} }).catch((err) => logger$
|
|
17038
|
+
} }).catch((err) => logger$28.warn({
|
|
16602
17039
|
err,
|
|
16603
17040
|
storyKey
|
|
16604
17041
|
}, "patchStoryState(finalization) failed — pipeline continues"));
|
|
16605
|
-
logger$
|
|
17042
|
+
logger$28.info({
|
|
16606
17043
|
storyKey,
|
|
16607
17044
|
branchName,
|
|
16608
17045
|
mode: finalizationMode,
|
|
@@ -16610,7 +17047,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16610
17047
|
}, "story finalized without self-merge — branch is the deliverable");
|
|
16611
17048
|
return "finalized";
|
|
16612
17049
|
}
|
|
16613
|
-
logger$
|
|
17050
|
+
logger$28.info({
|
|
16614
17051
|
storyKey,
|
|
16615
17052
|
branchName,
|
|
16616
17053
|
startBranch: _orchestratorStartBranch
|
|
@@ -16628,7 +17065,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16628
17065
|
});
|
|
16629
17066
|
} catch (mergeErr) {
|
|
16630
17067
|
const errMsg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
16631
|
-
logger$
|
|
17068
|
+
logger$28.error({
|
|
16632
17069
|
storyKey,
|
|
16633
17070
|
err: mergeErr
|
|
16634
17071
|
}, "merge-to-main phase threw unexpectedly — escalating story");
|
|
@@ -16652,7 +17089,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16652
17089
|
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.`);
|
|
16653
17090
|
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.`);
|
|
16654
17091
|
else issues.push(`merge conflict in ${mergeResult.conflictingFiles?.length ?? 0} file(s): ${(mergeResult.conflictingFiles ?? []).join(", ")}`);
|
|
16655
|
-
logger$
|
|
17092
|
+
logger$28.warn({
|
|
16656
17093
|
storyKey,
|
|
16657
17094
|
branchName,
|
|
16658
17095
|
reason: failReason,
|
|
@@ -16673,7 +17110,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16673
17110
|
await persistState();
|
|
16674
17111
|
return "terminal";
|
|
16675
17112
|
}
|
|
16676
|
-
logger$
|
|
17113
|
+
logger$28.info({
|
|
16677
17114
|
storyKey,
|
|
16678
17115
|
branchName
|
|
16679
17116
|
}, "merge-to-main phase completed successfully");
|
|
@@ -16692,7 +17129,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16692
17129
|
mode: "merge",
|
|
16693
17130
|
branch: branchName,
|
|
16694
17131
|
...storyDeliverableSha ? { sha: storyDeliverableSha } : {}
|
|
16695
|
-
} }).catch((err) => logger$
|
|
17132
|
+
} }).catch((err) => logger$28.warn({
|
|
16696
17133
|
err,
|
|
16697
17134
|
storyKey
|
|
16698
17135
|
}, "patchStoryState(finalization) failed — pipeline continues"));
|
|
@@ -16754,7 +17191,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16754
17191
|
"NEEDS_MAJOR_REWORK": 2
|
|
16755
17192
|
};
|
|
16756
17193
|
for (const group of batchFileGroups) {
|
|
16757
|
-
logger$
|
|
17194
|
+
logger$28.info({
|
|
16758
17195
|
storyKey,
|
|
16759
17196
|
batchIndex: group.batchIndex,
|
|
16760
17197
|
fileCount: group.files.length
|
|
@@ -16800,7 +17237,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16800
17237
|
rawOutput: lastRawOutput,
|
|
16801
17238
|
tokenUsage: aggregateTokens
|
|
16802
17239
|
};
|
|
16803
|
-
logger$
|
|
17240
|
+
logger$28.info({
|
|
16804
17241
|
storyKey,
|
|
16805
17242
|
batchCount: batchFileGroups.length,
|
|
16806
17243
|
verdict: worstVerdict,
|
|
@@ -16844,7 +17281,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16844
17281
|
storyKey,
|
|
16845
17282
|
reviewCycle: reviewCycles
|
|
16846
17283
|
})
|
|
16847
|
-
})).catch((tokenErr) => logger$
|
|
17284
|
+
})).catch((tokenErr) => logger$28.warn({
|
|
16848
17285
|
storyKey,
|
|
16849
17286
|
err: tokenErr
|
|
16850
17287
|
}, "Failed to record code-review token usage"));
|
|
@@ -16862,7 +17299,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16862
17299
|
...reviewResult.details !== void 0 ? { details: reviewResult.details } : {}
|
|
16863
17300
|
});
|
|
16864
17301
|
if (schemaValidationRetries <= MAX_SCHEMA_VALIDATION_RETRIES) {
|
|
16865
|
-
logger$
|
|
17302
|
+
logger$28.warn({
|
|
16866
17303
|
storyKey,
|
|
16867
17304
|
reviewCycles,
|
|
16868
17305
|
attempt: schemaValidationRetries,
|
|
@@ -16871,7 +17308,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16871
17308
|
previousIterationWasMalformed = true;
|
|
16872
17309
|
continue;
|
|
16873
17310
|
}
|
|
16874
|
-
logger$
|
|
17311
|
+
logger$28.warn({
|
|
16875
17312
|
storyKey,
|
|
16876
17313
|
reviewCycles,
|
|
16877
17314
|
schemaValidationRetries
|
|
@@ -16894,7 +17331,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16894
17331
|
}
|
|
16895
17332
|
if (isPhantomReview && !timeoutRetried) {
|
|
16896
17333
|
timeoutRetried = true;
|
|
16897
|
-
logger$
|
|
17334
|
+
logger$28.warn({
|
|
16898
17335
|
storyKey,
|
|
16899
17336
|
reviewCycles,
|
|
16900
17337
|
error: reviewResult.error
|
|
@@ -16924,7 +17361,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16924
17361
|
}
|
|
16925
17362
|
const isStoryFileMissing = (reviewResult.error ?? "").includes("story-file-missing");
|
|
16926
17363
|
const escalationReason = isStoryFileMissing ? "story-file-missing" : "consecutive-review-timeouts";
|
|
16927
|
-
logger$
|
|
17364
|
+
logger$28.warn({
|
|
16928
17365
|
storyKey,
|
|
16929
17366
|
reviewCycles,
|
|
16930
17367
|
error: reviewResult.error,
|
|
@@ -16949,7 +17386,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16949
17386
|
verdict = reviewResult.verdict;
|
|
16950
17387
|
issueList = reviewResult.issue_list ?? [];
|
|
16951
17388
|
if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
|
|
16952
|
-
logger$
|
|
17389
|
+
logger$28.info({
|
|
16953
17390
|
storyKey,
|
|
16954
17391
|
originalVerdict: verdict,
|
|
16955
17392
|
issuesBefore: previousIssueList.length,
|
|
@@ -16978,7 +17415,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16978
17415
|
await persistState();
|
|
16979
17416
|
if (runManifest !== null) {
|
|
16980
17417
|
const persistedVerdict = reviewResult.agentVerdict ?? verdict;
|
|
16981
|
-
runManifest.patchStoryState(storyKey, { verdict: persistedVerdict }).catch((err) => logger$
|
|
17418
|
+
runManifest.patchStoryState(storyKey, { verdict: persistedVerdict }).catch((err) => logger$28.warn({
|
|
16982
17419
|
err,
|
|
16983
17420
|
storyKey
|
|
16984
17421
|
}, "patchStoryState(verdict) failed — pipeline continues"));
|
|
@@ -16992,7 +17429,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
16992
17429
|
if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
|
|
16993
17430
|
parts.push(`${fileCount} files`);
|
|
16994
17431
|
parts.push(`${totalTokensK} tokens`);
|
|
16995
|
-
logger$
|
|
17432
|
+
logger$28.info({
|
|
16996
17433
|
storyKey,
|
|
16997
17434
|
verdict,
|
|
16998
17435
|
agentVerdict: reviewResult.agentVerdict
|
|
@@ -17055,9 +17492,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
17055
17492
|
}),
|
|
17056
17493
|
rationale: `Advisory notes from LGTM_WITH_NOTES review of ${storyKey}`
|
|
17057
17494
|
});
|
|
17058
|
-
logger$
|
|
17495
|
+
logger$28.info({ storyKey }, "Advisory notes persisted to decision store");
|
|
17059
17496
|
} catch (advisoryErr) {
|
|
17060
|
-
logger$
|
|
17497
|
+
logger$28.warn({
|
|
17061
17498
|
storyKey,
|
|
17062
17499
|
error: advisoryErr instanceof Error ? advisoryErr.message : String(advisoryErr)
|
|
17063
17500
|
}, "Failed to persist advisory notes (best-effort)");
|
|
@@ -17065,27 +17502,27 @@ function createImplementationOrchestrator(deps) {
|
|
|
17065
17502
|
if (telemetryPersistence !== void 0) try {
|
|
17066
17503
|
const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
|
|
17067
17504
|
if (turns.length > 0) {
|
|
17068
|
-
const scorer = new EfficiencyScorer(logger$
|
|
17505
|
+
const scorer = new EfficiencyScorer(logger$28);
|
|
17069
17506
|
const effScore = scorer.score(storyKey, turns);
|
|
17070
17507
|
await telemetryPersistence.storeEfficiencyScore(effScore);
|
|
17071
|
-
logger$
|
|
17508
|
+
logger$28.info({
|
|
17072
17509
|
storyKey,
|
|
17073
17510
|
compositeScore: effScore.compositeScore,
|
|
17074
17511
|
modelCount: effScore.perModelBreakdown.length
|
|
17075
17512
|
}, "Efficiency score computed and persisted");
|
|
17076
|
-
} else logger$
|
|
17513
|
+
} else logger$28.debug({ storyKey }, "No turn analysis data available — skipping efficiency scoring");
|
|
17077
17514
|
} catch (effErr) {
|
|
17078
|
-
logger$
|
|
17515
|
+
logger$28.warn({
|
|
17079
17516
|
storyKey,
|
|
17080
17517
|
error: effErr instanceof Error ? effErr.message : String(effErr)
|
|
17081
17518
|
}, "Efficiency scoring failed — story verdict unchanged");
|
|
17082
17519
|
}
|
|
17083
17520
|
if (telemetryPersistence !== void 0) try {
|
|
17084
17521
|
const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
|
|
17085
|
-
if (turns.length === 0) logger$
|
|
17522
|
+
if (turns.length === 0) logger$28.debug({ storyKey }, "No turn analysis data for telemetry categorization — skipping");
|
|
17086
17523
|
else {
|
|
17087
|
-
const categorizer = new Categorizer(logger$
|
|
17088
|
-
const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$
|
|
17524
|
+
const categorizer = new Categorizer(logger$28);
|
|
17525
|
+
const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$28);
|
|
17089
17526
|
const categoryStats = categorizer.computeCategoryStatsFromTurns(turns);
|
|
17090
17527
|
const consumerStats = consumerAnalyzer.analyzeFromTurns(turns);
|
|
17091
17528
|
await telemetryPersistence.storeCategoryStats(storyKey, categoryStats);
|
|
@@ -17093,7 +17530,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17093
17530
|
const growingCount = categoryStats.filter((c) => c.trend === "growing").length;
|
|
17094
17531
|
const topCategory = categoryStats[0]?.category ?? "none";
|
|
17095
17532
|
const topConsumer = consumerStats[0]?.consumerKey ?? "none";
|
|
17096
|
-
logger$
|
|
17533
|
+
logger$28.info({
|
|
17097
17534
|
storyKey,
|
|
17098
17535
|
topCategory,
|
|
17099
17536
|
topConsumer,
|
|
@@ -17101,7 +17538,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17101
17538
|
}, "Semantic categorization and consumer analysis complete");
|
|
17102
17539
|
}
|
|
17103
17540
|
} catch (catErr) {
|
|
17104
|
-
logger$
|
|
17541
|
+
logger$28.warn({
|
|
17105
17542
|
storyKey,
|
|
17106
17543
|
error: catErr instanceof Error ? catErr.message : String(catErr)
|
|
17107
17544
|
}, "Semantic categorization failed — story verdict unchanged");
|
|
@@ -17124,7 +17561,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17124
17561
|
filesModified: devFilesModified,
|
|
17125
17562
|
workingDirectory: effectiveProjectRoot
|
|
17126
17563
|
});
|
|
17127
|
-
logger$
|
|
17564
|
+
logger$28.debug({
|
|
17128
17565
|
storyKey,
|
|
17129
17566
|
expansion_priority: expansionResult.expansion_priority,
|
|
17130
17567
|
coverage_gaps: expansionResult.coverage_gaps.length
|
|
@@ -17137,7 +17574,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17137
17574
|
value: JSON.stringify(expansionResult)
|
|
17138
17575
|
});
|
|
17139
17576
|
} catch (expansionErr) {
|
|
17140
|
-
logger$
|
|
17577
|
+
logger$28.warn({
|
|
17141
17578
|
storyKey,
|
|
17142
17579
|
error: expansionErr instanceof Error ? expansionErr.message : String(expansionErr)
|
|
17143
17580
|
}, "Test expansion failed — story verdict unchanged");
|
|
@@ -17166,7 +17603,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17166
17603
|
await persistState();
|
|
17167
17604
|
return;
|
|
17168
17605
|
}
|
|
17169
|
-
logger$
|
|
17606
|
+
logger$28.info({
|
|
17170
17607
|
storyKey,
|
|
17171
17608
|
reviewCycles: finalReviewCycles,
|
|
17172
17609
|
issueCount: issueList.length
|
|
@@ -17232,7 +17669,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17232
17669
|
fixPrompt = assembled.prompt;
|
|
17233
17670
|
} catch {
|
|
17234
17671
|
fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
|
|
17235
|
-
logger$
|
|
17672
|
+
logger$28.warn({ storyKey }, "Failed to assemble auto-approve fix prompt, using fallback");
|
|
17236
17673
|
}
|
|
17237
17674
|
const handle = dispatcher.dispatch({
|
|
17238
17675
|
prompt: fixPrompt,
|
|
@@ -17257,9 +17694,9 @@ function createImplementationOrchestrator(deps) {
|
|
|
17257
17694
|
output: fixResult.tokenEstimate.output
|
|
17258
17695
|
} : void 0 }
|
|
17259
17696
|
});
|
|
17260
|
-
if (fixResult.status === "timeout") logger$
|
|
17697
|
+
if (fixResult.status === "timeout") logger$28.warn({ storyKey }, "Auto-approve fix timed out — approving anyway (issues were minor)");
|
|
17261
17698
|
} catch (err) {
|
|
17262
|
-
logger$
|
|
17699
|
+
logger$28.warn({
|
|
17263
17700
|
storyKey,
|
|
17264
17701
|
err
|
|
17265
17702
|
}, "Auto-approve fix dispatch failed — approving anyway (issues were minor)");
|
|
@@ -17288,7 +17725,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17288
17725
|
outcome: "retried",
|
|
17289
17726
|
cost_usd: 0,
|
|
17290
17727
|
timestamp: new Date().toISOString()
|
|
17291
|
-
}).catch((err) => logger$
|
|
17728
|
+
}).catch((err) => logger$28.warn({
|
|
17292
17729
|
err,
|
|
17293
17730
|
storyKey
|
|
17294
17731
|
}, "appendRecoveryEntry failed — pipeline continues"));
|
|
@@ -17428,7 +17865,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17428
17865
|
fixPrompt = assembled.prompt;
|
|
17429
17866
|
} catch {
|
|
17430
17867
|
fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
|
|
17431
|
-
logger$
|
|
17868
|
+
logger$28.warn({
|
|
17432
17869
|
storyKey,
|
|
17433
17870
|
taskType
|
|
17434
17871
|
}, "Failed to assemble fix prompt, using fallback");
|
|
@@ -17472,7 +17909,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17472
17909
|
if (taskType === "minor-fixes") {
|
|
17473
17910
|
const finalReviewCycles = reviewCycles + 1;
|
|
17474
17911
|
const downgradedVerdict = "LGTM_WITH_NOTES";
|
|
17475
|
-
logger$
|
|
17912
|
+
logger$28.warn({
|
|
17476
17913
|
storyKey,
|
|
17477
17914
|
reviewCycles: finalReviewCycles,
|
|
17478
17915
|
issueCount: issueList.length
|
|
@@ -17492,7 +17929,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17492
17929
|
keepReviewing = false;
|
|
17493
17930
|
return;
|
|
17494
17931
|
}
|
|
17495
|
-
logger$
|
|
17932
|
+
logger$28.warn({
|
|
17496
17933
|
storyKey,
|
|
17497
17934
|
taskType
|
|
17498
17935
|
}, "Fix dispatch timed out — escalating story");
|
|
@@ -17514,7 +17951,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17514
17951
|
}
|
|
17515
17952
|
if (fixResult.status === "failed") {
|
|
17516
17953
|
if (isMajorRework) {
|
|
17517
|
-
logger$
|
|
17954
|
+
logger$28.warn({
|
|
17518
17955
|
storyKey,
|
|
17519
17956
|
exitCode: fixResult.exitCode
|
|
17520
17957
|
}, "Major rework dispatch failed — escalating story");
|
|
@@ -17534,7 +17971,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17534
17971
|
await persistState();
|
|
17535
17972
|
return;
|
|
17536
17973
|
}
|
|
17537
|
-
logger$
|
|
17974
|
+
logger$28.warn({
|
|
17538
17975
|
storyKey,
|
|
17539
17976
|
taskType,
|
|
17540
17977
|
exitCode: fixResult.exitCode
|
|
@@ -17542,7 +17979,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17542
17979
|
}
|
|
17543
17980
|
if (isMajorRework) replaceDevStorySignals(fixResult.parsed);
|
|
17544
17981
|
} catch (err) {
|
|
17545
|
-
logger$
|
|
17982
|
+
logger$28.warn({
|
|
17546
17983
|
storyKey,
|
|
17547
17984
|
taskType,
|
|
17548
17985
|
err
|
|
@@ -17611,7 +18048,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17611
18048
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
17612
18049
|
}
|
|
17613
18050
|
}).catch((err) => {
|
|
17614
|
-
logger$
|
|
18051
|
+
logger$28.warn({ err }, "interactive prompt failed during auth-failure halt — halting anyway");
|
|
17615
18052
|
});
|
|
17616
18053
|
for (const [key, state] of _stories) if (state.phase === "PENDING" && key !== triggeredStoryKey) {
|
|
17617
18054
|
updateStory(key, {
|
|
@@ -17624,7 +18061,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17624
18061
|
escalation_reason: "auth-failure-halt"
|
|
17625
18062
|
}).catch(() => {});
|
|
17626
18063
|
}
|
|
17627
|
-
logger$
|
|
18064
|
+
logger$28.error({
|
|
17628
18065
|
runId,
|
|
17629
18066
|
triggeredStoryKey,
|
|
17630
18067
|
matchedSignature
|
|
@@ -17658,7 +18095,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17658
18095
|
eventBus.emit("decision:halt-skipped-non-interactive", payload);
|
|
17659
18096
|
}
|
|
17660
18097
|
}).catch((err) => {
|
|
17661
|
-
logger$
|
|
18098
|
+
logger$28.warn({ err }, "interactive prompt failed during cost-ceiling halt — continuing with default action");
|
|
17662
18099
|
});
|
|
17663
18100
|
} else eventBus.emit("decision:autonomous", {
|
|
17664
18101
|
runId,
|
|
@@ -17686,7 +18123,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17686
18123
|
severity: routeResult.severity
|
|
17687
18124
|
});
|
|
17688
18125
|
_budgetExhausted = true;
|
|
17689
|
-
logger$
|
|
18126
|
+
logger$28.warn({
|
|
17690
18127
|
skipped: allSkipped.length,
|
|
17691
18128
|
cumulative: result.cumulative,
|
|
17692
18129
|
ceiling: result.ceiling,
|
|
@@ -17705,7 +18142,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17705
18142
|
const completedStoryKeys = [];
|
|
17706
18143
|
for (const storyKey of group) {
|
|
17707
18144
|
if (_shutdownRequested) {
|
|
17708
|
-
logger$
|
|
18145
|
+
logger$28.info({ storyKey }, "shutdown requested — skipping dispatch");
|
|
17709
18146
|
return;
|
|
17710
18147
|
}
|
|
17711
18148
|
if (runManifest !== null && runManifest !== void 0) try {
|
|
@@ -17728,7 +18165,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17728
18165
|
}
|
|
17729
18166
|
}
|
|
17730
18167
|
} catch (err) {
|
|
17731
|
-
logger$
|
|
18168
|
+
logger$28.debug({ err }, "Cost ceiling check failed — proceeding without enforcement");
|
|
17732
18169
|
}
|
|
17733
18170
|
let optimizationDirectives;
|
|
17734
18171
|
if (telemetryAdvisor !== void 0 && completedStoryKeys.length > 0) try {
|
|
@@ -17736,13 +18173,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
17736
18173
|
const directives = telemetryAdvisor.formatOptimizationDirectives(recs);
|
|
17737
18174
|
if (directives.length > 0) {
|
|
17738
18175
|
optimizationDirectives = directives;
|
|
17739
|
-
logger$
|
|
18176
|
+
logger$28.debug({
|
|
17740
18177
|
storyKey,
|
|
17741
18178
|
directiveCount: recs.filter((r) => r.severity !== "info").length
|
|
17742
18179
|
}, "Optimization directives ready for dispatch");
|
|
17743
18180
|
}
|
|
17744
18181
|
} catch (err) {
|
|
17745
|
-
logger$
|
|
18182
|
+
logger$28.debug({
|
|
17746
18183
|
err,
|
|
17747
18184
|
storyKey
|
|
17748
18185
|
}, "Failed to fetch optimization directives — proceeding without");
|
|
@@ -17866,7 +18303,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17866
18303
|
recommendedAction: "serialize"
|
|
17867
18304
|
});
|
|
17868
18305
|
} catch {}
|
|
17869
|
-
logger$
|
|
18306
|
+
logger$28.info({
|
|
17870
18307
|
storyKeys: evt.storyKeys,
|
|
17871
18308
|
collisionPaths: evt.collisionPaths
|
|
17872
18309
|
}, "Cross-story file collision detected — serializing affected groups to prevent race conditions");
|
|
@@ -17879,7 +18316,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17879
18316
|
mergedGroupMap.set(root2, [...existing, ...group]);
|
|
17880
18317
|
}
|
|
17881
18318
|
const result = [...mergedGroupMap.values()];
|
|
17882
|
-
logger$
|
|
18319
|
+
logger$28.info({
|
|
17883
18320
|
originalGroupCount: batchGroups.length,
|
|
17884
18321
|
mergedGroupCount: result.length,
|
|
17885
18322
|
collisionCount
|
|
@@ -17923,7 +18360,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17923
18360
|
async function shutdownGracefully(reason, signal) {
|
|
17924
18361
|
if (_shutdownRequested) return;
|
|
17925
18362
|
_shutdownRequested = true;
|
|
17926
|
-
logger$
|
|
18363
|
+
logger$28.info({
|
|
17927
18364
|
reason,
|
|
17928
18365
|
signal
|
|
17929
18366
|
}, "Graceful shutdown initiated — stopping new dispatches");
|
|
@@ -17933,8 +18370,8 @@ function createImplementationOrchestrator(deps) {
|
|
|
17933
18370
|
run_status: "stopped",
|
|
17934
18371
|
stopped_reason: reason,
|
|
17935
18372
|
stopped_at: new Date().toISOString()
|
|
17936
|
-
}).catch((err) => logger$
|
|
17937
|
-
if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$
|
|
18373
|
+
}).catch((err) => logger$28.warn({ err }, "patchRunStatus failed during shutdown (best-effort)"));
|
|
18374
|
+
if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$28.warn({ err }, "updatePipelineRun(stopped) failed during shutdown (best-effort)"));
|
|
17938
18375
|
const activePhases = [
|
|
17939
18376
|
"PENDING",
|
|
17940
18377
|
"IN_STORY_CREATION",
|
|
@@ -17945,7 +18382,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
17945
18382
|
"CHECKPOINT"
|
|
17946
18383
|
];
|
|
17947
18384
|
const cancellations = [];
|
|
17948
|
-
for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$
|
|
18385
|
+
for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$28.warn({
|
|
17949
18386
|
err,
|
|
17950
18387
|
storyKey
|
|
17951
18388
|
}, "wg_stories → cancelled failed during shutdown (best-effort)")));
|
|
@@ -17954,11 +18391,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
17954
18391
|
}
|
|
17955
18392
|
async function run(storyKeys) {
|
|
17956
18393
|
if (_state === "RUNNING" || _state === "PAUSED") {
|
|
17957
|
-
logger$
|
|
18394
|
+
logger$28.warn({ state: _state }, "run() called while orchestrator is already running or paused — ignoring");
|
|
17958
18395
|
return getStatus();
|
|
17959
18396
|
}
|
|
17960
18397
|
if (_state === "COMPLETE") {
|
|
17961
|
-
logger$
|
|
18398
|
+
logger$28.warn({ state: _state }, "run() called on a COMPLETE orchestrator — ignoring");
|
|
17962
18399
|
return getStatus();
|
|
17963
18400
|
}
|
|
17964
18401
|
_state = "RUNNING";
|
|
@@ -17973,15 +18410,15 @@ function createImplementationOrchestrator(deps) {
|
|
|
17973
18410
|
"pipe"
|
|
17974
18411
|
]
|
|
17975
18412
|
}).trim();
|
|
17976
|
-
logger$
|
|
18413
|
+
logger$28.info({ orchestratorStartBranch: _orchestratorStartBranch }, "Captured orchestrator start branch for merge-to-main");
|
|
17977
18414
|
} catch (branchErr) {
|
|
17978
18415
|
if (config.noWorktree !== true) {
|
|
17979
|
-
logger$
|
|
18416
|
+
logger$28.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.");
|
|
17980
18417
|
_state = "FAILED";
|
|
17981
18418
|
_completedAt = new Date().toISOString();
|
|
17982
18419
|
return getStatus();
|
|
17983
18420
|
}
|
|
17984
|
-
logger$
|
|
18421
|
+
logger$28.warn({ err: branchErr }, "Failed to capture orchestrator start branch — merge-to-main will skip worktree integration (--no-worktree run)");
|
|
17985
18422
|
}
|
|
17986
18423
|
for (const key of storyKeys) {
|
|
17987
18424
|
const pendingState = {
|
|
@@ -18024,13 +18461,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
18024
18461
|
await persistState();
|
|
18025
18462
|
recordProgress();
|
|
18026
18463
|
if (config.enableHeartbeat) startHeartbeat();
|
|
18027
|
-
if (_orchestratorStartBranch !== void 0 && runManifest !== null) runManifest.patchRunStatus({ orchestrator_start_branch: _orchestratorStartBranch }).catch((err) => logger$
|
|
18464
|
+
if (_orchestratorStartBranch !== void 0 && runManifest !== null) runManifest.patchRunStatus({ orchestrator_start_branch: _orchestratorStartBranch }).catch((err) => logger$28.warn({ err }, "Failed to persist orchestrator_start_branch to manifest (best-effort)"));
|
|
18028
18465
|
const _startupTimings = {};
|
|
18029
18466
|
if (projectRoot !== void 0) {
|
|
18030
18467
|
const seedStart = Date.now();
|
|
18031
18468
|
const seedResult = await seedMethodologyContext(db, projectRoot);
|
|
18032
18469
|
_startupTimings.seedMethodologyMs = Date.now() - seedStart;
|
|
18033
|
-
if (seedResult.decisionsCreated > 0) logger$
|
|
18470
|
+
if (seedResult.decisionsCreated > 0) logger$28.info({
|
|
18034
18471
|
decisionsCreated: seedResult.decisionsCreated,
|
|
18035
18472
|
skippedCategories: seedResult.skippedCategories,
|
|
18036
18473
|
durationMs: _startupTimings.seedMethodologyMs
|
|
@@ -18040,12 +18477,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
18040
18477
|
const ingestStart = Date.now();
|
|
18041
18478
|
try {
|
|
18042
18479
|
const ingestResult = await autoIngestEpicsDependencies(db, projectRoot);
|
|
18043
|
-
if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$
|
|
18480
|
+
if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$28.info({
|
|
18044
18481
|
...ingestResult,
|
|
18045
18482
|
durationMs: Date.now() - ingestStart
|
|
18046
18483
|
}, "Auto-ingested stories and dependencies from epics document");
|
|
18047
18484
|
} catch (err) {
|
|
18048
|
-
logger$
|
|
18485
|
+
logger$28.debug({ err }, "Auto-ingest from epics document skipped — work graph may be unavailable");
|
|
18049
18486
|
}
|
|
18050
18487
|
}
|
|
18051
18488
|
const sigtermHandler = () => {
|
|
@@ -18059,7 +18496,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18059
18496
|
try {
|
|
18060
18497
|
if (ingestionServer !== void 0) {
|
|
18061
18498
|
if (telemetryPersistence !== void 0) try {
|
|
18062
|
-
const pipelineLogger = logger$
|
|
18499
|
+
const pipelineLogger = logger$28;
|
|
18063
18500
|
const telemetryPipeline = new TelemetryPipeline({
|
|
18064
18501
|
normalizer: new TelemetryNormalizer(pipelineLogger),
|
|
18065
18502
|
turnAnalyzer: new TurnAnalyzer(pipelineLogger),
|
|
@@ -18071,14 +18508,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
18071
18508
|
persistence: telemetryPersistence
|
|
18072
18509
|
});
|
|
18073
18510
|
ingestionServer.setPipeline(telemetryPipeline);
|
|
18074
|
-
logger$
|
|
18511
|
+
logger$28.info("TelemetryPipeline wired to IngestionServer");
|
|
18075
18512
|
} catch (pipelineErr) {
|
|
18076
|
-
logger$
|
|
18513
|
+
logger$28.warn({ err: pipelineErr }, "Failed to create TelemetryPipeline — continuing without analysis pipeline");
|
|
18077
18514
|
}
|
|
18078
|
-
await ingestionServer.start().catch((err) => logger$
|
|
18515
|
+
await ingestionServer.start().catch((err) => logger$28.warn({ err }, "IngestionServer.start() failed — continuing without telemetry (best-effort)"));
|
|
18079
18516
|
try {
|
|
18080
18517
|
_otlpEndpoint = ingestionServer.getOtlpEnvVars().OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
18081
|
-
logger$
|
|
18518
|
+
logger$28.info({ otlpEndpoint: _otlpEndpoint }, "OTLP telemetry ingestion active");
|
|
18082
18519
|
} catch {}
|
|
18083
18520
|
}
|
|
18084
18521
|
const interfaceContractDecisions = await getDecisionsByCategory(db, "interface-contract");
|
|
@@ -18104,12 +18541,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
18104
18541
|
const conflictDetectStart = Date.now();
|
|
18105
18542
|
const { batches, edges: contractEdges } = detectConflictGroupsWithContracts(storyKeys, { moduleMap: pack.manifest.conflictGroups }, contractDeclarations);
|
|
18106
18543
|
_startupTimings.conflictDetectMs = Date.now() - conflictDetectStart;
|
|
18107
|
-
if (contractEdges.length > 0) logger$
|
|
18544
|
+
if (contractEdges.length > 0) logger$28.info({
|
|
18108
18545
|
contractEdges,
|
|
18109
18546
|
edgeCount: contractEdges.length
|
|
18110
18547
|
}, "Contract dependency edges detected — applying contract-aware dispatch ordering");
|
|
18111
|
-
wgRepo.addContractDependencies(contractEdges).catch((err) => logger$
|
|
18112
|
-
logger$
|
|
18548
|
+
wgRepo.addContractDependencies(contractEdges).catch((err) => logger$28.warn({ err }, "contract dep persistence failed (best-effort)"));
|
|
18549
|
+
logger$28.info({
|
|
18113
18550
|
storyCount: storyKeys.length,
|
|
18114
18551
|
groupCount: batches.reduce((sum, b) => sum + b.length, 0),
|
|
18115
18552
|
batchCount: batches.length,
|
|
@@ -18119,7 +18556,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18119
18556
|
groups: batch.map((g) => g.join(","))
|
|
18120
18557
|
}))
|
|
18121
18558
|
}, "Orchestrator starting");
|
|
18122
|
-
logger$
|
|
18559
|
+
logger$28.info({
|
|
18123
18560
|
storyCount: storyKeys.length,
|
|
18124
18561
|
conflictGroups: batches.length,
|
|
18125
18562
|
maxConcurrency: config.maxConcurrency
|
|
@@ -18140,7 +18577,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18140
18577
|
exitCode,
|
|
18141
18578
|
output: truncatedOutput
|
|
18142
18579
|
});
|
|
18143
|
-
logger$
|
|
18580
|
+
logger$28.error({
|
|
18144
18581
|
exitCode,
|
|
18145
18582
|
reason: preFlightResult.reason
|
|
18146
18583
|
}, "Pre-flight build check failed — aborting pipeline before any story dispatch");
|
|
@@ -18149,19 +18586,19 @@ function createImplementationOrchestrator(deps) {
|
|
|
18149
18586
|
await persistState();
|
|
18150
18587
|
return getStatus();
|
|
18151
18588
|
}
|
|
18152
|
-
if (preFlightResult.status !== "skipped") logger$
|
|
18589
|
+
if (preFlightResult.status !== "skipped") logger$28.info("Pre-flight build check passed");
|
|
18153
18590
|
}
|
|
18154
|
-
logger$
|
|
18591
|
+
logger$28.info(_startupTimings, "Orchestrator startup timings (ms)");
|
|
18155
18592
|
const totalGroups = batches.reduce((sum, b) => sum + b.length, 0);
|
|
18156
18593
|
const actualConcurrency = Math.min(config.maxConcurrency, totalGroups);
|
|
18157
18594
|
if (actualConcurrency > 1 && projectRoot !== void 0) try {
|
|
18158
18595
|
_packageSnapshot = capturePackageSnapshot({ projectRoot });
|
|
18159
|
-
logger$
|
|
18596
|
+
logger$28.info({
|
|
18160
18597
|
fileCount: _packageSnapshot.files.size,
|
|
18161
18598
|
installCommand: _packageSnapshot.installCommand
|
|
18162
18599
|
}, "Package snapshot captured for concurrent story protection");
|
|
18163
18600
|
} catch (snapErr) {
|
|
18164
|
-
logger$
|
|
18601
|
+
logger$28.warn({ err: snapErr }, "Failed to capture package snapshot — continuing without protection");
|
|
18165
18602
|
}
|
|
18166
18603
|
try {
|
|
18167
18604
|
for (const rawBatchGroups of batches) {
|
|
@@ -18186,14 +18623,14 @@ function createImplementationOrchestrator(deps) {
|
|
|
18186
18623
|
manifest: runManifest,
|
|
18187
18624
|
adapter: db
|
|
18188
18625
|
});
|
|
18189
|
-
if (!recoveryResult.noStale) logger$
|
|
18626
|
+
if (!recoveryResult.noStale) logger$28.info({
|
|
18190
18627
|
recovered: recoveryResult.recovered,
|
|
18191
18628
|
stillFailed: recoveryResult.stillFailed,
|
|
18192
18629
|
recoveredCount: recoveryResult.recovered.length,
|
|
18193
18630
|
stillFailedCount: recoveryResult.stillFailed.length
|
|
18194
18631
|
}, "Cross-story race recovery complete");
|
|
18195
18632
|
} catch (recoveryErr) {
|
|
18196
|
-
logger$
|
|
18633
|
+
logger$28.warn({ err: recoveryErr }, "Cross-story race recovery failed (non-fatal) — pipeline continues");
|
|
18197
18634
|
}
|
|
18198
18635
|
}
|
|
18199
18636
|
}
|
|
@@ -18202,7 +18639,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18202
18639
|
_state = "FAILED";
|
|
18203
18640
|
_completedAt = new Date().toISOString();
|
|
18204
18641
|
await persistState();
|
|
18205
|
-
logger$
|
|
18642
|
+
logger$28.error({ err }, "Orchestrator failed with unhandled error");
|
|
18206
18643
|
return getStatus();
|
|
18207
18644
|
}
|
|
18208
18645
|
stopHeartbeat();
|
|
@@ -18212,7 +18649,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18212
18649
|
const totalDeclarations = contractDeclarations.length;
|
|
18213
18650
|
const currentSprintDeclarations = contractDeclarations.filter((d) => storyKeys.includes(d.storyKey));
|
|
18214
18651
|
const stalePruned = totalDeclarations - currentSprintDeclarations.length;
|
|
18215
|
-
if (stalePruned > 0) logger$
|
|
18652
|
+
if (stalePruned > 0) logger$28.info({
|
|
18216
18653
|
stalePruned,
|
|
18217
18654
|
remaining: currentSprintDeclarations.length
|
|
18218
18655
|
}, "Pruned stale contract declarations from previous epics");
|
|
@@ -18226,11 +18663,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
18226
18663
|
contractName: mismatch.contractName,
|
|
18227
18664
|
mismatchDescription: mismatch.mismatchDescription
|
|
18228
18665
|
});
|
|
18229
|
-
logger$
|
|
18666
|
+
logger$28.warn({
|
|
18230
18667
|
mismatchCount: mismatches.length,
|
|
18231
18668
|
mismatches
|
|
18232
18669
|
}, "Post-sprint contract verification found mismatches — manual review required");
|
|
18233
|
-
} else if (currentSprintDeclarations.length > 0) logger$
|
|
18670
|
+
} else if (currentSprintDeclarations.length > 0) logger$28.info("Post-sprint contract verification passed — all declared contracts satisfied");
|
|
18234
18671
|
eventBus.emit("pipeline:contract-verification-summary", {
|
|
18235
18672
|
verified: currentSprintDeclarations.length,
|
|
18236
18673
|
stalePruned,
|
|
@@ -18238,7 +18675,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18238
18675
|
verdict: mismatches.length === 0 ? "pass" : "fail"
|
|
18239
18676
|
});
|
|
18240
18677
|
} catch (err) {
|
|
18241
|
-
logger$
|
|
18678
|
+
logger$28.error({ err }, "Post-sprint contract verification threw an error — skipping");
|
|
18242
18679
|
}
|
|
18243
18680
|
if (projectRoot !== void 0) try {
|
|
18244
18681
|
const indicators = checkProfileStaleness(projectRoot);
|
|
@@ -18248,15 +18685,15 @@ function createImplementationOrchestrator(deps) {
|
|
|
18248
18685
|
message,
|
|
18249
18686
|
indicators
|
|
18250
18687
|
});
|
|
18251
|
-
logger$
|
|
18688
|
+
logger$28.warn({ indicators }, message);
|
|
18252
18689
|
}
|
|
18253
18690
|
} catch (err) {
|
|
18254
|
-
logger$
|
|
18691
|
+
logger$28.debug({ err }, "Profile staleness check failed (best-effort)");
|
|
18255
18692
|
}
|
|
18256
18693
|
try {
|
|
18257
18694
|
await auditJourneyCoverage({ final: true }, { persist: true });
|
|
18258
18695
|
} catch (err) {
|
|
18259
|
-
logger$
|
|
18696
|
+
logger$28.warn({ err }, "A0.3: run-end coverage sweep failed (best-effort)");
|
|
18260
18697
|
}
|
|
18261
18698
|
let completed = 0;
|
|
18262
18699
|
let escalated = 0;
|
|
@@ -18275,7 +18712,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18275
18712
|
} finally {
|
|
18276
18713
|
process.off("SIGTERM", sigtermHandler);
|
|
18277
18714
|
process.off("SIGINT", sigintHandler);
|
|
18278
|
-
if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$
|
|
18715
|
+
if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$28.warn({ err }, "IngestionServer.stop() failed (best-effort)"));
|
|
18279
18716
|
}
|
|
18280
18717
|
}
|
|
18281
18718
|
function pause() {
|
|
@@ -18284,7 +18721,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18284
18721
|
_pauseGate = createPauseGate();
|
|
18285
18722
|
_state = "PAUSED";
|
|
18286
18723
|
eventBus.emit("orchestrator:paused", {});
|
|
18287
|
-
logger$
|
|
18724
|
+
logger$28.info("Orchestrator paused");
|
|
18288
18725
|
}
|
|
18289
18726
|
function resume() {
|
|
18290
18727
|
if (_state !== "PAUSED") return;
|
|
@@ -18295,7 +18732,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
18295
18732
|
}
|
|
18296
18733
|
_state = "RUNNING";
|
|
18297
18734
|
eventBus.emit("orchestrator:resumed", {});
|
|
18298
|
-
logger$
|
|
18735
|
+
logger$28.info("Orchestrator resumed");
|
|
18299
18736
|
}
|
|
18300
18737
|
return {
|
|
18301
18738
|
run,
|
|
@@ -35387,16 +35824,16 @@ var require_ajv = __commonJS({ "node_modules/ajv/lib/ajv.js"(exports, module) {
|
|
|
35387
35824
|
return metaOpts;
|
|
35388
35825
|
}
|
|
35389
35826
|
function setLogger(self) {
|
|
35390
|
-
var logger$
|
|
35391
|
-
if (logger$
|
|
35827
|
+
var logger$28 = self._opts.logger;
|
|
35828
|
+
if (logger$28 === false) self.logger = {
|
|
35392
35829
|
log: noop,
|
|
35393
35830
|
warn: noop,
|
|
35394
35831
|
error: noop
|
|
35395
35832
|
};
|
|
35396
35833
|
else {
|
|
35397
|
-
if (logger$
|
|
35398
|
-
if (!(typeof logger$
|
|
35399
|
-
self.logger = logger$
|
|
35834
|
+
if (logger$28 === void 0) logger$28 = console;
|
|
35835
|
+
if (!(typeof logger$28 == "object" && logger$28.log && logger$28.warn && logger$28.error)) throw new Error("logger must implement log, warn and error methods");
|
|
35836
|
+
self.logger = logger$28;
|
|
35400
35837
|
}
|
|
35401
35838
|
}
|
|
35402
35839
|
function noop() {}
|
|
@@ -46493,6 +46930,35 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
|
|
|
46493
46930
|
...payload.prUrl !== void 0 ? { pr_url: payload.prUrl } : {}
|
|
46494
46931
|
});
|
|
46495
46932
|
});
|
|
46933
|
+
eventBus.on("orchestrator:acceptance-started", (payload) => {
|
|
46934
|
+
ndjsonEmitter.emit({
|
|
46935
|
+
type: "acceptance:started",
|
|
46936
|
+
ts: new Date().toISOString(),
|
|
46937
|
+
key: payload.storyKey,
|
|
46938
|
+
journeys: payload.journeys
|
|
46939
|
+
});
|
|
46940
|
+
});
|
|
46941
|
+
eventBus.on("orchestrator:acceptance-rendered", (payload) => {
|
|
46942
|
+
ndjsonEmitter.emit({
|
|
46943
|
+
type: "acceptance:rendered",
|
|
46944
|
+
ts: new Date().toISOString(),
|
|
46945
|
+
key: payload.storyKey,
|
|
46946
|
+
surface: payload.surface,
|
|
46947
|
+
status: payload.status,
|
|
46948
|
+
artifacts_dir: payload.artifactsDir,
|
|
46949
|
+
artifacts: payload.artifacts,
|
|
46950
|
+
...payload.error !== void 0 ? { error: payload.error } : {}
|
|
46951
|
+
});
|
|
46952
|
+
});
|
|
46953
|
+
eventBus.on("orchestrator:acceptance-verdict", (payload) => {
|
|
46954
|
+
ndjsonEmitter.emit({
|
|
46955
|
+
type: "acceptance:verdict",
|
|
46956
|
+
ts: new Date().toISOString(),
|
|
46957
|
+
key: payload.storyKey,
|
|
46958
|
+
journey: payload.journeyId,
|
|
46959
|
+
verdicts: payload.verdicts
|
|
46960
|
+
});
|
|
46961
|
+
});
|
|
46496
46962
|
eventBus.on("orchestrator:acceptance-coverage", (payload) => {
|
|
46497
46963
|
ndjsonEmitter.emit({
|
|
46498
46964
|
type: "acceptance:coverage",
|
|
@@ -48255,7 +48721,7 @@ async function runFullPipeline(options) {
|
|
|
48255
48721
|
*/
|
|
48256
48722
|
async function emitPreDispatchVersionAdvisory(currentVersion) {
|
|
48257
48723
|
if (process.env["SUBSTRATE_NO_UPDATE_CHECK"] === "1") return;
|
|
48258
|
-
const { createVersionManager } = await import("./version-manager-impl-
|
|
48724
|
+
const { createVersionManager } = await import("./version-manager-impl-Cc7yx4i5.js");
|
|
48259
48725
|
const vm = createVersionManager();
|
|
48260
48726
|
const result = await vm.checkForUpdates(true);
|
|
48261
48727
|
const gap = classifyVersionGap(currentVersion, result.latestVersion);
|
|
@@ -48362,4 +48828,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
|
|
|
48362
48828
|
|
|
48363
48829
|
//#endregion
|
|
48364
48830
|
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 };
|
|
48365
|
-
//# sourceMappingURL=run-
|
|
48831
|
+
//# sourceMappingURL=run-DsjRvAd4.js.map
|