@outerlayer/cli 0.27.1 → 0.28.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 (128) hide show
  1. package/CHANGELOG.md +32 -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-NDDOASVO.js} +70 -61
  9. package/dist/{chunk-VS27BP3E.js → chunk-2YSCKEL2.js} +7 -7
  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-LPFOWUHG.js → chunk-6BWJQGTV.js} +20 -13
  17. package/dist/{chunk-BWH36FOC.js → chunk-7CK2TJFB.js} +20 -4
  18. package/dist/{chunk-5VMDGJGH.js → chunk-7UGFIWIW.js} +37 -23
  19. package/dist/{chunk-QKIQ2R7F.js → chunk-ATJOFXTE.js} +3 -3
  20. package/dist/chunk-CDDED64E.js +13 -0
  21. package/dist/{chunk-QHH4OSD4.js → chunk-CTYSTE5C.js} +1 -1
  22. package/dist/{chunk-DJHNEGNM.js → chunk-DKWQMPSL.js} +18 -2
  23. package/dist/{chunk-IMOB4IOI.js → chunk-DQYMQ47E.js} +3 -2
  24. package/dist/{chunk-YETTWTAY.js → chunk-E7R2GIAW.js} +4 -4
  25. package/dist/{chunk-GFUE5TKO.js → chunk-F4FA3ZUT.js} +24 -14
  26. package/dist/{chunk-6TRNCUM4.js → chunk-FGF52V4V.js} +1 -1
  27. package/dist/{chunk-MATUHHN4.js → chunk-GUXWQIEY.js} +1 -1
  28. package/dist/{chunk-2I3LIRZP.js → chunk-HXAEQPZR.js} +101 -10
  29. package/dist/{chunk-R7SGBXUD.js → chunk-IKXY47R5.js} +107 -56
  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-KVDVNOUK.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-7AQ5AM7U.js → chunk-MQHTM4YJ.js} +177 -21
  37. package/dist/{chunk-6KKM7VGZ.js → chunk-N7WAEEIU.js} +3 -3
  38. package/dist/{chunk-D7ECMB7B.js → chunk-NUHZV3A4.js} +1 -1
  39. package/dist/{chunk-MHX7YX7Y.js → chunk-P2RWZCV7.js} +1 -1
  40. package/dist/chunk-QBQHQEUG.js +300 -0
  41. package/dist/{chunk-FP23SVDD.js → chunk-QJFDAKRF.js} +5 -5
  42. package/dist/{chunk-WUL2OP5A.js → chunk-QKXF7CLR.js} +3 -3
  43. package/dist/{chunk-Y7ZCHBYB.js → chunk-QWAYRAUX.js} +3 -3
  44. package/dist/{chunk-64GMBWAK.js → chunk-R7SS5RLJ.js} +6 -6
  45. package/dist/{chunk-XZ6Q6ZNR.js → chunk-SATUCMAJ.js} +3 -2
  46. package/dist/{chunk-2BTFKNTR.js → chunk-SJZL5F3F.js} +2 -2
  47. package/dist/{chunk-HWDYLXHH.js → chunk-T2QSWFSU.js} +4 -4
  48. package/dist/{chunk-B7DJVG25.js → chunk-T57XUI6N.js} +3 -3
  49. package/dist/{chunk-E5IJ5533.js → chunk-TF7G2PR6.js} +3 -3
  50. package/dist/{chunk-O2IJTY7L.js → chunk-TVZAC2NP.js} +3 -3
  51. package/dist/{chunk-QE3UQAHK.js → chunk-UHU7H57K.js} +26 -7
  52. package/dist/{chunk-WSYXLLA5.js → chunk-USJZ2LDK.js} +6 -6
  53. package/dist/{chunk-EX5MQYEF.js → chunk-VC5J7QPV.js} +5 -5
  54. package/dist/{chunk-N4D5TMVU.js → chunk-VU7ZJPIR.js} +5 -5
  55. package/dist/{chunk-ZFBJUOYT.js → chunk-W3FSGH2M.js} +10 -10
  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-QC6ZKHPK.js} +149 -128
  64. package/dist/cli-update-notice-4DLZ3655.js +9 -0
  65. package/dist/{command-V7B7GTPZ.js → command-3F6GY4CK.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-P7O5XGOB.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-QPQDF7FB.js} +159 -41
  73. package/dist/{emit-artifact-cmd-ALDK55Y2.js → emit-artifact-cmd-O3IBUMUY.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-BNS57DD3.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-3DAGX7UY.js → init-36XMFFRQ.js} +38 -37
  88. package/dist/init-HHEAJDPN.js +56 -0
  89. package/dist/{init-cmd-RIDBVSE4.js → init-cmd-K2IKTSXJ.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-F5ASKFRJ.js +80 -0
  98. package/dist/{machine-OOQ2NXC3.js → machine-6STGIRJJ.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/{runner-env-YRRNRKF4.js → runner-env-EIB6WFPG.js} +6 -7
  107. package/dist/{runner-identity-YS2BZXZV.js → runner-identity-S3V6I4I3.js} +7 -6
  108. package/dist/{runner-key-EFNTZWNX.js → runner-key-Y76QXVNV.js} +36 -35
  109. package/dist/{session-sender-SC5PSU2G.js → session-sender-LFYMN6TT.js} +20 -17
  110. package/dist/{spec-cmd-JGYHHJ4P.js → spec-cmd-Z6MGATWC.js} +16 -13
  111. package/dist/{starter-pack-GPU4X6B7.js → starter-pack-5SOT5V4I.js} +4 -3
  112. package/dist/{status-7WM7S7JX.js → status-OANG2EM3.js} +39 -37
  113. package/dist/{sync-cmd-ATXJVS7S.js → sync-cmd-TNOOUPY2.js} +19 -16
  114. package/dist/{watch-M7NR3DOW.js → watch-HBNNYATF.js} +19 -16
  115. package/dist/{work-claim-cmd-DNUDZKJA.js → work-claim-cmd-CXALMILD.js} +21 -18
  116. package/dist/{work-cmd-VECTYST6.js → work-cmd-COESFSHE.js} +16 -13
  117. package/dist/{work-comment-cmd-F3NRWKPZ.js → work-comment-cmd-A4ZUVCSA.js} +16 -13
  118. package/dist/{work-logs-cmd-QF6P32FE.js → work-logs-cmd-CTF43MBE.js} +16 -13
  119. package/dist/{work-open-pr-cmd-XE23JA3R.js → work-open-pr-cmd-EMGYJXVD.js} +17 -14
  120. package/dist/{work-pr-cmd-BH56GUKN.js → work-pr-cmd-FEXMS6RH.js} +16 -13
  121. package/dist/{work-stop-cmd-C3F5HNUO.js → work-stop-cmd-NIHAN45R.js} +16 -13
  122. package/package.json +1 -1
  123. package/dist/build-HRLACBOZ.js +0 -12
  124. package/dist/chunk-STSLH5EJ.js +0 -71
  125. package/dist/init-SWKYV6CL.js +0 -55
  126. package/dist/loop-AIJZVUNA.js +0 -79
  127. package/dist/pending-3YZCSKON.js +0 -9
  128. package/dist/{chunk-6BLXUD56.js → chunk-HOU33DW5.js} +1 -1
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { keepStagedContext, describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript } from './chunk-WSYXLLA5.js';
4
- import { runnerImageVersion } from './chunk-M3MHHIUW.js';
5
- import { realFdStorePort } from './chunk-YB3CSYXX.js';
6
- import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-HWDYLXHH.js';
3
+ import { execCapture } from './chunk-MHAR6S7B.js';
4
+ import { GUEST_CID } from './chunk-WWQVKFN6.js';
5
+ import { keepStagedContext, describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript } from './chunk-USJZ2LDK.js';
6
+ import { runnerImageVersion } from './chunk-Z3ASAXVU.js';
7
+ import { hostAllowed } from './chunk-UXYLWVTQ.js';
8
+ import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-T2QSWFSU.js';
7
9
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
8
10
  import { currentCliBuild } from './chunk-OGFGZQA3.js';
9
- import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, JUDGE_DIR, JUDGE_REPORT, MAX_REPORT_BYTES, spawnRun } from './chunk-EX5MQYEF.js';
10
- import { FIRECRACKER_VERSION, hostHelperPinned, firecrackerArch, MICROVM_ARCHES, RecipeError, DOCKER_FEATURE, CLAUDE_CODE_VERSION, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, DEFAULT_BASE_IMAGE } from './chunk-2BTFKNTR.js';
11
- import { execCapture } from './chunk-XBPUTQ7E.js';
12
- import { GUEST_CID } from './chunk-GLUKDQS4.js';
13
- import { WorkCommandError } from './chunk-55GNQPO6.js';
14
- import { hostAllowed } from './chunk-UXYLWVTQ.js';
11
+ import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, JUDGE_DIR, JUDGE_REPORT, MAX_REPORT_BYTES, spawnRun } from './chunk-VC5J7QPV.js';
15
12
  import { readDu } from './chunk-YJLHUKYS.js';
16
- import { sharedSkillNames, skillConflictMessage } from './chunk-6TRNCUM4.js';
13
+ import { FIRECRACKER_VERSION, hostHelperPinned, firecrackerArch, MICROVM_ARCHES, RecipeError, DOCKER_FEATURE, CLAUDE_CODE_VERSION, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, DEFAULT_BASE_IMAGE } from './chunk-SJZL5F3F.js';
14
+ import { WorkCommandError } from './chunk-X52PMPOM.js';
15
+ import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-UHU7H57K.js';
16
+ import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, SHIM_DIR } from './chunk-5K3KB4YR.js';
17
+ import { repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT } from './chunk-HXAEQPZR.js';
18
+ import { sharedSkillNames, skillConflictMessage } from './chunk-FGF52V4V.js';
17
19
  import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
18
- import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-QE3UQAHK.js';
19
20
  import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-RKOTJQVG.js';
20
21
  import { downconvertSession } from './chunk-QZBXLLTV.js';
21
- import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, SHIM_DIR } from './chunk-RHAGBUL5.js';
22
- import { repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT } from './chunk-2I3LIRZP.js';
22
+ import { realFdStorePort } from './chunk-XD4ZCMA4.js';
23
23
  import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, DOCKER_DESKTOP_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, MAX_OPEN_STREAMS, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-JGD5TWQ2.js';
24
- import { readFileSync, mkdirSync, existsSync, mkdtempSync, rmSync, chmodSync, truncateSync, writeFileSync, readdirSync, lstatSync, copyFileSync, accessSync, constants, statSync, rmdirSync, renameSync, unlinkSync, openSync, closeSync, createWriteStream, createReadStream } from 'fs';
25
- import { join, dirname, basename } from 'path';
24
+ import { readFileSync, mkdirSync, existsSync, mkdtempSync, rmSync, chmodSync, truncateSync, writeFileSync, readdirSync, lstatSync, copyFileSync, accessSync, constants, statSync, rmdirSync, renameSync, unlinkSync, openSync, closeSync, createWriteStream, createReadStream, writeSync } from 'fs';
25
+ import { join, dirname, resolve, basename } from 'path';
26
26
  import { isIP, createConnection, connect, createServer as createServer$1 } from 'net';
27
27
  import { spawnSync, spawn } from 'child_process';
28
28
  import { availableParallelism, networkInterfaces } from 'os';
@@ -51,7 +51,8 @@ function prepareRunnerCgroup(setup) {
51
51
  if (root === void 0) return void 0;
52
52
  const { fs } = setup;
53
53
  if (!fs.exists(root) || !fs.writable(join(root, "cgroup.procs"))) return void 0;
54
- if (!(fs.read(join(root, "cgroup.controllers")) ?? "").split(/\s+/).includes("memory")) return void 0;
54
+ const controllers = (fs.read(join(root, "cgroup.controllers")) ?? "").split(/\s+/);
55
+ if (!controllers.includes("memory")) return void 0;
55
56
  for (const name of fs.list(root)) {
56
57
  if (!name.startsWith(BUILD_PREFIX)) continue;
57
58
  try {
@@ -61,7 +62,7 @@ function prepareRunnerCgroup(setup) {
61
62
  }
62
63
  if (!fs.exists(join(root, LEAF))) fs.mkdir(join(root, LEAF));
63
64
  fs.write(join(root, LEAF, "cgroup.procs"), String(setup.pid));
64
- fs.write(join(root, "cgroup.subtree_control"), "+memory");
65
+ fs.write(join(root, "cgroup.subtree_control"), controllers.includes("io") ? "+memory +io" : "+memory");
65
66
  return { root };
66
67
  }
67
68
  var BUILD_RECLAIM_HEADROOM_BYTES = 256 * 1024 ** 2;
@@ -161,7 +162,7 @@ var START_TIMEOUT_MS = 12e4;
161
162
  var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
162
163
  var MAX_REPLY_BYTES = 1024 * 1024;
163
164
  function ask(socketPath, request, timeoutMs) {
164
- return new Promise((resolve, reject) => {
165
+ return new Promise((resolve2, reject) => {
165
166
  const conn = createConnection(socketPath);
166
167
  let text = "";
167
168
  let settled = false;
@@ -187,7 +188,7 @@ function ask(socketPath, request, timeoutMs) {
187
188
  return reject(new Error(`the helper at ${socketPath} sent a reply that is not JSON`));
188
189
  }
189
190
  if (reply.status === "refused") return reject(new HelperRefusal(String(reply.code ?? "refused"), String(reply.reason ?? "the helper refused the request")));
190
- resolve(reply);
191
+ resolve2(reply);
191
192
  });
192
193
  });
193
194
  conn.on("error", (err) => settle(() => reject(new Error(`the helper at ${socketPath} did not answer: ${err.message}`))));
@@ -374,6 +375,10 @@ function formatCpuList(cores) {
374
375
  }
375
376
  return parts.join(",");
376
377
  }
378
+ function capCpus(wanted, cpuset) {
379
+ const cores = cpuset === void 0 ? void 0 : parseCpuList(cpuset);
380
+ return cores === void 0 ? wanted : Math.min(wanted, cores.length);
381
+ }
377
382
  function usableCpus(deps = {}) {
378
383
  try {
379
384
  const status = (deps.readStatus ?? (() => readFileSync("/proc/self/status", "utf8")))();
@@ -643,9 +648,9 @@ function createContainerHost(deps = {}) {
643
648
  stderr = (stderr + chunk.toString()).slice(-400);
644
649
  });
645
650
  child.stderr?.on("error", () => void 0);
646
- const exited = new Promise((resolve) => {
647
- child.once("error", () => resolve(-1));
648
- child.once("close", (code) => resolve(code ?? -1));
651
+ const exited = new Promise((resolve2) => {
652
+ child.once("error", () => resolve2(-1));
653
+ child.once("close", (code) => resolve2(code ?? -1));
649
654
  });
650
655
  child.stdin.on("error", () => void 0);
651
656
  return { stdin: child.stdin, stdout: child.stdout, exited, kill: () => void child.kill("SIGKILL"), stderrTail: () => stderr };
@@ -717,7 +722,7 @@ function converterArgs(dest, memoryBytes, extra, script) {
717
722
  }
718
723
  var firstLine2 = (text) => text.trim().split("\n")[0] ?? "";
719
724
  function exportInto(container, converter) {
720
- return new Promise((resolve, reject) => {
725
+ return new Promise((resolve2, reject) => {
721
726
  const exporter = spawn("docker", ["export", container], { stdio: ["ignore", "pipe", "pipe"], env: childEnvironment(process.env) });
722
727
  const writer = spawn("docker", converter, { stdio: ["pipe", "ignore", "pipe"], env: childEnvironment(process.env) });
723
728
  const errors = [];
@@ -734,7 +739,7 @@ function exportInto(container, converter) {
734
739
  if (code !== 0 && failure2 === void 0) failure2 = `${name} exited ${code}`;
735
740
  exits += 1;
736
741
  if (exits < 2) return;
737
- if (failure2 === void 0) resolve();
742
+ if (failure2 === void 0) resolve2();
738
743
  else reject(new Error(`${failure2}: ${firstLine2(errors.join("\n"))}`));
739
744
  };
740
745
  exporter.once("exit", (code) => done("docker export", code));
@@ -819,6 +824,46 @@ async function createBuildDisk(input) {
819
824
  function deleteBuildDisk(path) {
820
825
  rmSync(path, { force: true });
821
826
  }
827
+ var CONSOLE_CUT_NOTE = "[outerlayer runner: cut the console at 8 MiB; the microVM keeps running]\n";
828
+ function pumpConsole(fd, streams) {
829
+ const cap = 8 * 1024 ** 2;
830
+ let written = 0;
831
+ let lastByte = 10;
832
+ let cut = false;
833
+ const append = (data) => {
834
+ try {
835
+ writeSync(fd, data);
836
+ } catch {
837
+ }
838
+ };
839
+ const onData = (chunk) => {
840
+ if (cut) return;
841
+ const room = cap - written;
842
+ if (chunk.length <= room) {
843
+ append(chunk);
844
+ written += chunk.length;
845
+ lastByte = chunk[chunk.length - 1] ?? lastByte;
846
+ return;
847
+ }
848
+ const head = chunk.subarray(0, room);
849
+ append(head);
850
+ if (head.length > 0) lastByte = head[head.length - 1];
851
+ append(Buffer.from(`${lastByte === 10 ? "" : "\n"}${CONSOLE_CUT_NOTE}`));
852
+ written = cap;
853
+ cut = true;
854
+ };
855
+ let open = streams.length;
856
+ for (const stream of streams) {
857
+ stream.on("data", onData);
858
+ stream.on("error", () => void 0);
859
+ stream.once("close", () => {
860
+ open -= 1;
861
+ if (open === 0) closeSync(fd);
862
+ });
863
+ }
864
+ }
865
+
866
+ // src/runner/microvm/firecracker.ts
822
867
  var clearBit = (bit) => `0b${"x".repeat(31 - bit)}0${"x".repeat(bit)}`;
823
868
  var CPU_TEMPLATE = {
824
869
  cpuid_modifiers: [
@@ -859,8 +904,9 @@ function machineConfig(limits2, paths) {
859
904
  }
860
905
  function firecrackerCommand(input) {
861
906
  const args = ["--no-api", "--config-file", input.configPath];
862
- if (input.cgroup === void 0) return { command: input.binary, args };
863
- return { command: "sh", args: ["-c", 'echo $$ > "$1/cgroup.procs" && shift && exec "$@"', "sh", input.cgroup, input.binary, ...args] };
907
+ const binary = resolve(input.binary);
908
+ if (input.cgroup === void 0) return { command: binary, args };
909
+ return { command: "/bin/sh", args: ["-c", 'echo $$ > "$1/cgroup.procs" && shift && exec "$@"', "sh", input.cgroup, binary, ...args] };
864
910
  }
865
911
  var STOP_WAIT_MS = 1e4;
866
912
  var POLL_MS = 20;
@@ -874,6 +920,7 @@ function isZombie(pid) {
874
920
  }
875
921
  function createFirecrackerHost(options = {}) {
876
922
  const launch = options.launch ?? firecrackerCommand;
923
+ const spawnChild = options.spawnChild ?? spawn;
877
924
  const exits = /* @__PURE__ */ new Map();
878
925
  const alive = (vm) => isSameProcess(vm.pid, vm.start) && !isZombie(vm.pid);
879
926
  return {
@@ -881,18 +928,22 @@ function createFirecrackerHost(options = {}) {
881
928
  const { command, args } = launch(input);
882
929
  mkdirSync(dirname(input.consolePath), { recursive: true });
883
930
  const consoleFd = openSync(input.consolePath, "a", 384);
931
+ let pumping = false;
884
932
  try {
885
- const child = spawn(command, args, { detached: true, stdio: ["ignore", consoleFd, consoleFd] });
933
+ const child = spawnChild(command, args, { detached: true, stdio: ["ignore", "pipe", "pipe"], env: {} });
934
+ pumpConsole(consoleFd, [child.stdout, child.stderr]);
935
+ pumping = true;
936
+ for (const stream of [child.stdout, child.stderr]) stream.unref?.();
886
937
  const failed = new Promise((_resolve, reject) => child.once("error", reject));
887
938
  const pid = child.pid;
888
939
  if (pid === void 0) return await failed;
889
- exits.set(pid, new Promise((resolve) => child.once("exit", () => resolve())));
940
+ exits.set(pid, new Promise((resolve2) => child.once("exit", () => resolve2())));
890
941
  child.unref();
891
942
  const start = startTimeOf(pid);
892
943
  if (start === null) throw new Error(`${command} exited as soon as it started; its console is at ${input.consolePath}`);
893
944
  return { pid, start };
894
945
  } finally {
895
- closeSync(consoleFd);
946
+ if (!pumping) closeSync(consoleFd);
896
947
  }
897
948
  },
898
949
  async stop(vm) {
@@ -903,8 +954,8 @@ function createFirecrackerHost(options = {}) {
903
954
  }
904
955
  const exited = exits.get(vm.pid);
905
956
  const deadline = Date.now() + STOP_WAIT_MS;
906
- if (exited !== void 0) await Promise.race([exited, new Promise((resolve) => setTimeout(resolve, STOP_WAIT_MS))]);
907
- while (alive(vm) && Date.now() < deadline) await new Promise((resolve) => setTimeout(resolve, POLL_MS));
957
+ if (exited !== void 0) await Promise.race([exited, new Promise((resolve2) => setTimeout(resolve2, STOP_WAIT_MS))]);
958
+ while (alive(vm) && Date.now() < deadline) await new Promise((resolve2) => setTimeout(resolve2, POLL_MS));
908
959
  exits.delete(vm.pid);
909
960
  },
910
961
  alive
@@ -1366,11 +1417,11 @@ function serveSession(transport, services, opts = {}) {
1366
1417
  session.setLocalWindowSize(SESSION_WINDOW);
1367
1418
  } catch {
1368
1419
  }
1369
- const ended = new Promise((resolve) => {
1420
+ const ended = new Promise((resolve2) => {
1370
1421
  session.on("error", (err) => {
1371
1422
  if (typeof err.code === "string" && err.code.startsWith("ERR_HTTP2_")) malformed = true;
1372
1423
  });
1373
- session.on("close", () => resolve({ malformed, served }));
1424
+ session.on("close", () => resolve2({ malformed, served }));
1374
1425
  });
1375
1426
  session.on("stream", (stream, headers) => {
1376
1427
  stream.on("error", noop);
@@ -1404,14 +1455,14 @@ var JOINED_AFTER_MS = 2e3;
1404
1455
  var EXIT_WAIT_MS = 5e3;
1405
1456
  function exitedWithin(stream, ms) {
1406
1457
  let timer;
1407
- const late = new Promise((resolve) => {
1408
- timer = setTimeout(() => resolve(void 0), ms);
1458
+ const late = new Promise((resolve2) => {
1459
+ timer = setTimeout(() => resolve2(void 0), ms);
1409
1460
  timer.unref();
1410
1461
  });
1411
1462
  return Promise.race([stream.exited, late]).finally(() => clearTimeout(timer));
1412
1463
  }
1413
1464
  function superviseRelay(input) {
1414
- const sleep = input.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1465
+ const sleep = input.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
1415
1466
  const exitWaitMs = input.exitWaitMs ?? EXIT_WAIT_MS;
1416
1467
  let closed = false;
1417
1468
  let fatal;
@@ -1461,7 +1512,7 @@ function superviseRelay(input) {
1461
1512
  input.log?.(`could not join the relay in ${input.container}${status === 0 || status === void 0 ? "" : ` (exec exited ${status})`}${reason === "" ? "" : `: ${reason}`} \xB7 trying again`);
1462
1513
  }
1463
1514
  if (closed) return;
1464
- await Promise.race([sleep(backoff), new Promise((resolve) => wake = resolve)]);
1515
+ await Promise.race([sleep(backoff), new Promise((resolve2) => wake = resolve2)]);
1465
1516
  backoff = Math.min(backoff * 2, LONGEST_BACKOFF_MS);
1466
1517
  }
1467
1518
  })();
@@ -1652,9 +1703,9 @@ async function git(args, cwd, env, input) {
1652
1703
  if (size < maxOutputBytes) out.push(chunk);
1653
1704
  size += chunk.length;
1654
1705
  });
1655
- const closed = new Promise((resolve, reject) => {
1706
+ const closed = new Promise((resolve2, reject) => {
1656
1707
  child.once("error", reject);
1657
- child.once("close", (status) => resolve(status));
1708
+ child.once("close", (status) => resolve2(status));
1658
1709
  });
1659
1710
  if (input !== void 0) {
1660
1711
  await pipeline(input, child.stdin).catch(() => void 0);
@@ -1851,14 +1902,14 @@ async function drain(req) {
1851
1902
  }
1852
1903
  }
1853
1904
  function readPrefix(req, gzip) {
1854
- return new Promise((resolve, reject) => {
1905
+ return new Promise((resolve2, reject) => {
1855
1906
  const held = [];
1856
1907
  const finish = (section) => {
1857
1908
  req.off("data", onData);
1858
1909
  req.off("end", onEnd);
1859
1910
  req.off("error", reject);
1860
1911
  req.pause();
1861
- resolve({ held, section });
1912
+ resolve2({ held, section });
1862
1913
  };
1863
1914
  const onData = (chunk) => {
1864
1915
  held.push(chunk);
@@ -1872,19 +1923,19 @@ function readPrefix(req, gzip) {
1872
1923
  });
1873
1924
  }
1874
1925
  function readBody(req, limit) {
1875
- return new Promise((resolve, reject) => {
1926
+ return new Promise((resolve2, reject) => {
1876
1927
  const chunks = [];
1877
1928
  let size = 0;
1878
1929
  req.on("data", (chunk) => {
1879
1930
  size += chunk.length;
1880
1931
  if (size > limit) {
1881
1932
  req.pause();
1882
- resolve(void 0);
1933
+ resolve2(void 0);
1883
1934
  return;
1884
1935
  }
1885
1936
  chunks.push(chunk);
1886
1937
  });
1887
- req.once("end", () => resolve(Buffer.concat(chunks)));
1938
+ req.once("end", () => resolve2(Buffer.concat(chunks)));
1888
1939
  req.once("error", reject);
1889
1940
  });
1890
1941
  }
@@ -1898,7 +1949,7 @@ function createGitRemote(options) {
1898
1949
  const { route, res } = input;
1899
1950
  const url = new URL(`${gitUrl}/${route.owner}/${route.name}.git/${route.kind === "info-refs" ? "info/refs" : route.kind === "lfs-batch" ? "info/lfs/objects/batch" : `git-${route.kind}`}${route.search === "" ? "" : `?${route.search}`}`);
1900
1951
  const send = url.protocol === "https:" ? request$1 : request;
1901
- return new Promise((resolve) => {
1952
+ return new Promise((resolve2) => {
1902
1953
  const upstream = send(url, { method: input.method, headers: { ...input.headers, connection: "close" } }, (answer) => {
1903
1954
  const headers = {};
1904
1955
  for (const [name, value] of Object.entries(answer.headers)) {
@@ -1920,18 +1971,18 @@ function createGitRemote(options) {
1920
1971
  });
1921
1972
  answer.once("end", () => {
1922
1973
  res.end();
1923
- resolve();
1974
+ resolve2();
1924
1975
  });
1925
1976
  answer.once("error", () => {
1926
1977
  res.destroy();
1927
- resolve();
1978
+ resolve2();
1928
1979
  });
1929
1980
  });
1930
1981
  upstream.on("error", (err) => {
1931
1982
  log(`could not reach GitHub for ${route.kind}: ${err.message}`);
1932
1983
  if (res.headersSent) res.destroy();
1933
1984
  else plain(res, 502, "the runner could not reach GitHub\n");
1934
- resolve();
1985
+ resolve2();
1935
1986
  });
1936
1987
  res.once("close", () => upstream.destroy());
1937
1988
  input.feed(upstream);
@@ -2249,7 +2300,7 @@ async function startTunnel(socketPath, opts = {}) {
2249
2300
  if (Buffer.byteLength(socketPath) > MAX_SOCKET_PATH_BYTES) {
2250
2301
  throw new Error(`${socketPath} is too long for a Unix socket; keep the runner's config file nearer the root of the filesystem`);
2251
2302
  }
2252
- const resolve = opts.resolve ?? systemResolve;
2303
+ const resolve2 = opts.resolve ?? systemResolve;
2253
2304
  const openConnection = opts.connect ?? ((t) => connect({ host: t.address, port: t.port }));
2254
2305
  const ownAddresses = opts.hostAddresses ?? systemHostAddresses;
2255
2306
  const connectTimeoutMs = opts.connectTimeoutMs ?? CONNECT_TIMEOUT_MS;
@@ -2333,7 +2384,7 @@ async function startTunnel(socketPath, opts = {}) {
2333
2384
  }
2334
2385
  let addresses;
2335
2386
  try {
2336
- addresses = await resolve(host);
2387
+ addresses = await resolve2(host);
2337
2388
  } catch {
2338
2389
  return { ok: false, status: 502, body: `could not resolve ${host}
2339
2390
  ` };
@@ -2534,7 +2585,7 @@ function createContainerRuntime(opts = {}) {
2534
2585
  )),
2535
2586
  startTunnel: opts.startTunnel ?? startTunnel,
2536
2587
  tunnelOptions: opts.tunnelOptions,
2537
- sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
2588
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms))),
2538
2589
  hostEnv: opts.hostEnv ?? process.env,
2539
2590
  platform: opts.platform ?? process.platform,
2540
2591
  credentials: opts.credentials ?? /* @__PURE__ */ new Map(),
@@ -2835,7 +2886,7 @@ async function provisionContainer(input) {
2835
2886
  } catch (err) {
2836
2887
  return bail(`the tunnel could not start: ${describeCallFailure(err)}`);
2837
2888
  }
2838
- const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096, cpuset: state.cpuset };
2889
+ const limits2 = { memory: config.build?.memory ?? "8g", cpus: capCpus(config.build?.cpus ?? 4, state.cpuset), pids: config.build?.pids ?? 4096, cpuset: state.cpuset };
2839
2890
  const runnerId = runnerLabelValue(config.configPath);
2840
2891
  const volume = await host.createVolume(name, { [BUILD_LABEL]: buildId, [RUNNER_LABEL]: runnerId });
2841
2892
  if (volume.status !== 0) return dockerFailed("creating the build's volume", volume);
@@ -3017,8 +3068,8 @@ async function stopContainer(runtime, state) {
3017
3068
  var DISK_CHECK_MS = 12e4;
3018
3069
  async function measureDisk(runtime, state) {
3019
3070
  let timer;
3020
- const late = new Promise((resolve) => {
3021
- timer = setTimeout(() => resolve({ failure: "du ran past 2 minutes" }), DISK_CHECK_MS);
3071
+ const late = new Promise((resolve2) => {
3072
+ timer = setTimeout(() => resolve2({ failure: "du ran past 2 minutes" }), DISK_CHECK_MS);
3022
3073
  });
3023
3074
  try {
3024
3075
  const run = runtime.host.exec(
@@ -3306,7 +3357,7 @@ async function startCheckContainer(input) {
3306
3357
  } catch (err) {
3307
3358
  return fail(`the tunnel could not start: ${describeCallFailure(err)}`);
3308
3359
  }
3309
- const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096, cpuset };
3360
+ const limits2 = { memory: config.build?.memory ?? "8g", cpus: capCpus(config.build?.cpus ?? 4, cpuset), pids: config.build?.pids ?? 4096, cpuset };
3310
3361
  const runnerId = runnerLabelValue(config.configPath);
3311
3362
  const volume = await host.createVolume(name, { [BUILD_LABEL]: buildId, [RUNNER_LABEL]: runnerId });
3312
3363
  if (volume.status !== 0) return dockerFailed("creating the check environment's volume", volume);
@@ -1,18 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-XZ6Q6ZNR.js';
4
- import { skillsBaseFor, isAgentsMdLayout } from './chunk-LOKSLO25.js';
5
- import { findGitDirs } from './chunk-BJ3KTMDH.js';
6
- import { machineSkillsState, staleClaudeSkills } from './chunk-IMOB4IOI.js';
7
- import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, skillDir, namesCore, MACHINE_SKILL_PATH, AGENTS_SKILLS_BASE, MAINTAINED_SKILLS, isMaintainedCopy, loadTemplateFiles, rewriteSkillPaths, restoreSkillPaths, TEMPLATE_SKILLS } from './chunk-7OUOLGUV.js';
8
3
  import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-KT4CN6OU.js';
4
+ import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-SATUCMAJ.js';
5
+ import { skillsBaseFor } from './chunk-5B7BEQPR.js';
6
+ import { findGitDirs } from './chunk-BJ3KTMDH.js';
7
+ import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, skillDir, loadTemplateFiles, rewriteSkillPaths, restoreSkillPaths, TEMPLATE_SKILLS } from './chunk-JGML2VUN.js';
9
8
  import { cliInvocation } from './chunk-CRB3POP4.js';
10
9
  import { hasSymlinkComponent } from './chunk-VWFOKRYS.js';
11
10
  import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
12
- import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-RKOTJQVG.js';
13
11
  import { createHash } from 'crypto';
14
- import { existsSync, readFileSync, realpathSync } from 'fs';
15
- import { join, dirname } from 'path';
12
+ import { existsSync, readFileSync } from 'fs';
13
+ import { join } from 'path';
16
14
 
17
15
  createRequire(import.meta.url);
18
16
  var SHIPPED_MANIFEST = "shipped.json";
@@ -190,138 +188,5 @@ function checkStarterFiles(cwd, opts = {}) {
190
188
  const fix = actionable ? `Run \`${UPDATE}\` to update the outdated files and write the missing ones. It never changes a file you edited.${compare}` : "Reinstall the CLI: `npm install -g @outerlayer/cli`, or run it with `npx -y @outerlayer/cli`.";
191
189
  return { checks: [{ name: NAME, status: "warn", detail: parts.join("; "), fix }], mcpOutdated };
192
190
  }
193
- var BUILD_PHASES = ["Intake", "Criteria", "Implement", "Review", "Pull request", "Evidence"];
194
- var MACHINE_CORE = `${MACHINE_SKILL_PATH}/outerlayer-build/SKILL.md`;
195
- var CHANGES_HEADING = "## Changes for this repository";
196
- var NAME2 = "Build skill";
197
- function changeHeadings(text) {
198
- const lines = text.split(/\r?\n/);
199
- const start = lines.findIndex((line) => line.trim() === CHANGES_HEADING);
200
- if (start === -1) return [];
201
- const headings = [];
202
- for (const line of lines.slice(start + 1)) {
203
- if (/^## /.test(line)) break;
204
- const match = /^### (.+?)\s*$/.exec(line);
205
- if (match) headings.push(match[1]);
206
- }
207
- return headings;
208
- }
209
- function skillsFolders() {
210
- const probe = `${skillDir("probe")}/SKILL.md`;
211
- const compiled = emitTree({
212
- entries: classifyTree([probe]).entries,
213
- contents: /* @__PURE__ */ new Map([[probe, "---\nname: probe\ndescription: probe\n---\n"]]),
214
- assetPaths: [],
215
- targets: [...ALL_TARGET_IDS]
216
- });
217
- return [...new Set(compiled.files.map((file) => dirname(dirname(file.path))))].sort();
218
- }
219
- function shortBuild() {
220
- const file = loadTemplateFiles().find((f) => f.path === `${skillDir("build")}/SKILL.md`);
221
- if (file === void 0) return "";
222
- return splitRawFile(file.content).body.split("\n").filter((line) => !line.startsWith("<!--")).join("\n").trim();
223
- }
224
- var read = (abs) => {
225
- try {
226
- return readFileSync(abs, "utf8");
227
- } catch {
228
- return void 0;
229
- }
230
- };
231
- function buildsOf(repoRoot, folders) {
232
- const source = `${folders[0]}/build/SKILL.md`;
233
- return (existsSync(join(repoRoot, source)) ? [source] : folders.slice(1).map((f) => `${f}/build/SKILL.md`)).map((path) => ({ path, text: read(join(repoRoot, path)) })).filter((b) => b.text !== void 0);
234
- }
235
- function checkBuildSkill(repoRoot) {
236
- const folders = [".outerlayer/skills", ...skillsFolders()];
237
- const builds = buildsOf(repoRoot, folders);
238
- const checks = [];
239
- const detached = builds.filter((b) => !namesCore(b.text));
240
- if (detached.length > 0) {
241
- checks.push({
242
- name: NAME2,
243
- status: "warn",
244
- detail: `${detached.map((b) => b.path).join(", ")} does not name outerlayer-build, so it gets no updates from the core`,
245
- fix: `Move to the short build, and put your own changes under the name of the phase each applies to:
246
-
247
- ${shortBuild()}`
248
- });
249
- }
250
- for (const build of builds.filter((b) => namesCore(b.text))) {
251
- const unknown = changeHeadings(build.text).filter((heading) => !BUILD_PHASES.includes(heading));
252
- if (unknown.length === 0) continue;
253
- checks.push({
254
- name: NAME2,
255
- status: "warn",
256
- detail: `${build.path} has ${unknown.map((h) => `"${h}"`).join(", ")} under "Changes for this repository", which matches no phase`,
257
- fix: `Rename each heading to a phase: ${BUILD_PHASES.join(", ")}.`
258
- });
259
- }
260
- const agentsMd = isAgentsMdLayout(repoRoot);
261
- const seen = /* @__PURE__ */ new Set();
262
- const lacking = folders.filter((folder) => {
263
- const text = read(join(repoRoot, folder, "build", "SKILL.md")) ?? "";
264
- if (!namesCore(text) || text.includes(MACHINE_CORE) || existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))) return false;
265
- let key = folder;
266
- try {
267
- key = realpathSync(join(repoRoot, folder));
268
- } catch {
269
- }
270
- if (seen.has(key)) return false;
271
- seen.add(key);
272
- return true;
273
- });
274
- if (lacking.length > 0) {
275
- checks.push({
276
- name: NAME2,
277
- status: "warn",
278
- detail: `${lacking.join(", ")} holds build with no outerlayer-build beside it`,
279
- fix: `Run \`${cliInvocation()} ${agentsMd ? "init --update" : "context emit"}\` to write outerlayer-build, then commit.`
280
- });
281
- }
282
- return checks;
283
- }
284
- function committedMaintainedFolders(repoRoot) {
285
- const found = [];
286
- for (const base of [AGENTS_SKILLS_BASE, ".claude/skills"]) {
287
- for (const name of MAINTAINED_SKILLS) {
288
- const folder = skillDir(name, base);
289
- if (!hasSymlinkComponent(repoRoot, folder) && isMaintainedCopy(repoRoot, name, base)) found.push(folder);
290
- }
291
- }
292
- return found;
293
- }
294
- function checkCommittedMaintainedSkills(repoRoot) {
295
- if (!isAgentsMdLayout(repoRoot)) return [];
296
- const folders = committedMaintainedFolders(repoRoot);
297
- if (folders.length === 0) return [];
298
- return [
299
- {
300
- name: "Committed maintained skills",
301
- status: "warn",
302
- detail: `${folders.join(", ")} ${folders.length === 1 ? "is a maintained skill" : "are maintained skills"} that every machine keeps in ${MACHINE_SKILL_PATH}/ now`,
303
- fix: `Run \`${cliInvocation()} init --update\` to remove ${folders.length === 1 ? "it" : "them"}, then commit. Before you commit, every machine and runner host must run this CLI version or later, and each machine a person works on must run \`${cliInvocation()} init --local\`.`
304
- }
305
- ];
306
- }
307
- function checkMachineSkills(opts) {
308
- const build = buildsOf(opts.repoRoot, [".outerlayer/skills", ...skillsFolders()]).find((b) => b.text.includes(MACHINE_CORE));
309
- if (build === void 0) return [];
310
- const problems = machineSkillsState(opts.home, opts.version).filter((s) => s.state !== "current");
311
- const claudeStale = staleClaudeSkills(opts.home, opts.version);
312
- if (problems.length === 0 && claudeStale.length === 0) return [];
313
- const parts = [
314
- ...problems.map((s) => `${MACHINE_SKILL_PATH}/${s.name} ${s.state === "missing" ? "is missing" : "is from another CLI version"}`),
315
- ...claudeStale.map((name) => `~/.claude/skills/${name} is not this CLI version's copy`)
316
- ];
317
- return [
318
- {
319
- name: "Maintained skills on this machine",
320
- status: "warn",
321
- detail: `${build.path} reads ${MACHINE_CORE}, but ${parts.join(", ")}`,
322
- fix: `Run \`${cliInvocation()} init --local\` on this machine. If it reports a failed write, fix the permissions on the folder it names first.`
323
- }
324
- ];
325
- }
326
191
 
327
- export { canonical, checkBuildSkill, checkCommittedMaintainedSkills, checkMachineSkills, checkStarterFiles, committedMaintainedFolders, contentHash, contextIsGoverned, inspectStarterFiles, readShippedManifest, skillsFolders };
192
+ export { canonical, checkStarterFiles, contentHash, contextIsGoverned, inspectStarterFiles, readShippedManifest };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-RHAGBUL5.js';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-5K3KB4YR.js';
4
4
  import { readFileSync, existsSync, rmSync, mkdirSync, writeFileSync, renameSync } from 'fs';
5
5
  import { join } from 'path';
6
6
 
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { splitRawFile } from './chunk-RKOTJQVG.js';
3
+ import { MAINTAINED_SKILLS } from './chunk-CDDED64E.js';
4
4
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
5
+ import { splitRawFile } from './chunk-RKOTJQVG.js';
5
6
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
6
7
  import { join, dirname } from 'path';
7
8
  import { fileURLToPath } from 'url';
8
9
 
9
10
  createRequire(import.meta.url);
10
11
  var TEMPLATE_SKILLS = ["spec", "writing-specs", "writing-tests", "build"];
11
- var MAINTAINED_SKILLS = ["outerlayer-evidence", "outerlayer-amend", "outerlayer-findings", "outerlayer-cli", "outerlayer-build"];
12
12
  function templateClassLine(version) {
13
13
  return `<!-- yours to edit. Copied once from the default template by outerlayer init ${version}; never overwritten. -->`;
14
14
  }
@@ -130,10 +130,6 @@ var FORMER_MAINTAINED_NAMES = {
130
130
  outerlayer: "outerlayer-cli"
131
131
  };
132
132
  var MAINTAINED_LINE = /^<!-- maintained by OuterLayer \S+?\. /m;
133
- var MAINTAINED_LINE_VERSION = /^<!-- maintained by OuterLayer (\S+?)\. /m;
134
- function maintainedLineVersion(text) {
135
- return MAINTAINED_LINE_VERSION.exec(text)?.[1];
136
- }
137
133
  function isMaintainedCopy(repoRoot, skill, base = OUTERLAYER_SKILLS_BASE) {
138
134
  try {
139
135
  return MAINTAINED_LINE.test(readFileSync(join(repoRoot, skillDir(skill, base), "SKILL.md"), "utf8"));
@@ -145,4 +141,4 @@ function formerNameExists(repoRoot, skill, base) {
145
141
  return Object.entries(FORMER_MAINTAINED_NAMES).some(([former, current]) => current === skill && isMaintainedCopy(repoRoot, former, base));
146
142
  }
147
143
 
148
- export { AGENTS_SKILLS_BASE, FORMER_MAINTAINED_NAMES, MACHINE_SKILL_PATH, MAINTAINED_SKILLS, OUTERLAYER_SKILLS_BASE, TEMPLATE_SKILLS, isMaintainedCopy, loadMachineSkillFiles, loadMaintainedFiles, loadTemplateFiles, maintainedFilesForExistingSkills, maintainedLineVersion, namesCore, resolvePackRoot, restoreSkillPaths, rewriteSkillPaths, skillDir, writeMaintainedFiles };
144
+ export { AGENTS_SKILLS_BASE, FORMER_MAINTAINED_NAMES, MACHINE_SKILL_PATH, OUTERLAYER_SKILLS_BASE, TEMPLATE_SKILLS, isMaintainedCopy, loadMachineSkillFiles, loadMaintainedFiles, loadTemplateFiles, maintainedFilesForExistingSkills, namesCore, resolvePackRoot, restoreSkillPaths, rewriteSkillPaths, skillDir, writeMaintainedFiles };