@outerlayer/cli 0.5.0 → 0.5.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 (27) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/build-info.json +1 -1
  3. package/dist/{check-AXCXDYO2.js → check-4Q33B5ZE.js} +10 -8
  4. package/dist/{chunk-5Y3QQRUH.js → chunk-3DD6AOWC.js} +37 -0
  5. package/dist/{chunk-OHFDWLJP.js → chunk-CHLVJNTE.js} +3 -3
  6. package/dist/{chunk-L24G4PLP.js → chunk-F4NU4H3V.js} +399 -18
  7. package/dist/{chunk-ZLB7GCTY.js → chunk-H4CK2YK4.js} +4 -4
  8. package/dist/{chunk-RJ467PDQ.js → chunk-RTXKYLCA.js} +1 -1
  9. package/dist/{chunk-4NMBDRBS.js → chunk-T52PKE2Y.js} +142 -125
  10. package/dist/chunk-UGP76IZ5.js +34 -0
  11. package/dist/{chunk-RWOTHXYE.js → chunk-UWH5DSUP.js} +27 -15
  12. package/dist/{chunk-FC7TMRNA.js → chunk-W7UTFZDH.js} +2 -2
  13. package/dist/chunk-YYYRBYWG.js +32 -0
  14. package/dist/{chunk-QDQEUVUF.js → chunk-ZXBITXTS.js} +1 -1
  15. package/dist/{cli-NNWPFP5S.js → cli-LHSUYYMI.js} +29 -24
  16. package/dist/{config-XVJYZ4IQ.js → config-HL2AIR3K.js} +1 -1
  17. package/dist/{doctor-J3GIMR7K.js → doctor-MOA3RIEP.js} +19 -5
  18. package/dist/index.js +1 -1
  19. package/dist/{init-CZX7ZDWF.js → init-2IPOIXJV.js} +4 -4
  20. package/dist/{init-3ZQLFPNC.js → init-FYDJAKTM.js} +3 -3
  21. package/dist/{init-cmd-W5NOLQPX.js → init-cmd-KLIDRVXQ.js} +1 -1
  22. package/dist/{loop-VGM772I7.js → loop-NEBUGD2Q.js} +7 -5
  23. package/dist/{machine-5WEJA36F.js → machine-ECU3QCZD.js} +2 -2
  24. package/dist/record-C43U4PKS.js +7 -0
  25. package/dist/{status-KBDVUYQ3.js → status-CLATHCTQ.js} +22 -4
  26. package/dist/{work-claim-cmd-BQPPURBW.js → work-claim-cmd-3OPWA77E.js} +2 -2
  27. package/package.json +1 -1
@@ -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-ZLB7GCTY.js';
3
+ import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-H4CK2YK4.js';
4
4
  import './chunk-D2KWEAN6.js';
5
5
  import './chunk-F47JBIAW.js';
6
6
  import './chunk-BKO6JEZI.js';
@@ -3846,7 +3846,7 @@ function buildProgram(argv = process.argv) {
3846
3846
  else process.stdout.write(outcome.text);
3847
3847
  return;
3848
3848
  }
3849
- const { runInitCommand } = await import('./init-cmd-W5NOLQPX.js');
3849
+ const { runInitCommand } = await import('./init-cmd-KLIDRVXQ.js');
3850
3850
  const code = await runInitCommand(
3851
3851
  { json: opts.json, factory: opts.factory },
3852
3852
  {
@@ -4350,7 +4350,7 @@ live addition remains on it.
4350
4350
  "\n outerlayer work claim --item 42 --kind implement\n\nRecords a lease for this host. A live lease already held by a\ndifferent host is refused; claiming again under the same host extends\nit.\n"
4351
4351
  ).action(async (opts) => {
4352
4352
  warnIfApiKeyFlag(opts);
4353
- const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-BQPPURBW.js');
4353
+ const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-3OPWA77E.js');
4354
4354
  try {
4355
4355
  await runWorkClaim(opts);
4356
4356
  } catch (err) {
@@ -4366,7 +4366,7 @@ live addition remains on it.
4366
4366
  "\n outerlayer work renew --item 42\n\nExtends this host's own live lease. Refused with a 410 if the lease\nhas expired, or a 403 if a different host holds it.\n"
4367
4367
  ).action(async (opts) => {
4368
4368
  warnIfApiKeyFlag(opts);
4369
- const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-BQPPURBW.js');
4369
+ const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-3OPWA77E.js');
4370
4370
  try {
4371
4371
  await runWorkRenew(opts);
4372
4372
  } catch (err) {
@@ -4385,7 +4385,7 @@ live addition remains on it.
4385
4385
  "\n outerlayer work release --item 42 --outcome ok\n\nMarks this host's lease released, optionally with an outcome.\nReleasing an already-released lease is a no-op that returns the\nrecorded release time and outcome.\n"
4386
4386
  ).action(async (opts) => {
4387
4387
  warnIfApiKeyFlag(opts);
4388
- const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-BQPPURBW.js');
4388
+ const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-3OPWA77E.js');
4389
4389
  try {
4390
4390
  await runWorkRelease(opts);
4391
4391
  } catch (err) {
@@ -4434,8 +4434,8 @@ function registerRunnerCommands(program2) {
4434
4434
  const runnerCmd = program2.command("runner").description("Take work from the implement and amend queues on this machine");
4435
4435
  const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
4436
4436
  runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
4437
- const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-XVJYZ4IQ.js');
4438
- const { start, RunnerStartError } = await import('./loop-VGM772I7.js');
4437
+ const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-HL2AIR3K.js');
4438
+ const { start, RunnerStartError } = await import('./loop-NEBUGD2Q.js');
4439
4439
  const { RunnerAlreadyRunningError } = await import('./pidfile-UZRH774M.js');
4440
4440
  const configPath = opts.config ?? defaultRunnerConfigPath();
4441
4441
  try {
@@ -4450,8 +4450,8 @@ function registerRunnerCommands(program2) {
4450
4450
  }
4451
4451
  });
4452
4452
  runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
4453
- const { defaultRunnerConfigPath } = await import('./config-XVJYZ4IQ.js');
4454
- const { runRunnerCheck } = await import('./check-AXCXDYO2.js');
4453
+ const { defaultRunnerConfigPath } = await import('./config-HL2AIR3K.js');
4454
+ const { runRunnerCheck } = await import('./check-4Q33B5ZE.js');
4455
4455
  const configPath = opts.config ?? defaultRunnerConfigPath();
4456
4456
  const result = await runRunnerCheck(configPath);
4457
4457
  if (!result.ok) {
@@ -4467,7 +4467,7 @@ function registerRunnerCommands(program2) {
4467
4467
  `);
4468
4468
  });
4469
4469
  runnerCmd.command("install").description("Put this CLI into the runner's install layout, so the runner can update itself").option("--config <path>", configOption).action(async (opts) => {
4470
- const { defaultRunnerConfigPath } = await import('./config-XVJYZ4IQ.js');
4470
+ const { defaultRunnerConfigPath } = await import('./config-HL2AIR3K.js');
4471
4471
  const { runRunnerInstall, RunnerInstallError } = await import('./install-cmd-7WXOIFDO.js');
4472
4472
  const configPath = opts.config ?? defaultRunnerConfigPath();
4473
4473
  try {
@@ -4489,10 +4489,10 @@ Start the runner from the install layout by putting this line in the service uni
4489
4489
  }
4490
4490
  });
4491
4491
  runnerCmd.command("init").description("Write a runner block that fits this machine; on macOS, offers a Linux VM").option("--config <path>", configOption).option("--vm", "on macOS, run the runner in a Linux VM (Lima), with container builds").option("--no-vm", "on macOS, skip the VM and run builds as unisolated processes").option("--allow-process-builds", "where builds cannot be isolated, run them as processes anyway").addOption(new Option("--config-stdin", "the VM-side hand-off: read the whole config as JSON on stdin").hideHelp()).addOption(new Option("--vm-cli-package <path>", "install this packed CLI tarball in the VM instead of the published version").hideHelp()).action(async (opts) => {
4492
- const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-XVJYZ4IQ.js');
4493
- const { runRunnerInit, RunnerInitError } = await import('./init-3ZQLFPNC.js');
4494
- const { detectMachine } = await import('./machine-5WEJA36F.js');
4495
- const { chooseVm, runVmInit, VmInitError } = await import('./init-CZX7ZDWF.js');
4492
+ const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-HL2AIR3K.js');
4493
+ const { runRunnerInit, RunnerInitError } = await import('./init-FYDJAKTM.js');
4494
+ const { detectMachine } = await import('./machine-ECU3QCZD.js');
4495
+ const { chooseVm, runVmInit, VmInitError } = await import('./init-2IPOIXJV.js');
4496
4496
  const configPath = opts.config ?? defaultRunnerConfigPath();
4497
4497
  try {
4498
4498
  const machine = detectMachine();
@@ -4596,7 +4596,7 @@ Next:
4596
4596
  "after",
4597
4597
  "\nFetches the head of the default branch into the runner's cache, reads its\n.devcontainer/devcontainer.json, and builds the image with the devcontainer CLI. Settings\nthat reach the host or widen the container's privileges are ignored and listed. The\nimage holds this CLI and a pinned Claude Code. Nothing runs inside the image.\n"
4598
4598
  ).action(async (opts) => {
4599
- const { defaultRunnerConfigPath } = await import('./config-XVJYZ4IQ.js');
4599
+ const { defaultRunnerConfigPath } = await import('./config-HL2AIR3K.js');
4600
4600
  const { buildRepositoryImage, RecipeError } = await import('./build-PAEKVYVK.js');
4601
4601
  const { currentCliBuild } = await import('./cli-build-K56DK4DS.js');
4602
4602
  const { createDockerHost } = await import('./docker-NEGDLU6D.js');
@@ -4648,19 +4648,21 @@ Next:
4648
4648
  }
4649
4649
  });
4650
4650
  runnerCmd.command("stop").description("Take no more work; wait for running jobs to finish, 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) => {
4651
- const { defaultRunnerConfigPath } = await import('./config-XVJYZ4IQ.js');
4652
- const { requestStop } = await import('./loop-VGM772I7.js');
4651
+ const { defaultRunnerConfigPath } = await import('./config-HL2AIR3K.js');
4652
+ const { requestStop } = await import('./loop-NEBUGD2Q.js');
4653
4653
  const configPath = opts.config ?? defaultRunnerConfigPath();
4654
4654
  await requestStop(configPath, Boolean(opts.now));
4655
4655
  });
4656
4656
  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) => {
4657
- const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-XVJYZ4IQ.js');
4658
- const { jobsDir } = await import('./paths-OYKMVYJP.js');
4659
- const { listJobFiles, runnerProcessState } = await import('./loop-VGM772I7.js');
4660
- const { renderStatus } = await import('./status-KBDVUYQ3.js');
4657
+ const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-HL2AIR3K.js');
4658
+ const { jobsDir, runnerDir } = await import('./paths-OYKMVYJP.js');
4659
+ const { listJobFiles, runnerProcessState } = await import('./loop-NEBUGD2Q.js');
4660
+ const { renderStatus } = await import('./status-CLATHCTQ.js');
4661
+ const { readHousekeepingRecord } = await import('./record-C43U4PKS.js');
4661
4662
  const path2 = await import('path');
4662
4663
  const configPath = opts.config ?? defaultRunnerConfigPath();
4663
4664
  const all = listJobFiles(configPath);
4665
+ const housekeeping = readHousekeepingRecord(runnerDir(configPath));
4664
4666
  let host = "unknown";
4665
4667
  let concurrency = 1;
4666
4668
  try {
@@ -4676,6 +4678,8 @@ Next:
4676
4678
  configPath,
4677
4679
  process: processState,
4678
4680
  concurrency,
4681
+ // A hold is only true of a runner that is running.
4682
+ housekeeping: processState.state === "running" ? housekeeping : { ...housekeeping, holding: void 0 },
4679
4683
  jobs: all.map(({ dirName, job }) => ({ ...withoutItemKey(job), jobDir: path2.join(jobsDir(configPath), dirName) }))
4680
4684
  });
4681
4685
  return;
@@ -4688,14 +4692,15 @@ Next:
4688
4692
  concurrency,
4689
4693
  jobs: all,
4690
4694
  now: /* @__PURE__ */ new Date(),
4691
- recent: Boolean(opts.recent)
4695
+ recent: Boolean(opts.recent),
4696
+ housekeeping
4692
4697
  })}
4693
4698
  `
4694
4699
  );
4695
4700
  });
4696
4701
  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) => {
4697
- const { defaultRunnerConfigPath } = await import('./config-XVJYZ4IQ.js');
4698
- const { listJobFiles } = await import('./loop-VGM772I7.js');
4702
+ const { defaultRunnerConfigPath } = await import('./config-HL2AIR3K.js');
4703
+ const { listJobFiles } = await import('./loop-NEBUGD2Q.js');
4699
4704
  const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-7RYUH5A6.js');
4700
4705
  const configPath = opts.config ?? defaultRunnerConfigPath();
4701
4706
  const item = parseTrackerNumber(itemArg);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, loadRunnerConfig, resolveBuild, runnerVmOf } from './chunk-5Y3QQRUH.js';
3
+ export { RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, loadRunnerConfig, resolveBuild, runnerVmOf } from './chunk-3DD6AOWC.js';
4
4
  import './chunk-F6GFZXZ3.js';
5
5
  import './chunk-AUFG23AA.js';
6
6
  import './chunk-VNVZDWO3.js';
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { needsClaudeCredential, claudeCredentialCheck, missingPermissionOf, missingPermissionFix } from './chunk-OHFDWLJP.js';
3
+ import { needsClaudeCredential, claudeCredentialCheck, missingPermissionOf, missingPermissionFix } from './chunk-CHLVJNTE.js';
4
+ import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
4
5
  import { RepoFilter } from './chunk-TBT347UY.js';
5
- import './chunk-FC7TMRNA.js';
6
- import { detectMachine, supportsContainerBuilds, describeMachineDocker, reachDockerStep, supportsMicroVmBuilds, microVmArchSupported, microVmAssetsPinned } from './chunk-RJ467PDQ.js';
7
- import { MIN_ENGINE_MAJOR } from './chunk-4NMBDRBS.js';
6
+ import './chunk-W7UTFZDH.js';
7
+ import { detectMachine, supportsContainerBuilds, describeMachineDocker, reachDockerStep, supportsMicroVmBuilds, microVmArchSupported, microVmAssetsPinned } from './chunk-RTXKYLCA.js';
8
+ import { MIN_ENGINE_MAJOR } from './chunk-T52PKE2Y.js';
8
9
  import { CLAUDE_CODE_VERSION } from './chunk-Z62HNKEJ.js';
9
10
  import './chunk-N5FOE5PS.js';
10
11
  import './chunk-OGFGZQA3.js';
@@ -16,7 +17,7 @@ import { getJson, WorkCommandError, signatureRefusalMessage } from './chunk-RMAZ
16
17
  import './chunk-BFESLKPP.js';
17
18
  import './chunk-WOBNRVQT.js';
18
19
  import { compareVersions } from './chunk-EX6M5JPR.js';
19
- import { builtinKind } from './chunk-5Y3QQRUH.js';
20
+ import { builtinKind } from './chunk-3DD6AOWC.js';
20
21
  import { parseSize } from './chunk-F6GFZXZ3.js';
21
22
  import './chunk-AUFG23AA.js';
22
23
  import './chunk-WZBHBH3J.js';
@@ -390,6 +391,18 @@ async function controlPlaneAccessCheck(env, fetchImpl) {
390
391
  detail: readable.length > 0 ? `this host's git login reads ${[...new Set(readable)].join(", ")}` : repositories.length === 0 ? "the factory has no repositories this runner builds" : `no control plane governs ${repositories.length === 1 ? "the repository" : "any of the repositories"} ${listFactory ? "connected to the factory" : "in repos.include"}`
391
392
  };
392
393
  }
394
+ function freeDiskCheck(configPath, minFreeDisk, freeBytes2) {
395
+ const name = "Free disk";
396
+ const free = freeBytes2(runnerDir(configPath));
397
+ if (free === void 0) return { name, status: "warn", detail: "the free space on the runner's file system could not be read" };
398
+ if (free >= minFreeDisk) return { name, status: "pass", detail: `${formatBytes(free)} free, ${formatBytes(minFreeDisk)} needed` };
399
+ return {
400
+ name,
401
+ status: "warn",
402
+ detail: `${formatBytes(free)} free, below runner.housekeeping.minFreeDisk of ${formatBytes(minFreeDisk)}, so this runner claims no new work`,
403
+ fix: "free disk space on the runner's file system, or lower runner.housekeeping.minFreeDisk; the runner takes work again by itself once there is room"
404
+ };
405
+ }
393
406
  async function runnerHostChecks(env) {
394
407
  const dockerAvailable = env.dockerAvailable ?? (() => spawnSync("docker", ["info"], { stdio: "ignore" }).status === 0);
395
408
  const devcontainerRunnable = env.devcontainerRunnable ?? (() => devcontainerCliRunnable());
@@ -409,6 +422,7 @@ async function runnerHostChecks(env) {
409
422
  kvmCheck(env.machine ?? detectMachine()),
410
423
  ...env.runner === void 0 ? [] : [memoryCheck({ concurrency: env.runner.concurrency, buildMemory: env.runner.buildMemory, hostMemory: env.hostMemory ?? totalmem() })]
411
424
  ] : [],
425
+ ...env.runner?.minFreeDisk === void 0 ? [] : [freeDiskCheck(env.configPath, env.runner.minFreeDisk, env.freeBytes ?? freeBytes)],
412
426
  ...env.hooks !== void 0 && needsClaudeCredential(env.hooks) ? [claudeCredentialCheck(env.env ?? process.env, { shell: true })] : [],
413
427
  ...env.gateway === void 0 ? [] : [await hostKeyBindingCheck(env.configPath, env.gateway, env.fetchImpl ?? defaultFetch)],
414
428
  ...env.gateway === void 0 || env.hooks === void 0 || !["container", "vm"].includes(builtinKind(env.hooks.provision)) ? [] : [await controlPlaneAccessCheck({ ...env, gateway: env.gateway }, env.fetchImpl ?? defaultFetch)],
package/dist/index.js CHANGED
@@ -21,5 +21,5 @@ if (argv[0] === "statusline") {
21
21
  await runStatuslineFast(argv.slice(1));
22
22
  process.exit(0);
23
23
  }
24
- var { runCli } = await import('./cli-NNWPFP5S.js');
24
+ var { runCli } = await import('./cli-LHSUYYMI.js');
25
25
  await runCli(process.argv);
@@ -2,9 +2,9 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { execStartCommand } from './chunk-YYYXRJUW.js';
4
4
  import { writeLaunchAgent } from './chunk-LF6MLJCY.js';
5
- import { readConfigObject, RunnerInitError, isPlaceholderCommand } from './chunk-FC7TMRNA.js';
6
- import './chunk-RJ467PDQ.js';
7
- import './chunk-4NMBDRBS.js';
5
+ import { readConfigObject, RunnerInitError, isPlaceholderCommand } from './chunk-W7UTFZDH.js';
6
+ import './chunk-RTXKYLCA.js';
7
+ import './chunk-T52PKE2Y.js';
8
8
  import './chunk-Z62HNKEJ.js';
9
9
  import './chunk-N5FOE5PS.js';
10
10
  import './chunk-OGFGZQA3.js';
@@ -16,7 +16,7 @@ import './chunk-RMAZ2NWA.js';
16
16
  import './chunk-BFESLKPP.js';
17
17
  import './chunk-WOBNRVQT.js';
18
18
  import './chunk-EX6M5JPR.js';
19
- import { resolveBuild } from './chunk-5Y3QQRUH.js';
19
+ import { resolveBuild } from './chunk-3DD6AOWC.js';
20
20
  import { parseSize } from './chunk-F6GFZXZ3.js';
21
21
  import './chunk-AUFG23AA.js';
22
22
  import './chunk-WZBHBH3J.js';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { PLACEHOLDER_MARKER, RunnerInitError, isPlaceholderCommand, readConfigObject, runRunnerInit } from './chunk-FC7TMRNA.js';
4
- import './chunk-RJ467PDQ.js';
5
- import './chunk-4NMBDRBS.js';
3
+ export { PLACEHOLDER_MARKER, RunnerInitError, isPlaceholderCommand, readConfigObject, runRunnerInit } from './chunk-W7UTFZDH.js';
4
+ import './chunk-RTXKYLCA.js';
5
+ import './chunk-T52PKE2Y.js';
6
6
  import './chunk-Z62HNKEJ.js';
7
7
  import './chunk-N5FOE5PS.js';
8
8
  import './chunk-OGFGZQA3.js';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { summarizeChecks, summaryText, renderDoctorText } from './chunk-ZLB7GCTY.js';
3
+ import { summarizeChecks, summaryText, renderDoctorText } from './chunk-H4CK2YK4.js';
4
4
  import { runConnect } from './chunk-OR6AEEDO.js';
5
5
  import './chunk-D2KWEAN6.js';
6
6
  import './chunk-F47JBIAW.js';
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { RunnerStartError, listJobFiles, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick } from './chunk-L24G4PLP.js';
4
- import './chunk-RWOTHXYE.js';
5
- import './chunk-QDQEUVUF.js';
3
+ export { RunnerStartError, listJobFiles, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick } from './chunk-F4NU4H3V.js';
4
+ import './chunk-UWH5DSUP.js';
5
+ import './chunk-ZXBITXTS.js';
6
+ import './chunk-UGP76IZ5.js';
6
7
  import './chunk-ABIWDUMS.js';
7
8
  import './chunk-YYYXRJUW.js';
8
9
  import './chunk-CBPPJSAR.js';
10
+ import './chunk-YYYRBYWG.js';
9
11
  import './chunk-ZOC7JSYC.js';
10
12
  import './chunk-TBT347UY.js';
11
- import './chunk-4NMBDRBS.js';
13
+ import './chunk-T52PKE2Y.js';
12
14
  import './chunk-Z62HNKEJ.js';
13
15
  import './chunk-N5FOE5PS.js';
14
16
  import './chunk-OGFGZQA3.js';
@@ -20,7 +22,7 @@ import './chunk-RMAZ2NWA.js';
20
22
  import './chunk-BFESLKPP.js';
21
23
  import './chunk-WOBNRVQT.js';
22
24
  import './chunk-EX6M5JPR.js';
23
- import './chunk-5Y3QQRUH.js';
25
+ import './chunk-3DD6AOWC.js';
24
26
  import './chunk-F6GFZXZ3.js';
25
27
  import './chunk-AUFG23AA.js';
26
28
  import './chunk-WZBHBH3J.js';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { describeMachineDocker, detectMachine, microVmArchSupported, microVmAssetsPinned, reachDockerStep, supportsContainerBuilds, supportsMicroVmBuilds } from './chunk-RJ467PDQ.js';
4
- import './chunk-4NMBDRBS.js';
3
+ export { describeMachineDocker, detectMachine, microVmArchSupported, microVmAssetsPinned, reachDockerStep, supportsContainerBuilds, supportsMicroVmBuilds } from './chunk-RTXKYLCA.js';
4
+ import './chunk-T52PKE2Y.js';
5
5
  import './chunk-Z62HNKEJ.js';
6
6
  import './chunk-N5FOE5PS.js';
7
7
  import './chunk-OGFGZQA3.js';
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ export { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
4
+ import './chunk-ZM2IMMYN.js';
5
+ import './chunk-Z5GEFMRW.js';
6
+
7
+ createRequire(import.meta.url);
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { LEASE_SECONDS, RENEW_INTERVAL_SECONDS } from './chunk-RWOTHXYE.js';
3
+ import { LEASE_SECONDS, RENEW_INTERVAL_SECONDS } from './chunk-UWH5DSUP.js';
4
4
  import './chunk-CBPPJSAR.js';
5
+ import { formatBytes } from './chunk-YYYRBYWG.js';
5
6
  import './chunk-ZOC7JSYC.js';
6
- import { formatDuration, formatClock, relativeToRunner } from './chunk-4NMBDRBS.js';
7
+ import { formatDuration, formatClock, relativeToRunner } from './chunk-T52PKE2Y.js';
7
8
  import './chunk-Z62HNKEJ.js';
8
9
  import './chunk-N5FOE5PS.js';
9
10
  import './chunk-OGFGZQA3.js';
@@ -15,7 +16,7 @@ import './chunk-RMAZ2NWA.js';
15
16
  import './chunk-BFESLKPP.js';
16
17
  import './chunk-WOBNRVQT.js';
17
18
  import './chunk-EX6M5JPR.js';
18
- import './chunk-5Y3QQRUH.js';
19
+ import './chunk-3DD6AOWC.js';
19
20
  import './chunk-F6GFZXZ3.js';
20
21
  import './chunk-AUFG23AA.js';
21
22
  import './chunk-WZBHBH3J.js';
@@ -55,12 +56,29 @@ function leaseCell(job, now) {
55
56
  const untilNext = RENEW_INTERVAL_SECONDS * 1e3 - sinceMs;
56
57
  return untilNext <= 0 ? "renew due" : `renews ${formatDuration(untilNext)}`;
57
58
  }
59
+ function housekeepingLines(input) {
60
+ const record = input.housekeeping;
61
+ if (record === void 0) return [];
62
+ const lines = [];
63
+ if (record.lastRunAt !== void 0) {
64
+ const ago = formatDuration(input.now.getTime() - new Date(record.lastRunAt).getTime());
65
+ lines.push(`housekeeping last ran ${ago} ago (${formatClock(new Date(record.lastRunAt), input.now)}), freed ${formatBytes(record.freedBytes ?? 0)}`);
66
+ }
67
+ if (record.holding !== void 0 && input.process.state === "running") {
68
+ lines.push(
69
+ `holding off new work for disk: ${formatBytes(record.holding.free)} free, ${formatBytes(record.holding.needed)} needed (since ${formatClock(new Date(record.holding.since), input.now)})`
70
+ );
71
+ }
72
+ return lines;
73
+ }
58
74
  function renderStatus(input) {
59
75
  const lines = [];
60
76
  const running = input.jobs.filter(({ job }) => isUnfinished(job));
61
77
  const finished = input.jobs.filter(({ job }) => !isUnfinished(job)).sort((a, b) => (b.job.endedAt ?? "").localeCompare(a.job.endedAt ?? "")).slice(0, 20);
62
78
  const header = input.process.state === "running" ? `runner ${input.host} running, pid ${input.process.pid} \xB7 config ${input.configPath} \xB7 ${running.length} of ${input.concurrency} slots in use` : input.process.state === "stale" ? `runner ${input.host} not running (stale pid file for pid ${input.process.pid}) \xB7 config ${input.configPath}` : `runner ${input.host} not running (pid file absent) \xB7 config ${input.configPath}`;
63
- lines.push(header, "");
79
+ lines.push(header);
80
+ lines.push(...housekeepingLines(input));
81
+ lines.push("");
64
82
  if (running.length === 0) {
65
83
  lines.push("No running jobs.");
66
84
  } else {
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RUNNER_PROTOCOL } from './chunk-QDQEUVUF.js';
3
+ import { RUNNER_PROTOCOL } from './chunk-ZXBITXTS.js';
4
4
  import { resolveCredentials, WorkCommandError, parsePositiveInt, postJson, resolveRepository, findLiveItem } from './chunk-RMAZ2NWA.js';
5
5
  export { WorkCommandError } from './chunk-RMAZ2NWA.js';
6
6
  import './chunk-BFESLKPP.js';
7
7
  import './chunk-WOBNRVQT.js';
8
8
  import './chunk-EX6M5JPR.js';
9
- import { defaultRunnerConfigPath } from './chunk-5Y3QQRUH.js';
9
+ import { defaultRunnerConfigPath } from './chunk-3DD6AOWC.js';
10
10
  import './chunk-F6GFZXZ3.js';
11
11
  import './chunk-AUFG23AA.js';
12
12
  import './chunk-WZBHBH3J.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outerlayer/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "OuterLayer CLI — commands: init, connect, doctor, login, logout, sync, daemon (alias: watch), emit, work, runner, hooks, mcp, import, 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.",