@outerlayer/cli 0.10.0 → 0.10.1

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 (47) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/build-info.json +1 -1
  3. package/dist/{builder-5DKTBWT3.js → builder-EVO6F2NO.js} +2 -2
  4. package/dist/{check-VJRJ2KQ4.js → check-RBRRI77E.js} +15 -15
  5. package/dist/{chunk-QPPPUKQJ.js → chunk-472KC6JV.js} +1 -1
  6. package/dist/{chunk-YCPV7FN6.js → chunk-4AVAETSU.js} +8 -8
  7. package/dist/{chunk-LBU4CLK5.js → chunk-BREEX2Z7.js} +4 -4
  8. package/dist/{chunk-KWCJLAHQ.js → chunk-DTDZXDQ3.js} +3 -3
  9. package/dist/{chunk-XGCJNSI7.js → chunk-ESZJ5QIC.js} +4 -4
  10. package/dist/{chunk-VMK7I3TB.js → chunk-HKUH5AR2.js} +2 -2
  11. package/dist/{chunk-5K3IUOPJ.js → chunk-I263FZ3A.js} +2 -2
  12. package/dist/{chunk-LTJPX7TX.js → chunk-IU4NZROR.js} +249 -18
  13. package/dist/{chunk-TV36SKEN.js → chunk-JSUUXA5W.js} +1 -1
  14. package/dist/{chunk-OSKO3PAL.js → chunk-KZ5M4QOB.js} +7 -7
  15. package/dist/{chunk-WJBJY5DQ.js → chunk-MC6J453K.js} +2 -2
  16. package/dist/{chunk-XZNO4QED.js → chunk-R2UYH4QV.js} +5 -5
  17. package/dist/{chunk-LYESSQUA.js → chunk-UES67HLJ.js} +2 -2
  18. package/dist/{chunk-ZEQMTBRD.js → chunk-VDI5POCC.js} +80 -2
  19. package/dist/{chunk-FKFGQJNN.js → chunk-VVIRHTH4.js} +1 -1
  20. package/dist/{chunk-543OT6V5.js → chunk-Y6P5XX2B.js} +25 -7
  21. package/dist/{chunk-KPUJGBA4.js → chunk-ZQ5JGHUO.js} +2 -2
  22. package/dist/{cli-77URFYI7.js → cli-G6TH4YMK.js} +47 -47
  23. package/dist/{command-2LYWVGIK.js → command-LNEFKIVC.js} +9 -9
  24. package/dist/{connect-cmd-MPZWSEKY.js → connect-cmd-5MIUNYAY.js} +3 -3
  25. package/dist/{dist-QY5CL5LB.js → dist-3M3ZMEZF.js} +1 -1
  26. package/dist/{docker-V7B6UKPF.js → docker-GM526LGX.js} +3 -3
  27. package/dist/{doctor-PUAL5LTL.js → doctor-QSV4DYT2.js} +11 -11
  28. package/dist/{emit-artifact-cmd-P3IWNSQY.js → emit-artifact-cmd-VKPW577P.js} +5 -5
  29. package/dist/{emit-criteria-cmd-GOSP6X74.js → emit-criteria-cmd-U2TL6FYY.js} +4 -4
  30. package/dist/{emit-finding-cmd-D554IQKU.js → emit-finding-cmd-TMOOKHPD.js} +4 -4
  31. package/dist/{emit-result-cmd-QACXTIBV.js → emit-result-cmd-GKBVPMU4.js} +5 -5
  32. package/dist/index.js +1 -1
  33. package/dist/{init-TMBE3BRN.js → init-OKCDXEOG.js} +10 -10
  34. package/dist/{init-WX5XE6L3.js → init-ORDCPTFD.js} +10 -10
  35. package/dist/{init-cmd-4FQKQLJ5.js → init-cmd-5TEM2QNH.js} +6 -6
  36. package/dist/{loop-QLL4DKRF.js → loop-ZNUQT736.js} +15 -15
  37. package/dist/{machine-7T7FBSUL.js → machine-TBJKZ6TN.js} +9 -9
  38. package/dist/{session-sender-HVWTYG35.js → session-sender-E3UHGSNV.js} +4 -4
  39. package/dist/{status-SMF5JG2K.js → status-KPDVZMJ6.js} +11 -11
  40. package/dist/{sync-cmd-SLMPCUXO.js → sync-cmd-ULKXCHO2.js} +3 -3
  41. package/dist/{watch-TLM5QN5X.js → watch-IU6NHB4K.js} +3 -3
  42. package/dist/{work-claim-cmd-VSSZDFY5.js → work-claim-cmd-DYD6II56.js} +6 -6
  43. package/dist/{work-cmd-TK4VOOHL.js → work-cmd-ZJY3NA2G.js} +5 -5
  44. package/dist/{work-comment-cmd-VQCG72ZQ.js → work-comment-cmd-34FTLPUO.js} +5 -5
  45. package/dist/{work-open-pr-cmd-YESMWATB.js → work-open-pr-cmd-N2RBDKZ4.js} +6 -6
  46. package/dist/{work-pr-cmd-6TMSCO3Q.js → work-pr-cmd-EXTOGBJC.js} +5 -5
  47. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { readStatuslineState, STATE_FRESH_MS } from './chunk-F47JBIAW.js';
4
- import { resolveCredentials, getJson, WorkCommandError } from './chunk-KWCJLAHQ.js';
5
- import { isLinkedRepository } from './chunk-LYESSQUA.js';
6
- import { sanitizeTerminal } from './chunk-ZEQMTBRD.js';
7
- import { resolveRepoIdentity, compareVersions, SUPPORTED_VERSIONS } from './chunk-LTJPX7TX.js';
4
+ import { resolveCredentials, getJson, WorkCommandError } from './chunk-DTDZXDQ3.js';
5
+ import { isLinkedRepository } from './chunk-UES67HLJ.js';
6
+ import { sanitizeTerminal } from './chunk-VDI5POCC.js';
7
+ import { resolveRepoIdentity, compareVersions, SUPPORTED_VERSIONS } from './chunk-IU4NZROR.js';
8
8
  import { C } from './chunk-YRYMNBGQ.js';
9
9
  import { readSettings, settingsPath, isOurStatuslineSlot, statuslineWrappedOriginal, REGISTERED_EVENTS, isOurHookCommand, ourCommandBins, cliBinResolvable, ourDirectScriptBins, wrappedOriginalCommand } from './chunk-5QRP3MVS.js';
10
10
  import { readPin, readContextManifest, readDegraded, readSourceCache } from './chunk-BMX3L7CR.js';
@@ -1016,7 +1016,7 @@ async function gatherDoctorChecks() {
1016
1016
  const { runnerVmCheck } = await import('./doctor-53F2PYY7.js');
1017
1017
  checks.push(runnerVmCheck(configPath, { lima: realLima(), home: homeFromEnv(), instance: runnerVm.instance }));
1018
1018
  } else if (hasRunnerBlock(configPath)) {
1019
- const { runnerHostChecks } = await import('./doctor-PUAL5LTL.js');
1019
+ const { runnerHostChecks } = await import('./doctor-QSV4DYT2.js');
1020
1020
  const hooks = (() => {
1021
1021
  try {
1022
1022
  return loadRunnerConfig(configPath).hooks;
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { sanitizeTerminal } from './chunk-ZEQMTBRD.js';
4
- import { remoteLookupFailed } from './chunk-LTJPX7TX.js';
3
+ import { sanitizeTerminal } from './chunk-VDI5POCC.js';
4
+ import { remoteLookupFailed } from './chunk-IU4NZROR.js';
5
5
  import { DEFAULT_DASHBOARD } from './chunk-USO2DKBD.js';
6
6
  import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
7
7
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { ArtifactTombstoneRecordSchema, ArtifactSpoolRecordSchema } from './chunk-YT35WGIP.js';
4
4
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
- import { mkdirSync, appendFileSync, writeFileSync, renameSync, existsSync, unlinkSync, readdirSync, readFileSync } from 'fs';
5
+ import { mkdirSync, appendFileSync, writeFileSync, renameSync, unlinkSync, existsSync, readdirSync, readFileSync, statSync } from 'fs';
6
6
  import { join, dirname } from 'path';
7
7
 
8
8
  createRequire(import.meta.url);
@@ -15,6 +15,9 @@ function artifactBlobsDir(home = homeFromEnv()) {
15
15
  function artifactsStatePath(home = homeFromEnv()) {
16
16
  return join(home, ".outerlayer", "spool", "artifacts.state.json");
17
17
  }
18
+ function artifactsLockPath(home = homeFromEnv()) {
19
+ return join(home, ".outerlayer", "spool", "artifacts.lock");
20
+ }
18
21
  var ARTIFACT_RETRY_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
19
22
  function appendArtifactRecord(record, home = homeFromEnv()) {
20
23
  const path = artifactsSpoolPath(home);
@@ -239,6 +242,81 @@ function writeArtifactSpoolState(state, home = homeFromEnv()) {
239
242
  return false;
240
243
  }
241
244
  }
245
+ var ARTIFACT_LOCK_STALE_MS = 30 * 60 * 1e3;
246
+ var ARTIFACT_LOCK_WAIT_MS = 2 * 60 * 1e3;
247
+ var ARTIFACT_LOCK_POLL_MS = 250;
248
+ function processIsAlive(pid) {
249
+ try {
250
+ process.kill(pid, 0);
251
+ return true;
252
+ } catch (err) {
253
+ return err.code === "EPERM";
254
+ }
255
+ }
256
+ function artifactLockIsStale(path, nowMs, isAlive) {
257
+ let raw;
258
+ let mtimeMs;
259
+ try {
260
+ raw = readFileSync(path, "utf8");
261
+ mtimeMs = statSync(path).mtimeMs;
262
+ } catch {
263
+ return false;
264
+ }
265
+ if (nowMs - mtimeMs > ARTIFACT_LOCK_STALE_MS) return true;
266
+ try {
267
+ const pid = JSON.parse(raw).pid;
268
+ return typeof pid === "number" && !isAlive(pid);
269
+ } catch {
270
+ return false;
271
+ }
272
+ }
273
+ async function acquireArtifactSpoolLock(home = homeFromEnv(), opts = {}) {
274
+ const path = artifactsLockPath(home);
275
+ const waitMs = opts.waitMs ?? ARTIFACT_LOCK_WAIT_MS;
276
+ const sleep = opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
277
+ const isAlive = opts.isAlive ?? processIsAlive;
278
+ const now = opts.now ?? Date.now;
279
+ const deadline = now() + waitMs;
280
+ try {
281
+ mkdirSync(dirname(path), { recursive: true });
282
+ } catch (err) {
283
+ return { ok: false, reason: `cannot create ${dirname(path)}: ${String(err)}` };
284
+ }
285
+ for (; ; ) {
286
+ try {
287
+ writeFileSync(path, JSON.stringify({ pid: process.pid, t: (/* @__PURE__ */ new Date()).toISOString() }), { flag: "wx" });
288
+ let released = false;
289
+ return {
290
+ ok: true,
291
+ // Once only: a second unlink could remove a lock another sync has
292
+ // taken since.
293
+ release: () => {
294
+ if (released) return;
295
+ released = true;
296
+ try {
297
+ unlinkSync(path);
298
+ } catch {
299
+ }
300
+ }
301
+ };
302
+ } catch (err) {
303
+ if (err.code !== "EEXIST") {
304
+ return { ok: false, reason: `cannot create ${path}: ${String(err)}` };
305
+ }
306
+ }
307
+ if (artifactLockIsStale(path, now(), isAlive)) {
308
+ try {
309
+ unlinkSync(path);
310
+ } catch {
311
+ }
312
+ continue;
313
+ }
314
+ if (now() >= deadline) {
315
+ return { ok: false, reason: `another outerlayer sync has held ${path} for longer than ${Math.round(waitMs / 1e3)}s` };
316
+ }
317
+ await sleep(ARTIFACT_LOCK_POLL_MS);
318
+ }
319
+ }
242
320
  function migrateLegacyArtifactSidecars(home = homeFromEnv()) {
243
321
  if (existsSync(artifactsStatePath(home))) return;
244
322
  const paths = legacySidecarPaths(home);
@@ -380,4 +458,4 @@ function resolveArtifactTurnIndex(turns, filename) {
380
458
  return found;
381
459
  }
382
460
 
383
- export { ARTIFACT_RETRY_MAX_AGE_MS, appendArtifactRecord, appendArtifactTombstone, artifactBlobsDir, artifactsSpoolPath, artifactsStatePath, findPendingArtifactRecord, isArtifactTombstoned, localArtifactIds, migrateLegacyArtifactSidecars, neededArtifactShas, planArtifactUpload, readEffectiveArtifactSpoolState, reclaimUnneededArtifactBlobs, resolveArtifactTurnIndex, sanitizeTerminal, writeArtifactSpoolState };
461
+ export { ARTIFACT_RETRY_MAX_AGE_MS, acquireArtifactSpoolLock, appendArtifactRecord, appendArtifactTombstone, artifactBlobsDir, artifactsSpoolPath, artifactsStatePath, findPendingArtifactRecord, isArtifactTombstoned, localArtifactIds, migrateLegacyArtifactSidecars, neededArtifactShas, planArtifactUpload, readEffectiveArtifactSpoolState, reclaimUnneededArtifactBlobs, resolveArtifactTurnIndex, sanitizeTerminal, writeArtifactSpoolState };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { RecipeError } from './chunk-QOZKPLVJ.js';
4
- import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-TV36SKEN.js';
4
+ import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-JSUUXA5W.js';
5
5
  import { spawn } from 'child_process';
6
6
  import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync } from 'fs';
7
7
  import { join, dirname } from 'path';
@@ -4,8 +4,8 @@ import { LaunchFilter } from './chunk-HHJDN6AU.js';
4
4
  import { RepoFilter } from './chunk-TBT347UY.js';
5
5
  import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
6
6
  import { applyReportedCost } from './chunk-BKO6JEZI.js';
7
- import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-ZEQMTBRD.js';
8
- import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-LTJPX7TX.js';
7
+ import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-VDI5POCC.js';
8
+ import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-IU4NZROR.js';
9
9
  import { C } from './chunk-YRYMNBGQ.js';
10
10
  import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-GQD22KKN.js';
11
11
  import { readLatestProvenanceForSession, readContextProvenance } from './chunk-ZJSNLVCE.js';
@@ -1553,20 +1553,34 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1553
1553
  }
1554
1554
  let artifactsUploaded;
1555
1555
  let artifactsHeld;
1556
- if (combinedRecords.length > 0 || artifactPlan.held.length > 0) {
1556
+ const artifactLock = combinedRecords.length > 0 || artifactPlan.held.length > 0 ? await acquireArtifactSpoolLock(home, { waitMs: opts.artifactLockWaitMs }) : void 0;
1557
+ if (artifactLock !== void 0 && !artifactLock.ok) {
1558
+ artifactsUploaded = 0;
1559
+ artifactsHeld = combinedRecords.length + artifactPlan.held.length;
1560
+ if (!opts.quiet) {
1561
+ process.stderr.write(
1562
+ `${C.yellow}!${C.reset} artifacts not attempted: ${artifactLock.reason} \u2014 ${artifactsHeld} record(s) stay queued for the next sync
1563
+ `
1564
+ );
1565
+ }
1566
+ }
1567
+ const releaseArtifactLock = artifactLock?.ok === true ? artifactLock.release : () => {
1568
+ };
1569
+ const livePlan = artifactLock?.ok === true ? planArtifactUpload({ home }) : void 0;
1570
+ if (livePlan !== void 0) {
1557
1571
  const artifactEndpoint = new URL("/v1/artifacts", url).toString();
1558
1572
  const nowMs = Date.now();
1559
- const state = artifactPlan.state;
1573
+ const state = livePlan.state;
1560
1574
  const failedOrDroppedThisRun = /* @__PURE__ */ new Set();
1561
1575
  let uploadedCount = 0;
1562
- let heldCount = artifactPlan.held.length;
1576
+ let heldCount = livePlan.held.length;
1563
1577
  let droppedCount = 0;
1564
1578
  const warn = (message) => {
1565
1579
  if (!opts.quiet) process.stderr.write(`${C.yellow}!${C.reset} ${message}
1566
1580
  `);
1567
1581
  };
1568
1582
  let unauthorized;
1569
- for (const { record } of combinedRecords) {
1583
+ for (const { record } of livePlan.candidates) {
1570
1584
  const name = sanitizeTerminal(record.filename);
1571
1585
  const holdReason = artifactHoldReason(record.sessionId);
1572
1586
  if (holdReason !== void 0) {
@@ -1597,7 +1611,9 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1597
1611
  reachedServer: true
1598
1612
  });
1599
1613
  failedOrDroppedThisRun.add(record.artifactId);
1600
- warn(`artifact ${name}: blob missing from the spool \u2014 dropping the record`);
1614
+ warn(
1615
+ `artifact ${name} (${record.artifactId}): blob missing from the spool \u2014 ${join(artifactBlobsDir(home), record.sha256)} does not exist; dropping the record`
1616
+ );
1601
1617
  droppedCount += 1;
1602
1618
  continue;
1603
1619
  }
@@ -1738,11 +1754,13 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1738
1754
  );
1739
1755
  }
1740
1756
  reclaimUnneededArtifactBlobs(home, neededArtifactShas(home, state));
1757
+ releaseArtifactLock();
1741
1758
  if (unauthorized) {
1742
1759
  failureContext();
1743
1760
  throw unauthorized;
1744
1761
  }
1745
1762
  }
1763
+ releaseArtifactLock();
1746
1764
  if (shippedBatches === batches.length && (opts.url || opts.apiKey || opts.appId)) {
1747
1765
  if (isLoopbackUrl(url)) {
1748
1766
  if (!opts.quiet) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-LYESSQUA.js';
4
- import { resolveRepoIdentity } from './chunk-LTJPX7TX.js';
3
+ import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-UES67HLJ.js';
4
+ import { resolveRepoIdentity } from './chunk-IU4NZROR.js';
5
5
  import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
6
6
  import { findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
7
7
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-XZNO4QED.js';
3
+ import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-R2UYH4QV.js';
4
4
  import './chunk-F47JBIAW.js';
5
5
  import './chunk-BKO6JEZI.js';
6
- import './chunk-KWCJLAHQ.js';
7
- import './chunk-KPUJGBA4.js';
6
+ import './chunk-DTDZXDQ3.js';
7
+ import './chunk-ZQ5JGHUO.js';
8
8
  import './chunk-BFESLKPP.js';
9
- import './chunk-LYESSQUA.js';
10
- import './chunk-ZEQMTBRD.js';
11
- import './chunk-LTJPX7TX.js';
9
+ import './chunk-UES67HLJ.js';
10
+ import './chunk-VDI5POCC.js';
11
+ import './chunk-IU4NZROR.js';
12
12
  import './chunk-USO2DKBD.js';
13
13
  import './chunk-N6LURUEF.js';
14
14
  import { C, NO_COLOR_FLAG, warnDeprecated, stripNoColor, API_KEY_FLAG_DEPRECATION } from './chunk-YRYMNBGQ.js';
@@ -3801,8 +3801,8 @@ ${starter.output}`),
3801
3801
  }
3802
3802
  }
3803
3803
  async function realConnectDepsForCwd() {
3804
- const { realConnectDeps } = await import('./connect-cmd-MPZWSEKY.js');
3805
- const { resolveRepoIdentity } = await import('./dist-QY5CL5LB.js');
3804
+ const { realConnectDeps } = await import('./connect-cmd-5MIUNYAY.js');
3805
+ const { resolveRepoIdentity } = await import('./dist-3M3ZMEZF.js');
3806
3806
  return {
3807
3807
  ...realConnectDeps(),
3808
3808
  home: homeFromEnv(),
@@ -3855,7 +3855,7 @@ function buildProgram(argv = process.argv) {
3855
3855
  else process.stdout.write(outcome.text);
3856
3856
  return;
3857
3857
  }
3858
- const { runInitCommand } = await import('./init-cmd-4FQKQLJ5.js');
3858
+ const { runInitCommand } = await import('./init-cmd-5TEM2QNH.js');
3859
3859
  const code = await runInitCommand(
3860
3860
  { json: opts.json, factory: opts.factory },
3861
3861
  {
@@ -3879,7 +3879,7 @@ function buildProgram(argv = process.argv) {
3879
3879
  "after",
3880
3880
  "\nRun it in a repository, after `outerlayer login`. With a login, connect lists\nthe factories you can use and takes the first rule that leaves one answer:\n 1. --factory <org>/<factory>, or a factory id\n 2. the factory this repository is already connected to\n 3. the one factory this repository is linked to\n 4. the one factory you can use\n 5. on a terminal, ask; with no terminal, exit 1 and list each --factory value\n\nIt says what it chose and why. The choice is saved in this repository's git\ndirectory (outerlayer/connection.json), shared by every worktree of the\nclone and never committed. A factory key already belongs to one factory, so\nconnect changes nothing for it. Connect never links a repository.\n\nAfter it saves the choice, connect checks that this repository is linked to\nthe factory. If it is not, connect says so, prints the factory's Work page\nlink where you link it, and exits 2. The choice is saved either way. Run\nconnect again once the repository is linked. With --json, the document has\nlinked (true, false, or null when it could not be checked) and, when false,\nlinkUrl.\n"
3881
3881
  ).action(async (opts) => {
3882
- const { runConnectCommand } = await import('./connect-cmd-MPZWSEKY.js');
3882
+ const { runConnectCommand } = await import('./connect-cmd-5MIUNYAY.js');
3883
3883
  const code = await runConnectCommand({ factory: opts.factory, json: opts.json }, await realConnectDepsForCwd(), {
3884
3884
  stdout: process.stdout,
3885
3885
  stderr: process.stderr
@@ -3927,7 +3927,7 @@ function buildProgram(argv = process.argv) {
3927
3927
  "\nIncremental: only sessions newer than the last checkpoint ship. The tier\nis applied on this machine before anything leaves it; `--dry-run` prints\nexactly what would. The hook-triggered background sync runs `--quiet`.\nExit 2 means the server rejected at least one session.\n"
3928
3928
  ).action(async (opts) => {
3929
3929
  warnIfApiKeyFlag(opts);
3930
- const { runSync, SyncConfigError, SyncTransportError } = await import('./sync-cmd-SLMPCUXO.js');
3930
+ const { runSync, SyncConfigError, SyncTransportError } = await import('./sync-cmd-ULKXCHO2.js');
3931
3931
  try {
3932
3932
  const result = await runSync({
3933
3933
  url: opts.url,
@@ -3956,7 +3956,7 @@ function buildProgram(argv = process.argv) {
3956
3956
  if (invokedCommandToken(argv) === "watch") {
3957
3957
  warnDeprecated("`outerlayer watch` is now `outerlayer daemon`; the old name will be removed in a future release.");
3958
3958
  }
3959
- const { runWatch } = await import('./watch-TLM5QN5X.js');
3959
+ const { runWatch } = await import('./watch-IU6NHB4K.js');
3960
3960
  await runWatch({ once: opts.once });
3961
3961
  });
3962
3962
  program2.command("hook <event>", { hidden: true }).description("capture-hook fast path, installed by `init`").action(() => {
@@ -4010,7 +4010,7 @@ function buildProgram(argv = process.argv) {
4010
4010
  }
4011
4011
  });
4012
4012
  program2.command("session-sender", { hidden: true }).description("stream a runner build's sessions to its work item while the build runs").action(async () => {
4013
- const { runSessionSender } = await import('./session-sender-HVWTYG35.js');
4013
+ const { runSessionSender } = await import('./session-sender-E3UHGSNV.js');
4014
4014
  try {
4015
4015
  await runSessionSender();
4016
4016
  } catch (err) {
@@ -4068,7 +4068,7 @@ function registerEmitCommands(program2) {
4068
4068
  return;
4069
4069
  }
4070
4070
  warnIfApiKeyFlag(opts);
4071
- const { runEmitResult, EmitResultError } = await import('./emit-result-cmd-QACXTIBV.js');
4071
+ const { runEmitResult, EmitResultError } = await import('./emit-result-cmd-GKBVPMU4.js');
4072
4072
  try {
4073
4073
  const result = await runEmitResult({
4074
4074
  name,
@@ -4119,7 +4119,7 @@ locally so it never uploads. One correction can retire several duplicates.
4119
4119
  `
4120
4120
  ).action(async (file, opts) => {
4121
4121
  warnIfApiKeyFlag(opts);
4122
- const { runEmitArtifact, EmitArtifactError } = await import('./emit-artifact-cmd-P3IWNSQY.js');
4122
+ const { runEmitArtifact, EmitArtifactError } = await import('./emit-artifact-cmd-VKPW577P.js');
4123
4123
  let pr;
4124
4124
  if (opts.pr !== void 0) {
4125
4125
  pr = parseTrackerNumber(opts.pr);
@@ -4154,7 +4154,7 @@ locally so it never uploads. One correction can retire several duplicates.
4154
4154
  '\n outerlayer emit finding --id gate-skip --category tooling \\\n --title "The pre-push gate prints green when a step was skipped" \\\n --file scripts/git/pre-push-checks.mjs --where "build session"\n\nRecords one problem you hit in the factory: an instruction that is wrong or\nmissing (context), a flaky test, a misbehaving script (tooling), a local\nsetup trap (environment), a bug outside your own change (defect), or\nanything else. A problem in your own change is fixed, not recorded.\nA context finding needs --rule-path and --rule-relation, and --rule-quote\nunless the relation is missing.\n--item names the work item; without it, inside a recorded session, the\nitem that session was launched for is used automatically.\n'
4155
4155
  ).action(async (opts) => {
4156
4156
  warnIfApiKeyFlag(opts);
4157
- const { runEmitFinding, refuseRemovedFindingFlags, EmitFindingError } = await import('./emit-finding-cmd-D554IQKU.js');
4157
+ const { runEmitFinding, refuseRemovedFindingFlags, EmitFindingError } = await import('./emit-finding-cmd-TMOOKHPD.js');
4158
4158
  try {
4159
4159
  refuseRemovedFindingFlags(opts);
4160
4160
  const result = await runEmitFinding({
@@ -4193,7 +4193,7 @@ locally so it never uploads. One correction can retire several duplicates.
4193
4193
  "\n outerlayer emit findings review.json --item 412\n\nRecords a whole batch at once \u2014 a FindingBatch JSON file (schemaVersion,\noptional headSha / contextSourceSha, and 1-500 findings), validated against\nthe same contract `emit finding` uses before anything is sent. Re-emitting\nan id already on the item replaces that row rather than adding a second one.\n--item names the work item; without it, inside a recorded session, the item\nthat session was launched for is used automatically.\n"
4194
4194
  ).action(async (file, opts) => {
4195
4195
  warnIfApiKeyFlag(opts);
4196
- const { runEmitFindings, EmitFindingError } = await import('./emit-finding-cmd-D554IQKU.js');
4196
+ const { runEmitFindings, EmitFindingError } = await import('./emit-finding-cmd-TMOOKHPD.js');
4197
4197
  try {
4198
4198
  const result = await runEmitFindings({
4199
4199
  file,
@@ -4217,7 +4217,7 @@ locally so it never uploads. One correction can retire several duplicates.
4217
4217
  '\n outerlayer emit criteria criteria.json --item 412\n\nRecords the item\'s acceptance criteria as one list. The file is JSON:\n { "criteria": [ { "id": "AC-1", "text": "Given ...", "proof": null },\n { "id": "login.redirect", "text": "...", "proof": "screenshot" } ] }\nAn id is 1-64 characters of A-Z a-z 0-9 . _ : - and is the id evidence is bound to with\n`emit artifact --for`. proof is video, screenshot, report, log, test, file or null (any bound\nartifact proves it). The list holds 1 to 200 criteria, each text at most 2,000\ncharacters, and no id twice. The list is validated before anything is sent.\nOnce an item has a list, only a person can replace it: run the command outside an\nagent session, with your own login. A key bound to no member cannot replace it either.\n--item names the work item; without it, inside a recorded session, the item that\nsession was launched for is used automatically.\n'
4218
4218
  ).action(async (file, opts) => {
4219
4219
  warnIfApiKeyFlag(opts);
4220
- const { runEmitCriteria, EmitCriteriaError } = await import('./emit-criteria-cmd-GOSP6X74.js');
4220
+ const { runEmitCriteria, EmitCriteriaError } = await import('./emit-criteria-cmd-U2TL6FYY.js');
4221
4221
  try {
4222
4222
  const result = await runEmitCriteria({
4223
4223
  file,
@@ -4244,7 +4244,7 @@ function registerWorkCommands(program2) {
4244
4244
  "\n outerlayer work build --issue 42 # a host builds it\n outerlayer work build --item 7 # retry an item already on Work\n outerlayer work build --issue 42 --local # you build it\n outerlayer work build --issue ENG-123 --tracker linear # a Linear issue\n\nWithout --local, records a build request: a host takes the item when it\nhas a free slot. It never links the calling session and never takes a\nlease, even run from inside one.\n\nWith --local, puts the item on Work with no build request, so no host\ntakes it, and prints the line that starts your session on it. That\nsession links itself and holds the item's lease while it works.\n"
4245
4245
  ).action(async (opts) => {
4246
4246
  warnIfApiKeyFlag(opts);
4247
- const { runWorkBuild, WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4247
+ const { runWorkBuild, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4248
4248
  try {
4249
4249
  await runWorkBuild(opts);
4250
4250
  } catch (err) {
@@ -4260,7 +4260,7 @@ function registerWorkCommands(program2) {
4260
4260
  "\n outerlayer work link-session 42\n\nNames an item that already exists on the calling session \u2014 it never\ncreates one. Create one with `outerlayer work build --local`. Linking\nthe same session to the same item twice is a no-op. Also takes or\nrenews that session's own 20-minute lease, unless --no-lease or\n--ended is given, or another worker already holds a live one.\n"
4261
4261
  ).action(async (number, opts) => {
4262
4262
  warnIfApiKeyFlag(opts);
4263
- const { runWorkLinkSession, WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4263
+ const { runWorkLinkSession, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4264
4264
  try {
4265
4265
  await runWorkLinkSession({ ...opts, number, noLease: opts.lease === false, logFailures: opts.logFailures === true });
4266
4266
  } catch (err) {
@@ -4285,8 +4285,8 @@ most one action flag may be given.
4285
4285
  `
4286
4286
  ).action(async (opts) => {
4287
4287
  warnIfApiKeyFlag(opts);
4288
- const { runWorkComment, WorkCommentCommandError } = await import('./work-comment-cmd-VQCG72ZQ.js');
4289
- const { WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4288
+ const { runWorkComment, WorkCommentCommandError } = await import('./work-comment-cmd-34FTLPUO.js');
4289
+ const { WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4290
4290
  try {
4291
4291
  await runWorkComment(opts);
4292
4292
  } catch (err) {
@@ -4302,8 +4302,8 @@ most one action flag may be given.
4302
4302
  "\n outerlayer work threads --item 7\n\nPrints the item's general thread, then one thread per acceptance\ncriterion that carries proof or a comment, each with who is waiting\non whom next.\n"
4303
4303
  ).action(async (opts) => {
4304
4304
  warnIfApiKeyFlag(opts);
4305
- const { runWorkThreads, WorkCommentCommandError } = await import('./work-comment-cmd-VQCG72ZQ.js');
4306
- const { WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4305
+ const { runWorkThreads, WorkCommentCommandError } = await import('./work-comment-cmd-34FTLPUO.js');
4306
+ const { WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4307
4307
  try {
4308
4308
  await runWorkThreads(opts);
4309
4309
  } catch (err) {
@@ -4325,7 +4325,7 @@ live addition remains on it.
4325
4325
  `
4326
4326
  ).action(async (opts) => {
4327
4327
  warnIfApiKeyFlag(opts);
4328
- const { runWorkRemove, WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4328
+ const { runWorkRemove, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4329
4329
  try {
4330
4330
  await runWorkRemove(opts);
4331
4331
  } catch (err) {
@@ -4338,7 +4338,7 @@ live addition remains on it.
4338
4338
  });
4339
4339
  workCmd.command("status").description("Show one item's stage, gate ledger, and additions").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
4340
4340
  warnIfApiKeyFlag(opts);
4341
- const { runWorkStatus, WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4341
+ const { runWorkStatus, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4342
4342
  try {
4343
4343
  await runWorkStatus(opts);
4344
4344
  } catch (err) {
@@ -4351,7 +4351,7 @@ live addition remains on it.
4351
4351
  });
4352
4352
  workCmd.command("list").description("List live work items for this factory").option("--stage <spec|build|review>", "filter by stage").option("--section <attention|waiting|flowing>", "filter by Queue section").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--unclaimed", "only items with no live lease").option("--claimed", "only items with a live lease, held by a host or a local session").option("--startable", "only items with an unused build request and no live lease").option("--needs <amend>", "only items with a thread waiting on an agent").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
4353
4353
  warnIfApiKeyFlag(opts);
4354
- const { runWorkList, WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4354
+ const { runWorkList, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4355
4355
  try {
4356
4356
  await runWorkList(opts);
4357
4357
  } catch (err) {
@@ -4367,7 +4367,7 @@ live addition remains on it.
4367
4367
  "\n outerlayer work claim --item 42 --kind implement\n\nRecords a lease held by the API key that sends it. A live lease held\nby a different key is refused; claiming again with the same key extends\nit. --host is a label only.\n"
4368
4368
  ).action(async (opts) => {
4369
4369
  warnIfApiKeyFlag(opts);
4370
- const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-VSSZDFY5.js');
4370
+ const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-DYD6II56.js');
4371
4371
  try {
4372
4372
  await runWorkClaim(opts);
4373
4373
  } catch (err) {
@@ -4383,7 +4383,7 @@ live addition remains on it.
4383
4383
  "\n outerlayer work renew --item 42\n\nExtends the live lease this API key holds. Refused with a 410 if the\nlease has expired, or a 403 if a different key holds it.\n"
4384
4384
  ).action(async (opts) => {
4385
4385
  warnIfApiKeyFlag(opts);
4386
- const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-VSSZDFY5.js');
4386
+ const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-DYD6II56.js');
4387
4387
  try {
4388
4388
  await runWorkRenew(opts);
4389
4389
  } catch (err) {
@@ -4402,7 +4402,7 @@ live addition remains on it.
4402
4402
  "\n outerlayer work release --item 42 --outcome ok\n outerlayer work release --item 42\n\nMarks the lease this API key holds released, optionally with an\noutcome. A lease held by a different key is refused. Releasing an\nalready-released lease is a no-op that returns the recorded release\ntime and outcome.\n\nRun inside a session with no --host, it releases that session's own\nlease instead, so the item's review opens without ending the\nsession. It never releases another session's lease. --outcome\napplies to a host's lease only. A later tool call in the session\ntakes the lease again.\n"
4403
4403
  ).action(async (opts) => {
4404
4404
  warnIfApiKeyFlag(opts);
4405
- const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-VSSZDFY5.js');
4405
+ const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-DYD6II56.js');
4406
4406
  try {
4407
4407
  await runWorkRelease(opts);
4408
4408
  } catch (err) {
@@ -4418,7 +4418,7 @@ live addition remains on it.
4418
4418
  "\n outerlayer work pr 481\n outerlayer work pr 481 --withdraw --item 250\n\nRun inside a session already on a work item. Records that pull\nrequest 481 in the checkout's repository belongs to the item named by\nOUTERLAYER_WORK, or refuses when the session is not on it. The same\nfact a `pr-link` in the session's own transcript records on sync.\nIdempotent: declaring the same pull request twice is a no-op.\n\n--withdraw removes one item's declaration of the pull request. It\nneeds your own login; an agent session or a factory key is refused.\n"
4419
4419
  ).action(async (number, opts) => {
4420
4420
  warnIfApiKeyFlag(opts);
4421
- const { runWorkPr, WorkPrCommandError } = await import('./work-pr-cmd-6TMSCO3Q.js');
4421
+ const { runWorkPr, WorkPrCommandError } = await import('./work-pr-cmd-EXTOGBJC.js');
4422
4422
  try {
4423
4423
  await runWorkPr({ ...opts, number });
4424
4424
  } catch (err) {
@@ -4434,8 +4434,8 @@ live addition remains on it.
4434
4434
  '\n outerlayer work open-pr --title "Add the thing" --body-file pr.md\n\nIn a host build, which holds an item key, the gateway opens the pull\nrequest as the factory\'s GitHub App, from the branch the claim named,\nor edits the one already open on that branch. No gh command runs.\nIn your own session it runs `gh pr create` (or `gh pr edit`) under your\nlogin, then declares the pull request on the item, as `work pr` does.\nRun it again after a change to the title or description.\n'
4435
4435
  ).action(async (opts) => {
4436
4436
  warnIfApiKeyFlag(opts);
4437
- const { runWorkOpenPr, WorkOpenPrCommandError } = await import('./work-open-pr-cmd-YESMWATB.js');
4438
- const { WorkCommandError } = await import('./work-cmd-TK4VOOHL.js');
4437
+ const { runWorkOpenPr, WorkOpenPrCommandError } = await import('./work-open-pr-cmd-N2RBDKZ4.js');
4438
+ const { WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4439
4439
  try {
4440
4440
  await runWorkOpenPr(opts);
4441
4441
  } catch (err) {
@@ -4452,7 +4452,7 @@ function registerRunnerCommands(program2) {
4452
4452
  const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
4453
4453
  runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
4454
4454
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-X45X7AS4.js');
4455
- const { start, RunnerStartError } = await import('./loop-QLL4DKRF.js');
4455
+ const { start, RunnerStartError } = await import('./loop-ZNUQT736.js');
4456
4456
  const { RunnerAlreadyRunningError } = await import('./pidfile-UZRH774M.js');
4457
4457
  const configPath = opts.config ?? defaultRunnerConfigPath();
4458
4458
  try {
@@ -4468,7 +4468,7 @@ function registerRunnerCommands(program2) {
4468
4468
  });
4469
4469
  runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
4470
4470
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4471
- const { runRunnerCheck } = await import('./check-VJRJ2KQ4.js');
4471
+ const { runRunnerCheck } = await import('./check-RBRRI77E.js');
4472
4472
  const configPath = opts.config ?? defaultRunnerConfigPath();
4473
4473
  const result = await runRunnerCheck(configPath);
4474
4474
  if (!result.ok) {
@@ -4497,7 +4497,7 @@ function registerRunnerCommands(program2) {
4497
4497
  }
4498
4498
  try {
4499
4499
  if (opts.service === true) {
4500
- const { installServiceCommand } = await import('./command-2LYWVGIK.js');
4500
+ const { installServiceCommand } = await import('./command-LNEFKIVC.js');
4501
4501
  const result2 = await installServiceCommand({
4502
4502
  configPath,
4503
4503
  print: opts.print,
@@ -4553,7 +4553,7 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
4553
4553
  return;
4554
4554
  }
4555
4555
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4556
- const { uninstallServiceCommand } = await import('./command-2LYWVGIK.js');
4556
+ const { uninstallServiceCommand } = await import('./command-LNEFKIVC.js');
4557
4557
  const result = await uninstallServiceCommand({ configPath: opts.config ?? defaultRunnerConfigPath(), unitName: opts.unitName, home: homeFromEnv() });
4558
4558
  if (result.ok) for (const line of result.lines) process.stdout.write(`${C.green}\u2713${C.reset} ${line}
4559
4559
  `);
@@ -4561,9 +4561,9 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
4561
4561
  });
4562
4562
  runnerCmd.command("init").description("Write a runner block that fits this machine; on macOS, offers a Linux VM").option("--config <path>", configOption).option("--vm", "on macOS, run the runner in a Linux VM (Lima), with container builds").option("--no-vm", "on macOS, skip the VM and run builds as unisolated processes").option("--allow-process-builds", "where builds cannot be isolated, run them as processes anyway").addOption(new Option("--config-stdin", "the VM-side hand-off: read the whole config as JSON on stdin").hideHelp()).option("--vm-cli-package <path>", "with --vm, install this packed CLI tarball in the VM").option("--unit-name <name>", "the service unit's name, to run a second runner beside the first").action(async (opts) => {
4563
4563
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-X45X7AS4.js');
4564
- const { runRunnerInit, RunnerInitError } = await import('./init-TMBE3BRN.js');
4565
- const { detectMachine } = await import('./machine-7T7FBSUL.js');
4566
- const { chooseVm, runVmInit, VmInitError } = await import('./init-WX5XE6L3.js');
4564
+ const { runRunnerInit, RunnerInitError } = await import('./init-OKCDXEOG.js');
4565
+ const { detectMachine } = await import('./machine-TBJKZ6TN.js');
4566
+ const { chooseVm, runVmInit, VmInitError } = await import('./init-ORDCPTFD.js');
4567
4567
  const configPath = opts.config ?? defaultRunnerConfigPath();
4568
4568
  try {
4569
4569
  const machine = detectMachine();
@@ -4663,7 +4663,7 @@ ${C.yellow}The runner will not update itself: ${installErr.message}${C.reset}
4663
4663
  }
4664
4664
  let serviceUp = false;
4665
4665
  if (installedLayout) {
4666
- const { installServiceCommand } = await import('./command-2LYWVGIK.js');
4666
+ const { installServiceCommand } = await import('./command-LNEFKIVC.js');
4667
4667
  const service = await installServiceCommand({
4668
4668
  configPath,
4669
4669
  entryPath: process.argv[1] ?? "",
@@ -4704,8 +4704,8 @@ Next:
4704
4704
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4705
4705
  const { buildRepositoryImage, RecipeError } = await import('./build-LELVCWHV.js');
4706
4706
  const { currentCliBuild } = await import('./cli-build-K56DK4DS.js');
4707
- const { createDockerHost } = await import('./docker-V7B6UKPF.js');
4708
- const { builderSpec } = await import('./builder-5DKTBWT3.js');
4707
+ const { createDockerHost } = await import('./docker-GM526LGX.js');
4708
+ const { builderSpec } = await import('./builder-EVO6F2NO.js');
4709
4709
  const { loadRunnerConfig } = await import('./config-X45X7AS4.js');
4710
4710
  const configPath = opts.config ?? defaultRunnerConfigPath();
4711
4711
  const memory = (() => {
@@ -4768,15 +4768,15 @@ Next:
4768
4768
  });
4769
4769
  runnerCmd.command("stop").description("Take no more work; wait for running jobs to finish, then exit").option("--config <path>", "the cloud config file naming the runner to stop").option("--now", "end running jobs immediately, with outcome stopped").action(async (opts) => {
4770
4770
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4771
- const { requestStop } = await import('./loop-QLL4DKRF.js');
4771
+ const { requestStop } = await import('./loop-ZNUQT736.js');
4772
4772
  const configPath = opts.config ?? defaultRunnerConfigPath();
4773
4773
  await requestStop(configPath, Boolean(opts.now));
4774
4774
  });
4775
4775
  runnerCmd.command("status").description("List running jobs; with --recent, finished ones too").option("--config <path>", "the cloud config file naming the runner to inspect").option("--recent", "also list finished jobs, newest first, capped at 20").option("--json", "machine-readable JSON output").action(async (opts) => {
4776
4776
  const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-X45X7AS4.js');
4777
4777
  const { jobsDir, runnerDir } = await import('./paths-OYKMVYJP.js');
4778
- const { listJobFiles, runnerProcessState } = await import('./loop-QLL4DKRF.js');
4779
- const { renderStatus } = await import('./status-SMF5JG2K.js');
4778
+ const { listJobFiles, runnerProcessState } = await import('./loop-ZNUQT736.js');
4779
+ const { renderStatus } = await import('./status-KPDVZMJ6.js');
4780
4780
  const { readHousekeepingRecord } = await import('./record-C43U4PKS.js');
4781
4781
  const path2 = await import('path');
4782
4782
  const configPath = opts.config ?? defaultRunnerConfigPath();
@@ -4828,7 +4828,7 @@ Next:
4828
4828
  });
4829
4829
  runnerCmd.command("logs").argument("<item>", "the work item's number in the factory").description("Print the newest attempt's log for one item").option("--config <path>", "the cloud config file naming the runner to inspect").option("-f, --follow", "keep printing as the log grows").action(async (itemArg, opts) => {
4830
4830
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4831
- const { listJobFiles } = await import('./loop-QLL4DKRF.js');
4831
+ const { listJobFiles } = await import('./loop-ZNUQT736.js');
4832
4832
  const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-H55NWW4H.js');
4833
4833
  const configPath = opts.config ?? defaultRunnerConfigPath();
4834
4834
  const item = parseTrackerNumber(itemArg);
@@ -5,8 +5,8 @@ import './chunk-I2UOAV7X.js';
5
5
  import { readJobFile } from './chunk-T6OIJQRT.js';
6
6
  import './chunk-PTW6W5NR.js';
7
7
  import { currentLink, execStartCommand } from './chunk-TI7B7UEO.js';
8
- import { detectMachine } from './chunk-QPPPUKQJ.js';
9
- import './chunk-LBU4CLK5.js';
8
+ import { detectMachine } from './chunk-472KC6JV.js';
9
+ import './chunk-BREEX2Z7.js';
10
10
  import { installService, uninstallService, realTaskScheduler } from './chunk-NTLGWCWK.js';
11
11
  import './chunk-FBTE2A2X.js';
12
12
  import './chunk-JKIWMRFH.js';
@@ -15,18 +15,18 @@ import { writeLaunchAgent, launchAgentPath } from './chunk-LF6MLJCY.js';
15
15
  import './chunk-3FMPZPJQ.js';
16
16
  import './chunk-N5FOE5PS.js';
17
17
  import './chunk-OGFGZQA3.js';
18
- import './chunk-FKFGQJNN.js';
18
+ import './chunk-VVIRHTH4.js';
19
19
  import './chunk-QOZKPLVJ.js';
20
- import './chunk-TV36SKEN.js';
20
+ import './chunk-JSUUXA5W.js';
21
21
  import './chunk-CX22S5BA.js';
22
22
  import './chunk-6CXYORUS.js';
23
23
  import './chunk-S6IUUNCD.js';
24
- import './chunk-KWCJLAHQ.js';
25
- import './chunk-KPUJGBA4.js';
24
+ import './chunk-DTDZXDQ3.js';
25
+ import './chunk-ZQ5JGHUO.js';
26
26
  import './chunk-BFESLKPP.js';
27
- import './chunk-LYESSQUA.js';
28
- import './chunk-ZEQMTBRD.js';
29
- import './chunk-LTJPX7TX.js';
27
+ import './chunk-UES67HLJ.js';
28
+ import './chunk-VDI5POCC.js';
29
+ import './chunk-IU4NZROR.js';
30
30
  import './chunk-USO2DKBD.js';
31
31
  import './chunk-N6LURUEF.js';
32
32
  import './chunk-YRYMNBGQ.js';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { COMMIT_LINE, autoConnectedLine, fetchFactories, promptOnTerminal, realConnectDeps, runConnect, runConnectCommand, saveFactoryConnection, selectFactory } from './chunk-LYESSQUA.js';
4
- import './chunk-ZEQMTBRD.js';
5
- import './chunk-LTJPX7TX.js';
3
+ export { COMMIT_LINE, autoConnectedLine, fetchFactories, promptOnTerminal, realConnectDeps, runConnect, runConnectCommand, saveFactoryConnection, selectFactory } from './chunk-UES67HLJ.js';
4
+ import './chunk-VDI5POCC.js';
5
+ import './chunk-IU4NZROR.js';
6
6
  import './chunk-USO2DKBD.js';
7
7
  import './chunk-N6LURUEF.js';
8
8
  import './chunk-YRYMNBGQ.js';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { CaptureDaemon, PRICE_TABLE_SOURCE, SECRET_PATTERNS, SOURCE_ADAPTERS, SUPPORTED_VERSIONS, StatuslineAggregator, WARNING_CODES, claudeCodeAdapter, codexAdapter, codexSessionIdFromPath, compareVersions, completePrefix, computeStatuslineState, costOfUsage, cursorAdapter, cursorChatIdFromPath, defaultCodexSessionsDir, defaultCursorChatsDir, defaultCursorProjectsDir, defaultProjectsDir, defaultRawDir, enrichSessionRepo, findCodexRollouts, findCursorChats, findTranscripts, isNewerThanSupported, isPriceKnown, normalizeErrorSignature, normalizeRemote, parseCodexRollout, parseCursorChat, parseTranscript, readStatuslineState, readSyncWatermarkMs, remoteLookupFailed, resolvePrice, resolveRepoIdentity, rootChildIds, scanAll, scrubDeep, scrubText, sessionIdFromPath, setCustomScrubbers, setLocalIdentity, setRepoRoot, statuslineStatePath, tailTranscript, workspacesByHash, writeStatuslineState } from './chunk-LTJPX7TX.js';
3
+ export { CaptureDaemon, PRICE_TABLE_SOURCE, SECRET_PATTERNS, SOURCE_ADAPTERS, SUPPORTED_VERSIONS, StatuslineAggregator, WARNING_CODES, claudeCodeAdapter, codexAdapter, codexSessionIdFromPath, compareVersions, completePrefix, computeStatuslineState, costOfUsage, cursorAdapter, cursorChatIdFromPath, defaultCodexSessionsDir, defaultCursorChatsDir, defaultCursorProjectsDir, defaultProjectsDir, defaultRawDir, enrichSessionRepo, findCodexRollouts, findCursorChats, findTranscripts, isNewerThanSupported, isPriceKnown, normalizeErrorSignature, normalizeRemote, parseCodexRollout, parseCursorChat, parseTranscript, readStatuslineState, readSyncWatermarkMs, remoteLookupFailed, resolvePrice, resolveRepoIdentity, rootChildIds, scanAll, scrubDeep, scrubText, sessionIdFromPath, setCustomScrubbers, setLocalIdentity, setRepoRoot, statuslineStatePath, tailTranscript, workspacesByHash, writeStatuslineState } from './chunk-IU4NZROR.js';
4
4
  import './chunk-YT35WGIP.js';
5
5
  import './chunk-Z5GEFMRW.js';
6
6