@outerlayer/cli 0.27.1 → 0.28.2

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 (129) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +6 -0
  3. package/dist/{agent-setup-UW36TAQM.js → agent-setup-YVR5RO56.js} +17 -14
  4. package/dist/{bridge-B5VJVECY.js → bridge-WW2V7DTB.js} +3 -2
  5. package/dist/build-5FRC3RKM.js +13 -0
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-6Y6ZWGNH.js → builder-4F2XNSFC.js} +7 -6
  8. package/dist/{check-YTXFVWK7.js → check-YEI6TCUH.js} +70 -61
  9. package/dist/{chunk-LPFOWUHG.js → chunk-25X2PJDI.js} +20 -13
  10. package/dist/{chunk-BPKO76QR.js → chunk-4XN5FRRJ.js} +4 -4
  11. package/dist/{chunk-EPPIISRD.js → chunk-55XLX5PA.js} +1 -1
  12. package/dist/{chunk-LOKSLO25.js → chunk-5B7BEQPR.js} +1 -1
  13. package/dist/chunk-5BHIBJDA.js +93 -0
  14. package/dist/{chunk-RHAGBUL5.js → chunk-5K3KB4YR.js} +1 -1
  15. package/dist/{chunk-ABXQBEYK.js → chunk-66T6XJAB.js} +1 -1
  16. package/dist/{chunk-ZFBJUOYT.js → chunk-6S4V4UIC.js} +10 -10
  17. package/dist/{chunk-BWH36FOC.js → chunk-7CK2TJFB.js} +20 -4
  18. package/dist/{chunk-QKIQ2R7F.js → chunk-ATJOFXTE.js} +3 -3
  19. package/dist/chunk-CDDED64E.js +13 -0
  20. package/dist/{chunk-QHH4OSD4.js → chunk-CTYSTE5C.js} +1 -1
  21. package/dist/{chunk-DJHNEGNM.js → chunk-DKWQMPSL.js} +18 -2
  22. package/dist/{chunk-IMOB4IOI.js → chunk-DQYMQ47E.js} +3 -2
  23. package/dist/{chunk-YETTWTAY.js → chunk-E7R2GIAW.js} +4 -4
  24. package/dist/{chunk-GFUE5TKO.js → chunk-F4FA3ZUT.js} +24 -14
  25. package/dist/{chunk-6TRNCUM4.js → chunk-FGF52V4V.js} +1 -1
  26. package/dist/{chunk-R7SGBXUD.js → chunk-GLL4TN2M.js} +226 -72
  27. package/dist/{chunk-MATUHHN4.js → chunk-GUXWQIEY.js} +1 -1
  28. package/dist/{chunk-B7DJVG25.js → chunk-HOB7Z4JQ.js} +3 -3
  29. package/dist/{chunk-2I3LIRZP.js → chunk-HXAEQPZR.js} +101 -10
  30. package/dist/{chunk-P33PZIWS.js → chunk-ITAIEJ2T.js} +7 -142
  31. package/dist/{chunk-RHGF73IU.js → chunk-IVX3U7KV.js} +1 -1
  32. package/dist/{chunk-7OUOLGUV.js → chunk-JGML2VUN.js} +3 -7
  33. package/dist/{chunk-6VFH52MP.js → chunk-KU7QL4XW.js} +24 -22
  34. package/dist/{chunk-2F762IXY.js → chunk-LNIFYSNK.js} +3 -3
  35. package/dist/{chunk-XBPUTQ7E.js → chunk-MHAR6S7B.js} +1 -1
  36. package/dist/{chunk-VS27BP3E.js → chunk-MKIC65SD.js} +52 -9
  37. package/dist/{chunk-64GMBWAK.js → chunk-MNHMUZGC.js} +6 -6
  38. package/dist/{chunk-7AQ5AM7U.js → chunk-MQHTM4YJ.js} +177 -21
  39. package/dist/{chunk-6KKM7VGZ.js → chunk-N7WAEEIU.js} +3 -3
  40. package/dist/{chunk-D7ECMB7B.js → chunk-NUHZV3A4.js} +1 -1
  41. package/dist/{chunk-5VMDGJGH.js → chunk-O65LES4V.js} +39 -25
  42. package/dist/{chunk-MHX7YX7Y.js → chunk-P2RWZCV7.js} +1 -1
  43. package/dist/chunk-QBQHQEUG.js +300 -0
  44. package/dist/{chunk-FP23SVDD.js → chunk-QJFDAKRF.js} +5 -5
  45. package/dist/{chunk-WUL2OP5A.js → chunk-QKXF7CLR.js} +3 -3
  46. package/dist/{chunk-XZ6Q6ZNR.js → chunk-SATUCMAJ.js} +3 -2
  47. package/dist/{chunk-Y7ZCHBYB.js → chunk-SFJXGISY.js} +3 -3
  48. package/dist/{chunk-2BTFKNTR.js → chunk-SJZL5F3F.js} +2 -2
  49. package/dist/{chunk-HWDYLXHH.js → chunk-T2QSWFSU.js} +4 -4
  50. package/dist/{chunk-E5IJ5533.js → chunk-TF7G2PR6.js} +3 -3
  51. package/dist/{chunk-O2IJTY7L.js → chunk-TVZAC2NP.js} +3 -3
  52. package/dist/{chunk-QE3UQAHK.js → chunk-UHU7H57K.js} +26 -7
  53. package/dist/{chunk-WSYXLLA5.js → chunk-USJZ2LDK.js} +6 -6
  54. package/dist/{chunk-EX5MQYEF.js → chunk-VC5J7QPV.js} +5 -5
  55. package/dist/{chunk-N4D5TMVU.js → chunk-VU7ZJPIR.js} +5 -5
  56. package/dist/{chunk-GLUKDQS4.js → chunk-WWQVKFN6.js} +1 -1
  57. package/dist/{chunk-55GNQPO6.js → chunk-X52PMPOM.js} +7 -7
  58. package/dist/{chunk-YB3CSYXX.js → chunk-XD4ZCMA4.js} +81 -2
  59. package/dist/{chunk-Y4OKEFAX.js → chunk-YL2VDSNF.js} +1 -1
  60. package/dist/{chunk-M3MHHIUW.js → chunk-Z3ASAXVU.js} +1 -1
  61. package/dist/{chunk-XS3FDWSZ.js → chunk-ZTY7HHYB.js} +1 -1
  62. package/dist/{claude-launcher-NQSZBTQ5.js → claude-launcher-7RGVOYCD.js} +6 -5
  63. package/dist/{cli-GHEOBXC7.js → cli-SCTKM2Y5.js} +151 -130
  64. package/dist/cli-update-notice-4DLZ3655.js +9 -0
  65. package/dist/{command-V7B7GTPZ.js → command-PY3C2E4B.js} +53 -37
  66. package/dist/{config-TWS5VZEN.js → config-5QYIKYUP.js} +3 -2
  67. package/dist/{connect-cmd-HGS7YPA2.js → connect-cmd-5TYAOK5M.js} +14 -11
  68. package/dist/{container-start-FHB2VDC4.js → container-start-7WLZMPEI.js} +37 -36
  69. package/dist/{control-plane-launch-DBQA3KLJ.js → control-plane-launch-FZMD4MXX.js} +13 -10
  70. package/dist/{dist-QPHZE47F.js → dist-JFVKLUHL.js} +1 -1
  71. package/dist/{docker-YT6Z3LXI.js → docker-ZTC4EIU4.js} +7 -6
  72. package/dist/{doctor-Y4NCNSJM.js → doctor-DQWRUAEB.js} +159 -41
  73. package/dist/{emit-artifact-cmd-ALDK55Y2.js → emit-artifact-cmd-SOXLBPQB.js} +19 -16
  74. package/dist/{emit-cmd-VAQHRWJR.js → emit-cmd-QUABLVO6.js} +6 -5
  75. package/dist/{emit-criteria-cmd-Q7SM6VP2.js → emit-criteria-cmd-JDO2VUG5.js} +15 -12
  76. package/dist/{emit-finding-cmd-2NBAPDSV.js → emit-finding-cmd-VCQPCLI2.js} +16 -13
  77. package/dist/{emit-result-cmd-KUSL56RI.js → emit-result-cmd-TKA3GAN7.js} +19 -16
  78. package/dist/{emit-step-cmd-KD4AKEAT.js → emit-step-cmd-XN44BXYU.js} +16 -13
  79. package/dist/{exec-client-6WVS7DRZ.js → exec-client-VKT2XNB3.js} +4 -3
  80. package/dist/fleet-readiness-G5X3MKP2.js +29 -0
  81. package/dist/{governing-source-VVUA5TKB.js → governing-source-B3M2U4BC.js} +21 -18
  82. package/dist/{guest-init-H5K2RW3P.js → guest-init-QW2DPX7H.js} +5 -4
  83. package/dist/{hook-fast-3SUJM765.js → hook-fast-EFC44SXV.js} +4 -1
  84. package/dist/{host-key-XNKZCWTS.js → host-key-AC6LTZDS.js} +4 -3
  85. package/dist/{image-tag-R34J4O3F.js → image-tag-SS7YKJHN.js} +4 -3
  86. package/dist/index.js +4 -4
  87. package/dist/init-5LHTF72R.js +56 -0
  88. package/dist/{init-3DAGX7UY.js → init-BTH5YPBC.js} +38 -37
  89. package/dist/{init-cmd-RIDBVSE4.js → init-cmd-L4VW3ZCT.js} +25 -21
  90. package/dist/{init-update-ECWNG47R.js → init-update-RWTQSTPE.js} +51 -35
  91. package/dist/{inspect-IPFA7AAT.js → inspect-L7JIBK3Y.js} +1 -1
  92. package/dist/{install-6OIY3KHZ.js → install-35SAMY75.js} +5 -5
  93. package/dist/{install-cmd-JMT67P35.js → install-cmd-GFY4QF72.js} +6 -5
  94. package/dist/{layout-XNFDTOET.js → layout-BBTQPS6V.js} +4 -3
  95. package/dist/{login-browser-EWXSGHM7.js → login-browser-WSOSQH2T.js} +2 -2
  96. package/dist/{logs-XHAS6LMZ.js → logs-X2IRDP5T.js} +3 -2
  97. package/dist/loop-QDV7T65M.js +80 -0
  98. package/dist/{machine-OOQ2NXC3.js → machine-PLNSGKNF.js} +32 -30
  99. package/dist/{machine-skills-FLIRJYP7.js → machine-skills-O7W6NMWB.js} +4 -3
  100. package/dist/{mcp-serve-cmd-LY5A3CE7.js → mcp-serve-cmd-IITCPAAR.js} +9 -6
  101. package/dist/{paths-LHSPNORF.js → paths-32DWGK35.js} +3 -2
  102. package/dist/pending-CSIY4Y2I.js +10 -0
  103. package/dist/{pidfile-DKMYYXLH.js → pidfile-CYCTH6NQ.js} +4 -3
  104. package/dist/{real-deps-KNNBQC75.js → real-deps-QX5YH7FG.js} +1 -1
  105. package/dist/{record-3LPTY3G5.js → record-N4WPZCGK.js} +4 -3
  106. package/dist/{relay-GFPPD6GF.js → relay-FJ5K37Z5.js} +8 -4
  107. package/dist/{runner-env-YRRNRKF4.js → runner-env-EIB6WFPG.js} +6 -7
  108. package/dist/{runner-identity-YS2BZXZV.js → runner-identity-S3V6I4I3.js} +7 -6
  109. package/dist/{runner-key-EFNTZWNX.js → runner-key-M4N2BY5A.js} +36 -35
  110. package/dist/{session-sender-SC5PSU2G.js → session-sender-UQ3VF732.js} +20 -17
  111. package/dist/{spec-cmd-JGYHHJ4P.js → spec-cmd-Z6MGATWC.js} +16 -13
  112. package/dist/{starter-pack-GPU4X6B7.js → starter-pack-5SOT5V4I.js} +4 -3
  113. package/dist/{status-7WM7S7JX.js → status-PWMPP4ES.js} +39 -37
  114. package/dist/{sync-cmd-ATXJVS7S.js → sync-cmd-N4R7ST6X.js} +19 -16
  115. package/dist/{watch-M7NR3DOW.js → watch-L5MSAWEO.js} +19 -16
  116. package/dist/{work-claim-cmd-DNUDZKJA.js → work-claim-cmd-CXALMILD.js} +21 -18
  117. package/dist/{work-cmd-VECTYST6.js → work-cmd-COESFSHE.js} +16 -13
  118. package/dist/{work-comment-cmd-F3NRWKPZ.js → work-comment-cmd-A4ZUVCSA.js} +16 -13
  119. package/dist/{work-logs-cmd-QF6P32FE.js → work-logs-cmd-CTF43MBE.js} +16 -13
  120. package/dist/{work-open-pr-cmd-XE23JA3R.js → work-open-pr-cmd-EMGYJXVD.js} +17 -14
  121. package/dist/{work-pr-cmd-BH56GUKN.js → work-pr-cmd-FEXMS6RH.js} +16 -13
  122. package/dist/{work-stop-cmd-C3F5HNUO.js → work-stop-cmd-NIHAN45R.js} +16 -13
  123. package/package.json +1 -1
  124. package/dist/build-HRLACBOZ.js +0 -12
  125. package/dist/chunk-STSLH5EJ.js +0 -71
  126. package/dist/init-SWKYV6CL.js +0 -55
  127. package/dist/loop-AIJZVUNA.js +0 -79
  128. package/dist/pending-3YZCSKON.js +0 -9
  129. package/dist/{chunk-6BLXUD56.js → chunk-HOU33DW5.js} +1 -1
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { FD_SLOTS_PER_BUILD, FD_STORE_ENV } from './chunk-YB3CSYXX.js';
4
- import { builtinKind } from './chunk-EPPIISRD.js';
3
+ import { builtinKind } from './chunk-55XLX5PA.js';
5
4
  import { parseSize } from './chunk-YJLHUKYS.js';
6
- import { runnerDir } from './chunk-RHAGBUL5.js';
7
- import { dirname } from 'path';
5
+ import { runnerDir } from './chunk-5K3KB4YR.js';
6
+ import { CLAUDE_CREDENTIAL_ID, CLAUDE_ENV_FILE, credentialLineIn, withoutCredentialLines } from './chunk-HXAEQPZR.js';
7
+ import { FD_SLOTS_PER_BUILD, FD_STORE_ENV } from './chunk-XD4ZCMA4.js';
8
+ import { existsSync, readFileSync, writeFileSync, chmodSync, renameSync } from 'fs';
9
+ import { dirname, join } from 'path';
8
10
  import { spawnSync } from 'child_process';
9
11
 
10
12
  createRequire(import.meta.url);
@@ -16,6 +18,9 @@ var STOP_MARGIN_MINUTES = 10;
16
18
  function escapeUnitPath(path) {
17
19
  return path.replace(/%/g, "%%").replace(/ /g, "\\x20");
18
20
  }
21
+ function credentialPath(path) {
22
+ return path.replace(/%/g, "%%");
23
+ }
19
24
  function runnerUnit(unit) {
20
25
  const helperService = unit.helper === void 0 ? void 0 : `${unit.helper.unit}.service`;
21
26
  return `${UNIT_MARKER}
@@ -31,6 +36,7 @@ ExecStart=${unit.execStart}
31
36
  ${unit.helper === void 0 ? "" : `Environment=OUTERLAYER_HELPER_SOCKET=${unit.helper.socket}
32
37
  `}${unit.fdStore === void 0 ? "" : `Environment=${FD_STORE_ENV}=${unit.fdStore}
33
38
  `}EnvironmentFile=-${escapeUnitPath(`${unit.configDir}/runner.env`)}
39
+ ${unit.credential === "load" ? `LoadCredential=${CLAUDE_CREDENTIAL_ID}:${credentialPath(`${unit.configDir}/${CLAUDE_ENV_FILE}`)}` : `EnvironmentFile=-${escapeUnitPath(`${unit.configDir}/${CLAUDE_ENV_FILE}`)}`}
34
40
  Restart=on-failure
35
41
  RestartForceExitStatus=75
36
42
  RestartSec=30
@@ -68,7 +74,7 @@ function checkFit(input) {
68
74
  };
69
75
  }
70
76
  function withSystemd(conf) {
71
- const lines = (conf ?? "").split("\n");
77
+ const lines = conf.split("\n");
72
78
  if (lines.at(-1) === "") lines.pop();
73
79
  const boot = lines.findIndex((line) => line.trim() === "[boot]");
74
80
  if (boot === -1) {
@@ -91,6 +97,54 @@ systemd=true
91
97
  return { text: `${lines.join("\n")}
92
98
  `, changed: true };
93
99
  }
100
+ function windowsAccessOff() {
101
+ return [
102
+ { section: "interop", key: "enabled" },
103
+ { section: "interop", key: "appendWindowsPath" },
104
+ { section: "automount", key: "enabled" }
105
+ ];
106
+ }
107
+ function withWindowsAccessOff(conf) {
108
+ const lines = conf.split("\n");
109
+ if (lines.at(-1) === "") lines.pop();
110
+ let changed = false;
111
+ for (const { section, key } of windowsAccessOff()) {
112
+ const header = (line) => {
113
+ const matched = /^\s*\[\s*([^\]]*?)\s*\]/.exec(line);
114
+ return matched === null ? void 0 : matched[1].toLowerCase();
115
+ };
116
+ const first = lines.findIndex((line) => header(line) === section);
117
+ const wanted = `${key}=false`;
118
+ if (first === -1) {
119
+ if (lines.length > 0 && lines.at(-1) !== "") lines.push("");
120
+ lines.push(`[${section}]`, wanted);
121
+ changed = true;
122
+ continue;
123
+ }
124
+ let found = false;
125
+ let inSection = false;
126
+ for (const [at, line] of lines.entries()) {
127
+ const name = header(line);
128
+ if (name !== void 0) {
129
+ inSection = name === section;
130
+ continue;
131
+ }
132
+ const match = inSection ? /^\s*([^=#;\s][^=]*?)\s*=\s*(.*?)\s*$/.exec(line) : null;
133
+ if (match === null || match[1].toLowerCase() !== key.toLowerCase()) continue;
134
+ found = true;
135
+ if (match[2].toLowerCase() !== "false") {
136
+ lines[at] = wanted;
137
+ changed = true;
138
+ }
139
+ }
140
+ if (!found) {
141
+ lines.splice(first + 1, 0, wanted);
142
+ changed = true;
143
+ }
144
+ }
145
+ return { text: `${lines.join("\n")}
146
+ `, changed };
147
+ }
94
148
  function taskNameFor(unitName) {
95
149
  return unitName;
96
150
  }
@@ -119,6 +173,48 @@ function defaultRun(args) {
119
173
 
120
174
  // src/runner/service/install.ts
121
175
  var DEFAULT_UNIT_NAME = "outerlayer-runner";
176
+ var LOAD_CREDENTIAL_SINCE = 247;
177
+ var CREDENTIAL_FILE_MODE = 384;
178
+ function prepareCredentialFile(configDir, lines) {
179
+ const claudePath = join(configDir, CLAUDE_ENV_FILE);
180
+ const runnerPath = join(configDir, "runner.env");
181
+ try {
182
+ const stored = existsSync(claudePath) ? readFileSync(claudePath, "utf8") : void 0;
183
+ if (stored !== void 0 && credentialLineIn(stored) !== void 0) return true;
184
+ const moved = existsSync(runnerPath) ? credentialLineIn(readFileSync(runnerPath, "utf8")) : void 0;
185
+ if (stored !== void 0 && moved === void 0) return true;
186
+ const kept = stored === void 0 || stored === "" ? "" : stored.endsWith("\n") ? stored : `${stored}
187
+ `;
188
+ const temporary = `${claudePath}.${process.pid}.tmp`;
189
+ writeFileSync(temporary, moved === void 0 ? kept : `${kept}${moved}
190
+ `, { mode: CREDENTIAL_FILE_MODE });
191
+ chmodSync(temporary, CREDENTIAL_FILE_MODE);
192
+ renameSync(temporary, claudePath);
193
+ return true;
194
+ } catch (err) {
195
+ lines.push(`${claudePath} could not be written (${err instanceof Error ? err.message : String(err)}), so nothing was changed`);
196
+ return false;
197
+ }
198
+ }
199
+ function finishCredentialMove(configDir, lines, reload) {
200
+ const runnerPath = join(configDir, "runner.env");
201
+ try {
202
+ if (!existsSync(runnerPath)) return;
203
+ if (credentialLineIn(readFileSync(join(configDir, CLAUDE_ENV_FILE), "utf8")) === void 0) return;
204
+ const text = withoutCredentialLines(readFileSync(runnerPath, "utf8"));
205
+ if (text === void 0) return;
206
+ if (reload !== void 0 && !reload()) {
207
+ lines.push(`the Claude credential is in ${join(configDir, CLAUDE_ENV_FILE)} and is also still in ${runnerPath}, because systemd may still hold the old unit: run \`sudo systemctl daemon-reload\`, then this command again`);
208
+ return;
209
+ }
210
+ const temporary = `${runnerPath}.${process.pid}.tmp`;
211
+ writeFileSync(temporary, text, { mode: CREDENTIAL_FILE_MODE });
212
+ chmodSync(temporary, CREDENTIAL_FILE_MODE);
213
+ renameSync(temporary, runnerPath);
214
+ } catch (err) {
215
+ lines.push(`the Claude credential is in ${join(configDir, CLAUDE_ENV_FILE)} and is also still in ${runnerPath}, which could not be changed (${err instanceof Error ? err.message : String(err)}): remove its line by hand`);
216
+ }
217
+ }
122
218
  function unitPathFor(unitName = DEFAULT_UNIT_NAME) {
123
219
  return `/etc/systemd/system/${unitName}.service`;
124
220
  }
@@ -146,9 +242,13 @@ function installService(request, deps) {
146
242
  const say = deps.say ?? ((line) => void lines.push(line));
147
243
  const kind = builtinKind(request.hooks.provision);
148
244
  const own = kind === "own" || builtinKind(request.hooks.cleanup) === "own";
245
+ const configDir = dirname(request.configPath);
246
+ const version = deps.systemd.version();
247
+ const credential = (version ?? 0) >= LOAD_CREDENTIAL_SINCE ? "load" : "environment-file";
149
248
  const unit = runnerUnit({
150
249
  user: request.user,
151
- configDir: dirname(request.configPath),
250
+ configDir,
251
+ credential,
152
252
  execStart: request.execStart,
153
253
  timeLimitMinutes: request.timeLimitMinutes,
154
254
  docker: kind === "container" || kind === "vm" || builtinKind(request.hooks.cleanup) === "container" || builtinKind(request.hooks.cleanup) === "vm",
@@ -165,7 +265,9 @@ function installService(request, deps) {
165
265
  }
166
266
  if (!deps.systemd.running()) {
167
267
  if (deps.platform === "wsl2" && deps.wslConf !== void 0) {
168
- const merged = withSystemd(deps.wslConf.read());
268
+ const current = deps.wslConf.read();
269
+ if (current.kind === "unreadable") return outcome(false, "refused", [unreadableConf(current.message)]);
270
+ const merged = withSystemd(current.kind === "text" ? current.text : "");
169
271
  if (merged.changed) {
170
272
  say("sudo tee /etc/wsl.conf");
171
273
  const wslConf = deps.wslConf;
@@ -183,57 +285,104 @@ function installService(request, deps) {
183
285
  if (!fit.fits) return outcome(false, "refused", [`${fit.message}. Nothing is set up: lower runner.concurrency or runner.build.memory, then run this again`]);
184
286
  }
185
287
  const existing = deps.systemd.read(unitPath);
288
+ const fallbackNote = () => {
289
+ if (credential === "load") return;
290
+ lines.push(
291
+ `the Claude credential stays in the service's environment: ${version === void 0 ? "the systemd version could not be read" : `systemd ${version} is older than ${LOAD_CREDENTIAL_SINCE}`}, and LoadCredential= needs ${LOAD_CREDENTIAL_SINCE} or later, so the unit loads claude.env with EnvironmentFile=`
292
+ );
293
+ };
186
294
  const write = () => {
187
295
  say(`sudo tee ${unitPath}`);
188
296
  return attempt(lines, () => deps.systemd.write(unitPath, unit));
189
297
  };
190
298
  const running = () => deps.systemd.systemctl(["is-enabled", unitName]).status === 0 && deps.systemd.systemctl(["is-active", unitName]).status === 0;
191
- const ensureTask = () => {
192
- if (deps.platform === "wsl2") lines.push(...ensureLoginTask(deps, unitName));
299
+ const windowsSteps = () => {
300
+ if (deps.platform !== "wsl2") return true;
301
+ lines.push(...ensureLoginTask(deps, unitName));
302
+ return ensureWindowsAccessOff(deps, unitName, say, lines);
193
303
  };
194
304
  if (existing === unit) {
305
+ if (!prepareCredentialFile(configDir, lines)) return outcome(false, "refused", lines);
195
306
  const wasRunning = running();
196
307
  if (!wasRunning && !asRoot(deps, lines, say, ["enable", "--now", unitName])) return outcome(false, "refused", lines);
308
+ finishCredentialMove(configDir, lines, () => asRoot(deps, lines, say, ["daemon-reload"]));
197
309
  if (wasRunning && request.restart === true) {
198
- ensureTask();
310
+ const windowsOk2 = windowsSteps();
311
+ const finish2 = (state) => windowsOk2 ? outcome(true, state, lines) : outcome(false, "refused", lines);
199
312
  if (deps.buildsRunning(runnerDir(request.configPath))) {
200
- lines.push(`the service ${unitName} is current; a build is running, so it was not restarted and reads runner.env at its next restart`);
201
- return outcome(true, "pending-restart", lines);
313
+ lines.push(`the service ${unitName} is current; a build is running, so it was not restarted and reads claude.env and runner.env at its next restart`);
314
+ fallbackNote();
315
+ return finish2("pending-restart");
202
316
  }
203
317
  if (!asRoot(deps, lines, say, ["restart", unitName])) return outcome(false, "refused", lines);
204
- lines.push(`restarted the service ${unitName}, so it reads runner.env`);
205
- return outcome(true, "updated", lines);
318
+ lines.push(`restarted the service ${unitName}, so it reads claude.env and runner.env`);
319
+ fallbackNote();
320
+ return finish2("updated");
206
321
  }
207
322
  lines.push(`the service ${unitName} is current: the unit already matches the config, so nothing was changed`);
208
- ensureTask();
323
+ fallbackNote();
324
+ if (!windowsSteps()) return outcome(false, "refused", lines);
209
325
  return outcome(true, "current", lines);
210
326
  }
211
327
  if (existing === void 0) {
328
+ if (!prepareCredentialFile(configDir, lines)) return outcome(false, "refused", lines);
212
329
  if (!write()) return outcome(false, "refused", lines);
213
330
  if (!asRoot(deps, lines, say, ["daemon-reload"]) || !asRoot(deps, lines, say, ["enable", "--now", unitName])) {
214
331
  say(`sudo rm ${unitPath}`);
215
332
  if (attempt(lines, () => deps.systemd.remove(unitPath))) deps.systemd.systemctl(["daemon-reload"], { sudo: true });
216
333
  return outcome(false, "refused", lines);
217
334
  }
335
+ finishCredentialMove(configDir, lines);
218
336
  lines.push(`installed and started the service ${unitName}: the runner starts at boot and after a crash`);
219
- ensureTask();
337
+ fallbackNote();
338
+ if (!windowsSteps()) return outcome(false, "refused", lines);
220
339
  return outcome(true, "installed", lines);
221
340
  }
222
341
  if (!existing.startsWith(UNIT_MARKER) && request.replace !== true) {
223
342
  lines.push(`${unitPath} differs from what this command writes, and it was not written by it, so it was left alone. Pass --replace to replace it, or \`--print\` to compare`);
224
343
  return outcome(false, "differs", lines);
225
344
  }
345
+ if (!prepareCredentialFile(configDir, lines)) return outcome(false, "refused", lines);
226
346
  if (!write()) return outcome(false, "refused", lines);
227
347
  if (!asRoot(deps, lines, say, ["daemon-reload"])) return outcome(false, "refused", lines);
228
348
  if ((!existing.startsWith(UNIT_MARKER) || !running()) && !asRoot(deps, lines, say, ["enable", "--now", unitName])) return outcome(false, "refused", lines);
229
- ensureTask();
349
+ finishCredentialMove(configDir, lines);
350
+ fallbackNote();
351
+ const windowsOk = windowsSteps();
352
+ const finish = (state) => windowsOk ? outcome(true, state, lines) : outcome(false, "refused", lines);
230
353
  if (deps.buildsRunning(runnerDir(request.configPath))) {
231
354
  lines.push(`rewrote ${unitPath}; a build is running, so the service was not restarted and the new unit applies at the next restart`);
232
- return outcome(true, "pending-restart", lines);
355
+ return finish("pending-restart");
233
356
  }
234
357
  if (!asRoot(deps, lines, say, ["restart", unitName])) return outcome(false, "refused", lines);
235
358
  lines.push(`rewrote ${unitPath} and restarted the service ${unitName}`);
236
- return outcome(true, "updated", lines);
359
+ return finish("updated");
360
+ }
361
+ var WINDOWS_ACCESS_SETTINGS = "`[interop] enabled=false`, `[interop] appendWindowsPath=false` and `[automount] enabled=false`, each key under the section header it names";
362
+ function unreadableConf(message) {
363
+ return `/etc/wsl.conf exists and could not be read (${message}), so it was not changed. Add ${WINDOWS_ACCESS_SETTINGS} to /etc/wsl.conf by hand, then restart the distribution`;
364
+ }
365
+ function ensureWindowsAccessOff(deps, unitName, say, lines) {
366
+ const host = deps.wslConf;
367
+ if (host === void 0) return true;
368
+ const current = host.read();
369
+ if (current.kind === "unreadable") {
370
+ lines.push(unreadableConf(current.message));
371
+ return false;
372
+ }
373
+ const merged = withWindowsAccessOff(current.kind === "text" ? current.text : "");
374
+ if (!merged.changed) return true;
375
+ say("sudo tee /etc/wsl.conf");
376
+ const written = attempt(lines, () => host.write(merged.text));
377
+ if (!written) {
378
+ lines.push(`/etc/wsl.conf was not changed. Add ${WINDOWS_ACCESS_SETTINGS} to /etc/wsl.conf by hand, then restart the distribution`);
379
+ return false;
380
+ }
381
+ const distro = deps.distro === void 0 || deps.distro === "" ? "<distribution>" : deps.distro;
382
+ lines.push(
383
+ `Windows interop and drive mounts stay on in this distribution until it restarts. A restart stops any running build. From Windows, run: \`wsl --terminate ${distro}\`, then \`schtasks /Run /TN ${taskNameFor(unitName)}\`${distro === "<distribution>" ? ", with the name `wsl -l` shows" : ""}`
384
+ );
385
+ return true;
237
386
  }
238
387
  function ensureLoginTask(deps, unitName) {
239
388
  const tasks = deps.tasks;
@@ -245,7 +394,9 @@ function ensureLoginTask(deps, unitName) {
245
394
  const command = taskCommand(deps.distro);
246
395
  const manual = `from Windows, run: schtasks /Create /F /TN ${name} /SC ONLOGON /TR "${command}"`;
247
396
  if (tasks === void 0 || !tasks.available()) {
248
- return [`Windows interop is off, so the scheduled task that starts WSL2 at login was not made: ${manual}`];
397
+ return [
398
+ `schtasks.exe cannot start from this distribution, so the scheduled task ${name} is neither checked nor made. From Windows, run \`schtasks /Query /TN ${name}\` to check for it, and if it is not there, run: schtasks /Create /F /TN ${name} /SC ONLOGON /TR "${command}"`
399
+ ];
249
400
  }
250
401
  if (tasks.exists(name)) return [`the scheduled task ${name} already starts WSL2 at login`];
251
402
  const created = tasks.create(name, command);
@@ -258,7 +409,12 @@ function uninstallService(request, deps) {
258
409
  const say = deps.say ?? ((line) => void lines.push(line));
259
410
  const taskName = taskNameFor(unitName);
260
411
  const removeTask = () => {
261
- if (deps.platform !== "wsl2" || deps.tasks === void 0 || !deps.tasks.available() || !deps.tasks.exists(taskName)) return;
412
+ if (deps.platform !== "wsl2") return;
413
+ if (deps.tasks === void 0 || !deps.tasks.available()) {
414
+ lines.push(`schtasks.exe cannot start from this distribution, so the scheduled task ${taskName} is neither checked nor removed: from Windows, run: schtasks /Delete /F /TN ${taskName}`);
415
+ return;
416
+ }
417
+ if (!deps.tasks.exists(taskName)) return;
262
418
  const removed = deps.tasks.remove(taskName);
263
419
  lines.push(removed.ok ? `removed the scheduled task ${taskName}` : `the scheduled task ${taskName} was not removed (${removed.message ?? "schtasks.exe failed"}): from Windows, run: schtasks /Delete /F /TN ${taskName}`);
264
420
  };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { BRIDGE_ADDRESS, TUNNEL_PORT, BRIDGE_CIDR } from './chunk-XS3FDWSZ.js';
3
+ import { BRIDGE_ADDRESS, TUNNEL_PORT, BRIDGE_CIDR } from './chunk-ZTY7HHYB.js';
4
+ import { EXEC_PORT } from './chunk-WWQVKFN6.js';
4
5
  import { startTimeOf } from './chunk-JBJTC3UU.js';
5
- import { EXEC_PORT } from './chunk-GLUKDQS4.js';
6
- import { RELAY_PORT } from './chunk-2I3LIRZP.js';
6
+ import { RELAY_PORT } from './chunk-HXAEQPZR.js';
7
7
  import { spawn, spawnSync } from 'child_process';
8
8
  import { symlinkSync, lstatSync, writeFileSync, chmodSync, mkdirSync } from 'fs';
9
9
 
@@ -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-RHAGBUL5.js';
4
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-5K3KB4YR.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from 'fs';
6
6
  import { dirname } from 'path';
7
7
 
@@ -1,32 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-6VFH52MP.js';
4
- import { writePendingUpdate } from './chunk-RHGF73IU.js';
5
- import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
6
- import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-ABXQBEYK.js';
3
+ import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-KU7QL4XW.js';
7
4
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
8
- import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
5
+ import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-E7R2GIAW.js';
9
6
  import { RUNNER_PROTOCOL } from './chunk-TPKYTORP.js';
10
- import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-ZFBJUOYT.js';
11
- import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-MATUHHN4.js';
7
+ import { writePendingUpdate } from './chunk-IVX3U7KV.js';
8
+ import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
9
+ import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-66T6XJAB.js';
10
+ import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-6S4V4UIC.js';
12
11
  import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
12
+ import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-GUXWQIEY.js';
13
13
  import { RepoFilter } from './chunk-TBT347UY.js';
14
- import { leaseTimeLeftMs, LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec, setUpRunnerCgroup, createContainerRuntime, measureDisk, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied, gitRemoteFor, startServicesFor, createLeaseChannel } from './chunk-R7SGBXUD.js';
15
- import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-WSYXLLA5.js';
16
- import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-M3MHHIUW.js';
14
+ import { leaseTimeLeftMs, createContainerRuntime, withTunnelLog, LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec, setUpRunnerCgroup, measureDisk, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied, gitRemoteFor, startServicesFor, createLeaseChannel } from './chunk-GLL4TN2M.js';
15
+ import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-USJZ2LDK.js';
16
+ import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-Z3ASAXVU.js';
17
17
  import { isVersion, compareVersions, satisfiesRange } from './chunk-TQMI335S.js';
18
- import { checkFit } from './chunk-7AQ5AM7U.js';
19
- import { fdName } from './chunk-YB3CSYXX.js';
20
- import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-D7ECMB7B.js';
18
+ import { checkFit } from './chunk-MQHTM4YJ.js';
19
+ import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-55XLX5PA.js';
20
+ import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-NUHZV3A4.js';
21
21
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
22
- import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-EX5MQYEF.js';
23
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-55GNQPO6.js';
24
- import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-EPPIISRD.js';
22
+ import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-VC5J7QPV.js';
25
23
  import { exceedsDisk } from './chunk-YJLHUKYS.js';
24
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-X52PMPOM.js';
25
+ import { loadHostKey, ensureHostKey, signerFor } from './chunk-YL2VDSNF.js';
26
+ import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, rootfsDir } from './chunk-5K3KB4YR.js';
27
+ import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, takeClaudeCredential, heldClaudeCredential, claudeCredential, currentClaudeCredential } from './chunk-HXAEQPZR.js';
26
28
  import { resolveVersion } from './chunk-RA3O54FC.js';
27
- import { loadHostKey, ensureHostKey, signerFor } from './chunk-Y4OKEFAX.js';
28
- import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, rootfsDir } from './chunk-RHAGBUL5.js';
29
- import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-2I3LIRZP.js';
29
+ import { fdName } from './chunk-XD4ZCMA4.js';
30
30
  import { COMMAND_LOST_REASON, CONTAINER_STOPPED_REASON } from './chunk-JGD5TWQ2.js';
31
31
  import { randomBytes } from 'crypto';
32
32
  import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync, statSync, readdirSync, readFileSync, closeSync, rmSync, openSync, constants, lstatSync } from 'fs';
@@ -76,7 +76,7 @@ function checkBlocked(config, probes) {
76
76
  }
77
77
  if (kind !== "own" && claudeCredential(probes.env) === void 0) {
78
78
  return {
79
- reason: "there is no Claude credential in the runner's environment. Put CLAUDE_CODE_OAUTH_TOKEN (from `claude setup-token`) or ANTHROPIC_API_KEY in the runner.env beside the config, then restart the service"
79
+ reason: "there is no Claude credential in the runner's environment. Store CLAUDE_CODE_OAUTH_TOKEN (from `claude setup-token`) or ANTHROPIC_API_KEY with `outerlayer runner init --agent claude`, which writes the claude.env beside the config, then restart the service"
80
80
  };
81
81
  }
82
82
  return void 0;
@@ -482,7 +482,9 @@ async function prepareUpdate(args) {
482
482
  return finish(args, retryFailure(version, err));
483
483
  }
484
484
  if (!verified.ok) return finish(args, { outcome: verified.outcome, reason: verified.reason });
485
- const staged = await deps.runNode([entryIn(verified.dir), "runner", "check", "--config", configPath], verified.dir);
485
+ const held = currentClaudeCredential(process.env);
486
+ const stagedEnv = held === void 0 ? void 0 : { ...process.env, [held.variable]: held.value };
487
+ const staged = await deps.runNode([entryIn(verified.dir), "runner", "check", "--config", configPath], verified.dir, stagedEnv);
486
488
  if (staged.status !== 0) {
487
489
  removeStaging(verified.dir);
488
490
  return finish(args, {
@@ -1089,7 +1091,7 @@ function leaseTimeLeftFor(state, active) {
1089
1091
  return () => (state.deps.leaseTimeLeftMs ?? leaseTimeLeftMs)(active.job, nowOf(state).getTime());
1090
1092
  }
1091
1093
  function runtimeOf(state) {
1092
- state.containerRuntime ??= createContainerRuntime(state.deps.container);
1094
+ state.containerRuntime ??= createContainerRuntime(withTunnelLog(state.deps.container, (line) => logOf(state).line(line)));
1093
1095
  return state.containerRuntime;
1094
1096
  }
1095
1097
  function finishDepsOf(state) {
@@ -1777,7 +1779,7 @@ var CLAIM_REFUSAL_CODES = new Set(
1777
1779
  "pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected repository_not_reachable branch_claimed_elsewhere".split(" ")
1778
1780
  );
1779
1781
  async function tryClaimAndStart(state, item, queue) {
1780
- const { postJson: postJson2 } = await import('./work-cmd-VECTYST6.js');
1782
+ const { postJson: postJson2 } = await import('./work-cmd-COESFSHE.js');
1781
1783
  const log = logOf(state);
1782
1784
  const hostKey = await loadHostKey(state.config.configPath);
1783
1785
  const claim = await retrySend(
@@ -2935,14 +2937,26 @@ async function logUnusableHelper(config, runtime, log) {
2935
2937
  if (helper.reason === "unsupported") log.line(helper.detail);
2936
2938
  else if (helper.unreachable === true) log.line(`${helper.detail}, so microVM builds run without the jailer`);
2937
2939
  }
2940
+ function hooksOf(configPath) {
2941
+ try {
2942
+ return loadRunnerConfig(configPath).hooks;
2943
+ } catch {
2944
+ return { provision: "builtin:container" };
2945
+ }
2946
+ }
2938
2947
  async function start(configPath, deps = { fetchImpl: fetch }) {
2939
2948
  const log = deps.log ??= createRunnerLog(deps.now ?? (() => /* @__PURE__ */ new Date()));
2949
+ takeClaudeCredential(process.env, hooksOf(configPath));
2940
2950
  const update = deps.update;
2941
2951
  if (update !== void 0) {
2942
2952
  const outcome = await onStartUnderMarker({
2943
2953
  configPath,
2944
2954
  own: ownVersionOf(deps),
2945
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-YTXFVWK7.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2955
+ check: update.check ? () => update.check(configPath) : async () => {
2956
+ const held = heldClaudeCredential();
2957
+ const env = held === void 0 ? process.env : { ...process.env, [held.variable]: held.value };
2958
+ return (await import('./check-YEI6TCUH.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
2959
+ },
2946
2960
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
2947
2961
  log
2948
2962
  });
@@ -3256,4 +3270,4 @@ function runnerProcessState(configPath) {
3256
3270
  return isSameProcess(entry.pid, entry.start) ? { state: "running", pid: entry.pid } : { state: "stale", pid: entry.pid };
3257
3271
  }
3258
3272
 
3259
- export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick };
3273
+ export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, runtimeOf, start, tick, watchTick };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-7OUOLGUV.js';
3
+ import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-JGML2VUN.js';
4
4
  import { cliInvocation } from './chunk-CRB3POP4.js';
5
5
  import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-RKOTJQVG.js';
6
6
  import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';