@outerlayer/cli 0.34.0-next.20261028132110 → 0.34.0-next.20261028164329

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 (119) hide show
  1. package/dist/{agent-setup-MO7DHLV4.js → agent-setup-IVXRBFVV.js} +6 -6
  2. package/dist/{bridge-4DFOWIY2.js → bridge-4GRZFXJU.js} +2 -2
  3. package/dist/{build-3IZ6XHYN.js → build-SEJJWGTO.js} +7 -7
  4. package/dist/{build-disk-TEITBQKE.js → build-disk-EYRR3PBT.js} +5 -5
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-S42B4STV.js → builder-T7B46P7T.js} +4 -4
  7. package/dist/{check-E47RDQFK.js → check-SPMUN5C4.js} +36 -36
  8. package/dist/{chunk-S25I6OCB.js → chunk-2EHDLYSL.js} +9 -9
  9. package/dist/{chunk-IZKUPAXF.js → chunk-3KGXXTMN.js} +1 -1
  10. package/dist/{chunk-NYMDS542.js → chunk-4YD7N6V3.js} +4 -4
  11. package/dist/{chunk-VJQQVTCS.js → chunk-5TXQFZHY.js} +1 -1
  12. package/dist/{chunk-NPTEYMBW.js → chunk-5W2YSWIW.js} +9 -4
  13. package/dist/{chunk-LBEYOL5K.js → chunk-7JSWRF5O.js} +2 -2
  14. package/dist/{chunk-BUVDDPOM.js → chunk-BBJ6BM5U.js} +1 -1
  15. package/dist/{chunk-QELQ6Y4I.js → chunk-CUAB7FAZ.js} +1 -1
  16. package/dist/{chunk-ZXQEBRCB.js → chunk-DCBFUUDL.js} +5 -5
  17. package/dist/{chunk-4557WV4R.js → chunk-EA2PQRCU.js} +2 -2
  18. package/dist/{chunk-GHZLVKA3.js → chunk-FUOKDHRB.js} +6 -6
  19. package/dist/{chunk-GHQW2BBX.js → chunk-GG5OE6MY.js} +2 -2
  20. package/dist/{chunk-6G3BG2GI.js → chunk-H7MGR2GN.js} +2 -2
  21. package/dist/{chunk-26WUFKYZ.js → chunk-HFOZTCTN.js} +1 -1
  22. package/dist/{chunk-FG564H3C.js → chunk-I2MFIT6X.js} +5 -5
  23. package/dist/{chunk-AJ3CC3HT.js → chunk-IPWKT5J7.js} +147 -29
  24. package/dist/{chunk-E3GX4WVJ.js → chunk-KH4774QT.js} +1 -1
  25. package/dist/{chunk-UAINHP2C.js → chunk-KPEMNHVF.js} +3 -3
  26. package/dist/{chunk-SH5JFBPO.js → chunk-KQDK4Q6A.js} +1 -1
  27. package/dist/{chunk-7XDF7PNF.js → chunk-MCPCOKHN.js} +2 -2
  28. package/dist/{chunk-JDQBJUXQ.js → chunk-MEIDQLXQ.js} +1 -1
  29. package/dist/{chunk-BRBZKIZG.js → chunk-MRLJK4GZ.js} +2 -2
  30. package/dist/{chunk-QGTJ5IJN.js → chunk-NCOL5RYI.js} +1 -1
  31. package/dist/{chunk-S44ZN3CV.js → chunk-OYQVLQP3.js} +52 -13
  32. package/dist/{chunk-HA46L5FG.js → chunk-P2PNBDUT.js} +5 -4
  33. package/dist/{chunk-XDCD4GD5.js → chunk-POND2SMT.js} +3 -3
  34. package/dist/{chunk-265SXBQ5.js → chunk-QGDGGLSD.js} +3 -3
  35. package/dist/{chunk-262MWE4Q.js → chunk-QGEGLZSY.js} +6 -6
  36. package/dist/{chunk-YMYU56JD.js → chunk-QI7JB2GU.js} +87 -23
  37. package/dist/{chunk-DKIZDYUX.js → chunk-ROQPDCRU.js} +1 -1
  38. package/dist/{chunk-47SFTQA5.js → chunk-RRXS4CWE.js} +2 -2
  39. package/dist/{chunk-2CW2QMSG.js → chunk-S6UM3N4R.js} +1 -1
  40. package/dist/{chunk-64LLUVJR.js → chunk-SAAVZ2BX.js} +1 -1
  41. package/dist/{chunk-7XZQTJOD.js → chunk-T3XPLCJG.js} +11 -5
  42. package/dist/{chunk-6MLX26T4.js → chunk-TDCHUEKY.js} +2 -2
  43. package/dist/{chunk-ORENXMHA.js → chunk-UXC3RQLF.js} +1 -1
  44. package/dist/{chunk-X2ZJL7GA.js → chunk-UZEIBWTP.js} +2 -2
  45. package/dist/{chunk-WHONZ53R.js → chunk-V2S2WRGD.js} +1 -1
  46. package/dist/{chunk-BEILLR5Q.js → chunk-W7E6IMEW.js} +3 -3
  47. package/dist/{chunk-ESK6EWAQ.js → chunk-WA3HIJVK.js} +3 -3
  48. package/dist/{chunk-TTUI3S6B.js → chunk-WH3FPBPO.js} +603 -45
  49. package/dist/{chunk-T664NDNT.js → chunk-XDAMLX2L.js} +5 -5
  50. package/dist/{chunk-JDYBPAPP.js → chunk-YF7W7B7Y.js} +24 -8
  51. package/dist/{chunk-ECCAFFAH.js → chunk-YIK5SGEN.js} +5 -5
  52. package/dist/{chunk-4N7BQBO4.js → chunk-YLPJOUVF.js} +5 -3
  53. package/dist/{chunk-TVDKDXW6.js → chunk-ZCA34T7R.js} +3 -3
  54. package/dist/{chunk-TZXJSNN4.js → chunk-ZCZY3Q55.js} +1 -1
  55. package/dist/{chunk-BTA5QOKD.js → chunk-ZTOJIRJH.js} +2 -2
  56. package/dist/{claude-launcher-TG7CHE3N.js → claude-launcher-7IC6QWR5.js} +1 -1
  57. package/dist/{cli-3V7AMF2V.js → cli-GKROH23V.js} +110 -110
  58. package/dist/{command-57COSNSG.js → command-XA6DOFL4.js} +24 -24
  59. package/dist/config-RSOCVUKC.js +17 -0
  60. package/dist/{connect-cmd-VBEYNPAK.js → connect-cmd-JFGDHFLA.js} +5 -5
  61. package/dist/{container-start-RS3S6WYE.js → container-start-ZDSVXSAL.js} +30 -30
  62. package/dist/{context-show-cmd-GMF7YMSN.js → context-show-cmd-XWLTP6R4.js} +6 -6
  63. package/dist/{control-plane-launch-4WRFVYNP.js → control-plane-launch-3MBWPYWZ.js} +5 -5
  64. package/dist/{demo-record-cmd-KM2UPWPL.js → demo-record-cmd-SIKNTSGI.js} +2 -2
  65. package/dist/{demo-voice-cmd-KFNEU2GR.js → demo-voice-cmd-SAB3QU4F.js} +11 -11
  66. package/dist/{docker-UP7EFFLL.js → docker-YMRPMDOW.js} +4 -4
  67. package/dist/{doctor-B2EZV6SJ.js → doctor-NVHAE4LS.js} +24 -24
  68. package/dist/{emit-artifact-cmd-NLCKM5TU.js → emit-artifact-cmd-TZTVQCFT.js} +10 -10
  69. package/dist/{emit-criteria-cmd-GO3TDUCG.js → emit-criteria-cmd-WH7JB4RQ.js} +7 -7
  70. package/dist/{emit-demo-cmd-EJBQHFR2.js → emit-demo-cmd-DNUVG5N7.js} +11 -11
  71. package/dist/{emit-finding-cmd-PHUHZLQ3.js → emit-finding-cmd-X5CBH4ZA.js} +7 -7
  72. package/dist/{emit-result-cmd-UJSWTGDG.js → emit-result-cmd-VCKNZ4RZ.js} +9 -9
  73. package/dist/{emit-step-cmd-M2JEWJ4Q.js → emit-step-cmd-IUXZZYKO.js} +7 -7
  74. package/dist/{exec-client-BQIZRROT.js → exec-client-U4544U2S.js} +3 -3
  75. package/dist/{find-unit-H5DKNRBG.js → find-unit-QYD2FMCP.js} +8 -8
  76. package/dist/{findings-cmd-O3VCFA55.js → findings-cmd-PLHBAQW4.js} +7 -7
  77. package/dist/{fleet-readiness-SXIYBEWC.js → fleet-readiness-F65CKZY5.js} +5 -5
  78. package/dist/{governing-source-QEXH6MIZ.js → governing-source-JFCTQXYK.js} +9 -9
  79. package/dist/{guest-init-DXXSPKHY.js → guest-init-MI4SEME4.js} +4 -4
  80. package/dist/{hook-fast-DPC75LFQ.js → hook-fast-GOH4T6SN.js} +1 -1
  81. package/dist/{host-checks-DN6HLRIW.js → host-checks-LEVAIIN4.js} +28 -28
  82. package/dist/{pending-V5FBWIJ4.js → host-key-OMLDWLNG.js} +3 -3
  83. package/dist/{image-tag-3KPTSRB4.js → image-tag-YJJONB64.js} +3 -3
  84. package/dist/index.js +4 -4
  85. package/dist/{init-SCUDJ6QI.js → init-JVKJTJNM.js} +21 -21
  86. package/dist/{init-6D3RKRRB.js → init-W3ATJYLX.js} +24 -22
  87. package/dist/{init-cmd-ELTRVJLG.js → init-cmd-XJOEU2PB.js} +10 -10
  88. package/dist/{init-update-4GUGHNS5.js → init-update-KX3FFQ5H.js} +8 -8
  89. package/dist/{install-cmd-6HGNO2HF.js → install-cmd-QTIIMO6B.js} +5 -5
  90. package/dist/{logs-HUENB7U4.js → logs-YVXVAYTD.js} +2 -2
  91. package/dist/{loop-LILQBIHK.js → loop-NNJN2XOW.js} +35 -35
  92. package/dist/{machine-UVPCJGJU.js → machine-OQOHEMJB.js} +21 -21
  93. package/dist/{mcp-serve-cmd-OFK3CS2T.js → mcp-serve-cmd-ECTAPDB3.js} +4 -4
  94. package/dist/{paths-VQ3ALYZ3.js → paths-M66LPPUF.js} +2 -2
  95. package/dist/{host-key-5P3ZL5XW.js → pending-7LC6XDRO.js} +3 -3
  96. package/dist/{pidfile-AVJFRZZT.js → pidfile-DSQOOAZV.js} +3 -3
  97. package/dist/{record-XE7Z3QGF.js → record-3KKIJ3XL.js} +3 -3
  98. package/dist/{runner-env-K4DOSDUV.js → runner-env-EX7YUIUH.js} +8 -8
  99. package/dist/{runner-identity-4RVY2MHX.js → runner-identity-LJWBXNM5.js} +4 -4
  100. package/dist/{runner-key-4OIOA3CD.js → runner-key-CAUO4RKG.js} +21 -21
  101. package/dist/{session-sender-N6QHL35T.js → session-sender-U2CTD7EX.js} +10 -10
  102. package/dist/{spec-cmd-EZGRJPUQ.js → spec-cmd-SAWQYHKM.js} +8 -8
  103. package/dist/{status-5RSSYZBU.js → status-IPIMYTG5.js} +28 -28
  104. package/dist/{sync-cmd-NEAZMEIL.js → sync-cmd-EBJQ5LMH.js} +9 -9
  105. package/dist/{update-steps-6JOHOMGM.js → update-steps-E2PP5DPR.js} +29 -29
  106. package/dist/{watch-FOY5LSSS.js → watch-6NRBX6VE.js} +9 -9
  107. package/dist/{work-claim-cmd-EJT55FZY.js → work-claim-cmd-SLVX2N4L.js} +12 -12
  108. package/dist/{work-cmd-KLPPJG4U.js → work-cmd-VSHZCXHQ.js} +7 -7
  109. package/dist/{work-comment-cmd-TT6TFF6Q.js → work-comment-cmd-3DCL7VHN.js} +8 -8
  110. package/dist/{work-demo-cmd-22PLEX4X.js → work-demo-cmd-SZJIKB5J.js} +7 -7
  111. package/dist/{work-logs-cmd-DWK5AYLK.js → work-logs-cmd-MRFSBMJM.js} +7 -7
  112. package/dist/{work-open-pr-cmd-MKHZBGA6.js → work-open-pr-cmd-N7GK7FUQ.js} +8 -8
  113. package/dist/{work-pr-cmd-P7PRHAJD.js → work-pr-cmd-HD5OIHUU.js} +7 -7
  114. package/dist/{work-proofs-cmd-7C22LBBE.js → work-proofs-cmd-H2GGE5HK.js} +8 -8
  115. package/dist/{work-proofs-record-SLIZUXUY.js → work-proofs-record-CJAFFWXG.js} +14 -14
  116. package/dist/{work-stop-cmd-U42TFT7X.js → work-stop-cmd-M6RIGF7S.js} +7 -7
  117. package/package.json +1 -1
  118. package/skill-pack/maintained/outerlayer-build/SKILL.md +22 -0
  119. package/dist/config-2EADRNJB.js +0 -17
@@ -1,33 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { sha256OfFile, downloadPinned, VoiceDownloadError } from './chunk-2PGI6RDE.js';
4
- import { readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, SHARED_OWNER, SHARED_NAME, metadataFromLabels, writeRecord } from './chunk-S44ZN3CV.js';
5
- import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-7XZQTJOD.js';
4
+ import { readDefaultBranchFiles, readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, SHARED_OWNER, SHARED_NAME, universalBase, metadataFromLabels, writeRecord } from './chunk-OYQVLQP3.js';
5
+ import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-T3XPLCJG.js';
6
6
  import { currentCliBuild } from './chunk-OGFGZQA3.js';
7
- import { runExec, execCapture, waitForAgent } from './chunk-NPTEYMBW.js';
8
- import { GUEST_CID, linkVsockSockets } from './chunk-DKIZDYUX.js';
9
- import { retrySend, describeCallFailure, keepStagedContext, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-ZXQEBRCB.js';
10
- import { runnerImageVersion } from './chunk-ORENXMHA.js';
11
- import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-UAINHP2C.js';
12
- import { optionalEgress, runnerCredentialProblem, builtinKind, allowHostProblem, systemClock, emptyEgressCounts, hostAllowed } from './chunk-JDYBPAPP.js';
13
- import { formatBytes, allocatedBytes } from './chunk-47SFTQA5.js';
14
- import { NETWORK_HELPER_MEMORY, createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, networkHelperName, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, mountableHome, homeCopyRunArgs, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, NETWORK_READY_FILE, spawnRun, identityRunArgs, parseIdentity, networkHelperRunArgs } from './chunk-HA46L5FG.js';
7
+ import { runExec, execCapture, waitForAgent } from './chunk-5W2YSWIW.js';
8
+ import { GUEST_CID, linkVsockSockets } from './chunk-ROQPDCRU.js';
9
+ import { retrySend, describeCallFailure, keepStagedContext, formatDuration, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-DCBFUUDL.js';
10
+ import { runnerImageVersion } from './chunk-UXC3RQLF.js';
11
+ import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-KPEMNHVF.js';
12
+ import { optionalEgress, runnerCredentialProblem, builtinKind, DEFAULT_SETUP_MINUTES, allowHostProblem, DEFAULT_SAVED_STATE_MAX_BYTES, systemClock, emptyEgressCounts, hostAllowed } from './chunk-YF7W7B7Y.js';
13
+ import { DEFAULT_BUILD_DISK, formatBytes, allocatedBytes } from './chunk-RRXS4CWE.js';
14
+ import { parseSize, NETWORK_HELPER_MEMORY, createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, networkHelperName, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, mountableHome, homeCopyRunArgs, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, NETWORK_READY_FILE, spawnRun, identityRunArgs, parseIdentity, networkHelperRunArgs, SAVED_STATE_LABEL } from './chunk-P2PNBDUT.js';
15
15
  import { RecipeError, DOCKER_FEATURE, universalImagePending, writeSanitizedRecipe, classifyProperties } from './chunk-CM4J53WZ.js';
16
- import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, networkHelperPinned, NETWORK_HELPER_SHA256, universalImagePinned, UNIVERSAL_IMAGE, UNIVERSAL_IMAGE_DIGEST, UNIVERSAL_IMAGE_REPOSITORY, UNIVERSAL_IMAGE_SOURCE, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-D3CT6XQ4.js';
16
+ import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, networkHelperPinned, NETWORK_HELPER_SHA256, universalImagePinned, UNIVERSAL_IMAGE, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-D3CT6XQ4.js';
17
17
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
18
- import { postJson, WorkCommandError, getJson } from './chunk-T664NDNT.js';
18
+ import { postJson, WorkCommandError, getJson } from './chunk-XDAMLX2L.js';
19
19
  import { sanitizeTerminal } from './chunk-VEVNGDTP.js';
20
- import { signerFor } from './chunk-VJQQVTCS.js';
20
+ import { signerFor } from './chunk-5TXQFZHY.js';
21
21
  import { sharedSkillNames, skillConflictMessage } from './chunk-FGF52V4V.js';
22
22
  import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
23
23
  import { MIN_SCRUBBED_LITERAL, setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-GH2HEEOH.js';
24
24
  import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-2EEW6FJN.js';
25
25
  import { downconvertSession } from './chunk-IXRUVR25.js';
26
- import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-2CW2QMSG.js';
27
- import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, checkoutPath, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment, checkEnvironment, withMiseVariables, AGENT_CREDENTIAL_MISSING, isMiseVariableAllowed, JOB_MOUNT, realFdStorePort } from './chunk-4N7BQBO4.js';
26
+ import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-S6UM3N4R.js';
27
+ import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, checkoutPath, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment, checkEnvironment, withMiseVariables, isMiseVariableAllowed, JOB_MOUNT, realFdStorePort, AGENT_CREDENTIAL_MISSING } from './chunk-YLPJOUVF.js';
28
28
  import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, DOCKER_DESKTOP_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, JOIN_WAIT_MS, MAX_OPEN_STREAMS, STREAM_RESET_RATE, STREAM_RESET_BURST, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-MESOOLF4.js';
29
29
  import { spawn, spawnSync } from 'child_process';
30
- import { mkdirSync, existsSync, readFileSync, mkdtempSync, rmSync, chmodSync, truncateSync, statSync, accessSync, constants, readdirSync, writeFileSync, lstatSync, copyFileSync, renameSync, rmdirSync, unlinkSync, linkSync, openSync, closeSync, cpSync, writeSync, appendFileSync, createWriteStream, createReadStream } from 'fs';
30
+ import { mkdirSync, existsSync, readFileSync, mkdtempSync, rmSync, chmodSync, truncateSync, statSync, accessSync, constants, readdirSync, writeFileSync, renameSync, lstatSync, copyFileSync, rmdirSync, unlinkSync, linkSync, openSync, closeSync, cpSync, writeSync, appendFileSync, createWriteStream, createReadStream } from 'fs';
31
31
  import { randomBytes, createHash } from 'crypto';
32
32
  import { join, dirname, isAbsolute, relative, resolve, basename } from 'path';
33
33
  import { createConnection, connect, createServer as createServer$1, isIP } from 'net';
@@ -186,9 +186,9 @@ async function download(file, url, fetchImpl) {
186
186
  if (!response.ok) throw new AssetError(file, `${file} could not be downloaded from ${url}: the server answered ${response.status}`);
187
187
  return Buffer.from(await response.arrayBuffer());
188
188
  }
189
- function keptPath(dir, sha256, name) {
190
- mkdirSync(join(dir, sha256), { recursive: true, mode: RUNNER_DIR_MODE });
191
- return join(dir, sha256, name);
189
+ function keptPath(dir, sha2562, name) {
190
+ mkdirSync(join(dir, sha2562), { recursive: true, mode: RUNNER_DIR_MODE });
191
+ return join(dir, sha2562, name);
192
192
  }
193
193
  async function ensureFile(dir, file, pin, fetchImpl, mode, stops = MICROVM_STOPS) {
194
194
  const path = keptPath(dir, pin.sha256, file);
@@ -2392,8 +2392,7 @@ async function buildInBuilder(opts, deps, prepared) {
2392
2392
  claudeCodeVersion: prepared.claudeCodeVersion,
2393
2393
  buildId: opts.cli.buildId,
2394
2394
  guestHelper: true,
2395
- fetched: true,
2396
- ...location.kind === "default" ? { universal: true } : {}
2395
+ fetched: true
2397
2396
  })
2398
2397
  );
2399
2398
  inputs = builderInput({ checkoutDir: checkout.dir, toolsDir, toolFilesDir, recipeDir }, archive);
@@ -2415,6 +2414,7 @@ async function buildInBuilder(opts, deps, prepared) {
2415
2414
  const described = JSON.parse(result);
2416
2415
  const imageConfig = parseImageConfig(JSON.stringify(described.config));
2417
2416
  const labels = described.config.Labels ?? {};
2417
+ const base = universalBase(location, labels);
2418
2418
  mkdirSync(recordDir, { recursive: true, mode: RUNNER_DIR_MODE });
2419
2419
  const fd = openSync(partial, "w", 384);
2420
2420
  let received = 0;
@@ -2444,7 +2444,7 @@ async function buildInBuilder(opts, deps, prepared) {
2444
2444
  sourceCommit: checkout.commit,
2445
2445
  defaultBranch: checkout.defaultBranch,
2446
2446
  recipe: location.kind === "default" ? "default" : location.path,
2447
- ...location.kind === "default" ? { base: { reference: `${UNIVERSAL_IMAGE_REPOSITORY}:${UNIVERSAL_IMAGE_SOURCE}`, digest: UNIVERSAL_IMAGE_DIGEST } } : {},
2447
+ ...base === void 0 ? {} : { base },
2448
2448
  recipeKey: prepared.recipeKey,
2449
2449
  toolsKey: prepared.toolsKey,
2450
2450
  imageId: `${ROOT_DISK_ID_PREFIX}${rKey}-${tKey}`,
@@ -2847,8 +2847,8 @@ function needsBuildSkill(queue, command) {
2847
2847
  }
2848
2848
  function missingBuildSkillReason(governed, lookupFailure) {
2849
2849
  const checked = governed === void 0 ? BUILD_SKILL_PATHS.join(" and ") : `${BUILD_SKILL_PATHS.join(", ")} and the governed context from ${governed.repository}@${governed.commit.slice(0, 7)}`;
2850
- const lookup2 = lookupFailure === void 0 ? "" : `, and the lookup of the governing repository failed (${lookupFailure})`;
2851
- return `the build has no \`build\` skill, so /build would load nothing${lookup2}: checked ${checked}`;
2850
+ const lookup3 = lookupFailure === void 0 ? "" : `, and the lookup of the governing repository failed (${lookupFailure})`;
2851
+ return `the build has no \`build\` skill, so /build would load nothing${lookup3}: checked ${checked}`;
2852
2852
  }
2853
2853
  function cloneHasBuildSkill(checkout) {
2854
2854
  return BUILD_SKILL_PATHS.some((path) => existsSync(join(checkout, path)));
@@ -2989,6 +2989,22 @@ var MANIFESTS = {
2989
2989
  "build.gradle": "java",
2990
2990
  "build.gradle.kts": "java"
2991
2991
  };
2992
+ var VERSION_FILES = [
2993
+ ".nvmrc",
2994
+ ".node-version",
2995
+ ".python-version",
2996
+ ".ruby-version",
2997
+ ".java-version",
2998
+ ".go-version",
2999
+ ".tool-versions",
3000
+ "mise.toml",
3001
+ ".mise.toml",
3002
+ ".config/mise.toml",
3003
+ ".config/mise/config.toml",
3004
+ "go.mod",
3005
+ "rust-toolchain.toml",
3006
+ "rust-toolchain"
3007
+ ];
2992
3008
  var IMAGE_CONFIG = "/etc/mise/config.toml";
2993
3009
  var RUST_PIN_FILES = ["rust-toolchain.toml", "rust-toolchain"];
2994
3010
  var REFUSALS_NAMED2 = 3;
@@ -3127,6 +3143,128 @@ function ranRuntimeStep(state) {
3127
3143
  return state?.unpinnedRuntimes !== void 0;
3128
3144
  }
3129
3145
 
3146
+ // src/runner/setup-scripts.ts
3147
+ var SETUP_SCRIPT = ".outerlayer/setup.sh";
3148
+ var RUN_SCRIPT = 'if [ -x "$1" ]; then exec "$1"; else exec /bin/sh "$1"; fi';
3149
+ function tailOf(result) {
3150
+ const lines = `${result.stdout}
3151
+ ${result.stderr}`.split("\n").map((line2) => line2.trimEnd()).filter((line2) => line2 !== "");
3152
+ return lines.slice(-20).join(" | ");
3153
+ }
3154
+ function failureReason(entry, input, result) {
3155
+ const tail = tailOf(result);
3156
+ const printed = tail === "" ? "it printed nothing" : `the last lines it printed: ${tail}`;
3157
+ if (result.timedOut === true) {
3158
+ return `setup_timed_out: ${SETUP_SCRIPT} in ${entry.repository} ran past runner.build.setupMinutes (${input.limitMinutes} ${input.limitMinutes === 1 ? "minute" : "minutes"}); ${printed}`;
3159
+ }
3160
+ return `setup_failed: ${SETUP_SCRIPT} in ${entry.repository} failed (exit ${result.status}); ${printed}`;
3161
+ }
3162
+ async function runSetupScripts(input) {
3163
+ const { exec, log, tag } = input;
3164
+ const ran = [];
3165
+ const missing = [];
3166
+ for (const entry of input.repositories) {
3167
+ if (input.aborted()) return { ok: false, reason: "", aborted: true };
3168
+ const path = checkoutPath(entry);
3169
+ const probe = await exec(["test", "-f", SETUP_SCRIPT], path, { quiet: true });
3170
+ if (probe.status === 1) {
3171
+ missing.push(entry.repository);
3172
+ continue;
3173
+ }
3174
+ if (probe.status !== 0) return { ok: false, reason: `setup_failed: checking for ${SETUP_SCRIPT} in ${entry.repository} failed (exit ${probe.status})` };
3175
+ log.line(`${tag} setup ${entry.repository}: running ${SETUP_SCRIPT}`);
3176
+ const started = Date.now();
3177
+ const result = await exec(["sh", "-c", RUN_SCRIPT, "setup", SETUP_SCRIPT], path, { timeoutMs: input.timeoutMs });
3178
+ if (result.status !== 0 || result.timedOut === true) return { ok: false, reason: failureReason(entry, input, result) };
3179
+ log.line(`${tag} setup ${entry.repository}: ${SETUP_SCRIPT} passed in ${formatDuration(Date.now() - started)}`);
3180
+ ran.push(entry.repository);
3181
+ }
3182
+ return { ok: true, ran, missing };
3183
+ }
3184
+ function keepMissingSetupScripts(state, steps) {
3185
+ if (steps.missingSetupScripts !== void 0) state.missingSetupScripts = steps.missingSetupScripts;
3186
+ }
3187
+
3188
+ // src/runner/saved-state/key.ts
3189
+ function sha256(text) {
3190
+ return createHash("sha256").update(text).digest("hex");
3191
+ }
3192
+ function keyFilePaths() {
3193
+ return [SETUP_SCRIPT, ...VERSION_FILES];
3194
+ }
3195
+ function significant(path, content) {
3196
+ if (path !== "go.mod") return content;
3197
+ return content.split("\n").filter((line2) => /^\s*(go|toolchain)\s/.test(line2)).map((line2) => line2.trim()).join("\n");
3198
+ }
3199
+ function hashOf(path, content) {
3200
+ return content === null || content === void 0 ? "absent" : sha256(`present:${significant(path, content)}`);
3201
+ }
3202
+ function stateKey(input) {
3203
+ const baseKey = sha256(JSON.stringify({ version: 1, factory: input.factory, repositories: input.repositories.map((entry) => entry.repository), imageDigest: input.imageDigest, diskBytes: input.diskBytes }));
3204
+ const fileHashes = {};
3205
+ for (const entry of input.repositories) {
3206
+ for (const path of keyFilePaths()) fileHashes[`${entry.repository}:${path}`] = hashOf(path, entry.files[path]);
3207
+ }
3208
+ return { baseKey, key: sha256(JSON.stringify([baseKey, fileHashes])), fileHashes };
3209
+ }
3210
+ function changedFiles(saved, current) {
3211
+ const names = /* @__PURE__ */ new Set([...Object.keys(saved), ...Object.keys(current)]);
3212
+ return [...names].filter((name) => (saved[name] ?? "absent") !== (current[name] ?? "absent"));
3213
+ }
3214
+
3215
+ // src/runner/saved-state/select.ts
3216
+ var SAVED_STATE_MAX_AGE_MS = 7 * 864e5;
3217
+ var INCOMPLETE_GRACE_MS = 36e5;
3218
+ function savedAtOf(record) {
3219
+ return Date.parse(record.savedAt);
3220
+ }
3221
+ function oldestFirst(records) {
3222
+ return [...records].sort((a, b) => savedAtOf(a) - savedAtOf(b));
3223
+ }
3224
+ function newestFirst(records) {
3225
+ return oldestFirst(records).reverse();
3226
+ }
3227
+ function lookup2(records, key, nowMs) {
3228
+ const complete = newestFirst(records.filter((record) => record.complete));
3229
+ const same = complete.filter((record) => record.key === key.key);
3230
+ const fresh = same.find((record) => nowMs - savedAtOf(record) < SAVED_STATE_MAX_AGE_MS);
3231
+ if (fresh !== void 0) return { kind: "usable", record: fresh, ageMs: nowMs - savedAtOf(fresh) };
3232
+ if (same[0] !== void 0) return { kind: "expired", record: same[0], ageMs: nowMs - savedAtOf(same[0]) };
3233
+ const near = complete.find((record) => record.baseKey === key.baseKey);
3234
+ if (near !== void 0) return { kind: "changed", record: near, files: changedFiles(near.fileHashes, key.fileHashes) };
3235
+ return { kind: "none" };
3236
+ }
3237
+ function savingRefusedBecause(input) {
3238
+ if (!input.universalImage) return "its image comes from a devcontainer file";
3239
+ if (input.managed) return "this runner is managed";
3240
+ if (input.savedStateMax === "off") return "runner.housekeeping.savedStateMax is off";
3241
+ return void 0;
3242
+ }
3243
+ function checkoutNotAtDefaultHead(checkouts) {
3244
+ for (const entry of checkouts) {
3245
+ if (entry.keyCommit === void 0) return `${entry.repository}: the host did not read its default branch`;
3246
+ if (entry.startCommit !== entry.keyCommit) return `${entry.repository}: its default branch moved after the host read the key's files`;
3247
+ if (entry.head !== entry.startCommit) return `${entry.repository}: its branch already holds commits`;
3248
+ }
3249
+ return void 0;
3250
+ }
3251
+ function selectExpired(records, nowMs) {
3252
+ return records.filter((record) => nowMs - savedAtOf(record) >= SAVED_STATE_MAX_AGE_MS);
3253
+ }
3254
+ function selectToFit(records, maxBytes) {
3255
+ let total = records.reduce((sum, record) => sum + record.bytes, 0);
3256
+ const selected = [];
3257
+ for (const record of oldestFirst(records)) {
3258
+ if (total <= maxBytes) break;
3259
+ selected.push(record);
3260
+ total -= record.bytes;
3261
+ }
3262
+ return selected;
3263
+ }
3264
+ function selectStaleIncomplete(records, nowMs) {
3265
+ return records.filter((record) => !record.complete && nowMs - savedAtOf(record) >= INCOMPLETE_GRACE_MS);
3266
+ }
3267
+
3130
3268
  // src/runner/build-steps.ts
3131
3269
  var aborted = () => ({ ok: false, reason: "", aborted: true });
3132
3270
  function gitErrorLine(text) {
@@ -3192,13 +3330,24 @@ async function deliver(input, staged) {
3192
3330
  if (recorded.status !== 0) return { ok: false, reason: failure("recording the delivery failed", recorded) };
3193
3331
  return { ok: true };
3194
3332
  }
3195
- async function checkOut(input, entry) {
3333
+ async function checkOut(input, entry, restored) {
3196
3334
  const { exec, log, tag } = input;
3197
3335
  const path = checkoutPath(entry);
3198
- const clone = await exec(["git", "clone", "--filter=blob:none", "--single-branch", `https://github.com/${entry.repository}.git`, path], "/build/work");
3199
- if (clone.status !== 0) {
3200
- const detail = gitErrorLine(clone.stderr);
3201
- return { ok: false, reason: `the clone of ${entry.repository} failed (exit ${clone.status})${detail === "" ? "" : `: ${detail}`}` };
3336
+ const failed = (reason) => ({ ok: false, reason, ...restored ? { restoreFailed: true } : {} });
3337
+ if (restored) {
3338
+ for (const argv of [["git", "reset", "--hard", "-q"], ["git", "clean", "-fdq"]]) {
3339
+ const cleaned = await exec(argv, path, { quiet: true });
3340
+ if (cleaned.status !== 0) {
3341
+ const detail = gitErrorLine(cleaned.stderr);
3342
+ return failed(`the saved checkout of ${entry.repository} could not be cleaned (${argv[1]} exit ${cleaned.status})${detail === "" ? "" : `: ${detail}`}`);
3343
+ }
3344
+ }
3345
+ } else {
3346
+ const clone = await exec(["git", "clone", "--filter=blob:none", "--single-branch", `https://github.com/${entry.repository}.git`, path], "/build/work");
3347
+ if (clone.status !== 0) {
3348
+ const detail = gitErrorLine(clone.stderr);
3349
+ return { ok: false, reason: `the clone of ${entry.repository} failed (exit ${clone.status})${detail === "" ? "" : `: ${detail}`}` };
3350
+ }
3202
3351
  }
3203
3352
  try {
3204
3353
  const prepared = await prepareBranch({
@@ -3210,9 +3359,12 @@ async function checkOut(input, entry) {
3210
3359
  }
3211
3360
  });
3212
3361
  log.line(`${tag} ${entry.primary ? "" : `${entry.repository} `}on ${prepared.branch} at ${prepared.head.slice(0, 8)}`);
3213
- return { ok: true, startCommit: prepared.startCommit };
3362
+ return { ok: true, head: prepared.head, startCommit: prepared.startCommit };
3214
3363
  } catch (err) {
3215
- if (err instanceof BranchPrepareError) return { ok: false, reason: entry.primary ? err.message : `${entry.repository}: ${err.message}` };
3364
+ if (err instanceof BranchPrepareError) {
3365
+ const reason = entry.primary ? err.message : `${entry.repository}: ${err.message}`;
3366
+ return failed(restored ? `the saved checkout of ${entry.repository} could not be switched to ${entry.branch}: ${err.message}` : reason);
3367
+ }
3216
3368
  throw err;
3217
3369
  }
3218
3370
  }
@@ -3235,24 +3387,29 @@ async function runBuildSteps(input) {
3235
3387
  const primary = primaryOf(repositories) ?? { repository, branch: input.branch, primary: true };
3236
3388
  const rewrite = await exec(["git", "config", "--global", `url.http://127.0.0.1:${RELAY_PORT}/github.com/.insteadOf`, "https://github.com/"], "/build/work");
3237
3389
  if (rewrite.status !== 0) return { ok: false, reason: `configuring the build's git remote failed (exit ${rewrite.status})` };
3238
- const first = await checkOut(input, { ...primary, primary: true });
3390
+ const restored = input.setup?.restored === true;
3391
+ const heads = [];
3392
+ const keyCommits = input.setup?.keyCommits ?? {};
3393
+ const first = await checkOut(input, { ...primary, primary: true }, restored);
3239
3394
  if (!first.ok) return first;
3240
3395
  startCommit = first.startCommit;
3241
- if (repositories.length > 1) {
3396
+ heads.push({ repository: primary.repository, head: first.head, startCommit: first.startCommit, keyCommit: keyCommits[primary.repository] });
3397
+ if (repositories.length > 1 && !restored) {
3242
3398
  const linkPath = repositoryPath(primary.repository);
3243
3399
  const linked = await exec(["sh", "-c", 'mkdir -p "$(dirname "$1")" && ln -s "$2" "$1"', "link", linkPath, CHECKOUT_DIR], "/build/work");
3244
3400
  if (linked.status !== 0) return { ok: false, reason: `linking ${primary.repository} at ${linkPath} failed (exit ${linked.status})` };
3245
3401
  }
3246
3402
  for (const entry of repositories.filter((candidate) => candidate.repository !== primary.repository)) {
3247
3403
  if (input.aborted()) return aborted();
3248
- const checked = await checkOut(input, { ...entry, primary: false });
3404
+ const checked = await checkOut(input, { ...entry, primary: false }, restored);
3249
3405
  if (!checked.ok) return checked;
3406
+ heads.push({ repository: entry.repository, head: checked.head, startCommit: checked.startCommit, keyCommit: keyCommits[entry.repository] });
3250
3407
  }
3251
3408
  if (input.governing !== void 0) await noteIgnoredDevcontainers(input, repositories, input.governing.repository);
3409
+ const ordered = [{ ...primary, primary: true }, ...repositories.filter((candidate) => candidate.repository !== primary.repository).map((entry) => ({ ...entry, primary: false }))];
3252
3410
  let unpinnedRuntimes;
3253
3411
  let miseVariables;
3254
3412
  if (input.runtimes !== void 0) {
3255
- const ordered = [{ ...primary, primary: true }, ...repositories.filter((candidate) => candidate.repository !== primary.repository).map((entry) => ({ ...entry, primary: false }))];
3256
3413
  const chosen = await provisionRuntimes({ repositories: ordered, exec, log, tag, refusals: input.runtimes.refusals, aborted: input.aborted });
3257
3414
  if (!chosen.ok) return chosen.aborted === true ? aborted() : { ok: false, reason: chosen.reason };
3258
3415
  unpinnedRuntimes = chosen.unpinned;
@@ -3267,6 +3424,25 @@ async function runBuildSteps(input) {
3267
3424
  if (ran.status !== 0) return { ok: false, reason: lifecycleFailureReason(step, ran.status) };
3268
3425
  }
3269
3426
  if (input.aborted()) return aborted();
3427
+ let missingSetupScripts;
3428
+ let savedState = false;
3429
+ if (input.setup !== void 0) {
3430
+ const { setup } = input;
3431
+ const ran = await runSetupScripts({ repositories: ordered, exec: commandExec, log, tag, timeoutMs: setup.timeoutMs, limitMinutes: setup.limitMinutes, aborted: input.aborted });
3432
+ if (!ran.ok) return ran.aborted === true ? aborted() : { ok: false, reason: ran.reason };
3433
+ missingSetupScripts = ran.missing;
3434
+ if (setup.saveState !== void 0 && setup.restored !== true && ran.ran.length > 0) {
3435
+ const notAtHead = checkoutNotAtDefaultHead(heads);
3436
+ if (notAtHead !== void 0) {
3437
+ log.line(`${tag} this build saves no state: ${notAtHead}`);
3438
+ } else {
3439
+ const saved = await setup.saveState();
3440
+ if (saved.ok) savedState = true;
3441
+ else log.line(`${tag} the build's state could not be saved: ${saved.reason}`);
3442
+ }
3443
+ }
3444
+ if (input.aborted()) return aborted();
3445
+ }
3270
3446
  const staged = await input.stageContext();
3271
3447
  if (staged.kind === "refused") return { ok: false, reason: staged.reason };
3272
3448
  let controlPlane;
@@ -3308,9 +3484,324 @@ async function runBuildSteps(input) {
3308
3484
  startCommit,
3309
3485
  ...controlPlane === void 0 ? {} : { controlPlane },
3310
3486
  ...unpinnedRuntimes === void 0 ? {} : { unpinnedRuntimes },
3487
+ ...missingSetupScripts === void 0 ? {} : { missingSetupScripts },
3488
+ ...savedState ? { savedState: true } : {},
3311
3489
  ...miseVariables === void 0 ? {} : { miseVariables }
3312
3490
  };
3313
3491
  }
3492
+ function savedStatesDir(runnerDirPath) {
3493
+ return join(runnerDirPath, "saved-states");
3494
+ }
3495
+ function writeRecord2(dir, record) {
3496
+ mkdirSync(dir, { recursive: true, mode: RUNNER_DIR_MODE });
3497
+ const target = join(dir, `${record.id}.json`);
3498
+ const partial = `${target}.partial`;
3499
+ writeFileSync(partial, `${JSON.stringify(record, null, 2)}
3500
+ `, { mode: RUNNER_FILE_MODE });
3501
+ renameSync(partial, target);
3502
+ }
3503
+ function isRecord(value) {
3504
+ if (typeof value !== "object" || value === null) return false;
3505
+ const r = value;
3506
+ return typeof r.id === "string" && (r.kind === "volume" || r.kind === "tar") && typeof r.savedAt === "string" && Number.isFinite(Date.parse(r.savedAt)) && typeof r.bytes === "number" && typeof r.baseKey === "string" && typeof r.key === "string" && typeof r.fileHashes === "object" && r.fileHashes !== null && typeof r.complete === "boolean";
3507
+ }
3508
+ function readRecords(dir) {
3509
+ let names;
3510
+ try {
3511
+ names = readdirSync(dir);
3512
+ } catch {
3513
+ return [];
3514
+ }
3515
+ const records = [];
3516
+ for (const name of names) {
3517
+ if (!name.endsWith(".json")) continue;
3518
+ try {
3519
+ const parsed = JSON.parse(readFileSync(join(dir, name), "utf8"));
3520
+ if (isRecord(parsed)) records.push(parsed);
3521
+ } catch {
3522
+ }
3523
+ }
3524
+ return records;
3525
+ }
3526
+ function deleteRecord(dir, id) {
3527
+ rmSync(join(dir, `${id}.json`), { force: true });
3528
+ }
3529
+
3530
+ // src/runner/saved-state/plan.ts
3531
+ function savedStateBase(report) {
3532
+ const digest = report.recipe === "default" ? report.base?.digest : void 0;
3533
+ return digest === void 0 ? void 0 : { digest };
3534
+ }
3535
+ function savedStateMaxOf(config) {
3536
+ return config.housekeeping?.savedStateMax ?? DEFAULT_SAVED_STATE_MAX_BYTES;
3537
+ }
3538
+ async function planSavedState(input) {
3539
+ const { config, runtime, log } = input;
3540
+ const refused2 = savingRefusedBecause({ universalImage: input.base !== void 0, managed: config.managed === true, savedStateMax: savedStateMaxOf(config) });
3541
+ if (refused2 !== void 0 || input.base === void 0) {
3542
+ const why = refused2 ?? "its image comes from a devcontainer file";
3543
+ log(`this build saves no state: ${why}`);
3544
+ return { keyCommits: {}, noSave: why };
3545
+ }
3546
+ const root = runnerDir(config.configPath);
3547
+ const repositories = [];
3548
+ const keyCommits = {};
3549
+ for (const entry of input.repositories) {
3550
+ let token;
3551
+ try {
3552
+ token = entry.primary ? await input.tokens.token("read") : await input.tokens.token("read", entry.repository);
3553
+ } catch (err) {
3554
+ return unread(`the read token for ${entry.repository} could not be had: ${describeCallFailure(err)}`, log);
3555
+ }
3556
+ const [owner = "", name = ""] = entry.repository.split("/");
3557
+ const read = await runtime.readKeyFiles({
3558
+ remote: runtime.remoteFor?.(entry.repository) ?? `${runtime.github.gitUrl}/${entry.repository}.git`,
3559
+ dir: join(root, "key-files", owner, name),
3560
+ paths: keyFilePaths(),
3561
+ token
3562
+ });
3563
+ if (!read.ok) return unread(read.reason, log);
3564
+ keyCommits[entry.repository] = read.commit;
3565
+ repositories.push({ repository: entry.repository, commit: read.commit, files: read.files });
3566
+ }
3567
+ const key = stateKey({
3568
+ factory: config.appId,
3569
+ repositories,
3570
+ imageDigest: input.base.digest,
3571
+ diskBytes: parseSize(config.build?.disk ?? DEFAULT_BUILD_DISK) ?? 0
3572
+ });
3573
+ const found = lookup2(readRecords(savedStatesDir(root)), key, input.now.getTime());
3574
+ if (found.kind === "usable" && input.allowRestore) {
3575
+ log(`starting from saved state ${found.record.id}, saved ${formatDuration(found.ageMs)} ago`);
3576
+ return { key, keyCommits, restore: { record: found.record, ageMs: found.ageMs } };
3577
+ }
3578
+ if (found.kind === "expired") {
3579
+ log(`saved state ${found.record.id} is ${formatDuration(found.ageMs)} old, past the limit of ${SAVED_STATE_MAX_AGE_MS / 864e5} days; starting from a fresh disk`);
3580
+ } else if (found.kind === "changed") {
3581
+ log(`the setup script or version files changed on the default branch since saved state ${found.record.id}: ${found.files.join(", ")}; starting from a fresh disk`);
3582
+ } else if (found.kind === "none") {
3583
+ log("no saved state matches this build's key; starting from a fresh disk");
3584
+ }
3585
+ return { key, keyCommits };
3586
+ }
3587
+ function unread(reason, log) {
3588
+ log(`this build starts from no saved state and saves none: ${reason}`);
3589
+ return { keyCommits: {}, noSave: `its key files could not be read: ${reason}` };
3590
+ }
3591
+ async function removeSavedState(record, deps) {
3592
+ if (record.kind === "volume" && record.volume !== void 0) {
3593
+ const result = await deps.removeVolume(record.volume);
3594
+ if (result !== void 0 && result.status !== 0) {
3595
+ const line2 = (result.stderr ?? "").trim().split("\n").filter((text) => text.trim() !== "").at(-1);
3596
+ throw new Error(`Docker could not remove volume ${record.volume} (exit ${result.status}${line2 === void 0 ? "" : `: ${line2}`})`);
3597
+ }
3598
+ }
3599
+ if (record.kind === "tar" && record.path !== void 0) {
3600
+ rmSync(`${record.path}.partial`, { force: true });
3601
+ rmSync(record.path, { force: true });
3602
+ }
3603
+ deleteRecord(deps.dir, record.id);
3604
+ }
3605
+ async function removeOldestUntil(input) {
3606
+ const removed = [];
3607
+ for (const record of oldestFirst(input.records)) {
3608
+ if (input.enough()) break;
3609
+ try {
3610
+ await removeSavedState(record, input.deps);
3611
+ removed.push(record);
3612
+ input.log(`removed saved state ${record.id} from ${record.savedAt}`);
3613
+ } catch (err) {
3614
+ input.log(`could not remove saved state ${record.id}: ${describeCallFailure(err)}`);
3615
+ }
3616
+ }
3617
+ return removed;
3618
+ }
3619
+ async function removeSuperseded(input) {
3620
+ for (const old of input.records.filter((record) => record.complete && record.key === input.made.key && record.id !== input.made.id && Date.parse(record.savedAt) < Date.parse(input.made.savedAt))) {
3621
+ try {
3622
+ await removeSavedState(old, input.deps);
3623
+ input.log(`removed saved state ${old.id}, saved state ${input.made.id} replaces it`);
3624
+ } catch (err) {
3625
+ input.log(`could not remove saved state ${old.id}: ${describeCallFailure(err)}`);
3626
+ }
3627
+ }
3628
+ }
3629
+
3630
+ // src/runner/saved-state/provision.ts
3631
+ var isRetryFresh = (value) => typeof value === "object" && value !== null && "retryFresh" in value;
3632
+ async function provisionWithFreshFallback(input) {
3633
+ const first = await input.attempt(true);
3634
+ if (!isRetryFresh(first)) return first;
3635
+ input.log(`${first.reason}; provisioning the build again from a fresh disk`);
3636
+ return await input.attempt(false);
3637
+ }
3638
+ function clockOf(now) {
3639
+ return now ?? (() => /* @__PURE__ */ new Date());
3640
+ }
3641
+ function taggedLog(log, tag) {
3642
+ return (line2) => log.line(`${tag} ${line2}`);
3643
+ }
3644
+ function uidFromProbe(probe) {
3645
+ const uid = Number(probe.stdout);
3646
+ return probe.status === 0 && Number.isInteger(uid) ? uid : null;
3647
+ }
3648
+ function agentUidOf(probe) {
3649
+ return uidFromProbe(probe) ?? void 0;
3650
+ }
3651
+ function userIdChangedReason(savedUid, agentUid) {
3652
+ if (savedUid === void 0 || agentUid === savedUid) return void 0;
3653
+ return `the build user's id is ${agentUid ?? "unknown"} and it was ${savedUid} when the state was saved`;
3654
+ }
3655
+ function setupInputFor(input) {
3656
+ const minutes = input.setupMinutes ?? DEFAULT_SETUP_MINUTES;
3657
+ return {
3658
+ timeoutMs: minutes * 6e4,
3659
+ limitMinutes: minutes,
3660
+ restored: input.plan.restore !== void 0,
3661
+ keyCommits: input.plan.keyCommits,
3662
+ // A plan has a key exactly when the build may save a state. A build that starts from one is not asked to save.
3663
+ ...input.plan.key === void 0 ? {} : { saveState: input.saveState }
3664
+ };
3665
+ }
3666
+ async function saveAndPrune(input) {
3667
+ const made = await input.save();
3668
+ if (!made.ok) return made;
3669
+ input.log(`saved state ${made.record.id}`);
3670
+ await removeSuperseded({ made: made.record, records: readRecords(input.dir), deps: { dir: input.dir, removeVolume: input.removeVolume }, log: input.log });
3671
+ return { ok: true };
3672
+ }
3673
+ async function discardUnusableState(input) {
3674
+ try {
3675
+ await removeSavedState(input.record, { dir: input.dir, removeVolume: input.removeVolume });
3676
+ } catch (err) {
3677
+ input.onError(`could not remove saved state ${input.record.id}: ${describeCallFailure(err)}`);
3678
+ }
3679
+ return { retryFresh: true, reason: `saved state ${input.record.id} could not be used: ${input.reason}` };
3680
+ }
3681
+ function settleFailedSteps(steps, on) {
3682
+ return steps.restoreFailed === true ? on.giveUp(steps.reason) : on.bail(steps.reason, steps.aborted === true);
3683
+ }
3684
+ var SAVED_FOLDERS = ["home", "work"];
3685
+ function stopProcessesScript() {
3686
+ return [
3687
+ "me=$$; uid=$(id -u); n=0; pass=0",
3688
+ "while [ $pass -lt 25 ]; do",
3689
+ ' left=""',
3690
+ " for p in /proc/[0-9]*; do",
3691
+ " pid=${p##*/}",
3692
+ ' [ "$pid" = "$me" ] && continue',
3693
+ ` info=$(sed -n -e 's/^State:[[:space:]]*\\(.\\).*/S=\\1/p' -e 's/^Uid:[[:space:]]*\\([0-9]*\\).*/U=\\1/p' "$p/status" 2>/dev/null) || continue`,
3694
+ ' case "$info" in *"S=Z"*) continue ;; esac',
3695
+ // The uid is the last line of `info`, so a match at its end cannot be the longer id 10000 for 1000.
3696
+ ' case "$info" in *"U=$uid") left="$left $pid" ;; esac',
3697
+ " done",
3698
+ ' [ -z "$left" ] && break',
3699
+ ' for pid in $left; do kill -KILL "$pid" 2>/dev/null && n=$((n+1)); done',
3700
+ " pass=$((pass+1))",
3701
+ " sleep 0.2",
3702
+ "done",
3703
+ '[ -z "$left" ] || { echo "$left are still running" >&2; exit 1; }',
3704
+ 'echo "stopped $n"'
3705
+ ].join("\n");
3706
+ }
3707
+ var HELPER_FLAGS = [
3708
+ "--rm",
3709
+ "--network",
3710
+ "none",
3711
+ "--cap-drop",
3712
+ "ALL",
3713
+ "--cap-add",
3714
+ "CHOWN",
3715
+ "--cap-add",
3716
+ "DAC_OVERRIDE",
3717
+ "--cap-add",
3718
+ "DAC_READ_SEARCH",
3719
+ "--cap-add",
3720
+ "FOWNER",
3721
+ "--security-opt",
3722
+ "no-new-privileges",
3723
+ "--read-only",
3724
+ "--user",
3725
+ "0",
3726
+ "--pids-limit",
3727
+ "256"
3728
+ ];
3729
+ function helperArgs(input) {
3730
+ return [
3731
+ ...HELPER_FLAGS,
3732
+ "--label",
3733
+ `${RUNNER_LABEL}=${input.runnerId}`,
3734
+ "--mount",
3735
+ `type=volume,src=${input.from},dst=/from,readonly`,
3736
+ "--mount",
3737
+ `type=volume,src=${input.to},dst=/to`,
3738
+ "--entrypoint",
3739
+ "sh",
3740
+ input.image,
3741
+ "-c",
3742
+ input.script
3743
+ ];
3744
+ }
3745
+ var SAVE_SCRIPT = `set -e; cp -a ${SAVED_FOLDERS.map((name) => `/from/${name}`).join(" ")} /to/; du -sk /to | cut -f1`;
3746
+ var RESTORE_SCRIPT = `set -e; cp -a ${SAVED_FOLDERS.map((name) => `/from/${name}`).join(" ")} /to/`;
3747
+ function failureText(result) {
3748
+ const line2 = result.stderr.trim().split("\n").at(-1) ?? "";
3749
+ return `exit ${result.status}${line2 === "" ? "" : `: ${line2}`}`;
3750
+ }
3751
+ async function saveContainerState(input) {
3752
+ const { host } = input;
3753
+ const id = randomBytes(6).toString("hex");
3754
+ const volume = `outerlayer-saved-${id}`;
3755
+ const record = {
3756
+ id,
3757
+ kind: "volume",
3758
+ volume,
3759
+ savedAt: input.now.toISOString(),
3760
+ bytes: 0,
3761
+ baseKey: input.key.baseKey,
3762
+ key: input.key.key,
3763
+ fileHashes: input.key.fileHashes,
3764
+ ...input.agentUid === void 0 ? {} : { agentUid: input.agentUid },
3765
+ complete: false
3766
+ };
3767
+ const discard = async (reason) => {
3768
+ const removed = await host.removeVolume(volume).catch((err) => ({ status: -1, stderr: describeCallFailure(err) }));
3769
+ if (removed.status !== 0) {
3770
+ input.log(`the volume ${volume} could not be removed (${failureText({ status: removed.status, stderr: removed.stderr })}); its record stays so a later pass retries`);
3771
+ return { ok: false, reason };
3772
+ }
3773
+ deleteRecord(input.dir, id);
3774
+ return { ok: false, reason };
3775
+ };
3776
+ try {
3777
+ const noEnv = { literals: {}, passed: {} };
3778
+ const stopped = await host.exec({ container: input.container, user: input.agentUser, env: noEnv, argv: ["sh", "-c", stopProcessesScript()] });
3779
+ if (stopped.status !== 0) return { ok: false, reason: `the build's processes could not be stopped (${failureText(stopped)})` };
3780
+ input.log(`${stopped.stdout.trim() || "stopped 0"} process${stopped.stdout.trim() === "stopped 1" ? "" : "es"} before saving the state`);
3781
+ const flushed = await host.exec({ container: input.container, user: input.agentUser, env: noEnv, argv: ["sync"] });
3782
+ if (flushed.status !== 0) return { ok: false, reason: `the build's disk could not be flushed (${failureText(flushed)})` };
3783
+ writeRecord2(input.dir, record);
3784
+ const created = await host.createVolume(volume, { [SAVED_STATE_LABEL]: id, [RUNNER_LABEL]: input.runnerId });
3785
+ if (created.status !== 0) return await discard(`the volume for the saved state could not be made (${failureText(created)})`);
3786
+ const copied = await host.run(helperArgs({ image: input.image, from: input.buildVolume, to: volume, script: SAVE_SCRIPT, runnerId: input.runnerId }), { logPath: input.logPath });
3787
+ if (copied.status !== 0) return await discard(`the copy into the saved state failed (${failureText(copied)})`);
3788
+ const kilobytes = Number(copied.stdout.trim().split("\n").at(-1));
3789
+ const done = { ...record, bytes: Number.isFinite(kilobytes) ? kilobytes * 1024 : 0, complete: true };
3790
+ writeRecord2(input.dir, done);
3791
+ return { ok: true, record: done };
3792
+ } catch (err) {
3793
+ return await discard(`the state could not be saved: ${describeCallFailure(err)}`);
3794
+ }
3795
+ }
3796
+ async function restoreContainerState(input) {
3797
+ try {
3798
+ const copied = await input.host.run(helperArgs({ image: input.image, from: input.savedVolume, to: input.targetVolume, script: RESTORE_SCRIPT, runnerId: input.runnerId }), { logPath: input.logPath });
3799
+ if (copied.status !== 0) return { ok: false, reason: `the saved volume could not be copied (${failureText(copied)})` };
3800
+ return { ok: true };
3801
+ } catch (err) {
3802
+ return { ok: false, reason: `the saved volume could not be copied: ${describeCallFailure(err)}` };
3803
+ }
3804
+ }
3314
3805
  var EVAL_INPUT_NAME = "eval-input";
3315
3806
  var TRANSCRIPT_ROOT = "/build/home/.claude/projects";
3316
3807
  var MAX_TRANSCRIPT_BYTES = 7 * 1024 * 1024;
@@ -4601,6 +5092,7 @@ function createContainerRuntime(opts = {}) {
4601
5092
  github: { gitUrl: opts.github?.gitUrl ?? "https://github.com", apiUrl: opts.github?.apiUrl ?? "https://api.github.com" },
4602
5093
  remoteFor,
4603
5094
  readHead: opts.readHead ?? readDefaultBranchHead,
5095
+ readKeyFiles: opts.readKeyFiles ?? readDefaultBranchFiles,
4604
5096
  clone: opts.clone ?? ((input) => cloneRepository(input.remote, input.dest)),
4605
5097
  destinationOptions: opts.destinationOptions,
4606
5098
  claudeUpstream: opts.claudeUpstream,
@@ -4763,6 +5255,12 @@ async function controlPlaneReadToken(tokens, controlPlane) {
4763
5255
  }
4764
5256
  }
4765
5257
  async function provisionContainer(input) {
5258
+ return provisionWithFreshFallback({
5259
+ attempt: (allowRestore) => provisionContainerOnce(input, allowRestore),
5260
+ log: (line2) => input.log.line(`#${input.item.number} ${line2}`)
5261
+ });
5262
+ }
5263
+ async function provisionContainerOnce(input, allowRestore) {
4766
5264
  const { config, runtime, item, itemKey, jobDir, log, tokens } = input;
4767
5265
  const { host } = runtime;
4768
5266
  const tag = `#${item.number}`;
@@ -4821,6 +5319,18 @@ async function provisionContainer(input) {
4821
5319
  if (!obtained.ok) return obtained.aborted === true ? { ok: false, reason: obtained.reason, aborted: true } : fail(obtained.reason);
4822
5320
  const built = obtained.built;
4823
5321
  const { report } = built;
5322
+ const tagged = taggedLog(log, tag);
5323
+ const plan = await planSavedState({
5324
+ config,
5325
+ repositories,
5326
+ base: savedStateBase(report),
5327
+ runtime,
5328
+ tokens,
5329
+ now: clockOf(input.now)(),
5330
+ allowRestore,
5331
+ log: tagged
5332
+ });
5333
+ const savedStatesPath = savedStatesDir(runnerDir(config.configPath));
4824
5334
  const buildId = randomBytes(6).toString("hex");
4825
5335
  const name = `outerlayer-build-${buildId}`;
4826
5336
  const buildDir2 = buildDir(config.configPath, buildId);
@@ -4877,6 +5387,16 @@ async function provisionContainer(input) {
4877
5387
  return aborted2 ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(reason);
4878
5388
  };
4879
5389
  const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${said(result.stderr)}`);
5390
+ const giveUpState = async (reason) => {
5391
+ await bail(reason);
5392
+ return discardUnusableState({
5393
+ record: plan.restore.record,
5394
+ reason,
5395
+ dir: savedStatesPath,
5396
+ removeVolume: (volume2) => host.removeVolume(volume2),
5397
+ onError: (line2) => log.error(`${tag} ${line2}`)
5398
+ });
5399
+ };
4880
5400
  if (input.aborted()) return bail("", true);
4881
5401
  mkdirSync(buildDir2, { recursive: true });
4882
5402
  const ghDir = ghConfigDir(buildDir2);
@@ -4928,6 +5448,10 @@ async function provisionContainer(input) {
4928
5448
  };
4929
5449
  const prepared = await host.run(prepareRunArgs(runInput), { logPath });
4930
5450
  if (prepared.status !== 0) return dockerFailed("preparing the build's volume", prepared);
5451
+ if (plan.restore !== void 0) {
5452
+ const restored = await restoreContainerState({ host, image: report.imageId, savedVolume: plan.restore.record.volume, targetVolume: name, runnerId, logPath });
5453
+ if (!restored.ok) return giveUpState(restored.reason);
5454
+ }
4931
5455
  const imageConfig = await host.imageConfig(report.imageId);
4932
5456
  const resolved = await resolveBuildUser(runtime, runInput, { remoteUser: report.apply.remoteUser, imageUser: imageConfig.user }, logPath);
4933
5457
  if (!resolved.ok) return bail(resolved.reason);
@@ -4953,6 +5477,10 @@ async function provisionContainer(input) {
4953
5477
  delivered: readToken,
4954
5478
  onFailure: (reason) => log.error(`${tag} ${reason}`)
4955
5479
  });
5480
+ const agentUidProbe = await host.exec({ container: name, user: ADDED_USER, env: NO_ENV, argv: ["id", "-u", agentUser] });
5481
+ const agentUid = agentUidOf(agentUidProbe);
5482
+ const changed = userIdChangedReason(plan.restore?.record.agentUid, agentUid);
5483
+ if (changed !== void 0) return giveUpState(changed);
4956
5484
  const tools = await host.exec({ container: name, user: ADDED_USER, env: NO_ENV, argv: ["cat", "/opt/outerlayer/tools.json"] });
4957
5485
  const agentVersion = agentVersionOf(tools.status === 0 ? tools.stdout : "");
4958
5486
  environment.agentVersion = agentVersion;
@@ -4960,7 +5488,29 @@ async function provisionContainer(input) {
4960
5488
  const hashed = program.status === 0 ? parseProgramHash(program.stdout) : void 0;
4961
5489
  if (hashed !== void 0) state.judgeProgram = { path: JUDGE_PROGRAM, sha256: hashed };
4962
5490
  input.save(state, environment);
4963
- const exec = (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env: withMiseVariables(env, opts?.variables), argv }, opts?.quiet === true ? void 0 : { logPath });
5491
+ const exec = async (argv, workdir, opts) => {
5492
+ const ran = await host.exec({ container: name, user: agentUser, workdir, env: withMiseVariables(env, opts?.variables), argv }, { ...opts?.quiet === true ? {} : { logPath }, ...opts?.timeoutMs === void 0 ? {} : { timeoutMs: opts.timeoutMs } });
5493
+ return endedAtLimit(ran) ? { ...ran, timedOut: true } : ran;
5494
+ };
5495
+ const saveState = () => saveAndPrune({
5496
+ save: () => saveContainerState({
5497
+ host,
5498
+ image: report.imageId,
5499
+ container: name,
5500
+ agentUser,
5501
+ agentUid,
5502
+ buildVolume: name,
5503
+ runnerId,
5504
+ dir: savedStatesPath,
5505
+ key: plan.key,
5506
+ now: clockOf(input.now)(),
5507
+ logPath,
5508
+ log: tagged
5509
+ }),
5510
+ dir: savedStatesPath,
5511
+ removeVolume: (volume2) => host.removeVolume(volume2),
5512
+ log: tagged
5513
+ });
4964
5514
  const steps = await runBuildSteps({
4965
5515
  repository,
4966
5516
  branch: primary.branch,
@@ -4992,18 +5542,23 @@ async function provisionContainer(input) {
4992
5542
  removeStagedContext: () => removeStagedContext(buildDir2),
4993
5543
  keepIn: jobDir,
4994
5544
  ...input.requireBuildSkill === true ? { requireBuildSkill: true } : {},
4995
- // A repository with no devcontainer file builds on the universal image, whose runtimes the build chooses and installs.
4996
- ...runtimeStepInput(report, services)
5545
+ // A build on the universal image, or on an image built from it, chooses and installs its runtimes.
5546
+ ...runtimeStepInput(report, services),
5547
+ setup: setupInputFor({ setupMinutes: config.build?.setupMinutes, plan, saveState })
4997
5548
  });
4998
- if (!steps.ok) return bail(steps.reason, steps.aborted === true);
5549
+ if (!steps.ok) return settleFailedSteps(steps, { giveUp: giveUpState, bail });
4999
5550
  state.startCommit = steps.startCommit;
5000
5551
  keepRuntimeStep(state, steps);
5552
+ keepMissingSetupScripts(state, steps);
5001
5553
  if (steps.controlPlane !== void 0) environment.controlPlane = steps.controlPlane;
5002
5554
  return { ok: true, workdir: CHECKOUT_DIR, state, environment };
5003
5555
  }
5556
+ function endedAtLimit(result) {
5557
+ return result.status === 124 && /no answer within \d+s/.test(result.stderr);
5558
+ }
5004
5559
  async function resolveBuildUser(runtime, runInput, named, logPath) {
5005
5560
  const lookups = /* @__PURE__ */ new Map();
5006
- const lookup2 = async (user2) => {
5561
+ const lookup3 = async (user2) => {
5007
5562
  const known = lookups.get(user2);
5008
5563
  if (known !== void 0) return known;
5009
5564
  const ran = await runtime.host.run(identityRunArgs({ ...runInput, user: ADDED_USER }, user2));
@@ -5017,8 +5572,8 @@ async function resolveBuildUser(runtime, runInput, named, logPath) {
5017
5572
  let user;
5018
5573
  let home;
5019
5574
  try {
5020
- user = await resolveAgentUser({ ...named, probe: async (name) => (await lookup2(name))?.uid ?? null });
5021
- home = user === ADDED_USER ? void 0 : mountableHome((await lookup2(user))?.home);
5575
+ user = await resolveAgentUser({ ...named, probe: async (name) => (await lookup3(name))?.uid ?? null });
5576
+ home = user === ADDED_USER ? void 0 : mountableHome((await lookup3(user))?.home);
5022
5577
  } catch (err) {
5023
5578
  if (err instanceof AgentUserError) return { ok: false, reason: err.message };
5024
5579
  throw err;
@@ -5055,6 +5610,7 @@ function containerCommandExec(input) {
5055
5610
  hostEnv: input.runtime.hostEnv,
5056
5611
  containerEnv: state.containerEnv ?? {},
5057
5612
  unpinnedRuntimes: state.unpinnedRuntimes,
5613
+ missingSetupScripts: state.missingSetupScripts,
5058
5614
  miseVariables: state.miseVariables,
5059
5615
  builtIns: state.builtIns === true,
5060
5616
  identity: input.job.commitIdentity
@@ -5080,6 +5636,7 @@ function containerSenderCommand(input) {
5080
5636
  hostEnv: input.runtime.hostEnv,
5081
5637
  containerEnv: state.containerEnv ?? {},
5082
5638
  unpinnedRuntimes: state.unpinnedRuntimes,
5639
+ missingSetupScripts: state.missingSetupScripts,
5083
5640
  miseVariables: state.miseVariables,
5084
5641
  builtIns: state.builtIns === true,
5085
5642
  identity: input.job.commitIdentity
@@ -5220,6 +5777,7 @@ async function runCliInContainer(input, argv, logName) {
5220
5777
  hostEnv: runtime.hostEnv,
5221
5778
  containerEnv: state.containerEnv ?? {},
5222
5779
  unpinnedRuntimes: state.unpinnedRuntimes,
5780
+ missingSetupScripts: state.missingSetupScripts,
5223
5781
  miseVariables: state.miseVariables,
5224
5782
  builtIns: state.builtIns === true,
5225
5783
  identity: job.commitIdentity
@@ -5321,8 +5879,8 @@ function containerJudgeEnvironment(input) {
5321
5879
  },
5322
5880
  hashProgram: async () => {
5323
5881
  const ran = await runtime.host.exec({ container: state.container, user: ADDED_USER, env: NO_ENV, argv: [...HASH_ARGV] });
5324
- const sha256 = ran.status === 0 ? parseProgramHash(ran.stdout) : void 0;
5325
- return sha256 === void 0 ? { ok: false, reason: firstLine4(ran.stderr) || `the hash could not be taken (exit ${ran.status})` } : { ok: true, sha256 };
5882
+ const sha2562 = ran.status === 0 ? parseProgramHash(ran.stdout) : void 0;
5883
+ return sha2562 === void 0 ? { ok: false, reason: firstLine4(ran.stderr) || `the hash could not be taken (exit ${ran.status})` } : { ok: true, sha256: sha2562 };
5326
5884
  },
5327
5885
  prepare: async (files, tree) => {
5328
5886
  if (filesAreCopied(state)) {
@@ -5605,4 +6163,4 @@ function describeMachineDocker(machine) {
5605
6163
  return `Docker Engine ${version ?? "of no known version"}, older than the ${MIN_ENGINE_MAJOR} that container builds need`;
5606
6164
  }
5607
6165
 
5608
- export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, PROOFS_LOG, RECORD_PROOFS_ARGV, ROOT_DISK_ID_PREFIX, RunnerInitError, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureNetworkReady, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, firstLine4 as firstLine, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, keepRuntimeStep, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, provisionRuntimes, ranRuntimeStep, reachDockerStep, readConfigObject, recordProofsInContainer, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, runtimeStepInput, said, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, stoppedHelperReason, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, withFactoryHosts, withTunnelLog, writeEvalInput, writeRunnerInit };
6166
+ export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, PROOFS_LOG, RECORD_PROOFS_ARGV, ROOT_DISK_ID_PREFIX, RunnerInitError, agentUidOf, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, clockOf, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deleteRecord, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, discardUnusableState, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureNetworkReady, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, firstLine4 as firstLine, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, keepMissingSetupScripts, keepRuntimeStep, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, planSavedState, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, provisionRuntimes, provisionWithFreshFallback, ranRuntimeStep, reachDockerStep, readConfigObject, readRecords, recordProofsInContainer, removeOldestUntil, removeSavedState, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, runtimeStepInput, said, saveAndPrune, savedStateBase, savedStatesDir, selectExpired, selectStaleIncomplete, selectToFit, senderAliveScript, senderSignalScript, setUpRunnerCgroup, settleFailedSteps, setupInputFor, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, stoppedHelperReason, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, taggedLog, uidFromProbe, userIdChangedReason, withFactoryHosts, withTunnelLog, writeEvalInput, writeRecord2 as writeRecord, writeRunnerInit };