@outcomeeng/spx 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +1157 -548
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -91,120 +91,394 @@ var DEFAULT_CLI_IO = {
91
91
  exit: (exitCode) => process.exit(exitCode)
92
92
  };
93
93
 
94
- // src/commands/claude/init.ts
95
- import { execa } from "execa";
96
- async function initCommand(options = {}) {
97
- const cwd = options.cwd || CONFIG_PROCESS_CWD.read();
98
- try {
99
- const { stdout: listOutput } = await execa(
100
- "claude",
101
- ["plugin", "marketplace", "list"],
102
- { cwd }
103
- );
104
- const exists = listOutput.includes("outcomeeng");
105
- if (!exists) {
106
- await execa(
107
- "claude",
108
- ["plugin", "marketplace", "add", "outcomeeng/plugins"],
109
- { cwd }
110
- );
111
- return "\u2713 outcomeeng marketplace installed successfully\n\nRun 'claude plugin marketplace list' to view all marketplaces.";
112
- } else {
113
- await execa("claude", ["plugin", "marketplace", "update", "outcomeeng"], {
114
- cwd
115
- });
116
- return "\u2713 outcomeeng marketplace updated successfully\n\nThe marketplace is now up to date.";
94
+ // src/interfaces/cli/agent.ts
95
+ import { inspect } from "util";
96
+
97
+ // src/commands/agent/resume.ts
98
+ import { readdir, readFile, stat } from "fs/promises";
99
+ import { homedir } from "os";
100
+
101
+ // src/domains/agent/protocol.ts
102
+ var AGENT_SESSION_KIND = {
103
+ CODEX: "codex",
104
+ CLAUDE_CODE: "claude-code"
105
+ };
106
+ var AGENT_SESSION_LABEL = {
107
+ [AGENT_SESSION_KIND.CODEX]: "Codex",
108
+ [AGENT_SESSION_KIND.CLAUDE_CODE]: "Claude Code"
109
+ };
110
+ var AGENT_RESUME_COMMAND = {
111
+ CODEX_BINARY: "codex",
112
+ CODEX_RESUME: "resume",
113
+ CLAUDE_BINARY: "claude",
114
+ CLAUDE_RESUME: "--resume"
115
+ };
116
+ var AGENT_SESSION_STORE = {
117
+ CODEX_DIR: ".codex",
118
+ CODEX_SESSIONS_DIR: "sessions",
119
+ CLAUDE_DIR: ".claude",
120
+ CLAUDE_PROJECTS_DIR: "projects",
121
+ JSONL_EXTENSION: ".jsonl",
122
+ TEXT_ENCODING: "utf8"
123
+ };
124
+ var AGENT_RESUME_LIMITS = {
125
+ RECENT_DAYS: 7,
126
+ DISPLAYED_CANDIDATES: 20,
127
+ HOURS_PER_DAY: 24,
128
+ MINUTES_PER_HOUR: 60,
129
+ SECONDS_PER_MINUTE: 60,
130
+ MILLISECONDS_PER_SECOND: 1e3,
131
+ ROOT_RESOLUTION_CONCURRENCY: 8
132
+ };
133
+ var AGENT_RESUME_MODE = {
134
+ PICK: "pick",
135
+ LATEST: "latest",
136
+ LIST: "list",
137
+ JSON: "json"
138
+ };
139
+ var AGENT_RESUME_TEXT = {
140
+ NO_MATCHES: "No matching agent sessions found.",
141
+ INTERACTIVE_REQUIRED: "agent resume requires an interactive terminal.",
142
+ MODE_CONFLICT: "Choose only one resume mode"
143
+ };
144
+ var AGENT_SESSION_JSON_FIELDS = {
145
+ TIMESTAMP: "timestamp",
146
+ TYPE: "type",
147
+ CWD: "cwd",
148
+ ORIGINATOR: "originator",
149
+ SOURCE: "source",
150
+ SESSION_ID: "session_id",
151
+ SESSION_ID_CAMEL: "sessionId",
152
+ ID: "id",
153
+ PAYLOAD: "payload",
154
+ GIT_BRANCH: "gitBranch",
155
+ THREAD_SOURCE: "thread_source"
156
+ };
157
+ var AGENT_SESSION_ROW_TYPE = {
158
+ CODEX_SESSION_META: "session_meta"
159
+ };
160
+ var CODEX_SESSION_ORIGINATOR = {
161
+ TUI: "codex-tui",
162
+ CLI: "codex_cli",
163
+ VSCODE: "codex_vscode",
164
+ VSCODE_HYPHEN: "codex-vscode",
165
+ EXEC: "codex-exec"
166
+ };
167
+ var AGENT_RESUME_RECENT_WINDOW_MS = AGENT_RESUME_LIMITS.RECENT_DAYS * AGENT_RESUME_LIMITS.HOURS_PER_DAY * AGENT_RESUME_LIMITS.MINUTES_PER_HOUR * AGENT_RESUME_LIMITS.SECONDS_PER_MINUTE * AGENT_RESUME_LIMITS.MILLISECONDS_PER_SECOND;
168
+
169
+ // src/domains/agent/resume.ts
170
+ import { resolve as resolve3 } from "path";
171
+ var AGENT_RESUME_PICKER_ACTION = {
172
+ MOVE_UP: "move-up",
173
+ MOVE_DOWN: "move-down",
174
+ CHOOSE: "choose",
175
+ QUIT: "quit",
176
+ IGNORE: "ignore"
177
+ };
178
+ var FIRST_PICKER_INDEX = 0;
179
+ var PICKER_MOVE_UP_DELTA = -1;
180
+ var PICKER_MOVE_DOWN_DELTA = 1;
181
+ var PICKER_QUIT_INPUT = "q";
182
+ var AgentResumeModeError = class extends Error {
183
+ constructor(selectedModes) {
184
+ super(`${AGENT_RESUME_TEXT.MODE_CONFLICT}: ${selectedModes.join(", ")}`);
185
+ this.selectedModes = selectedModes;
186
+ this.name = "AgentResumeModeError";
187
+ }
188
+ selectedModes;
189
+ };
190
+ function resolveAgentResumeMode(flags) {
191
+ const selected = [];
192
+ if (flags.latest === true) selected.push(AGENT_RESUME_MODE.LATEST);
193
+ if (flags.list === true) selected.push(AGENT_RESUME_MODE.LIST);
194
+ if (flags.json === true) selected.push(AGENT_RESUME_MODE.JSON);
195
+ if (selected.length > 1) {
196
+ throw new AgentResumeModeError(selected);
197
+ }
198
+ return selected[0] ?? AGENT_RESUME_MODE.PICK;
199
+ }
200
+ function initialAgentResumePickerState() {
201
+ return { selectedIndex: FIRST_PICKER_INDEX };
202
+ }
203
+ function resolveAgentResumePickerAction(input) {
204
+ if (input.upArrow) return AGENT_RESUME_PICKER_ACTION.MOVE_UP;
205
+ if (input.downArrow) return AGENT_RESUME_PICKER_ACTION.MOVE_DOWN;
206
+ if (input.return) return AGENT_RESUME_PICKER_ACTION.CHOOSE;
207
+ if (input.escape || input.input === PICKER_QUIT_INPUT) return AGENT_RESUME_PICKER_ACTION.QUIT;
208
+ return AGENT_RESUME_PICKER_ACTION.IGNORE;
209
+ }
210
+ function reduceAgentResumePickerState(state, action, candidateCount) {
211
+ if (action === AGENT_RESUME_PICKER_ACTION.MOVE_UP) {
212
+ return moveAgentResumePickerSelection(state, PICKER_MOVE_UP_DELTA, candidateCount);
213
+ }
214
+ if (action === AGENT_RESUME_PICKER_ACTION.MOVE_DOWN) {
215
+ return moveAgentResumePickerSelection(state, PICKER_MOVE_DOWN_DELTA, candidateCount);
216
+ }
217
+ return state;
218
+ }
219
+ function moveAgentResumePickerSelection(state, delta, candidateCount) {
220
+ const lastIndex = Math.max(candidateCount - 1, FIRST_PICKER_INDEX);
221
+ const nextIndex = Math.min(Math.max(state.selectedIndex + delta, FIRST_PICKER_INDEX), lastIndex);
222
+ return { selectedIndex: nextIndex };
223
+ }
224
+ function codexSessionStoreDir(homeDir) {
225
+ return resolve3(homeDir, AGENT_SESSION_STORE.CODEX_DIR, AGENT_SESSION_STORE.CODEX_SESSIONS_DIR);
226
+ }
227
+ function claudeCodeSessionStoreDir(homeDir) {
228
+ return resolve3(homeDir, AGENT_SESSION_STORE.CLAUDE_DIR, AGENT_SESSION_STORE.CLAUDE_PROJECTS_DIR);
229
+ }
230
+ async function discoverAgentResumeCandidates(options) {
231
+ const invocationRoot = await options.resolveWorktreeRoot(options.invocationDir);
232
+ if (invocationRoot === null) {
233
+ return [];
234
+ }
235
+ const drafts = [
236
+ ...await discoverCodexResumeCandidates(
237
+ codexSessionStoreDir(options.homeDir),
238
+ options.fs,
239
+ options.nowMs
240
+ ),
241
+ ...await discoverClaudeCodeResumeCandidates(
242
+ claudeCodeSessionStoreDir(options.homeDir),
243
+ options.fs,
244
+ options.nowMs
245
+ )
246
+ ];
247
+ const sortedDrafts = [...drafts];
248
+ sortedDrafts.sort(compareCandidates);
249
+ const rootResults = await mapWithConcurrency(
250
+ sortedDrafts,
251
+ AGENT_RESUME_LIMITS.ROOT_RESOLUTION_CONCURRENCY,
252
+ async (candidate) => ({
253
+ candidate,
254
+ root: await options.resolveWorktreeRoot(candidate.cwd)
255
+ })
256
+ );
257
+ return rootResults.filter((result) => result.root !== null && samePath(result.root, invocationRoot)).map((result) => result.candidate).slice(0, AGENT_RESUME_LIMITS.DISPLAYED_CANDIDATES);
258
+ }
259
+ function buildAgentResumeLaunchCommand(candidate) {
260
+ if (candidate.agent === AGENT_SESSION_KIND.CODEX) {
261
+ return {
262
+ command: AGENT_RESUME_COMMAND.CODEX_BINARY,
263
+ args: [AGENT_RESUME_COMMAND.CODEX_RESUME, candidate.sessionId],
264
+ cwd: candidate.cwd
265
+ };
266
+ }
267
+ return {
268
+ command: AGENT_RESUME_COMMAND.CLAUDE_BINARY,
269
+ args: [AGENT_RESUME_COMMAND.CLAUDE_RESUME, candidate.sessionId],
270
+ cwd: candidate.cwd
271
+ };
272
+ }
273
+ function renderAgentResumeList(candidates) {
274
+ if (candidates.length === 0) {
275
+ return AGENT_RESUME_TEXT.NO_MATCHES;
276
+ }
277
+ return candidates.map((candidate) => {
278
+ const updatedAt = candidate.updatedAt ?? new Date(candidate.modifiedAtMs).toISOString();
279
+ return `${updatedAt} ${AGENT_SESSION_LABEL[candidate.agent]} ${candidate.sessionId} ${candidate.cwd}`;
280
+ }).join("\n");
281
+ }
282
+ function renderAgentResumeJson(candidates) {
283
+ return JSON.stringify(candidates, null, 2);
284
+ }
285
+ async function discoverCodexResumeCandidates(root, fs8, nowMs) {
286
+ return discoverStoreCandidates(root, fs8, nowMs, parseCodexCandidateFile);
287
+ }
288
+ async function discoverClaudeCodeResumeCandidates(root, fs8, nowMs) {
289
+ return discoverStoreCandidates(root, fs8, nowMs, parseClaudeCodeCandidateFile);
290
+ }
291
+ async function discoverStoreCandidates(root, fs8, nowMs, parseCandidate) {
292
+ const files = await collectJsonlFiles(root, fs8);
293
+ const candidates = [];
294
+ for (const file of files) {
295
+ const stat7 = await fs8.stat(file).catch(() => null);
296
+ if (stat7 === null || !isRecentAgentSessionMtime(stat7.mtimeMs, nowMs)) {
297
+ continue;
117
298
  }
118
- } catch (error) {
119
- if (error instanceof Error) {
120
- if (error.message.includes("ENOENT") || error.message.includes("command not found")) {
121
- throw new Error(
122
- "Claude CLI not found. Please install Claude Code first.\n\nVisit: https://docs.anthropic.com/claude-code"
123
- );
124
- }
125
- throw new Error(`Failed to initialize marketplace: ${error.message}`);
299
+ const content = await fs8.readFile(file).catch(() => null);
300
+ if (content === null) {
301
+ continue;
302
+ }
303
+ const candidate = parseCandidate(file, content, stat7.mtimeMs);
304
+ if (candidate !== null) {
305
+ candidates.push(candidate);
126
306
  }
127
- throw error;
128
307
  }
308
+ return candidates;
129
309
  }
130
-
131
- // src/lib/claude/permissions/discovery.ts
132
- import fs from "fs/promises";
133
- import path from "path";
134
- async function findSettingsFiles(root, visited = /* @__PURE__ */ new Set()) {
135
- const normalizedRoot = path.resolve(root.replace(/^~/, process.env.HOME || "~"));
136
- if (visited.has(normalizedRoot)) {
137
- return [];
310
+ async function collectJsonlFiles(root, fs8) {
311
+ const entries = await fs8.readDir(root).catch(() => []);
312
+ const files = [];
313
+ for (const entry of entries) {
314
+ const child = resolve3(root, entry.name);
315
+ if (entry.isDirectory) {
316
+ files.push(...await collectJsonlFiles(child, fs8));
317
+ } else if (entry.isFile && entry.name.endsWith(AGENT_SESSION_STORE.JSONL_EXTENSION)) {
318
+ files.push(child);
319
+ }
320
+ }
321
+ return files;
322
+ }
323
+ function isRecentAgentSessionMtime(modifiedAtMs, nowMs) {
324
+ return modifiedAtMs <= nowMs && nowMs - modifiedAtMs <= AGENT_RESUME_RECENT_WINDOW_MS;
325
+ }
326
+ function parseCodexCandidateFile(sourcePath, content, modifiedAtMs) {
327
+ let sessionId = null;
328
+ let cwd = null;
329
+ let updatedAt = null;
330
+ let isInteractiveSession = false;
331
+ for (const line of content.split("\n")) {
332
+ const row = parseJsonObject(line);
333
+ if (row === null) {
334
+ continue;
335
+ }
336
+ isInteractiveSession = isCodexInteractiveSessionRow(row) || isInteractiveSession;
337
+ sessionId ??= firstString(row, [
338
+ [AGENT_SESSION_JSON_FIELDS.SESSION_ID],
339
+ [AGENT_SESSION_JSON_FIELDS.ID],
340
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.SESSION_ID],
341
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.ID]
342
+ ]);
343
+ cwd = firstString(row, [
344
+ [AGENT_SESSION_JSON_FIELDS.CWD],
345
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.CWD]
346
+ ]) ?? cwd;
347
+ updatedAt = maxIsoTimestamp(updatedAt, firstString(row, [[AGENT_SESSION_JSON_FIELDS.TIMESTAMP]]));
348
+ }
349
+ if (!isInteractiveSession || sessionId === null || cwd === null) {
350
+ return null;
351
+ }
352
+ return {
353
+ agent: AGENT_SESSION_KIND.CODEX,
354
+ sessionId,
355
+ cwd,
356
+ sourcePath,
357
+ modifiedAtMs,
358
+ updatedAt,
359
+ branch: null
360
+ };
361
+ }
362
+ function isCodexInteractiveSessionRow(row) {
363
+ if (firstString(row, [[AGENT_SESSION_JSON_FIELDS.TYPE]]) !== AGENT_SESSION_ROW_TYPE.CODEX_SESSION_META) {
364
+ return false;
365
+ }
366
+ const originator = firstString(row, [
367
+ [AGENT_SESSION_JSON_FIELDS.ORIGINATOR],
368
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.ORIGINATOR]
369
+ ]);
370
+ return originator === CODEX_SESSION_ORIGINATOR.TUI || originator === CODEX_SESSION_ORIGINATOR.CLI || originator === CODEX_SESSION_ORIGINATOR.VSCODE || originator === CODEX_SESSION_ORIGINATOR.VSCODE_HYPHEN;
371
+ }
372
+ function parseClaudeCodeCandidateFile(sourcePath, content, modifiedAtMs) {
373
+ let sessionId = null;
374
+ let cwd = null;
375
+ let updatedAt = null;
376
+ let branch = null;
377
+ for (const line of content.split("\n")) {
378
+ const row = parseJsonObject(line);
379
+ if (row === null) {
380
+ continue;
381
+ }
382
+ sessionId ??= firstString(row, [
383
+ [AGENT_SESSION_JSON_FIELDS.SESSION_ID_CAMEL],
384
+ [AGENT_SESSION_JSON_FIELDS.SESSION_ID],
385
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.SESSION_ID_CAMEL],
386
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.SESSION_ID]
387
+ ]);
388
+ cwd = firstString(row, [
389
+ [AGENT_SESSION_JSON_FIELDS.CWD],
390
+ [AGENT_SESSION_JSON_FIELDS.PAYLOAD, AGENT_SESSION_JSON_FIELDS.CWD]
391
+ ]) ?? cwd;
392
+ updatedAt = maxIsoTimestamp(updatedAt, firstString(row, [[AGENT_SESSION_JSON_FIELDS.TIMESTAMP]]));
393
+ branch = firstString(row, [[AGENT_SESSION_JSON_FIELDS.GIT_BRANCH]]) ?? branch;
394
+ }
395
+ if (sessionId === null || cwd === null) {
396
+ return null;
397
+ }
398
+ return {
399
+ agent: AGENT_SESSION_KIND.CLAUDE_CODE,
400
+ sessionId,
401
+ cwd,
402
+ sourcePath,
403
+ modifiedAtMs,
404
+ updatedAt,
405
+ branch
406
+ };
407
+ }
408
+ function parseJsonObject(line) {
409
+ const trimmed = line.trim();
410
+ if (trimmed.length === 0) {
411
+ return null;
138
412
  }
139
- visited.add(normalizedRoot);
140
413
  try {
141
- return await findSettingsFilesInDirectory(normalizedRoot, visited);
142
- } catch (error) {
143
- throw discoveryError(normalizedRoot, error);
414
+ const parsed = JSON.parse(trimmed);
415
+ return isRecord(parsed) ? parsed : null;
416
+ } catch {
417
+ return null;
144
418
  }
145
419
  }
146
- async function findSettingsFilesInDirectory(normalizedRoot, visited) {
147
- const stats = await fs.stat(normalizedRoot);
148
- if (!stats.isDirectory()) {
149
- throw new Error(`Path is not a directory: ${normalizedRoot}`);
420
+ function firstString(row, paths) {
421
+ for (const path7 of paths) {
422
+ const value = valueAtPath(row, path7);
423
+ if (typeof value === "string" && value.length > 0) {
424
+ return value;
425
+ }
150
426
  }
151
- const entries = await fs.readdir(normalizedRoot, { withFileTypes: true });
152
- const results = [];
153
- for (const entry of entries) {
154
- results.push(...await settingsFilesForEntry(normalizedRoot, entry, visited));
427
+ return null;
428
+ }
429
+ function valueAtPath(row, path7) {
430
+ let current = row;
431
+ for (const segment of path7) {
432
+ if (!isRecord(current)) {
433
+ return void 0;
434
+ }
435
+ current = current[segment];
155
436
  }
156
- return results;
437
+ return current;
157
438
  }
158
- async function settingsFilesForEntry(normalizedRoot, entry, visited) {
159
- if (!entry.isDirectory()) return [];
160
- const fullPath = path.join(normalizedRoot, entry.name);
161
- if (entry.name === ".claude") {
162
- const settingsPath = path.join(fullPath, "settings.local.json");
163
- return await isValidSettingsFile(settingsPath) ? [settingsPath] : [];
439
+ function isRecord(value) {
440
+ return typeof value === "object" && value !== null && !Array.isArray(value);
441
+ }
442
+ function maxIsoTimestamp(left, right) {
443
+ if (right === null) {
444
+ return left;
164
445
  }
165
- return findSettingsFiles(fullPath, visited);
446
+ if (left === null) {
447
+ return right;
448
+ }
449
+ return Date.parse(right) > Date.parse(left) ? right : left;
166
450
  }
167
- function discoveryError(normalizedRoot, error) {
168
- if (!(error instanceof Error)) return new Error(unknownErrorMessage(error));
169
- if (error.message.includes("ENOENT")) return new Error(`Directory not found: ${normalizedRoot}`);
170
- if (error.message.includes("EACCES")) return new Error(`Permission denied: ${normalizedRoot}`);
171
- return new Error(`Failed to search directory "${normalizedRoot}": ${error.message}`);
451
+ function compareCandidates(left, right) {
452
+ const modifiedDiff = right.modifiedAtMs - left.modifiedAtMs;
453
+ if (modifiedDiff !== 0) {
454
+ return modifiedDiff;
455
+ }
456
+ return `${left.agent}:${left.sessionId}`.localeCompare(`${right.agent}:${right.sessionId}`);
172
457
  }
173
- function unknownErrorMessage(error) {
174
- if (typeof error === "string") return error;
175
- if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") return error.toString();
176
- if (typeof error === "symbol") return error.description ?? "Symbol()";
177
- if (error === void 0) return "undefined";
178
- return Object.prototype.toString.call(error);
458
+ function samePath(left, right) {
459
+ return resolve3(left) === resolve3(right);
179
460
  }
180
- async function isValidSettingsFile(filePath) {
181
- try {
182
- await fs.access(filePath, fs.constants.R_OK);
183
- const stats = await fs.stat(filePath);
184
- if (!stats.isFile()) {
185
- return false;
461
+ async function mapWithConcurrency(items, concurrency, mapper) {
462
+ const results = new Array(items.length);
463
+ let nextIndex = 0;
464
+ async function worker() {
465
+ for (; ; ) {
466
+ const index = nextIndex;
467
+ nextIndex += 1;
468
+ if (index >= items.length) {
469
+ return;
470
+ }
471
+ results[index] = await mapper(items[index]);
186
472
  }
187
- return path.extname(filePath) === ".json";
188
- } catch {
189
- return false;
190
473
  }
474
+ const workerCount = Math.min(Math.max(1, concurrency), items.length);
475
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
476
+ return results;
191
477
  }
192
478
 
193
- // src/lib/state-store/index.ts
194
- import { createHash, randomBytes as nodeRandomBytes } from "crypto";
195
- import { constants as fsConstants } from "fs";
196
- import {
197
- lstat as nodeLstat,
198
- mkdir as nodeMkdir,
199
- open as nodeOpen,
200
- readdir as nodeReaddir,
201
- rm as nodeRm
202
- } from "fs/promises";
203
- import { dirname as dirname2, join as join2 } from "path";
204
-
205
479
  // src/git/root.ts
206
- import { execa as execa2 } from "execa";
207
- import { basename, dirname, isAbsolute, join, resolve as resolve3 } from "path";
480
+ import { execa } from "execa";
481
+ import { basename, dirname, isAbsolute, join, resolve as resolve4 } from "path";
208
482
 
209
483
  // src/git/environment.ts
210
484
  function withoutGitEnvironment(env) {
@@ -220,7 +494,7 @@ function withoutGitEnvironment(env) {
220
494
  // src/git/root.ts
221
495
  var defaultGitDependencies = {
222
496
  execa: async (command, args, options) => {
223
- const result = await execa2(command, args, {
497
+ const result = await execa(command, args, {
224
498
  ...options,
225
499
  env: withoutGitEnvironment(process.env),
226
500
  extendEnv: false
@@ -257,7 +531,8 @@ var GIT_ROOT_COMMAND = {
257
531
  CORE_BARE_KEY: "core.bare",
258
532
  REMOTE: "remote",
259
533
  GET_URL: "get-url",
260
- ORIGIN: "origin"
534
+ ORIGIN: "origin",
535
+ UNTRACKED_FILES_ALL: "--untracked-files=all"
261
536
  };
262
537
  var GIT_URL_SUFFIX = ".git";
263
538
  var GIT_DIR_BASENAME = ".git";
@@ -300,7 +575,8 @@ var GIT_ORIGIN_HEAD_REF_ARGS = [
300
575
  ];
301
576
  var GIT_STATUS_PORCELAIN_ARGS = [
302
577
  GIT_ROOT_COMMAND.STATUS,
303
- GIT_ROOT_COMMAND.PORCELAIN
578
+ GIT_ROOT_COMMAND.PORCELAIN,
579
+ GIT_ROOT_COMMAND.UNTRACKED_FILES_ALL
304
580
  ];
305
581
  var GIT_WORKTREE_LIST_PORCELAIN_ARGS = [
306
582
  GIT_ROOT_COMMAND.WORKTREE,
@@ -311,7 +587,8 @@ var GIT_WORKTREE_PORCELAIN_ROOT_PREFIX = "worktree ";
311
587
  var GIT_WORKTREE_PORCELAIN_BARE_LINE = "bare";
312
588
  var GIT_WORKTREE_PORCELAIN_PRUNABLE_LINE = "prunable";
313
589
  var GIT_WORKTREE_PORCELAIN_PRUNABLE_PREFIX = `${GIT_WORKTREE_PORCELAIN_PRUNABLE_LINE} `;
314
- var TRAILING_PATH_SEPARATORS_PATTERN = /[\\/]+$/;
590
+ var POSIX_PATH_SEPARATOR = "/";
591
+ var WINDOWS_PATH_SEPARATOR = "\\";
315
592
  async function detectWorktreeProductRoot(cwd = CONFIG_PROCESS_CWD.read(), deps = defaultGitDependencies) {
316
593
  try {
317
594
  const result = await deps.execa(
@@ -338,15 +615,20 @@ async function detectWorktreeProductRoot(cwd = CONFIG_PROCESS_CWD.read(), deps =
338
615
  };
339
616
  }
340
617
  }
618
+ function stripTrailingPathSeparators(value) {
619
+ let end = value.length;
620
+ while (end > 0 && (value[end - 1] === POSIX_PATH_SEPARATOR || value[end - 1] === WINDOWS_PATH_SEPARATOR)) {
621
+ end -= 1;
622
+ }
623
+ return value.slice(0, end);
624
+ }
341
625
  function extractStdout(stdout) {
342
626
  if (!stdout) return "";
343
- const str = typeof stdout === "string" ? stdout : String(stdout);
344
- return str.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, "");
627
+ return stripTrailingPathSeparators(stdout.trim());
345
628
  }
346
629
  function trimStdout(stdout) {
347
630
  if (!stdout) return "";
348
- const str = typeof stdout === "string" ? stdout : String(stdout);
349
- return str.trim();
631
+ return stdout.trim();
350
632
  }
351
633
  async function detectGitCommonDirProductRoot(cwd = CONFIG_PROCESS_CWD.read(), deps = defaultGitDependencies) {
352
634
  try {
@@ -377,7 +659,7 @@ async function detectGitCommonDirProductRoot(cwd = CONFIG_PROCESS_CWD.read(), de
377
659
  };
378
660
  }
379
661
  const commonDir = extractStdout(commonDirResult.stdout);
380
- const absoluteCommonDir = isAbsolute(commonDir) ? commonDir : resolve3(toplevel, commonDir);
662
+ const absoluteCommonDir = isAbsolute(commonDir) ? commonDir : resolve4(toplevel, commonDir);
381
663
  const gitCommonDirProductRoot = dirname(absoluteCommonDir);
382
664
  return {
383
665
  productDir: gitCommonDirProductRoot,
@@ -461,7 +743,7 @@ async function isWorkingTreeClean(cwd = CONFIG_PROCESS_CWD.read(), deps = defaul
461
743
  }
462
744
  function repositoryName(originUrl) {
463
745
  if (originUrl === null) return null;
464
- const trimmed = originUrl.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, "");
746
+ const trimmed = stripTrailingPathSeparators(originUrl.trim());
465
747
  const lastSeparator = Math.max(
466
748
  trimmed.lastIndexOf("/"),
467
749
  trimmed.lastIndexOf("\\"),
@@ -472,10 +754,10 @@ function repositoryName(originUrl) {
472
754
  return name.length === 0 ? null : name;
473
755
  }
474
756
  function normalizeGitPath(path7) {
475
- return path7.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, "");
757
+ return stripTrailingPathSeparators(path7.trim());
476
758
  }
477
759
  function normalizedGitPathKey(path7) {
478
- return normalizeGitPath(path7).replace(/\\/g, "/");
760
+ return normalizeGitPath(path7).replaceAll(WINDOWS_PATH_SEPARATOR, POSIX_PATH_SEPARATOR);
479
761
  }
480
762
  function isObservedWorktreeRoot(worktreeRoots, candidate) {
481
763
  const candidateKey = normalizedGitPathKey(candidate);
@@ -539,21 +821,561 @@ async function gatherGitFacts(cwd = CONFIG_PROCESS_CWD.read(), deps = defaultGit
539
821
  originUrl
540
822
  };
541
823
  }
542
- const rawCommonDir = extractStdout(commonDirResult.stdout);
543
- const commonDir = isAbsolute(rawCommonDir) ? rawCommonDir : resolve3(worktreeRoot, rawCommonDir);
544
- const bareResult = await deps.execa(
545
- GIT_ROOT_COMMAND.EXECUTABLE,
546
- [...GIT_CORE_BARE_ARGS],
547
- { cwd, reject: false }
548
- );
549
- const commonDirIsBare = bareResult.exitCode === 0 && extractStdout(bareResult.stdout) === GIT_CORE_BARE_TRUE;
550
- return { worktreeRoot, worktreeRoots, worktreeListRead, commonDir, commonDirIsBare, originUrl };
824
+ const rawCommonDir = extractStdout(commonDirResult.stdout);
825
+ const commonDir = isAbsolute(rawCommonDir) ? rawCommonDir : resolve4(worktreeRoot, rawCommonDir);
826
+ const bareResult = await deps.execa(
827
+ GIT_ROOT_COMMAND.EXECUTABLE,
828
+ [...GIT_CORE_BARE_ARGS],
829
+ { cwd, reject: false }
830
+ );
831
+ const commonDirIsBare = bareResult.exitCode === 0 && extractStdout(bareResult.stdout) === GIT_CORE_BARE_TRUE;
832
+ return { worktreeRoot, worktreeRoots, worktreeListRead, commonDir, commonDirIsBare, originUrl };
833
+ } catch {
834
+ return null;
835
+ }
836
+ }
837
+
838
+ // src/commands/agent/resume.ts
839
+ var nodeAgentSessionFileSystem = {
840
+ async readDir(path7) {
841
+ const entries = await readdir(path7, { withFileTypes: true });
842
+ return entries.map((entry) => ({
843
+ name: entry.name,
844
+ isDirectory: entry.isDirectory(),
845
+ isFile: entry.isFile()
846
+ }));
847
+ },
848
+ async readFile(path7) {
849
+ return readFile(path7, AGENT_SESSION_STORE.TEXT_ENCODING);
850
+ },
851
+ async stat(path7) {
852
+ const result = await stat(path7);
853
+ return { mtimeMs: result.mtimeMs };
854
+ }
855
+ };
856
+ var defaultAgentResumeCommandDeps = {
857
+ fs: nodeAgentSessionFileSystem,
858
+ homeDir: homedir,
859
+ nowMs: Date.now,
860
+ resolveWorktreeRoot: async (cwd) => {
861
+ const result = await detectWorktreeProductRoot(cwd);
862
+ return result.isGitRepo ? result.productDir : null;
863
+ }
864
+ };
865
+ async function loadAgentResumeCandidates(options) {
866
+ const deps = options.deps ?? defaultAgentResumeCommandDeps;
867
+ return discoverAgentResumeCandidates({
868
+ invocationDir: options.cwd,
869
+ homeDir: deps.homeDir(),
870
+ nowMs: deps.nowMs(),
871
+ fs: deps.fs,
872
+ resolveWorktreeRoot: deps.resolveWorktreeRoot
873
+ });
874
+ }
875
+ async function listAgentResumeSessions(options) {
876
+ return renderAgentResumeList(await loadAgentResumeCandidates(options));
877
+ }
878
+ async function jsonAgentResumeSessions(options) {
879
+ return renderAgentResumeJson(await loadAgentResumeCandidates(options));
880
+ }
881
+
882
+ // src/lib/process-lifecycle/exit-codes.ts
883
+ var SIGINT_EXIT_CODE = 130;
884
+ var SIGTERM_EXIT_CODE = 143;
885
+ var EPIPE_EXIT_CODE = 0;
886
+ var UNCAUGHT_EXIT_CODE = 1;
887
+
888
+ // src/lib/process-lifecycle/foreground-handoff.ts
889
+ var FOREGROUND_SIGNALS = ["SIGINT", "SIGTERM"];
890
+ function createSignalSuspender(target) {
891
+ return {
892
+ suspend() {
893
+ const ignore = () => {
894
+ };
895
+ const restorers = FOREGROUND_SIGNALS.map((signal) => {
896
+ const originals = target.listeners(signal);
897
+ for (const listener of originals) target.removeListener(signal, listener);
898
+ target.on(signal, ignore);
899
+ return () => {
900
+ target.removeListener(signal, ignore);
901
+ for (const listener of originals) target.on(signal, listener);
902
+ };
903
+ });
904
+ return () => {
905
+ for (const restore of restorers) restore();
906
+ };
907
+ }
908
+ };
909
+ }
910
+
911
+ // src/lib/process-lifecycle/handlers.ts
912
+ var SIGINT_NAME = "SIGINT";
913
+ var SIGTERM_NAME = "SIGTERM";
914
+ function createHandlers(deps) {
915
+ let cleanupOnce = false;
916
+ function killEachChild(signal) {
917
+ deps.registry.forEach((child) => {
918
+ if (!child.killed) child.kill(signal);
919
+ });
920
+ }
921
+ function exitOnce(code, killSignal) {
922
+ if (cleanupOnce) {
923
+ deps.exitController.exit(code);
924
+ return;
925
+ }
926
+ cleanupOnce = true;
927
+ if (killSignal !== void 0) killEachChild(killSignal);
928
+ deps.exitController.exit(code);
929
+ }
930
+ return {
931
+ onSigint() {
932
+ exitOnce(SIGINT_EXIT_CODE, SIGINT_NAME);
933
+ },
934
+ onSigterm() {
935
+ exitOnce(SIGTERM_EXIT_CODE, SIGTERM_NAME);
936
+ },
937
+ onEpipe() {
938
+ exitOnce(EPIPE_EXIT_CODE, SIGTERM_NAME);
939
+ },
940
+ onUncaught(_error) {
941
+ exitOnce(UNCAUGHT_EXIT_CODE, SIGTERM_NAME);
942
+ }
943
+ };
944
+ }
945
+
946
+ // src/lib/process-lifecycle/install.ts
947
+ import { spawn } from "child_process";
948
+
949
+ // src/lib/process-lifecycle/registry.ts
950
+ function createRegistry() {
951
+ const tracked = /* @__PURE__ */ new Set();
952
+ return {
953
+ add(child) {
954
+ tracked.add(child);
955
+ },
956
+ remove(child) {
957
+ tracked.delete(child);
958
+ },
959
+ forEach(fn) {
960
+ for (const child of tracked) fn(child);
961
+ },
962
+ get size() {
963
+ return tracked.size;
964
+ }
965
+ };
966
+ }
967
+
968
+ // src/lib/process-lifecycle/runner.ts
969
+ function createLifecycleRunner(deps) {
970
+ return {
971
+ spawn(command, args, options) {
972
+ const child = deps.spawn(command, args, options);
973
+ deps.registry.add(child);
974
+ child.on("exit", () => deps.registry.remove(child));
975
+ return child;
976
+ }
977
+ };
978
+ }
979
+
980
+ // src/lib/process-lifecycle/install.ts
981
+ var moduleRegistry = createRegistry();
982
+ var moduleExitController = {
983
+ exit(code) {
984
+ process.exit(code);
985
+ }
986
+ };
987
+ var installed = false;
988
+ var lifecycleProcessRunner = createLifecycleRunner({
989
+ registry: moduleRegistry,
990
+ spawn
991
+ });
992
+ var foregroundProcessRunner = { spawn };
993
+ var processSignalTarget = {
994
+ listeners: (signal) => process.listeners(signal),
995
+ on: (signal, listener) => {
996
+ process.on(signal, listener);
997
+ },
998
+ removeListener: (signal, listener) => {
999
+ process.removeListener(signal, listener);
1000
+ }
1001
+ };
1002
+ var lifecycleSignalSuspender = createSignalSuspender(processSignalTarget);
1003
+ var EPIPE_CODE = "EPIPE";
1004
+ var UNCAUGHT_PREFIX = "Uncaught: ";
1005
+ var NEWLINE = "\n";
1006
+ function formatUncaught(error) {
1007
+ if (error instanceof Error && error.stack !== void 0) {
1008
+ return UNCAUGHT_PREFIX + error.stack + NEWLINE;
1009
+ }
1010
+ return UNCAUGHT_PREFIX + String(error) + NEWLINE;
1011
+ }
1012
+ function logUncaughtToStderr(error) {
1013
+ try {
1014
+ process.stderr.write(formatUncaught(error));
1015
+ } catch {
1016
+ }
1017
+ }
1018
+ function installLifecycle() {
1019
+ if (installed) return;
1020
+ installed = true;
1021
+ const handlers = createHandlers({
1022
+ registry: moduleRegistry,
1023
+ exitController: moduleExitController
1024
+ });
1025
+ process.on("uncaughtException", (error) => {
1026
+ logUncaughtToStderr(error);
1027
+ handlers.onUncaught(error);
1028
+ });
1029
+ process.on("unhandledRejection", (reason) => {
1030
+ logUncaughtToStderr(reason);
1031
+ handlers.onUncaught(reason);
1032
+ });
1033
+ process.on("SIGTERM", () => handlers.onSigterm());
1034
+ process.on("SIGINT", () => handlers.onSigint());
1035
+ process.stdout.on("error", (error) => {
1036
+ if (error.code === EPIPE_CODE) {
1037
+ handlers.onEpipe();
1038
+ return;
1039
+ }
1040
+ handlers.onUncaught(error);
1041
+ });
1042
+ process.stderr.on("error", (error) => {
1043
+ if (error.code === EPIPE_CODE) {
1044
+ handlers.onEpipe();
1045
+ return;
1046
+ }
1047
+ handlers.onUncaught(error);
1048
+ });
1049
+ }
1050
+
1051
+ // src/lib/process-lifecycle/managed-subprocess.ts
1052
+ var MANAGED_SUBPROCESS_STDIO = "pipe";
1053
+ function spawnManagedSubprocess(runner, command, args, options) {
1054
+ return runner.spawn(command, args, {
1055
+ ...options,
1056
+ stdio: MANAGED_SUBPROCESS_STDIO
1057
+ });
1058
+ }
1059
+
1060
+ // src/interfaces/cli/foreground-launch.ts
1061
+ var FOREGROUND_LAUNCH_STDIO = "inherit";
1062
+ var LAUNCH_FAILURE_STATUS = 1;
1063
+ function launchForegroundCommand(runner, suspender, command) {
1064
+ const restoreSignals = suspender.suspend();
1065
+ return new Promise((resolve12) => {
1066
+ let settled = false;
1067
+ const settle = (status) => {
1068
+ if (settled) return;
1069
+ settled = true;
1070
+ restoreSignals();
1071
+ resolve12(status);
1072
+ };
1073
+ const child = runner.spawn(command.command, command.args, {
1074
+ cwd: command.cwd,
1075
+ stdio: FOREGROUND_LAUNCH_STDIO
1076
+ });
1077
+ child.once("exit", (code) => settle(code ?? LAUNCH_FAILURE_STATUS));
1078
+ child.once("error", () => settle(LAUNCH_FAILURE_STATUS));
1079
+ });
1080
+ }
1081
+
1082
+ // src/interfaces/cli/agent/resume/launch-agent-resume.ts
1083
+ function launchAgentResume(runner, suspender, command) {
1084
+ return launchForegroundCommand(runner, suspender, command);
1085
+ }
1086
+
1087
+ // src/interfaces/cli/agent/resume/run-picker.tsx
1088
+ import { render } from "ink";
1089
+
1090
+ // src/interfaces/cli/agent/resume/AgentResumePicker.tsx
1091
+ import { Box, Text, useInput } from "ink";
1092
+ import { useState } from "react";
1093
+ import { jsx, jsxs } from "react/jsx-runtime";
1094
+ var SELECTED_COLOR = "cyan";
1095
+ var SELECTED_MARKER = ">";
1096
+ var UNSELECTED_MARKER = " ";
1097
+ function AgentResumePicker(props) {
1098
+ const [state, setState] = useState(initialAgentResumePickerState);
1099
+ useInput((input, key) => {
1100
+ const action = resolveAgentResumePickerAction({
1101
+ input,
1102
+ upArrow: key.upArrow,
1103
+ downArrow: key.downArrow,
1104
+ return: key.return,
1105
+ escape: key.escape
1106
+ });
1107
+ if (action === AGENT_RESUME_PICKER_ACTION.CHOOSE) {
1108
+ const selected = props.candidates.at(state.selectedIndex);
1109
+ if (selected !== void 0) {
1110
+ props.onChoose(selected);
1111
+ }
1112
+ return;
1113
+ }
1114
+ if (action === AGENT_RESUME_PICKER_ACTION.QUIT) {
1115
+ props.onQuit();
1116
+ return;
1117
+ }
1118
+ setState((current) => reduceAgentResumePickerState(current, action, props.candidates.length));
1119
+ });
1120
+ if (props.candidates.length === 0) {
1121
+ return /* @__PURE__ */ jsx(Text, { children: AGENT_RESUME_TEXT.NO_MATCHES });
1122
+ }
1123
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: props.candidates.map((candidate, index) => /* @__PURE__ */ jsxs(
1124
+ Text,
1125
+ {
1126
+ color: index === state.selectedIndex ? SELECTED_COLOR : void 0,
1127
+ children: [
1128
+ index === state.selectedIndex ? SELECTED_MARKER : UNSELECTED_MARKER,
1129
+ " ",
1130
+ AGENT_SESSION_LABEL[candidate.agent],
1131
+ " ",
1132
+ candidate.sessionId,
1133
+ " ",
1134
+ candidate.cwd
1135
+ ]
1136
+ },
1137
+ `${candidate.agent}:${candidate.sessionId}`
1138
+ )) });
1139
+ }
1140
+
1141
+ // src/interfaces/cli/agent/resume/run-picker.tsx
1142
+ import { jsx as jsx2 } from "react/jsx-runtime";
1143
+ var AGENT_RESUME_PICKER_RESULT = {
1144
+ SELECTED: "selected",
1145
+ QUIT: "quit"
1146
+ };
1147
+ function selectedAgentResumeCandidate(candidate) {
1148
+ return { kind: AGENT_RESUME_PICKER_RESULT.SELECTED, candidate };
1149
+ }
1150
+ function quitAgentResumePicker() {
1151
+ return { kind: AGENT_RESUME_PICKER_RESULT.QUIT };
1152
+ }
1153
+ async function runAgentResumePicker(candidates, renderPicker = render) {
1154
+ let result = quitAgentResumePicker();
1155
+ let unmount = () => {
1156
+ };
1157
+ const instance = renderPicker(
1158
+ /* @__PURE__ */ jsx2(
1159
+ AgentResumePicker,
1160
+ {
1161
+ candidates,
1162
+ onChoose: (candidate) => {
1163
+ result = selectedAgentResumeCandidate(candidate);
1164
+ unmount();
1165
+ },
1166
+ onQuit: () => {
1167
+ result = quitAgentResumePicker();
1168
+ unmount();
1169
+ }
1170
+ }
1171
+ )
1172
+ );
1173
+ unmount = instance.unmount;
1174
+ await instance.waitUntilExit();
1175
+ return result;
1176
+ }
1177
+
1178
+ // src/interfaces/cli/agent.ts
1179
+ var AGENT_CLI = {
1180
+ commandName: "agent",
1181
+ resumeCommandName: "resume",
1182
+ flags: {
1183
+ latest: "--latest",
1184
+ list: "--list",
1185
+ json: "--json"
1186
+ }
1187
+ };
1188
+ var AGENT_CLI_EXIT = {
1189
+ SUCCESS: 0,
1190
+ FAILURE: 1
1191
+ };
1192
+ var DEFAULT_AGENT_CLI_DEPENDENCIES = {
1193
+ isInteractiveTerminal: () => Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY),
1194
+ pickCandidate: runAgentResumePicker,
1195
+ launchCandidate: async (candidate) => {
1196
+ return launchAgentResume(
1197
+ foregroundProcessRunner,
1198
+ lifecycleSignalSuspender,
1199
+ buildAgentResumeLaunchCommand(candidate)
1200
+ );
1201
+ }
1202
+ };
1203
+ function writeOutput(invocation, output) {
1204
+ invocation.io.writeStdout(`${output}
1205
+ `);
1206
+ }
1207
+ function writeError(invocation, output) {
1208
+ invocation.io.writeStderr(`${output}
1209
+ `);
1210
+ }
1211
+ function handleError(invocation, error) {
1212
+ const message = error instanceof Error ? `${error.name}: ${error.message}` : inspect(error);
1213
+ writeError(invocation, `Error: ${message}`);
1214
+ return invocation.io.exit(AGENT_CLI_EXIT.FAILURE);
1215
+ }
1216
+ function createAgentDomain(deps = {}) {
1217
+ const resolvedDeps = {
1218
+ ...DEFAULT_AGENT_CLI_DEPENDENCIES,
1219
+ ...deps
1220
+ };
1221
+ return {
1222
+ name: AGENT_CLI.commandName,
1223
+ description: "Find and resume coding-agent sessions",
1224
+ register: (program, invocation) => {
1225
+ const agentCmd = program.command(AGENT_CLI.commandName).description("Find and resume coding-agent sessions");
1226
+ agentCmd.command(AGENT_CLI.resumeCommandName).description("Resume a Codex or Claude Code agent session for this worktree").option(AGENT_CLI.flags.latest, "Launch the newest matching session").option(AGENT_CLI.flags.list, "List matching sessions").option(AGENT_CLI.flags.json, "Print matching sessions as JSON").action(async (options) => {
1227
+ let requestedExitCode = AGENT_CLI_EXIT.SUCCESS;
1228
+ try {
1229
+ const mode = resolveAgentResumeMode(options);
1230
+ if (mode === AGENT_RESUME_MODE.PICK && !resolvedDeps.isInteractiveTerminal()) {
1231
+ writeError(invocation, AGENT_RESUME_TEXT.INTERACTIVE_REQUIRED);
1232
+ requestedExitCode = AGENT_CLI_EXIT.FAILURE;
1233
+ } else {
1234
+ const commandOptions = {
1235
+ cwd: invocation.resolveEffectiveInvocationDir(),
1236
+ deps: resolvedDeps.resumeDeps
1237
+ };
1238
+ if (mode === AGENT_RESUME_MODE.JSON) {
1239
+ writeOutput(invocation, await jsonAgentResumeSessions(commandOptions));
1240
+ return;
1241
+ }
1242
+ if (mode === AGENT_RESUME_MODE.LIST) {
1243
+ writeOutput(invocation, await listAgentResumeSessions(commandOptions));
1244
+ return;
1245
+ }
1246
+ const candidates = await loadAgentResumeCandidates(commandOptions);
1247
+ if (candidates.length === 0) {
1248
+ writeError(invocation, AGENT_RESUME_TEXT.NO_MATCHES);
1249
+ requestedExitCode = AGENT_CLI_EXIT.FAILURE;
1250
+ } else if (mode === AGENT_RESUME_MODE.LATEST) {
1251
+ requestedExitCode = await resolvedDeps.launchCandidate(candidates[0]);
1252
+ } else {
1253
+ const pickerResult = await resolvedDeps.pickCandidate(candidates);
1254
+ if (pickerResult.kind === AGENT_RESUME_PICKER_RESULT.SELECTED) {
1255
+ requestedExitCode = await resolvedDeps.launchCandidate(pickerResult.candidate);
1256
+ }
1257
+ }
1258
+ }
1259
+ } catch (error) {
1260
+ handleError(invocation, error);
1261
+ }
1262
+ return invocation.io.exit(requestedExitCode);
1263
+ });
1264
+ }
1265
+ };
1266
+ }
1267
+ var agentDomain = createAgentDomain();
1268
+
1269
+ // src/commands/claude/init.ts
1270
+ import { execa as execa2 } from "execa";
1271
+ async function initCommand(options = {}) {
1272
+ const cwd = options.cwd || CONFIG_PROCESS_CWD.read();
1273
+ try {
1274
+ const { stdout: listOutput } = await execa2(
1275
+ "claude",
1276
+ ["plugin", "marketplace", "list"],
1277
+ { cwd }
1278
+ );
1279
+ const exists = listOutput.includes("outcomeeng");
1280
+ if (!exists) {
1281
+ await execa2(
1282
+ "claude",
1283
+ ["plugin", "marketplace", "add", "outcomeeng/plugins"],
1284
+ { cwd }
1285
+ );
1286
+ return "\u2713 outcomeeng marketplace installed successfully\n\nRun 'claude plugin marketplace list' to view all marketplaces.";
1287
+ } else {
1288
+ await execa2("claude", ["plugin", "marketplace", "update", "outcomeeng"], {
1289
+ cwd
1290
+ });
1291
+ return "\u2713 outcomeeng marketplace updated successfully\n\nThe marketplace is now up to date.";
1292
+ }
1293
+ } catch (error) {
1294
+ if (error instanceof Error) {
1295
+ if (error.message.includes("ENOENT") || error.message.includes("command not found")) {
1296
+ throw new Error(
1297
+ "Claude CLI not found. Please install Claude Code first.\n\nVisit: https://docs.anthropic.com/claude-code"
1298
+ );
1299
+ }
1300
+ throw new Error(`Failed to initialize marketplace: ${error.message}`);
1301
+ }
1302
+ throw error;
1303
+ }
1304
+ }
1305
+
1306
+ // src/lib/claude/permissions/discovery.ts
1307
+ import fs from "fs/promises";
1308
+ import path from "path";
1309
+ async function findSettingsFiles(root, visited = /* @__PURE__ */ new Set()) {
1310
+ const normalizedRoot = path.resolve(root.replace(/^~/, process.env.HOME || "~"));
1311
+ if (visited.has(normalizedRoot)) {
1312
+ return [];
1313
+ }
1314
+ visited.add(normalizedRoot);
1315
+ try {
1316
+ return await findSettingsFilesInDirectory(normalizedRoot, visited);
1317
+ } catch (error) {
1318
+ throw discoveryError(normalizedRoot, error);
1319
+ }
1320
+ }
1321
+ async function findSettingsFilesInDirectory(normalizedRoot, visited) {
1322
+ const stats = await fs.stat(normalizedRoot);
1323
+ if (!stats.isDirectory()) {
1324
+ throw new Error(`Path is not a directory: ${normalizedRoot}`);
1325
+ }
1326
+ const entries = await fs.readdir(normalizedRoot, { withFileTypes: true });
1327
+ const results = [];
1328
+ for (const entry of entries) {
1329
+ results.push(...await settingsFilesForEntry(normalizedRoot, entry, visited));
1330
+ }
1331
+ return results;
1332
+ }
1333
+ async function settingsFilesForEntry(normalizedRoot, entry, visited) {
1334
+ if (!entry.isDirectory()) return [];
1335
+ const fullPath = path.join(normalizedRoot, entry.name);
1336
+ if (entry.name === ".claude") {
1337
+ const settingsPath = path.join(fullPath, "settings.local.json");
1338
+ return await isValidSettingsFile(settingsPath) ? [settingsPath] : [];
1339
+ }
1340
+ return findSettingsFiles(fullPath, visited);
1341
+ }
1342
+ function discoveryError(normalizedRoot, error) {
1343
+ if (!(error instanceof Error)) return new Error(unknownErrorMessage(error));
1344
+ if (error.message.includes("ENOENT")) return new Error(`Directory not found: ${normalizedRoot}`);
1345
+ if (error.message.includes("EACCES")) return new Error(`Permission denied: ${normalizedRoot}`);
1346
+ return new Error(`Failed to search directory "${normalizedRoot}": ${error.message}`);
1347
+ }
1348
+ function unknownErrorMessage(error) {
1349
+ if (typeof error === "string") return error;
1350
+ if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") return error.toString();
1351
+ if (typeof error === "symbol") return error.description ?? "Symbol()";
1352
+ if (error === void 0) return "undefined";
1353
+ return Object.prototype.toString.call(error);
1354
+ }
1355
+ async function isValidSettingsFile(filePath) {
1356
+ try {
1357
+ await fs.access(filePath, fs.constants.R_OK);
1358
+ const stats = await fs.stat(filePath);
1359
+ if (!stats.isFile()) {
1360
+ return false;
1361
+ }
1362
+ return path.extname(filePath) === ".json";
551
1363
  } catch {
552
- return null;
1364
+ return false;
553
1365
  }
554
1366
  }
555
1367
 
556
1368
  // src/lib/state-store/index.ts
1369
+ import { createHash, randomBytes as nodeRandomBytes } from "crypto";
1370
+ import { constants as fsConstants } from "fs";
1371
+ import {
1372
+ lstat as nodeLstat,
1373
+ mkdir as nodeMkdir,
1374
+ open as nodeOpen,
1375
+ readdir as nodeReaddir,
1376
+ rm as nodeRm
1377
+ } from "fs/promises";
1378
+ import { dirname as dirname2, join as join2 } from "path";
557
1379
  var STATE_STORE_PATH = {
558
1380
  SPX_DIR: ".spx",
559
1381
  BRANCH_SCOPE: "branch",
@@ -1405,16 +2227,16 @@ function formatError(error) {
1405
2227
  }
1406
2228
  return "Unknown error";
1407
2229
  }
1408
- function writeOutput(io, output) {
2230
+ function writeOutput2(io, output) {
1409
2231
  io.writeStdout(`${output}
1410
2232
  `);
1411
2233
  }
1412
- function writeError(io, output) {
2234
+ function writeError2(io, output) {
1413
2235
  io.writeStderr(`${output}
1414
2236
  `);
1415
2237
  }
1416
2238
  function exitWithError(io, error) {
1417
- writeError(io, `Error: ${formatError(error)}`);
2239
+ writeError2(io, `Error: ${formatError(error)}`);
1418
2240
  return io.exit(1);
1419
2241
  }
1420
2242
  function registerClaudeCommands(claudeCmd, invocation) {
@@ -1422,7 +2244,7 @@ function registerClaudeCommands(claudeCmd, invocation) {
1422
2244
  claudeCmd.command("init").description("Initialize or update outcomeeng marketplace plugin").action(async () => {
1423
2245
  try {
1424
2246
  const output = await initCommand({ cwd: productDir() });
1425
- writeOutput(invocation.io, output);
2247
+ writeOutput2(invocation.io, output);
1426
2248
  } catch (error) {
1427
2249
  exitWithError(invocation.io, error);
1428
2250
  }
@@ -1443,7 +2265,7 @@ function registerClaudeCommands(claudeCmd, invocation) {
1443
2265
  async (options) => {
1444
2266
  try {
1445
2267
  if (options.write && options.outputFile) {
1446
- writeError(
2268
+ writeError2(
1447
2269
  invocation.io,
1448
2270
  "Error: --write and --output-file are mutually exclusive\nUse --write to modify global settings, or --output-file to write to a different location"
1449
2271
  );
@@ -1455,7 +2277,7 @@ function registerClaudeCommands(claudeCmd, invocation) {
1455
2277
  root: options.root,
1456
2278
  globalSettings: options.globalSettings
1457
2279
  });
1458
- writeOutput(invocation.io, output);
2280
+ writeOutput2(invocation.io, output);
1459
2281
  } catch (error) {
1460
2282
  exitWithError(invocation.io, error);
1461
2283
  }
@@ -1645,14 +2467,14 @@ async function compactRetrieveCommand(options) {
1645
2467
  }
1646
2468
 
1647
2469
  // src/commands/compact/store.ts
1648
- import { readFile } from "fs/promises";
2470
+ import { readFile as readFile2 } from "fs/promises";
1649
2471
  var UTF8_ENCODING = "utf8";
1650
2472
  async function compactStoreCommand(options) {
1651
2473
  const sessionToken = resolveCompactSessionToken(options.sessionId, options.env ?? process.env);
1652
2474
  if (sessionToken === void 0) return 1;
1653
2475
  let transcript;
1654
2476
  try {
1655
- transcript = await readFile(options.transcript, UTF8_ENCODING);
2477
+ transcript = await readFile2(options.transcript, UTF8_ENCODING);
1656
2478
  } catch {
1657
2479
  return 1;
1658
2480
  }
@@ -1708,7 +2530,7 @@ var compactDomain = {
1708
2530
  };
1709
2531
 
1710
2532
  // src/config/index.ts
1711
- import { readFile as readFile2 } from "fs/promises";
2533
+ import { readFile as readFile3 } from "fs/promises";
1712
2534
  import { join as join5 } from "path";
1713
2535
  import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
1714
2536
  import { parse as parseYaml, parseDocument as parseYamlDocument, stringify as stringifyYaml } from "yaml";
@@ -1811,7 +2633,7 @@ var AGENT_ENVIRONMENT_SKILL_ALLOWED_FIELDS = /* @__PURE__ */ new Set([
1811
2633
  AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE,
1812
2634
  AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION
1813
2635
  ]);
1814
- function isRecord(value) {
2636
+ function isRecord2(value) {
1815
2637
  return typeof value === "object" && value !== null && !Array.isArray(value);
1816
2638
  }
1817
2639
  function rejectUnknownFields(path7, value, allowed) {
@@ -1864,7 +2686,7 @@ function validateRuntimeArray(path7, value) {
1864
2686
  }
1865
2687
  function validateInstructions(raw) {
1866
2688
  const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS}`;
1867
- if (!isRecord(raw)) {
2689
+ if (!isRecord2(raw)) {
1868
2690
  return { ok: false, error: `${sectionPath} must be an object` };
1869
2691
  }
1870
2692
  const unknown = rejectUnknownFields(sectionPath, raw, AGENT_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS);
@@ -1888,7 +2710,7 @@ function validateInstructions(raw) {
1888
2710
  return { ok: true, value: { files } };
1889
2711
  }
1890
2712
  function validateInstructionFile(path7, raw) {
1891
- if (!isRecord(raw)) return { ok: false, error: `${path7} must be an object` };
2713
+ if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
1892
2714
  const unknown = rejectUnknownFields(
1893
2715
  path7,
1894
2716
  raw,
@@ -1909,7 +2731,7 @@ function validateInstructionFile(path7, raw) {
1909
2731
  }
1910
2732
  function validateRuntimes(raw) {
1911
2733
  const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES}`;
1912
- if (!isRecord(raw)) {
2734
+ if (!isRecord2(raw)) {
1913
2735
  return { ok: false, error: `${sectionPath} must be an object` };
1914
2736
  }
1915
2737
  const runtimes = { ...DEFAULT_AGENT_ENVIRONMENT_CONFIG.runtimes };
@@ -1923,7 +2745,7 @@ function validateRuntimes(raw) {
1923
2745
  return { ok: true, value: runtimes };
1924
2746
  }
1925
2747
  function validateRuntimeConfig(path7, raw, defaults5) {
1926
- if (!isRecord(raw)) return { ok: false, error: `${path7} must be an object` };
2748
+ if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
1927
2749
  const unknown = rejectUnknownFields(path7, raw, AGENT_ENVIRONMENT_RUNTIME_CONFIG_ALLOWED_FIELDS);
1928
2750
  if (!unknown.ok) return unknown;
1929
2751
  const enabledRaw = raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED];
@@ -1934,7 +2756,7 @@ function validateRuntimeConfig(path7, raw, defaults5) {
1934
2756
  }
1935
2757
  function validatePluginBootstrap(raw) {
1936
2758
  const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP}`;
1937
- if (!isRecord(raw)) {
2759
+ if (!isRecord2(raw)) {
1938
2760
  return { ok: false, error: `${sectionPath} must be an object` };
1939
2761
  }
1940
2762
  const unknown = rejectUnknownFields(
@@ -2053,7 +2875,7 @@ function validatePluginMarketplaceReferences(path7, marketplaces, plugins) {
2053
2875
  return { ok: true, value: void 0 };
2054
2876
  }
2055
2877
  function validateMarketplace(path7, raw) {
2056
- if (!isRecord(raw)) return { ok: false, error: `${path7} must be an object` };
2878
+ if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
2057
2879
  const unknown = rejectUnknownFields(
2058
2880
  path7,
2059
2881
  raw,
@@ -2070,7 +2892,7 @@ function validateMarketplace(path7, raw) {
2070
2892
  return { ok: true, value: { ...base.value, source: source.value } };
2071
2893
  }
2072
2894
  function validatePlugin(path7, raw) {
2073
- if (!isRecord(raw)) return { ok: false, error: `${path7} must be an object` };
2895
+ if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
2074
2896
  const unknown = rejectUnknownFields(
2075
2897
  path7,
2076
2898
  raw,
@@ -2099,7 +2921,7 @@ function validatePlugin(path7, raw) {
2099
2921
  };
2100
2922
  }
2101
2923
  function validateSkill(path7, raw) {
2102
- if (!isRecord(raw)) return { ok: false, error: `${path7} must be an object` };
2924
+ if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
2103
2925
  const unknown = rejectUnknownFields(
2104
2926
  path7,
2105
2927
  raw,
@@ -2145,7 +2967,7 @@ function validateOptionalString(path7, value) {
2145
2967
  return validateNonEmptyString(path7, value);
2146
2968
  }
2147
2969
  function validate(value) {
2148
- if (!isRecord(value)) {
2970
+ if (!isRecord2(value)) {
2149
2971
  return { ok: false, error: `${AGENT_ENVIRONMENT_SECTION} section must be an object` };
2150
2972
  }
2151
2973
  const unknown = rejectUnknownFields(
@@ -2179,7 +3001,7 @@ var agentEnvironmentConfigDescriptor = {
2179
3001
  };
2180
3002
 
2181
3003
  // src/domains/diagnose/facts.ts
2182
- function isRecord2(value) {
3004
+ function isRecord3(value) {
2183
3005
  return typeof value === "object" && value !== null && !Array.isArray(value);
2184
3006
  }
2185
3007
  function isNonEmptyString(value) {
@@ -2189,7 +3011,7 @@ function isNonEmptyStringArray(value) {
2189
3011
  return Array.isArray(value) && value.length > 0 && value.every(isNonEmptyString);
2190
3012
  }
2191
3013
  function validateMarketplaceIdentity(value, field) {
2192
- if (!isRecord2(value) || !isNonEmptyString(value.name) || !isNonEmptyString(value.source)) {
3014
+ if (!isRecord3(value) || !isNonEmptyString(value.name) || !isNonEmptyString(value.source)) {
2193
3015
  return { ok: false, error: `${field} must carry a non-empty \`name\` and \`source\`` };
2194
3016
  }
2195
3017
  return { ok: true, value: { name: value.name, source: value.source } };
@@ -2721,7 +3543,7 @@ var defaults2 = {
2721
3543
  scope: DEFAULT_SCOPE_CONFIG,
2722
3544
  tools: DEFAULT_TOOLS_CONFIG
2723
3545
  };
2724
- function isRecord3(value) {
3546
+ function isRecord4(value) {
2725
3547
  return typeof value === "object" && value !== null && !Array.isArray(value);
2726
3548
  }
2727
3549
  function validateStringField(section, field, value) {
@@ -2744,7 +3566,7 @@ function rejectUnknownFields2(section, value, allowed) {
2744
3566
  return { ok: true, value: void 0 };
2745
3567
  }
2746
3568
  function validateScope(raw) {
2747
- if (!isRecord3(raw)) {
3569
+ if (!isRecord4(raw)) {
2748
3570
  return {
2749
3571
  ok: false,
2750
3572
  error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE} must be an object`
@@ -2801,7 +3623,7 @@ function validateScope(raw) {
2801
3623
  };
2802
3624
  }
2803
3625
  function validateTools(raw) {
2804
- if (!isRecord3(raw)) {
3626
+ if (!isRecord4(raw)) {
2805
3627
  return {
2806
3628
  ok: false,
2807
3629
  error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS} must be an object`
@@ -2816,7 +3638,7 @@ function validateTools(raw) {
2816
3638
  error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} is not a recognized tool`
2817
3639
  };
2818
3640
  }
2819
- if (!isRecord3(adapterRaw)) {
3641
+ if (!isRecord4(adapterRaw)) {
2820
3642
  return {
2821
3643
  ok: false,
2822
3644
  error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} must be an object`
@@ -3418,7 +4240,7 @@ async function readProductConfigFile(productDir) {
3418
4240
  const path7 = join5(productDir, filename);
3419
4241
  let raw;
3420
4242
  try {
3421
- raw = await readFile2(path7, "utf8");
4243
+ raw = await readFile3(path7, "utf8");
3422
4244
  } catch (error) {
3423
4245
  if (isFileNotFound(error)) continue;
3424
4246
  return { ok: false, error: `failed to read ${filename}: ${toMessage(error)}` };
@@ -3702,7 +4524,7 @@ var configDomain = {
3702
4524
  };
3703
4525
 
3704
4526
  // src/interfaces/cli/diagnose.ts
3705
- import { readFile as readFile3 } from "fs/promises";
4527
+ import { readFile as readFile4 } from "fs/promises";
3706
4528
  import { Option } from "commander";
3707
4529
 
3708
4530
  // src/domains/diagnose/types.ts
@@ -3786,7 +4608,7 @@ function parseManifest(rawJson, availableChecks) {
3786
4608
  } catch (error) {
3787
4609
  return { ok: false, error: `manifest is not valid JSON: ${error.message}` };
3788
4610
  }
3789
- if (!isRecord2(parsed)) {
4611
+ if (!isRecord3(parsed)) {
3790
4612
  return { ok: false, error: "manifest must be a JSON object" };
3791
4613
  }
3792
4614
  const checks = validateChecks(parsed.checks, new Set(availableChecks));
@@ -4099,10 +4921,16 @@ function resolveHookSessionStartProductDir(payload, cwd) {
4099
4921
  return payload.cwd ?? cwd;
4100
4922
  }
4101
4923
  var NO_STARTUP_DIRECTIVE = "";
4924
+ var HOOK_COMPACT_FOUNDATION_ACTION = {
4925
+ CONTEXTUALIZE: "/contextualize",
4926
+ UNDERSTAND: "/understand"
4927
+ };
4928
+ var HOOK_COMPACT_FOUNDATION_REASON = `Hook fired because the agent runtime reported ${HOOK_SESSION_START_PAYLOAD.SOURCE}=${HOOK_SESSION_START_SOURCE.COMPACT}.`;
4102
4929
  var HOOK_COMPACT_FOUNDATION_DIRECTIVE = [
4930
+ HOOK_COMPACT_FOUNDATION_REASON,
4103
4931
  "Spec-tree foundation was reset by this compaction.",
4104
- "Before any spec-governed action, including resuming an in-flight PR, /apply, or /handoff, re-invoke /understand then /contextualize on every spec node still in scope (not just the next one) before any gh/git archaeology or reading spec-governed source.",
4105
- "The pre-compaction skill text in this summary is a historical record, not a live tool."
4932
+ `Before any spec-governed action, including resuming an in-flight PR, /apply, or /handoff, re-invoke ${HOOK_COMPACT_FOUNDATION_ACTION.UNDERSTAND} then ${HOOK_COMPACT_FOUNDATION_ACTION.CONTEXTUALIZE} on every spec node still in scope (not just the next one) before any gh/git archaeology or reading spec-governed source.`,
4933
+ "Skill text carried in the compaction summary is context only, outside active tool authority."
4106
4934
  ].join("\n");
4107
4935
  function renderSessionStartStdout(source) {
4108
4936
  return source === HOOK_SESSION_START_SOURCE.COMPACT ? HOOK_COMPACT_FOUNDATION_DIRECTIVE : NO_STARTUP_DIRECTIVE;
@@ -4883,7 +5711,7 @@ var DEFAULT_REGISTRY = {
4883
5711
  [CHECK_NAME.SESSION_STORE]: sessionStoreRunner(defaultSessionStoreProbe),
4884
5712
  [CHECK_NAME.MARKETPLACE_INSTALL]: marketplaceInstallRunner(defaultMarketplaceInstallProbe)
4885
5713
  };
4886
- function handleError(error, io) {
5714
+ function handleError2(error, io) {
4887
5715
  io.writeStderr(`Error: ${sanitizeCliArgument(error)}
4888
5716
  `);
4889
5717
  return io.exit(1);
@@ -4908,10 +5736,10 @@ var diagnoseDomain = {
4908
5736
  isTty: Boolean(process.stdout.isTTY)
4909
5737
  }),
4910
5738
  registry: DEFAULT_REGISTRY,
4911
- fs: { readFile: (path7) => readFile3(path7, "utf8") }
5739
+ fs: { readFile: (path7) => readFile4(path7, "utf8") }
4912
5740
  });
4913
5741
  if (!result.ok) {
4914
- handleError(result.error, invocation.io);
5742
+ handleError2(result.error, invocation.io);
4915
5743
  }
4916
5744
  invocation.io.writeStdout(`${result.value.output}
4917
5745
  `);
@@ -4969,7 +5797,7 @@ function isValidPid(pid) {
4969
5797
  }
4970
5798
 
4971
5799
  // src/domains/worktree/resolve.ts
4972
- import { dirname as dirname4, resolve as resolve4 } from "path";
5800
+ import { dirname as dirname4, resolve as resolve5 } from "path";
4973
5801
  var WORKTREE_RESOLVE_ERROR = {
4974
5802
  NOT_A_WORKTREE: "path resolves to no worktree",
4975
5803
  WORKTREE_LIST_UNAVAILABLE: "git worktree list is unavailable"
@@ -5002,7 +5830,7 @@ async function resolveAllTargetWorktrees(options) {
5002
5830
  }
5003
5831
  async function resolveTargetWorktree(options) {
5004
5832
  const base = options.cwd;
5005
- const targetPath = options.worktree === void 0 ? base : resolve4(base, options.worktree);
5833
+ const targetPath = options.worktree === void 0 ? base : resolve5(base, options.worktree);
5006
5834
  const targetGitPath = await options.pathInfo.isExistingNonDirectory(targetPath) ? dirname4(targetPath) : targetPath;
5007
5835
  const worktree = await detectWorktreeProductRoot(targetGitPath, options.gitDeps);
5008
5836
  if (!worktree.isGitRepo) {
@@ -5168,17 +5996,17 @@ function createProcessHookIo(streams) {
5168
5996
  return {
5169
5997
  readStdin: async () => {
5170
5998
  if (streams.stdin.isTTY) return { ok: true, value: void 0 };
5171
- return new Promise((resolve11) => {
5999
+ return new Promise((resolve12) => {
5172
6000
  let data = "";
5173
6001
  streams.stdin.setEncoding("utf-8");
5174
6002
  streams.stdin.on(HOOK_PROCESS_IO_EVENT.DATA, (chunk) => {
5175
6003
  data += chunk;
5176
6004
  });
5177
6005
  streams.stdin.on(HOOK_PROCESS_IO_EVENT.END, () => {
5178
- resolve11({ ok: true, value: data.length === 0 ? void 0 : data });
6006
+ resolve12({ ok: true, value: data.length === 0 ? void 0 : data });
5179
6007
  });
5180
6008
  streams.stdin.on(HOOK_PROCESS_IO_EVENT.ERROR, (error) => {
5181
- resolve11({ ok: false, error: formatStdinReadError(error) });
6009
+ resolve12({ ok: false, error: formatStdinReadError(error) });
5182
6010
  });
5183
6011
  });
5184
6012
  },
@@ -5225,13 +6053,13 @@ var HOOK_CLI = {
5225
6053
  WORKTREES_DIR_FLAG: "--worktrees-dir"
5226
6054
  };
5227
6055
  var HOOK_DOMAIN_DESCRIPTION = "Run host lifecycle hook events";
5228
- function writeError2(invocation, output) {
6056
+ function writeError3(invocation, output) {
5229
6057
  invocation.io.writeStderr(`${output}
5230
6058
  `);
5231
6059
  }
5232
6060
  function writeInvocationWarning(invocation, warning) {
5233
6061
  if (warning !== void 0) {
5234
- writeError2(invocation, warning);
6062
+ writeError3(invocation, warning);
5235
6063
  }
5236
6064
  }
5237
6065
  function registerHookCommands(hookCmd, invocation) {
@@ -6214,7 +7042,7 @@ function sessionOptionToken(option) {
6214
7042
  }
6215
7043
 
6216
7044
  // src/commands/session/archive.ts
6217
- import { mkdir, rename, stat } from "fs/promises";
7045
+ import { mkdir, rename, stat as stat2 } from "fs/promises";
6218
7046
  import { dirname as dirname6, join as join9 } from "path";
6219
7047
 
6220
7048
  // src/domains/session/archive.ts
@@ -6527,7 +7355,7 @@ var SessionAlreadyArchivedError = class extends Error {
6527
7355
  };
6528
7356
  async function fileExists(path7) {
6529
7357
  try {
6530
- const stats = await stat(path7);
7358
+ const stats = await stat2(path7);
6531
7359
  return stats.isFile();
6532
7360
  } catch {
6533
7361
  return false;
@@ -6569,7 +7397,7 @@ async function archiveCommand(options) {
6569
7397
  }
6570
7398
 
6571
7399
  // src/commands/session/delete.ts
6572
- import { stat as stat2, unlink } from "fs/promises";
7400
+ import { stat as stat3, unlink } from "fs/promises";
6573
7401
 
6574
7402
  // src/domains/session/delete.ts
6575
7403
  function resolveDeletePath(sessionId, existingPaths) {
@@ -7018,7 +7846,7 @@ async function findExistingPaths(paths) {
7018
7846
  const existing = [];
7019
7847
  for (const path7 of paths) {
7020
7848
  try {
7021
- const stats = await stat2(path7);
7849
+ const stats = await stat3(path7);
7022
7850
  if (stats.isFile()) {
7023
7851
  existing.push(path7);
7024
7852
  }
@@ -7040,8 +7868,8 @@ async function deleteCommand(options) {
7040
7868
  }
7041
7869
 
7042
7870
  // src/commands/session/handoff.ts
7043
- import { mkdir as mkdir2, stat as stat3, writeFile } from "fs/promises";
7044
- import { join as join11, resolve as resolve5 } from "path";
7871
+ import { mkdir as mkdir2, stat as stat4, writeFile } from "fs/promises";
7872
+ import { join as join11, resolve as resolve6 } from "path";
7045
7873
  import { stringify as stringifyYaml3 } from "yaml";
7046
7874
 
7047
7875
  // src/domains/session/create.ts
@@ -7291,7 +8119,7 @@ async function rejectDirectoryInjectionEntries(entries, cwd) {
7291
8119
  if (entry.length === 0) continue;
7292
8120
  let entryIsDirectory = false;
7293
8121
  try {
7294
- entryIsDirectory = (await stat3(resolve5(cwd, entry))).isDirectory();
8122
+ entryIsDirectory = (await stat4(resolve6(cwd, entry))).isDirectory();
7295
8123
  } catch {
7296
8124
  continue;
7297
8125
  }
@@ -7340,7 +8168,7 @@ async function handoffCommand(options) {
7340
8168
  const fullContent = `${SESSION_FRONT_MATTER_OPEN}${yaml}${SESSION_FRONT_MATTER_CLOSE}${body}`;
7341
8169
  const filename = `${sessionId}.md`;
7342
8170
  const sessionPath = join11(config.todoDir, filename);
7343
- const absolutePath = resolve5(sessionPath);
8171
+ const absolutePath = resolve6(sessionPath);
7344
8172
  await mkdir2(config.todoDir, { recursive: true });
7345
8173
  await writeFile(sessionPath, fullContent, SESSION_FILE_ENCODING);
7346
8174
  const output = `Created handoff session ${formatSessionOutputMarker(SESSION_OUTPUT_MARKER.HANDOFF_ID, sessionId)}
@@ -7349,7 +8177,7 @@ ${formatSessionOutputMarker(SESSION_OUTPUT_MARKER.SESSION_FILE, absolutePath)}`;
7349
8177
  }
7350
8178
 
7351
8179
  // src/commands/session/list.ts
7352
- import { readdir, readFile as readFile4 } from "fs/promises";
8180
+ import { readdir as readdir2, readFile as readFile5 } from "fs/promises";
7353
8181
  import { join as join12 } from "path";
7354
8182
  var SESSION_LIST_FORMAT = {
7355
8183
  TEXT: "text",
@@ -7358,13 +8186,13 @@ var SESSION_LIST_FORMAT = {
7358
8186
  var SESSION_LIST_EMPTY_TEXT = "(no sessions)";
7359
8187
  async function loadSessionsFromDir(dir, status) {
7360
8188
  try {
7361
- const files = await readdir(dir);
8189
+ const files = await readdir2(dir);
7362
8190
  const sessions = [];
7363
8191
  for (const file of files) {
7364
8192
  if (!file.endsWith(".md")) continue;
7365
8193
  const id = file.replace(".md", "");
7366
8194
  const filePath = join12(dir, file);
7367
- const content = await readFile4(filePath, SESSION_FILE_ENCODING);
8195
+ const content = await readFile5(filePath, SESSION_FILE_ENCODING);
7368
8196
  const metadata = parseSessionMetadata(content);
7369
8197
  sessions.push({
7370
8198
  id,
@@ -7427,8 +8255,8 @@ async function listCommand(options) {
7427
8255
  }
7428
8256
 
7429
8257
  // src/commands/session/pickup.ts
7430
- import { mkdir as mkdir3, readdir as readdir2, readFile as readFile5, rename as rename2 } from "fs/promises";
7431
- import { join as join13, resolve as resolve6 } from "path";
8258
+ import { mkdir as mkdir3, readdir as readdir3, readFile as readFile6, rename as rename2 } from "fs/promises";
8259
+ import { join as join13, resolve as resolve7 } from "path";
7432
8260
 
7433
8261
  // src/domains/session/pickup.ts
7434
8262
  function buildClaimPaths(sessionId, config) {
@@ -7467,8 +8295,8 @@ function selectBestSession(sessions) {
7467
8295
  var PICKUP_TARGET_STATUS = SESSION_STATUSES[1];
7468
8296
  var PICKUP_DEPS = {
7469
8297
  mkdir: mkdir3,
7470
- readdir: readdir2,
7471
- readFile: readFile5,
8298
+ readdir: readdir3,
8299
+ readFile: readFile6,
7472
8300
  rename: rename2
7473
8301
  };
7474
8302
  async function loadTodoSessions(config) {
@@ -7503,7 +8331,7 @@ var SESSION_INJECTION_SECTION_PREFIX = "Injected file";
7503
8331
  var SESSION_INJECTION_MISSING_WARNING_PREFIX = "Warning: missing session injection file";
7504
8332
  var SESSION_INJECTION_UNREADABLE_WARNING_PREFIX = "Warning: unreadable session injection path";
7505
8333
  function injectionPath(cwd, filePath) {
7506
- return resolve6(cwd, filePath);
8334
+ return resolve7(cwd, filePath);
7507
8335
  }
7508
8336
  function formatInjectedFile(listedPath, content) {
7509
8337
  return `${SESSION_INJECTION_SECTION_PREFIX}: ${listedPath}
@@ -7577,7 +8405,7 @@ async function loadPickCandidates(options) {
7577
8405
  }
7578
8406
 
7579
8407
  // src/commands/session/prune.ts
7580
- import { readdir as readdir3, readFile as readFile6, unlink as unlink2 } from "fs/promises";
8408
+ import { readdir as readdir4, readFile as readFile7, unlink as unlink2 } from "fs/promises";
7581
8409
  import { join as join14 } from "path";
7582
8410
 
7583
8411
  // src/domains/session/prune.ts
@@ -7622,13 +8450,13 @@ function validatePruneOptions(options) {
7622
8450
  }
7623
8451
  async function loadArchiveSessions(config) {
7624
8452
  try {
7625
- const files = await readdir3(config.archiveDir);
8453
+ const files = await readdir4(config.archiveDir);
7626
8454
  const sessions = [];
7627
8455
  for (const file of files) {
7628
8456
  if (!file.endsWith(".md")) continue;
7629
8457
  const id = file.replace(".md", "");
7630
8458
  const filePath = join14(config.archiveDir, file);
7631
- const content = await readFile6(filePath, SESSION_FILE_ENCODING);
8459
+ const content = await readFile7(filePath, SESSION_FILE_ENCODING);
7632
8460
  const metadata = parseSessionMetadata(content);
7633
8461
  sessions.push({
7634
8462
  id,
@@ -7677,7 +8505,7 @@ async function pruneCommand(options) {
7677
8505
  }
7678
8506
 
7679
8507
  // src/commands/session/release.ts
7680
- import { readdir as readdir4, rename as rename3 } from "fs/promises";
8508
+ import { readdir as readdir5, rename as rename3 } from "fs/promises";
7681
8509
 
7682
8510
  // src/domains/session/release.ts
7683
8511
  function buildReleasePaths(sessionId, config) {
@@ -7708,7 +8536,7 @@ var SESSION_RELEASE_OUTPUT = {
7708
8536
  };
7709
8537
  async function loadDoingSessions(config) {
7710
8538
  try {
7711
- const files = await readdir4(config.doingDir);
8539
+ const files = await readdir5(config.doingDir);
7712
8540
  return files.filter((file) => file.endsWith(".md")).map((file) => ({ id: file.replace(".md", "") }));
7713
8541
  } catch (error) {
7714
8542
  if (error instanceof Error && "code" in error && error.code === SESSION_FILE_ERROR_CODE.NOT_FOUND) {
@@ -7745,12 +8573,12 @@ async function releaseCommand(options) {
7745
8573
  }
7746
8574
 
7747
8575
  // src/commands/session/show.ts
7748
- import { readFile as readFile7, stat as stat4 } from "fs/promises";
8576
+ import { readFile as readFile8, stat as stat5 } from "fs/promises";
7749
8577
  async function findExistingPath(paths, _config) {
7750
8578
  for (let i = 0; i < paths.length; i++) {
7751
8579
  const filePath = paths[i];
7752
8580
  try {
7753
- const stats = await stat4(filePath);
8581
+ const stats = await stat5(filePath);
7754
8582
  if (stats.isFile()) {
7755
8583
  return { path: filePath, status: SEARCH_ORDER[i] };
7756
8584
  }
@@ -7765,7 +8593,7 @@ async function resolveSession(sessionId, config) {
7765
8593
  if (!found) {
7766
8594
  throw new SessionNotFoundError(sessionId);
7767
8595
  }
7768
- const content = await readFile7(found.path, SESSION_FILE_ENCODING);
8596
+ const content = await readFile8(found.path, SESSION_FILE_ENCODING);
7769
8597
  return { status: found.status, path: found.path, content };
7770
8598
  }
7771
8599
  async function showSingle(sessionId, config) {
@@ -7878,7 +8706,7 @@ Output:
7878
8706
  `;
7879
8707
 
7880
8708
  // src/domains/session/pick-model.ts
7881
- import { resolve as resolve7 } from "path";
8709
+ import { resolve as resolve8 } from "path";
7882
8710
  var ELLIPSIS = "\u2026";
7883
8711
  var PICKER_RUNTIME = {
7884
8712
  CLAUDE: "claude",
@@ -7895,7 +8723,7 @@ function buildPickupCommand(runtime, autoContinue, reference) {
7895
8723
  return { command: runtime, args: [prompt] };
7896
8724
  }
7897
8725
  function pickupReference(session, sessionsDir, cwd) {
7898
- return sessionsDir === void 0 ? session.id : resolve7(cwd, session.path);
8726
+ return sessionsDir === void 0 ? session.id : resolve8(cwd, session.path);
7899
8727
  }
7900
8728
  function toSingleLine(text) {
7901
8729
  return text.replaceAll(/\s+/g, " ").trim();
@@ -8010,209 +8838,18 @@ function reducePicker(state, action) {
8010
8838
  }
8011
8839
  }
8012
8840
 
8013
- // src/lib/process-lifecycle/exit-codes.ts
8014
- var SIGINT_EXIT_CODE = 130;
8015
- var SIGTERM_EXIT_CODE = 143;
8016
- var EPIPE_EXIT_CODE = 0;
8017
- var UNCAUGHT_EXIT_CODE = 1;
8018
-
8019
- // src/lib/process-lifecycle/foreground-handoff.ts
8020
- var FOREGROUND_SIGNALS = ["SIGINT", "SIGTERM"];
8021
- function createSignalSuspender(target) {
8022
- return {
8023
- suspend() {
8024
- const ignore = () => {
8025
- };
8026
- const restorers = FOREGROUND_SIGNALS.map((signal) => {
8027
- const originals = target.listeners(signal);
8028
- for (const listener of originals) target.removeListener(signal, listener);
8029
- target.on(signal, ignore);
8030
- return () => {
8031
- target.removeListener(signal, ignore);
8032
- for (const listener of originals) target.on(signal, listener);
8033
- };
8034
- });
8035
- return () => {
8036
- for (const restore of restorers) restore();
8037
- };
8038
- }
8039
- };
8040
- }
8041
-
8042
- // src/lib/process-lifecycle/handlers.ts
8043
- var SIGINT_NAME = "SIGINT";
8044
- var SIGTERM_NAME = "SIGTERM";
8045
- function createHandlers(deps) {
8046
- let cleanupOnce = false;
8047
- function killEachChild(signal) {
8048
- deps.registry.forEach((child) => {
8049
- if (!child.killed) child.kill(signal);
8050
- });
8051
- }
8052
- function exitOnce(code, killSignal) {
8053
- if (cleanupOnce) {
8054
- deps.exitController.exit(code);
8055
- return;
8056
- }
8057
- cleanupOnce = true;
8058
- if (killSignal !== void 0) killEachChild(killSignal);
8059
- deps.exitController.exit(code);
8060
- }
8061
- return {
8062
- onSigint() {
8063
- exitOnce(SIGINT_EXIT_CODE, SIGINT_NAME);
8064
- },
8065
- onSigterm() {
8066
- exitOnce(SIGTERM_EXIT_CODE, SIGTERM_NAME);
8067
- },
8068
- onEpipe() {
8069
- exitOnce(EPIPE_EXIT_CODE, SIGTERM_NAME);
8070
- },
8071
- onUncaught(_error) {
8072
- exitOnce(UNCAUGHT_EXIT_CODE, SIGTERM_NAME);
8073
- }
8074
- };
8075
- }
8076
-
8077
- // src/lib/process-lifecycle/install.ts
8078
- import { spawn } from "child_process";
8079
-
8080
- // src/lib/process-lifecycle/registry.ts
8081
- function createRegistry() {
8082
- const tracked = /* @__PURE__ */ new Set();
8083
- return {
8084
- add(child) {
8085
- tracked.add(child);
8086
- },
8087
- remove(child) {
8088
- tracked.delete(child);
8089
- },
8090
- forEach(fn) {
8091
- for (const child of tracked) fn(child);
8092
- },
8093
- get size() {
8094
- return tracked.size;
8095
- }
8096
- };
8097
- }
8098
-
8099
- // src/lib/process-lifecycle/runner.ts
8100
- function createLifecycleRunner(deps) {
8101
- return {
8102
- spawn(command, args, options) {
8103
- const child = deps.spawn(command, args, options);
8104
- deps.registry.add(child);
8105
- child.on("exit", () => deps.registry.remove(child));
8106
- return child;
8107
- }
8108
- };
8109
- }
8110
-
8111
- // src/lib/process-lifecycle/install.ts
8112
- var moduleRegistry = createRegistry();
8113
- var moduleExitController = {
8114
- exit(code) {
8115
- process.exit(code);
8116
- }
8117
- };
8118
- var installed = false;
8119
- var lifecycleProcessRunner = createLifecycleRunner({
8120
- registry: moduleRegistry,
8121
- spawn
8122
- });
8123
- var foregroundProcessRunner = { spawn };
8124
- var processSignalTarget = {
8125
- listeners: (signal) => process.listeners(signal),
8126
- on: (signal, listener) => {
8127
- process.on(signal, listener);
8128
- },
8129
- removeListener: (signal, listener) => {
8130
- process.removeListener(signal, listener);
8131
- }
8132
- };
8133
- var lifecycleSignalSuspender = createSignalSuspender(processSignalTarget);
8134
- var EPIPE_CODE = "EPIPE";
8135
- var UNCAUGHT_PREFIX = "Uncaught: ";
8136
- var NEWLINE = "\n";
8137
- function formatUncaught(error) {
8138
- if (error instanceof Error && error.stack !== void 0) {
8139
- return UNCAUGHT_PREFIX + error.stack + NEWLINE;
8140
- }
8141
- return UNCAUGHT_PREFIX + String(error) + NEWLINE;
8142
- }
8143
- function logUncaughtToStderr(error) {
8144
- try {
8145
- process.stderr.write(formatUncaught(error));
8146
- } catch {
8147
- }
8148
- }
8149
- function installLifecycle() {
8150
- if (installed) return;
8151
- installed = true;
8152
- const handlers = createHandlers({
8153
- registry: moduleRegistry,
8154
- exitController: moduleExitController
8155
- });
8156
- process.on("uncaughtException", (error) => {
8157
- logUncaughtToStderr(error);
8158
- handlers.onUncaught(error);
8159
- });
8160
- process.on("unhandledRejection", (reason) => {
8161
- logUncaughtToStderr(reason);
8162
- handlers.onUncaught(reason);
8163
- });
8164
- process.on("SIGTERM", () => handlers.onSigterm());
8165
- process.on("SIGINT", () => handlers.onSigint());
8166
- process.stdout.on("error", (error) => {
8167
- if (error.code === EPIPE_CODE) {
8168
- handlers.onEpipe();
8169
- return;
8170
- }
8171
- handlers.onUncaught(error);
8172
- });
8173
- process.stderr.on("error", (error) => {
8174
- if (error.code === EPIPE_CODE) {
8175
- handlers.onEpipe();
8176
- return;
8177
- }
8178
- handlers.onUncaught(error);
8179
- });
8180
- }
8181
-
8182
- // src/lib/process-lifecycle/managed-subprocess.ts
8183
- var MANAGED_SUBPROCESS_STDIO = "pipe";
8184
- function spawnManagedSubprocess(runner, command, args, options) {
8185
- return runner.spawn(command, args, {
8186
- ...options,
8187
- stdio: MANAGED_SUBPROCESS_STDIO
8188
- });
8189
- }
8190
-
8191
8841
  // src/interfaces/cli/session/pick/launch-agent.ts
8192
- var LAUNCH_FAILURE_STATUS = 1;
8193
8842
  function launchAgent(runner, suspender, command) {
8194
- const restoreSignals = suspender.suspend();
8195
- return new Promise((resolve11) => {
8196
- let settled = false;
8197
- const settle = (status) => {
8198
- if (settled) return;
8199
- settled = true;
8200
- restoreSignals();
8201
- resolve11(status);
8202
- };
8203
- const child = runner.spawn(command.command, command.args, { stdio: "inherit" });
8204
- child.once("exit", (code) => settle(code ?? LAUNCH_FAILURE_STATUS));
8205
- child.once("error", () => settle(LAUNCH_FAILURE_STATUS));
8206
- });
8843
+ return launchForegroundCommand(runner, suspender, command);
8207
8844
  }
8208
8845
 
8209
8846
  // src/interfaces/cli/session/pick/run-picker.tsx
8210
- import { render } from "ink";
8847
+ import { render as render2 } from "ink";
8211
8848
 
8212
8849
  // src/interfaces/cli/session/pick/SessionPicker.tsx
8213
- import { Box, Text, useInput, useStdout } from "ink";
8214
- import { useState } from "react";
8215
- import { jsx, jsxs } from "react/jsx-runtime";
8850
+ import { Box as Box2, Text as Text2, useInput as useInput2, useStdout } from "ink";
8851
+ import { useState as useState2 } from "react";
8852
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
8216
8853
  var SESSION_PICKER_TITLE = "Pick a session to launch";
8217
8854
  var SESSION_PICKER_EMPTY_TEXT = "No claimable sessions.";
8218
8855
  var SESSION_PICKER_BROWSE_HINT = "\u2191\u2193 move \xB7 / filter \xB7 c/C claude \xB7 x/X codex \xB7 q quit";
@@ -8245,33 +8882,33 @@ function SessionRow({ session, selected, columns }) {
8245
8882
  const badge = priority === DEFAULT_PRIORITY ? "" : ` [${priority}]`;
8246
8883
  const reserved = visibleWidth(marker) + visibleWidth(" ") + visibleWidth(session.id) + visibleWidth(badge) + visibleWidth(" ");
8247
8884
  const goal = truncateToWidth(toSingleLine(session.metadata.goal), Math.max(MIN_GOAL_WIDTH, columns - reserved));
8248
- return /* @__PURE__ */ jsxs(Text, { wrap: "truncate", color: selected ? "cyan" : void 0, children: [
8885
+ return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", color: selected ? "cyan" : void 0, children: [
8249
8886
  marker,
8250
8887
  " ",
8251
8888
  session.id,
8252
- /* @__PURE__ */ jsx(Text, { color: PRIORITY_COLOR[priority], children: badge }),
8889
+ /* @__PURE__ */ jsx3(Text2, { color: PRIORITY_COLOR[priority], children: badge }),
8253
8890
  " ",
8254
8891
  goal
8255
8892
  ] });
8256
8893
  }
8257
8894
  function PreviewField({ label, value }) {
8258
- return /* @__PURE__ */ jsx(Text, { children: `${label} ${value}` });
8895
+ return /* @__PURE__ */ jsx3(Text2, { children: `${label} ${value}` });
8259
8896
  }
8260
8897
  function PreviewPane({ session }) {
8261
8898
  if (session === null) {
8262
- return /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: SESSION_PICKER_EMPTY_TEXT }) });
8899
+ return /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: SESSION_PICKER_EMPTY_TEXT }) });
8263
8900
  }
8264
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
8265
- /* @__PURE__ */ jsx(PreviewField, { label: PREVIEW_GOAL_LABEL, value: session.metadata.goal }),
8266
- /* @__PURE__ */ jsx(PreviewField, { label: PREVIEW_NEXT_LABEL, value: session.metadata.next_step })
8901
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, children: [
8902
+ /* @__PURE__ */ jsx3(PreviewField, { label: PREVIEW_GOAL_LABEL, value: session.metadata.goal }),
8903
+ /* @__PURE__ */ jsx3(PreviewField, { label: PREVIEW_NEXT_LABEL, value: session.metadata.next_step })
8267
8904
  ] });
8268
8905
  }
8269
8906
  function SessionPicker({ sessions, onLaunch, onQuit, columns: columnsProp }) {
8270
8907
  const { stdout } = useStdout();
8271
8908
  const stdoutColumns = Reflect.get(stdout, "columns");
8272
8909
  const columns = columnsProp ?? (typeof stdoutColumns === "number" ? stdoutColumns : FALLBACK_COLUMNS);
8273
- const [state, setState] = useState(() => initialPickerState(sessions));
8274
- useInput((input, key) => {
8910
+ const [state, setState] = useState2(() => initialPickerState(sessions));
8911
+ useInput2((input, key) => {
8275
8912
  const action = keyToAction(toPickerKey(input, key), state.mode);
8276
8913
  if (action === null) return;
8277
8914
  if (action.type === PICKER_ACTION.LAUNCH) {
@@ -8288,28 +8925,28 @@ function SessionPicker({ sessions, onLaunch, onQuit, columns: columnsProp }) {
8288
8925
  const visible = visibleCandidates(state);
8289
8926
  const selected = selectedSession(state);
8290
8927
  const hint = state.mode === PICKER_MODE.FILTER ? SESSION_PICKER_FILTER_HINT : SESSION_PICKER_BROWSE_HINT;
8291
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
8292
- /* @__PURE__ */ jsx(Text, { bold: true, children: SESSION_PICKER_TITLE }),
8293
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
8928
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
8929
+ /* @__PURE__ */ jsx3(Text2, { bold: true, children: SESSION_PICKER_TITLE }),
8930
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
8294
8931
  SESSION_PICKER_FILTER_LABEL,
8295
8932
  " ",
8296
8933
  state.query
8297
8934
  ] }),
8298
- visible.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: SESSION_PICKER_EMPTY_TEXT }) : visible.map((session, index) => /* @__PURE__ */ jsx(SessionRow, { session, selected: index === state.selectedIndex, columns }, session.id)),
8299
- /* @__PURE__ */ jsx(PreviewPane, { session: selected }),
8300
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) })
8935
+ visible.length === 0 ? /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: SESSION_PICKER_EMPTY_TEXT }) : visible.map((session, index) => /* @__PURE__ */ jsx3(SessionRow, { session, selected: index === state.selectedIndex, columns }, session.id)),
8936
+ /* @__PURE__ */ jsx3(PreviewPane, { session: selected }),
8937
+ /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: hint }) })
8301
8938
  ] });
8302
8939
  }
8303
8940
 
8304
8941
  // src/interfaces/cli/session/pick/run-picker.tsx
8305
- import { jsx as jsx2 } from "react/jsx-runtime";
8942
+ import { jsx as jsx4 } from "react/jsx-runtime";
8306
8943
  var PICK_NON_TTY_MESSAGE = "session pick requires an interactive terminal. Run `claude '/pickup <id>'` or `codex '$pickup <id>'` directly in a non-interactive context.";
8307
- async function runPicker(sessions, renderPicker = render) {
8944
+ async function runPicker(sessions, renderPicker = render2) {
8308
8945
  let choice = null;
8309
8946
  let unmount = () => {
8310
8947
  };
8311
8948
  const instance = renderPicker(
8312
- /* @__PURE__ */ jsx2(
8949
+ /* @__PURE__ */ jsx4(
8313
8950
  SessionPicker,
8314
8951
  {
8315
8952
  sessions,
@@ -8333,31 +8970,31 @@ async function readStdin() {
8333
8970
  if (process.stdin.isTTY) {
8334
8971
  return void 0;
8335
8972
  }
8336
- return new Promise((resolve11) => {
8973
+ return new Promise((resolve12) => {
8337
8974
  let data = "";
8338
8975
  process.stdin.setEncoding(SESSION_FILE_ENCODING);
8339
8976
  process.stdin.on("data", (chunk) => {
8340
8977
  data += chunk;
8341
8978
  });
8342
8979
  process.stdin.on("end", () => {
8343
- resolve11(data.length === 0 ? void 0 : data);
8980
+ resolve12(data.length === 0 ? void 0 : data);
8344
8981
  });
8345
8982
  process.stdin.on("error", () => {
8346
- resolve11(void 0);
8983
+ resolve12(void 0);
8347
8984
  });
8348
8985
  });
8349
8986
  }
8350
- function writeOutput2(invocation, output) {
8987
+ function writeOutput3(invocation, output) {
8351
8988
  invocation.io.writeStdout(`${output}
8352
8989
  `);
8353
8990
  }
8354
- function writeError3(invocation, output) {
8991
+ function writeError4(invocation, output) {
8355
8992
  invocation.io.writeStderr(`${output}
8356
8993
  `);
8357
8994
  }
8358
8995
  function writeInvocationWarning2(invocation, warning) {
8359
8996
  if (warning !== void 0) {
8360
- writeError3(invocation, warning);
8997
+ writeError4(invocation, warning);
8361
8998
  }
8362
8999
  }
8363
9000
  function formatError2(error) {
@@ -8366,8 +9003,8 @@ function formatError2(error) {
8366
9003
  }
8367
9004
  return toMessage(error);
8368
9005
  }
8369
- function handleError2(invocation, error) {
8370
- writeError3(invocation, `Error: ${formatError2(error)}`);
9006
+ function handleError3(invocation, error) {
9007
+ writeError4(invocation, `Error: ${formatError2(error)}`);
8371
9008
  return invocation.io.exit(1);
8372
9009
  }
8373
9010
  function colorFlagFromOption(colorOption) {
@@ -8420,9 +9057,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8420
9057
  cwd: effectiveInvocationDir(),
8421
9058
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8422
9059
  });
8423
- writeOutput2(invocation, output);
9060
+ writeOutput3(invocation, output);
8424
9061
  } catch (error) {
8425
- handleError2(invocation, error);
9062
+ handleError3(invocation, error);
8426
9063
  }
8427
9064
  }
8428
9065
  );
@@ -8432,7 +9069,7 @@ function registerSessionCommands(sessionCmd, invocation) {
8432
9069
  ).action(async (options) => {
8433
9070
  try {
8434
9071
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
8435
- writeError3(invocation, PICK_NON_TTY_MESSAGE);
9072
+ writeError4(invocation, PICK_NON_TTY_MESSAGE);
8436
9073
  invocation.io.exit(1);
8437
9074
  }
8438
9075
  const sessions = await loadPickCandidates({
@@ -8448,7 +9085,7 @@ function registerSessionCommands(sessionCmd, invocation) {
8448
9085
  invocation.io.exit(code);
8449
9086
  }
8450
9087
  } catch (error) {
8451
- handleError2(invocation, error);
9088
+ handleError3(invocation, error);
8452
9089
  }
8453
9090
  });
8454
9091
  addSessionOptions(
@@ -8466,9 +9103,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8466
9103
  cwd: effectiveInvocationDir(),
8467
9104
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8468
9105
  });
8469
- writeOutput2(invocation, output);
9106
+ writeOutput3(invocation, output);
8470
9107
  } catch (error) {
8471
- handleError2(invocation, error);
9108
+ handleError3(invocation, error);
8472
9109
  }
8473
9110
  });
8474
9111
  addSessionOptions(
@@ -8483,9 +9120,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8483
9120
  cwd: effectiveInvocationDir(),
8484
9121
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8485
9122
  });
8486
- writeOutput2(invocation, output);
9123
+ writeOutput3(invocation, output);
8487
9124
  } catch (error) {
8488
- handleError2(invocation, error);
9125
+ handleError3(invocation, error);
8489
9126
  }
8490
9127
  });
8491
9128
  addSessionOptions(
@@ -8494,7 +9131,7 @@ function registerSessionCommands(sessionCmd, invocation) {
8494
9131
  ).addHelpText("after", PICKUP_SELECTION_HELP).action(async (ids, options) => {
8495
9132
  try {
8496
9133
  if (ids.length === 0 && !options.auto) {
8497
- writeError3(invocation, "Error: Either session ID or --auto flag is required");
9134
+ writeError4(invocation, "Error: Either session ID or --auto flag is required");
8498
9135
  invocation.io.exit(1);
8499
9136
  }
8500
9137
  const output = await pickupCommand({
@@ -8505,9 +9142,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8505
9142
  cwd: effectiveInvocationDir(),
8506
9143
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8507
9144
  });
8508
- writeOutput2(invocation, output);
9145
+ writeOutput3(invocation, output);
8509
9146
  } catch (error) {
8510
- handleError2(invocation, error);
9147
+ handleError3(invocation, error);
8511
9148
  }
8512
9149
  });
8513
9150
  addSessionOptions(
@@ -8521,9 +9158,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8521
9158
  cwd: effectiveInvocationDir(),
8522
9159
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8523
9160
  });
8524
- writeOutput2(invocation, output);
9161
+ writeOutput3(invocation, output);
8525
9162
  } catch (error) {
8526
- handleError2(invocation, error);
9163
+ handleError3(invocation, error);
8527
9164
  }
8528
9165
  });
8529
9166
  addSessionOptions(
@@ -8538,17 +9175,17 @@ function registerSessionCommands(sessionCmd, invocation) {
8538
9175
  cwd: effectiveInvocationDir(),
8539
9176
  env: process.env
8540
9177
  });
8541
- writeOutput2(invocation, result.output);
9178
+ writeOutput3(invocation, result.output);
8542
9179
  } catch (error) {
8543
9180
  if (error instanceof SessionHandoffBaseError) {
8544
9181
  if (error.checklist !== null) {
8545
- writeError3(invocation, renderHandoffBaseChecklist(error.checklist));
9182
+ writeError4(invocation, renderHandoffBaseChecklist(error.checklist));
8546
9183
  } else if (!error.silent) {
8547
- writeError3(invocation, `Error: ${error.name}: ${error.message}`);
9184
+ writeError4(invocation, `Error: ${error.name}: ${error.message}`);
8548
9185
  }
8549
9186
  invocation.io.exit(1);
8550
9187
  }
8551
- handleError2(invocation, error);
9188
+ handleError3(invocation, error);
8552
9189
  }
8553
9190
  });
8554
9191
  addSessionOptions(
@@ -8562,9 +9199,9 @@ function registerSessionCommands(sessionCmd, invocation) {
8562
9199
  cwd: effectiveInvocationDir(),
8563
9200
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8564
9201
  });
8565
- writeOutput2(invocation, output);
9202
+ writeOutput3(invocation, output);
8566
9203
  } catch (error) {
8567
- handleError2(invocation, error);
9204
+ handleError3(invocation, error);
8568
9205
  }
8569
9206
  });
8570
9207
  addSessionOptions(
@@ -8580,13 +9217,13 @@ function registerSessionCommands(sessionCmd, invocation) {
8580
9217
  cwd: effectiveInvocationDir(),
8581
9218
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8582
9219
  });
8583
- writeOutput2(invocation, output);
9220
+ writeOutput3(invocation, output);
8584
9221
  } catch (error) {
8585
9222
  if (error instanceof PruneValidationError) {
8586
- writeError3(invocation, `Error: ${error.message}`);
9223
+ writeError4(invocation, `Error: ${error.message}`);
8587
9224
  invocation.io.exit(1);
8588
9225
  }
8589
- handleError2(invocation, error);
9226
+ handleError3(invocation, error);
8590
9227
  }
8591
9228
  });
8592
9229
  addSessionOptions(
@@ -8600,13 +9237,13 @@ function registerSessionCommands(sessionCmd, invocation) {
8600
9237
  cwd: effectiveInvocationDir(),
8601
9238
  onWarning: (warning) => writeInvocationWarning2(invocation, warning)
8602
9239
  });
8603
- writeOutput2(invocation, output);
9240
+ writeOutput3(invocation, output);
8604
9241
  } catch (error) {
8605
9242
  if (error instanceof SessionAlreadyArchivedError) {
8606
- writeError3(invocation, `Error: ${error.message}`);
9243
+ writeError4(invocation, `Error: ${error.message}`);
8607
9244
  invocation.io.exit(1);
8608
9245
  }
8609
- handleError2(invocation, error);
9246
+ handleError3(invocation, error);
8610
9247
  }
8611
9248
  });
8612
9249
  }
@@ -8620,7 +9257,7 @@ var sessionDomain = {
8620
9257
  };
8621
9258
 
8622
9259
  // src/lib/spec-tree/index.ts
8623
- import { readdir as readdir5, readFile as readFile8 } from "fs/promises";
9260
+ import { readdir as readdir6, readFile as readFile9 } from "fs/promises";
8624
9261
  import { join as join15 } from "path";
8625
9262
  var SPEC_TREE_FIELD_KEY = {
8626
9263
  VERSION: "version",
@@ -8705,7 +9342,7 @@ function createFilesystemSpecTreeSource(options) {
8705
9342
  if (ref.path === void 0) {
8706
9343
  throw new Error("Filesystem source refs require a path");
8707
9344
  }
8708
- return readFile8(join15(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);
9345
+ return readFile9(join15(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);
8709
9346
  }
8710
9347
  };
8711
9348
  }
@@ -8996,7 +9633,7 @@ async function* readFilesystemSourceEntries(productDir, registry, schemaVersions
8996
9633
  async function* walkFilesystemDirectory(context) {
8997
9634
  let entries;
8998
9635
  try {
8999
- entries = await readdir5(context.absolutePath, { withFileTypes: true });
9636
+ entries = await readdir6(context.absolutePath, { withFileTypes: true });
9000
9637
  } catch (error) {
9001
9638
  if (isFileNotFound2(error)) return;
9002
9639
  throw error;
@@ -9168,7 +9805,7 @@ function formatNextNode(node) {
9168
9805
  }
9169
9806
 
9170
9807
  // src/commands/test/discovery.ts
9171
- import { readdir as readdir6 } from "fs/promises";
9808
+ import { readdir as readdir7 } from "fs/promises";
9172
9809
  import { join as join16, relative, sep } from "path";
9173
9810
  var TESTS_DIRECTORY_NAME = SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME;
9174
9811
  var SPEC_ROOT_DIRECTORY = SPEC_TREE_CONFIG.ROOT_DIRECTORY;
@@ -9182,7 +9819,7 @@ async function discoverTestFiles(productDir) {
9182
9819
  async function collectTestFiles(directory, insideTestsDir, found) {
9183
9820
  let entries;
9184
9821
  try {
9185
- entries = await readdir6(directory, { withFileTypes: true });
9822
+ entries = await readdir7(directory, { withFileTypes: true });
9186
9823
  } catch (error) {
9187
9824
  if (hasErrorCode2(error, ERROR_CODE_NOT_FOUND2)) return;
9188
9825
  throw error;
@@ -9516,7 +10153,7 @@ async function readTestRunStatePath(runFilePath, fs8) {
9516
10153
  return { ok: true, value: validated.value };
9517
10154
  }
9518
10155
  function validateTestRunState(value) {
9519
- if (!isRecord4(value)) return { ok: false, error: "testing run state must be an object" };
10156
+ if (!isRecord5(value)) return { ok: false, error: "testing run state must be an object" };
9520
10157
  const branchName = readString(value, TEST_RUN_STATE_FIELDS.BRANCH_NAME);
9521
10158
  if (!branchName.ok) return branchName;
9522
10159
  const headSha = readString(value, TEST_RUN_STATE_FIELDS.HEAD_SHA);
@@ -9559,7 +10196,7 @@ function readRunnerOutcomes(raw) {
9559
10196
  }
9560
10197
  const outcomes = [];
9561
10198
  for (const entry of raw) {
9562
- if (!isRecord4(entry)) {
10199
+ if (!isRecord5(entry)) {
9563
10200
  return { ok: false, error: `${TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES} entries must be objects` };
9564
10201
  }
9565
10202
  const runnerId = readString(entry, TEST_RUNNER_OUTCOME_FIELDS.RUNNER_ID);
@@ -9580,7 +10217,7 @@ function readProductInputDigests(raw) {
9580
10217
  }
9581
10218
  const digests = [];
9582
10219
  for (const entry of raw) {
9583
- if (!isRecord4(entry)) {
10220
+ if (!isRecord5(entry)) {
9584
10221
  return { ok: false, error: `${TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS} entries must be objects` };
9585
10222
  }
9586
10223
  const descriptorId = readString(entry, PRODUCT_INPUT_DIGEST_FIELDS.DESCRIPTOR_ID);
@@ -9642,7 +10279,7 @@ function testingWriteError(error) {
9642
10279
  function withDomainErrorDetail(domainError, detail) {
9643
10280
  return detail === void 0 ? domainError : `${domainError}: ${detail}`;
9644
10281
  }
9645
- function isRecord4(value) {
10282
+ function isRecord5(value) {
9646
10283
  return typeof value === "object" && value !== null && !Array.isArray(value);
9647
10284
  }
9648
10285
  function sha256Hex2(value) {
@@ -10024,7 +10661,7 @@ function createNodeStatusProvider(productDir) {
10024
10661
  }
10025
10662
 
10026
10663
  // src/lib/node-status/update.ts
10027
- import { mkdir as mkdir4, readdir as readdir7, rm, writeFile as writeFile2 } from "fs/promises";
10664
+ import { mkdir as mkdir4, readdir as readdir8, rm, writeFile as writeFile2 } from "fs/promises";
10028
10665
  import { dirname as dirname7, join as join21 } from "path";
10029
10666
 
10030
10667
  // src/git/tracked-paths.ts
@@ -10151,7 +10788,7 @@ async function collectNodeStatusFiles(directory) {
10151
10788
  }
10152
10789
  async function readDirectoryEntries(directory) {
10153
10790
  try {
10154
- return await readdir7(directory, { withFileTypes: true });
10791
+ return await readdir8(directory, { withFileTypes: true });
10155
10792
  } catch (error) {
10156
10793
  if (isNodeError3(error) && error.code === "ENOENT") return [];
10157
10794
  throw error;
@@ -10654,7 +11291,7 @@ var VALID_STATUS_FORMATS = [
10654
11291
  OUTPUT_FORMAT.TABLE
10655
11292
  ];
10656
11293
  var UNPRINTABLE_ERROR_MESSAGE = "unprintable error";
10657
- function writeOutput3(io, output) {
11294
+ function writeOutput4(io, output) {
10658
11295
  io.writeStdout(`${output}
10659
11296
  `);
10660
11297
  }
@@ -10712,7 +11349,7 @@ function registerSpecCommands(specCmd, invocation) {
10712
11349
  runnerDepsFor: createRunnerDepsFor(productDir2, process.stderr)
10713
11350
  })
10714
11351
  }) : await statusCommand({ cwd: productDir(), format: format2, onWarning });
10715
- writeOutput3(invocation.io, output);
11352
+ writeOutput4(invocation.io, output);
10716
11353
  } catch (error) {
10717
11354
  handleCommandError(invocation.io, error);
10718
11355
  }
@@ -10720,7 +11357,7 @@ function registerSpecCommands(specCmd, invocation) {
10720
11357
  specCmd.command(SPEC_DOMAIN_CLI.NEXT_COMMAND).description("Find next spec-tree node to work on").action(async () => {
10721
11358
  try {
10722
11359
  const output = await nextCommand({ cwd: productDir(), onWarning });
10723
- writeOutput3(invocation.io, output);
11360
+ writeOutput4(invocation.io, output);
10724
11361
  } catch (error) {
10725
11362
  handleCommandError(invocation.io, error);
10726
11363
  }
@@ -10974,7 +11611,7 @@ var testingDomain = createTestingDomain();
10974
11611
 
10975
11612
  // src/interfaces/cli/validation.ts
10976
11613
  import { existsSync as existsSync8, realpathSync } from "fs";
10977
- import { isAbsolute as isAbsolute9, relative as relative9, resolve as resolve10, sep as sep3 } from "path";
11614
+ import { isAbsolute as isAbsolute9, relative as relative9, resolve as resolve11, sep as sep3 } from "path";
10978
11615
 
10979
11616
  // src/commands/validation/formatting.ts
10980
11617
  import { existsSync, statSync } from "fs";
@@ -11165,7 +11802,7 @@ function buildDprintCheckArgs(options) {
11165
11802
  }
11166
11803
  async function validateFormatting(context, runner = defaultFormattingProcessRunner) {
11167
11804
  const args = buildDprintCheckArgs({ files: context.files, excludes: context.excludes });
11168
- return new Promise((resolve11) => {
11805
+ return new Promise((resolve12) => {
11169
11806
  const child = spawnManagedSubprocess(runner, DPRINT_COMMAND, args, { cwd: context.projectRoot });
11170
11807
  const chunks = [];
11171
11808
  const capture = (chunk) => {
@@ -11174,10 +11811,10 @@ async function validateFormatting(context, runner = defaultFormattingProcessRunn
11174
11811
  child.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
11175
11812
  child.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
11176
11813
  child.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
11177
- resolve11({ success: code === 0, output: chunks.join("") });
11814
+ resolve12({ success: code === 0, output: chunks.join("") });
11178
11815
  });
11179
11816
  child.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {
11180
- resolve11({ success: false, output: chunks.join(""), error: error.message });
11817
+ resolve12({ success: false, output: chunks.join(""), error: error.message });
11181
11818
  });
11182
11819
  });
11183
11820
  }
@@ -12195,39 +12832,39 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12195
12832
  const token = _scanner.scan();
12196
12833
  switch (_scanner.getTokenError()) {
12197
12834
  case 4:
12198
- handleError4(
12835
+ handleError5(
12199
12836
  14
12200
12837
  /* ParseErrorCode.InvalidUnicode */
12201
12838
  );
12202
12839
  break;
12203
12840
  case 5:
12204
- handleError4(
12841
+ handleError5(
12205
12842
  15
12206
12843
  /* ParseErrorCode.InvalidEscapeCharacter */
12207
12844
  );
12208
12845
  break;
12209
12846
  case 3:
12210
- handleError4(
12847
+ handleError5(
12211
12848
  13
12212
12849
  /* ParseErrorCode.UnexpectedEndOfNumber */
12213
12850
  );
12214
12851
  break;
12215
12852
  case 1:
12216
12853
  if (!disallowComments) {
12217
- handleError4(
12854
+ handleError5(
12218
12855
  11
12219
12856
  /* ParseErrorCode.UnexpectedEndOfComment */
12220
12857
  );
12221
12858
  }
12222
12859
  break;
12223
12860
  case 2:
12224
- handleError4(
12861
+ handleError5(
12225
12862
  12
12226
12863
  /* ParseErrorCode.UnexpectedEndOfString */
12227
12864
  );
12228
12865
  break;
12229
12866
  case 6:
12230
- handleError4(
12867
+ handleError5(
12231
12868
  16
12232
12869
  /* ParseErrorCode.InvalidCharacter */
12233
12870
  );
@@ -12237,7 +12874,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12237
12874
  case 12:
12238
12875
  case 13:
12239
12876
  if (disallowComments) {
12240
- handleError4(
12877
+ handleError5(
12241
12878
  10
12242
12879
  /* ParseErrorCode.InvalidCommentToken */
12243
12880
  );
@@ -12246,7 +12883,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12246
12883
  }
12247
12884
  break;
12248
12885
  case 16:
12249
- handleError4(
12886
+ handleError5(
12250
12887
  1
12251
12888
  /* ParseErrorCode.InvalidSymbol */
12252
12889
  );
@@ -12259,7 +12896,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12259
12896
  }
12260
12897
  }
12261
12898
  }
12262
- function handleError4(error, skipUntilAfter = [], skipUntil = []) {
12899
+ function handleError5(error, skipUntilAfter = [], skipUntil = []) {
12263
12900
  onError(error);
12264
12901
  if (skipUntilAfter.length + skipUntil.length > 0) {
12265
12902
  let token = _scanner.getToken();
@@ -12291,7 +12928,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12291
12928
  const tokenValue = _scanner.getTokenValue();
12292
12929
  let value = Number(tokenValue);
12293
12930
  if (isNaN(value)) {
12294
- handleError4(
12931
+ handleError5(
12295
12932
  2
12296
12933
  /* ParseErrorCode.InvalidNumberFormat */
12297
12934
  );
@@ -12316,7 +12953,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12316
12953
  }
12317
12954
  function parseProperty() {
12318
12955
  if (_scanner.getToken() !== 10) {
12319
- handleError4(3, [], [
12956
+ handleError5(3, [], [
12320
12957
  2,
12321
12958
  5
12322
12959
  /* SyntaxKind.CommaToken */
@@ -12328,14 +12965,14 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12328
12965
  onSeparator(":");
12329
12966
  scanNext();
12330
12967
  if (!parseValue()) {
12331
- handleError4(4, [], [
12968
+ handleError5(4, [], [
12332
12969
  2,
12333
12970
  5
12334
12971
  /* SyntaxKind.CommaToken */
12335
12972
  ]);
12336
12973
  }
12337
12974
  } else {
12338
- handleError4(5, [], [
12975
+ handleError5(5, [], [
12339
12976
  2,
12340
12977
  5
12341
12978
  /* SyntaxKind.CommaToken */
@@ -12351,7 +12988,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12351
12988
  while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
12352
12989
  if (_scanner.getToken() === 5) {
12353
12990
  if (!needsComma) {
12354
- handleError4(4, [], []);
12991
+ handleError5(4, [], []);
12355
12992
  }
12356
12993
  onSeparator(",");
12357
12994
  scanNext();
@@ -12359,10 +12996,10 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12359
12996
  break;
12360
12997
  }
12361
12998
  } else if (needsComma) {
12362
- handleError4(6, [], []);
12999
+ handleError5(6, [], []);
12363
13000
  }
12364
13001
  if (!parseProperty()) {
12365
- handleError4(4, [], [
13002
+ handleError5(4, [], [
12366
13003
  2,
12367
13004
  5
12368
13005
  /* SyntaxKind.CommaToken */
@@ -12372,7 +13009,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12372
13009
  }
12373
13010
  onObjectEnd();
12374
13011
  if (_scanner.getToken() !== 2) {
12375
- handleError4(7, [
13012
+ handleError5(7, [
12376
13013
  2
12377
13014
  /* SyntaxKind.CloseBraceToken */
12378
13015
  ], []);
@@ -12389,7 +13026,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12389
13026
  while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
12390
13027
  if (_scanner.getToken() === 5) {
12391
13028
  if (!needsComma) {
12392
- handleError4(4, [], []);
13029
+ handleError5(4, [], []);
12393
13030
  }
12394
13031
  onSeparator(",");
12395
13032
  scanNext();
@@ -12397,7 +13034,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12397
13034
  break;
12398
13035
  }
12399
13036
  } else if (needsComma) {
12400
- handleError4(6, [], []);
13037
+ handleError5(6, [], []);
12401
13038
  }
12402
13039
  if (isFirstElement) {
12403
13040
  _jsonPath.push(0);
@@ -12406,7 +13043,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12406
13043
  _jsonPath[_jsonPath.length - 1]++;
12407
13044
  }
12408
13045
  if (!parseValue()) {
12409
- handleError4(4, [], [
13046
+ handleError5(4, [], [
12410
13047
  4,
12411
13048
  5
12412
13049
  /* SyntaxKind.CommaToken */
@@ -12419,7 +13056,7 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12419
13056
  _jsonPath.pop();
12420
13057
  }
12421
13058
  if (_scanner.getToken() !== 4) {
12422
- handleError4(8, [
13059
+ handleError5(8, [
12423
13060
  4
12424
13061
  /* SyntaxKind.CloseBracketToken */
12425
13062
  ], []);
@@ -12445,15 +13082,15 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
12445
13082
  if (options.allowEmptyContent) {
12446
13083
  return true;
12447
13084
  }
12448
- handleError4(4, [], []);
13085
+ handleError5(4, [], []);
12449
13086
  return false;
12450
13087
  }
12451
13088
  if (!parseValue()) {
12452
- handleError4(4, [], []);
13089
+ handleError5(4, [], []);
12453
13090
  return false;
12454
13091
  }
12455
13092
  if (_scanner.getToken() !== 17) {
12456
- handleError4(9, [], []);
13093
+ handleError5(9, [], []);
12457
13094
  }
12458
13095
  return true;
12459
13096
  }
@@ -12512,7 +13149,7 @@ var ParseErrorCode;
12512
13149
 
12513
13150
  // src/validation/config/scope.ts
12514
13151
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "fs";
12515
- import { isAbsolute as isAbsolute5, join as join27, relative as relative5, resolve as resolve8 } from "path";
13152
+ import { isAbsolute as isAbsolute5, join as join27, relative as relative5, resolve as resolve9 } from "path";
12516
13153
  var TSCONFIG_FILES = {
12517
13154
  full: "tsconfig.json",
12518
13155
  production: "tsconfig.production.json"
@@ -12665,7 +13302,7 @@ function directoryPassesIncludePatterns(directory, patterns, projectRoot, deps)
12665
13302
  (pattern) => includePatternTargetsTypeScriptScope(pattern, projectRoot, deps) && typeScriptScopePatternIntersectsDirectory(pattern, directory)
12666
13303
  );
12667
13304
  }
12668
- function stripTrailingPathSeparators(value) {
13305
+ function stripTrailingPathSeparators2(value) {
12669
13306
  let end = value.length;
12670
13307
  while (end > 0 && value.charAt(end - 1) === PATH_SEGMENT_SEPARATOR3) {
12671
13308
  end -= 1;
@@ -12674,7 +13311,7 @@ function stripTrailingPathSeparators(value) {
12674
13311
  }
12675
13312
  function normalizeTypeScriptScopePath(path7) {
12676
13313
  const joined = path7.split(/[\\/]/gu).join(PATH_SEGMENT_SEPARATOR3).replace(/^\.\//u, "");
12677
- return stripTrailingPathSeparators(joined);
13314
+ return stripTrailingPathSeparators2(joined);
12678
13315
  }
12679
13316
  function pathMatchesLiteralPrefix(path7, prefix) {
12680
13317
  const normalizedPath = normalizeTypeScriptScopePath(path7);
@@ -12694,7 +13331,7 @@ function globLiteralPrefix(pattern) {
12694
13331
  if (globIndex === -1) {
12695
13332
  return normalizedPattern;
12696
13333
  }
12697
- return stripTrailingPathSeparators(normalizedPattern.slice(0, globIndex));
13334
+ return stripTrailingPathSeparators2(normalizedPattern.slice(0, globIndex));
12698
13335
  }
12699
13336
  function firstGlobMarkerIndex(path7) {
12700
13337
  const globIndex = path7.indexOf(GLOB_MARKER);
@@ -12886,13 +13523,13 @@ function pathPassesTypeScriptScope(path7, scopeConfig) {
12886
13523
  return included && !excluded;
12887
13524
  }
12888
13525
  function pathStaysInsideTypeScriptScopeRoot(projectRoot, path7) {
12889
- const resolvedPath = isAbsolute5(path7) ? resolve8(path7) : resolve8(projectRoot, path7);
13526
+ const resolvedPath = isAbsolute5(path7) ? resolve9(path7) : resolve9(projectRoot, path7);
12890
13527
  const relativePath = relative5(projectRoot, resolvedPath);
12891
13528
  const segments = normalizeTypeScriptScopePath(relativePath).split(PATH_SEGMENT_SEPARATOR3);
12892
13529
  return relativePath.length === 0 || !segments.includes("..") && !isAbsolute5(relativePath);
12893
13530
  }
12894
13531
  function toProjectRelativeTypeScriptScopePath(projectRoot, path7) {
12895
- const resolvedPath = isAbsolute5(path7) ? resolve8(path7) : resolve8(projectRoot, path7);
13532
+ const resolvedPath = isAbsolute5(path7) ? resolve9(path7) : resolve9(projectRoot, path7);
12896
13533
  const relativePath = relative5(projectRoot, resolvedPath);
12897
13534
  return relativePath.length === 0 ? TYPESCRIPT_SCOPE_PROJECT_ROOT : normalizeTypeScriptScopePath(relativePath);
12898
13535
  }
@@ -13645,13 +14282,13 @@ async function runKnipSubprocess(projectRoot, typescriptScope, runner, deps) {
13645
14282
  knipProcess.stderr?.on("data", (data) => {
13646
14283
  knipError += data.toString();
13647
14284
  });
13648
- return new Promise((resolve11) => {
14285
+ return new Promise((resolve12) => {
13649
14286
  const resolveAfterCleanup = (result) => {
13650
14287
  if (resultResolved) {
13651
14288
  return;
13652
14289
  }
13653
14290
  resultResolved = true;
13654
- void cleanupOnce().finally(() => resolve11(result));
14291
+ void cleanupOnce().finally(() => resolve12(result));
13655
14292
  };
13656
14293
  knipProcess.on("close", (code) => {
13657
14294
  if (code === 0) {
@@ -14078,7 +14715,7 @@ async function validateESLint(context, runner = defaultEslintProcessRunner, outp
14078
14715
  scope: scope2,
14079
14716
  scopeConfig: context.scopeConfig
14080
14717
  });
14081
- return new Promise((resolve11) => {
14718
+ return new Promise((resolve12) => {
14082
14719
  const localBin = join31(projectRoot, ...ESLINT_LOCAL_BIN_SEGMENTS);
14083
14720
  const binary = existsSync6(localBin) ? localBin : "npx";
14084
14721
  const spawnArgs = binary === "npx" ? eslintArgs : eslintArgs.slice(1);
@@ -14088,13 +14725,13 @@ async function validateESLint(context, runner = defaultEslintProcessRunner, outp
14088
14725
  forwardValidationSubprocessOutput(eslintProcess, outputStreams);
14089
14726
  eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
14090
14727
  if (code === 0) {
14091
- resolve11({ success: true });
14728
+ resolve12({ success: true });
14092
14729
  } else {
14093
- resolve11({ success: false, error: `ESLint exited with code ${code}` });
14730
+ resolve12({ success: false, error: `ESLint exited with code ${code}` });
14094
14731
  }
14095
14732
  });
14096
14733
  eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {
14097
- resolve11({ success: false, error: error.message });
14734
+ resolve12({ success: false, error: error.message });
14098
14735
  });
14099
14736
  });
14100
14737
  }
@@ -14192,8 +14829,8 @@ function formatLintResult(result, quiet, durationMs) {
14192
14829
  }
14193
14830
 
14194
14831
  // src/validation/literal/index.ts
14195
- import { readFile as readFile9 } from "fs/promises";
14196
- import { isAbsolute as isAbsolute7, relative as relative7, resolve as resolve9 } from "path";
14832
+ import { readFile as readFile10 } from "fs/promises";
14833
+ import { isAbsolute as isAbsolute7, relative as relative7, resolve as resolve10 } from "path";
14197
14834
 
14198
14835
  // src/lib/file-inclusion/predicates/ignore-source.ts
14199
14836
  var IGNORE_SOURCE_LAYER = "ignore-source";
@@ -14227,7 +14864,7 @@ var ignoreSourceLayer = makeLayer(
14227
14864
  );
14228
14865
 
14229
14866
  // src/lib/file-inclusion/pipeline.ts
14230
- import { readdir as readdir8 } from "fs/promises";
14867
+ import { readdir as readdir9 } from "fs/promises";
14231
14868
  import { join as join32, relative as relative6, sep as sep2 } from "path";
14232
14869
  var EXPLICIT_OVERRIDE_LAYER = "explicit-override";
14233
14870
  function isNodeError4(err) {
@@ -14236,7 +14873,7 @@ function isNodeError4(err) {
14236
14873
  async function collectPaths(absoluteDir, projectRoot, result, artifactDirs) {
14237
14874
  let dirEntries;
14238
14875
  try {
14239
- dirEntries = await readdir8(absoluteDir, { withFileTypes: true });
14876
+ dirEntries = await readdir9(absoluteDir, { withFileTypes: true });
14240
14877
  } catch (err) {
14241
14878
  if (isNodeError4(err) && (err.code === "ENOENT" || err.code === "ENOTDIR")) {
14242
14879
  return;
@@ -14733,37 +15370,22 @@ function isTestFile(relPath) {
14733
15370
  }
14734
15371
 
14735
15372
  // src/validation/literal/index.ts
14736
- var PATH_PREFIX_SEPARATOR2 = "/";
14737
15373
  var DEFAULT_LITERAL_COLLECT_OPTIONS = {
14738
15374
  visitorKeys: defaultVisitorKeys,
14739
15375
  minStringLength: literalConfigDescriptor.defaults.minStringLength,
14740
15376
  minNumberDigits: literalConfigDescriptor.defaults.minNumberDigits
14741
15377
  };
14742
- function normalizePathPrefix3(prefix) {
14743
- const posix = prefix.split(/[\\/]/g).join(PATH_PREFIX_SEPARATOR2);
14744
- return posix.endsWith(PATH_PREFIX_SEPARATOR2) ? posix : `${posix}${PATH_PREFIX_SEPARATOR2}`;
14745
- }
14746
15378
  function applyPathFilter2(entries, pathConfig) {
14747
15379
  if (pathConfig === void 0) {
14748
15380
  return entries;
14749
15381
  }
14750
- const includePrefixes = (pathConfig.include ?? []).map(normalizePathPrefix3);
14751
- const excludePrefixes = (pathConfig.exclude ?? []).map(normalizePathPrefix3);
14752
- return entries.filter((entry) => {
14753
- if (includePrefixes.length > 0 && !includePrefixes.some((p) => entry.path.startsWith(p))) {
14754
- return false;
14755
- }
14756
- if (excludePrefixes.some((p) => entry.path.startsWith(p))) {
14757
- return false;
14758
- }
14759
- return true;
14760
- });
15382
+ return entries.filter((entry) => pathPassesValidationFilter(entry.path, pathConfig));
14761
15383
  }
14762
15384
  async function validateLiteralReuse(input) {
14763
15385
  const config = input.config ?? literalConfigDescriptor.defaults;
14764
15386
  const request = input.scopeConfig === void 0 && input.files ? {
14765
15387
  explicit: input.files.map((f) => {
14766
- const abs = isAbsolute7(f) ? f : resolve9(input.productDir, f);
15388
+ const abs = isAbsolute7(f) ? f : resolve10(input.productDir, f);
14767
15389
  return relative7(input.productDir, abs).split(/[\\/]/g).join("/");
14768
15390
  })
14769
15391
  } : { walkRoot: input.productDir };
@@ -14777,7 +15399,7 @@ async function validateLiteralReuse(input) {
14777
15399
  const pathFiltered = applyPathFilter2(scope2.included, input.pathConfig);
14778
15400
  const literalScopeConfig = input.scopeConfig;
14779
15401
  const filtered = literalScopeConfig === void 0 ? pathFiltered : pathFiltered.filter((entry) => pathPassesTypeScriptScope(entry.path, literalScopeConfig));
14780
- const candidateFiles = filtered.filter((entry) => isTypescriptSource(entry.path)).map((entry) => resolve9(input.productDir, entry.path));
15402
+ const candidateFiles = filtered.filter((entry) => isTypescriptSource(entry.path)).map((entry) => resolve10(input.productDir, entry.path));
14781
15403
  const collectOptions = {
14782
15404
  visitorKeys: defaultVisitorKeys,
14783
15405
  minStringLength: config.minStringLength,
@@ -14812,7 +15434,7 @@ async function validateLiteralReuse(input) {
14812
15434
  }
14813
15435
  async function readSafe(path7) {
14814
15436
  try {
14815
- return await readFile9(path7, "utf8");
15437
+ return await readFile10(path7, "utf8");
14816
15438
  } catch (err) {
14817
15439
  if (typeof err === "object" && err !== null && "code" in err) {
14818
15440
  const code = err.code;
@@ -15175,7 +15797,7 @@ function resolveProjectTscInvocation(projectRoot, deps, tscArgs) {
15175
15797
  }
15176
15798
  function runTypeScriptInvocation(projectRoot, invocation, runner, outputStreams, cleanup = () => {
15177
15799
  }) {
15178
- return new Promise((resolve11) => {
15800
+ return new Promise((resolve12) => {
15179
15801
  const tscProcess = spawnManagedSubprocess(runner, invocation.tool, invocation.args, {
15180
15802
  cwd: projectRoot
15181
15803
  });
@@ -15183,14 +15805,14 @@ function runTypeScriptInvocation(projectRoot, invocation, runner, outputStreams,
15183
15805
  tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
15184
15806
  cleanup();
15185
15807
  if (code === 0) {
15186
- resolve11({ success: true, skipped: false });
15808
+ resolve12({ success: true, skipped: false });
15187
15809
  } else {
15188
- resolve11({ success: false, error: `TypeScript exited with code ${code}` });
15810
+ resolve12({ success: false, error: `TypeScript exited with code ${code}` });
15189
15811
  }
15190
15812
  });
15191
15813
  tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {
15192
15814
  cleanup();
15193
- resolve11({ success: false, error: error.message });
15815
+ resolve12({ success: false, error: error.message });
15194
15816
  });
15195
15817
  });
15196
15818
  }
@@ -15457,17 +16079,22 @@ async function allowlistExisting(options) {
15457
16079
  if (configRead.kind === "ambiguous") {
15458
16080
  return { exitCode: EXIT_ERROR, output: formatConfigFileAmbiguityError(configRead.detected) };
15459
16081
  }
15460
- const currentLiteralConfig = readCurrentLiteralConfig(configRead);
15461
- if (!currentLiteralConfig.ok) {
15462
- return { exitCode: EXIT_ERROR, output: currentLiteralConfig.error };
16082
+ const resolvedConfig = resolveConfigFromReadResult(configRead, [validationConfigDescriptor]);
16083
+ if (!resolvedConfig.ok) {
16084
+ return { exitCode: EXIT_ERROR, output: resolvedConfig.error };
15463
16085
  }
16086
+ const validationConfig = resolvedConfig.value[validationConfigDescriptor.section];
15464
16087
  const detection = await validateLiteralReuse({
15465
16088
  productDir: options.productDir,
15466
- config: currentLiteralConfig.value
16089
+ config: validationConfig.literal.values,
16090
+ pathConfig: validationPathFilterForTool(
16091
+ validationConfig.paths,
16092
+ VALIDATION_PATH_TOOL_SUBSECTIONS.LITERAL
16093
+ )
15467
16094
  });
15468
16095
  const findingValues = collectFindingValues(detection.findings);
15469
16096
  const updatedInclude = computeUpdatedInclude(
15470
- currentLiteralConfig.value.include,
16097
+ validationConfig.literal.values.include,
15471
16098
  findingValues
15472
16099
  );
15473
16100
  const target = configRead.kind === "ok" ? configRead.file : configFileForFormat(options.productDir, DEFAULT_CONFIG_FILE_FORMAT);
@@ -15478,25 +16105,6 @@ async function allowlistExisting(options) {
15478
16105
  await writer.write(target.path, serialized.value);
15479
16106
  return { exitCode: EXIT_OK, output: "" };
15480
16107
  }
15481
- function readCurrentLiteralConfig(read) {
15482
- if (read.kind !== "ok") return { ok: true, value: literalConfigDescriptor.defaults };
15483
- const sections = parseConfigFileSections(read.file);
15484
- if (!sections.ok) return sections;
15485
- const validationRaw = sections.value[VALIDATION_SECTION];
15486
- if (typeof validationRaw !== "object" || validationRaw === null) {
15487
- return { ok: true, value: literalConfigDescriptor.defaults };
15488
- }
15489
- const literalRaw = validationRaw[VALIDATION_LITERAL_SUBSECTION];
15490
- if (typeof literalRaw !== "object" || literalRaw === null) {
15491
- return { ok: true, value: literalConfigDescriptor.defaults };
15492
- }
15493
- const valuesRaw = literalRaw[VALIDATION_LITERAL_VALUES_SUBSECTION];
15494
- if (valuesRaw === void 0) {
15495
- return { ok: true, value: literalConfigDescriptor.defaults };
15496
- }
15497
- const validated = literalConfigDescriptor.validate(valuesRaw);
15498
- return validated.ok ? validated : { ok: true, value: literalConfigDescriptor.defaults };
15499
- }
15500
16108
  function collectFindingValues(findings) {
15501
16109
  const values = /* @__PURE__ */ new Set();
15502
16110
  for (const finding of findings.srcReuse) values.add(finding.value);
@@ -15637,9 +16245,9 @@ function addCommonOptions(cmd) {
15637
16245
  return cmd.argument(pathOperands.optionalVariadic, pathOperands.description).option("--scope <scope>", "Validation scope (full|production)", "full").option("--quiet", "Suppress progress output").option("--json", "Output results as JSON");
15638
16246
  }
15639
16247
  function normalizeProductPathOperand(productDir, effectiveInvocationDir, operand) {
15640
- const resolvedProductDir = canonicalExistingPath(resolve10(productDir));
15641
- const resolvedInvocationDir = canonicalExistingPath(resolve10(effectiveInvocationDir));
15642
- const absoluteOperand = canonicalExistingPath(resolve10(resolvedInvocationDir, operand));
16248
+ const resolvedProductDir = canonicalExistingPath(resolve11(productDir));
16249
+ const resolvedInvocationDir = canonicalExistingPath(resolve11(effectiveInvocationDir));
16250
+ const absoluteOperand = canonicalExistingPath(resolve11(resolvedInvocationDir, operand));
15643
16251
  const relativeOperand = relative9(resolvedProductDir, absoluteOperand);
15644
16252
  if (relativeOperand === ".." || relativeOperand.startsWith(`..${sep3}`) || isAbsolute9(relativeOperand)) {
15645
16253
  return void 0;
@@ -16169,11 +16777,11 @@ function renderTextStatus(record6) {
16169
16777
  }
16170
16778
 
16171
16779
  // src/lib/worktree-path-info.ts
16172
- import { stat as stat5 } from "fs/promises";
16780
+ import { stat as stat6 } from "fs/promises";
16173
16781
  var defaultWorktreePathInfo = {
16174
16782
  isExistingNonDirectory: async (path7) => {
16175
16783
  try {
16176
- const pathStats = await stat5(path7);
16784
+ const pathStats = await stat6(path7);
16177
16785
  return !pathStats.isDirectory();
16178
16786
  } catch {
16179
16787
  return false;
@@ -16194,21 +16802,21 @@ var WORKTREE_CLI = {
16194
16802
  WORKTREES_DIR_FLAG: "--worktrees-dir"
16195
16803
  };
16196
16804
  var WORKTREE_DOMAIN_DESCRIPTION = "Coordinate worktree occupancy across a bare-repository pool";
16197
- function writeOutput4(invocation, output) {
16805
+ function writeOutput5(invocation, output) {
16198
16806
  invocation.io.writeStdout(`${output}
16199
16807
  `);
16200
16808
  }
16201
- function writeError4(invocation, output) {
16809
+ function writeError5(invocation, output) {
16202
16810
  invocation.io.writeStderr(`${output}
16203
16811
  `);
16204
16812
  }
16205
16813
  function writeInvocationWarning4(invocation, warning) {
16206
16814
  if (warning !== void 0) {
16207
- writeError4(invocation, warning);
16815
+ writeError5(invocation, warning);
16208
16816
  }
16209
16817
  }
16210
- function handleError3(invocation, error) {
16211
- writeError4(invocation, `Error: ${error}`);
16818
+ function handleError4(invocation, error) {
16819
+ writeError5(invocation, `Error: ${error}`);
16212
16820
  return invocation.io.exit(1);
16213
16821
  }
16214
16822
  function registerWorktreeCommands(worktreeCmd, invocation) {
@@ -16226,7 +16834,7 @@ function registerWorktreeCommands(worktreeCmd, invocation) {
16226
16834
  worktreesDir: options.worktreesDir,
16227
16835
  onWarning: (warning) => writeInvocationWarning4(invocation, warning)
16228
16836
  });
16229
- if (!result.ok) handleError3(invocation, result.error);
16837
+ if (!result.ok) handleError4(invocation, result.error);
16230
16838
  });
16231
16839
  worktreeCmd.command(`${WORKTREE_CLI.STATUS} ${WORKTREE_CLI.WORKTREE_ARGUMENT}`).description("Report a worktree's occupancy (running | free)").option(WORKTREE_CLI.ALL_FLAG, "Report every git-observed worktree").option(`${WORKTREE_CLI.FORMAT_FLAG} <format>`, "Output format (text|json)", WORKTREE_STATUS_FORMAT.TEXT).option(`${WORKTREE_CLI.WORKTREES_DIR_FLAG} <path>`, "Explicit .spx/worktrees directory").action(
16232
16840
  async (worktrees, options) => {
@@ -16242,8 +16850,8 @@ function registerWorktreeCommands(worktreeCmd, invocation) {
16242
16850
  worktreesDir: options.worktreesDir,
16243
16851
  onWarning: (warning) => writeInvocationWarning4(invocation, warning)
16244
16852
  });
16245
- if (!result.ok) handleError3(invocation, result.error);
16246
- writeOutput4(invocation, result.value);
16853
+ if (!result.ok) handleError4(invocation, result.error);
16854
+ writeOutput5(invocation, result.value);
16247
16855
  }
16248
16856
  );
16249
16857
  worktreeCmd.command(WORKTREE_CLI.RELEASE).description("Release the running worktree's occupancy claim").option(`${WORKTREE_CLI.WORKTREES_DIR_FLAG} <path>`, "Explicit .spx/worktrees directory").action(async (options) => {
@@ -16254,7 +16862,7 @@ function registerWorktreeCommands(worktreeCmd, invocation) {
16254
16862
  worktreesDir: options.worktreesDir,
16255
16863
  onWarning: (warning) => writeInvocationWarning4(invocation, warning)
16256
16864
  });
16257
- if (!result.ok) handleError3(invocation, result.error);
16865
+ if (!result.ok) handleError4(invocation, result.error);
16258
16866
  });
16259
16867
  }
16260
16868
  var worktreeDomain = {
@@ -16268,6 +16876,7 @@ var worktreeDomain = {
16268
16876
 
16269
16877
  // src/interfaces/cli/registry.ts
16270
16878
  var CLI_DOMAINS = [
16879
+ agentDomain,
16271
16880
  claudeDomain,
16272
16881
  compactDomain,
16273
16882
  configDomain,