@outerlayer/cli 0.31.1-next.20261020180727 → 0.32.0-next.20261020183646
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/dist/build-info.json +1 -1
- package/dist/{check-PLBJ2RPE.js → check-OL7QVTHJ.js} +3 -2
- package/dist/{chunk-AIN2UF6L.js → chunk-E3XOQJKZ.js} +1 -1
- package/dist/{chunk-5L4JA6WI.js → chunk-KHINKAHX.js} +4 -1
- package/dist/{chunk-UA3QZWFR.js → chunk-NYZAIBNV.js} +14 -6
- package/dist/chunk-WHSYPR3U.js +36 -0
- package/dist/{cli-7XWXBODE.js → cli-PYG5SDEC.js} +10 -10
- package/dist/{container-start-2B3F3VUL.js → container-start-J3ZZQED4.js} +49 -2
- package/dist/{doctor-T6WNAW6E.js → doctor-KCEZ7EFR.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{init-cmd-R3PKRIHL.js → init-cmd-WHLP52BW.js} +1 -1
- package/dist/{loop-BMSO6QD2.js → loop-U4SWVDRP.js} +3 -2
- package/package.json +1 -1
- package/skill-pack/shipped.json +4 -1
- package/skill-pack/template/spec/SKILL.md +14 -9
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"2026-10-20T18:
|
|
1
|
+
{"id":"2026-10-20T18:47:15.319Z+d39f74e","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { probeCredentials } from './chunk-
|
|
3
|
+
import { probeCredentials } from './chunk-NYZAIBNV.js';
|
|
4
4
|
import './chunk-CWAZNCFQ.js';
|
|
5
5
|
import './chunk-3JVYMD4G.js';
|
|
6
|
+
import './chunk-WHSYPR3U.js';
|
|
6
7
|
import './chunk-E7R2GIAW.js';
|
|
7
8
|
import './chunk-WRU3K5AN.js';
|
|
8
9
|
import './chunk-TZQIEUDE.js';
|
|
@@ -15,7 +16,7 @@ import './chunk-IBG2ESJX.js';
|
|
|
15
16
|
import './chunk-JCCUTTRI.js';
|
|
16
17
|
import './chunk-ESVW4MJY.js';
|
|
17
18
|
import './chunk-XTNMIV77.js';
|
|
18
|
-
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, managedProblems, managedFactsOf, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-
|
|
19
|
+
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, managedProblems, managedFactsOf, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-KHINKAHX.js';
|
|
19
20
|
import './chunk-YYYRBYWG.js';
|
|
20
21
|
import './chunk-ZZSQYOY5.js';
|
|
21
22
|
import './chunk-TBT347UY.js';
|
|
@@ -1211,7 +1211,7 @@ async function gatherDoctorChecks() {
|
|
|
1211
1211
|
const { runnerVmCheck } = await import('./doctor-53F2PYY7.js');
|
|
1212
1212
|
checks.push(runnerVmCheck(configPath, { lima: realLima(), home: homeFromEnv(), instance: runnerVm.instance }));
|
|
1213
1213
|
} else if (hasRunnerBlock(configPath)) {
|
|
1214
|
-
const { runnerHostChecks } = await import('./doctor-
|
|
1214
|
+
const { runnerHostChecks } = await import('./doctor-KCEZ7EFR.js');
|
|
1215
1215
|
const gateway = (() => {
|
|
1216
1216
|
try {
|
|
1217
1217
|
const { url, apiKey, appId } = loadRunnerConfig(configPath);
|
|
@@ -182,7 +182,10 @@ function checkBlocked(config, probes) {
|
|
|
182
182
|
buildMemory: config.build?.memory ?? DEFAULT_BUILD_MEMORY,
|
|
183
183
|
usableBytes: probes.totalMemoryBytes()
|
|
184
184
|
});
|
|
185
|
-
if (!fit.fits)
|
|
185
|
+
if (!fit.fits) {
|
|
186
|
+
const advice = probes.inImage === true ? "Set OUTERLAYER_BUILD_MEMORY or OUTERLAYER_CONCURRENCY in the env file and recreate the container, or give the machine more memory" : `Lower runner.concurrency or runner.build.memory in ${config.configPath}`;
|
|
187
|
+
return { reason: `${fit.message}. ${advice}` };
|
|
188
|
+
}
|
|
186
189
|
}
|
|
187
190
|
const kvm = kind === "vm" ? probes.kvm() : "usable";
|
|
188
191
|
if (kvm === "absent") {
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
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-CWAZNCFQ.js';
|
|
4
4
|
import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
|
|
5
|
+
import { fitImageBuildMemory } from './chunk-WHSYPR3U.js';
|
|
5
6
|
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-E7R2GIAW.js';
|
|
6
7
|
import { RUNNER_PROTOCOL } from './chunk-WRU3K5AN.js';
|
|
7
8
|
import { writePendingUpdate } from './chunk-TZQIEUDE.js';
|
|
8
9
|
import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
|
|
9
10
|
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-X7UUIHGH.js';
|
|
10
|
-
import { currentSkillCommand, formerSkillProblem, realBlockedProbes, checkBlocked } from './chunk-
|
|
11
|
+
import { currentSkillCommand, formerSkillProblem, realBlockedProbes, checkBlocked } from './chunk-KHINKAHX.js';
|
|
11
12
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
12
13
|
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-ZZSQYOY5.js';
|
|
13
14
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
@@ -29,8 +30,8 @@ import { fdName } from './chunk-XD4ZCMA4.js';
|
|
|
29
30
|
import { COMMAND_LOST_REASON, CONTAINER_STOPPED_REASON } from './chunk-MESOOLF4.js';
|
|
30
31
|
import { randomBytes } from 'crypto';
|
|
31
32
|
import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync, statSync, readdirSync, readFileSync, closeSync, rmSync, lstatSync } from 'fs';
|
|
33
|
+
import { totalmem, constants } from 'os';
|
|
32
34
|
import { join, dirname } from 'path';
|
|
33
|
-
import { constants } from 'os';
|
|
34
35
|
|
|
35
36
|
createRequire(import.meta.url);
|
|
36
37
|
|
|
@@ -1124,13 +1125,17 @@ function reloadConfig(state) {
|
|
|
1124
1125
|
logOf(state).error(`config re-read rejected: ${hookProblem} \xB7 keeping the last good config`);
|
|
1125
1126
|
return;
|
|
1126
1127
|
}
|
|
1127
|
-
state.config = reloaded;
|
|
1128
|
+
state.config = fitForImage(state.deps, reloaded).config;
|
|
1128
1129
|
const timerNote = state.pollTimerSeconds !== void 0 && state.pollTimerSeconds !== reloaded.pollSeconds ? ` \xB7 still polling every ${state.pollTimerSeconds}s until the runner restarts` : "";
|
|
1129
1130
|
logOf(state).line(`config re-read \xB7 ${describeConfig(reloaded)}${timerNote}`);
|
|
1130
1131
|
} catch (err) {
|
|
1131
1132
|
logOf(state).error(`config re-read rejected: ${describeCallFailure(err)} \xB7 keeping the last good config`);
|
|
1132
1133
|
}
|
|
1133
1134
|
}
|
|
1135
|
+
function fitForImage(deps, config) {
|
|
1136
|
+
if (deps.image === void 0) return { config };
|
|
1137
|
+
return fitImageBuildMemory(config, (deps.blocked?.totalMemoryBytes ?? totalmem)());
|
|
1138
|
+
}
|
|
1134
1139
|
function describeConfig(config) {
|
|
1135
1140
|
return `queues ${config.queues.join(",")} \xB7 concurrency ${config.concurrency} \xB7 poll ${config.pollSeconds}s`;
|
|
1136
1141
|
}
|
|
@@ -1603,6 +1608,7 @@ function holdWhenBlocked(state, jailer) {
|
|
|
1603
1608
|
...state.deps.container?.hostEnv === void 0 ? {} : { env: state.deps.container.hostEnv },
|
|
1604
1609
|
...state.deps.blocked?.imageBuilder === void 0 ? { imageBuilder: imageBuilderState(state) } : {},
|
|
1605
1610
|
...jailer === void 0 ? {} : { jailer },
|
|
1611
|
+
inImage: state.deps.image !== void 0,
|
|
1606
1612
|
...state.deps.blocked
|
|
1607
1613
|
};
|
|
1608
1614
|
const blocked = checkBlocked(state.config, probes);
|
|
@@ -2926,7 +2932,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2926
2932
|
check: update.check ? () => update.check(configPath) : async () => {
|
|
2927
2933
|
const held = heldClaudeCredential();
|
|
2928
2934
|
const env = held === void 0 ? process.env : { ...process.env, [held.variable]: held.value };
|
|
2929
|
-
return (await import('./check-
|
|
2935
|
+
return (await import('./check-OL7QVTHJ.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
|
|
2930
2936
|
},
|
|
2931
2937
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
2932
2938
|
log
|
|
@@ -2936,9 +2942,10 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2936
2942
|
throw new RunnerStartError("went back to the previous version; restarting");
|
|
2937
2943
|
}
|
|
2938
2944
|
}
|
|
2939
|
-
const
|
|
2940
|
-
const hookProblem = checkHooks(
|
|
2945
|
+
const loaded = loadRunnerConfig(configPath);
|
|
2946
|
+
const hookProblem = checkHooks(loaded);
|
|
2941
2947
|
if (hookProblem) throw new RunnerStartError(hookProblem);
|
|
2948
|
+
const { config, note: fitNote } = fitForImage(deps, loaded);
|
|
2942
2949
|
await ensureHostKey(configPath);
|
|
2943
2950
|
if (builtinKind(config.hooks.provision) === "container" || builtinKind(config.hooks.provision) === "vm") {
|
|
2944
2951
|
await ensureRunnerIdentity(configPath, {
|
|
@@ -2965,6 +2972,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2965
2972
|
}
|
|
2966
2973
|
const state = { config, jobs: /* @__PURE__ */ new Map(), deps, configMtimeMs };
|
|
2967
2974
|
log.line(`runner ${config.host} started \xB7 config ${configPath} \xB7 ${describeConfig(config)}`);
|
|
2975
|
+
if (fitNote !== void 0) log.line(fitNote);
|
|
2968
2976
|
const leavesBuilds = await canLeaveBuilds(state);
|
|
2969
2977
|
let sigusr2Target;
|
|
2970
2978
|
let sigusr2Early = false;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { checkFit, RUNNER_RESERVE_BYTES } from './chunk-RQGHHEM7.js';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
|
|
6
|
+
createRequire(import.meta.url);
|
|
7
|
+
var GIB = 1024 ** 3;
|
|
8
|
+
var DEFAULT_GIB = 8;
|
|
9
|
+
var MINIMUM_GIB = 4;
|
|
10
|
+
var BUILD_MEMORY_VARIABLE = "OUTERLAYER_BUILD_MEMORY";
|
|
11
|
+
function memoryIsSet(configPath) {
|
|
12
|
+
try {
|
|
13
|
+
const raw = JSON.parse(readFileSync(configPath, "utf8"));
|
|
14
|
+
return raw.runner.build.memory !== void 0;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function gib(bytes) {
|
|
20
|
+
return `${Number((bytes / GIB).toFixed(1))} GiB`;
|
|
21
|
+
}
|
|
22
|
+
function fitImageBuildMemory(config, totalMemoryBytes) {
|
|
23
|
+
if (memoryIsSet(config.configPath)) return { config };
|
|
24
|
+
const current = config.build?.memory ?? `${DEFAULT_GIB}g`;
|
|
25
|
+
if (checkFit({ concurrency: config.concurrency, buildMemory: current, usableBytes: totalMemoryBytes }).fits) return { config };
|
|
26
|
+
const available = Math.max(0, totalMemoryBytes - RUNNER_RESERVE_BYTES);
|
|
27
|
+
const perBuild = Math.floor(available / config.concurrency / GIB);
|
|
28
|
+
if (perBuild < MINIMUM_GIB) return { config };
|
|
29
|
+
const memory = `${perBuild}g`;
|
|
30
|
+
return {
|
|
31
|
+
config: { ...config, build: { ...config.build, memory } },
|
|
32
|
+
note: `builds get ${memory} of memory to fit this machine's ${gib(totalMemoryBytes)}; set ${BUILD_MEMORY_VARIABLE} to choose another value`
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { BUILD_MEMORY_VARIABLE, fitImageBuildMemory };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-
|
|
3
|
+
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-E3XOQJKZ.js';
|
|
4
4
|
import './chunk-BCWVTWS7.js';
|
|
5
5
|
import './chunk-4XPAQXJF.js';
|
|
6
6
|
import './chunk-KT4CN6OU.js';
|
|
@@ -3926,13 +3926,13 @@ what CLIs older than ${FIRST_VERSION_READING_AGENTS_SKILLS} do. \`` + cliInvocat
|
|
|
3926
3926
|
if (changed.length > 0 && !opts.json) process.stdout.write(`Removed the claude function from ${changed.join(", ")}.
|
|
3927
3927
|
`);
|
|
3928
3928
|
}
|
|
3929
|
-
const shell = !opts.remove && opts.shellFunction !== void 0 ? (await import('./init-cmd-
|
|
3929
|
+
const shell = !opts.remove && opts.shellFunction !== void 0 ? (await import('./init-cmd-WHLP52BW.js')).applyShellFunctionFlag(opts.shellFunction, { home: homeFromEnv(), shellPath: process.env.SHELL }) : void 0;
|
|
3930
3930
|
if (opts.json) writeJson(shell === void 0 ? outcome.result : { ...outcome.result, shellFunction: { outcome: shell.outcome, reason: shell.reason } });
|
|
3931
3931
|
else process.stdout.write(outcome.text + skillsLine + (shell?.text ?? ""));
|
|
3932
3932
|
return;
|
|
3933
3933
|
}
|
|
3934
3934
|
await installMachineSkillsForSetup();
|
|
3935
|
-
const { runInitCommand } = await import('./init-cmd-
|
|
3935
|
+
const { runInitCommand } = await import('./init-cmd-WHLP52BW.js');
|
|
3936
3936
|
const code = await runInitCommand(
|
|
3937
3937
|
{ json: opts.json, factory: opts.factory, shellFunction: opts.shellFunction },
|
|
3938
3938
|
{
|
|
@@ -4978,7 +4978,7 @@ function registerRunnerCommands(program2) {
|
|
|
4978
4978
|
const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
|
|
4979
4979
|
runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
|
|
4980
4980
|
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-3JRFDYZL.js');
|
|
4981
|
-
const { start, RunnerStartError } = await import('./loop-
|
|
4981
|
+
const { start, RunnerStartError } = await import('./loop-U4SWVDRP.js');
|
|
4982
4982
|
const { RunnerAlreadyRunningError } = await import('./pidfile-BMFAUQAI.js');
|
|
4983
4983
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4984
4984
|
try {
|
|
@@ -4997,8 +4997,8 @@ function registerRunnerCommands(program2) {
|
|
|
4997
4997
|
"\nReads OUTERLAYER_URL, OUTERLAYER_APP_ID, OUTERLAYER_API_KEY, OUTERLAYER_RUNNER_NAME and one Claude credential\n(CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY) from the environment. OUTERLAYER_AGENT\nis optional and defaults to claude. On a later start it refuses variables that disagree with the config in the volume.\nThe image sets OUTERLAYER_RUNNER_IMAGE; outside the image, use `runner start`.\n"
|
|
4998
4998
|
).action(async () => {
|
|
4999
4999
|
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-3JRFDYZL.js');
|
|
5000
|
-
const { containerStart } = await import('./container-start-
|
|
5001
|
-
const { start, RunnerStartError } = await import('./loop-
|
|
5000
|
+
const { containerStart } = await import('./container-start-J3ZZQED4.js');
|
|
5001
|
+
const { start, RunnerStartError } = await import('./loop-U4SWVDRP.js');
|
|
5002
5002
|
const { RunnerAlreadyRunningError } = await import('./pidfile-BMFAUQAI.js');
|
|
5003
5003
|
try {
|
|
5004
5004
|
const result = await containerStart({
|
|
@@ -5018,7 +5018,7 @@ function registerRunnerCommands(program2) {
|
|
|
5018
5018
|
});
|
|
5019
5019
|
runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
|
|
5020
5020
|
const { defaultRunnerConfigPath } = await import('./config-3JRFDYZL.js');
|
|
5021
|
-
const { runRunnerCheck } = await import('./check-
|
|
5021
|
+
const { runRunnerCheck } = await import('./check-OL7QVTHJ.js');
|
|
5022
5022
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5023
5023
|
const result = await runRunnerCheck(configPath);
|
|
5024
5024
|
if (!result.ok) {
|
|
@@ -5418,7 +5418,7 @@ Next:
|
|
|
5418
5418
|
});
|
|
5419
5419
|
runnerCmd.command("stop").description("Take no more work; finish running jobs, then exit").option("--config <path>", "the cloud config file naming the runner to stop").option("--now", "end running jobs immediately, with outcome stopped").action(async (opts) => {
|
|
5420
5420
|
const { defaultRunnerConfigPath } = await import('./config-3JRFDYZL.js');
|
|
5421
|
-
const { requestStop } = await import('./loop-
|
|
5421
|
+
const { requestStop } = await import('./loop-U4SWVDRP.js');
|
|
5422
5422
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5423
5423
|
const { runnerImageVersion } = await import('./image-tag-OYT7UG7Y.js');
|
|
5424
5424
|
await requestStop(configPath, Boolean(opts.now), void 0, { image: runnerImageVersion() !== void 0 });
|
|
@@ -5426,7 +5426,7 @@ Next:
|
|
|
5426
5426
|
runnerCmd.command("status").description("List running jobs; with --recent, finished ones too").option("--config <path>", "the cloud config file naming the runner to inspect").option("--recent", "also list finished jobs, newest first, capped at 20").option("--json", "machine-readable JSON output").action(async (opts) => {
|
|
5427
5427
|
const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-3JRFDYZL.js');
|
|
5428
5428
|
const { jobsDir, runnerDir } = await import('./paths-OK2EZS7W.js');
|
|
5429
|
-
const { listJobFiles, runnerProcessState } = await import('./loop-
|
|
5429
|
+
const { listJobFiles, runnerProcessState } = await import('./loop-U4SWVDRP.js');
|
|
5430
5430
|
const { renderStatus } = await import('./status-QVRUCO6L.js');
|
|
5431
5431
|
const { readHousekeepingRecord } = await import('./record-26AH6WDB.js');
|
|
5432
5432
|
const path2 = await import('path');
|
|
@@ -5487,7 +5487,7 @@ Next:
|
|
|
5487
5487
|
});
|
|
5488
5488
|
runnerCmd.command("logs").argument("<item>", "the work item's number in the factory").description("Print the newest attempt's log for one item").option("--config <path>", "the cloud config file naming the runner to inspect").option("-f, --follow", "keep printing as the log grows").action(async (itemArg, opts) => {
|
|
5489
5489
|
const { defaultRunnerConfigPath } = await import('./config-3JRFDYZL.js');
|
|
5490
|
-
const { listJobFiles } = await import('./loop-
|
|
5490
|
+
const { listJobFiles } = await import('./loop-U4SWVDRP.js');
|
|
5491
5491
|
const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-C3RJ3ZTC.js');
|
|
5492
5492
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5493
5493
|
const item = parseTrackerNumber(itemArg);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
import { BUILD_MEMORY_VARIABLE } from './chunk-WHSYPR3U.js';
|
|
3
4
|
import { RunnerInitError, prepareRunnerInit, writeRunnerInit } from './chunk-4NOO2ZFW.js';
|
|
4
5
|
import { detectMachine, supportsContainerBuilds, describeMachineDocker } from './chunk-ETVHXBCZ.js';
|
|
5
6
|
import { MIN_ENGINE_MAJOR } from './chunk-76QNSSOZ.js';
|
|
@@ -17,7 +18,7 @@ import './chunk-T5TBGOT6.js';
|
|
|
17
18
|
import './chunk-JBJTC3UU.js';
|
|
18
19
|
import './chunk-OGFGZQA3.js';
|
|
19
20
|
import './chunk-2JPVI45I.js';
|
|
20
|
-
import './chunk-YJLHUKYS.js';
|
|
21
|
+
import { parseSize } from './chunk-YJLHUKYS.js';
|
|
21
22
|
import './chunk-SJZL5F3F.js';
|
|
22
23
|
import './chunk-GPRIHEGQ.js';
|
|
23
24
|
import './chunk-4EU4X2ML.js';
|
|
@@ -52,7 +53,7 @@ import './chunk-VNVZDWO3.js';
|
|
|
52
53
|
import './chunk-XD4ZCMA4.js';
|
|
53
54
|
import './chunk-MESOOLF4.js';
|
|
54
55
|
import './chunk-Z5GEFMRW.js';
|
|
55
|
-
import { existsSync, readFileSync } from 'fs';
|
|
56
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
56
57
|
|
|
57
58
|
createRequire(import.meta.url);
|
|
58
59
|
var DOCKER_SOCKET = "/var/run/docker.sock";
|
|
@@ -81,6 +82,43 @@ var keyHint = (key) => {
|
|
|
81
82
|
if (key === "") return "none";
|
|
82
83
|
return key.length < KEY_MIN_SHOWN ? `a ${key.length}-character key` : `\u2026${key.slice(-4)}`;
|
|
83
84
|
};
|
|
85
|
+
var CONCURRENCY_VARIABLE = "OUTERLAYER_CONCURRENCY";
|
|
86
|
+
function settingsOf(env) {
|
|
87
|
+
const memory = set(env, BUILD_MEMORY_VARIABLE);
|
|
88
|
+
if (memory !== void 0 && parseSize(memory) === void 0) {
|
|
89
|
+
return `${BUILD_MEMORY_VARIABLE} is ${memory}, which is not a size. Use a number with a unit, such as 6g or 512m.`;
|
|
90
|
+
}
|
|
91
|
+
const concurrency = set(env, CONCURRENCY_VARIABLE);
|
|
92
|
+
if (concurrency !== void 0 && !/^[1-9]\d*$/.test(concurrency)) {
|
|
93
|
+
return `${CONCURRENCY_VARIABLE} is ${concurrency}. It takes a positive integer, such as 2.`;
|
|
94
|
+
}
|
|
95
|
+
return { memory, concurrency: concurrency === void 0 ? void 0 : Number(concurrency) };
|
|
96
|
+
}
|
|
97
|
+
function writeSettings(configPath, settings) {
|
|
98
|
+
const config = readConfig(configPath);
|
|
99
|
+
if (config instanceof RunnerInitError) throw config;
|
|
100
|
+
const runner = config.runner ?? {};
|
|
101
|
+
if (runner.build !== void 0 && (typeof runner.build !== "object" || runner.build === null || Array.isArray(runner.build))) {
|
|
102
|
+
throw new RunnerInitError(`${configPath}: runner.build must be an object`);
|
|
103
|
+
}
|
|
104
|
+
const build = runner.build ?? {};
|
|
105
|
+
const lines = [];
|
|
106
|
+
if (settings.memory !== void 0 && build.memory !== settings.memory) {
|
|
107
|
+
lines.push(`runner.build.memory is ${settings.memory}${build.memory === void 0 ? "" : `, not ${String(build.memory)}`}, as ${BUILD_MEMORY_VARIABLE} says`);
|
|
108
|
+
build.memory = settings.memory;
|
|
109
|
+
runner.build = build;
|
|
110
|
+
}
|
|
111
|
+
if (settings.concurrency !== void 0 && runner.concurrency !== settings.concurrency) {
|
|
112
|
+
lines.push(`runner.concurrency is ${settings.concurrency}${runner.concurrency === void 0 ? "" : `, not ${String(runner.concurrency)}`}, as ${CONCURRENCY_VARIABLE} says`);
|
|
113
|
+
runner.concurrency = settings.concurrency;
|
|
114
|
+
}
|
|
115
|
+
if (lines.length > 0) {
|
|
116
|
+
config.runner = runner;
|
|
117
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
118
|
+
`);
|
|
119
|
+
}
|
|
120
|
+
return lines;
|
|
121
|
+
}
|
|
84
122
|
var withoutSlash = (url) => url.replace(/\/+$/, "");
|
|
85
123
|
function disagreements(config, env) {
|
|
86
124
|
const lines = [];
|
|
@@ -130,6 +168,8 @@ async function containerStart(deps) {
|
|
|
130
168
|
if (missing.length > 0) {
|
|
131
169
|
return refuse(`the container needs these variables, and they are not set: ${missing.join("; ")}. Put them in the file you pass to docker run with --env-file.`);
|
|
132
170
|
}
|
|
171
|
+
const settings = settingsOf(env);
|
|
172
|
+
if (typeof settings === "string") return refuse(settings);
|
|
133
173
|
const socketPresent = deps.socketPresent ?? existsSync;
|
|
134
174
|
if (!socketPresent(DOCKER_SOCKET)) {
|
|
135
175
|
return refuse(
|
|
@@ -175,6 +215,13 @@ Change the variables to match the volume, or use a new volume to make a new runn
|
|
|
175
215
|
throw err;
|
|
176
216
|
}
|
|
177
217
|
}
|
|
218
|
+
try {
|
|
219
|
+
for (const line of writeSettings(configPath, settings)) (deps.log ?? ((text) => process.stdout.write(`${text}
|
|
220
|
+
`)))(line);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
if (err instanceof RunnerInitError) return refuse(err.message);
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
178
225
|
await deps.start(configPath, { fetchImpl: deps.fetchImpl ?? fetch, image: { version, ...deps.exit === void 0 ? {} : { exit: deps.exit } } });
|
|
179
226
|
return { ok: true };
|
|
180
227
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { needsClaudeCredential, claudeCredentialCheck, managedProblems, missingPermissionOf, missingPermissionFix } from './chunk-
|
|
3
|
+
import { needsClaudeCredential, claudeCredentialCheck, managedProblems, missingPermissionOf, missingPermissionFix } from './chunk-KHINKAHX.js';
|
|
4
4
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
5
5
|
import { launcherCheck } from './chunk-ZBN4JGTJ.js';
|
|
6
6
|
import './chunk-ZZSQYOY5.js';
|
package/dist/index.js
CHANGED
|
@@ -26,5 +26,5 @@ if (argv[0] === "claude") {
|
|
|
26
26
|
process.exit(await runClaudeLauncher(argv.slice(1)));
|
|
27
27
|
}
|
|
28
28
|
(await import('./hook-fast-UFHR6EKZ.js')).recordLinkExitFailure(argv);
|
|
29
|
-
var { runCli } = await import('./cli-
|
|
29
|
+
var { runCli } = await import('./cli-PYG5SDEC.js');
|
|
30
30
|
await runCli(process.argv);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { summarizeChecks, summaryText, renderDoctorText } from './chunk-
|
|
3
|
+
import { summarizeChecks, summaryText, renderDoctorText } from './chunk-E3XOQJKZ.js';
|
|
4
4
|
import './chunk-BCWVTWS7.js';
|
|
5
5
|
import { shellFunctionInstalled, removeShellFunction, installShellFunction, SHELL_FUNCTION_LINE } from './chunk-CJJDJ7AT.js';
|
|
6
6
|
import './chunk-4XPAQXJF.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, runtimeOf, start, tick, watchTick } from './chunk-
|
|
3
|
+
export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, runtimeOf, start, tick, watchTick } from './chunk-NYZAIBNV.js';
|
|
4
4
|
import './chunk-CWAZNCFQ.js';
|
|
5
5
|
import './chunk-3JVYMD4G.js';
|
|
6
|
+
import './chunk-WHSYPR3U.js';
|
|
6
7
|
import './chunk-E7R2GIAW.js';
|
|
7
8
|
import './chunk-WRU3K5AN.js';
|
|
8
9
|
import './chunk-TZQIEUDE.js';
|
|
@@ -15,7 +16,7 @@ import './chunk-IBG2ESJX.js';
|
|
|
15
16
|
import './chunk-JCCUTTRI.js';
|
|
16
17
|
import './chunk-ESVW4MJY.js';
|
|
17
18
|
import './chunk-XTNMIV77.js';
|
|
18
|
-
import './chunk-
|
|
19
|
+
import './chunk-KHINKAHX.js';
|
|
19
20
|
import './chunk-YYYRBYWG.js';
|
|
20
21
|
import './chunk-ZZSQYOY5.js';
|
|
21
22
|
import './chunk-TBT347UY.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outerlayer/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0-next.20261020183646",
|
|
4
4
|
"description": "OuterLayer CLI — commands: init, claude, connect, doctor, login, logout, sync, daemon (alias: watch), emit, findings, work, spec, runner, hooks, mcp, context. Capture and sync coding-agent sessions, and record proof of factory work.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Magu Studios, Inc.",
|
package/skill-pack/shipped.json
CHANGED
|
@@ -84,10 +84,13 @@
|
|
|
84
84
|
"71e81fabf353ad6117c54e061868538bf00066b78c2528f5a8364445d1def02e",
|
|
85
85
|
"7676c9a19f8ea8741ffbe8f09e4600764cb3f98c2c6bce15ee5a90b4c5f1d41e",
|
|
86
86
|
"82f75a53c591f94615dc27c099e94fcf95e2a09b95aceb38b9022d5f7f054cb0",
|
|
87
|
-
"
|
|
87
|
+
"8d3a5131d0c82302279d319c51bcde74f7677e8d2e3f6cd68aa7f3ea84fa1051",
|
|
88
|
+
"9039ae30d4e836b5c5cfba4a14344e46fd13694ae9e4d88e750abce34dfcd9e6",
|
|
89
|
+
"fc2bec8d43764c4e4b40b0ee761b7f9ee8646950dd4e52392f652e68679f79ea"
|
|
88
90
|
],
|
|
89
91
|
".outerlayer/skills/writing-specs/SKILL.md": [
|
|
90
92
|
"a956aac4249118a058c4327c5751472883588720950d4a96f80c7e91f454bef9",
|
|
93
|
+
"d9423f48add241b2cf23bf49b467858355882727a08e068937a07571399555d8",
|
|
91
94
|
"dbadb39cba5dae936e7c4b97cb852c59072e4a60e44caec01b128a045c1be090",
|
|
92
95
|
"eb8aa95f5e76a46ae9bf340989fb40e470fd750ded791ba80b5f8c5c325513e5"
|
|
93
96
|
],
|
|
@@ -101,16 +101,21 @@ Run them in order. Do not skip the approval.
|
|
|
101
101
|
someone else's change. Never search by key to find `updatedAt`: search
|
|
102
102
|
matches words, not keys. A `conflict` refusal means someone changed the
|
|
103
103
|
issue since: tell the user, read the issue again and redo the edit.
|
|
104
|
-
8. **Ask whether to build.** Ask the user exactly one question
|
|
105
|
-
|
|
106
|
-
issue.
|
|
107
|
-
9. **Start the build.**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
8. **Ask whether to build.** Ask the user exactly one question with three
|
|
105
|
+
answers: build it on a host, build it yourself in a new session, or not
|
|
106
|
+
yet. Never start work unasked, because the user may want to hold the issue.
|
|
107
|
+
9. **Start the build.** The reference is the issue number or the Linear or
|
|
108
|
+
Jira key exactly as the user typed it. For an issue just filed, that is the
|
|
109
|
+
number or key `outerlayer spec file` printed.
|
|
110
|
+
- **On a host:** run `outerlayer work build --issue <reference>`. A host
|
|
111
|
+
takes the item when it has a free slot. Print the item number the
|
|
112
|
+
command reports and stop. Print no launch line: a session started on the
|
|
113
|
+
item would build it a second time.
|
|
114
|
+
- **Yourself:** run `outerlayer work build --issue <reference> --local`. No
|
|
115
|
+
host takes the item. Print the item number the command reports and the
|
|
116
|
+
launch line:
|
|
112
117
|
|
|
113
|
-
|
|
118
|
+
OUTERLAYER_WORK=<number> claude "/build"
|
|
114
119
|
|
|
115
120
|
If the command is refused, the error says why. Relay it, show the command for
|
|
116
121
|
the user to run later, and stop. If the CLI rejects a flag named here, run
|