substrate-ai 0.20.148 → 0.20.149

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.
@@ -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-Aqc5cghP.js";
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-ByQadq3J.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, 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, createPipelineRun, createRequirement, createStderrLogger, 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-CZk5SeSt.js";
5
- import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-D6NAZgt8.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-C2CAZDep.js";
5
+ import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-knD2uWkz.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-BLkX0iE_.js";
8
+ import { runInteractivePrompt } from "./interactive-prompt-CMBlj6UF.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";
@@ -15,14 +15,12 @@ import yaml from "js-yaml";
15
15
  import * as actualFS from "node:fs";
16
16
  import { accessSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
17
17
  import { exec, execFile, execFileSync, execSync, spawn } from "node:child_process";
18
- import * as path$5 from "node:path";
19
- import * as path$4 from "node:path";
20
18
  import * as path$2 from "node:path";
21
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";
22
20
  import { tmpdir } from "node:os";
23
21
  import { createHash, randomUUID } from "node:crypto";
24
22
  import { z } from "zod";
25
- import { access as access$1, copyFile, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, rename, rm, stat as stat$1, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
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";
26
24
  import { existsSync as existsSync$1, lstatSync, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdir as readdir$2, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "fs";
27
25
  import { promisify } from "node:util";
28
26
  import { fileURLToPath } from "node:url";
@@ -34,780 +32,6 @@ import { channel, tracingChannel } from "node:diagnostics_channel";
34
32
  import Stream from "node:stream";
35
33
  import { StringDecoder } from "node:string_decoder";
36
34
 
37
- //#region packages/core/dist/git/git-utils.js
38
- const MIN_GIT_MAJOR = 2;
39
- const MIN_GIT_MINOR = 20;
40
- /**
41
- * Spawn a git subprocess with the given args.
42
- *
43
- * @param args - Arguments to pass to git (e.g., ['worktree', 'add', ...])
44
- * @param options - Optional spawn options (cwd, env)
45
- * @returns - Object with stdout, stderr, and exit code
46
- */
47
- function spawnGit(args, options) {
48
- return new Promise((resolve$6) => {
49
- const proc$1 = spawn("git", args, {
50
- cwd: options?.cwd,
51
- env: options?.env ?? process.env,
52
- stdio: [
53
- "ignore",
54
- "pipe",
55
- "pipe"
56
- ]
57
- });
58
- let stdout = "";
59
- let stderr = "";
60
- proc$1.stdout?.on("data", (chunk) => {
61
- stdout += chunk.toString();
62
- });
63
- proc$1.stderr?.on("data", (chunk) => {
64
- stderr += chunk.toString();
65
- });
66
- proc$1.on("close", (code) => {
67
- resolve$6({
68
- stdout: stdout.trim(),
69
- stderr: stderr.trim(),
70
- code: code ?? 1
71
- });
72
- });
73
- proc$1.on("error", (err) => {
74
- resolve$6({
75
- stdout: "",
76
- stderr: err.message,
77
- code: 1
78
- });
79
- });
80
- });
81
- }
82
- /**
83
- * Get the installed git version string.
84
- *
85
- * @returns Version string like "2.42.0"
86
- * @throws Error if git is not installed or version cannot be parsed
87
- */
88
- async function getGitVersion() {
89
- const result = await spawnGit(["--version"]);
90
- if (result.code !== 0) throw new Error(`git --version failed: ${result.stderr}`);
91
- const match$2 = /git version\s+(\d+\.\d+(?:\.\d+)?)/.exec(result.stdout);
92
- if (match$2 === null || match$2[1] === void 0) throw new Error(`Unable to parse git version from output: "${result.stdout}"`);
93
- return match$2[1];
94
- }
95
- /**
96
- * Parse a git version string into major/minor/patch components.
97
- *
98
- * @param versionString - Version string like "2.42.0" or "2.20"
99
- * @returns - Parsed version components
100
- */
101
- function parseGitVersion(versionString) {
102
- const parts = versionString.split(".").map(Number);
103
- return {
104
- major: parts[0] ?? 0,
105
- minor: parts[1] ?? 0,
106
- patch: parts[2] ?? 0
107
- };
108
- }
109
- /**
110
- * Check if the given git version string is >= 2.20.0.
111
- *
112
- * @param version - Version string like "2.42.0"
113
- * @returns - true if version >= 2.20.0
114
- */
115
- function isGitVersionSupported(version) {
116
- const { major, minor } = parseGitVersion(version);
117
- if (major > MIN_GIT_MAJOR) return true;
118
- if (major === MIN_GIT_MAJOR && minor >= MIN_GIT_MINOR) return true;
119
- return false;
120
- }
121
- /**
122
- * Verify that git is installed and version >= 2.20.
123
- *
124
- * @throws Error with clear message if git is not installed or too old
125
- */
126
- async function verifyGitVersion() {
127
- let version;
128
- try {
129
- version = await getGitVersion();
130
- } catch (err) {
131
- throw new Error(`git is not installed or could not be executed. Please install git 2.20 or newer. Details: ${String(err)}`);
132
- }
133
- if (!isGitVersionSupported(version)) {
134
- const { major, minor, patch } = parseGitVersion(version);
135
- throw new Error(`Git version ${major}.${minor}.${patch} is too old. Substrate requires git 2.20 or newer. Please upgrade git: https://git-scm.com/downloads`);
136
- }
137
- }
138
- /**
139
- * Decide whether a registered worktree from a prior dispatch can be reclaimed
140
- * for a fresh re-run. Safe only when there is nothing to lose: no uncommitted
141
- * changes AND no commits on the branch beyond the base branch. A negative
142
- * `commitsAhead` means the ahead-count could not be determined → not safe.
143
- *
144
- * Pure + exported for testing (the git I/O that produces the inputs lives in
145
- * createWorktree).
146
- */
147
- function decideWorktreeReclaim(hasUncommittedChanges, commitsAhead, baseBranch) {
148
- if (hasUncommittedChanges) return {
149
- safe: false,
150
- reason: "it has uncommitted changes that are NOT on the branch"
151
- };
152
- if (commitsAhead > 0) return {
153
- safe: false,
154
- reason: `its branch has ${String(commitsAhead)} commit(s) beyond ${baseBranch}`
155
- };
156
- if (commitsAhead < 0) return {
157
- safe: false,
158
- reason: "its state could not be verified as safe to discard"
159
- };
160
- return { safe: true };
161
- }
162
- /**
163
- * Decide whether removing a story worktree AND deleting its branch is safe
164
- * (H0.3, field findings #17/#19). Unsafe when:
165
- * - the worktree has uncommitted changes (removal destroys the only copy), or
166
- * - the branch carries commits not reachable from the project's current HEAD
167
- * (branch -D destroys them — this is where H0.1's wip checkpoints live), or
168
- * - either state could not be determined (negative unmergedCommits).
169
- *
170
- * Pure + exported for testing (mirrors decideWorktreeReclaim; the git I/O that
171
- * produces the inputs lives in inspectWorktreeRemovalSafety).
172
- */
173
- function decideWorktreeRemoval(hasUncommittedChanges, uncommittedFiles, unmergedCommits, branchName) {
174
- const reasons = [];
175
- if (hasUncommittedChanges) {
176
- const preview = uncommittedFiles.slice(0, 10).join(", ");
177
- const more = uncommittedFiles.length > 10 ? ` (+${String(uncommittedFiles.length - 10)} more)` : "";
178
- reasons.push(`the worktree has ${String(uncommittedFiles.length)} uncommitted change(s) that removal would destroy` + (preview.length > 0 ? `: ${preview}${more}` : ""));
179
- }
180
- if (unmergedCommits > 0) reasons.push(`branch ${branchName} carries ${String(unmergedCommits)} commit(s) not reachable from the current HEAD — deleting the branch would destroy them`);
181
- if (unmergedCommits < 0) reasons.push("the branch state could not be verified as safe to discard");
182
- return {
183
- safe: reasons.length === 0,
184
- reasons
185
- };
186
- }
187
- /**
188
- * Gather the inputs for `decideWorktreeRemoval` from git. Thin I/O wrapper:
189
- * - `git status --porcelain` inside the worktree (skipped when the directory
190
- * is missing — nothing on disk to lose)
191
- * - `git rev-list --count HEAD..<branch>` in the project root (commits the
192
- * branch has that the current checkout does not; 0 when the branch is
193
- * merged or absent, -1 when the count could not be determined)
194
- */
195
- async function inspectWorktreeRemovalSafety(worktreePath, projectRoot, branchName) {
196
- let hasUncommittedChanges = false;
197
- let uncommittedFiles = [];
198
- const worktreeOnDisk = await access$1(worktreePath).then(() => true).catch(() => false);
199
- if (worktreeOnDisk) {
200
- const statusResult = await spawnGit(["status", "--porcelain"], { cwd: worktreePath });
201
- if (statusResult.code === 0) {
202
- uncommittedFiles = statusResult.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => line.slice(3).trim());
203
- hasUncommittedChanges = uncommittedFiles.length > 0;
204
- } else return decideWorktreeRemoval(false, [], -1, branchName);
205
- }
206
- const branchExists = (await spawnGit([
207
- "rev-parse",
208
- "--verify",
209
- branchName
210
- ], { cwd: projectRoot })).code === 0;
211
- let unmergedCommits = 0;
212
- if (branchExists) {
213
- const aheadResult = await spawnGit([
214
- "rev-list",
215
- "--count",
216
- `HEAD..${branchName}`
217
- ], { cwd: projectRoot });
218
- unmergedCommits = aheadResult.code === 0 ? Number.parseInt(aheadResult.stdout.trim(), 10) || 0 : -1;
219
- }
220
- return decideWorktreeRemoval(hasUncommittedChanges, uncommittedFiles, unmergedCommits, branchName);
221
- }
222
- async function createWorktree(projectRoot, taskId, branchName, baseBranch, copyFiles = []) {
223
- const worktreePath = path$5.join(projectRoot, ".substrate-worktrees", taskId);
224
- const worktreeExists = await access$1(worktreePath).then(() => true).catch((err) => {
225
- if (err.code === "ENOENT") return false;
226
- throw err;
227
- });
228
- if (worktreeExists) {
229
- const listResult = await spawnGit([
230
- "worktree",
231
- "list",
232
- "--porcelain"
233
- ], { cwd: projectRoot });
234
- const registeredPaths = listResult.stdout.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice(9).trim());
235
- const isRegistered = registeredPaths.includes(worktreePath);
236
- if (!isRegistered) await rm(worktreePath, {
237
- recursive: true,
238
- force: true
239
- });
240
- else {
241
- const statusResult = await spawnGit(["status", "--porcelain"], { cwd: worktreePath });
242
- const hasUncommittedChanges = statusResult.code === 0 && statusResult.stdout.trim().length > 0;
243
- const aheadResult = await spawnGit([
244
- "rev-list",
245
- "--count",
246
- `${baseBranch}..${branchName}`
247
- ], { cwd: projectRoot });
248
- const commitsAhead = aheadResult.code === 0 ? Number.parseInt(aheadResult.stdout.trim(), 10) || 0 : -1;
249
- const decision = decideWorktreeReclaim(hasUncommittedChanges, commitsAhead, baseBranch);
250
- if (!decision.safe) throw new Error(`Worktree at ${worktreePath} is already registered (branch: ${branchName}) and ${decision.reason}.\nIt was preserved from a prior dispatch for inspection — inspect before removing.\n\nTo remove and re-dispatch:\n substrate worktrees --cleanup ${taskId}\n\nTo remove all substrate worktrees:\n substrate worktrees --cleanup`);
251
- await spawnGit([
252
- "worktree",
253
- "remove",
254
- "--force",
255
- worktreePath
256
- ], { cwd: projectRoot });
257
- await spawnGit([
258
- "branch",
259
- "-D",
260
- branchName
261
- ], { cwd: projectRoot });
262
- }
263
- }
264
- const addResult = await spawnGit([
265
- "worktree",
266
- "add",
267
- worktreePath,
268
- "-b",
269
- branchName,
270
- baseBranch
271
- ], { cwd: projectRoot });
272
- if (addResult.code !== 0) throw new Error(`git worktree add failed for task "${taskId}": ${addResult.stderr || addResult.stdout}`);
273
- await copyFilesToWorktree(projectRoot, worktreePath, copyFiles);
274
- return { worktreePath };
275
- }
276
- /**
277
- * Copy files from a source directory into a target worktree.
278
- *
279
- * Skips missing files silently (intentional — config like `[".env",
280
- * ".env.local"]` should not blow up if `.env.local` doesn't exist in the
281
- * parent checkout). Creates parent directories for nested paths.
282
- *
283
- * Exported for testability; not part of the public worktree API.
284
- */
285
- async function copyFilesToWorktree(sourceRoot, worktreePath, files) {
286
- if (files.length === 0) return;
287
- for (const relativePath of files) {
288
- if (path$5.isAbsolute(relativePath) || relativePath.split(path$5.sep).includes("..")) continue;
289
- const sourcePath = path$5.join(sourceRoot, relativePath);
290
- const destPath = path$5.join(worktreePath, relativePath);
291
- try {
292
- await access$1(sourcePath);
293
- } catch {
294
- continue;
295
- }
296
- const destDir = path$5.dirname(destPath);
297
- if (destDir !== worktreePath) await mkdir$1(destDir, { recursive: true });
298
- await copyFile(sourcePath, destPath);
299
- }
300
- }
301
- /**
302
- * Remove a git worktree by path.
303
- *
304
- * Uses `git worktree remove --force` to handle unclean worktrees.
305
- *
306
- * @param worktreePath - Absolute path to the worktree directory
307
- * @param projectRoot - Absolute path to the git repository root
308
- * @throws - Error if git command fails
309
- */
310
- async function removeWorktree(worktreePath, projectRoot) {
311
- const spawnOpts = {};
312
- if (projectRoot !== void 0) spawnOpts.cwd = projectRoot;
313
- const result = await spawnGit([
314
- "worktree",
315
- "remove",
316
- "--force",
317
- worktreePath
318
- ], spawnOpts);
319
- if (result.code !== 0) throw new Error(`git worktree remove failed for "${worktreePath}": ${result.stderr || result.stdout}`);
320
- }
321
- /**
322
- * Delete a git branch using `git branch -D`.
323
- *
324
- * @param branchName - Branch name to delete (e.g., "substrate/story-abc123")
325
- * @param projectRoot - Absolute path to the git repository root
326
- * @returns - true if branch was successfully deleted, false otherwise
327
- */
328
- async function removeBranch(branchName, projectRoot) {
329
- const spawnOpts = {};
330
- if (projectRoot !== void 0) spawnOpts.cwd = projectRoot;
331
- const result = await spawnGit([
332
- "branch",
333
- "-D",
334
- branchName
335
- ], spawnOpts);
336
- if (result.code !== 0) return false;
337
- return true;
338
- }
339
- /**
340
- * Scan the worktrees base directory and return paths of all found worktree directories.
341
- *
342
- * @param projectRoot - Absolute path to the git repository root
343
- * @param baseDirectory - Relative directory name for worktrees (default: '.substrate-worktrees')
344
- * @returns - Array of absolute worktree directory paths
345
- */
346
- async function getOrphanedWorktrees(projectRoot, baseDirectory = ".substrate-worktrees") {
347
- const worktreesDir = path$5.join(projectRoot, baseDirectory);
348
- try {
349
- await access$1(worktreesDir);
350
- } catch {
351
- return [];
352
- }
353
- let entries;
354
- try {
355
- entries = await readdir$1(worktreesDir, { withFileTypes: true });
356
- } catch {
357
- return [];
358
- }
359
- return entries.filter((entry) => entry.isDirectory()).map((entry) => path$5.join(worktreesDir, entry.name));
360
- }
361
- /**
362
- * Simulate a merge using git merge --no-commit --no-ff without committing.
363
- *
364
- * This runs in the target branch's working directory (the project root or
365
- * worktree path). The simulation must be aborted after checking conflicts
366
- * via abortMerge().
367
- *
368
- * @param branchName - The source branch to simulate merging
369
- * @param cwd - Working directory (must be on the target branch)
370
- * @returns - true if merge would be clean, false if there are conflicts
371
- */
372
- async function simulateMerge(branchName, cwd) {
373
- const result = await spawnGit([
374
- "merge",
375
- "--no-commit",
376
- "--no-ff",
377
- branchName
378
- ], { cwd });
379
- if (result.code === 0) return true;
380
- return false;
381
- }
382
- /**
383
- * Abort a merge in progress using git merge --abort.
384
- *
385
- * Should be called after simulateMerge() to clean up the merge state,
386
- * regardless of whether conflicts were found.
387
- *
388
- * @param cwd - Working directory (same as used for simulateMerge)
389
- */
390
- async function abortMerge(cwd) {
391
- await spawnGit(["merge", "--abort"], { cwd });
392
- }
393
- /**
394
- * Get a list of files with conflicts during a merge.
395
- *
396
- * Must be called while a merge is in progress (after simulateMerge() and
397
- * before abortMerge()).
398
- *
399
- * @param cwd - Working directory of the repository
400
- * @returns - Array of conflicting file paths
401
- */
402
- async function getConflictingFiles(cwd) {
403
- const result = await spawnGit([
404
- "diff",
405
- "--name-only",
406
- "--diff-filter=U"
407
- ], { cwd });
408
- if (result.code !== 0) return [];
409
- if (result.stdout.trim() === "") return [];
410
- return result.stdout.trim().split("\n").filter((f$1) => f$1.trim().length > 0);
411
- }
412
- /**
413
- * Perform an actual merge using git merge --no-ff.
414
- *
415
- * Should only be called after detectConflicts() confirms there are no conflicts.
416
- * Creates a merge commit even if fast-forward is possible (--no-ff ensures history).
417
- *
418
- * @param branchName - The source branch to merge
419
- * @param cwd - Working directory (must be on the target branch)
420
- * @returns - true if merge succeeded, false otherwise
421
- */
422
- async function performMerge(branchName, cwd) {
423
- const result = await spawnGit([
424
- "merge",
425
- "--no-ff",
426
- branchName
427
- ], { cwd });
428
- if (result.code !== 0) return false;
429
- return true;
430
- }
431
- /**
432
- * Get a list of files changed in the most recent merge.
433
- *
434
- * Uses git diff --name-only HEAD~1..HEAD to find files in the merge commit.
435
- * Falls back to empty array if commit history is insufficient.
436
- *
437
- * @param cwd - Working directory of the repository
438
- * @returns - Array of file paths that were merged
439
- */
440
- async function getMergedFiles(cwd) {
441
- const result = await spawnGit([
442
- "diff",
443
- "--name-only",
444
- "HEAD~1..HEAD"
445
- ], { cwd });
446
- if (result.code !== 0) {
447
- const altResult = await spawnGit([
448
- "show",
449
- "--name-only",
450
- "--format=",
451
- "HEAD"
452
- ], { cwd });
453
- if (altResult.code !== 0) return [];
454
- return altResult.stdout.trim().split("\n").filter((f$1) => f$1.trim().length > 0);
455
- }
456
- if (result.stdout.trim() === "") return [];
457
- return result.stdout.trim().split("\n").filter((f$1) => f$1.trim().length > 0);
458
- }
459
-
460
- //#endregion
461
- //#region packages/core/dist/git/git-worktree-manager-impl.js
462
- /**
463
- * Branch name prefix for substrate per-story branches.
464
- *
465
- * Exported as the canonical source of truth so consumers (orchestrator,
466
- * integration tests, tooling) can compose branch names without
467
- * independently encoding the prefix. v0.20.82 production bug:
468
- * `orchestrator-impl.ts:4290` hardcoded `substrate/story-${storyKey}`
469
- * while this module created `substrate/task-${taskId}` — the resulting
470
- * merge-to-main looked at a non-existent branch. Recurrence prevention:
471
- * all branch-name construction MUST import this constant.
472
- */
473
- const BRANCH_PREFIX = "substrate/story-";
474
- const DEFAULT_WORKTREE_BASE = ".substrate-worktrees";
475
- var GitWorktreeManagerImpl = class {
476
- _eventBus;
477
- _projectRoot;
478
- _baseDirectory;
479
- _db;
480
- _logger;
481
- /** v0.20.109: files to copy from project root into each new worktree (e.g. `.env`). */
482
- _copyFiles;
483
- /** Bound listener references for cleanup in shutdown() */
484
- _onTaskReady;
485
- _onTaskComplete;
486
- _onTaskFailed;
487
- constructor(eventBus, projectRoot, baseDirectory = DEFAULT_WORKTREE_BASE, db = null, logger$27, copyFiles = []) {
488
- this._eventBus = eventBus;
489
- this._projectRoot = projectRoot;
490
- this._baseDirectory = baseDirectory;
491
- this._db = db;
492
- this._logger = logger$27 ?? createStderrLogger("git-worktree-manager");
493
- this._copyFiles = copyFiles;
494
- this._onTaskReady = ({ taskId }) => {
495
- this._handleTaskReady(taskId).catch((err) => {
496
- this._logger.error({
497
- taskId,
498
- err
499
- }, "Unhandled error in _handleTaskReady");
500
- });
501
- };
502
- this._onTaskComplete = ({ taskId }) => {
503
- this._handleTaskDone(taskId);
504
- };
505
- this._onTaskFailed = ({ taskId }) => {
506
- this._handleTaskDone(taskId);
507
- };
508
- }
509
- async initialize() {
510
- this._logger.info({ projectRoot: this._projectRoot }, "GitWorktreeManager.initialize()");
511
- await this.verifyGitVersion();
512
- const cleaned = await this.cleanupAllWorktrees();
513
- if (cleaned > 0) this._logger.info({ cleaned }, "Recovered orphaned worktrees on startup");
514
- this._eventBus.on("task:ready", this._onTaskReady);
515
- this._eventBus.on("task:complete", this._onTaskComplete);
516
- this._eventBus.on("task:failed", this._onTaskFailed);
517
- this._logger.info("GitWorktreeManager initialized");
518
- }
519
- async shutdown() {
520
- this._logger.info("GitWorktreeManager.shutdown()");
521
- this._eventBus.off("task:ready", this._onTaskReady);
522
- this._eventBus.off("task:complete", this._onTaskComplete);
523
- this._eventBus.off("task:failed", this._onTaskFailed);
524
- await this.cleanupAllWorktrees();
525
- this._logger.info("GitWorktreeManager shutdown complete");
526
- }
527
- async _handleTaskReady(taskId) {
528
- this._logger.debug({ taskId }, "task:ready — creating worktree");
529
- try {
530
- await this.createWorktree(taskId);
531
- } catch (err) {
532
- this._logger.error({
533
- taskId,
534
- err
535
- }, "Failed to create worktree for task");
536
- }
537
- }
538
- async _handleTaskDone(taskId) {
539
- this._logger.debug({ taskId }, "task done — cleaning up worktree");
540
- try {
541
- await this.cleanupWorktree(taskId);
542
- } catch (err) {
543
- this._logger.warn({
544
- taskId,
545
- err
546
- }, "Failed to cleanup worktree for task");
547
- }
548
- }
549
- async createWorktree(taskId, baseBranch = "main") {
550
- if (!taskId || taskId.trim().length === 0) throw new Error("createWorktree: taskId must be a non-empty string");
551
- const branchName = BRANCH_PREFIX + taskId;
552
- const worktreePath = this.getWorktreePath(taskId);
553
- this._logger.debug({
554
- taskId,
555
- branchName,
556
- worktreePath,
557
- baseBranch,
558
- copyFiles: this._copyFiles
559
- }, "createWorktree");
560
- const copyFiles = this._copyFiles.includes(".substrate/project-profile.yaml") ? this._copyFiles : [...this._copyFiles, ".substrate/project-profile.yaml"];
561
- await createWorktree(this._projectRoot, taskId, branchName, baseBranch, copyFiles);
562
- const createdAt = new Date();
563
- this._eventBus.emit("worktree:created", {
564
- taskId,
565
- branchName,
566
- worktreePath,
567
- createdAt
568
- });
569
- const info = {
570
- taskId,
571
- branchName,
572
- worktreePath,
573
- createdAt
574
- };
575
- this._logger.info({
576
- taskId,
577
- branchName,
578
- worktreePath
579
- }, "Worktree created");
580
- return info;
581
- }
582
- async cleanupWorktree(taskId, opts) {
583
- const branchName = BRANCH_PREFIX + taskId;
584
- const worktreePath = this.getWorktreePath(taskId);
585
- this._logger.debug({
586
- taskId,
587
- branchName,
588
- worktreePath,
589
- force: opts?.force === true
590
- }, "cleanupWorktree");
591
- if (opts?.force !== true) {
592
- const decision = await inspectWorktreeRemovalSafety(worktreePath, this._projectRoot, branchName);
593
- const blockingReasons = opts?.keepBranch === true ? decision.reasons.filter((r) => r.includes("uncommitted")) : decision.reasons;
594
- if (blockingReasons.length > 0) throw new Error(`refusing to clean up worktree for "${taskId}": ${blockingReasons.join("; ")}.\nInspect first (git -C ${worktreePath} status; git log ${branchName} --oneline) or re-run with --force to discard.`);
595
- }
596
- let worktreeExists = false;
597
- try {
598
- await access$1(worktreePath);
599
- worktreeExists = true;
600
- } catch {
601
- this._logger.debug({
602
- taskId,
603
- worktreePath
604
- }, "cleanupWorktree: worktree does not exist, skipping removal");
605
- }
606
- if (worktreeExists) try {
607
- await removeWorktree(worktreePath, this._projectRoot);
608
- } catch (err) {
609
- this._logger.warn({
610
- taskId,
611
- worktreePath,
612
- err
613
- }, "removeWorktree failed during cleanup");
614
- }
615
- if (opts?.keepBranch !== true) try {
616
- await removeBranch(branchName, this._projectRoot);
617
- } catch (err) {
618
- this._logger.warn({
619
- taskId,
620
- branchName,
621
- err
622
- }, "removeBranch failed during cleanup");
623
- }
624
- this._eventBus.emit("worktree:removed", {
625
- taskId,
626
- branchName
627
- });
628
- this._logger.info({
629
- taskId,
630
- branchName
631
- }, "Worktree cleaned up");
632
- }
633
- async cleanupAllWorktrees(opts) {
634
- this._logger.debug({
635
- projectRoot: this._projectRoot,
636
- force: opts?.force === true
637
- }, "cleanupAllWorktrees");
638
- const orphanedPaths = await getOrphanedWorktrees(this._projectRoot, this._baseDirectory);
639
- let cleaned = 0;
640
- for (const worktreePath of orphanedPaths) {
641
- const taskId = path$4.basename(worktreePath);
642
- const branchGuardName = BRANCH_PREFIX + taskId;
643
- const decision = opts?.force === true ? {
644
- safe: true,
645
- reasons: []
646
- } : await inspectWorktreeRemovalSafety(worktreePath, this._projectRoot, branchGuardName);
647
- if (!decision.safe) {
648
- this._logger.warn({
649
- taskId,
650
- worktreePath,
651
- reasons: decision.reasons
652
- }, "cleanupAllWorktrees: preserving worktree — removal would destroy work (use `substrate worktrees cleanup --force` to discard)");
653
- continue;
654
- }
655
- let worktreeRemoved = false;
656
- try {
657
- await removeWorktree(worktreePath, this._projectRoot);
658
- worktreeRemoved = true;
659
- this._logger.debug({
660
- taskId,
661
- worktreePath
662
- }, "cleanupAllWorktrees: removed orphaned worktree");
663
- } catch (err) {
664
- this._logger.warn({
665
- taskId,
666
- worktreePath,
667
- err
668
- }, "cleanupAllWorktrees: failed to remove worktree");
669
- }
670
- const branchName = BRANCH_PREFIX + taskId;
671
- try {
672
- const branchRemoved = await removeBranch(branchName, this._projectRoot);
673
- if (branchRemoved) this._logger.debug({
674
- taskId,
675
- branchName
676
- }, "cleanupAllWorktrees: removed orphaned branch");
677
- } catch (err) {
678
- this._logger.warn({
679
- taskId,
680
- branchName,
681
- err
682
- }, "cleanupAllWorktrees: failed to remove branch");
683
- }
684
- if (worktreeRemoved) cleaned++;
685
- }
686
- if (cleaned > 0) this._logger.info({ cleaned }, "cleanupAllWorktrees: recovered orphaned worktrees");
687
- return cleaned;
688
- }
689
- async detectConflicts(taskId, targetBranch = "main") {
690
- if (!taskId || taskId.trim().length === 0) throw new Error("detectConflicts: taskId must be a non-empty string");
691
- const branchName = BRANCH_PREFIX + taskId;
692
- const worktreePath = this.getWorktreePath(taskId);
693
- this._logger.debug({
694
- taskId,
695
- branchName,
696
- targetBranch
697
- }, "detectConflicts");
698
- try {
699
- await access$1(worktreePath);
700
- } catch {
701
- throw new Error(`detectConflicts: Worktree for task "${taskId}" not found at "${worktreePath}". The worktree may have already been cleaned up.`);
702
- }
703
- const mergeClean = await simulateMerge(branchName, this._projectRoot);
704
- let conflictingFiles = [];
705
- try {
706
- if (!mergeClean) conflictingFiles = await getConflictingFiles(this._projectRoot);
707
- } finally {
708
- await abortMerge(this._projectRoot);
709
- }
710
- const report = {
711
- hasConflicts: !mergeClean || conflictingFiles.length > 0,
712
- conflictingFiles,
713
- taskId,
714
- targetBranch
715
- };
716
- if (report.hasConflicts) this._eventBus.emit("worktree:conflict", {
717
- taskId,
718
- branch: branchName,
719
- conflictingFiles: report.conflictingFiles
720
- });
721
- this._logger.info({
722
- taskId,
723
- hasConflicts: report.hasConflicts,
724
- conflictCount: conflictingFiles.length
725
- }, "Conflict detection complete");
726
- return report;
727
- }
728
- async mergeWorktree(taskId, targetBranch = "main") {
729
- if (!taskId || taskId.trim().length === 0) throw new Error("mergeWorktree: taskId must be a non-empty string");
730
- const branchName = BRANCH_PREFIX + taskId;
731
- this._logger.debug({
732
- taskId,
733
- branchName,
734
- targetBranch
735
- }, "mergeWorktree");
736
- const conflictReport = await this.detectConflicts(taskId, targetBranch);
737
- if (conflictReport.hasConflicts) {
738
- this._logger.info({
739
- taskId,
740
- conflictCount: conflictReport.conflictingFiles.length
741
- }, "Merge skipped due to conflicts");
742
- return {
743
- success: false,
744
- mergedFiles: [],
745
- conflicts: conflictReport
746
- };
747
- }
748
- const mergeSuccess = await performMerge(branchName, this._projectRoot);
749
- if (!mergeSuccess) throw new Error(`mergeWorktree: git merge --no-ff failed for task "${taskId}" branch "${branchName}"`);
750
- const mergedFiles = await getMergedFiles(this._projectRoot);
751
- this._eventBus.emit("worktree:merged", {
752
- taskId,
753
- branch: branchName,
754
- mergedFiles
755
- });
756
- const result = {
757
- success: true,
758
- mergedFiles
759
- };
760
- this._logger.info({
761
- taskId,
762
- branchName,
763
- mergedFileCount: mergedFiles.length
764
- }, "Worktree merged successfully");
765
- return result;
766
- }
767
- async listWorktrees() {
768
- this._logger.debug({
769
- projectRoot: this._projectRoot,
770
- baseDirectory: this._baseDirectory
771
- }, "listWorktrees");
772
- const worktreePaths = await getOrphanedWorktrees(this._projectRoot, this._baseDirectory);
773
- const results = [];
774
- for (const worktreePath of worktreePaths) {
775
- const taskId = path$4.basename(worktreePath);
776
- const branchName = BRANCH_PREFIX + taskId;
777
- let createdAt;
778
- try {
779
- const { stat: stat$2 } = await import("node:fs/promises");
780
- const stats = await stat$2(worktreePath);
781
- createdAt = stats.birthtime ?? stats.ctime;
782
- } catch {
783
- createdAt = new Date();
784
- }
785
- results.push({
786
- taskId,
787
- branchName,
788
- worktreePath,
789
- createdAt
790
- });
791
- }
792
- this._logger.debug({ count: results.length }, "listWorktrees: found worktrees");
793
- return results;
794
- }
795
- getWorktreePath(taskId) {
796
- return path$4.join(this._projectRoot, this._baseDirectory, taskId);
797
- }
798
- async verifyGitVersion() {
799
- try {
800
- await verifyGitVersion();
801
- } catch (err) {
802
- throw new Error(`GitWorktreeManager: git version check failed: ${String(err)}`);
803
- }
804
- }
805
- };
806
- function createGitWorktreeManager(options) {
807
- return new GitWorktreeManagerImpl(options.eventBus, options.projectRoot, options.baseDirectory, options.db ?? null, options.logger, options.copyFiles);
808
- }
809
-
810
- //#endregion
811
35
  //#region src/modules/methodology-pack/schemas.ts
812
36
  /**
813
37
  * A reference to a context value to inject into a step prompt.
@@ -2961,7 +2185,7 @@ These on-disk files back the new autonomy commands. External monitors (dashboard
2961
2185
  - \`.substrate/current-run-id\` — plain text file containing the latest run ID; consulted by the canonical run-discovery chain.
2962
2186
  - \`.substrate/notifications/<run-id>-<timestamp>.json\` — operator halt notifications written by the Recovery Engine when \`--halt-on\` triggers; deleted by \`substrate report\` after read.
2963
2187
  - \`pending_proposals[]\` field in the run manifest — Recovery Engine Tier B re-scope proposals collected here for next-morning operator review. Back-pressure pauses dispatching at \`>= 2\` proposals (work-graph-aware) or \`>= 5\` (safety valve).
2964
- - \`.substrate-worktrees/story-<key>/\` — per-story git worktree directories created during dispatch on branch \`substrate/story-<key>\`. **Substrate auto-commits** the dispatched agent's output to the branch after SHIP_IT with a \`feat(story-N-M): <title>\` message (v0.20.86+ — substrate does not rely on the agent committing). Pre-commit hooks fire on the substrate commit. The branch is then merged to the base branch and the worktree is removed. On verification failure or auto-commit failure, the worktree and branch are preserved for \`substrate reconcile-from-disk\` inspection. Use \`--no-worktree\` (or \`SUBSTRATE_NO_WORKTREE=1\`) to disable per-story worktrees entirely; dispatch then runs against the parent project tree.
2188
+ - Per-story git worktrees are created during dispatch on branch \`substrate/story-<key>\`. H4.2: the default base is EXTERNAL — \`~/.substrate/worktrees/<projectname>-<hash8>/<key>/\` — so agents have no parent repo above their worktree; set \`worktree.base: in-repo\` in .substrate/config.yaml to restore the legacy \`.substrate-worktrees/<key>/\` location (tooling that globbed the old path should use \`substrate worktrees list\`). **Substrate auto-commits** the dispatched agent's output to the branch after SHIP_IT with a \`feat(story-N-M): <title>\` message (v0.20.86+ — substrate does not rely on the agent committing). Pre-commit hooks fire on the substrate commit. The branch is then merged to the base branch and the worktree is removed. On verification failure or auto-commit failure, the worktree and branch are preserved for \`substrate reconcile-from-disk\` inspection. Use \`--no-worktree\` (or \`SUBSTRATE_NO_WORKTREE=1\`) to disable per-story worktrees entirely; dispatch then runs against the parent project tree.
2965
2189
 
2966
2190
  ## Environment Variables
2967
2191
 
@@ -3574,8 +2798,8 @@ var GrammarLoader = class {
3574
2798
  throw err;
3575
2799
  }
3576
2800
  }
3577
- _loadModule(path$6) {
3578
- return __require(path$6);
2801
+ _loadModule(path$4) {
2802
+ return __require(path$4);
3579
2803
  }
3580
2804
  };
3581
2805
 
@@ -7192,10 +6416,10 @@ function computeStoryFileFidelity(storyFileContent, namedPaths) {
7192
6416
  };
7193
6417
  const missing = [];
7194
6418
  const present = [];
7195
- for (const path$6 of namedPaths) {
7196
- const basename$2 = path$6.includes("/") ? path$6.slice(path$6.lastIndexOf("/") + 1) : path$6;
7197
- if (storyFileContent.includes(path$6) || storyFileContent.includes(basename$2)) present.push(path$6);
7198
- else missing.push(path$6);
6419
+ for (const path$4 of namedPaths) {
6420
+ const basename$2 = path$4.includes("/") ? path$4.slice(path$4.lastIndexOf("/") + 1) : path$4;
6421
+ if (storyFileContent.includes(path$4) || storyFileContent.includes(basename$2)) present.push(path$4);
6422
+ else missing.push(path$4);
7199
6423
  }
7200
6424
  return {
7201
6425
  missing,
@@ -8901,7 +8125,7 @@ function extractReferencedFiles(storyContent) {
8901
8125
  const matches = storyContent.match(filePathRegex) ?? [];
8902
8126
  const freq = new Map();
8903
8127
  for (const m of matches) freq.set(m, (freq.get(m) ?? 0) + 1);
8904
- const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([path$6]) => path$6);
8128
+ const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([path$4]) => path$4);
8905
8129
  return sorted.filter((p) => !p.includes(".test."));
8906
8130
  }
8907
8131
  function extractFilesInScope(storyContent) {
@@ -19979,8 +19203,8 @@ async function resolveContext(ref, deps, runId, params, stepOutputs) {
19979
19203
  return params[key] ?? "";
19980
19204
  }
19981
19205
  if (source.startsWith("decision:")) {
19982
- const path$6 = source.slice(9);
19983
- const [phase, category] = path$6.split(".");
19206
+ const path$4 = source.slice(9);
19207
+ const [phase, category] = path$4.split(".");
19984
19208
  if (!phase || !category) return "";
19985
19209
  const decisions = await getDecisionsByPhaseForRun(deps.db, runId, phase);
19986
19210
  const filtered = decisions.filter((d) => d.category === category);
@@ -20051,8 +19275,8 @@ async function runSteps(steps, deps, runId, phase, params) {
20051
19275
  for (const ref of step.context) {
20052
19276
  let value;
20053
19277
  if (ref.source.startsWith("decision:")) {
20054
- const path$6 = ref.source.slice(9);
20055
- const [decPhase, decCategory] = path$6.split(".");
19278
+ const path$4 = ref.source.slice(9);
19279
+ const [decPhase, decCategory] = path$4.split(".");
20056
19280
  if (decPhase && decCategory) {
20057
19281
  const decisions = await getDecisionsByPhaseForRun(deps.db, runId, decPhase);
20058
19282
  const filtered = decisions.filter((d) => d.category === decCategory);
@@ -31140,8 +30364,8 @@ var require_uri_all = __commonJS({ "node_modules/uri-js/dist/es5/uri.all.js"(exp
31140
30364
  wsComponents.secure = void 0;
31141
30365
  }
31142
30366
  if (wsComponents.resourceName) {
31143
- var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path$6 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
31144
- wsComponents.path = path$6 && path$6 !== "/" ? path$6 : void 0;
30367
+ var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path$4 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
30368
+ wsComponents.path = path$4 && path$4 !== "/" ? path$4 : void 0;
31145
30369
  wsComponents.query = query;
31146
30370
  wsComponents.resourceName = void 0;
31147
30371
  }
@@ -31482,12 +30706,12 @@ var require_util = __commonJS({ "node_modules/ajv/lib/compile/util.js"(exports,
31482
30706
  return "'" + escapeQuotes(str) + "'";
31483
30707
  }
31484
30708
  function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
31485
- var path$6 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
31486
- return joinPaths(currentPath, path$6);
30709
+ var path$4 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
30710
+ return joinPaths(currentPath, path$4);
31487
30711
  }
31488
30712
  function getPath(currentPath, prop, jsonPointers) {
31489
- var path$6 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
31490
- return joinPaths(currentPath, path$6);
30713
+ var path$4 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
30714
+ return joinPaths(currentPath, path$4);
31491
30715
  }
31492
30716
  var JSON_POINTER$1 = /^\/(?:[^~]|~0|~1)*$/;
31493
30717
  var RELATIVE_JSON_POINTER$1 = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
@@ -35696,8 +34920,8 @@ var ToolRegistry = class {
35696
34920
  if (!valid) {
35697
34921
  const errors = validate$1.errors ?? [];
35698
34922
  const messages = errors.map((e) => {
35699
- const path$6 = e.instancePath ?? e.dataPath ?? "";
35700
- return `${path$6} ${e.message ?? ""}`.trim();
34923
+ const path$4 = e.instancePath ?? e.dataPath ?? "";
34924
+ return `${path$4} ${e.message ?? ""}`.trim();
35701
34925
  }).join(", ");
35702
34926
  return {
35703
34927
  content: `Validation failed for tool '${name}': ${messages}`,
@@ -42403,10 +41627,10 @@ var PathBase = class {
42403
41627
  /**
42404
41628
  * Get the Path object referenced by the string path, resolved from this Path
42405
41629
  */
42406
- resolve(path$6) {
42407
- if (!path$6) return this;
42408
- const rootPath = this.getRootString(path$6);
42409
- const dir = path$6.substring(rootPath.length);
41630
+ resolve(path$4) {
41631
+ if (!path$4) return this;
41632
+ const rootPath = this.getRootString(path$4);
41633
+ const dir = path$4.substring(rootPath.length);
42410
41634
  const dirParts = dir.split(this.splitSep);
42411
41635
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
42412
41636
  return result;
@@ -43061,8 +42285,8 @@ var PathWin32 = class PathWin32 extends PathBase {
43061
42285
  /**
43062
42286
  * @internal
43063
42287
  */
43064
- getRootString(path$6) {
43065
- return win32.parse(path$6).root;
42288
+ getRootString(path$4) {
42289
+ return win32.parse(path$4).root;
43066
42290
  }
43067
42291
  /**
43068
42292
  * @internal
@@ -43107,8 +42331,8 @@ var PathPosix = class PathPosix extends PathBase {
43107
42331
  /**
43108
42332
  * @internal
43109
42333
  */
43110
- getRootString(path$6) {
43111
- return path$6.startsWith("/") ? "/" : "";
42334
+ getRootString(path$4) {
42335
+ return path$4.startsWith("/") ? "/" : "";
43112
42336
  }
43113
42337
  /**
43114
42338
  * @internal
@@ -43201,9 +42425,9 @@ var PathScurryBase = class {
43201
42425
  /**
43202
42426
  * Get the depth of a provided path, string, or the cwd
43203
42427
  */
43204
- depth(path$6 = this.cwd) {
43205
- if (typeof path$6 === "string") path$6 = this.cwd.resolve(path$6);
43206
- return path$6.depth();
42428
+ depth(path$4 = this.cwd) {
42429
+ if (typeof path$4 === "string") path$4 = this.cwd.resolve(path$4);
42430
+ return path$4.depth();
43207
42431
  }
43208
42432
  /**
43209
42433
  * Return the cache of child entries. Exposed so subclasses can create
@@ -43584,9 +42808,9 @@ var PathScurryBase = class {
43584
42808
  process$1();
43585
42809
  return results;
43586
42810
  }
43587
- chdir(path$6 = this.cwd) {
42811
+ chdir(path$4 = this.cwd) {
43588
42812
  const oldCwd = this.cwd;
43589
- this.cwd = typeof path$6 === "string" ? this.cwd.resolve(path$6) : path$6;
42813
+ this.cwd = typeof path$4 === "string" ? this.cwd.resolve(path$4) : path$4;
43590
42814
  this.cwd[setAsCwd](oldCwd);
43591
42815
  }
43592
42816
  };
@@ -43970,8 +43194,8 @@ var MatchRecord = class {
43970
43194
  this.store.set(target, current === void 0 ? n$1 : n$1 & current);
43971
43195
  }
43972
43196
  entries() {
43973
- return [...this.store.entries()].map(([path$6, n$1]) => [
43974
- path$6,
43197
+ return [...this.store.entries()].map(([path$4, n$1]) => [
43198
+ path$4,
43975
43199
  !!(n$1 & 2),
43976
43200
  !!(n$1 & 1)
43977
43201
  ]);
@@ -44147,9 +43371,9 @@ var GlobUtil = class {
44147
43371
  signal;
44148
43372
  maxDepth;
44149
43373
  includeChildMatches;
44150
- constructor(patterns, path$6, opts) {
43374
+ constructor(patterns, path$4, opts) {
44151
43375
  this.patterns = patterns;
44152
- this.path = path$6;
43376
+ this.path = path$4;
44153
43377
  this.opts = opts;
44154
43378
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
44155
43379
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -44170,11 +43394,11 @@ var GlobUtil = class {
44170
43394
  });
44171
43395
  }
44172
43396
  }
44173
- #ignored(path$6) {
44174
- return this.seen.has(path$6) || !!this.#ignore?.ignored?.(path$6);
43397
+ #ignored(path$4) {
43398
+ return this.seen.has(path$4) || !!this.#ignore?.ignored?.(path$4);
44175
43399
  }
44176
- #childrenIgnored(path$6) {
44177
- return !!this.#ignore?.childrenIgnored?.(path$6);
43400
+ #childrenIgnored(path$4) {
43401
+ return !!this.#ignore?.childrenIgnored?.(path$4);
44178
43402
  }
44179
43403
  pause() {
44180
43404
  this.paused = true;
@@ -44356,8 +43580,8 @@ var GlobUtil = class {
44356
43580
  };
44357
43581
  var GlobWalker = class extends GlobUtil {
44358
43582
  matches = new Set();
44359
- constructor(patterns, path$6, opts) {
44360
- super(patterns, path$6, opts);
43583
+ constructor(patterns, path$4, opts) {
43584
+ super(patterns, path$4, opts);
44361
43585
  }
44362
43586
  matchEmit(e) {
44363
43587
  this.matches.add(e);
@@ -44384,8 +43608,8 @@ var GlobWalker = class extends GlobUtil {
44384
43608
  };
44385
43609
  var GlobStream = class extends GlobUtil {
44386
43610
  results;
44387
- constructor(patterns, path$6, opts) {
44388
- super(patterns, path$6, opts);
43611
+ constructor(patterns, path$4, opts) {
43612
+ super(patterns, path$4, opts);
44389
43613
  this.results = new Minipass({
44390
43614
  signal: this.signal,
44391
43615
  objectMode: true
@@ -48496,7 +47720,7 @@ async function runFullPipeline(options) {
48496
47720
  */
48497
47721
  async function emitPreDispatchVersionAdvisory(currentVersion) {
48498
47722
  if (process.env["SUBSTRATE_NO_UPDATE_CHECK"] === "1") return;
48499
- const { createVersionManager } = await import("./version-manager-impl-_x1n4xZk.js");
47723
+ const { createVersionManager } = await import("./version-manager-impl-DizCvYy8.js");
48500
47724
  const vm = createVersionManager();
48501
47725
  const result = await vm.checkForUpdates(true);
48502
47726
  const gap = classifyVersionGap(currentVersion, result.latestVersion);
@@ -48602,5 +47826,5 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
48602
47826
  }
48603
47827
 
48604
47828
  //#endregion
48605
- export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
48606
- //# sourceMappingURL=run-B9DV9sro.js.map
47829
+ 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 };
47830
+ //# sourceMappingURL=run-BAUlPom3.js.map