@outcomeeng/spx 0.6.10 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -289,9 +289,6 @@ async function resolveAgentResumeScopeContext(options) {
289
289
  return { match: (core) => core.branch === target, claudeDirAccepts: () => true };
290
290
  }
291
291
  const invocationRoot = await options.resolveWorktreeRoot(options.invocationDir);
292
- if (invocationRoot === null) {
293
- return null;
294
- }
295
292
  const projectPrefix = claudeProjectDirName(invocationRoot);
296
293
  return {
297
294
  match: (core) => isPathInsideOrEqual(invocationRoot, core.cwd),
@@ -326,11 +323,11 @@ function renderAgentResumeJson(candidates) {
326
323
  }
327
324
  async function recentStoreFiles(paths, fs8, nowMs) {
328
325
  const stats = await mapWithConcurrency(paths, AGENT_RESUME_LIMITS.READ_CONCURRENCY, async (path7) => {
329
- const stat8 = await fs8.stat(path7).catch(() => null);
330
- if (stat8 === null || !isRecentAgentSessionMtime(stat8.mtimeMs, nowMs)) {
326
+ const stat9 = await fs8.stat(path7).catch(() => null);
327
+ if (stat9 === null || !isRecentAgentSessionMtime(stat9.mtimeMs, nowMs)) {
331
328
  return null;
332
329
  }
333
- return { path: path7, modifiedAtMs: stat8.mtimeMs };
330
+ return { path: path7, modifiedAtMs: stat9.mtimeMs };
334
331
  });
335
332
  return stats.filter((file) => file !== null).sort((left, right) => right.modifiedAtMs - left.modifiedAtMs || left.path.localeCompare(right.path));
336
333
  }
@@ -529,6 +526,195 @@ async function mapWithConcurrency(items, concurrency, mapper) {
529
526
  return results;
530
527
  }
531
528
 
529
+ // src/domains/session/types.ts
530
+ var SESSION_PRIORITY = {
531
+ HIGH: "high",
532
+ MEDIUM: "medium",
533
+ LOW: "low"
534
+ };
535
+ var SESSION_STATUSES = ["todo", "doing", "archive"];
536
+ var DEFAULT_LIST_STATUSES = ["doing", "todo"];
537
+ var SESSION_FILE_ENCODING = "utf-8";
538
+ var SESSION_FILE_ERROR_CODE = {
539
+ NOT_FOUND: "ENOENT"
540
+ };
541
+ var SESSION_OUTPUT_MARKER = {
542
+ HANDOFF_ID: "HANDOFF_ID",
543
+ PICKUP_ID: "PICKUP_ID",
544
+ SESSION_FILE: "SESSION_FILE"
545
+ };
546
+ function formatSessionOutputMarker(marker, value) {
547
+ return `<${marker}>${value}</${marker}>`;
548
+ }
549
+ var CLAIMABLE_STATUS = SESSION_STATUSES[0];
550
+ var PRIORITY_ORDER = {
551
+ [SESSION_PRIORITY.HIGH]: 0,
552
+ [SESSION_PRIORITY.MEDIUM]: 1,
553
+ [SESSION_PRIORITY.LOW]: 2
554
+ };
555
+ var DEFAULT_PRIORITY = SESSION_PRIORITY.MEDIUM;
556
+ var SESSION_FRONT_MATTER = {
557
+ PRIORITY: "priority",
558
+ GIT_REF: "git_ref",
559
+ GOAL: "goal",
560
+ NEXT_STEP: "next_step",
561
+ CREATED_AT: "created_at",
562
+ AGENT_SESSION_ID: "agent_session_id",
563
+ SPECS: "specs",
564
+ FILES: "files"
565
+ };
566
+
567
+ // src/domains/agent/search.ts
568
+ var AGENT_SEARCH_DEFAULT_LIMIT = 20;
569
+ var AGENT_SEARCH_MATCH_REASON = {
570
+ ALL: "all",
571
+ PICKUP_ID: "pickup-id",
572
+ CONTAINS: "contains",
573
+ SESSION_ID: "session-id",
574
+ AGENT: "agent",
575
+ BRANCH: "branch"
576
+ };
577
+ function pickupIdSearchLiteral(pickupId) {
578
+ return formatSessionOutputMarker(SESSION_OUTPUT_MARKER.PICKUP_ID, pickupId);
579
+ }
580
+ function agentSearchQueryFromOptions(options) {
581
+ const contentNeedles = [];
582
+ if (options.pickupId !== void 0) {
583
+ contentNeedles.push({
584
+ reason: AGENT_SEARCH_MATCH_REASON.PICKUP_ID,
585
+ value: pickupIdSearchLiteral(options.pickupId)
586
+ });
587
+ }
588
+ if (options.contains !== void 0) {
589
+ contentNeedles.push({ reason: AGENT_SEARCH_MATCH_REASON.CONTAINS, value: options.contains });
590
+ }
591
+ return {
592
+ contentNeedles,
593
+ sessionId: options.sessionId ?? null,
594
+ branch: options.branch ?? null,
595
+ agent: options.agent ?? null,
596
+ includeAll: options.all === true,
597
+ limit: options.limit ?? AGENT_SEARCH_DEFAULT_LIMIT
598
+ };
599
+ }
600
+ async function searchAgentSessions(options) {
601
+ const selectedAgents = options.query.agent === null ? [AGENT_SESSION_KIND.CODEX, AGENT_SESSION_KIND.CLAUDE_CODE] : [options.query.agent];
602
+ const perAgent = await Promise.all(
603
+ selectedAgents.map((agent) => searchAgentStore(agent, options))
604
+ );
605
+ return perAgent.flat().sort(compareSearchResults).slice(0, Math.max(0, options.query.limit));
606
+ }
607
+ function renderAgentSearchJson(results) {
608
+ return JSON.stringify(results, null, 2);
609
+ }
610
+ function renderAgentSearchList(results) {
611
+ if (results.length === 0) {
612
+ return "No matching agent sessions found.";
613
+ }
614
+ return results.map((result) => {
615
+ const updatedAt = result.updatedAt ?? new Date(result.modifiedAtMs).toISOString();
616
+ return `${updatedAt} ${AGENT_SESSION_LABEL[result.agent]} ${result.sessionId} ${result.cwd}`;
617
+ }).join("\n");
618
+ }
619
+ async function searchAgentStore(agent, options) {
620
+ const paths = agent === AGENT_SESSION_KIND.CODEX ? await collectJsonlFiles(codexSessionStoreDir(options.homeDir), options.fs) : await claudeTranscriptFiles(
621
+ claudeCodeSessionStoreDir(options.homeDir),
622
+ options.fs,
623
+ claudeDirAcceptsProductScope(options.productScopeRoot)
624
+ );
625
+ const files = await storeFiles(paths, options.fs, options.nowMs, options.query.includeAll);
626
+ const parser = agent === AGENT_SESSION_KIND.CODEX ? parseCodexHead : parseClaudeHead;
627
+ return collectMatchingSessions(agent, files, options, parser);
628
+ }
629
+ function claudeDirAcceptsProductScope(productScopeRoot) {
630
+ const projectPrefix = claudeProjectDirName(productScopeRoot);
631
+ return (dirName) => dirName === projectPrefix || dirName.startsWith(`${projectPrefix}${CLAUDE_PROJECT_ENCODED_SEPARATOR}`);
632
+ }
633
+ async function collectMatchingSessions(agent, files, options, parseHead) {
634
+ const results = [];
635
+ const seen = /* @__PURE__ */ new Set();
636
+ for (const file of files) {
637
+ const head = await options.fs.readHead(file.path, AGENT_RESUME_LIMITS.METADATA_HEAD_BYTES).catch(() => null);
638
+ if (head === null) continue;
639
+ const core = parseHead(head);
640
+ if (core === null || !core.interactive || seen.has(core.sessionId)) continue;
641
+ if (!coreMatchesProductScope(core, options.productScopeRoot)) continue;
642
+ const matches = await matchReasons(agent, core, file.path, options);
643
+ if (matches.length === 0) continue;
644
+ seen.add(core.sessionId);
645
+ results.push({
646
+ agent,
647
+ sessionId: core.sessionId,
648
+ cwd: core.cwd,
649
+ sourcePath: file.path,
650
+ modifiedAtMs: file.modifiedAtMs,
651
+ updatedAt: core.updatedAt,
652
+ branch: core.branch,
653
+ matches
654
+ });
655
+ }
656
+ return results;
657
+ }
658
+ async function matchReasons(agent, core, path7, options) {
659
+ if (!hasSearchSelector(options.query)) {
660
+ return [AGENT_SEARCH_MATCH_REASON.ALL];
661
+ }
662
+ const metadataMatches = metadataMatchReasons(agent, core, options.query);
663
+ const contentMatches = await contentMatchReasons(path7, options);
664
+ if (metadataMatches === null || contentMatches === null) {
665
+ return [];
666
+ }
667
+ return [...metadataMatches, ...contentMatches];
668
+ }
669
+ function hasSearchSelector(query) {
670
+ return query.contentNeedles.length > 0 || query.sessionId !== null || query.branch !== null || query.agent !== null;
671
+ }
672
+ function metadataMatchReasons(agent, core, query) {
673
+ const matches = [];
674
+ if (query.agent !== null) {
675
+ if (agent !== query.agent) return null;
676
+ matches.push(AGENT_SEARCH_MATCH_REASON.AGENT);
677
+ }
678
+ if (query.sessionId !== null && core.sessionId === query.sessionId) {
679
+ matches.push(AGENT_SEARCH_MATCH_REASON.SESSION_ID);
680
+ } else if (query.sessionId !== null) {
681
+ return null;
682
+ }
683
+ if (query.branch !== null) {
684
+ if (core.branch !== query.branch) return null;
685
+ matches.push(AGENT_SEARCH_MATCH_REASON.BRANCH);
686
+ }
687
+ return matches;
688
+ }
689
+ async function contentMatchReasons(path7, options) {
690
+ if (options.query.contentNeedles.length === 0) {
691
+ return [];
692
+ }
693
+ const content = await options.fs.readText(path7).catch(() => null);
694
+ return content === null ? null : matchingContentNeedles(content, options.query.contentNeedles);
695
+ }
696
+ function matchingContentNeedles(content, needles) {
697
+ const matches = needles.filter((needle) => content.includes(needle.value)).map((needle) => needle.reason);
698
+ return matches.length === needles.length ? matches : null;
699
+ }
700
+ function coreMatchesProductScope(core, productScopeRoot) {
701
+ return isPathInsideOrEqual(productScopeRoot, core.cwd);
702
+ }
703
+ async function storeFiles(paths, fs8, nowMs, includeAll) {
704
+ const files = await mapWithConcurrency(paths, AGENT_RESUME_LIMITS.READ_CONCURRENCY, async (path7) => {
705
+ const stat9 = await fs8.stat(path7).catch(() => null);
706
+ if (stat9 === null) return null;
707
+ if (!includeAll && !isRecentAgentSessionMtime(stat9.mtimeMs, nowMs)) return null;
708
+ return { path: path7, modifiedAtMs: stat9.mtimeMs };
709
+ });
710
+ return files.filter((file) => file !== null).sort((left, right) => right.modifiedAtMs - left.modifiedAtMs || left.path.localeCompare(right.path));
711
+ }
712
+ function compareSearchResults(left, right) {
713
+ const modifiedDiff = right.modifiedAtMs - left.modifiedAtMs;
714
+ if (modifiedDiff !== 0) return modifiedDiff;
715
+ return `${left.agent}:${left.sessionId}`.localeCompare(`${right.agent}:${right.sessionId}`);
716
+ }
717
+
532
718
  // src/git/root.ts
533
719
  import { execa } from "execa";
534
720
  import { basename, dirname, isAbsolute as isAbsolute2, join, resolve as resolve4 } from "path";
@@ -917,9 +1103,9 @@ var defaultAgentResumeCommandDeps = {
917
1103
  fs: nodeAgentSessionFileSystem,
918
1104
  homeDir: homedir,
919
1105
  nowMs: Date.now,
920
- resolveWorktreeRoot: async (cwd) => {
1106
+ resolveWorktreeRoot: async (cwd, fallbackWorktreeRoot) => {
921
1107
  const result = await detectWorktreeProductRoot(cwd);
922
- return result.isGitRepo ? result.productDir : null;
1108
+ return result.isGitRepo ? result.productDir : fallbackWorktreeRoot;
923
1109
  }
924
1110
  };
925
1111
  async function loadAgentResumeCandidates(options) {
@@ -930,7 +1116,7 @@ async function loadAgentResumeCandidates(options) {
930
1116
  nowMs: deps.nowMs(),
931
1117
  scope: options.scope,
932
1118
  fs: deps.fs,
933
- resolveWorktreeRoot: deps.resolveWorktreeRoot
1119
+ resolveWorktreeRoot: (cwd) => deps.resolveWorktreeRoot(cwd, options.fallbackWorktreeRoot)
934
1120
  });
935
1121
  }
936
1122
  async function listAgentResumeSessions(options) {
@@ -940,6 +1126,63 @@ async function jsonAgentResumeSessions(options) {
940
1126
  return renderAgentResumeJson(await loadAgentResumeCandidates(options));
941
1127
  }
942
1128
 
1129
+ // src/commands/agent/search.ts
1130
+ import { open as open2, readdir as readdir2, readFile, stat as stat2 } from "fs/promises";
1131
+ import { homedir as homedir2 } from "os";
1132
+ var nodeAgentSearchFileSystem = {
1133
+ async readDir(path7) {
1134
+ const entries = await readdir2(path7, { withFileTypes: true });
1135
+ return entries.map((entry) => ({
1136
+ name: entry.name,
1137
+ isDirectory: entry.isDirectory(),
1138
+ isFile: entry.isFile()
1139
+ }));
1140
+ },
1141
+ async readHead(path7, maxBytes) {
1142
+ const handle = await open2(path7, "r");
1143
+ try {
1144
+ const buffer = Buffer.alloc(maxBytes);
1145
+ const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);
1146
+ return buffer.toString(AGENT_SESSION_STORE.TEXT_ENCODING, 0, bytesRead);
1147
+ } finally {
1148
+ await handle.close();
1149
+ }
1150
+ },
1151
+ async readText(path7) {
1152
+ return readFile(path7, AGENT_SESSION_STORE.TEXT_ENCODING);
1153
+ },
1154
+ async stat(path7) {
1155
+ const result = await stat2(path7);
1156
+ return { mtimeMs: result.mtimeMs };
1157
+ }
1158
+ };
1159
+ var defaultAgentSearchCommandDeps = {
1160
+ fs: nodeAgentSearchFileSystem,
1161
+ homeDir: homedir2,
1162
+ nowMs: Date.now,
1163
+ resolveProductScopeRoot: resolveAgentSearchProductScopeRoot
1164
+ };
1165
+ async function resolveAgentSearchProductScopeRoot(cwd, fallbackProductScopeRoot, gitDeps = defaultGitDependencies) {
1166
+ const result = await detectWorktreeProductRoot(cwd, gitDeps);
1167
+ return result.isGitRepo ? result.productDir : fallbackProductScopeRoot;
1168
+ }
1169
+ async function loadAgentSearchResults(options) {
1170
+ const deps = options.deps ?? defaultAgentSearchCommandDeps;
1171
+ return searchAgentSessions({
1172
+ homeDir: deps.homeDir(),
1173
+ nowMs: deps.nowMs(),
1174
+ productScopeRoot: await deps.resolveProductScopeRoot(options.cwd, options.fallbackProductScopeRoot),
1175
+ fs: deps.fs,
1176
+ query: options.query
1177
+ });
1178
+ }
1179
+ async function listAgentSearchSessions(options) {
1180
+ return renderAgentSearchList(await loadAgentSearchResults(options));
1181
+ }
1182
+ async function jsonAgentSearchSessions(options) {
1183
+ return renderAgentSearchJson(await loadAgentSearchResults(options));
1184
+ }
1185
+
943
1186
  // src/lib/process-lifecycle/exit-codes.ts
944
1187
  var SIGINT_EXIT_CODE = 130;
945
1188
  var SIGTERM_EXIT_CODE = 143;
@@ -1118,6 +1361,50 @@ function spawnManagedSubprocess(runner, command, args, options) {
1118
1361
  });
1119
1362
  }
1120
1363
 
1364
+ // src/lib/sanitize-cli-argument.ts
1365
+ var MAX_CLI_ARGUMENT_DISPLAY_LENGTH = 120;
1366
+ var ELLIPSIS_TOKEN = "...";
1367
+ var SENTINEL_UNDEFINED = "<undefined>";
1368
+ var SENTINEL_NULL = "<null>";
1369
+ var SENTINEL_EMPTY = "<empty>";
1370
+ var CONTROL_CHAR_UPPER_BOUND = 31;
1371
+ var DEL_CHAR_CODE = 127;
1372
+ var HEX_RADIX = 16;
1373
+ var HEX_PAD = 2;
1374
+ function formatHexEscape(code) {
1375
+ return String.raw`\x${code.toString(HEX_RADIX).padStart(HEX_PAD, "0")}`;
1376
+ }
1377
+ function nonStringSentinel(type) {
1378
+ return `<non-string:${type}>`;
1379
+ }
1380
+ function sanitizeCliArgument(input) {
1381
+ return truncate(escapeCliArgument(input));
1382
+ }
1383
+ function escapeCliArgument(input) {
1384
+ if (input === void 0) return SENTINEL_UNDEFINED;
1385
+ if (input === null) return SENTINEL_NULL;
1386
+ if (typeof input !== "string") return nonStringSentinel(typeof input);
1387
+ if (input.length === 0) return SENTINEL_EMPTY;
1388
+ return escapeControlCharacters(input);
1389
+ }
1390
+ function escapeControlCharacters(value) {
1391
+ let out = "";
1392
+ for (const char of value) {
1393
+ const code = char.codePointAt(0);
1394
+ if (code === void 0) continue;
1395
+ if (code <= CONTROL_CHAR_UPPER_BOUND || code === DEL_CHAR_CODE) {
1396
+ out += formatHexEscape(code);
1397
+ } else {
1398
+ out += char;
1399
+ }
1400
+ }
1401
+ return out;
1402
+ }
1403
+ function truncate(value) {
1404
+ if (value.length <= MAX_CLI_ARGUMENT_DISPLAY_LENGTH) return value;
1405
+ return value.slice(0, MAX_CLI_ARGUMENT_DISPLAY_LENGTH - ELLIPSIS_TOKEN.length) + ELLIPSIS_TOKEN;
1406
+ }
1407
+
1121
1408
  // src/interfaces/cli/foreground-launch.ts
1122
1409
  var FOREGROUND_LAUNCH_STDIO = "inherit";
1123
1410
  var LAUNCH_FAILURE_STATUS = 1;
@@ -1240,14 +1527,26 @@ async function runAgentResumePicker(candidates, renderPicker = render) {
1240
1527
  var AGENT_CLI = {
1241
1528
  commandName: "agent",
1242
1529
  resumeCommandName: "resume",
1530
+ searchCommandName: "search",
1243
1531
  flags: {
1244
1532
  latest: "--latest",
1245
1533
  list: "--list",
1246
1534
  json: "--json",
1247
- branch: "--branch"
1535
+ branch: "--branch",
1536
+ all: "--all",
1537
+ pickupId: "--pickup-id",
1538
+ contains: "--contains",
1539
+ sessionId: "--session-id",
1540
+ agent: "--agent",
1541
+ limit: "--limit"
1248
1542
  },
1249
1543
  optionArgs: {
1250
- branch: "--branch <name>"
1544
+ branch: "--branch <name>",
1545
+ pickupId: "--pickup-id <id>",
1546
+ contains: "--contains <literal>",
1547
+ sessionId: "--session-id <id>",
1548
+ agent: "--agent <kind>",
1549
+ limit: "--limit <count>"
1251
1550
  }
1252
1551
  };
1253
1552
  var AGENT_CLI_EXIT = {
@@ -1265,6 +1564,7 @@ var DEFAULT_AGENT_CLI_DEPENDENCIES = {
1265
1564
  );
1266
1565
  }
1267
1566
  };
1567
+ var POSITIVE_DECIMAL_INTEGER_PATTERN = /^[1-9][0-9]*$/;
1268
1568
  function writeOutput(invocation, output) {
1269
1569
  invocation.io.writeStdout(`${output}
1270
1570
  `);
@@ -1281,6 +1581,33 @@ function handleError(invocation, error) {
1281
1581
  function resumeScopeFromOptions(options) {
1282
1582
  return options.branch === void 0 ? worktreeResumeScope() : branchResumeScope(options.branch);
1283
1583
  }
1584
+ function parseSearchLimit(value) {
1585
+ if (!POSITIVE_DECIMAL_INTEGER_PATTERN.test(value)) {
1586
+ throw new Error(`agent search limit must be a positive integer: ${sanitizeCliArgument(value)}`);
1587
+ }
1588
+ const parsed = Number.parseInt(value, 10);
1589
+ if (!Number.isSafeInteger(parsed)) {
1590
+ throw new Error(`agent search limit must be a positive integer: ${sanitizeCliArgument(value)}`);
1591
+ }
1592
+ return parsed;
1593
+ }
1594
+ function parseSearchAgentKind(value) {
1595
+ if (value === AGENT_SESSION_KIND.CODEX || value === AGENT_SESSION_KIND.CLAUDE_CODE) {
1596
+ return value;
1597
+ }
1598
+ throw new Error(`agent search kind must be codex or claude-code: ${sanitizeCliArgument(value)}`);
1599
+ }
1600
+ function searchQueryFromOptions(options) {
1601
+ return {
1602
+ pickupId: options.pickupId,
1603
+ contains: options.contains,
1604
+ sessionId: options.sessionId,
1605
+ branch: options.branch,
1606
+ agent: options.agent === void 0 ? void 0 : parseSearchAgentKind(options.agent),
1607
+ all: options.all,
1608
+ limit: options.limit === void 0 ? AGENT_SEARCH_DEFAULT_LIMIT : parseSearchLimit(options.limit)
1609
+ };
1610
+ }
1284
1611
  async function dispatchInteractiveResume(mode, commandOptions, deps, invocation) {
1285
1612
  const candidates = await loadAgentResumeCandidates(commandOptions);
1286
1613
  if (candidates.length === 0) {
@@ -1307,12 +1634,14 @@ function createAgentDomain(deps = {}) {
1307
1634
  let requestedExitCode = AGENT_CLI_EXIT.SUCCESS;
1308
1635
  try {
1309
1636
  const mode = resolveAgentResumeMode(options);
1637
+ const productContext = invocation.resolveProductContext();
1310
1638
  if (mode === AGENT_RESUME_MODE.PICK && !resolvedDeps.isInteractiveTerminal()) {
1311
1639
  writeError(invocation, AGENT_RESUME_TEXT.INTERACTIVE_REQUIRED);
1312
1640
  requestedExitCode = AGENT_CLI_EXIT.FAILURE;
1313
1641
  } else {
1314
1642
  const commandOptions = {
1315
- cwd: invocation.resolveEffectiveInvocationDir(),
1643
+ cwd: productContext.effectiveInvocationDir,
1644
+ fallbackWorktreeRoot: productContext.productDir,
1316
1645
  scope: resumeScopeFromOptions(options),
1317
1646
  deps: resolvedDeps.resumeDeps
1318
1647
  };
@@ -1331,6 +1660,21 @@ function createAgentDomain(deps = {}) {
1331
1660
  }
1332
1661
  return invocation.io.exit(requestedExitCode);
1333
1662
  });
1663
+ agentCmd.command(AGENT_CLI.searchCommandName).description("Search Codex and Claude Code agent session transcripts for this product").option(AGENT_CLI.optionArgs.pickupId, "Search for an exact SPX pickup marker").option(AGENT_CLI.optionArgs.contains, "Search transcript content for a literal string").option(AGENT_CLI.optionArgs.sessionId, "Search for an agent session id").option(AGENT_CLI.optionArgs.branch, "Search for sessions started on the named branch").option(AGENT_CLI.optionArgs.agent, "Search only one agent kind").option(AGENT_CLI.flags.all, "Include sessions outside the recent-session window").option(AGENT_CLI.optionArgs.limit, "Maximum number of results").option(AGENT_CLI.flags.json, "Print matching sessions as JSON").action(async (options) => {
1664
+ try {
1665
+ const productContext = invocation.resolveProductContext();
1666
+ const commandOptions = {
1667
+ cwd: productContext.effectiveInvocationDir,
1668
+ fallbackProductScopeRoot: productContext.productDir,
1669
+ query: agentSearchQueryFromOptions(searchQueryFromOptions(options)),
1670
+ deps: resolvedDeps.searchDeps
1671
+ };
1672
+ const output = options.json === true ? await jsonAgentSearchSessions(commandOptions) : await listAgentSearchSessions(commandOptions);
1673
+ writeOutput(invocation, output);
1674
+ } catch (error) {
1675
+ handleError(invocation, error);
1676
+ }
1677
+ });
1334
1678
  }
1335
1679
  };
1336
1680
  }
@@ -2545,14 +2889,14 @@ async function compactRetrieveCommand(options) {
2545
2889
  }
2546
2890
 
2547
2891
  // src/commands/compact/store.ts
2548
- import { readFile } from "fs/promises";
2892
+ import { readFile as readFile2 } from "fs/promises";
2549
2893
  var UTF8_ENCODING = "utf8";
2550
2894
  async function compactStoreCommand(options) {
2551
2895
  const sessionToken = resolveCompactSessionToken(options.sessionId, options.env ?? process.env);
2552
2896
  if (sessionToken === void 0) return 1;
2553
2897
  let transcript;
2554
2898
  try {
2555
- transcript = await readFile(options.transcript, UTF8_ENCODING);
2899
+ transcript = await readFile2(options.transcript, UTF8_ENCODING);
2556
2900
  } catch {
2557
2901
  return 1;
2558
2902
  }
@@ -2608,7 +2952,7 @@ var compactDomain = {
2608
2952
  };
2609
2953
 
2610
2954
  // src/config/index.ts
2611
- import { readFile as readFile2 } from "fs/promises";
2955
+ import { readFile as readFile3 } from "fs/promises";
2612
2956
  import { join as join4 } from "path";
2613
2957
  import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
2614
2958
  import { parse as parseYaml, parseDocument as parseYamlDocument, stringify as stringifyYaml } from "yaml";
@@ -4269,7 +4613,7 @@ async function readProductConfigFile(productDir) {
4269
4613
  const path7 = join4(productDir, filename);
4270
4614
  let raw;
4271
4615
  try {
4272
- raw = await readFile2(path7, "utf8");
4616
+ raw = await readFile3(path7, "utf8");
4273
4617
  } catch (error) {
4274
4618
  if (isFileNotFound(error)) continue;
4275
4619
  return { ok: false, error: `failed to read ${filename}: ${toMessage(error)}` };
@@ -4553,7 +4897,7 @@ var configDomain = {
4553
4897
  };
4554
4898
 
4555
4899
  // src/interfaces/cli/diagnose.ts
4556
- import { readFile as readFile3 } from "fs/promises";
4900
+ import { readFile as readFile4 } from "fs/promises";
4557
4901
  import { Option } from "commander";
4558
4902
 
4559
4903
  // src/domains/diagnose/types.ts
@@ -6251,50 +6595,6 @@ var defaultSpxReachabilityProbe = {
6251
6595
  }
6252
6596
  };
6253
6597
 
6254
- // src/lib/sanitize-cli-argument.ts
6255
- var MAX_CLI_ARGUMENT_DISPLAY_LENGTH = 120;
6256
- var ELLIPSIS_TOKEN = "...";
6257
- var SENTINEL_UNDEFINED = "<undefined>";
6258
- var SENTINEL_NULL = "<null>";
6259
- var SENTINEL_EMPTY = "<empty>";
6260
- var CONTROL_CHAR_UPPER_BOUND = 31;
6261
- var DEL_CHAR_CODE = 127;
6262
- var HEX_RADIX = 16;
6263
- var HEX_PAD = 2;
6264
- function formatHexEscape(code) {
6265
- return String.raw`\x${code.toString(HEX_RADIX).padStart(HEX_PAD, "0")}`;
6266
- }
6267
- function nonStringSentinel(type) {
6268
- return `<non-string:${type}>`;
6269
- }
6270
- function sanitizeCliArgument(input) {
6271
- return truncate(escapeCliArgument(input));
6272
- }
6273
- function escapeCliArgument(input) {
6274
- if (input === void 0) return SENTINEL_UNDEFINED;
6275
- if (input === null) return SENTINEL_NULL;
6276
- if (typeof input !== "string") return nonStringSentinel(typeof input);
6277
- if (input.length === 0) return SENTINEL_EMPTY;
6278
- return escapeControlCharacters(input);
6279
- }
6280
- function escapeControlCharacters(value) {
6281
- let out = "";
6282
- for (const char of value) {
6283
- const code = char.codePointAt(0);
6284
- if (code === void 0) continue;
6285
- if (code <= CONTROL_CHAR_UPPER_BOUND || code === DEL_CHAR_CODE) {
6286
- out += formatHexEscape(code);
6287
- } else {
6288
- out += char;
6289
- }
6290
- }
6291
- return out;
6292
- }
6293
- function truncate(value) {
6294
- if (value.length <= MAX_CLI_ARGUMENT_DISPLAY_LENGTH) return value;
6295
- return value.slice(0, MAX_CLI_ARGUMENT_DISPLAY_LENGTH - ELLIPSIS_TOKEN.length) + ELLIPSIS_TOKEN;
6296
- }
6297
-
6298
6598
  // src/interfaces/cli/diagnose.ts
6299
6599
  var DIAGNOSE_CLI = {
6300
6600
  COMMAND: "diagnose",
@@ -6341,7 +6641,7 @@ var diagnoseDomain = {
6341
6641
  isTty: Boolean(process.stdout.isTTY)
6342
6642
  }),
6343
6643
  registry: defaultRegistry(),
6344
- fs: { readFile: (path7) => readFile3(path7, "utf8") }
6644
+ fs: { readFile: (path7) => readFile4(path7, "utf8") }
6345
6645
  });
6346
6646
  if (!result.ok) {
6347
6647
  handleError2(result.error, invocation.io);
@@ -7658,6 +7958,18 @@ async function readSealedJournalRunSet(scope2, options = {}) {
7658
7958
  }))
7659
7959
  };
7660
7960
  }
7961
+ async function findJournalRunBranchSlugs(scope2, options = {}) {
7962
+ const fs8 = options.fs ?? defaultFileSystem;
7963
+ const branches = await branchSlugs(scope2, fs8);
7964
+ if (!branches.ok) return branches;
7965
+ const matches = [];
7966
+ for (const branchSlug of branches.value) {
7967
+ const runFilePath = bindRunFilePath({ ...scope2, branchSlug });
7968
+ if (!runFilePath.ok) return runFilePath;
7969
+ if (await runFileExists(fs8, runFilePath.value)) matches.push(branchSlug);
7970
+ }
7971
+ return { ok: true, value: matches };
7972
+ }
7661
7973
  async function appendJournalEvent(ref, input, sink, options = {}) {
7662
7974
  const bound = await bindJournal(ref, options.fs);
7663
7975
  if (!bound.ok) return bound;
@@ -7736,6 +8048,7 @@ var JOURNAL_CLI_ERROR = {
7736
8048
  INVALID_READ_SET_EVENT_LIMIT: "journal read-set event limit must be a positive whole integer",
7737
8049
  INVALID_SEALED_FILTER: "journal list sealed filter is not registered",
7738
8050
  INVALID_TERMINAL_STATE_FILTER: "journal list terminal-state filter is not registered",
8051
+ RUN_TOKEN_AMBIGUOUS: "journal run token matches multiple branch scopes; rerun with --branch-slug",
7739
8052
  OPEN_HYDRATION_FAILED: "journal open failed to hydrate the pull request's prior runs"
7740
8053
  };
7741
8054
  var CURSOR_PATTERN = /^\d+$/;
@@ -7858,6 +8171,34 @@ function verbOptions(deps) {
7858
8171
  function runRef(context, runToken) {
7859
8172
  return { productDir: context.productDir, branchSlug: context.branchSlug, type: context.type, runToken };
7860
8173
  }
8174
+ async function inspectionRunRef(scope2, deps) {
8175
+ const context = await resolveJournalRunContext(scope2, deps);
8176
+ if (!context.ok) return context;
8177
+ if (scope2.branchSlug !== void 0) return { ok: true, value: runRef(context.value, scope2.runToken) };
8178
+ const branches = await findJournalRunBranchSlugs(
8179
+ {
8180
+ productDir: context.value.productDir,
8181
+ type: context.value.type,
8182
+ runToken: scope2.runToken
8183
+ },
8184
+ verbOptions(deps)
8185
+ );
8186
+ if (!branches.ok) return branches;
8187
+ if (branches.value.length === 1) {
8188
+ const branchSlug = branches.value[0];
8189
+ return {
8190
+ ok: true,
8191
+ value: {
8192
+ productDir: context.value.productDir,
8193
+ branchSlug,
8194
+ type: context.value.type,
8195
+ runToken: scope2.runToken
8196
+ }
8197
+ };
8198
+ }
8199
+ if (branches.value.length > 1) return { ok: false, error: JOURNAL_CLI_ERROR.RUN_TOKEN_AMBIGUOUS };
8200
+ return { ok: true, value: runRef(context.value, scope2.runToken) };
8201
+ }
7861
8202
  function okResult(output) {
7862
8203
  return { exitCode: JOURNAL_CLI_EXIT_CODE.OK, output };
7863
8204
  }
@@ -7974,9 +8315,9 @@ async function journalAppendCommand(scope2, input, binding, deps = {}) {
7974
8315
  async function journalReadCommand(scope2, fromCursor, deps = {}) {
7975
8316
  const cursor = parseJournalCursor(fromCursor);
7976
8317
  if (!cursor.ok) return errorResult(cursor.error);
7977
- const context = await resolveJournalRunContext(scope2, deps);
7978
- if (!context.ok) return errorResult(context.error);
7979
- const events = await readJournalEvents(runRef(context.value, scope2.runToken), cursor.value, verbOptions(deps));
8318
+ const ref = await inspectionRunRef(scope2, deps);
8319
+ if (!ref.ok) return errorResult(ref.error);
8320
+ const events = await readJournalEvents(ref.value, cursor.value, verbOptions(deps));
7980
8321
  if (!events.ok) return errorResult(events.error);
7981
8322
  return okResult(JSON.stringify(events.value));
7982
8323
  }
@@ -8025,10 +8366,10 @@ async function journalSealCommand(scope2, deps = {}) {
8025
8366
  return okResult(JSON.stringify({ sealed: true }));
8026
8367
  }
8027
8368
  async function journalRenderCommand(scope2, deps = {}) {
8028
- const context = await resolveJournalRunContext(scope2, deps);
8029
- if (!context.ok) return errorResult(context.error);
8369
+ const ref = await inspectionRunRef(scope2, deps);
8370
+ if (!ref.ok) return errorResult(ref.error);
8030
8371
  const rendered = await renderJournalRun(
8031
- runRef(context.value, scope2.runToken),
8372
+ ref.value,
8032
8373
  (events) => [...events],
8033
8374
  verbOptions(deps)
8034
8375
  );
@@ -8354,7 +8695,7 @@ function sessionOptionToken(option) {
8354
8695
  }
8355
8696
 
8356
8697
  // src/commands/session/archive.ts
8357
- import { mkdir, rename, stat as stat2 } from "fs/promises";
8698
+ import { mkdir, rename, stat as stat3 } from "fs/promises";
8358
8699
  import { dirname as dirname7, join as join8 } from "path";
8359
8700
 
8360
8701
  // src/domains/session/archive.ts
@@ -8667,7 +9008,7 @@ var SessionAlreadyArchivedError = class extends Error {
8667
9008
  };
8668
9009
  async function fileExists(path7) {
8669
9010
  try {
8670
- const stats = await stat2(path7);
9011
+ const stats = await stat3(path7);
8671
9012
  return stats.isFile();
8672
9013
  } catch {
8673
9014
  return false;
@@ -8709,7 +9050,7 @@ async function archiveCommand(options) {
8709
9050
  }
8710
9051
 
8711
9052
  // src/commands/session/delete.ts
8712
- import { stat as stat3, unlink } from "fs/promises";
9053
+ import { stat as stat4, unlink } from "fs/promises";
8713
9054
 
8714
9055
  // src/domains/session/delete.ts
8715
9056
  function resolveDeletePath(sessionId, existingPaths) {
@@ -8882,44 +9223,6 @@ function parseSessionId(id) {
8882
9223
  return date;
8883
9224
  }
8884
9225
 
8885
- // src/domains/session/types.ts
8886
- var SESSION_PRIORITY = {
8887
- HIGH: "high",
8888
- MEDIUM: "medium",
8889
- LOW: "low"
8890
- };
8891
- var SESSION_STATUSES = ["todo", "doing", "archive"];
8892
- var DEFAULT_LIST_STATUSES = ["doing", "todo"];
8893
- var SESSION_FILE_ENCODING = "utf-8";
8894
- var SESSION_FILE_ERROR_CODE = {
8895
- NOT_FOUND: "ENOENT"
8896
- };
8897
- var SESSION_OUTPUT_MARKER = {
8898
- HANDOFF_ID: "HANDOFF_ID",
8899
- PICKUP_ID: "PICKUP_ID",
8900
- SESSION_FILE: "SESSION_FILE"
8901
- };
8902
- function formatSessionOutputMarker(marker, value) {
8903
- return `<${marker}>${value}</${marker}>`;
8904
- }
8905
- var CLAIMABLE_STATUS = SESSION_STATUSES[0];
8906
- var PRIORITY_ORDER = {
8907
- [SESSION_PRIORITY.HIGH]: 0,
8908
- [SESSION_PRIORITY.MEDIUM]: 1,
8909
- [SESSION_PRIORITY.LOW]: 2
8910
- };
8911
- var DEFAULT_PRIORITY = SESSION_PRIORITY.MEDIUM;
8912
- var SESSION_FRONT_MATTER = {
8913
- PRIORITY: "priority",
8914
- GIT_REF: "git_ref",
8915
- GOAL: "goal",
8916
- NEXT_STEP: "next_step",
8917
- CREATED_AT: "created_at",
8918
- AGENT_SESSION_ID: "agent_session_id",
8919
- SPECS: "specs",
8920
- FILES: "files"
8921
- };
8922
-
8923
9226
  // src/domains/session/list.ts
8924
9227
  var FRONT_MATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n(?:---|\.\.\.)\r?\n?/;
8925
9228
  var SESSION_PRIORITY_VALUES = Object.values(SESSION_PRIORITY);
@@ -9158,7 +9461,7 @@ async function findExistingPaths(paths) {
9158
9461
  const existing = [];
9159
9462
  for (const path7 of paths) {
9160
9463
  try {
9161
- const stats = await stat3(path7);
9464
+ const stats = await stat4(path7);
9162
9465
  if (stats.isFile()) {
9163
9466
  existing.push(path7);
9164
9467
  }
@@ -9180,7 +9483,7 @@ async function deleteCommand(options) {
9180
9483
  }
9181
9484
 
9182
9485
  // src/commands/session/handoff.ts
9183
- import { mkdir as mkdir2, stat as stat4, writeFile } from "fs/promises";
9486
+ import { mkdir as mkdir2, stat as stat5, writeFile } from "fs/promises";
9184
9487
  import { join as join10, resolve as resolve6 } from "path";
9185
9488
  import { stringify as stringifyYaml3 } from "yaml";
9186
9489
 
@@ -9431,7 +9734,7 @@ async function rejectDirectoryInjectionEntries(entries, cwd) {
9431
9734
  if (entry.length === 0) continue;
9432
9735
  let entryIsDirectory = false;
9433
9736
  try {
9434
- entryIsDirectory = (await stat4(resolve6(cwd, entry))).isDirectory();
9737
+ entryIsDirectory = (await stat5(resolve6(cwd, entry))).isDirectory();
9435
9738
  } catch {
9436
9739
  continue;
9437
9740
  }
@@ -9489,7 +9792,7 @@ ${formatSessionOutputMarker(SESSION_OUTPUT_MARKER.SESSION_FILE, absolutePath)}`;
9489
9792
  }
9490
9793
 
9491
9794
  // src/commands/session/list.ts
9492
- import { readdir as readdir2, readFile as readFile4 } from "fs/promises";
9795
+ import { readdir as readdir3, readFile as readFile5 } from "fs/promises";
9493
9796
  import { join as join11 } from "path";
9494
9797
  var SESSION_LIST_FORMAT = {
9495
9798
  TEXT: "text",
@@ -9498,13 +9801,13 @@ var SESSION_LIST_FORMAT = {
9498
9801
  var SESSION_LIST_EMPTY_TEXT = "(no sessions)";
9499
9802
  async function loadSessionsFromDir(dir, status) {
9500
9803
  try {
9501
- const files = await readdir2(dir);
9804
+ const files = await readdir3(dir);
9502
9805
  const sessions = [];
9503
9806
  for (const file of files) {
9504
9807
  if (!file.endsWith(".md")) continue;
9505
9808
  const id = file.replace(".md", "");
9506
9809
  const filePath = join11(dir, file);
9507
- const content = await readFile4(filePath, SESSION_FILE_ENCODING);
9810
+ const content = await readFile5(filePath, SESSION_FILE_ENCODING);
9508
9811
  const metadata = parseSessionMetadata(content);
9509
9812
  sessions.push({
9510
9813
  id,
@@ -9567,7 +9870,7 @@ async function listCommand(options) {
9567
9870
  }
9568
9871
 
9569
9872
  // src/commands/session/pickup.ts
9570
- import { mkdir as mkdir3, readdir as readdir3, readFile as readFile5, rename as rename2 } from "fs/promises";
9873
+ import { mkdir as mkdir3, readdir as readdir4, readFile as readFile6, rename as rename2 } from "fs/promises";
9571
9874
  import { join as join12, resolve as resolve7 } from "path";
9572
9875
 
9573
9876
  // src/domains/session/pickup.ts
@@ -9607,8 +9910,8 @@ function selectBestSession(sessions) {
9607
9910
  var PICKUP_TARGET_STATUS = SESSION_STATUSES[1];
9608
9911
  var PICKUP_DEPS = {
9609
9912
  mkdir: mkdir3,
9610
- readdir: readdir3,
9611
- readFile: readFile5,
9913
+ readdir: readdir4,
9914
+ readFile: readFile6,
9612
9915
  rename: rename2
9613
9916
  };
9614
9917
  async function loadTodoSessions(config) {
@@ -9717,7 +10020,7 @@ async function loadPickCandidates(options) {
9717
10020
  }
9718
10021
 
9719
10022
  // src/commands/session/prune.ts
9720
- import { readdir as readdir4, readFile as readFile6, unlink as unlink2 } from "fs/promises";
10023
+ import { readdir as readdir5, readFile as readFile7, unlink as unlink2 } from "fs/promises";
9721
10024
  import { join as join13 } from "path";
9722
10025
 
9723
10026
  // src/domains/session/prune.ts
@@ -9762,13 +10065,13 @@ function validatePruneOptions(options) {
9762
10065
  }
9763
10066
  async function loadArchiveSessions(config) {
9764
10067
  try {
9765
- const files = await readdir4(config.archiveDir);
10068
+ const files = await readdir5(config.archiveDir);
9766
10069
  const sessions = [];
9767
10070
  for (const file of files) {
9768
10071
  if (!file.endsWith(".md")) continue;
9769
10072
  const id = file.replace(".md", "");
9770
10073
  const filePath = join13(config.archiveDir, file);
9771
- const content = await readFile6(filePath, SESSION_FILE_ENCODING);
10074
+ const content = await readFile7(filePath, SESSION_FILE_ENCODING);
9772
10075
  const metadata = parseSessionMetadata(content);
9773
10076
  sessions.push({
9774
10077
  id,
@@ -9817,7 +10120,7 @@ async function pruneCommand(options) {
9817
10120
  }
9818
10121
 
9819
10122
  // src/commands/session/release.ts
9820
- import { readdir as readdir5, rename as rename3 } from "fs/promises";
10123
+ import { readdir as readdir6, rename as rename3 } from "fs/promises";
9821
10124
 
9822
10125
  // src/domains/session/release.ts
9823
10126
  function buildReleasePaths(sessionId, config) {
@@ -9848,7 +10151,7 @@ var SESSION_RELEASE_OUTPUT = {
9848
10151
  };
9849
10152
  async function loadDoingSessions(config) {
9850
10153
  try {
9851
- const files = await readdir5(config.doingDir);
10154
+ const files = await readdir6(config.doingDir);
9852
10155
  return files.filter((file) => file.endsWith(".md")).map((file) => ({ id: file.replace(".md", "") }));
9853
10156
  } catch (error) {
9854
10157
  if (error instanceof Error && "code" in error && error.code === SESSION_FILE_ERROR_CODE.NOT_FOUND) {
@@ -9885,12 +10188,12 @@ async function releaseCommand(options) {
9885
10188
  }
9886
10189
 
9887
10190
  // src/commands/session/show.ts
9888
- import { readFile as readFile7, stat as stat5 } from "fs/promises";
10191
+ import { readFile as readFile8, stat as stat6 } from "fs/promises";
9889
10192
  async function findExistingPath(paths, _config) {
9890
10193
  for (let i = 0; i < paths.length; i++) {
9891
10194
  const filePath = paths[i];
9892
10195
  try {
9893
- const stats = await stat5(filePath);
10196
+ const stats = await stat6(filePath);
9894
10197
  if (stats.isFile()) {
9895
10198
  return { path: filePath, status: SEARCH_ORDER[i] };
9896
10199
  }
@@ -9905,7 +10208,7 @@ async function resolveSession(sessionId, config) {
9905
10208
  if (!found) {
9906
10209
  throw new SessionNotFoundError(sessionId);
9907
10210
  }
9908
- const content = await readFile7(found.path, SESSION_FILE_ENCODING);
10211
+ const content = await readFile8(found.path, SESSION_FILE_ENCODING);
9909
10212
  return { status: found.status, path: found.path, content };
9910
10213
  }
9911
10214
  async function showSingle(sessionId, config) {
@@ -10569,7 +10872,7 @@ var sessionDomain = {
10569
10872
  };
10570
10873
 
10571
10874
  // src/lib/spec-tree/index.ts
10572
- import { readdir as readdir6, readFile as readFile8 } from "fs/promises";
10875
+ import { readdir as readdir7, readFile as readFile9 } from "fs/promises";
10573
10876
  import { join as join14 } from "path";
10574
10877
  var SPEC_TREE_FIELD_KEY = {
10575
10878
  VERSION: "version",
@@ -10654,7 +10957,7 @@ function createFilesystemSpecTreeSource(options) {
10654
10957
  if (ref.path === void 0) {
10655
10958
  throw new Error("Filesystem source refs require a path");
10656
10959
  }
10657
- return readFile8(join14(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);
10960
+ return readFile9(join14(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);
10658
10961
  }
10659
10962
  };
10660
10963
  }
@@ -10945,7 +11248,7 @@ async function* readFilesystemSourceEntries(productDir, registry, schemaVersions
10945
11248
  async function* walkFilesystemDirectory(context) {
10946
11249
  let entries;
10947
11250
  try {
10948
- entries = await readdir6(context.absolutePath, { withFileTypes: true });
11251
+ entries = await readdir7(context.absolutePath, { withFileTypes: true });
10949
11252
  } catch (error) {
10950
11253
  if (isFileNotFound2(error)) return;
10951
11254
  throw error;
@@ -11117,7 +11420,7 @@ function formatNextNode(node) {
11117
11420
  }
11118
11421
 
11119
11422
  // src/commands/test/discovery.ts
11120
- import { readdir as readdir7 } from "fs/promises";
11423
+ import { readdir as readdir8 } from "fs/promises";
11121
11424
  import { join as join15, relative as relative2, sep as sep2 } from "path";
11122
11425
  var TESTS_DIRECTORY_NAME = SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME;
11123
11426
  var SPEC_ROOT_DIRECTORY = SPEC_TREE_CONFIG.ROOT_DIRECTORY;
@@ -11131,7 +11434,7 @@ async function discoverTestFiles(productDir) {
11131
11434
  async function collectTestFiles(directory, insideTestsDir, found) {
11132
11435
  let entries;
11133
11436
  try {
11134
- entries = await readdir7(directory, { withFileTypes: true });
11437
+ entries = await readdir8(directory, { withFileTypes: true });
11135
11438
  } catch (error) {
11136
11439
  if (hasErrorCode2(error, ERROR_CODE_NOT_FOUND2)) return;
11137
11440
  throw error;
@@ -12542,7 +12845,7 @@ function createNodeStatusProvider(productDir) {
12542
12845
  }
12543
12846
 
12544
12847
  // src/lib/node-status/update.ts
12545
- import { mkdir as mkdir4, readdir as readdir8, rm, writeFile as writeFile2 } from "fs/promises";
12848
+ import { mkdir as mkdir4, readdir as readdir9, rm, writeFile as writeFile2 } from "fs/promises";
12546
12849
  import { dirname as dirname8, join as join21 } from "path";
12547
12850
 
12548
12851
  // src/git/tracked-paths.ts
@@ -12666,7 +12969,7 @@ async function collectNodeStatusFiles(directory) {
12666
12969
  }
12667
12970
  async function readDirectoryEntries(directory) {
12668
12971
  try {
12669
- return await readdir8(directory, { withFileTypes: true });
12972
+ return await readdir9(directory, { withFileTypes: true });
12670
12973
  } catch (error) {
12671
12974
  if (isNodeError3(error) && error.code === "ENOENT") return [];
12672
12975
  throw error;
@@ -13275,7 +13578,7 @@ var testingRegistry = {
13275
13578
 
13276
13579
  // src/interfaces/cli/test-runner-deps.ts
13277
13580
  import { createWriteStream } from "fs";
13278
- import { mkdtemp, readFile as readFile9 } from "fs/promises";
13581
+ import { mkdtemp, readFile as readFile10 } from "fs/promises";
13279
13582
  import { tmpdir } from "os";
13280
13583
  import { join as join23 } from "path";
13281
13584
  import { finished } from "stream/promises";
@@ -13325,7 +13628,7 @@ function createRunnerDepsFor(productDir, outStream = process.stdout) {
13325
13628
  }
13326
13629
  function createRelatedDepsFor(productDir) {
13327
13630
  const runCommand = createRelatedCommandRunner(productDir);
13328
- return () => ({ runCommand, readFile: (path7) => readFile9(join23(productDir, path7), "utf8") });
13631
+ return () => ({ runCommand, readFile: (path7) => readFile10(join23(productDir, path7), "utf8") });
13329
13632
  }
13330
13633
  function artifactFileName(index, suffix) {
13331
13634
  return `${index.toString(ARTIFACT_INDEX_RADIX).padStart(ARTIFACT_INDEX_WIDTH, "0")}-${suffix}`;
@@ -17025,11 +17328,11 @@ function formatLintResult(result, quiet, durationMs) {
17025
17328
  }
17026
17329
 
17027
17330
  // src/validation/literal/index.ts
17028
- import { readFile as readFile11 } from "fs/promises";
17331
+ import { readFile as readFile12 } from "fs/promises";
17029
17332
  import { isAbsolute as isAbsolute9, relative as relative7, resolve as resolve10 } from "path";
17030
17333
 
17031
17334
  // src/lib/file-inclusion/pipeline.ts
17032
- import { readdir as readdir9, readFile as readFile10, stat as stat6 } from "fs/promises";
17335
+ import { readdir as readdir10, readFile as readFile11, stat as stat7 } from "fs/promises";
17033
17336
  import { join as join33, relative as relative6, sep as sep3 } from "path";
17034
17337
 
17035
17338
  // src/lib/file-inclusion/ignore-source.ts
@@ -17335,7 +17638,7 @@ function isNodeError4(err) {
17335
17638
  }
17336
17639
  async function isDirectory(absolutePath) {
17337
17640
  try {
17338
- return (await stat6(absolutePath)).isDirectory();
17641
+ return (await stat7(absolutePath)).isDirectory();
17339
17642
  } catch (err) {
17340
17643
  if (isNodeError4(err) && (err.code === "ENOENT" || err.code === "ENOTDIR")) {
17341
17644
  return false;
@@ -17345,7 +17648,7 @@ async function isDirectory(absolutePath) {
17345
17648
  }
17346
17649
  async function isGitdirPointerFile(absolutePath) {
17347
17650
  try {
17348
- const content = await readFile10(absolutePath, "utf8");
17651
+ const content = await readFile11(absolutePath, "utf8");
17349
17652
  return content.startsWith(GITDIR_POINTER_PREFIX);
17350
17653
  } catch (err) {
17351
17654
  if (isNodeError4(err) && (err.code === "ENOENT" || err.code === "ENOTDIR")) {
@@ -17356,7 +17659,7 @@ async function isGitdirPointerFile(absolutePath) {
17356
17659
  }
17357
17660
  async function readDirectoryEntries2(absoluteDir) {
17358
17661
  try {
17359
- return await readdir9(absoluteDir, { withFileTypes: true });
17662
+ return await readdir10(absoluteDir, { withFileTypes: true });
17360
17663
  } catch (err) {
17361
17664
  if (isNodeError4(err) && (err.code === "ENOENT" || err.code === "ENOTDIR")) {
17362
17665
  return [];
@@ -17969,7 +18272,7 @@ async function validateLiteralReuse(input) {
17969
18272
  }
17970
18273
  async function readSafe(path7) {
17971
18274
  try {
17972
- return await readFile11(path7, "utf8");
18275
+ return await readFile12(path7, "utf8");
17973
18276
  } catch (err) {
17974
18277
  if (typeof err === "object" && err !== null && "code" in err) {
17975
18278
  const code = err.code;
@@ -19264,7 +19567,7 @@ var verificationContextDomain = {
19264
19567
  };
19265
19568
 
19266
19569
  // src/interfaces/cli/verify.ts
19267
- import { readFile as readFile12 } from "fs/promises";
19570
+ import { readFile as readFile13 } from "fs/promises";
19268
19571
 
19269
19572
  // src/commands/verify/cli.ts
19270
19573
  import { dirname as dirname12 } from "path";
@@ -19741,7 +20044,7 @@ async function readStdinText() {
19741
20044
  }
19742
20045
  async function readCliSource(source) {
19743
20046
  if (source === VERIFY_INPUT_SOURCE.STDIN) return readStdinText();
19744
- return readFile12(source, CLI_SOURCE_ENCODING);
20047
+ return readFile13(source, CLI_SOURCE_ENCODING);
19745
20048
  }
19746
20049
  var verifyDomain = {
19747
20050
  name: VERIFY_CLI.commandName,
@@ -19927,11 +20230,11 @@ function renderTextStatusChild(record6) {
19927
20230
  }
19928
20231
 
19929
20232
  // src/lib/worktree-path-info.ts
19930
- import { stat as stat7 } from "fs/promises";
20233
+ import { stat as stat8 } from "fs/promises";
19931
20234
  var defaultWorktreePathInfo = {
19932
20235
  isExistingNonDirectory: async (path7) => {
19933
20236
  try {
19934
- const pathStats = await stat7(path7);
20237
+ const pathStats = await stat8(path7);
19935
20238
  return !pathStats.isDirectory();
19936
20239
  } catch {
19937
20240
  return false;