@outerlayer/cli 0.24.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +9 -0
  3. package/dist/{agent-setup-QQYRBPK2.js → agent-setup-PDIIGMKE.js} +7 -7
  4. package/dist/{bridge-4ZARDVGS.js → bridge-5KZ36YDG.js} +3 -3
  5. package/dist/build-YYVAJ75G.js +12 -0
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-MECDEKXX.js → builder-MNUJS4RG.js} +7 -7
  8. package/dist/{check-YYKNYFNI.js → check-C6HEFW6R.js} +39 -38
  9. package/dist/{chunk-BUBCPP3F.js → chunk-23SPSYXZ.js} +3 -3
  10. package/dist/{chunk-5ECUMU53.js → chunk-24LQ34XL.js} +6 -6
  11. package/dist/{chunk-BN3CSI7S.js → chunk-2K3TCQHW.js} +1 -1
  12. package/dist/{chunk-A62QFN2M.js → chunk-2N72GPS2.js} +3 -3
  13. package/dist/{chunk-TQ6Y7YV6.js → chunk-3FNPTQRH.js} +5 -5
  14. package/dist/{chunk-F2W2IYNP.js → chunk-3WZ5ECSM.js} +3 -3
  15. package/dist/{chunk-WH2QV3UL.js → chunk-4S4VBDSO.js} +1 -1
  16. package/dist/{chunk-IDSHLKQA.js → chunk-5222PA6S.js} +1 -1
  17. package/dist/{chunk-6GSA2SKT.js → chunk-A6ORKBVJ.js} +213 -59
  18. package/dist/{chunk-3W333NFO.js → chunk-APBTVIM4.js} +15 -4
  19. package/dist/{chunk-HHXBOTRO.js → chunk-ATGHVEU4.js} +1 -1
  20. package/dist/{chunk-D7K446H6.js → chunk-C36EOUUU.js} +5 -5
  21. package/dist/{chunk-RVYOOYOA.js → chunk-CQRIZNE6.js} +19 -10
  22. package/dist/{chunk-FWEWFW3F.js → chunk-DEBOL6ON.js} +1 -1
  23. package/dist/{chunk-GU4PKXN7.js → chunk-ENFBARQP.js} +185 -38
  24. package/dist/{chunk-H6IUKXXI.js → chunk-F57CLUH7.js} +207 -35
  25. package/dist/{chunk-E4OUL7ZP.js → chunk-FXUVXSY2.js} +2 -2
  26. package/dist/{chunk-F7Y2USIM.js → chunk-H6ZFLIX3.js} +3 -3
  27. package/dist/{chunk-LY2L3O2O.js → chunk-HPOEVC2V.js} +3 -2
  28. package/dist/{chunk-ZFLOFAUG.js → chunk-I25F6YVP.js} +8 -8
  29. package/dist/{chunk-DG2ULWM6.js → chunk-IGRRD7PX.js} +11 -7
  30. package/dist/{chunk-GISNHSYL.js → chunk-JGD5TWQ2.js} +4 -2
  31. package/dist/{chunk-D7X5ITVT.js → chunk-JWRX5ZTT.js} +6 -2
  32. package/dist/{chunk-755WXDBI.js → chunk-K5WVK7IC.js} +1 -1
  33. package/dist/{chunk-FKXGQOF5.js → chunk-M4B6QKNZ.js} +1 -1
  34. package/dist/{chunk-5XCAPBE2.js → chunk-N3VSI5ZI.js} +6 -6
  35. package/dist/{chunk-NTQTDCYR.js → chunk-O2WYUIK7.js} +1 -1
  36. package/dist/{chunk-BOQY756V.js → chunk-OEU4JSDE.js} +8 -7
  37. package/dist/{chunk-TTLVQZSH.js → chunk-Q435LWVN.js} +5 -5
  38. package/dist/{chunk-D4AMAEZ7.js → chunk-QE3UQAHK.js} +322 -17
  39. package/dist/{chunk-VV7ZD5LR.js → chunk-QMQC6JCO.js} +1 -1
  40. package/dist/{chunk-FQPN5S4Q.js → chunk-QXNJWSTM.js} +4 -4
  41. package/dist/{chunk-VBEXKEBV.js → chunk-S6AWZKJN.js} +19 -6
  42. package/dist/{chunk-V5Q3S4NM.js → chunk-SNQR2EYI.js} +2 -2
  43. package/dist/{chunk-CZUH2SLQ.js → chunk-UNF7MWEL.js} +1 -1
  44. package/dist/{chunk-W7O4LA4E.js → chunk-VAMUWK55.js} +3 -3
  45. package/dist/{chunk-PDIM5T65.js → chunk-XGJUNNXL.js} +1 -1
  46. package/dist/{chunk-NGZID7UI.js → chunk-XRYUJTAT.js} +8 -1
  47. package/dist/{chunk-LBCZXXOX.js → chunk-ZGMQQWCV.js} +2 -2
  48. package/dist/{chunk-KF37SUDM.js → chunk-ZI2ZVWKT.js} +1 -1
  49. package/dist/{chunk-PVRBE7S4.js → chunk-ZODVSFI4.js} +1 -1
  50. package/dist/chunk-ZVB57WI6.js +19 -0
  51. package/dist/{claude-launcher-JCPSHDZQ.js → claude-launcher-WGOCLTG6.js} +1 -1
  52. package/dist/{cli-ZTBH3FBG.js → cli-YMTNHR4W.js} +107 -102
  53. package/dist/command-DKYZC7PH.js +533 -0
  54. package/dist/{config-7Z5DHSGY.js → config-JJ3EO7SB.js} +3 -3
  55. package/dist/{connect-cmd-NY5LIKVC.js → connect-cmd-F7T4LNKX.js} +7 -7
  56. package/dist/{container-start-OHBUZEJJ.js → container-start-AX7QXJMR.js} +45 -36
  57. package/dist/{control-plane-launch-GKGI6HJA.js → control-plane-launch-ZFT6SI4N.js} +6 -6
  58. package/dist/{dist-2APO44JG.js → dist-QPHZE47F.js} +1 -1
  59. package/dist/{docker-RKGBJESN.js → docker-5EC5TE3Y.js} +7 -7
  60. package/dist/{doctor-DOAFZV4O.js → doctor-S6YCZGUU.js} +79 -33
  61. package/dist/{emit-artifact-cmd-VZHIDPXQ.js → emit-artifact-cmd-DJO475VZ.js} +11 -11
  62. package/dist/{emit-criteria-cmd-SYLBCWHW.js → emit-criteria-cmd-EULQ2MLI.js} +8 -8
  63. package/dist/{emit-finding-cmd-52M43NPC.js → emit-finding-cmd-QIIKMITO.js} +8 -8
  64. package/dist/{emit-result-cmd-BTMTGDAV.js → emit-result-cmd-NMCLTA47.js} +11 -11
  65. package/dist/{emit-step-cmd-6XTJITZT.js → emit-step-cmd-72OX5P6M.js} +9 -9
  66. package/dist/{exec-client-CKPK62K2.js → exec-client-KH33DICR.js} +4 -4
  67. package/dist/{governing-source-GWN7GVEN.js → governing-source-JNQ6PX2A.js} +11 -11
  68. package/dist/{guest-init-ZBL5CN7Y.js → guest-init-TOSKPGPF.js} +5 -5
  69. package/dist/{hook-fast-3JL4PXLG.js → hook-fast-NEELST6G.js} +1 -1
  70. package/dist/host-key-ICJEQBWH.js +9 -0
  71. package/dist/{image-tag-AO4RBAKW.js → image-tag-6KJOGBQK.js} +4 -4
  72. package/dist/index.js +4 -4
  73. package/dist/{init-TSQ3EOQW.js → init-624F4JIP.js} +25 -23
  74. package/dist/{init-EQTR7AEF.js → init-G7XC5WWL.js} +25 -23
  75. package/dist/{init-cmd-AF2MH36A.js → init-cmd-UUYA57VO.js} +11 -11
  76. package/dist/{init-update-SHISHMXV.js → init-update-MMV33PLM.js} +9 -9
  77. package/dist/{install-ORQC26ZE.js → install-MPEJJ7X6.js} +5 -5
  78. package/dist/{install-cmd-4LA3UJZ4.js → install-cmd-SE6NCTJK.js} +6 -6
  79. package/dist/job-state-format-WJQGQB6F.js +6 -0
  80. package/dist/{logs-5EPHIPZB.js → logs-T4ERSOQ4.js} +3 -3
  81. package/dist/loop-K5B2A3VW.js +78 -0
  82. package/dist/{machine-6UNLIPLE.js → machine-J4IFVIKU.js} +21 -19
  83. package/dist/{mcp-serve-cmd-KMWEKM7C.js → mcp-serve-cmd-7M4VLNI4.js} +5 -5
  84. package/dist/{paths-XY5ADO32.js → paths-2KGM2LZV.js} +3 -3
  85. package/dist/pending-BGLMTB5Q.js +9 -0
  86. package/dist/{pidfile-OJ7RP4Q2.js → pidfile-VYBH3IMN.js} +4 -4
  87. package/dist/{record-BEJB4J7N.js → record-GNOHDJ2O.js} +4 -4
  88. package/dist/{relay-PSZ4LGMW.js → relay-GFPPD6GF.js} +1 -1
  89. package/dist/relay-protocol-HELO5SNH.js +6 -0
  90. package/dist/{runner-env-ZJWJOJKQ.js → runner-env-GUFV544G.js} +6 -6
  91. package/dist/{runner-identity-2OOUJSFJ.js → runner-identity-HZ6CBM2R.js} +7 -7
  92. package/dist/{runner-key-WDFBSJRX.js → runner-key-FFVZUEHE.js} +25 -23
  93. package/dist/{session-sender-X3BBQZMF.js → session-sender-3SUWNNVP.js} +12 -12
  94. package/dist/{spec-cmd-QRF5YXKK.js → spec-cmd-VZDE6FFH.js} +9 -9
  95. package/dist/{status-ZCAAF6MD.js → status-GXTD44DX.js} +35 -29
  96. package/dist/{sync-cmd-UQK3RYAC.js → sync-cmd-VFB3NEJ6.js} +11 -11
  97. package/dist/{watch-MOQ3GQTE.js → watch-LWMTDD3L.js} +11 -11
  98. package/dist/{work-claim-cmd-RT343CLA.js → work-claim-cmd-FOBTDQVR.js} +12 -12
  99. package/dist/{work-cmd-APXSER2D.js → work-cmd-6HARIBMW.js} +9 -9
  100. package/dist/{work-comment-cmd-AT5NUYUU.js → work-comment-cmd-BITPALHR.js} +9 -9
  101. package/dist/{work-logs-cmd-Z5DMNEJP.js → work-logs-cmd-VGB3O2LZ.js} +9 -9
  102. package/dist/{work-open-pr-cmd-ZTS6MJHL.js → work-open-pr-cmd-SVZCNOIM.js} +10 -10
  103. package/dist/{work-pr-cmd-IWZCC3WH.js → work-pr-cmd-SJT46GN4.js} +9 -9
  104. package/dist/{work-stop-cmd-DCAWFDZC.js → work-stop-cmd-WXKVVA4S.js} +9 -9
  105. package/package.json +2 -2
  106. package/skill-pack/maintained/outerlayer-build/SKILL.md +1 -1
  107. package/skill-pack/maintained/outerlayer-build/references/agent-briefs.md +3 -2
  108. package/skill-pack/maintained/outerlayer-build/references/review-briefs.md +3 -1
  109. package/dist/build-OVZIT2G2.js +0 -12
  110. package/dist/command-DO4TERRT.js +0 -208
  111. package/dist/host-key-W2DLZGZ7.js +0 -9
  112. package/dist/loop-4WUCS5JP.js +0 -77
  113. package/dist/pending-35J3ZPLR.js +0 -9
  114. package/dist/relay-protocol-K7KP2SPI.js +0 -6
@@ -1,32 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { senderPidfile } from './chunk-W7O4LA4E.js';
4
- import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-A62QFN2M.js';
5
- import { writeDockerClientConfig } from './chunk-CZUH2SLQ.js';
6
- import { installScrubContext } from './chunk-D7K446H6.js';
7
- import { ADDED_USER, AssetError, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, resolveAgentUser, AgentUserError, runBuildSteps, shellQuote, LEASE_SECONDS, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, signalInContainer, syncInContainer, copyTranscriptsFromContainer, senderAliveScript, GH_CONFIG_YML, ghHostsYml, isLiteralAddress, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, copyJudgeTree } from './chunk-GU4PKXN7.js';
8
- import { readBranchHead, fetchCommit, diffBetween } from './chunk-TTLVQZSH.js';
3
+ import { readsJobState, READ_JOB_STATE_FORMATS, jobStateFormatOf } from './chunk-ZVB57WI6.js';
4
+ import { senderPidfile } from './chunk-VAMUWK55.js';
5
+ import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-2N72GPS2.js';
6
+ import { writeDockerClientConfig } from './chunk-UNF7MWEL.js';
7
+ import { installScrubContext } from './chunk-C36EOUUU.js';
8
+ import { ADDED_USER, AssetError, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, resolveAgentUser, AgentUserError, runBuildSteps, shellQuote, LEASE_SECONDS, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, signalInContainer, syncInContainer, copyTranscriptsFromContainer, senderAliveScript, HelperRefusal, GH_CONFIG_YML, ghHostsYml, isLiteralAddress, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, copyJudgeTree } from './chunk-ENFBARQP.js';
9
+ import { readBranchHead, fetchCommit, diffBetween } from './chunk-Q435LWVN.js';
9
10
  import { isSameProcess, startTimeOf } from './chunk-JBJTC3UU.js';
10
- import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, COMMAND_DIR, childEnvironment, judgeCommand, JUDGE_MAX_TURNS, MAX_REPORT_BYTES, JUDGE_DIR } from './chunk-5XCAPBE2.js';
11
- import { CLAUDE_CODE_VERSION } from './chunk-3W333NFO.js';
12
- import { waitForAgent, vmExecArgs } from './chunk-LY2L3O2O.js';
13
- import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-PDIM5T65.js';
14
- import { describeCallFailure, resolveGoverningSource, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, formatDuration, retrySend, formatClock } from './chunk-TQ6Y7YV6.js';
15
- import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-RVYOOYOA.js';
11
+ import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, COMMAND_DIR, childEnvironment, judgeCommand, JUDGE_MAX_TURNS, MAX_REPORT_BYTES, JUDGE_DIR } from './chunk-N3VSI5ZI.js';
12
+ import { CLAUDE_CODE_VERSION } from './chunk-APBTVIM4.js';
13
+ import { waitForAgent, vmExecArgs } from './chunk-HPOEVC2V.js';
14
+ import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-XGJUNNXL.js';
15
+ import { describeCallFailure, resolveGoverningSource, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, formatDuration, retrySend, formatClock } from './chunk-3FNPTQRH.js';
16
+ import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-CQRIZNE6.js';
16
17
  import { planArtifactUpload } from './chunk-BUP5N3X6.js';
17
- import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-D7X5ITVT.js';
18
+ import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-JWRX5ZTT.js';
18
19
  import { parseSize } from './chunk-7RQ73DLO.js';
19
- import { scrubText } from './chunk-D4AMAEZ7.js';
20
+ import { scrubText } from './chunk-QE3UQAHK.js';
20
21
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
21
22
  import { resolvePackRoot } from './chunk-HBISTTG3.js';
22
23
  import { parsePolicy } from './chunk-RKOTJQVG.js';
23
24
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
24
25
  import { resolveVersion } from './chunk-RA3O54FC.js';
25
- import { signerFor } from './chunk-PVRBE7S4.js';
26
- import { RUNNER_FILE_MODE, runnerDir, buildDir, vsockPath } from './chunk-KF37SUDM.js';
27
- import { claudeCredential, repositoriesOf, primaryOf, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, authorEnvironment, withTunnelRecord, commitIdentityRecord, RELAY_PORT, repositoryPath, lifecycleWorkdir, checkEnvironment, EVAL_INPUT_DIR } from './chunk-BN3CSI7S.js';
28
- import { RUNNER_WORDED_REASONS, UNKNOWN_TRACKING_REASON } from './chunk-GISNHSYL.js';
29
- import { existsSync, statSync, appendFileSync, mkdirSync, chmodSync, writeFileSync, accessSync, constants, openSync, readFileSync, closeSync, rmSync, readdirSync, lstatSync, fstatSync, readSync, realpathSync } from 'fs';
26
+ import { signerFor } from './chunk-ZODVSFI4.js';
27
+ import { RUNNER_FILE_MODE, runnerDir, buildDir, vsockPath } from './chunk-ZI2ZVWKT.js';
28
+ import { claudeCredential, repositoriesOf, primaryOf, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, authorEnvironment, withTunnelRecord, commitIdentityRecord, RELAY_PORT, repositoryPath, lifecycleWorkdir, checkEnvironment, EVAL_INPUT_DIR } from './chunk-2K3TCQHW.js';
29
+ import { RUNNER_WORDED_REASONS, UNKNOWN_TRACKING_REASON } from './chunk-JGD5TWQ2.js';
30
+ import { existsSync, statSync, appendFileSync, mkdirSync, chmodSync, writeFileSync, accessSync, constants, openSync, readFileSync, closeSync, rmSync, readdirSync, linkSync, lstatSync, fstatSync, readSync, realpathSync } from 'fs';
30
31
  import { join, isAbsolute, dirname, delimiter, sep } from 'path';
31
32
  import { spawn, spawnSync } from 'child_process';
32
33
  import { randomBytes, createHash } from 'crypto';
@@ -94,6 +95,61 @@ function judgeProbe(probe, missedBefore) {
94
95
  if (probe.alive) return { kind: "running" };
95
96
  return missedBefore ? { kind: "lost" } : { kind: "recheck" };
96
97
  }
98
+ function unitNameFor(buildId) {
99
+ return `outerlayer-build-${buildId}`;
100
+ }
101
+ function linkIn(buildDir2, name, source) {
102
+ const target = join(buildDir2, name);
103
+ rmSync(target, { force: true });
104
+ try {
105
+ linkSync(source, target);
106
+ } catch (err) {
107
+ if (err.code === "EXDEV") {
108
+ throw new Error(`${source} and ${buildDir2} are on different file systems, so the build's files cannot be linked into its jail`);
109
+ }
110
+ throw err;
111
+ }
112
+ chmodSync(source, 292);
113
+ }
114
+ async function startJailed(input) {
115
+ linkIn(input.buildDir, "kernel", input.kernel);
116
+ linkIn(input.buildDir, "rootfs.ext4", input.rootfs);
117
+ for (const name of input.sockets) {
118
+ try {
119
+ chmodSync(join(input.buildDir, name), 438);
120
+ } catch (err) {
121
+ if (err.code !== "ENOENT") throw err;
122
+ }
123
+ }
124
+ return input.client.start({ build: input.buildId, kind: input.kind });
125
+ }
126
+ async function startJailedInto(state, input, save) {
127
+ state.jailed = { unit: unitNameFor(state.buildId), chroot: "" };
128
+ save();
129
+ try {
130
+ const started = await startJailed({ ...input, buildId: state.buildId, buildDir: state.buildDir });
131
+ state.jailed = { unit: started.unit, chroot: started.chroot };
132
+ state.vsockPath = started.vsock;
133
+ } catch (err) {
134
+ if (err instanceof HelperRefusal) {
135
+ delete state.jailed;
136
+ save();
137
+ }
138
+ throw err;
139
+ }
140
+ save();
141
+ }
142
+ async function stopJailed(helper, state) {
143
+ const probe = await helper.probe();
144
+ if (!probe.ok) throw new Error(`the build's unit ${state.jailed?.unit ?? unitNameFor(state.buildId)} could not be stopped, because there is no helper to ask: ${probe.detail}`);
145
+ try {
146
+ await probe.client.stop(state.buildId);
147
+ } catch (err) {
148
+ throw new Error(`the build's unit ${state.jailed?.unit ?? unitNameFor(state.buildId)} was not stopped: ${describeCallFailure(err)}`);
149
+ }
150
+ }
151
+
152
+ // src/runner/microvm/hooks.ts
97
153
  var DEFAULT_MEMORY = "8g";
98
154
  var DEFAULT_DISK = "40g";
99
155
  var DEFAULT_CPUS = 4;
@@ -147,6 +203,34 @@ async function unpackIntoGuest(runtime, state, dir, target, opts = {}) {
147
203
  async function deliverCommitHooks(input) {
148
204
  await unpackIntoGuest(input.runtime, input.state, input.hooksDir, GUEST_HOOKS_DIR);
149
205
  }
206
+ function vmAlive(runtime, state) {
207
+ if (state.jailed !== void 0) return runtime.vm.helper.alive(state.jailed.unit);
208
+ return state.firecracker !== void 0 && runtime.vm.firecracker.alive(state.firecracker);
209
+ }
210
+ async function helperFor(runtime, log) {
211
+ const probe = await runtime.vm.helper.probe();
212
+ if (probe.ok) return probe.client;
213
+ if (probe.reason === "unsupported") log(probe.detail);
214
+ else if (probe.unreachable === true) log(`${probe.detail}, so this build runs without the jailer`);
215
+ return void 0;
216
+ }
217
+ function silence(runtime, state, lastError, console) {
218
+ if (!vmAlive(runtime, state)) return `it exited before its exec agent answered; ${console}`;
219
+ const last = lastError === void 0 ? "" : `; the last connection to its exec agent failed: ${describeCallFailure(lastError)}`;
220
+ return `its exec agent did not answer; ${console}${last}`;
221
+ }
222
+ function consoleNote(state, consolePath) {
223
+ return state.jailed === void 0 ? `its console is in ${consolePath}` : `its console output is in the journal of the unit ${state.jailed.unit}`;
224
+ }
225
+ async function helperKills(runtime, state) {
226
+ const probe = await runtime.vm.helper.probe();
227
+ return probe.ok ? (await probe.client.state(state.buildId)).oomKills : 0;
228
+ }
229
+ async function microVmOomKills(runtime, state) {
230
+ if (state.cgroup !== void 0 && runtime.vm.cgroup.oomKills(state.cgroup) > 0) return 1;
231
+ if (state.jailed !== void 0) return helperKills(runtime, state);
232
+ return 0;
233
+ }
150
234
  async function provisionMicroVm(input) {
151
235
  const { config, runtime, item, itemKey, jobDir, log, tokens } = input;
152
236
  const { vm } = runtime;
@@ -224,9 +308,9 @@ async function provisionMicroVm(input) {
224
308
  input.save(state, environment);
225
309
  const bail = async (reason, aborted = false) => {
226
310
  let why = reason;
227
- if (!aborted && state.cgroup !== void 0) {
311
+ if (!aborted && (state.cgroup !== void 0 || state.jailed !== void 0)) {
228
312
  try {
229
- if (runtime.vm.cgroup.oomKills(state.cgroup) > 0) why = outOfMemoryReason(config.build?.memory);
313
+ if (await microVmOomKills(runtime, state) > 0) why = outOfMemoryReason(config.build?.memory);
230
314
  } catch (err) {
231
315
  log.error(`${tag} could not read the build's memory events: ${describeCallFailure(err)} \xB7 continuing`);
232
316
  }
@@ -266,8 +350,9 @@ async function provisionMicroVm(input) {
266
350
  };
267
351
  const links = vsockLinks({ destinations: config.build?.destinations?.length ?? 0, builtIns: true });
268
352
  const configPath = join(buildDir2, "vm.json");
353
+ const helper = await helperFor(runtime, (line) => log.line(`${tag} ${line}`));
269
354
  try {
270
- linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
355
+ if (helper === void 0) linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
271
356
  await createBuildDisk({ host: vm.rootfs, runnerDir: runnerDirPath, bytes: limits.diskBytes, dest: state.buildDisk, memoryBytes: limits.memoryBytes });
272
357
  writeFileSync(
273
358
  configPath,
@@ -282,24 +367,34 @@ async function provisionMicroVm(input) {
282
367
  return bail(`the build's disk and machine could not be made: ${describeCallFailure(err)}`);
283
368
  }
284
369
  if (input.aborted()) return bail("", true);
285
- try {
286
- state.cgroup = vm.cgroup.create(buildId, limits.memoryBytes);
287
- } catch (err) {
288
- return bail(`the build's memory limit could not be set: ${describeCallFailure(err)}`);
370
+ if (helper === void 0) {
371
+ try {
372
+ state.cgroup = vm.cgroup.create(buildId, limits.memoryBytes);
373
+ } catch (err) {
374
+ return bail(`the build's memory limit could not be set: ${describeCallFailure(err)}`);
375
+ }
376
+ if (state.cgroup !== void 0) input.save(state, environment);
289
377
  }
290
- if (state.cgroup !== void 0) input.save(state, environment);
291
378
  const consolePath = join(jobDir, "vm-console.log");
292
- try {
293
- state.firecracker = await vm.firecracker.spawn({ binary: assets.firecracker, configPath, consolePath, cgroup: state.cgroup });
294
- } catch (err) {
295
- return bail(`Firecracker did not start: ${describeCallFailure(err)}`);
379
+ if (helper !== void 0) {
380
+ try {
381
+ await startJailedInto(state, { client: helper, kind: "build", kernel: assets.kernel, rootfs: state.rootfs, sockets: links.map((link) => link.socket) }, () => input.save(state, environment));
382
+ } catch (err) {
383
+ return bail(`the microVM did not start under the jailer: ${describeCallFailure(err)}`);
384
+ }
385
+ } else {
386
+ try {
387
+ state.firecracker = await vm.firecracker.spawn({ binary: assets.firecracker, configPath, consolePath, cgroup: state.cgroup });
388
+ } catch (err) {
389
+ return bail(`Firecracker did not start: ${describeCallFailure(err)}`);
390
+ }
391
+ input.save(state, environment);
296
392
  }
297
- input.save(state, environment);
298
393
  if (input.aborted()) return bail("", true);
299
- const ready = await waitForAgent(state.vsockPath, { attempts: BOOT_ATTEMPTS, delayMs: BOOT_POLL_MS, sleep: runtime.sleep });
394
+ let lastError;
395
+ const ready = await waitForAgent(state.vsockPath, { attempts: BOOT_ATTEMPTS, delayMs: BOOT_POLL_MS, sleep: runtime.sleep, onFailure: (err) => lastError = err });
300
396
  if (!ready) {
301
- const why = vm.firecracker.alive(state.firecracker) ? "its exec agent did not answer" : "it exited before its exec agent answered";
302
- return bail(`the microVM did not start: ${why}; its console is in ${consolePath}`);
397
+ return bail(`the microVM did not start: ${silence(runtime, state, lastError, consoleNote(state, consolePath))}`);
303
398
  }
304
399
  let pushes = Promise.resolve();
305
400
  let firstWriteFailure;
@@ -325,7 +420,7 @@ async function provisionMicroVm(input) {
325
420
  }
326
421
  tokens.onRead((token) => {
327
422
  pushes = pushes.then(async () => {
328
- if (state.firecracker === void 0 || !vm.firecracker.alive(state.firecracker)) return;
423
+ if (!vmAlive(runtime, state)) return;
329
424
  await writeGuestGhConfig(runtime, state, token);
330
425
  }, void 0).catch(reportWrite);
331
426
  });
@@ -467,7 +562,7 @@ function microVmSenderCommand(input) {
467
562
  return { command: process.execPath, args: [input.cli, "vm-exec", ...vmExecArgs(options)], env };
468
563
  }
469
564
  function isRunning(runtime, state) {
470
- return state.firecracker !== void 0 && runtime.vm.firecracker.alive(state.firecracker);
565
+ return vmAlive(runtime, state);
471
566
  }
472
567
  async function syncInMicroVm(input) {
473
568
  const { runtime, job } = input;
@@ -549,7 +644,7 @@ function microVmJudgeEnvironment(input) {
549
644
  const state = job.microvm;
550
645
  const agentUser = state.agentUser ?? ADDED_USER;
551
646
  const needsVm = () => {
552
- if (state.firecracker !== void 0 && !isRunning(runtime, state)) throw new Error("the build's microVM is gone");
647
+ if ((state.firecracker !== void 0 || state.jailed !== void 0) && !isRunning(runtime, state)) throw new Error("the build's microVM is gone");
553
648
  };
554
649
  return {
555
650
  stop: async () => {
@@ -681,8 +776,9 @@ async function startCheckMicroVm(input) {
681
776
  };
682
777
  const links = vsockLinks({ destinations: config.build?.destinations?.length ?? 0, builtIns: false });
683
778
  const configPath = join(buildDir2, "vm.json");
779
+ const helper = await helperFor(runtime, (line) => log.line(`${tag} ${line}`));
684
780
  try {
685
- linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
781
+ if (helper === void 0) linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
686
782
  await createBuildDisk({ host: vm.rootfs, runnerDir: runnerDirPath, bytes: limits.diskBytes, dest: state.buildDisk, memoryBytes: limits.memoryBytes });
687
783
  writeFileSync(
688
784
  configPath,
@@ -697,24 +793,34 @@ async function startCheckMicroVm(input) {
697
793
  return fail(`the check environment's disk and machine could not be made: ${describeCallFailure(err)}`);
698
794
  }
699
795
  if (abandoned()) return fail(ABANDONED);
700
- try {
701
- state.cgroup = vm.cgroup.create(buildId, limits.memoryBytes);
702
- } catch (err) {
703
- return fail(`the check environment's memory limit could not be set: ${describeCallFailure(err)}`);
704
- }
705
- if (state.cgroup !== void 0) input.save(state);
706
- const boot = async () => {
796
+ if (helper === void 0) {
707
797
  try {
708
- state.firecracker = await vm.firecracker.spawn({ binary: assets.firecracker, configPath, consolePath, cgroup: state.cgroup });
798
+ state.cgroup = vm.cgroup.create(buildId, limits.memoryBytes);
709
799
  } catch (err) {
710
- return `Firecracker did not start: ${describeCallFailure(err)}`;
800
+ return fail(`the check environment's memory limit could not be set: ${describeCallFailure(err)}`);
801
+ }
802
+ if (state.cgroup !== void 0) input.save(state);
803
+ }
804
+ const boot = async () => {
805
+ if (helper !== void 0) {
806
+ try {
807
+ await startJailedInto(state, { client: helper, kind: "check", kernel: assets.kernel, rootfs: state.rootfs, sockets: links.map((link) => link.socket) }, () => input.save(state));
808
+ } catch (err) {
809
+ return `the microVM did not start under the jailer: ${describeCallFailure(err)}`;
810
+ }
811
+ } else {
812
+ try {
813
+ state.firecracker = await vm.firecracker.spawn({ binary: assets.firecracker, configPath, consolePath, cgroup: state.cgroup });
814
+ } catch (err) {
815
+ return `Firecracker did not start: ${describeCallFailure(err)}`;
816
+ }
817
+ input.save(state);
711
818
  }
712
- input.save(state);
713
819
  if (abandoned()) return ABANDONED;
714
- const ready = await waitForAgent(state.vsockPath, { attempts: BOOT_ATTEMPTS, delayMs: BOOT_POLL_MS, sleep: runtime.sleep });
820
+ let lastError;
821
+ const ready = await waitForAgent(state.vsockPath, { attempts: BOOT_ATTEMPTS, delayMs: BOOT_POLL_MS, sleep: runtime.sleep, onFailure: (err) => lastError = err });
715
822
  if (!ready) {
716
- const why = vm.firecracker.alive(state.firecracker) ? "its exec agent did not answer" : "it exited before its exec agent answered";
717
- return `the microVM did not start: ${why}; its console is in ${consolePath}`;
823
+ return `the microVM did not start: ${silence(runtime, state, lastError, consoleNote(state, consolePath))}`;
718
824
  }
719
825
  if (built.docker === true) return waitForDocker(runtime, state, agentUser, () => /* @__PURE__ */ new Date());
720
826
  return void 0;
@@ -740,7 +846,8 @@ async function startCheckMicroVm(input) {
740
846
  },
741
847
  restart: async () => {
742
848
  try {
743
- await vm.firecracker.stop(state.firecracker);
849
+ if (state.jailed !== void 0) await stopJailed(vm.helper, state);
850
+ else await vm.firecracker.stop(state.firecracker);
744
851
  rmSync(state.vsockPath, { force: true });
745
852
  if (await boot() !== void 0) return false;
746
853
  if (evalInput.delivered) await deliverEvalInput();
@@ -754,6 +861,10 @@ async function startCheckMicroVm(input) {
754
861
  }
755
862
  async function stopBuildMicroVm(runtime, state, jobDir) {
756
863
  await copyHookErrors(runtime, state, jobDir);
864
+ if (state.jailed !== void 0) {
865
+ await stopJailed(runtime.vm.helper, state);
866
+ return;
867
+ }
757
868
  if (state.firecracker === void 0) return;
758
869
  await runtime.vm.firecracker.stop(state.firecracker);
759
870
  if (runtime.vm.firecracker.alive(state.firecracker)) throw new Error(`the microVM (pid ${state.firecracker.pid}) is still running after it was stopped`);
@@ -761,6 +872,13 @@ async function stopBuildMicroVm(runtime, state, jobDir) {
761
872
  async function cleanupMicroVm(runtime, state, jobDir) {
762
873
  const failures = [];
763
874
  if (jobDir !== void 0) await copyHookErrors(runtime, state, jobDir);
875
+ if (state.jailed !== void 0) {
876
+ try {
877
+ await stopJailed(runtime.vm.helper, state);
878
+ } catch (err) {
879
+ failures.push(describeCallFailure(err));
880
+ }
881
+ }
764
882
  if (state.firecracker !== void 0) {
765
883
  try {
766
884
  await runtime.vm.firecracker.stop(state.firecracker);
@@ -786,6 +904,8 @@ async function cleanupMicroVm(runtime, state, jobDir) {
786
904
  }
787
905
  async function stopOrphanedMicroVms(input) {
788
906
  const stopped = [];
907
+ const report = (line) => input.onError?.(line);
908
+ const jailedByJobs = [];
789
909
  for (const { job } of input.jobs) {
790
910
  const states = [job.microvm, job.checkMicrovm].filter((state) => state !== void 0);
791
911
  if (states.length === 0) continue;
@@ -798,12 +918,38 @@ async function stopOrphanedMicroVms(input) {
798
918
  while (isSameProcess(job.pid, job.start) && Date.now() < deadline) await new Promise((resolve) => setTimeout(resolve, 10));
799
919
  }
800
920
  for (const state of states) {
921
+ if (state.jailed !== void 0) jailedByJobs.push(state.jailed.unit);
801
922
  if (state.firecracker !== void 0 && input.runtime.vm.firecracker.alive(state.firecracker)) {
802
- await input.runtime.vm.firecracker.stop(state.firecracker);
803
- stopped.push(state.buildId);
923
+ try {
924
+ await input.runtime.vm.firecracker.stop(state.firecracker);
925
+ stopped.push(state.buildId);
926
+ } catch (err) {
927
+ report(`the microVM of build ${state.buildId} (pid ${state.firecracker.pid}) was not stopped: ${describeCallFailure(err)}`);
928
+ }
804
929
  }
805
930
  }
806
931
  }
932
+ const probe = await input.runtime.vm.helper.probe();
933
+ if (!probe.ok) {
934
+ if (jailedByJobs.length > 0) report(`the units ${jailedByJobs.join(", ")} could not be stopped, because there is no helper to ask: ${probe.detail}`);
935
+ return stopped;
936
+ }
937
+ let builds;
938
+ try {
939
+ builds = await probe.client.list();
940
+ } catch (err) {
941
+ report(`the helper's list of builds could not be read: ${describeCallFailure(err)}`);
942
+ return stopped;
943
+ }
944
+ for (const build of builds) {
945
+ try {
946
+ await probe.client.stop(build);
947
+ } catch (err) {
948
+ report(`the unit of build ${build} was not stopped: ${describeCallFailure(err)}`);
949
+ continue;
950
+ }
951
+ if (!stopped.includes(build)) stopped.push(build);
952
+ }
807
953
  return stopped;
808
954
  }
809
955
  function provisionEnvironment(base, input) {
@@ -2468,9 +2614,9 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
2468
2614
  }
2469
2615
  }
2470
2616
  let outOfMemory;
2471
- if (vmBuild?.state.cgroup !== void 0 && outcome !== void 0 && outcome !== "ok" && ending?.reason === void 0) {
2617
+ if ((vmBuild?.state.cgroup !== void 0 || vmBuild?.state.jailed !== void 0) && outcome !== void 0 && outcome !== "ok" && ending?.reason === void 0) {
2472
2618
  try {
2473
- if (vmBuild.runtime.vm.cgroup.oomKills(vmBuild.state.cgroup) > 0) {
2619
+ if (await microVmOomKills(vmBuild.runtime, vmBuild.state) > 0) {
2474
2620
  outOfMemory = outOfMemoryReason(config.build?.memory);
2475
2621
  }
2476
2622
  } catch (err) {
@@ -2739,8 +2885,15 @@ function unfinishedJobs(jobsDirPath) {
2739
2885
  function isContainerTracked(job) {
2740
2886
  return job.container?.tracking === "container";
2741
2887
  }
2888
+ function isReadable(job) {
2889
+ return readsJobState(job, READ_JOB_STATE_FORMATS);
2890
+ }
2891
+ function listUnreadableJobs(jobsDirPath) {
2892
+ return unfinishedJobs(jobsDirPath).flatMap(({ dirPath, job }) => isReadable(job) ? [] : [{ dirPath, job, format: jobStateFormatOf(job) }]);
2893
+ }
2742
2894
  function listTrackedJobs(jobsDirPath) {
2743
2895
  return unfinishedJobs(jobsDirPath).flatMap(({ dirPath, job }) => {
2896
+ if (!isReadable(job)) return [];
2744
2897
  const tracking = job.container?.tracking;
2745
2898
  if (tracking === void 0) return [];
2746
2899
  if (tracking === "container" && inTeardown(job)) return [];
@@ -2749,12 +2902,13 @@ function listTrackedJobs(jobsDirPath) {
2749
2902
  }
2750
2903
  function listAdoptableJobs(jobsDirPath) {
2751
2904
  return unfinishedJobs(jobsDirPath).filter(
2752
- ({ job }) => job.microvm === void 0 && job.pid !== void 0 && job.start !== void 0 && isSameProcess(job.pid, job.start)
2905
+ ({ job }) => isReadable(job) && job.microvm === void 0 && job.pid !== void 0 && job.start !== void 0 && isSameProcess(job.pid, job.start)
2753
2906
  );
2754
2907
  }
2755
2908
  async function recoverLostJobs(jobsDirPath, config, deps) {
2756
2909
  const recovered = [];
2757
2910
  for (const { dirPath, job } of unfinishedJobs(jobsDirPath)) {
2911
+ if (!isReadable(job)) continue;
2758
2912
  const tracking = job.container?.tracking;
2759
2913
  if (tracking !== void 0 && tracking !== "container") {
2760
2914
  recovered.push(await finishJob(job, dirPath, "interrupted", config, deps, { reason: UNKNOWN_TRACKING_REASON }));
@@ -2928,4 +3082,4 @@ async function stopSender(input) {
2928
3082
  }
2929
3083
  }
2930
3084
 
2931
- export { ALREADY_RELEASED, AttemptLogBook, EXIT_CODE_FILE, RENEW_INTERVAL_SECONDS, appendCommandLog, commandLogOffset, deliverCommitHooks, describeHookEnd, execArgv, execCommandLine, finishJob, hookLimitsFor, hostCommandEnvironment, hostEnvironment, isContainerTracked, isGroupAlive, isIdle, isTimedOut, isUnfinished, jobEnv, judgeProbe, listAdoptableJobs, listTrackedJobs, listenOnBroker, microVmCommandLine, needsRenew, outcomeFromExitCode, probeCommand, provisionEnvironment, provisionMicroVm, provisionProcess, readCpuUsec, readProvisionOut, recoverLostJobs, releaseLease, renewLease, resolveHostBuild, restartSender, retryFailedReleases, runCommand, runHook, setStage, startHostServices, startSender, stopOrphanedMicroVms, unfinishedJobs, workdirProblem };
3085
+ export { ALREADY_RELEASED, AttemptLogBook, EXIT_CODE_FILE, RENEW_INTERVAL_SECONDS, appendCommandLog, commandLogOffset, deliverCommitHooks, describeHookEnd, execArgv, execCommandLine, finishJob, hookLimitsFor, hostCommandEnvironment, hostEnvironment, inTeardown, isContainerTracked, isGroupAlive, isIdle, isReadable, isTimedOut, isUnfinished, jobEnv, judgeProbe, listAdoptableJobs, listTrackedJobs, listUnreadableJobs, listenOnBroker, microVmCommandLine, needsRenew, outcomeFromExitCode, probeCommand, provisionEnvironment, provisionMicroVm, provisionProcess, readCpuUsec, readProvisionOut, recoverLostJobs, releaseLease, renewLease, resolveHostBuild, restartSender, retryFailedReleases, runCommand, runHook, setStage, startHostServices, startSender, stopOrphanedMicroVms, unfinishedJobs, workdirProblem };
@@ -242,12 +242,12 @@ var MICROVM_ARCHES = ["x86_64"];
242
242
  function firecrackerArch(nodeArch) {
243
243
  return nodeArch === "x64" ? "x86_64" : nodeArch === "arm64" ? "aarch64" : nodeArch;
244
244
  }
245
- var FIRECRACKER_VERSION = "1.13.1";
245
+ var FIRECRACKER_VERSION = "1.16.2";
246
246
  var FIRECRACKER_SHA256 = {
247
- x86_64: "59450b9171ff2ebdf2f9a25be3a248a7ba79fb6371aec51a9d6d8eefca7b4faf"
247
+ x86_64: "32e3cdcd4081f91fe2b024a266f57dcb3b4e5fec5033e0cb22467ad7f7820bda"
248
248
  };
249
249
  var FIRECRACKER_BINARY_SHA256 = {
250
- x86_64: "7d3924e0c8761edafbf85cb2a94c268ffad249644a40fd02d4e15cde4c206f6e"
250
+ x86_64: "8227875ceda44177a4d501052dae4a2f9d7837362f5399f02cf0748e68418377"
251
251
  };
252
252
  var GUEST_ASSETS_VERSION = "1";
253
253
  var GUEST_ASSETS_BASE_URL = `https://github.com/outerlayerai/guest-assets/releases/download/guest-${GUEST_ASSETS_VERSION}`;
@@ -261,5 +261,16 @@ function guestAssetsPinned(arch) {
261
261
  const zero = "0".repeat(64);
262
262
  return GUEST_KERNEL_SHA256[arch] !== zero && GUEST_HELPER_SHA256[arch] !== zero;
263
263
  }
264
+ var JAILER_BINARY_SHA256 = {
265
+ x86_64: "99832d2270741af67ffacd46da716b4b016338541af5a742907ab965b2e9ac9e"
266
+ };
267
+ var HOST_HELPER_ASSETS_VERSION = "4";
268
+ var HOST_HELPER_BASE_URL = `https://github.com/outerlayerai/guest-assets/releases/download/guest-${HOST_HELPER_ASSETS_VERSION}`;
269
+ var HOST_HELPER_SHA256 = {
270
+ x86_64: "5c9d9e46daf165411ebe594fa28f4adc6b363989d77673c7651ab6dccb808684"
271
+ };
272
+ function hostHelperPinned(arch = "x86_64", hashes = HOST_HELPER_SHA256) {
273
+ return hashes[arch] !== "0".repeat(64);
274
+ }
264
275
 
265
- export { BUILDKIT_IMAGE, CLAUDE_CODE_VERSION, DEFAULT_BASE_IMAGE, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GH_SHA256, GH_VERSION, GUEST_ASSETS_BASE_URL, GUEST_ASSETS_VERSION, GUEST_HELPER_SHA256, GUEST_KERNEL_SHA256, MICROVM_ARCHES, NODE_IMAGE, RecipeError, SANITIZED_NAME, TINI_SHA256, TINI_VERSION, assertBuildable, classifyProperties, firecrackerArch, guestAssetsPinned, locateRecipe, readRecipe, writeSanitizedRecipe };
276
+ export { BUILDKIT_IMAGE, CLAUDE_CODE_VERSION, DEFAULT_BASE_IMAGE, DOCKER_FEATURE, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GH_SHA256, GH_VERSION, GUEST_ASSETS_BASE_URL, GUEST_ASSETS_VERSION, GUEST_HELPER_SHA256, GUEST_KERNEL_SHA256, HOST_HELPER_ASSETS_VERSION, HOST_HELPER_BASE_URL, HOST_HELPER_SHA256, JAILER_BINARY_SHA256, MICROVM_ARCHES, NODE_IMAGE, RecipeError, SANITIZED_NAME, TINI_SHA256, TINI_VERSION, assertBuildable, classifyProperties, firecrackerArch, guestAssetsPinned, hostHelperPinned, locateRecipe, readRecipe, writeSanitizedRecipe };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { currentLink } from './chunk-VV7ZD5LR.js';
3
+ import { currentLink } from './chunk-QMQC6JCO.js';
4
4
  import { readFileSync, statSync, chmodSync, mkdirSync, writeFileSync, renameSync, rmSync, existsSync, lstatSync, accessSync, constants, realpathSync } from 'fs';
5
5
  import { randomBytes } from 'crypto';
6
6
  import { join, dirname, delimiter, resolve } from 'path';
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { uploadSpooledSteps } from './chunk-F7Y2USIM.js';
3
+ import { uploadSpooledSteps } from './chunk-H6ZFLIX3.js';
4
4
  import { LaunchFilter } from './chunk-ESVW4MJY.js';
5
5
  import { RepoFilter } from './chunk-TBT347UY.js';
6
6
  import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-BUP5N3X6.js';
7
- import { cliFetch, resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-FKXGQOF5.js';
8
- import { writeSyncStatus, spoolDir } from './chunk-755WXDBI.js';
7
+ import { cliFetch, resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-M4B6QKNZ.js';
8
+ import { writeSyncStatus, spoolDir } from './chunk-K5WVK7IC.js';
9
9
  import { readLatestProvenanceForSession, readContextProvenance } from './chunk-ZJSNLVCE.js';
10
10
  import { hookExecSpoolPath } from './chunk-DYEFPYME.js';
11
11
  import { applyReportedCost } from './chunk-BKO6JEZI.js';
12
12
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
13
- import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-D4AMAEZ7.js';
13
+ import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-QE3UQAHK.js';
14
14
  import { C } from './chunk-ANPNT6PM.js';
15
15
  import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
16
16
  import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-T2Q7ISPE.js';
@@ -18,7 +18,7 @@ import { cliInvocation } from './chunk-CRB3POP4.js';
18
18
  import { removeJournalHooks } from './chunk-TUSYOL2O.js';
19
19
  import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-QZBXLLTV.js';
20
20
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
21
- import { signerFor, signRunnerRequest } from './chunk-PVRBE7S4.js';
21
+ import { signerFor, signRunnerRequest } from './chunk-ZODVSFI4.js';
22
22
  import { dirname, basename, join } from 'path';
23
23
  import { statSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync, existsSync, rmSync } from 'fs';
24
24
  import { execFileSync } from 'child_process';
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { detectActiveSession, autoConnect } from './chunk-F2W2IYNP.js';
4
- import { workPageUrl } from './chunk-V5Q3S4NM.js';
3
+ import { detectActiveSession, autoConnect } from './chunk-3WZ5ECSM.js';
4
+ import { workPageUrl } from './chunk-SNQR2EYI.js';
5
5
  import { sanitizeTerminal } from './chunk-BUP5N3X6.js';
6
- import { resolveGatewayCredentials, unauthorizedMessage, defaultFetch } from './chunk-FKXGQOF5.js';
6
+ import { resolveGatewayCredentials, unauthorizedMessage, defaultFetch } from './chunk-M4B6QKNZ.js';
7
7
  import { readRepoConnection } from './chunk-BJ3KTMDH.js';
8
- import { resolveRepoIdentity } from './chunk-D4AMAEZ7.js';
8
+ import { resolveRepoIdentity } from './chunk-QE3UQAHK.js';
9
9
  import { C } from './chunk-ANPNT6PM.js';
10
10
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
11
11
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
12
- import { signRunnerRequest } from './chunk-PVRBE7S4.js';
12
+ import { signRunnerRequest } from './chunk-ZODVSFI4.js';
13
13
 
14
14
  createRequire(import.meta.url);
15
15
 
@@ -368,10 +368,11 @@ function issueLabel(subject) {
368
368
  if ("issue" in subject) return `issue ${sanitizeTerminal(subject.repository)}#${subject.issue}`;
369
369
  return `issue ${sanitizeTerminal(subject.key)}`;
370
370
  }
371
- function itemPageUrl(home, cwd, appId, workItemId) {
371
+ function itemPageUrl(home, cwd, appId, workItemId, number) {
372
372
  const connection = readRepoConnection(cwd);
373
373
  if (connection === void 0 || connection.appId !== appId || typeof workItemId !== "string" || workItemId === "") return void 0;
374
- return `${workPageUrl(home, connection.organization.name, connection.factory.name)}/${encodeURIComponent(workItemId)}`;
374
+ const segment = encodeURIComponent(number == null ? workItemId : String(number));
375
+ return `${workPageUrl(home, connection.organization.name, connection.factory.name)}/${segment}`;
375
376
  }
376
377
  async function runWorkBuild(opts) {
377
378
  const cwd = opts.cwd ?? process.cwd();
@@ -416,7 +417,7 @@ async function runWorkBuild(opts) {
416
417
  ...facts
417
418
  };
418
419
  const { data } = await postJsonWithRetry(url, "/v1/work-items/build", apiKey, appId, body, fetchImpl, retries, sleep);
419
- const page = itemPageUrl(home, cwd, appId, data.workItemId);
420
+ const page = itemPageUrl(home, cwd, appId, data.workItemId, data.number);
420
421
  const output = opts.json ? JSON.stringify(data) : `${C.green}\u2713${C.reset} build requested ${C.dim}\xB7${C.reset} ${itemLabel(data)}${"subject" in body ? ` (${issueLabel(body.subject)})` : ""} ${C.dim}\xB7${C.reset} by ${data.attestor}` + (page !== void 0 ? `
421
422
  ${page}` : "") + tokenWarning(data);
422
423
  if (!opts.quiet) process.stdout.write(output + "\n");
@@ -427,7 +428,7 @@ async function runWorkLinkSession(opts) {
427
428
  return await linkSession(opts);
428
429
  } catch (err) {
429
430
  if (opts.logFailures) {
430
- const { logHookError } = await import('./hook-fast-3JL4PXLG.js');
431
+ const { logHookError } = await import('./hook-fast-NEELST6G.js');
431
432
  const reason = err instanceof Error ? err.message : String(err);
432
433
  logHookError(opts.home ?? homeFromEnv(opts.env ?? process.env), new Error(`work link-session #${opts.number} failed: ${reason}`));
433
434
  }
@@ -514,9 +515,17 @@ async function runWorkRemove(opts) {
514
515
  if (!opts.quiet) process.stdout.write(output + "\n");
515
516
  return { data, output };
516
517
  }
518
+ function mergedUnverifiedLine(data) {
519
+ const block = data.gates?.block;
520
+ if (block?.mergedDespiteVerdict !== true) return "";
521
+ const at = typeof block.mergedAt === "string" ? ` at ${sanitizeTerminal(block.mergedAt)}` : "";
522
+ return `${C.yellow}Merged, unverified${C.reset}: the pull request merged${at} before its checks or review passed, so the stage stays at review.
523
+
524
+ `;
525
+ }
517
526
  function statusOutput(data, json) {
518
527
  if (json) return JSON.stringify(data);
519
- const document = JSON.stringify(data, null, 2);
528
+ const document = mergedUnverifiedLine(data) + JSON.stringify(data, null, 2);
520
529
  const criteria = data.criteria;
521
530
  if (criteria === void 0) return document;
522
531
  if (criteria === null || !Array.isArray(criteria.items)) return `${document}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { isSameProcess } from './chunk-JBJTC3UU.js';
4
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-KF37SUDM.js';
4
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZI2ZVWKT.js';
5
5
  import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync } from 'fs';
6
6
  import { dirname } from 'path';
7
7