@outerlayer/cli 0.18.0 → 0.19.0

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 (102) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +21 -2
  3. package/dist/{agent-setup-RBTEACYU.js → agent-setup-TPR4BBFV.js} +15 -16
  4. package/dist/{artifact-link-cmd-AVM2EKTV.js → artifact-link-cmd-W7XF5BFB.js} +2 -2
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-DUI2ZH2H.js → builder-C4QNTYMS.js} +3 -3
  7. package/dist/{check-5C4YDZYV.js → check-UWQAL2MN.js} +44 -43
  8. package/dist/{chunk-S26M3YBJ.js → chunk-3UZTIRLF.js} +1 -1
  9. package/dist/{chunk-W5VPCONO.js → chunk-452TM7J4.js} +33 -227
  10. package/dist/{chunk-UYOYTKE2.js → chunk-5GHGAF6P.js} +3 -3
  11. package/dist/{chunk-QQM2UJ6T.js → chunk-5MYFOW5V.js} +182 -28
  12. package/dist/{chunk-Y5GE76XC.js → chunk-5TN7GLYX.js} +33 -81
  13. package/dist/{chunk-GOBOJMOJ.js → chunk-6D7GT22T.js} +4 -4
  14. package/dist/{chunk-3OFZM4X6.js → chunk-6U3MV7TZ.js} +151 -20
  15. package/dist/{chunk-F4XSVQJ4.js → chunk-6X4SQ5MY.js} +2 -2
  16. package/dist/{chunk-Y5MXET4M.js → chunk-7KSSBQTS.js} +11 -10
  17. package/dist/{chunk-JF42URPU.js → chunk-7SJPQWBM.js} +33 -9
  18. package/dist/{chunk-N3CUDFCW.js → chunk-7VUK5RFS.js} +15 -2
  19. package/dist/{chunk-SWCTGCSC.js → chunk-7YP7T6GV.js} +1 -1
  20. package/dist/{chunk-KDVIU23F.js → chunk-BWSUPRDK.js} +1 -1
  21. package/dist/{chunk-S76AYB4M.js → chunk-CG36IONK.js} +5 -5
  22. package/dist/chunk-CJJDJ7AT.js +56 -0
  23. package/dist/{chunk-FUB7LRUE.js → chunk-DADWEUH3.js} +5 -5
  24. package/dist/{chunk-RAZTWYZN.js → chunk-DJ3ZUSC3.js} +7 -8
  25. package/dist/{chunk-MQJSXHV7.js → chunk-G3IJ3N6F.js} +5 -3
  26. package/dist/{chunk-KK4VBOH6.js → chunk-HPJNLETG.js} +10 -11
  27. package/dist/{chunk-IP7BIBXJ.js → chunk-IF2OSI5T.js} +35 -1
  28. package/dist/{chunk-T4Y6SCG3.js → chunk-IXYZUUYQ.js} +2 -2
  29. package/dist/chunk-KYS3TQAG.js +296 -0
  30. package/dist/chunk-LLM3I5YU.js +89 -0
  31. package/dist/{chunk-B3UKB46N.js → chunk-LRG3ZMZD.js} +4 -5
  32. package/dist/{chunk-ULSIJGLS.js → chunk-NFIR3GEE.js} +56 -14
  33. package/dist/{chunk-MNTSH4CL.js → chunk-NNLA7LLQ.js} +1 -1
  34. package/dist/{chunk-WGAUY5LE.js → chunk-QEFKA2QD.js} +1 -1
  35. package/dist/{chunk-BMYGAGBJ.js → chunk-QNLX477Q.js} +155 -23
  36. package/dist/chunk-TUSYOL2O.js +113 -0
  37. package/dist/{chunk-ESC6UR76.js → chunk-TWF3RICI.js} +6 -6
  38. package/dist/{chunk-NL4XPC7W.js → chunk-UVG35MWF.js} +1 -1
  39. package/dist/{chunk-L2USZT6T.js → chunk-VMJPFQNE.js} +1 -1
  40. package/dist/chunk-VRRGENS4.js +144 -0
  41. package/dist/{chunk-X5N6KC6V.js → chunk-WFSUUUAN.js} +2 -3
  42. package/dist/{chunk-6CHIYEZZ.js → chunk-XSZD4AZ6.js} +9 -83
  43. package/dist/{chunk-LXAY4A2G.js → chunk-YQR6E6OV.js} +34 -49
  44. package/dist/{chunk-47TTLEDX.js → chunk-ZHAUSEEN.js} +35 -13
  45. package/dist/{claude-launcher-YVXI76NX.js → claude-launcher-FPPHZPMR.js} +20 -7
  46. package/dist/{cli-C77H54BV.js → cli-HROW5T7X.js} +203 -228
  47. package/dist/{command-H5CILO4S.js → command-OEAV7BVX.js} +29 -30
  48. package/dist/{config-FXDG4NPJ.js → config-CLSGABD5.js} +2 -2
  49. package/dist/{connect-cmd-ZW5FV3ZW.js → connect-cmd-UNYKGDAL.js} +7 -7
  50. package/dist/context-cleanup-HSVYDGMI.js +9 -0
  51. package/dist/control-plane-launch-NYVDJESK.js +216 -0
  52. package/dist/{dist-QTX4RSCL.js → dist-WO7NOJNG.js} +2 -2
  53. package/dist/{docker-RC3PRX3Q.js → docker-BFU3AQGY.js} +4 -4
  54. package/dist/{doctor-2NQQML6P.js → doctor-23BBJWBX.js} +32 -33
  55. package/dist/{emit-artifact-cmd-7MP63KXU.js → emit-artifact-cmd-O6SCM7TV.js} +17 -17
  56. package/dist/{emit-cmd-PPN4QQF2.js → emit-cmd-7SP3I6UZ.js} +6 -6
  57. package/dist/{emit-criteria-cmd-3RXPDLNK.js → emit-criteria-cmd-LQNERZRV.js} +11 -12
  58. package/dist/{emit-finding-cmd-OL7JB6H3.js → emit-finding-cmd-AJPKHIOV.js} +12 -13
  59. package/dist/{emit-result-cmd-UZVMOCF4.js → emit-result-cmd-RUICOKWQ.js} +17 -17
  60. package/dist/emit-step-cmd-347XNGPQ.js +26 -0
  61. package/dist/{governing-source-BUU4IABS.js → governing-source-V5EEGPTA.js} +21 -22
  62. package/dist/{hook-fast-W5MKHMJT.js → hook-fast-YAZG5MDX.js} +3 -3
  63. package/dist/{import-capture-cmd-ZO6KGHI2.js → import-capture-cmd-KKFFOGWP.js} +4 -4
  64. package/dist/{import-ruler-cmd-KJMWL5V6.js → import-ruler-cmd-5P6JOXQN.js} +2 -2
  65. package/dist/index.js +4 -4
  66. package/dist/{init-WNXXYMO7.js → init-LWHDMZQG.js} +30 -31
  67. package/dist/{init-VWXIZEAN.js → init-MOINY2DD.js} +30 -31
  68. package/dist/{init-cmd-WS6TIRYT.js → init-cmd-HSMRID6A.js} +67 -26
  69. package/dist/{init-update-E3J6TVIN.js → init-update-LWX5MPPR.js} +21 -22
  70. package/dist/{install-CBWIEF3R.js → install-4SEFIIW2.js} +3 -3
  71. package/dist/{login-browser-O63QZN7D.js → login-browser-DX35MARZ.js} +2 -2
  72. package/dist/{loop-UGI2BJOT.js → loop-SYYPVFYW.js} +44 -43
  73. package/dist/{machine-JOW4RNZ7.js → machine-6X63G2KH.js} +26 -27
  74. package/dist/{mcp-serve-cmd-DOTY5FKY.js → mcp-serve-cmd-N3UTY6EE.js} +5 -5
  75. package/dist/{runner-env-4NB2GA7O.js → runner-env-FRZFFHDF.js} +4 -4
  76. package/dist/{runner-key-TC3NFWFV.js → runner-key-276SJU5R.js} +30 -31
  77. package/dist/{session-sender-NNVPSPY7.js → session-sender-GGIY5OAX.js} +19 -15
  78. package/dist/shell-function-NRD4KVUK.js +6 -0
  79. package/dist/{spec-cmd-OWVTBB4J.js → spec-cmd-SIZBRN7D.js} +12 -13
  80. package/dist/{starter-pack-OPWUDOWX.js → starter-pack-6LQVLBIA.js} +5 -5
  81. package/dist/{status-TKCLLKFG.js → status-NAK6DYSF.js} +33 -32
  82. package/dist/{sync-cmd-Q6VYNPWG.js → sync-cmd-G7GF4UTW.js} +18 -14
  83. package/dist/{watch-ARAGADTF.js → watch-EVM5GSMP.js} +18 -14
  84. package/dist/{work-claim-cmd-34FERLYX.js → work-claim-cmd-3J3QW56U.js} +16 -17
  85. package/dist/{work-cmd-7S5B2H2P.js → work-cmd-5EPPD33Y.js} +12 -13
  86. package/dist/{work-comment-cmd-SZJSPM5S.js → work-comment-cmd-2ACOZQAE.js} +12 -13
  87. package/dist/work-logs-cmd-QDD2NMJL.js +60 -0
  88. package/dist/{work-open-pr-cmd-RPXKCBWS.js → work-open-pr-cmd-XNCEI4ZM.js} +13 -14
  89. package/dist/{work-pr-cmd-5LGANL32.js → work-pr-cmd-H4OQR26N.js} +12 -13
  90. package/package.json +2 -2
  91. package/skill-pack/maintained/outerlayer-cli/SKILL.md +9 -2
  92. package/skill-pack/maintained/outerlayer-cli/references/find-out-why-a-build-ended.md +76 -0
  93. package/skill-pack/shipped.json +1 -0
  94. package/skill-pack/template/build/references/release.md +3 -1
  95. package/dist/chunk-WBT5X3NH.js +0 -40
  96. package/dist/chunk-XCCLFVXM.js +0 -401
  97. package/dist/context-adopt-O5OFXMKI.js +0 -109
  98. package/dist/context-materialize-Y5IJ4MQT.js +0 -23
  99. package/dist/{chunk-NACDBXUG.js → chunk-BM63HB2M.js} +1 -1
  100. package/dist/{chunk-ZRL6HKBY.js → chunk-FVMYKL6L.js} +1 -1
  101. package/dist/{chunk-52NC2FIU.js → chunk-NTRCK4NH.js} +1 -1
  102. package/dist/{chunk-XGP3VYOG.js → chunk-P53VEAOF.js} +1 -1
@@ -1,34 +1,34 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { writeJobFile, readJobFile } from './chunk-SADUQSO4.js';
4
- import { senderPidfile } from './chunk-UYOYTKE2.js';
4
+ import { senderPidfile } from './chunk-5GHGAF6P.js';
5
5
  import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-XNGMQ27R.js';
6
- import { installScrubContext } from './chunk-JF42URPU.js';
7
- import { AssetError, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, resolveAgentUser, AgentUserError, runBuildSteps, shellQuote, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, syncInContainer, copyTranscriptsFromContainer, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, copyJudgeTree } from './chunk-Y5MXET4M.js';
8
- import { childEnvironment } from './chunk-L2USZT6T.js';
9
- import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR } from './chunk-S26M3YBJ.js';
6
+ import { installScrubContext } from './chunk-7SJPQWBM.js';
7
+ import { AssetError, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, resolveAgentUser, AgentUserError, runBuildSteps, shellQuote, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, syncInContainer, copyTranscriptsFromContainer, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, copyJudgeTree } from './chunk-7KSSBQTS.js';
8
+ import { childEnvironment } from './chunk-VMJPFQNE.js';
9
+ import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR } from './chunk-3UZTIRLF.js';
10
10
  import { waitForAgent, vmExecArgs } from './chunk-GGOMT6KF.js';
11
11
  import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-X5H2WYMB.js';
12
- import { describeCallFailure, resolveGoverningSource, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, createRunnerLog, formatDuration, retrySend, formatClock } from './chunk-6CHIYEZZ.js';
13
- import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-KK4VBOH6.js';
14
- import { planArtifactUpload } from './chunk-MQJSXHV7.js';
15
- import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-XGP3VYOG.js';
12
+ import { describeCallFailure, resolveGoverningSource, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, formatDuration, retrySend, formatClock } from './chunk-XSZD4AZ6.js';
13
+ import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-HPJNLETG.js';
14
+ import { planArtifactUpload } from './chunk-G3IJ3N6F.js';
15
+ import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-P53VEAOF.js';
16
16
  import { parseSize } from './chunk-7RQ73DLO.js';
17
17
  import { readBranchHead, fetchCommit, diffBetween } from './chunk-3CWUOFV6.js';
18
18
  import { CLAUDE_CODE_VERSION } from './chunk-CX22S5BA.js';
19
19
  import { isSameProcess, startTimeOf } from './chunk-JBJTC3UU.js';
20
- import { scrubText } from './chunk-BMYGAGBJ.js';
21
- import { resolvePackRoot } from './chunk-MNTSH4CL.js';
22
- import { parsePolicy } from './chunk-X5N6KC6V.js';
20
+ import { scrubText } from './chunk-QNLX477Q.js';
21
+ import { resolvePackRoot } from './chunk-NNLA7LLQ.js';
22
+ import { parsePolicy } from './chunk-WFSUUUAN.js';
23
23
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
24
+ import { homeFromEnv } from './chunk-VNVZDWO3.js';
24
25
  import { resolveVersion } from './chunk-RA3O54FC.js';
25
26
  import { signerFor } from './chunk-M2ZWWTWZ.js';
26
27
  import { runnerDir, buildDir, vsockPath, RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
27
28
  import { claudeCredential, repositoriesOf, primaryOf, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, authorEnvironment, withTunnelRecord, commitIdentityRecord, RELAY_PORT, repositoryPath, lifecycleWorkdir, checkEnvironment, EVAL_INPUT_DIR } from './chunk-BQXFBI7T.js';
28
- import { homeFromEnv } from './chunk-VNVZDWO3.js';
29
29
  import { spawn, spawnSync } from 'child_process';
30
30
  import { randomBytes, createHash } from 'crypto';
31
- import { mkdirSync, chmodSync, writeFileSync, appendFileSync, statSync, accessSync, constants, openSync, existsSync, readFileSync, closeSync, rmSync, readdirSync, lstatSync, realpathSync } from 'fs';
31
+ import { mkdirSync, chmodSync, writeFileSync, appendFileSync, statSync, accessSync, constants, openSync, existsSync, readFileSync, closeSync, rmSync, readdirSync, lstatSync, fstatSync, readSync, realpathSync } from 'fs';
32
32
  import { join, isAbsolute, dirname, delimiter, sep } from 'path';
33
33
  import { pathToFileURL } from 'url';
34
34
 
@@ -989,6 +989,119 @@ async function settleVerdict(deps) {
989
989
  await deps.sleep(everyMs);
990
990
  }
991
991
  }
992
+ var RUNNER_LOG_FILE = "runner.log";
993
+ var RUNNER_LOG_KEEP_BYTES = 65536;
994
+ function isTailedStage(stage) {
995
+ const tailed = ["provision", "sync", "cleanup", "report"];
996
+ return tailed.includes(stage);
997
+ }
998
+ var READ_LIMIT_BYTES = 1048576;
999
+ var ITEM_LINE = /^#(\d+)\b/;
1000
+ var AttemptLogBook = class {
1001
+ constructor(now = () => /* @__PURE__ */ new Date()) {
1002
+ this.now = now;
1003
+ this.dirs = /* @__PURE__ */ new Map();
1004
+ this.lastByKey = /* @__PURE__ */ new Map();
1005
+ }
1006
+ /** Starts keeping lines for `item` in `jobDirPath`. Idempotent. */
1007
+ open(item, jobDirPath) {
1008
+ this.dirs.set(Number(item), jobDirPath);
1009
+ }
1010
+ /** Stops keeping lines for `item`; its file stays on disk until housekeeping removes the job directory. */
1011
+ close(item) {
1012
+ const number = Number(item);
1013
+ this.dirs.delete(number);
1014
+ for (const key of [...this.lastByKey.keys()]) {
1015
+ if (key.startsWith(`${number}:`)) this.lastByKey.delete(key);
1016
+ }
1017
+ }
1018
+ /** The log with every line it writes for an open item also kept in that item's file. */
1019
+ wrap(log) {
1020
+ return {
1021
+ line: (text2) => {
1022
+ log.line(text2);
1023
+ this.keepItemLine(text2);
1024
+ },
1025
+ error: (text2) => {
1026
+ log.error(text2);
1027
+ this.keepItemLine(text2);
1028
+ }
1029
+ };
1030
+ }
1031
+ /** One line for `item` that does not itself start with its number. */
1032
+ note(item, text2) {
1033
+ this.append(Number(item), text2);
1034
+ }
1035
+ /** One line, written only when `text` differs from the last one written under `key` for the item. */
1036
+ noteChanged(item, key, text2) {
1037
+ const number = Number(item);
1038
+ const slot = `${number}:${key}`;
1039
+ if (this.lastByKey.get(slot) === text2) return;
1040
+ this.lastByKey.set(slot, text2);
1041
+ this.append(number, text2);
1042
+ }
1043
+ keepItemLine(text2) {
1044
+ const match = ITEM_LINE.exec(text2);
1045
+ if (match !== null) this.append(Number(match[1]), text2);
1046
+ }
1047
+ append(item, text2) {
1048
+ const dir = this.dirs.get(item);
1049
+ if (dir === void 0) return;
1050
+ try {
1051
+ appendFileSync(join(dir, RUNNER_LOG_FILE), `${logStamp(this.now())} ${text2.replace(/[\r\n]+/g, " ")}
1052
+ `, { mode: 384 });
1053
+ } catch {
1054
+ }
1055
+ }
1056
+ };
1057
+ function readEnd(path, maxBytes) {
1058
+ let fd;
1059
+ try {
1060
+ fd = openSync(path, "r");
1061
+ const size = fstatSync(fd).size;
1062
+ const length = Math.min(size, maxBytes);
1063
+ const buffer = Buffer.alloc(length);
1064
+ readSync(fd, buffer, 0, length, size - length);
1065
+ return buffer.toString("utf8");
1066
+ } catch {
1067
+ return void 0;
1068
+ } finally {
1069
+ if (fd !== void 0) closeSync(fd);
1070
+ }
1071
+ }
1072
+ function lastLines(text2, count) {
1073
+ const lines = text2.split("\n");
1074
+ if (lines.at(-1) === "") lines.pop();
1075
+ return lines.slice(-200);
1076
+ }
1077
+ function capRunnerLog(text2) {
1078
+ const bytes = Buffer.from(text2, "utf8");
1079
+ if (bytes.length <= RUNNER_LOG_KEEP_BYTES) return text2;
1080
+ let start = bytes.length - RUNNER_LOG_KEEP_BYTES;
1081
+ if (bytes[start - 1] !== 10) {
1082
+ const newline = bytes.indexOf(10, start);
1083
+ if (newline + 1 < bytes.length) {
1084
+ start = newline + 1;
1085
+ } else {
1086
+ while ((bytes[start] & 192) === 128) start++;
1087
+ }
1088
+ }
1089
+ return `[runner log truncated: the first ${start} bytes were cut]
1090
+ ${bytes.subarray(start).toString("utf8")}`;
1091
+ }
1092
+ function buildReleaseLog(jobDirPath, endStage, scrub) {
1093
+ const parts = [];
1094
+ const own = readEnd(join(jobDirPath, RUNNER_LOG_FILE), READ_LIMIT_BYTES);
1095
+ if (own !== void 0 && own.trim() !== "") parts.push(own.endsWith("\n") ? own.slice(0, -1) : own);
1096
+ if (isTailedStage(endStage)) {
1097
+ const file = `${endStage}.log`;
1098
+ const stage = readEnd(join(jobDirPath, file), READ_LIMIT_BYTES);
1099
+ const tail = stage === void 0 ? [] : lastLines(stage);
1100
+ if (tail.length > 0) parts.push(`--- the last ${tail.length} lines of ${file} ---`, ...tail);
1101
+ }
1102
+ if (parts.length === 0) return void 0;
1103
+ return capRunnerLog(scrub(parts.join("\n")) + "\n");
1104
+ }
992
1105
  var ENDED = "ended before provision finished";
993
1106
  async function provisionProcess(input) {
994
1107
  const { config, runtime, item, repository, jobDir } = input;
@@ -1898,6 +2011,14 @@ function transcriptScrub(config, secrets) {
1898
2011
  function stripUnsendableReasonChars(text2) {
1899
2012
  return text2.replace(/\u0000/g, "").replace(/\p{Cs}/gu, "");
1900
2013
  }
2014
+ function stripTerminalControls(text2) {
2015
+ return text2.replace(/\u001b\[[0-?]*[ -\/]*[@-~]/g, "").replace(/\u001b\][^\u0007\u001b\r\n]*(?:\u0007|\u001b\\)?/g, "").replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g, "");
2016
+ }
2017
+ function releaseLogFor(jobDirPath, job, config) {
2018
+ const home = homeFromEnv();
2019
+ installScrubContext(home, transcriptScrub(config, [job.itemKey, config.apiKey]));
2020
+ return buildReleaseLog(jobDirPath, job.endStage, (text2) => scrubText(stripTerminalControls(stripUnsendableReasonChars(text2))));
2021
+ }
1901
2022
  function readReasonLine(jobDirPath, config, home = homeFromEnv()) {
1902
2023
  let raw;
1903
2024
  try {
@@ -2032,28 +2153,31 @@ async function renewLease(config, item, fetchImpl) {
2032
2153
  }
2033
2154
  var ALREADY_RELEASED = "already released";
2034
2155
  async function releaseLease(config, item, outcome, detail, fetchImpl) {
2035
- const send = async (environment2, sent2) => postJson(
2156
+ const send = async (environment2, sent2, log2) => postJson(
2036
2157
  config.url,
2037
2158
  `/v1/work-items/${item}/claim/release`,
2038
2159
  config.apiKey,
2039
2160
  config.appId,
2040
- { host: config.host, outcome: sent2, stage: detail.stage, exitCode: detail.exitCode, reason: detail.reason, environment: environment2 },
2161
+ { host: config.host, outcome: sent2, stage: detail.stage, exitCode: detail.exitCode, reason: detail.reason, environment: environment2, log: log2 },
2041
2162
  fetchImpl,
2042
2163
  void 0,
2043
2164
  await signerFor(config.configPath)
2044
2165
  );
2045
2166
  let environment = detail.environment;
2046
2167
  let sent = outcome;
2168
+ let log = detail.log;
2047
2169
  let data;
2048
2170
  for (; ; ) {
2049
2171
  try {
2050
- ({ data } = await send(environment, sent));
2172
+ ({ data } = await send(environment, sent, log));
2051
2173
  break;
2052
2174
  } catch (err) {
2053
2175
  if (!(err instanceof WorkCommandError) || err.status !== 400 || err.code !== "invalid_request_body") throw err;
2054
2176
  const namesOutcome = /\boutcome\b/.test(err.message);
2055
2177
  if (sent === "incomplete" && namesOutcome) {
2056
2178
  sent = "ok";
2179
+ } else if (log !== void 0 && /\blog\b/.test(err.message)) {
2180
+ log = void 0;
2057
2181
  } else if (environment?.controlPlane !== void 0) {
2058
2182
  const { controlPlane: _omittedPlane, ...withoutPlane } = environment;
2059
2183
  environment = withoutPlane;
@@ -2150,6 +2274,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
2150
2274
  const jobFilePath = join(jobDirPath, "job.json");
2151
2275
  const logPath = join(jobDirPath, "command.log");
2152
2276
  const tag = `#${job.item}`;
2277
+ deps.attemptLogs?.open(job.item, jobDirPath);
2153
2278
  if (job.sender !== void 0) {
2154
2279
  await stopSender({ job, deps: { spawnFn, runtime: deps.container, log } });
2155
2280
  delete job.sender;
@@ -2424,6 +2549,9 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
2424
2549
  } else if (ending?.reason === void 0) {
2425
2550
  job.reason = (outcome === "ok" ? void 0 : held?.reason) ?? (isolated ? fromHook ?? job.reason : fromHook);
2426
2551
  }
2552
+ if (outcome === "failed" && job.reason === void 0 && job.commandEndReason !== void 0) {
2553
+ job.reason = scrubReason(job.commandEndReason, config);
2554
+ }
2427
2555
  const cliVersion = deps.cliVersion ?? resolveVersion();
2428
2556
  const base = job.environment ?? (job.microvm !== void 0 ? { isolation: "vm", cliVersion } : job.container === void 0 ? sharedUserEnvironment(cliVersion) : { isolation: "container", cliVersion });
2429
2557
  if (isolated || job.build !== void 0) {
@@ -2436,7 +2564,8 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
2436
2564
  writeJobFile(jobFilePath, job);
2437
2565
  }
2438
2566
  const sentAtMs = now().getTime();
2439
- const detail = outcome === void 0 ? {} : { stage: job.endStage, exitCode: job.endExitCode, reason: job.reason, environment: job.environment };
2567
+ const runnerLog = releaseLogFor(jobDirPath, job, config);
2568
+ const detail = outcome === void 0 ? { log: runnerLog } : { stage: job.endStage, exitCode: job.endExitCode, reason: job.reason, environment: job.environment, log: runnerLog };
2440
2569
  const release = await retrySend(() => releaseLease(config, job.item, outcome, detail, deps.fetchImpl), {
2441
2570
  now: deps.now,
2442
2571
  sleep: deps.sleep
@@ -2447,6 +2576,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
2447
2576
  job.endedAt = endedAt.toISOString();
2448
2577
  job.releaseFailed = release.ok ? alreadyReleased ? ALREADY_RELEASED : void 0 : release.reason;
2449
2578
  writeJobFile(jobFilePath, job);
2579
+ deps.attemptLogs?.close(job.item);
2450
2580
  const total = formatDuration(endedAt.getTime() - new Date(job.startedAt).getTime());
2451
2581
  if (alreadyReleased) {
2452
2582
  log.line(
@@ -2492,7 +2622,8 @@ async function retryFailedReleases(jobsDirPath, config, deps) {
2492
2622
  if (!job || job.releaseFailed === void 0 || job.releaseFailed === ALREADY_RELEASED || isUnfinished(job)) {
2493
2623
  continue;
2494
2624
  }
2495
- const detail = job.outcome === void 0 ? {} : { stage: job.endStage, exitCode: job.endExitCode, reason: job.reason, environment: job.environment };
2625
+ const runnerLog = releaseLogFor(dirPath, job, config);
2626
+ const detail = job.outcome === void 0 ? { log: runnerLog } : { stage: job.endStage, exitCode: job.endExitCode, reason: job.reason, environment: job.environment, log: runnerLog };
2496
2627
  const release = await retrySend(() => releaseLease(config, job.item, job.outcome, detail, deps.fetchImpl), {
2497
2628
  now: deps.now,
2498
2629
  sleep: deps.sleep
@@ -2665,4 +2796,4 @@ async function stopSender(input) {
2665
2796
  }
2666
2797
  }
2667
2798
 
2668
- export { ALREADY_RELEASED, LEASE_SECONDS, RENEW_INTERVAL_SECONDS, deliverCommitHooks, describeHookEnd, execArgv, execCommandLine, finishJob, hookLimitsFor, hostCommandEnvironment, hostEnvironment, isGroupAlive, isIdle, isTimedOut, isUnfinished, jobEnv, listAdoptableJobs, listenOnBroker, microVmCommandLine, needsRenew, outcomeFromExitCode, provisionEnvironment, provisionMicroVm, provisionProcess, readCpuUsec, readProvisionOut, recoverLostJobs, releaseLease, renewLease, resolveHostBuild, retryFailedReleases, runCommand, runHook, setStage, startHostServices, startSender, stopOrphanedMicroVms, unfinishedJobs, workdirProblem };
2799
+ export { ALREADY_RELEASED, AttemptLogBook, LEASE_SECONDS, RENEW_INTERVAL_SECONDS, deliverCommitHooks, describeHookEnd, execArgv, execCommandLine, finishJob, hookLimitsFor, hostCommandEnvironment, hostEnvironment, isGroupAlive, isIdle, isTimedOut, isUnfinished, jobEnv, listAdoptableJobs, listenOnBroker, microVmCommandLine, needsRenew, outcomeFromExitCode, provisionEnvironment, provisionMicroVm, provisionProcess, readCpuUsec, readProvisionOut, recoverLostJobs, releaseLease, renewLease, resolveHostBuild, retryFailedReleases, runCommand, runHook, setStage, startHostServices, startSender, stopOrphanedMicroVms, unfinishedJobs, workdirProblem };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-ANPNT6PM.js';
4
- import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-MNTSH4CL.js';
5
- import { resolvePackageVersion } from './chunk-RA3O54FC.js';
4
+ import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-NNLA7LLQ.js';
6
5
  import { cliInvocation } from './chunk-CRB3POP4.js';
6
+ import { resolvePackageVersion } from './chunk-RA3O54FC.js';
7
7
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
8
8
  import { join, dirname } from 'path';
9
9
 
@@ -1,24 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { createDockerHost, childEnvironment, spawnRun } from './chunk-L2USZT6T.js';
4
- import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, JUDGE_DIR, MAX_REPORT_BYTES } from './chunk-S26M3YBJ.js';
3
+ import { currentCliBuild } from './chunk-OGFGZQA3.js';
4
+ import { createDockerHost, childEnvironment, spawnRun } from './chunk-VMJPFQNE.js';
5
+ import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, JUDGE_DIR, MAX_REPORT_BYTES } from './chunk-3UZTIRLF.js';
5
6
  import { execCapture } from './chunk-GGOMT6KF.js';
6
7
  import { GUEST_CID } from './chunk-X5H2WYMB.js';
7
- import { describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, sharedSkillNames, shimScript } from './chunk-6CHIYEZZ.js';
8
- import { WorkCommandError } from './chunk-KK4VBOH6.js';
8
+ import { describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript } from './chunk-XSZD4AZ6.js';
9
+ import { WorkCommandError } from './chunk-HPJNLETG.js';
9
10
  import { hostAllowed } from './chunk-UXYLWVTQ.js';
10
11
  import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
11
12
  import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-3CWUOFV6.js';
12
13
  import { RecipeError } from './chunk-QOZKPLVJ.js';
13
14
  import { CLAUDE_CODE_VERSION, firecrackerArch, MICROVM_ARCHES, DEFAULT_BASE_IMAGE, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_VERSION } from './chunk-CX22S5BA.js';
14
15
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
15
- import { currentCliBuild } from './chunk-OGFGZQA3.js';
16
- import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-BMYGAGBJ.js';
17
- import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-X5N6KC6V.js';
18
- import { downconvertSession } from './chunk-N3CUDFCW.js';
16
+ import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-QNLX477Q.js';
17
+ import { sharedSkillNames, skillConflictMessage } from './chunk-LLM3I5YU.js';
18
+ import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-G2YNJIGF.js';
19
+ import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-WFSUUUAN.js';
20
+ import { downconvertSession } from './chunk-7VUK5RFS.js';
19
21
  import { rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, RUNNER_DIR_MODE, SHIM_DIR, vmAssetsDir } from './chunk-N2PXGQRL.js';
20
22
  import { repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT } from './chunk-BQXFBI7T.js';
21
- import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-G2YNJIGF.js';
22
23
  import { readFileSync, existsSync, mkdirSync, chmodSync, truncateSync, rmSync, writeFileSync, readdirSync, lstatSync, copyFileSync, accessSync, constants, statSync, rmdirSync, renameSync, unlinkSync, openSync, closeSync, mkdtempSync, createWriteStream, createReadStream } from 'fs';
23
24
  import { join, dirname, basename } from 'path';
24
25
  import { spawnSync, spawn } from 'child_process';
@@ -731,7 +732,7 @@ async function deliveryRefusal(input, staged) {
731
732
  const ownNames = new Set(own.stdout.split("\n").map((name) => name.trim()));
732
733
  const clash = sharedSkillNames(join(staged.dir, "tree")).find((name) => ownNames.has(name));
733
734
  if (clash === void 0) return void 0;
734
- return `context_skill_conflict: .claude/skills/${clash} in ${input.repository} has the same name as the shared skill ${clash} from ${staged.repository}, and would replace it in this build; rename or remove it from the repository`;
735
+ return `context_skill_conflict: ${skillConflictMessage({ skill: clash, repository: input.repository, controlPlane: staged.repository })}, and would replace it in this build; rename or remove it from the repository`;
735
736
  }
736
737
  async function deliver(input, staged) {
737
738
  const dir = deliveryDir(staged.repository, staged.sha);
@@ -1,24 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { uploadSpooledSteps } from './chunk-KYS3TQAG.js';
3
4
  import { LaunchFilter } from './chunk-ESVW4MJY.js';
4
5
  import { RepoFilter } from './chunk-TBT347UY.js';
5
- import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-MQJSXHV7.js';
6
+ import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-G3IJ3N6F.js';
7
+ import { writeSyncStatus, spoolDir } from './chunk-NFIR3GEE.js';
6
8
  import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
7
9
  import { applyReportedCost } from './chunk-BKO6JEZI.js';
8
- import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-BMYGAGBJ.js';
10
+ import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-QNLX477Q.js';
9
11
  import { C } from './chunk-ANPNT6PM.js';
10
12
  import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-T2Q7ISPE.js';
11
- import { defaultFetch } from './chunk-ZRL6HKBY.js';
12
- import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-52NC2FIU.js';
13
- import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-N3CUDFCW.js';
14
- import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
15
- import { signerFor, signRunnerRequest } from './chunk-M2ZWWTWZ.js';
16
- import { writeSyncStatus, spoolDir } from './chunk-ULSIJGLS.js';
17
- import { removeJournalHooks } from './chunk-XCCLFVXM.js';
13
+ import { defaultFetch } from './chunk-FVMYKL6L.js';
14
+ import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-NTRCK4NH.js';
18
15
  import { readLatestProvenanceForSession, readContextProvenance } from './chunk-ZJSNLVCE.js';
19
16
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
17
+ import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-7VUK5RFS.js';
18
+ import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
20
19
  import { cliInvocation } from './chunk-CRB3POP4.js';
20
+ import { removeJournalHooks } from './chunk-TUSYOL2O.js';
21
21
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
22
+ import { signerFor, signRunnerRequest } from './chunk-M2ZWWTWZ.js';
22
23
  import { dirname, basename, join } from 'path';
23
24
  import { statSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync, existsSync, rmSync } from 'fs';
24
25
  import { execFileSync } from 'child_process';
@@ -1797,6 +1798,29 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1797
1798
  }
1798
1799
  }
1799
1800
  releaseArtifactLock();
1801
+ const stepPass = await uploadSpooledSteps({
1802
+ home,
1803
+ url,
1804
+ apiKey,
1805
+ appId,
1806
+ kind: resolved.kind,
1807
+ onlyItem: itemScope?.item,
1808
+ fetchImpl,
1809
+ quiet: opts.quiet,
1810
+ lockWaitMs: opts.artifactLockWaitMs
1811
+ });
1812
+ if (stepPass !== void 0) {
1813
+ if (stepPass.uploaded > 0) stats.contacted = true;
1814
+ if (!opts.quiet) {
1815
+ process.stderr.write(
1816
+ `${C.dim}steps${C.reset} ${stepPass.uploaded} uploaded \xB7 ${stepPass.pending} queued \xB7 ${stepPass.dropped} dropped
1817
+ `
1818
+ );
1819
+ }
1820
+ if (stepPass.unauthorized !== void 0) {
1821
+ throw new SyncTransportError(stepPass.unauthorized, 401);
1822
+ }
1823
+ }
1800
1824
  if (shippedBatches === batches.length && (opts.url || opts.apiKey || opts.appId)) {
1801
1825
  if (isLoopbackUrl(url)) {
1802
1826
  if (!opts.quiet) {
@@ -22279,7 +22279,7 @@ var ArtifactTombstoneRecordSchema = external_exports.looseObject({
22279
22279
  });
22280
22280
  external_exports.union([ArtifactSpoolRecordSchema, ArtifactTombstoneRecordSchema]);
22281
22281
  var EMITTED_RESULTS = ["pass", "fail"];
22282
- var RESERVED_EMIT_NAMES = ["artifact", "criteria", "finding", "findings"];
22282
+ var RESERVED_EMIT_NAMES = ["artifact", "criteria", "finding", "findings", "step"];
22283
22283
  var EmittedNameSchema = external_exports.string().regex(/^[a-z][a-z0-9._-]{0,63}$/).superRefine((name, ctx) => {
22284
22284
  if (RESERVED_EMIT_NAMES.includes(name)) {
22285
22285
  ctx.addIssue({
@@ -22324,6 +22324,19 @@ external_exports.object({
22324
22324
  item: external_exports.object({ number: external_exports.number().int().positive() }).optional(),
22325
22325
  sessionId: external_exports.string().optional()
22326
22326
  }).superRefine((request, ctx) => refuseDuplicateIds(request.criteria, ctx));
22327
+ var STEP_NAME_MAX = 80;
22328
+ var CONTROL_CHARACTER = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;
22329
+ var StepNameSchema = external_exports.string().trim().min(1, "name must not be empty").max(STEP_NAME_MAX, `name must be at most ${STEP_NAME_MAX} characters`).refine((name) => !CONTROL_CHARACTER.test(name), {
22330
+ message: "name must be one line, with no line break or control character"
22331
+ });
22332
+ var StepBodySchema = external_exports.object({
22333
+ /** Minted by the CLI once per step; the same id on the same item is the same step. */
22334
+ clientStepId: external_exports.string().uuid(),
22335
+ name: StepNameSchema,
22336
+ item: external_exports.object({ number: external_exports.number().int().positive() }),
22337
+ /** When the agent started the step. The gateway clamps it to the receive time. */
22338
+ startedAt: external_exports.string().datetime({ offset: true })
22339
+ });
22327
22340
  var FINDING_CATEGORIES = ["context", "flaky-test", "tooling", "environment", "defect", "other"];
22328
22341
  var FINDING_RULE_RELATIONS = ["wrong", "broken", "missing"];
22329
22342
  var FINDING_ID_MAX_LENGTH = 64;
@@ -22531,4 +22544,4 @@ xmlchars/xmlns/1.0/ed3.js:
22531
22544
  *)
22532
22545
  */
22533
22546
 
22534
- export { ARTIFACT_KINDS, ARTIFACT_MAX_CAPTION_LENGTH, ARTIFACT_MAX_FILENAME_LENGTH, ARTIFACT_MAX_REPLACES_TARGETS, ArtifactCriterionIdSchema, ArtifactSpoolRecordSchema, ArtifactTombstoneRecordSchema, BUCKET_MODEL_MAX_LENGTH, CAPTURE_TIERS, CriteriaListSchema, EMITTED_RESULTS, EMITTED_RESULT_MAX_BODY_LENGTH, EMITTED_RESULT_MAX_LINK_LENGTH, EVENT_TYPES, EmittedNameSchema, FindingBatchSchema, FindingsResponseSchema, INPUT_BAND_BOUNDARIES, RESERVED_EMIT_NAMES, SAME_PROBLEM_RULES, SCHEMA_VERSION, SPEED_MAX_LENGTH, bannedPathsForTier, bindTests, downconvertSession, inferArtifactKind, inputBandOf, isHumanUserTurn, mediaTypeForArtifactPath, parseAgentSession, parseJunit, parseTestSelector, turnCountBound };
22547
+ export { ARTIFACT_KINDS, ARTIFACT_MAX_CAPTION_LENGTH, ARTIFACT_MAX_FILENAME_LENGTH, ARTIFACT_MAX_REPLACES_TARGETS, ArtifactCriterionIdSchema, ArtifactSpoolRecordSchema, ArtifactTombstoneRecordSchema, BUCKET_MODEL_MAX_LENGTH, CAPTURE_TIERS, CriteriaListSchema, EMITTED_RESULTS, EMITTED_RESULT_MAX_BODY_LENGTH, EMITTED_RESULT_MAX_LINK_LENGTH, EVENT_TYPES, EmittedNameSchema, FindingBatchSchema, FindingsResponseSchema, INPUT_BAND_BOUNDARIES, RESERVED_EMIT_NAMES, SAME_PROBLEM_RULES, SCHEMA_VERSION, SPEED_MAX_LENGTH, StepBodySchema, StepNameSchema, bannedPathsForTier, bindTests, downconvertSession, inferArtifactKind, inputBandOf, isHumanUserTurn, mediaTypeForArtifactPath, parseAgentSession, parseJunit, parseTestSelector, turnCountBound };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { DEFAULT_UNIT_NAME } from './chunk-WGAUY5LE.js';
3
+ import { DEFAULT_UNIT_NAME } from './chunk-QEFKA2QD.js';
4
4
  import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
5
5
  import { RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
6
6
  import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs';
@@ -4,6 +4,6 @@ import { createRequire } from 'node:module';
4
4
  createRequire(import.meta.url);
5
5
 
6
6
  // src/runner/protocol.ts
7
- var RUNNER_PROTOCOL = 19;
7
+ var RUNNER_PROTOCOL = 20;
8
8
 
9
9
  export { RUNNER_PROTOCOL };
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { sanitizeTerminal } from './chunk-MQJSXHV7.js';
4
- import { remoteLookupFailed } from './chunk-BMYGAGBJ.js';
5
- import { DEFAULT_DASHBOARD } from './chunk-NACDBXUG.js';
6
- import { resolveGatewayCredentials } from './chunk-52NC2FIU.js';
7
- import { readCloudConfig } from './chunk-EABW6AJQ.js';
3
+ import { sanitizeTerminal } from './chunk-G3IJ3N6F.js';
4
+ import { DEFAULT_DASHBOARD } from './chunk-BM63HB2M.js';
5
+ import { remoteLookupFailed } from './chunk-QNLX477Q.js';
6
+ import { resolveGatewayCredentials } from './chunk-NTRCK4NH.js';
8
7
  import { writeRepoConnection, findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
8
+ import { readCloudConfig } from './chunk-EABW6AJQ.js';
9
9
  import { cliInvocation } from './chunk-CRB3POP4.js';
10
10
  import { execFileSync } from 'child_process';
11
11
  import { createInterface } from 'readline/promises';
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
4
+ import { join, basename } from 'path';
5
+
6
+ createRequire(import.meta.url);
7
+ var BEGIN = "# BEGIN outerlayer claude";
8
+ var END = "# END outerlayer claude";
9
+ var SHELL_FUNCTION_LINE = 'claude() { outerlayer claude "$@"; }';
10
+ var STARTUP_FILES = { zsh: ".zshrc", bash: ".bashrc" };
11
+ function startupFileFor(home, shellPath) {
12
+ const name = STARTUP_FILES[basename(shellPath ?? "")];
13
+ return name === void 0 ? void 0 : join(home, name);
14
+ }
15
+ function blockLines() {
16
+ return [BEGIN, "# Added by `outerlayer init`. Remove this block, or run `outerlayer init --no-shell-function`, to undo it.", SHELL_FUNCTION_LINE, END];
17
+ }
18
+ function find(lines) {
19
+ let begin = -1;
20
+ for (let i = 0; i < lines.length; i++) {
21
+ if (lines[i] === BEGIN) begin = i;
22
+ else if (lines[i] === END && begin >= 0) return { begin, end: i };
23
+ }
24
+ return void 0;
25
+ }
26
+ function installShellFunction(input) {
27
+ const file = startupFileFor(input.home, input.shellPath);
28
+ if (file === void 0) return { status: "unsupported" };
29
+ const text = existsSync(file) ? readFileSync(file, "utf8") : "";
30
+ if (find(text.split("\n")) !== void 0) return { status: "unchanged", file };
31
+ const endsLine = text === "" || text.endsWith("\n");
32
+ writeFileSync(file, `${text}${endsLine ? "" : "\n"}
33
+ ${blockLines().join("\n")}${endsLine ? "\n" : ""}`);
34
+ return { status: "added", file };
35
+ }
36
+ function removeShellFunction(input) {
37
+ const changed = [];
38
+ for (const name of Object.values(STARTUP_FILES)) {
39
+ const file = join(input.home, name);
40
+ if (!existsSync(file)) continue;
41
+ const lines = readFileSync(file, "utf8").split("\n");
42
+ const found = find(lines);
43
+ if (found === void 0) continue;
44
+ const from = found.begin > 0 && lines[found.begin - 1] === "" ? found.begin - 1 : found.begin;
45
+ lines.splice(from, found.end - from + 1);
46
+ writeFileSync(file, lines.join("\n"));
47
+ changed.push(file);
48
+ }
49
+ return changed;
50
+ }
51
+ function shellFunctionInstalled(input) {
52
+ const file = startupFileFor(input.home, input.shellPath);
53
+ return file !== void 0 && existsSync(file) && find(readFileSync(file, "utf8").split("\n")) !== void 0;
54
+ }
55
+
56
+ export { SHELL_FUNCTION_LINE, installShellFunction, removeShellFunction, shellFunctionInstalled };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { isPlaceholderCommand } from './chunk-GOBOJMOJ.js';
4
- import { describeCallFailure } from './chunk-6CHIYEZZ.js';
5
- import { WorkCommandError, getJson } from './chunk-KK4VBOH6.js';
6
- import { sanitizeTerminal } from './chunk-MQJSXHV7.js';
7
- import { builtinKind } from './chunk-XGP3VYOG.js';
3
+ import { isPlaceholderCommand } from './chunk-6D7GT22T.js';
4
+ import { describeCallFailure } from './chunk-XSZD4AZ6.js';
5
+ import { WorkCommandError, getJson } from './chunk-HPJNLETG.js';
6
+ import { sanitizeTerminal } from './chunk-G3IJ3N6F.js';
7
+ import { builtinKind } from './chunk-P53VEAOF.js';
8
8
  import { signerFor } from './chunk-M2ZWWTWZ.js';
9
9
  import { CLAUDE_CREDENTIAL_VARIABLES, claudeCredential } from './chunk-BQXFBI7T.js';
10
10
 
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { runEmit } from './chunk-47TTLEDX.js';
3
+ import { runEmit } from './chunk-ZHAUSEEN.js';
4
4
  import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
5
- import { installStarterPack } from './chunk-F4XSVQJ4.js';
5
+ import { installStarterPack } from './chunk-6X4SQ5MY.js';
6
6
  import { C } from './chunk-ANPNT6PM.js';
7
- import { resolveGitCommonDir, defaultGitRunner } from './chunk-W5VPCONO.js';
8
- import { pinExists, readContextManifest } from './chunk-LXAY4A2G.js';
9
- import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-MNTSH4CL.js';
10
- import { generatedHeaderSource } from './chunk-X5N6KC6V.js';
7
+ import { resolveGitCommonDir, defaultGitRunner } from './chunk-452TM7J4.js';
8
+ import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-NNLA7LLQ.js';
9
+ import { generatedHeaderSource } from './chunk-WFSUUUAN.js';
11
10
  import { cliInvocation } from './chunk-CRB3POP4.js';
11
+ import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
12
12
  import { execFileSync } from 'child_process';
13
13
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
14
14
  import { join, dirname } from 'path';
@@ -40,10 +40,9 @@ function gitTopLevel(cwd) {
40
40
  }
41
41
  }
42
42
  function contextComesFromControlPlane(repoRoot) {
43
- if (pinExists(repoRoot)) return true;
44
43
  const gitCommonDir = resolveGitCommonDir(defaultGitRunner, repoRoot);
45
44
  if (gitCommonDir === void 0) throw new GitLookupError("git could not report this repository's git directory");
46
- return readContextManifest(gitCommonDir) !== void 0;
45
+ return cloneIsGoverned(gitCommonDir);
47
46
  }
48
47
  function mcpReplacementLosesNothing(existing, content) {
49
48
  try {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { ArtifactTombstoneRecordSchema, ArtifactSpoolRecordSchema } from './chunk-N3CUDFCW.js';
3
+ import { ArtifactTombstoneRecordSchema, ArtifactSpoolRecordSchema } from './chunk-7VUK5RFS.js';
4
4
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
5
  import { mkdirSync, appendFileSync, writeFileSync, renameSync, unlinkSync, existsSync, readdirSync, readFileSync, statSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -273,7 +273,9 @@ function artifactLockIsStale(path, nowMs, isAlive) {
273
273
  }
274
274
  }
275
275
  async function acquireArtifactSpoolLock(home = homeFromEnv(), opts = {}) {
276
- const path = artifactsLockPath(home);
276
+ return acquireSpoolLockAt(artifactsLockPath(home), opts);
277
+ }
278
+ async function acquireSpoolLockAt(path, opts = {}) {
277
279
  const waitMs = opts.waitMs ?? ARTIFACT_LOCK_WAIT_MS;
278
280
  const sleep = opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
279
281
  const isAlive = opts.isAlive ?? processIsAlive;
@@ -460,4 +462,4 @@ function resolveArtifactTurnIndex(turns, filename) {
460
462
  return found;
461
463
  }
462
464
 
463
- export { ARTIFACT_RETRY_MAX_AGE_MS, acquireArtifactSpoolLock, appendArtifactRecord, appendArtifactTombstone, artifactBlobsDir, artifactsSpoolPath, artifactsStatePath, findPendingArtifactRecord, isArtifactTombstoned, localArtifactIds, migrateLegacyArtifactSidecars, neededArtifactShas, planArtifactUpload, readEffectiveArtifactSpoolState, reclaimUnneededArtifactBlobs, resolveArtifactTurnIndex, sanitizeTerminal, writeArtifactSpoolState };
465
+ export { ARTIFACT_RETRY_MAX_AGE_MS, acquireArtifactSpoolLock, acquireSpoolLockAt, appendArtifactRecord, appendArtifactTombstone, artifactBlobsDir, artifactsSpoolPath, artifactsStatePath, findPendingArtifactRecord, isArtifactTombstoned, localArtifactIds, migrateLegacyArtifactSidecars, neededArtifactShas, planArtifactUpload, readEffectiveArtifactSpoolState, reclaimUnneededArtifactBlobs, resolveArtifactTurnIndex, sanitizeTerminal, writeArtifactSpoolState };