@outerlayer/cli 0.8.1 → 0.8.3

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 (86) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +27 -9
  3. package/dist/{agent-setup-K6RD2Z4P.js → agent-setup-FMTXHWWM.js} +8 -8
  4. package/dist/{build-MS34XEGN.js → build-3FSJR5OO.js} +1 -1
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-IG6FNA54.js → builder-QZA2Z3M3.js} +3 -3
  7. package/dist/{check-GX5ND6RO.js → check-AFYUJ5SQ.js} +27 -27
  8. package/dist/{chunk-R7STSBLC.js → chunk-2E2MG3KW.js} +1 -1
  9. package/dist/{chunk-OD2VTIHN.js → chunk-2FWL7CE2.js} +3 -2
  10. package/dist/{chunk-KV47VQJZ.js → chunk-2OZH6ZY2.js} +4 -4
  11. package/dist/{chunk-PXFEYBDE.js → chunk-33GOCSRO.js} +3 -3
  12. package/dist/{chunk-7ZR5UPMB.js → chunk-36H5BONJ.js} +169 -3
  13. package/dist/{chunk-ZZXLM64C.js → chunk-42OX3Q3A.js} +1 -1
  14. package/dist/{chunk-MQ3IPHIZ.js → chunk-47RS42OZ.js} +6 -3
  15. package/dist/{chunk-HSN5QNS5.js → chunk-4GS22GWM.js} +10 -10
  16. package/dist/{chunk-BQFNZOMQ.js → chunk-4NOIKXUL.js} +4 -4
  17. package/dist/{chunk-KSLNQOOS.js → chunk-7HWIKEU5.js} +1 -1
  18. package/dist/{chunk-PWBILI5P.js → chunk-7KI224YS.js} +1 -1
  19. package/dist/{chunk-Q4432IZT.js → chunk-BORFBENT.js} +5 -5
  20. package/dist/{chunk-M4ERCYDB.js → chunk-BPTAOD6W.js} +232 -15
  21. package/dist/{chunk-2BRSMBBB.js → chunk-CLURXEWV.js} +2 -2
  22. package/dist/{chunk-AX23QKHS.js → chunk-CRLAB4PM.js} +1 -1
  23. package/dist/{chunk-I7CJIRMM.js → chunk-ERI5GBNI.js} +6 -1
  24. package/dist/{chunk-ILEA3YHM.js → chunk-EWBM2USM.js} +2 -2
  25. package/dist/{chunk-GAYWY4GI.js → chunk-HN2JBGSI.js} +2 -1
  26. package/dist/{chunk-ZOAEPWGL.js → chunk-HWMYGAKF.js} +1 -1
  27. package/dist/{chunk-ABIWDUMS.js → chunk-IS4DIGBQ.js} +13 -1
  28. package/dist/{chunk-WVGSB3Z2.js → chunk-J5DPVNL3.js} +2 -2
  29. package/dist/{chunk-M3SQ4YGD.js → chunk-KZ2FOICE.js} +1 -1
  30. package/dist/{chunk-TEKZRTM3.js → chunk-NPBLDMSD.js} +1 -1
  31. package/dist/{chunk-QB5JQH5V.js → chunk-NT5M6LF3.js} +72 -19
  32. package/dist/{chunk-Z2THOHPP.js → chunk-OCHRV5A6.js} +2 -2
  33. package/dist/{chunk-VXLJORHL.js → chunk-OPSPDEVU.js} +1 -1
  34. package/dist/{chunk-EV3M3EH7.js → chunk-OULFBETM.js} +2 -2
  35. package/dist/{chunk-BOLTI6LR.js → chunk-PLMTLGYH.js} +1 -1
  36. package/dist/{chunk-4FPWKV7L.js → chunk-SMPKFYKY.js} +3 -3
  37. package/dist/{chunk-5ODHQP6O.js → chunk-SPUWEK2Q.js} +55 -12
  38. package/dist/{chunk-QNRSFEGY.js → chunk-VITHLJOZ.js} +1 -1
  39. package/dist/{chunk-4ACZCY4I.js → chunk-WMPO3SKK.js} +3 -3
  40. package/dist/{chunk-TTNFGMHO.js → chunk-Y7UQHKFY.js} +19 -1
  41. package/dist/{chunk-BF4KKEFY.js → chunk-YCHJIAP2.js} +3 -3
  42. package/dist/{cli-X5ONGYNY.js → cli-L2TU7WDF.js} +87 -84
  43. package/dist/{command-7NFU3IPO.js → command-J5KLUIOI.js} +24 -21
  44. package/dist/{config-Z3USDBLU.js → config-OOBPCY7Q.js} +2 -2
  45. package/dist/{connect-cmd-PNZ6IJLJ.js → connect-cmd-NV7WVBY7.js} +3 -3
  46. package/dist/{context-adopt-D2Z7F7PB.js → context-adopt-3GFYGDRT.js} +5 -5
  47. package/dist/{context-materialize-4PMTDS6K.js → context-materialize-YBOW5YCC.js} +5 -5
  48. package/dist/{dist-3ZTZF2TP.js → dist-2LNAXGPZ.js} +1 -1
  49. package/dist/{docker-PRHRSJM5.js → docker-RSALMGPL.js} +4 -4
  50. package/dist/{doctor-KALLPCRB.js → doctor-M65EXDE6.js} +57 -23
  51. package/dist/{emit-artifact-cmd-D5GMVWNC.js → emit-artifact-cmd-SGDZQNHP.js} +6 -6
  52. package/dist/{emit-cmd-2QRMYPYO.js → emit-cmd-KBVRX42C.js} +3 -3
  53. package/dist/{emit-criteria-cmd-IE7VIM64.js → emit-criteria-cmd-PSZYZ32B.js} +4 -4
  54. package/dist/{emit-finding-cmd-46PTPN3A.js → emit-finding-cmd-VTSYDJYZ.js} +4 -4
  55. package/dist/{emit-result-cmd-KXHHP6HX.js → emit-result-cmd-ANAY4ZXF.js} +6 -6
  56. package/dist/{exec-client-NPYNUAF3.js → exec-client-2UX6NHAO.js} +3 -3
  57. package/dist/{guest-init-JWNNAH2H.js → guest-init-VHQNFCFS.js} +3 -3
  58. package/dist/{hook-fast-5H5QBJKT.js → hook-fast-B7TFCJR2.js} +1 -1
  59. package/dist/{import-capture-cmd-T4556ELW.js → import-capture-cmd-SD6FI2BM.js} +3 -3
  60. package/dist/{import-ruler-cmd-SG3UVGI7.js → import-ruler-cmd-NUSPILXT.js} +1 -1
  61. package/dist/index.js +3 -3
  62. package/dist/{init-S4DH6PWW.js → init-EE4JI2E4.js} +18 -18
  63. package/dist/{init-B4CECVOX.js → init-S2Z3YDK2.js} +20 -20
  64. package/dist/{init-cmd-P4MVCBCZ.js → init-cmd-X6BETOWP.js} +9 -9
  65. package/dist/{install-FHTVJZS6.js → install-C33LT5KQ.js} +3 -3
  66. package/dist/{install-cmd-BEC7XTNG.js → install-cmd-5HYMXLEW.js} +1 -1
  67. package/dist/{loop-ODMRE3CW.js → loop-CR46DEHT.js} +27 -27
  68. package/dist/{machine-J4SAB3Z2.js → machine-XZ34ENE2.js} +17 -17
  69. package/dist/{mcp-install-cmd-RLK4SO3N.js → mcp-install-cmd-4AQMSIGY.js} +1 -1
  70. package/dist/{mcp-serve-cmd-CT47P4YQ.js → mcp-serve-cmd-3KVYEUXG.js} +1 -1
  71. package/dist/{real-deps-SU24ZA2K.js → real-deps-TK6JMQSW.js} +3 -2
  72. package/dist/{session-sender-V46VPWQ5.js → session-sender-B67S2DHF.js} +5 -5
  73. package/dist/{starter-pack-MUXMAU4S.js → starter-pack-TC6HZ7JK.js} +3 -3
  74. package/dist/{status-QBKSH3QE.js → status-HIOSSWBN.js} +29 -23
  75. package/dist/{sync-cmd-RJR77V4O.js → sync-cmd-JN5RXCJQ.js} +4 -4
  76. package/dist/{watch-YNZTFLEY.js → watch-2H4RVURC.js} +4 -4
  77. package/dist/{work-claim-cmd-KAD3ZAH7.js → work-claim-cmd-JUC6E3R2.js} +8 -8
  78. package/dist/{work-cmd-CNWPTH7W.js → work-cmd-66GA4ETV.js} +5 -5
  79. package/dist/{work-comment-cmd-HH45S6UE.js → work-comment-cmd-J5K47MBZ.js} +5 -5
  80. package/dist/{work-open-pr-cmd-5KR3KFCN.js → work-open-pr-cmd-X46UWSPE.js} +6 -6
  81. package/dist/{work-pr-cmd-TTEGCP76.js → work-pr-cmd-T6SU4TYN.js} +5 -5
  82. package/package.json +1 -1
  83. package/skill-pack/maintained/outerlayer/SKILL.md +12 -2
  84. package/skill-pack/maintained/outerlayer/references/open-pull-request.md +29 -0
  85. package/skill-pack/template/build/SKILL.md +3 -2
  86. package/skill-pack/template/build/references/release.md +11 -2
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { writeJobFile, readJobFile } from './chunk-T6OIJQRT.js';
4
- import { senderPidfile } from './chunk-4FPWKV7L.js';
5
- import { DOCKERD_LOG } from './chunk-WVGSB3Z2.js';
6
- import { installScrubContext } from './chunk-BF4KKEFY.js';
7
- import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, formatDuration, retrySend, formatClock, containerSenderCommand, syncInContainer, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, senderSignalScript } from './chunk-M4ERCYDB.js';
8
- import { readBranchHead, fetchCommit } from './chunk-TTNFGMHO.js';
4
+ import { senderPidfile } from './chunk-SMPKFYKY.js';
5
+ import { DOCKERD_LOG } from './chunk-J5DPVNL3.js';
6
+ import { installScrubContext } from './chunk-YCHJIAP2.js';
7
+ import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, formatDuration, retrySend, formatClock, containerSenderCommand, syncInContainer, copyTranscriptsFromContainer, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript } from './chunk-BPTAOD6W.js';
8
+ import { readBranchHead, diffBetween, fetchCommit } from './chunk-Y7UQHKFY.js';
9
9
  import { isSameProcess, startTimeOf } from './chunk-N5FOE5PS.js';
10
- import { childEnvironment } from './chunk-TEKZRTM3.js';
10
+ import { childEnvironment } from './chunk-NPBLDMSD.js';
11
11
  import { CLAUDE_CODE_VERSION } from './chunk-CX22S5BA.js';
12
- import { waitForAgent, vmExecArgs } from './chunk-ZOAEPWGL.js';
13
- import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-R7STSBLC.js';
14
- import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-KV47VQJZ.js';
12
+ import { waitForAgent, vmExecArgs } from './chunk-HWMYGAKF.js';
13
+ import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-2E2MG3KW.js';
14
+ import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-2OZH6ZY2.js';
15
15
  import { planArtifactUpload } from './chunk-ZYHKJKSU.js';
16
- import { scrubText } from './chunk-GAYWY4GI.js';
17
- import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-PWBILI5P.js';
16
+ import { scrubText } from './chunk-HN2JBGSI.js';
17
+ import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-7KI224YS.js';
18
18
  import { parseSize } from './chunk-7RQ73DLO.js';
19
- import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, withTunnelRecord, RELAY_PORT, checkEnvironment } from './chunk-OD2VTIHN.js';
19
+ import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, withTunnelRecord, RELAY_PORT, checkEnvironment, EVAL_INPUT_DIR } from './chunk-2FWL7CE2.js';
20
20
  import { withHooksPath, authorEnvironment, commitIdentityRecord } from './chunk-HKMPVPO7.js';
21
- import { parsePolicy } from './chunk-7ZR5UPMB.js';
21
+ import { parsePolicy } from './chunk-36H5BONJ.js';
22
22
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
23
23
  import { resolveVersion } from './chunk-RA3O54FC.js';
24
24
  import { signerFor } from './chunk-V7NIVOFD.js';
@@ -75,8 +75,8 @@ async function writeGuestGhConfig(runtime, state, token) {
75
75
  const result = await asRoot(runtime, state, ["/bin/sh", "-c", script], ghHostsYml(token));
76
76
  if (result.status !== 0) throw new Error(`writing gh's configuration in the guest failed (exit ${result.status}): ${firstLine(result.stderr)}`);
77
77
  }
78
- async function unpackIntoGuest(runtime, state, dir, target) {
79
- const script = `set -e; mkdir -p ${target}; tar -x --no-same-owner -C ${target}; chmod -R a+rX ${target}`;
78
+ async function unpackIntoGuest(runtime, state, dir, target, opts = {}) {
79
+ const script = opts.readOnly === true ? `set -e; rm -rf ${target}; mkdir -p ${target}; tar -x --no-same-owner -C ${target}; chmod -R a+rX,a-w ${target}` : `set -e; mkdir -p ${target}; tar -x --no-same-owner -C ${target}; chmod -R a+rX ${target}`;
80
80
  const result = await asRoot(runtime, state, ["/bin/sh", "-c", script], tarOf(dir));
81
81
  if (result.status !== 0) throw new Error(`unpacking into ${target} in the guest failed (exit ${result.status}): ${firstLine(result.stderr)}`);
82
82
  }
@@ -307,6 +307,7 @@ async function provisionMicroVm(input) {
307
307
  removeStagedContext: () => removeStagedContext(buildDir2)
308
308
  });
309
309
  if (!steps.ok) return bail(steps.reason, steps.aborted === true);
310
+ state.startCommit = steps.startCommit;
310
311
  return { ok: true, workdir: CHECKOUT_DIR, state, environment };
311
312
  }
312
313
  async function waitForDocker(runtime, state, agentUser, now) {
@@ -409,6 +410,10 @@ async function copyHookErrors(runtime, state, jobDir) {
409
410
  } catch {
410
411
  }
411
412
  }
413
+ async function copyTranscriptsFromMicroVm(runtime, state) {
414
+ if (!isRunning(runtime, state)) return { ok: false, reason: "the build's microVM is gone" };
415
+ return copyTranscripts((argv) => asRoot(runtime, state, argv));
416
+ }
412
417
  async function startCheckMicroVm(input) {
413
418
  const { config, runtime, job, jobDir, tokens, log } = input;
414
419
  const { vm } = runtime;
@@ -523,10 +528,16 @@ async function startCheckMicroVm(input) {
523
528
  if (failed !== void 0) return fail(failed);
524
529
  if (abandoned()) return fail(ABANDONED);
525
530
  const env = checkEnvironment({ config, item: job.item, repository, hostEnv: runtime.hostEnv, containerEnv: built.containerEnv ?? {} });
531
+ const evalInput = { dir: join(checksDir, EVAL_INPUT_NAME), delivered: false };
532
+ const deliverEvalInput = async () => {
533
+ await unpackIntoGuest(runtime, state, evalInput.dir, EVAL_INPUT_DIR, { readOnly: true });
534
+ evalInput.delivered = true;
535
+ };
526
536
  return {
527
537
  ok: true,
528
538
  environment: {
529
539
  state,
540
+ evalInput: { dir: evalInput.dir, deliver: deliverEvalInput },
530
541
  exec: async (argv, workdir, opts) => {
531
542
  const ran = await vm.exec(state.vsockPath, { argv, user: agentUser, cwd: workdir, env: execEnvironment(state.imageEnv, env) });
532
543
  if (opts?.logPath !== void 0) appendFileSync(opts.logPath, ran.stdout + ran.stderr);
@@ -536,7 +547,9 @@ async function startCheckMicroVm(input) {
536
547
  try {
537
548
  await vm.firecracker.stop(state.firecracker);
538
549
  rmSync(state.vsockPath, { force: true });
539
- return await boot() === void 0;
550
+ if (await boot() !== void 0) return false;
551
+ if (evalInput.delivered) await deliverEvalInput();
552
+ return true;
540
553
  } catch {
541
554
  return false;
542
555
  }
@@ -785,10 +798,15 @@ function parseEvaluation(value) {
785
798
  }
786
799
  return { verdict, sentence: text(raw.sentence), waitingOn: raw.waitingOn, open };
787
800
  }
801
+ async function readWorkItem(config, item, fetchImpl) {
802
+ const { data } = await getJson(config.url, `/v1/work-items/${item}`, config.apiKey, config.appId, fetchImpl, await signerFor(config.configPath));
803
+ return data;
804
+ }
788
805
  async function readItemEvaluation(config, item, fetchImpl) {
789
806
  try {
790
- const { data } = await getJson(config.url, `/v1/work-items/${item}`, config.apiKey, config.appId, fetchImpl, await signerFor(config.configPath));
791
- return { ok: true, evaluation: parseEvaluation(fields(data).evaluation) };
807
+ const body = fields(await readWorkItem(config, item, fetchImpl));
808
+ const hasPullRequest = Array.isArray(body.pullRequests) ? body.pullRequests.length > 0 : void 0;
809
+ return { ok: true, evaluation: parseEvaluation(body.evaluation), hasPullRequest };
792
810
  } catch (err) {
793
811
  return { ok: false, reason: describeCallFailure(err) };
794
812
  }
@@ -806,6 +824,9 @@ function fit(prefix, parts) {
806
824
  }
807
825
  function decideFromEvaluation(read) {
808
826
  if (!read.ok) return { outcome: "incomplete", reason: fit("the item's status could not be read: ", [read.reason]) };
827
+ if (read.hasPullRequest === false) {
828
+ return { outcome: "incomplete", reason: "the build opened no pull request for the item" };
829
+ }
809
830
  const evaluation = read.evaluation;
810
831
  if (evaluation === void 0) return { outcome: "ok" };
811
832
  if (evaluation === null) return { outcome: "incomplete", reason: "the item has no evidence evaluation yet" };
@@ -1035,6 +1056,14 @@ async function runHostChecks(input) {
1035
1056
  const limitMinutes = config.checks?.timeLimitMinutes ?? DEFAULT_CHECK_TIME_LIMIT_MINUTES;
1036
1057
  const minutes = `${limitMinutes} ${limitMinutes === 1 ? "minute" : "minutes"}`;
1037
1058
  const environmentLog = join(jobDir, "checks", "environment.log");
1059
+ let transcripts = { ok: false, reason: "the runner holds no way to read the build's sessions" };
1060
+ if (deps.collectSessions !== void 0) {
1061
+ try {
1062
+ transcripts = await deps.collectSessions();
1063
+ } catch (err) {
1064
+ transcripts = { ok: false, reason: describeCallFailure(err) };
1065
+ }
1066
+ }
1038
1067
  if (job.microvm !== void 0) {
1039
1068
  if (deps.endBuildMicroVm === void 0) return await failAll("the runner has no way to stop the build's microVM, so no check environment was made");
1040
1069
  try {
@@ -1113,6 +1142,24 @@ async function runHostChecks(input) {
1113
1142
  }
1114
1143
  if (typeof settled === "string") return await failAll(settled);
1115
1144
  const ready = settled;
1145
+ try {
1146
+ await writeEvalInput({
1147
+ job,
1148
+ dir: ready.evalInput.dir,
1149
+ scratch,
1150
+ remote,
1151
+ readToken,
1152
+ branchHead: read.sha,
1153
+ transcripts,
1154
+ scrub: transcriptScrub(config, [config.apiKey, job.itemKey, readToken]),
1155
+ readWorkItem: () => readWorkItem(config, job.item, deps.fetchImpl),
1156
+ fetchDiff: deps.fetchDiff ?? ((input2) => diffBetween(input2)),
1157
+ log
1158
+ });
1159
+ await ready.evalInput.deliver();
1160
+ } catch (err) {
1161
+ return await failAll(`the checks' input could not be written: ${describeCallFailure(err)}`);
1162
+ }
1116
1163
  let usable = true;
1117
1164
  for (const check of checks) {
1118
1165
  if (!usable) {
@@ -1163,6 +1210,7 @@ async function runHostChecks(input) {
1163
1210
  writeJobFile(jobFilePath, job);
1164
1211
  }
1165
1212
  rmSync(scratch, { recursive: true, force: true });
1213
+ rmSync(join(jobDir, "checks", EVAL_INPUT_NAME), { recursive: true, force: true });
1166
1214
  if (existsSync(scratch)) log.error(`${tag} the checks' scratch directory could not be removed`);
1167
1215
  log.line(`${tag} checks done (${formatDuration(now().getTime() - startedMs)})`);
1168
1216
  }
@@ -1362,6 +1410,10 @@ function releaseScrub(config, home) {
1362
1410
  const secrets = [...headerVariables(config.build?.destinations), ...CLAUDE_CREDENTIAL_VARIABLES].map((name) => process.env[name] ?? "");
1363
1411
  return { literals: [...scrubList(merged?.literals), ...secrets], patterns: scrubList(merged?.patterns) };
1364
1412
  }
1413
+ function transcriptScrub(config, secrets) {
1414
+ const base = releaseScrub(config, homeFromEnv());
1415
+ return { literals: [...scrubList(base.literals), ...secrets.filter((secret) => secret !== void 0 && secret !== "")], patterns: scrubList(base.patterns) };
1416
+ }
1365
1417
  function stripUnsendableReasonChars(text2) {
1366
1418
  return text2.replace(/\u0000/g, "").replace(/\p{Cs}/gu, "");
1367
1419
  }
@@ -1671,6 +1723,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1671
1723
  }
1672
1724
  await stopBuildMicroVm(vmBuild.runtime, vmBuild.state, jobDirPath);
1673
1725
  };
1726
+ const collectSessions = build !== void 0 ? () => copyTranscriptsFromContainer(build.runtime, build.state) : vmBuild !== void 0 ? () => copyTranscriptsFromMicroVm(vmBuild.runtime, vmBuild.state) : void 0;
1674
1727
  if (job.checkContainer !== void 0 && job.checksRan === true) {
1675
1728
  try {
1676
1729
  await cleanupContainer(deps.container ?? createContainerRuntime(), job.checkContainer);
@@ -1698,7 +1751,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1698
1751
  config,
1699
1752
  job,
1700
1753
  jobDir: jobDirPath,
1701
- deps: { fetchImpl: deps.fetchImpl, runtime: deps.container ?? createContainerRuntime(), log, now: deps.now, endBuildMicroVm, ...deps.hostChecks }
1754
+ deps: { fetchImpl: deps.fetchImpl, runtime: deps.container ?? createContainerRuntime(), log, now: deps.now, endBuildMicroVm, collectSessions, ...deps.hostChecks }
1702
1755
  });
1703
1756
  } catch (err) {
1704
1757
  log.error(`${tag} the host's checks stopped: ${describeCallFailure(err)} \xB7 continuing`);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-QNRSFEGY.js';
4
- import { MIN_ENGINE_MAJOR } from './chunk-M4ERCYDB.js';
3
+ import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-VITHLJOZ.js';
4
+ import { MIN_ENGINE_MAJOR } from './chunk-BPTAOD6W.js';
5
5
  import { RUNNER_DIR_MODE, runnerDir, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
6
6
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
7
7
  import { dirname } from 'path';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { splitRawFile } from './chunk-7ZR5UPMB.js';
3
+ import { splitRawFile } from './chunk-36H5BONJ.js';
4
4
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-VXLJORHL.js';
4
- import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-7ZR5UPMB.js';
3
+ import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-OPSPDEVU.js';
4
+ import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-36H5BONJ.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname, relative, sep } from 'path';
7
7
 
@@ -28,7 +28,7 @@ function resolveGatewayCredentials(sources = {}) {
28
28
  return { ok: false, message, url, credential, appId, kind };
29
29
  }
30
30
  if (!url || !credential || !appId) {
31
- const missing = [!url && "--url", !credential && "--api-key", !appId && "--app-id"].filter(Boolean).join(", ");
31
+ const missing = [!url && "--url", !credential && "a login or OUTERLAYER_API_KEY", !appId && "--app-id"].filter(Boolean).join(", ");
32
32
  return { ok: false, message: `missing ${missing}. ${MISSING_HELP}`, url, credential, appId, kind };
33
33
  }
34
34
  return { ok: true, url, credential, appId, kind };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { LiveUploader } from './chunk-BF4KKEFY.js';
4
- import { CaptureDaemon } from './chunk-GAYWY4GI.js';
3
+ import { LiveUploader } from './chunk-YCHJIAP2.js';
4
+ import { CaptureDaemon } from './chunk-HN2JBGSI.js';
5
5
  import { parseWorkItemEnv } from './chunk-GQD22KKN.js';
6
- import { spoolDir } from './chunk-KSLNQOOS.js';
6
+ import { spoolDir } from './chunk-7HWIKEU5.js';
7
7
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
8
8
  import { mkdirSync, writeFileSync, rmSync } from 'fs';
9
9
  import { join } from 'path';
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-ABIWDUMS.js';
3
+ import { decideInstalledSwitch, fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-IS4DIGBQ.js';
4
4
  import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
5
- import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-QB5JQH5V.js';
5
+ import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-NT5M6LF3.js';
6
6
  import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-T6OIJQRT.js';
7
7
  import { RUNNER_PROTOCOL } from './chunk-AIW6GLET.js';
8
8
  import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
9
- import { placeholderQueues, placeholderProblem } from './chunk-Q4432IZT.js';
10
- import { readMarker, currentVersion, removeMarker, writeMarker, entryIn, versionDir, switchCurrent, cleanVersions, isInLayout, startedThroughCurrent, stagingDir } from './chunk-TI7B7UEO.js';
9
+ import { placeholderQueues, placeholderProblem } from './chunk-BORFBENT.js';
10
+ import { currentVersion, entryIn, versionDir, startedThroughCurrent, writeMarker, readMarker, removeMarker, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-TI7B7UEO.js';
11
11
  import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
12
12
  import { RepoFilter } from './chunk-TBT347UY.js';
13
- import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock } from './chunk-M4ERCYDB.js';
13
+ import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock } from './chunk-BPTAOD6W.js';
14
14
  import { checkFit } from './chunk-JKIWMRFH.js';
15
15
  import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
16
- import { spawnRun } from './chunk-TEKZRTM3.js';
17
- import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-2BRSMBBB.js';
18
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-KV47VQJZ.js';
19
- import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-PWBILI5P.js';
16
+ import { spawnRun } from './chunk-NPBLDMSD.js';
17
+ import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-CLURXEWV.js';
18
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-2OZH6ZY2.js';
19
+ import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-7KI224YS.js';
20
20
  import { exceedsDisk } from './chunk-7RQ73DLO.js';
21
- import { sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-OD2VTIHN.js';
21
+ import { sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-2FWL7CE2.js';
22
22
  import { parseClaimIdentity } from './chunk-HKMPVPO7.js';
23
23
  import { resolveVersion } from './chunk-RA3O54FC.js';
24
24
  import { loadHostKey, ensureHostKey, signerFor } from './chunk-V7NIVOFD.js';
@@ -980,6 +980,48 @@ function reportUpdateResult(state, version, result) {
980
980
  const retryAt = new Date(result.retryAtMs).toISOString().slice(11, 16);
981
981
  logOf(state).error(`could not update to ${version}: ${result.detail} \xB7 attempt ${result.attempts}, trying again after ${retryAt} UTC`);
982
982
  }
983
+ function restartOntoInstalled(state) {
984
+ const update = state.deps.update;
985
+ if (update === void 0) return false;
986
+ const configPath = state.config.configPath;
987
+ const own = ownVersionOf(state.deps);
988
+ const current = currentVersion(configPath);
989
+ const decision = decideInstalledSwitch({
990
+ own,
991
+ current,
992
+ fromCurrent: startedThroughCurrent(configPath, update.entryPath),
993
+ underService: update.underService === true,
994
+ installed: current !== void 0 && existsSync(entryIn(versionDir(configPath, current)))
995
+ });
996
+ if (decision.kind === "none") {
997
+ state.installedSwitch = void 0;
998
+ return false;
999
+ }
1000
+ const said = `${decision.kind}:${decision.to}`;
1001
+ const first = state.installedSwitch !== said;
1002
+ state.installedSwitch = said;
1003
+ const log = logOf(state);
1004
+ if (decision.kind === "missing") {
1005
+ if (first) log.error(`current names ${decision.to}, which is not installed \xB7 staying on ${own}; run \`outerlayer runner install\` again`);
1006
+ return false;
1007
+ }
1008
+ if (decision.kind === "foreground") {
1009
+ if (first) log.line(`${decision.to} is installed and current names it \xB7 this runner keeps running ${own} until it is restarted`);
1010
+ return false;
1011
+ }
1012
+ if (state.jobs.size > 0) {
1013
+ if (first) log.line(`${decision.to} is installed \xB7 taking no new work, restarting onto it once ${state.jobs.size} running build(s) finish`);
1014
+ return true;
1015
+ }
1016
+ try {
1017
+ writeMarker(configPath, { from: own, to: decision.to, starts: 0 });
1018
+ } catch (err) {
1019
+ log.error(`could not write the update marker, so ${decision.to} starts without going back to ${own} if its checks fail: ${describeCallFailure(err)}`);
1020
+ }
1021
+ log.line(`restarting ${own} -> ${decision.to}, which runner install put in place`);
1022
+ (state.exitForUpdate ?? (() => update.exit(RESTART_EXIT_STATUS)))();
1023
+ return true;
1024
+ }
983
1025
  async function updateWhenIdle(state) {
984
1026
  const update = state.deps.update;
985
1027
  const version = state.pendingUpdate;
@@ -1133,6 +1175,7 @@ async function housekeepingPass(state) {
1133
1175
  }
1134
1176
  async function runTick(state) {
1135
1177
  reloadConfig(state);
1178
+ if (restartOntoInstalled(state)) return;
1136
1179
  if (await updateWhenIdle(state)) return;
1137
1180
  if (holdWhenBlocked(state)) return;
1138
1181
  if (holdOffForDisk(state)) return;
@@ -1189,7 +1232,7 @@ var CLAIM_REFUSAL_CODES = new Set(
1189
1232
  "pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous branch_claimed_elsewhere".split(" ")
1190
1233
  );
1191
1234
  async function tryClaimAndStart(state, item, queue) {
1192
- const { postJson: postJson2 } = await import('./work-cmd-CNWPTH7W.js');
1235
+ const { postJson: postJson2 } = await import('./work-cmd-66GA4ETV.js');
1193
1236
  const log = logOf(state);
1194
1237
  const hostKey = await loadHostKey(state.config.configPath);
1195
1238
  const claim = await retrySend(
@@ -1913,7 +1956,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
1913
1956
  const outcome = await onStartUnderMarker({
1914
1957
  configPath,
1915
1958
  own: ownVersionOf(deps),
1916
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-GX5ND6RO.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
1959
+ check: update.check ? () => update.check(configPath) : async () => (await import('./check-AFYUJ5SQ.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
1917
1960
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
1918
1961
  log
1919
1962
  });
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { MIN_ENGINE_MAJOR } from './chunk-M4ERCYDB.js';
3
+ import { MIN_ENGINE_MAJOR } from './chunk-BPTAOD6W.js';
4
4
  import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CX22S5BA.js';
5
5
  import { spawnSync } from 'child_process';
6
6
  import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchFactories, selectFactory, saveFactoryConnection, connectedLine } from './chunk-ILEA3YHM.js';
4
- import { resolveRepoIdentity } from './chunk-GAYWY4GI.js';
5
- import { resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
3
+ import { fetchFactories, selectFactory, saveFactoryConnection, connectedLine } from './chunk-EWBM2USM.js';
4
+ import { resolveRepoIdentity } from './chunk-HN2JBGSI.js';
5
+ import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
6
6
  import { findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
7
7
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
8
8
 
@@ -111,6 +111,24 @@ async function fetchCommit(input) {
111
111
  return { ok: false, reason: `the fetch of ${input.commit.slice(0, 8)} from ${input.remote} failed: ${detail}` };
112
112
  }
113
113
  }
114
+ async function diffBetween(input) {
115
+ const credential = input.token === void 0 ? void 0 : tokenSettings(input.remote, input.token);
116
+ try {
117
+ mkdirSync(input.dir, { recursive: true, mode: RUNNER_DIR_MODE });
118
+ await git(input.dir, ["init", "--quiet"]);
119
+ await git(input.dir, ["fetch", "--quiet", "--no-tags", "--filter=blob:none", input.remote, input.base, input.head], CLONE_TIMEOUT_MS, credential);
120
+ await git(
121
+ input.dir,
122
+ ["diff", "--no-ext-diff", "--no-textconv", "--no-color", "--binary", `--output=${input.output}`, `${input.base}...${input.head}`],
123
+ CLONE_TIMEOUT_MS,
124
+ credential
125
+ );
126
+ return { ok: true };
127
+ } catch (err) {
128
+ const detail = (err instanceof Error ? err.message : String(err)).replace(/^git [\w-]+ failed: /, "").split("\n")[0];
129
+ return { ok: false, reason: `the diff of ${input.head.slice(0, 8)} from ${input.base.slice(0, 8)} could not be read from ${input.remote}: ${detail}` };
130
+ }
131
+ }
114
132
  var CLONE_TIMEOUT_MS = 6e5;
115
133
  async function cloneRepository(remote, dest, timeoutMs = CLONE_TIMEOUT_MS) {
116
134
  mkdirSync(dirname(dest), { recursive: true, mode: RUNNER_DIR_MODE });
@@ -485,4 +503,4 @@ async function prune(host, repository, repoRecords, keep, runnerDirPath) {
485
503
  return removed;
486
504
  }
487
505
 
488
- export { buildRepositoryImage, cloneRepository, fetchCommit, readBranchHead, readDefaultBranchHead };
506
+ export { buildRepositoryImage, cloneRepository, diffBetween, fetchCommit, readBranchHead, readDefaultBranchHead };
@@ -5,16 +5,16 @@ import { RepoFilter } from './chunk-TBT347UY.js';
5
5
  import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
6
6
  import { applyReportedCost } from './chunk-BKO6JEZI.js';
7
7
  import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-ZYHKJKSU.js';
8
- import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-GAYWY4GI.js';
8
+ import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-HN2JBGSI.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';
12
12
  import { defaultFetch } from './chunk-YO4PSLVB.js';
13
- import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
13
+ import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-PLMTLGYH.js';
14
14
  import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-YNJEOGDL.js';
15
15
  import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
16
16
  import { signerFor, signRunnerRequest } from './chunk-V7NIVOFD.js';
17
- import { writeSyncStatus, spoolDir } from './chunk-KSLNQOOS.js';
17
+ import { writeSyncStatus, spoolDir } from './chunk-7HWIKEU5.js';
18
18
  import { removeJournalHooks } from './chunk-XCCLFVXM.js';
19
19
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
20
20
  import { homeFromEnv } from './chunk-VNVZDWO3.js';