@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.
- package/CHANGELOG.md +32 -0
- package/README.md +6 -0
- package/dist/{agent-setup-UW36TAQM.js → agent-setup-YVR5RO56.js} +17 -14
- package/dist/{bridge-B5VJVECY.js → bridge-WW2V7DTB.js} +3 -2
- package/dist/build-5FRC3RKM.js +13 -0
- package/dist/build-info.json +1 -1
- package/dist/{builder-6Y6ZWGNH.js → builder-4F2XNSFC.js} +7 -6
- package/dist/{check-YTXFVWK7.js → check-NDDOASVO.js} +70 -61
- package/dist/{chunk-VS27BP3E.js → chunk-2YSCKEL2.js} +7 -7
- package/dist/{chunk-BPKO76QR.js → chunk-4XN5FRRJ.js} +4 -4
- package/dist/{chunk-EPPIISRD.js → chunk-55XLX5PA.js} +1 -1
- package/dist/{chunk-LOKSLO25.js → chunk-5B7BEQPR.js} +1 -1
- package/dist/chunk-5BHIBJDA.js +93 -0
- package/dist/{chunk-RHAGBUL5.js → chunk-5K3KB4YR.js} +1 -1
- package/dist/{chunk-ABXQBEYK.js → chunk-66T6XJAB.js} +1 -1
- package/dist/{chunk-LPFOWUHG.js → chunk-6BWJQGTV.js} +20 -13
- package/dist/{chunk-BWH36FOC.js → chunk-7CK2TJFB.js} +20 -4
- package/dist/{chunk-5VMDGJGH.js → chunk-7UGFIWIW.js} +37 -23
- package/dist/{chunk-QKIQ2R7F.js → chunk-ATJOFXTE.js} +3 -3
- package/dist/chunk-CDDED64E.js +13 -0
- package/dist/{chunk-QHH4OSD4.js → chunk-CTYSTE5C.js} +1 -1
- package/dist/{chunk-DJHNEGNM.js → chunk-DKWQMPSL.js} +18 -2
- package/dist/{chunk-IMOB4IOI.js → chunk-DQYMQ47E.js} +3 -2
- package/dist/{chunk-YETTWTAY.js → chunk-E7R2GIAW.js} +4 -4
- package/dist/{chunk-GFUE5TKO.js → chunk-F4FA3ZUT.js} +24 -14
- package/dist/{chunk-6TRNCUM4.js → chunk-FGF52V4V.js} +1 -1
- package/dist/{chunk-MATUHHN4.js → chunk-GUXWQIEY.js} +1 -1
- package/dist/{chunk-2I3LIRZP.js → chunk-HXAEQPZR.js} +101 -10
- package/dist/{chunk-R7SGBXUD.js → chunk-IKXY47R5.js} +107 -56
- package/dist/{chunk-P33PZIWS.js → chunk-ITAIEJ2T.js} +7 -142
- package/dist/{chunk-RHGF73IU.js → chunk-IVX3U7KV.js} +1 -1
- package/dist/{chunk-7OUOLGUV.js → chunk-JGML2VUN.js} +3 -7
- package/dist/{chunk-6VFH52MP.js → chunk-KVDVNOUK.js} +24 -22
- package/dist/{chunk-2F762IXY.js → chunk-LNIFYSNK.js} +3 -3
- package/dist/{chunk-XBPUTQ7E.js → chunk-MHAR6S7B.js} +1 -1
- package/dist/{chunk-7AQ5AM7U.js → chunk-MQHTM4YJ.js} +177 -21
- package/dist/{chunk-6KKM7VGZ.js → chunk-N7WAEEIU.js} +3 -3
- package/dist/{chunk-D7ECMB7B.js → chunk-NUHZV3A4.js} +1 -1
- package/dist/{chunk-MHX7YX7Y.js → chunk-P2RWZCV7.js} +1 -1
- package/dist/chunk-QBQHQEUG.js +300 -0
- package/dist/{chunk-FP23SVDD.js → chunk-QJFDAKRF.js} +5 -5
- package/dist/{chunk-WUL2OP5A.js → chunk-QKXF7CLR.js} +3 -3
- package/dist/{chunk-Y7ZCHBYB.js → chunk-QWAYRAUX.js} +3 -3
- package/dist/{chunk-64GMBWAK.js → chunk-R7SS5RLJ.js} +6 -6
- package/dist/{chunk-XZ6Q6ZNR.js → chunk-SATUCMAJ.js} +3 -2
- package/dist/{chunk-2BTFKNTR.js → chunk-SJZL5F3F.js} +2 -2
- package/dist/{chunk-HWDYLXHH.js → chunk-T2QSWFSU.js} +4 -4
- package/dist/{chunk-B7DJVG25.js → chunk-T57XUI6N.js} +3 -3
- package/dist/{chunk-E5IJ5533.js → chunk-TF7G2PR6.js} +3 -3
- package/dist/{chunk-O2IJTY7L.js → chunk-TVZAC2NP.js} +3 -3
- package/dist/{chunk-QE3UQAHK.js → chunk-UHU7H57K.js} +26 -7
- package/dist/{chunk-WSYXLLA5.js → chunk-USJZ2LDK.js} +6 -6
- package/dist/{chunk-EX5MQYEF.js → chunk-VC5J7QPV.js} +5 -5
- package/dist/{chunk-N4D5TMVU.js → chunk-VU7ZJPIR.js} +5 -5
- package/dist/{chunk-ZFBJUOYT.js → chunk-W3FSGH2M.js} +10 -10
- package/dist/{chunk-GLUKDQS4.js → chunk-WWQVKFN6.js} +1 -1
- package/dist/{chunk-55GNQPO6.js → chunk-X52PMPOM.js} +7 -7
- package/dist/{chunk-YB3CSYXX.js → chunk-XD4ZCMA4.js} +81 -2
- package/dist/{chunk-Y4OKEFAX.js → chunk-YL2VDSNF.js} +1 -1
- package/dist/{chunk-M3MHHIUW.js → chunk-Z3ASAXVU.js} +1 -1
- package/dist/{chunk-XS3FDWSZ.js → chunk-ZTY7HHYB.js} +1 -1
- package/dist/{claude-launcher-NQSZBTQ5.js → claude-launcher-7RGVOYCD.js} +6 -5
- package/dist/{cli-GHEOBXC7.js → cli-QC6ZKHPK.js} +149 -128
- package/dist/cli-update-notice-4DLZ3655.js +9 -0
- package/dist/{command-V7B7GTPZ.js → command-3F6GY4CK.js} +53 -37
- package/dist/{config-TWS5VZEN.js → config-5QYIKYUP.js} +3 -2
- package/dist/{connect-cmd-HGS7YPA2.js → connect-cmd-5TYAOK5M.js} +14 -11
- package/dist/{container-start-FHB2VDC4.js → container-start-P7O5XGOB.js} +37 -36
- package/dist/{control-plane-launch-DBQA3KLJ.js → control-plane-launch-FZMD4MXX.js} +13 -10
- package/dist/{dist-QPHZE47F.js → dist-JFVKLUHL.js} +1 -1
- package/dist/{docker-YT6Z3LXI.js → docker-ZTC4EIU4.js} +7 -6
- package/dist/{doctor-Y4NCNSJM.js → doctor-QPQDF7FB.js} +159 -41
- package/dist/{emit-artifact-cmd-ALDK55Y2.js → emit-artifact-cmd-O3IBUMUY.js} +19 -16
- package/dist/{emit-cmd-VAQHRWJR.js → emit-cmd-QUABLVO6.js} +6 -5
- package/dist/{emit-criteria-cmd-Q7SM6VP2.js → emit-criteria-cmd-JDO2VUG5.js} +15 -12
- package/dist/{emit-finding-cmd-2NBAPDSV.js → emit-finding-cmd-VCQPCLI2.js} +16 -13
- package/dist/{emit-result-cmd-KUSL56RI.js → emit-result-cmd-BNS57DD3.js} +19 -16
- package/dist/{emit-step-cmd-KD4AKEAT.js → emit-step-cmd-XN44BXYU.js} +16 -13
- package/dist/{exec-client-6WVS7DRZ.js → exec-client-VKT2XNB3.js} +4 -3
- package/dist/fleet-readiness-G5X3MKP2.js +29 -0
- package/dist/{governing-source-VVUA5TKB.js → governing-source-B3M2U4BC.js} +21 -18
- package/dist/{guest-init-H5K2RW3P.js → guest-init-QW2DPX7H.js} +5 -4
- package/dist/{hook-fast-3SUJM765.js → hook-fast-EFC44SXV.js} +4 -1
- package/dist/{host-key-XNKZCWTS.js → host-key-AC6LTZDS.js} +4 -3
- package/dist/{image-tag-R34J4O3F.js → image-tag-SS7YKJHN.js} +4 -3
- package/dist/index.js +4 -4
- package/dist/{init-3DAGX7UY.js → init-36XMFFRQ.js} +38 -37
- package/dist/init-HHEAJDPN.js +56 -0
- package/dist/{init-cmd-RIDBVSE4.js → init-cmd-K2IKTSXJ.js} +25 -21
- package/dist/{init-update-ECWNG47R.js → init-update-RWTQSTPE.js} +51 -35
- package/dist/{inspect-IPFA7AAT.js → inspect-L7JIBK3Y.js} +1 -1
- package/dist/{install-6OIY3KHZ.js → install-35SAMY75.js} +5 -5
- package/dist/{install-cmd-JMT67P35.js → install-cmd-GFY4QF72.js} +6 -5
- package/dist/{layout-XNFDTOET.js → layout-BBTQPS6V.js} +4 -3
- package/dist/{login-browser-EWXSGHM7.js → login-browser-WSOSQH2T.js} +2 -2
- package/dist/{logs-XHAS6LMZ.js → logs-X2IRDP5T.js} +3 -2
- package/dist/loop-F5ASKFRJ.js +80 -0
- package/dist/{machine-OOQ2NXC3.js → machine-6STGIRJJ.js} +32 -30
- package/dist/{machine-skills-FLIRJYP7.js → machine-skills-O7W6NMWB.js} +4 -3
- package/dist/{mcp-serve-cmd-LY5A3CE7.js → mcp-serve-cmd-IITCPAAR.js} +9 -6
- package/dist/{paths-LHSPNORF.js → paths-32DWGK35.js} +3 -2
- package/dist/pending-CSIY4Y2I.js +10 -0
- package/dist/{pidfile-DKMYYXLH.js → pidfile-CYCTH6NQ.js} +4 -3
- package/dist/{real-deps-KNNBQC75.js → real-deps-QX5YH7FG.js} +1 -1
- package/dist/{record-3LPTY3G5.js → record-N4WPZCGK.js} +4 -3
- package/dist/{runner-env-YRRNRKF4.js → runner-env-EIB6WFPG.js} +6 -7
- package/dist/{runner-identity-YS2BZXZV.js → runner-identity-S3V6I4I3.js} +7 -6
- package/dist/{runner-key-EFNTZWNX.js → runner-key-Y76QXVNV.js} +36 -35
- package/dist/{session-sender-SC5PSU2G.js → session-sender-LFYMN6TT.js} +20 -17
- package/dist/{spec-cmd-JGYHHJ4P.js → spec-cmd-Z6MGATWC.js} +16 -13
- package/dist/{starter-pack-GPU4X6B7.js → starter-pack-5SOT5V4I.js} +4 -3
- package/dist/{status-7WM7S7JX.js → status-OANG2EM3.js} +39 -37
- package/dist/{sync-cmd-ATXJVS7S.js → sync-cmd-TNOOUPY2.js} +19 -16
- package/dist/{watch-M7NR3DOW.js → watch-HBNNYATF.js} +19 -16
- package/dist/{work-claim-cmd-DNUDZKJA.js → work-claim-cmd-CXALMILD.js} +21 -18
- package/dist/{work-cmd-VECTYST6.js → work-cmd-COESFSHE.js} +16 -13
- package/dist/{work-comment-cmd-F3NRWKPZ.js → work-comment-cmd-A4ZUVCSA.js} +16 -13
- package/dist/{work-logs-cmd-QF6P32FE.js → work-logs-cmd-CTF43MBE.js} +16 -13
- package/dist/{work-open-pr-cmd-XE23JA3R.js → work-open-pr-cmd-EMGYJXVD.js} +17 -14
- package/dist/{work-pr-cmd-BH56GUKN.js → work-pr-cmd-FEXMS6RH.js} +16 -13
- package/dist/{work-stop-cmd-C3F5HNUO.js → work-stop-cmd-NIHAN45R.js} +16 -13
- package/package.json +1 -1
- package/dist/build-HRLACBOZ.js +0 -12
- package/dist/chunk-STSLH5EJ.js +0 -71
- package/dist/init-SWKYV6CL.js +0 -55
- package/dist/loop-AIJZVUNA.js +0 -79
- package/dist/pending-3YZCSKON.js +0 -9
- 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 {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
647
|
-
child.once("error", () =>
|
|
648
|
-
child.once("close", (code) =>
|
|
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((
|
|
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)
|
|
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
|
-
|
|
863
|
-
|
|
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 =
|
|
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((
|
|
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((
|
|
907
|
-
while (alive(vm) && Date.now() < deadline) await new Promise((
|
|
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((
|
|
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", () =>
|
|
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((
|
|
1408
|
-
timer = setTimeout(() =>
|
|
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((
|
|
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((
|
|
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((
|
|
1706
|
+
const closed = new Promise((resolve2, reject) => {
|
|
1656
1707
|
child.once("error", reject);
|
|
1657
|
-
child.once("close", (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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
1933
|
+
resolve2(void 0);
|
|
1883
1934
|
return;
|
|
1884
1935
|
}
|
|
1885
1936
|
chunks.push(chunk);
|
|
1886
1937
|
});
|
|
1887
|
-
req.once("end", () =>
|
|
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((
|
|
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
|
-
|
|
1974
|
+
resolve2();
|
|
1924
1975
|
});
|
|
1925
1976
|
answer.once("error", () => {
|
|
1926
1977
|
res.destroy();
|
|
1927
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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((
|
|
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((
|
|
3021
|
-
timer = setTimeout(() =>
|
|
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
|
|
15
|
-
import { join
|
|
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,
|
|
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-
|
|
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 {
|
|
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,
|
|
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 };
|