@outerlayer/cli 0.8.1 → 0.8.2

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 (86) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +27 -9
  3. package/dist/{agent-setup-K6RD2Z4P.js → agent-setup-C5X4356W.js} +8 -8
  4. package/dist/{build-MS34XEGN.js → build-3FSJR5OO.js} +1 -1
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-IG6FNA54.js → builder-QZA2Z3M3.js} +3 -3
  7. package/dist/{check-GX5ND6RO.js → check-HQHFAOXW.js} +27 -27
  8. package/dist/{chunk-R7STSBLC.js → chunk-2E2MG3KW.js} +1 -1
  9. package/dist/{chunk-OD2VTIHN.js → chunk-2FWL7CE2.js} +3 -2
  10. package/dist/{chunk-PXFEYBDE.js → chunk-33GOCSRO.js} +3 -3
  11. package/dist/{chunk-HSN5QNS5.js → chunk-3J476JZC.js} +10 -10
  12. package/dist/{chunk-MQ3IPHIZ.js → chunk-47RS42OZ.js} +6 -3
  13. package/dist/{chunk-4FPWKV7L.js → chunk-4ZZR5SKG.js} +3 -3
  14. package/dist/{chunk-PWBILI5P.js → chunk-7KI224YS.js} +1 -1
  15. package/dist/{chunk-2BRSMBBB.js → chunk-CLURXEWV.js} +2 -2
  16. package/dist/{chunk-7ZR5UPMB.js → chunk-CMFCCIQN.js} +167 -1
  17. package/dist/{chunk-AX23QKHS.js → chunk-CRLAB4PM.js} +1 -1
  18. package/dist/{chunk-M4ERCYDB.js → chunk-EQG7L6LM.js} +232 -15
  19. package/dist/{chunk-I7CJIRMM.js → chunk-ERI5GBNI.js} +6 -1
  20. package/dist/{chunk-ILEA3YHM.js → chunk-EWBM2USM.js} +2 -2
  21. package/dist/{chunk-EV3M3EH7.js → chunk-G54QHBTI.js} +2 -2
  22. package/dist/{chunk-M3SQ4YGD.js → chunk-GXSMDL4M.js} +1 -1
  23. package/dist/{chunk-GAYWY4GI.js → chunk-HN2JBGSI.js} +2 -1
  24. package/dist/{chunk-ZOAEPWGL.js → chunk-HWMYGAKF.js} +1 -1
  25. package/dist/{chunk-ABIWDUMS.js → chunk-IS4DIGBQ.js} +13 -1
  26. package/dist/{chunk-WVGSB3Z2.js → chunk-J5DPVNL3.js} +2 -2
  27. package/dist/{chunk-VXLJORHL.js → chunk-JXH6LEEH.js} +1 -1
  28. package/dist/{chunk-KSLNQOOS.js → chunk-KI7VPNKC.js} +1 -1
  29. package/dist/{chunk-QNRSFEGY.js → chunk-LSPJHYHM.js} +1 -1
  30. package/dist/{chunk-QB5JQH5V.js → chunk-M2F2RAMK.js} +72 -19
  31. package/dist/{chunk-Z2THOHPP.js → chunk-MJLUWGUD.js} +2 -2
  32. package/dist/{chunk-BQFNZOMQ.js → chunk-NACLOOXP.js} +4 -4
  33. package/dist/{chunk-TEKZRTM3.js → chunk-NPBLDMSD.js} +1 -1
  34. package/dist/{chunk-BOLTI6LR.js → chunk-PLMTLGYH.js} +1 -1
  35. package/dist/{chunk-Q4432IZT.js → chunk-QJPO42VI.js} +5 -5
  36. package/dist/{chunk-KV47VQJZ.js → chunk-R5SPFO6F.js} +4 -4
  37. package/dist/{chunk-5ODHQP6O.js → chunk-VUGDEUMM.js} +55 -12
  38. package/dist/{chunk-4ACZCY4I.js → chunk-WMPO3SKK.js} +3 -3
  39. package/dist/{chunk-TTNFGMHO.js → chunk-Y7UQHKFY.js} +19 -1
  40. package/dist/{chunk-BF4KKEFY.js → chunk-YU4Z2O3W.js} +3 -3
  41. package/dist/{chunk-ZZXLM64C.js → chunk-ZJ3WRVRG.js} +1 -1
  42. package/dist/{cli-X5ONGYNY.js → cli-OWM54BIU.js} +87 -84
  43. package/dist/{command-7NFU3IPO.js → command-LIHTWJHQ.js} +24 -21
  44. package/dist/{config-Z3USDBLU.js → config-OOBPCY7Q.js} +2 -2
  45. package/dist/{connect-cmd-PNZ6IJLJ.js → connect-cmd-NV7WVBY7.js} +3 -3
  46. package/dist/{context-adopt-D2Z7F7PB.js → context-adopt-PPCNSN5D.js} +5 -5
  47. package/dist/{context-materialize-4PMTDS6K.js → context-materialize-YR3JQCUF.js} +5 -5
  48. package/dist/{dist-3ZTZF2TP.js → dist-2LNAXGPZ.js} +1 -1
  49. package/dist/{docker-PRHRSJM5.js → docker-RSALMGPL.js} +4 -4
  50. package/dist/{doctor-KALLPCRB.js → doctor-PKT42NOJ.js} +57 -23
  51. package/dist/{emit-artifact-cmd-D5GMVWNC.js → emit-artifact-cmd-BZYXRBCV.js} +6 -6
  52. package/dist/{emit-cmd-2QRMYPYO.js → emit-cmd-IRYNFHPM.js} +3 -3
  53. package/dist/{emit-criteria-cmd-IE7VIM64.js → emit-criteria-cmd-PSZYZ32B.js} +4 -4
  54. package/dist/{emit-finding-cmd-46PTPN3A.js → emit-finding-cmd-VTSYDJYZ.js} +4 -4
  55. package/dist/{emit-result-cmd-KXHHP6HX.js → emit-result-cmd-5P7ZFWMZ.js} +6 -6
  56. package/dist/{exec-client-NPYNUAF3.js → exec-client-2UX6NHAO.js} +3 -3
  57. package/dist/{guest-init-JWNNAH2H.js → guest-init-VHQNFCFS.js} +3 -3
  58. package/dist/{hook-fast-5H5QBJKT.js → hook-fast-OCHVQZTU.js} +1 -1
  59. package/dist/{import-capture-cmd-T4556ELW.js → import-capture-cmd-2QFLZQFY.js} +3 -3
  60. package/dist/{import-ruler-cmd-SG3UVGI7.js → import-ruler-cmd-BD22GUJS.js} +1 -1
  61. package/dist/index.js +3 -3
  62. package/dist/{init-B4CECVOX.js → init-CY4IMZE4.js} +20 -20
  63. package/dist/{init-S4DH6PWW.js → init-TQUN5RF7.js} +18 -18
  64. package/dist/{init-cmd-P4MVCBCZ.js → init-cmd-F4TZXQJH.js} +9 -9
  65. package/dist/{install-FHTVJZS6.js → install-C33LT5KQ.js} +3 -3
  66. package/dist/{install-cmd-BEC7XTNG.js → install-cmd-5HYMXLEW.js} +1 -1
  67. package/dist/{loop-ODMRE3CW.js → loop-NZP5FAC3.js} +27 -27
  68. package/dist/{machine-J4SAB3Z2.js → machine-RUSNVLKO.js} +17 -17
  69. package/dist/{mcp-install-cmd-RLK4SO3N.js → mcp-install-cmd-4AQMSIGY.js} +1 -1
  70. package/dist/{mcp-serve-cmd-CT47P4YQ.js → mcp-serve-cmd-3KVYEUXG.js} +1 -1
  71. package/dist/{real-deps-SU24ZA2K.js → real-deps-TK6JMQSW.js} +3 -2
  72. package/dist/{session-sender-V46VPWQ5.js → session-sender-EECVKXTC.js} +5 -5
  73. package/dist/{starter-pack-MUXMAU4S.js → starter-pack-VNWPYP5U.js} +3 -3
  74. package/dist/{status-QBKSH3QE.js → status-KCONQLOD.js} +29 -23
  75. package/dist/{sync-cmd-RJR77V4O.js → sync-cmd-R54ZBHXX.js} +4 -4
  76. package/dist/{watch-YNZTFLEY.js → watch-YTFNBO3S.js} +4 -4
  77. package/dist/{work-claim-cmd-KAD3ZAH7.js → work-claim-cmd-HRPJ4VUF.js} +8 -8
  78. package/dist/{work-cmd-CNWPTH7W.js → work-cmd-W4GQUUBC.js} +5 -5
  79. package/dist/{work-comment-cmd-HH45S6UE.js → work-comment-cmd-DDZ4SZ35.js} +5 -5
  80. package/dist/{work-open-pr-cmd-5KR3KFCN.js → work-open-pr-cmd-GXULDTSC.js} +6 -6
  81. package/dist/{work-pr-cmd-TTEGCP76.js → work-pr-cmd-T6SU4TYN.js} +5 -5
  82. package/package.json +1 -1
  83. package/skill-pack/maintained/outerlayer/SKILL.md +12 -2
  84. package/skill-pack/maintained/outerlayer/references/open-pull-request.md +29 -0
  85. package/skill-pack/template/build/SKILL.md +3 -2
  86. package/skill-pack/template/build/references/release.md +11 -2
@@ -1,21 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-TTNFGMHO.js';
3
+ import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-Y7UQHKFY.js';
4
4
  import { startTimeOf, isSameProcess } from './chunk-N5FOE5PS.js';
5
5
  import { currentCliBuild } from './chunk-OGFGZQA3.js';
6
- import { createDockerHost, childEnvironment, spawnRun } from './chunk-TEKZRTM3.js';
6
+ import { createDockerHost, childEnvironment, spawnRun } from './chunk-NPBLDMSD.js';
7
7
  import { RecipeError } from './chunk-QOZKPLVJ.js';
8
- import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-2BRSMBBB.js';
8
+ import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-CLURXEWV.js';
9
9
  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';
10
- import { execCapture } from './chunk-ZOAEPWGL.js';
11
- import { GUEST_CID } from './chunk-R7STSBLC.js';
12
- import { WorkCommandError, postJson } from './chunk-KV47VQJZ.js';
10
+ import { execCapture } from './chunk-HWMYGAKF.js';
11
+ import { GUEST_CID } from './chunk-2E2MG3KW.js';
12
+ import { WorkCommandError, postJson } from './chunk-R5SPFO6F.js';
13
+ import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-HN2JBGSI.js';
13
14
  import { hostAllowed } from './chunk-UXYLWVTQ.js';
14
15
  import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
15
- import { RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING } from './chunk-OD2VTIHN.js';
16
- import { defaultGitRunner, materializeContext } from './chunk-BQFNZOMQ.js';
17
- import { readContextManifest, readSourceCache } from './chunk-ZZXLM64C.js';
16
+ import { RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING } from './chunk-2FWL7CE2.js';
17
+ import { defaultGitRunner, materializeContext } from './chunk-NACLOOXP.js';
18
+ import { readContextManifest, readSourceCache } from './chunk-ZJ3WRVRG.js';
19
+ import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-CMFCCIQN.js';
18
20
  import { signingFetchFor } from './chunk-YO4PSLVB.js';
21
+ import { downconvertSession } from './chunk-YNJEOGDL.js';
19
22
  import { signerFor } from './chunk-V7NIVOFD.js';
20
23
  import { rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, stagedContextDir, contextHomeDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, RUNNER_DIR_MODE, vmAssetsDir } from './chunk-ZM2IMMYN.js';
21
24
  import { relative, join, dirname, basename } from 'path';
@@ -430,7 +433,11 @@ async function prepareBranch(opts) {
430
433
  throw new BranchPrepareError(`the pull request's branch ${branch} is not on the remote`);
431
434
  }
432
435
  await mustGit(git2, workdir, `checking out ${branch}`, ["checkout", "--quiet", "-B", branch, start]);
433
- return { branch, head: await mustGit(git2, workdir, "reading the checked-out commit", ["rev-parse", "HEAD"]) };
436
+ return {
437
+ branch,
438
+ head: await mustGit(git2, workdir, "reading the checked-out commit", ["rev-parse", "HEAD"]),
439
+ startCommit: await mustGit(git2, workdir, `reading the commit of ${defaultBranch}`, ["rev-parse", `origin/${defaultBranch}`])
440
+ };
434
441
  }
435
442
  async function isMerged(git2, workdir, branch, defaultBranch) {
436
443
  const result = await git2(workdir, ["merge-base", "--is-ancestor", `origin/${branch}`, `origin/${defaultBranch}`]);
@@ -892,6 +899,7 @@ function adoptionFailureReason(result) {
892
899
  }
893
900
  async function runBuildSteps(input) {
894
901
  const { exec, log, tag, repository } = input;
902
+ let startCommit = "";
895
903
  const rewrite = await exec(["git", "config", "--global", `url.http://127.0.0.1:${RELAY_PORT}/github.com/.insteadOf`, "https://github.com/"], "/build/work");
896
904
  if (rewrite.status !== 0) return { ok: false, reason: `configuring the build's git remote failed (exit ${rewrite.status})` };
897
905
  const clone = await exec(["git", "clone", "--filter=blob:none", "--single-branch", `https://github.com/${repository}.git`, CHECKOUT_DIR], "/build/work");
@@ -908,6 +916,7 @@ async function runBuildSteps(input) {
908
916
  return { status: ran.status, stdout: ran.stdout.trim(), stderr: ran.stderr.trim() };
909
917
  }
910
918
  });
919
+ startCommit = prepared.startCommit;
911
920
  log.line(`${tag} on ${prepared.branch} at ${prepared.head.slice(0, 8)}`);
912
921
  } catch (err) {
913
922
  if (err instanceof BranchPrepareError) return { ok: false, reason: err.message };
@@ -934,7 +943,200 @@ async function runBuildSteps(input) {
934
943
  }
935
944
  if (input.aborted()) return aborted();
936
945
  }
937
- return { ok: true };
946
+ return { ok: true, startCommit };
947
+ }
948
+ var EVAL_INPUT_NAME = "eval-input";
949
+ var TRANSCRIPT_ROOT = "/build/home/.claude/projects";
950
+ var MAX_TRANSCRIPT_BYTES = 7 * 1024 * 1024;
951
+ var MAX_TRANSCRIPTS = 500;
952
+ var MAX_TOTAL_TRANSCRIPT_BYTES = 64 * 1024 * 1024;
953
+ var TRANSCRIPT_COPY_MS = 2 * 60 * 1e3;
954
+ var BUILD_HOME = "/build/home";
955
+ function firstLine4(text) {
956
+ return text.trim().split("\n")[0] ?? "";
957
+ }
958
+ async function copyTranscripts(run, now = Date.now) {
959
+ const deadline = now() + TRANSCRIPT_COPY_MS;
960
+ let listed;
961
+ try {
962
+ listed = await run(["find", TRANSCRIPT_ROOT, "-type", "f", "-name", "*.jsonl", "-print0"]);
963
+ } catch (err) {
964
+ return { ok: false, reason: describeCallFailure(err) };
965
+ }
966
+ if (listed.status !== 0 && !/No such file or directory/.test(listed.stderr)) {
967
+ return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${firstLine4(listed.stderr) === "" ? "" : `: ${firstLine4(listed.stderr)}`}` };
968
+ }
969
+ const paths = listed.stdout.split("\0").filter((entry) => entry.startsWith(`${TRANSCRIPT_ROOT}/`) && !entry.includes("\n") && !entry.slice(TRANSCRIPT_ROOT.length + 1).split("/").includes("..")).map((entry) => entry.slice(TRANSCRIPT_ROOT.length + 1)).sort();
970
+ const copied = [];
971
+ const missed = [];
972
+ let total = 0;
973
+ for (const [index, path] of paths.entries()) {
974
+ if (index >= MAX_TRANSCRIPTS) {
975
+ missed.push({ path, reason: `the build wrote more than ${MAX_TRANSCRIPTS} transcripts` });
976
+ continue;
977
+ }
978
+ if (now() >= deadline) {
979
+ missed.push({ path, reason: `copying the transcripts took longer than ${TRANSCRIPT_COPY_MS / 1e3} seconds` });
980
+ continue;
981
+ }
982
+ try {
983
+ const read = await run(["head", "-c", String(MAX_TRANSCRIPT_BYTES + 1), `${TRANSCRIPT_ROOT}/${path}`]);
984
+ if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${firstLine4(read.stderr) === "" ? "" : `: ${firstLine4(read.stderr)}`}` });
985
+ else if (Buffer.byteLength(read.stdout) > MAX_TRANSCRIPT_BYTES) missed.push({ path, reason: `it is larger than ${MAX_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
986
+ else if (total + Buffer.byteLength(read.stdout) > MAX_TOTAL_TRANSCRIPT_BYTES) missed.push({ path, reason: `copying it would take the transcripts past ${MAX_TOTAL_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
987
+ else {
988
+ total += Buffer.byteLength(read.stdout);
989
+ copied.push({ path, content: read.stdout });
990
+ }
991
+ } catch (err) {
992
+ missed.push({ path, reason: describeCallFailure(err) });
993
+ }
994
+ }
995
+ return { ok: true, copied, missed };
996
+ }
997
+ function traceIdForSession(sessionId) {
998
+ const stripped = sessionId.replace(/-/g, "").toLowerCase();
999
+ if (/^[0-9a-f]{32}$/.test(stripped)) return stripped;
1000
+ return createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
1001
+ }
1002
+ function sessionOptionsOf(path) {
1003
+ const segments = path.split("/");
1004
+ const stem = (segments.at(-1) ?? path).replace(/\.jsonl$/, "");
1005
+ const at = segments.lastIndexOf("subagents");
1006
+ if (at <= 0) return { fallbackId: stem };
1007
+ const parent = segments[at - 1];
1008
+ return {
1009
+ fallbackId: stem,
1010
+ isSubagent: true,
1011
+ ...parent ? { parentSessionId: parent } : {},
1012
+ ownId: stem,
1013
+ ...segments[at + 1] === "workflows" && segments[at + 2] ? { workflowRunId: segments[at + 2] } : {}
1014
+ };
1015
+ }
1016
+ function scrubbing(scrub, author, work) {
1017
+ setCustomScrubbers(scrub, () => void 0);
1018
+ setLocalIdentity({ home: BUILD_HOME, ...author?.name === void 0 ? {} : { name: author.name }, ...author?.email === void 0 ? {} : { email: author.email } });
1019
+ setRepoRoot(CHECKOUT_DIR);
1020
+ try {
1021
+ return work();
1022
+ } finally {
1023
+ setCustomScrubbers(void 0, () => void 0);
1024
+ setLocalIdentity({});
1025
+ setRepoRoot(void 0);
1026
+ }
1027
+ }
1028
+ function scrubLine(line) {
1029
+ try {
1030
+ return JSON.stringify(scrubDeep(JSON.parse(line)));
1031
+ } catch {
1032
+ return scrubText(line);
1033
+ }
1034
+ }
1035
+ function writeReadOnly(path, text) {
1036
+ writeFileSync(path, text);
1037
+ chmodSync(path, 292);
1038
+ }
1039
+ function diffBase(job) {
1040
+ const recorded = (job.container ?? job.microvm)?.startCommit;
1041
+ if (recorded !== void 0 && recorded !== "") return { commit: recorded, source: "build" };
1042
+ const recipe = job.environment?.recipe?.sourceCommit;
1043
+ return recipe === void 0 || recipe === "" ? void 0 : { commit: recipe, source: "recipe" };
1044
+ }
1045
+ async function writeEvalInput(request) {
1046
+ const { job, dir, log } = request;
1047
+ const tag = `#${job.item}`;
1048
+ rmSync(dir, { recursive: true, force: true });
1049
+ mkdirSync(join(dir, "sessions"), { recursive: true });
1050
+ chmodSync(dir, 493);
1051
+ chmodSync(join(dir, "sessions"), 493);
1052
+ let workItem;
1053
+ try {
1054
+ const data = await request.readWorkItem();
1055
+ writeReadOnly(join(dir, "work-item.json"), `${JSON.stringify(data, null, 2)}
1056
+ `);
1057
+ workItem = { status: "written" };
1058
+ } catch (err) {
1059
+ workItem = { status: "unavailable", reason: describeCallFailure(err) };
1060
+ log.error(`${tag} the work item could not be read for the checks' input: ${workItem.reason}`);
1061
+ }
1062
+ const patch = join(dir, "diff.patch");
1063
+ const base = diffBase(job);
1064
+ let diff;
1065
+ if (base === void 0) {
1066
+ diff = { status: "unavailable", reason: "the build recorded no commit it started from" };
1067
+ } else {
1068
+ const fetched = await request.fetchDiff({ remote: request.remote, dir: join(request.scratch, "diff"), base: base.commit, head: request.branchHead, token: request.readToken, output: patch });
1069
+ diff = fetched.ok ? { status: "written", base: base.commit, head: request.branchHead, baseSource: base.source } : { status: "unavailable", base: base.commit, head: request.branchHead, baseSource: base.source, reason: fetched.reason };
1070
+ if (!fetched.ok) log.error(`${tag} the diff could not be read for the checks' input: ${fetched.reason}`);
1071
+ }
1072
+ if (diff.status === "unavailable") writeFileSync(patch, "");
1073
+ chmodSync(patch, 292);
1074
+ const sessions = [];
1075
+ const parsed = [];
1076
+ const copiedByTrace = /* @__PURE__ */ new Map();
1077
+ let sessionsUnavailable;
1078
+ if (!request.transcripts.ok) {
1079
+ sessionsUnavailable = request.transcripts.reason;
1080
+ log.error(`${tag} the sessions could not be copied for the checks' input: ${sessionsUnavailable}`);
1081
+ } else {
1082
+ const { copied, missed } = request.transcripts;
1083
+ scrubbing(request.scrub, request.job.commitIdentity?.author, () => {
1084
+ for (const transcript of copied) {
1085
+ const options = sessionOptionsOf(transcript.path);
1086
+ const subagent = options.isSubagent === true;
1087
+ const stem = options.fallbackId ?? transcript.path;
1088
+ let session = null;
1089
+ try {
1090
+ session = parseTranscript(transcript.content, options).session;
1091
+ } catch {
1092
+ }
1093
+ const traceId = traceIdForSession(session?.id ?? stem);
1094
+ if (session === null) {
1095
+ sessions.push({ traceId, subagent, status: "missing", reason: "the transcript holds no session" });
1096
+ log.error(`${tag} the transcript ${transcript.path} holds no session, so the checks' input leaves it out`);
1097
+ continue;
1098
+ }
1099
+ const kept = copiedByTrace.get(traceId);
1100
+ if (kept !== void 0) {
1101
+ kept.duplicates = (kept.duplicates ?? 0) + 1;
1102
+ log.error(`${tag} the transcript ${transcript.path} repeats session ${traceId}, so the checks' input leaves it out`);
1103
+ continue;
1104
+ }
1105
+ const file = `sessions/${traceId}.jsonl`;
1106
+ const text = transcript.content.split("\n").filter((line) => line.trim() !== "").map(scrubLine).join("\n");
1107
+ writeReadOnly(join(dir, file), `${text}
1108
+ `);
1109
+ scrubDeep(session);
1110
+ parsed.push({ session: downconvertSession(session, "full"), traceId, subagent });
1111
+ const entry = { traceId, subagent, file, status: "copied" };
1112
+ copiedByTrace.set(traceId, entry);
1113
+ sessions.push(entry);
1114
+ }
1115
+ for (const miss of missed) {
1116
+ const options = sessionOptionsOf(miss.path);
1117
+ sessions.push({ traceId: traceIdForSession(options.fallbackId ?? miss.path), subagent: options.isSubagent === true, status: "missing", reason: miss.reason });
1118
+ log.error(`${tag} the transcript ${miss.path} could not be copied for the checks' input: ${miss.reason}`);
1119
+ }
1120
+ });
1121
+ }
1122
+ const ordered = orderSessions(parsed.map((entry) => entry.session));
1123
+ const traceOf = new Map(parsed.map((entry) => [entry.session.id, entry.traceId]));
1124
+ const facts = extractFacts(sessionsToTimeline(parsed.map((entry) => entry.session)));
1125
+ const traceAt = (index) => traceOf.get(ordered[index].id);
1126
+ const recorded = { commands: facts.coverage.has("commands"), edits: facts.coverage.has("edits") };
1127
+ const activity = {
1128
+ schemaVersion: 1,
1129
+ sessions: sessions.sort((a, b) => a.traceId.localeCompare(b.traceId)),
1130
+ // Left out of the file when undefined.
1131
+ sessionsUnavailable,
1132
+ workItem,
1133
+ diff,
1134
+ recorded,
1135
+ commands: recorded.commands ? facts.runs.map((run) => ({ seq: run.seq, traceId: traceAt(run.sessionIndex), turn: run.turnIndex, command: run.normalized, kind: run.kind, status: run.status })) : null,
1136
+ edits: recorded.edits ? facts.edits.map((edit) => ({ seq: edit.seq, traceId: traceAt(edit.sessionIndex), turn: edit.turnIndex, file: edit.file, status: edit.status })) : null
1137
+ };
1138
+ writeReadOnly(join(dir, "activity.json"), `${JSON.stringify(activity, null, 2)}
1139
+ `);
938
1140
  }
939
1141
 
940
1142
  // src/runner/container/agent-user.ts
@@ -1996,7 +2198,7 @@ function gitRemoteFor(runtime, input) {
1996
2198
  ...input.readOnly === true ? { readOnly: true } : {}
1997
2199
  });
1998
2200
  }
1999
- function firstLine4(text) {
2201
+ function firstLine5(text) {
2000
2202
  return text.trim().split("\n")[0] ?? "";
2001
2203
  }
2002
2204
  var NO_ENV = { literals: {}, passed: {} };
@@ -2121,7 +2323,7 @@ async function provisionContainer(input) {
2121
2323
  }
2122
2324
  return aborted2 ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(reason);
2123
2325
  };
2124
- const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${firstLine4(result.stderr) === "" ? "" : `: ${firstLine4(result.stderr)}`}`);
2326
+ const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${firstLine5(result.stderr) === "" ? "" : `: ${firstLine5(result.stderr)}`}`);
2125
2327
  if (input.aborted()) return bail("", true);
2126
2328
  mkdirSync(buildDir2, { recursive: true });
2127
2329
  chmodSync(buildDir2, 493);
@@ -2206,6 +2408,7 @@ async function provisionContainer(input) {
2206
2408
  removeStagedContext: () => removeStagedContext(buildDir2)
2207
2409
  });
2208
2410
  if (!steps.ok) return bail(steps.reason, steps.aborted === true);
2411
+ state.startCommit = steps.startCommit;
2209
2412
  return { ok: true, workdir: CHECKOUT_DIR, state, environment };
2210
2413
  }
2211
2414
  function agentVersionOf(toolsJson) {
@@ -2341,6 +2544,18 @@ async function syncInContainer(input) {
2341
2544
  return { ok: false, reason: describeCallFailure(err) };
2342
2545
  }
2343
2546
  }
2547
+ async function copyTranscriptsFromContainer(runtime, state) {
2548
+ try {
2549
+ if (state.stopped) {
2550
+ const started = await runtime.host.start(state.container);
2551
+ if (started.status !== 0) return { ok: false, reason: `the build's container could not be started again (exit ${started.status})` };
2552
+ state.stopped = false;
2553
+ }
2554
+ } catch (err) {
2555
+ return { ok: false, reason: describeCallFailure(err) };
2556
+ }
2557
+ return copyTranscripts((argv) => runtime.host.exec({ container: state.container, user: state.agentUser ?? ADDED_USER, env: NO_ENV, argv }));
2558
+ }
2344
2559
  var HOOK_ERRORS_IN_CONTAINER = "/build/home/.outerlayer/spool/hook-errors.log";
2345
2560
  async function copyHookErrors(runtime, state, jobDir) {
2346
2561
  try {
@@ -2403,7 +2618,7 @@ async function startCheckContainer(input) {
2403
2618
  }
2404
2619
  return { ok: false, reason };
2405
2620
  };
2406
- const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${firstLine4(result.stderr) === "" ? "" : `: ${firstLine4(result.stderr)}`}`);
2621
+ const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${firstLine5(result.stderr) === "" ? "" : `: ${firstLine5(result.stderr)}`}`);
2407
2622
  mkdirSync(buildDir2, { recursive: true });
2408
2623
  chmodSync(buildDir2, 493);
2409
2624
  try {
@@ -2438,6 +2653,8 @@ async function startCheckContainer(input) {
2438
2653
  ok: true,
2439
2654
  container: {
2440
2655
  state,
2656
+ // The directory the container sees read-only at `JOB_MOUNT` is the build's directory on the host, so a folder written there is already in place.
2657
+ evalInput: { dir: join(buildDir2, EVAL_INPUT_NAME), deliver: async () => void 0 },
2441
2658
  exec: (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env, argv }, opts?.logPath === void 0 ? void 0 : { logPath: opts.logPath }),
2442
2659
  restart: async () => {
2443
2660
  await host.stop(name);
@@ -2448,4 +2665,4 @@ async function startCheckContainer(input) {
2448
2665
  };
2449
2666
  }
2450
2667
 
2451
- export { ADDED_USER, AgentUserError, AssetError, BuildTokens, GH_CONFIG_YML, MIN_ENGINE_MAJOR, classifyRefusal, cleanupContainer, containerCommandLine, containerSenderCommand, createBuildDisk, createContainerRuntime, createRunnerLog, deleteBuildDisk, describeCallFailure, ensureRootfs, ensureTunnel, formatClock, formatDuration, ghHostsYml, gitRemoteFor, isLiteralAddress, keepGhConfigCurrent, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, parseCpuList, prepareBranch, provisionContainer, refusalCode, relativeToRunner, removeStagedContext, resolveAgentUser, retrySend, runBuildSteps, senderSignalScript, setUpRunnerCgroup, shellQuote, shortClaim, signalInContainer, stageGovernedContext, startCheckContainer, startServicesFor, stopContainer, syncInContainer };
2668
+ export { ADDED_USER, AgentUserError, AssetError, BuildTokens, EVAL_INPUT_NAME, GH_CONFIG_YML, MIN_ENGINE_MAJOR, classifyRefusal, cleanupContainer, containerCommandLine, containerSenderCommand, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createRunnerLog, deleteBuildDisk, describeCallFailure, ensureRootfs, ensureTunnel, formatClock, formatDuration, ghHostsYml, gitRemoteFor, isLiteralAddress, keepGhConfigCurrent, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, parseCpuList, prepareBranch, provisionContainer, refusalCode, relativeToRunner, removeStagedContext, resolveAgentUser, retrySend, runBuildSteps, senderSignalScript, setUpRunnerCgroup, shellQuote, shortClaim, signalInContainer, stageGovernedContext, startCheckContainer, startServicesFor, stopContainer, syncInContainer, writeEvalInput };
@@ -59,6 +59,7 @@ function runRunnerInstall(args) {
59
59
  }
60
60
  return {
61
61
  version,
62
+ previous: installed,
62
63
  execStart: execStartLine(configPath, nodePath),
63
64
  launcher: {
64
65
  path: launcherPath(args.home),
@@ -89,5 +90,9 @@ function launcherSummary(launcher) {
89
90
  if (launcher.state === "foreign") return void 0;
90
91
  return `${launcher.state === "unchanged" ? "outerlayer command already at" : "wrote the outerlayer command at"} ${launcher.path}, which runs the CLI that ${launcher.follows} names`;
91
92
  }
93
+ function restartNote(result) {
94
+ if (result.previous === void 0 || result.previous === result.version) return void 0;
95
+ return `current moved from ${result.previous} to ${result.version}: a runner its service started takes no new work, waits for its running builds to finish, then restarts on ${result.version}. A runner started by hand keeps running until you restart it`;
96
+ }
92
97
 
93
- export { RunnerDowngradeError, RunnerInstallError, launcherSummary, runRunnerInstall };
98
+ export { RunnerDowngradeError, RunnerInstallError, launcherSummary, restartNote, runRunnerInstall };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { sanitizeTerminal } from './chunk-ZYHKJKSU.js';
4
- import { remoteLookupFailed } from './chunk-GAYWY4GI.js';
4
+ import { remoteLookupFailed } from './chunk-HN2JBGSI.js';
5
5
  import { DEFAULT_DASHBOARD } from './chunk-USO2DKBD.js';
6
- import { resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
6
+ import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
7
7
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
8
8
  import { writeRepoConnection, findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
9
9
  import { createInterface } from 'readline/promises';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-VXLJORHL.js';
4
- import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-7ZR5UPMB.js';
3
+ import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-JXH6LEEH.js';
4
+ import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-CMFCCIQN.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname, relative, sep } from 'path';
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
- import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-VXLJORHL.js';
4
+ import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-JXH6LEEH.js';
5
5
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
6
6
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
7
7
  import { join, dirname } from 'path';
@@ -21663,6 +21663,7 @@ function buildTokenPricingDictionary(models) {
21663
21663
  }
21664
21664
  var CACHE_CREATE_1H_INPUT_MULTIPLIER = 2;
21665
21665
  var isCount = (n) => typeof n === "number" && Number.isFinite(n) && n > 0;
21666
+ var tokensOf = (n) => isCount(n) ? n : 0;
21666
21667
  var hasTokens = (usage) => isCount(usage.in) || isCount(usage.out) || isCount(usage.cacheRead) || isCount(usage.cacheCreate5m) || isCount(usage.cacheCreate1h);
21667
21668
  function selectRates(price, context = {}) {
21668
21669
  var _a5, _b, _c;
@@ -21704,7 +21705,7 @@ function priceUsage(usage, price, context = {}) {
21704
21705
  if (isCount(usage.cacheCreate5m) && rates.cacheCreate === void 0) unpriced.push("cacheCreate5m");
21705
21706
  if (unpriced.length > 0) return { costUsd: null, unpricedClasses: unpriced };
21706
21707
  return {
21707
- costUsd: rates.in * usage.in + rates.out * usage.out + ((_a5 = rates.cacheRead) != null ? _a5 : 0) * usage.cacheRead + ((_b = rates.cacheCreate) != null ? _b : 0) * usage.cacheCreate5m + ((_c = rates.cacheCreate1h) != null ? _c : rates.in * CACHE_CREATE_1H_INPUT_MULTIPLIER) * usage.cacheCreate1h
21708
+ costUsd: rates.in * tokensOf(usage.in) + rates.out * tokensOf(usage.out) + ((_a5 = rates.cacheRead) != null ? _a5 : 0) * tokensOf(usage.cacheRead) + ((_b = rates.cacheCreate) != null ? _b : 0) * tokensOf(usage.cacheCreate5m) + ((_c = rates.cacheCreate1h) != null ? _c : rates.in * CACHE_CREATE_1H_INPUT_MULTIPLIER) * tokensOf(usage.cacheCreate1h)
21708
21709
  };
21709
21710
  }
21710
21711
  function priceBuckets(buckets, dict) {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-R7STSBLC.js';
3
+ import { EXEC_PORT } from './chunk-2E2MG3KW.js';
4
4
  import { createConnection } from 'net';
5
5
 
6
6
  createRequire(import.meta.url);
@@ -6,6 +6,18 @@ import { join, dirname } from 'path';
6
6
  import { createHash } from 'crypto';
7
7
 
8
8
  createRequire(import.meta.url);
9
+
10
+ // src/runner/update/installed-switch.ts
11
+ function decideInstalledSwitch(input) {
12
+ const to = input.current;
13
+ if (to === void 0 || to === input.own || !input.fromCurrent) return { kind: "none" };
14
+ if (!input.installed) return { kind: "missing", to };
15
+ if (!input.underService) return { kind: "foreground", to };
16
+ return { kind: "restart", to };
17
+ }
18
+ function startedByService(env, parentPid) {
19
+ return (env.INVOCATION_ID ?? "") !== "" && parentPid === 1;
20
+ }
9
21
  var REGISTRY_URL = "https://registry.npmjs.org";
10
22
  var PACKAGE_NAME = "@outerlayer/cli";
11
23
  var PACKAGE_PATH = "@outerlayer%2fcli";
@@ -101,4 +113,4 @@ async function auditSignatures(runNpm, dir) {
101
113
  return { ok: true };
102
114
  }
103
115
 
104
- export { auditSignatures, fetchProvenance, fetchTarballDigest, fetchVersionMeta, installVersion, npmSupportsProvenance, npmVersion, realRunNode, realRunNpm };
116
+ export { auditSignatures, decideInstalledSwitch, fetchProvenance, fetchTarballDigest, fetchVersionMeta, installVersion, npmSupportsProvenance, npmVersion, realRunNode, realRunNpm, startedByService };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-R7STSBLC.js';
4
- import { RELAY_PORT } from './chunk-OD2VTIHN.js';
3
+ import { EXEC_PORT } from './chunk-2E2MG3KW.js';
4
+ import { RELAY_PORT } from './chunk-2FWL7CE2.js';
5
5
  import { spawn, spawnSync } from 'child_process';
6
6
  import { writeFileSync, chmodSync, mkdirSync } from 'fs';
7
7
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { splitRawFile } from './chunk-7ZR5UPMB.js';
3
+ import { splitRawFile } from './chunk-CMFCCIQN.js';
4
4
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -628,7 +628,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
628
628
  recordHookErrorsSeen(home, hookErrorsBytes);
629
629
  if (contextPossiblyGoverned(sessionCwd, home)) {
630
630
  try {
631
- const { materializeContext: materialize } = await import('./context-materialize-4PMTDS6K.js');
631
+ const { materializeContext: materialize } = await import('./context-materialize-YR3JQCUF.js');
632
632
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
633
633
  const result = await materialize({ cwd: sessionCwd, sessionId, home });
634
634
  materializeMessage = result.message;
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { MIN_ENGINE_MAJOR } from './chunk-M4ERCYDB.js';
3
+ import { MIN_ENGINE_MAJOR } from './chunk-EQG7L6LM.js';
4
4
  import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CX22S5BA.js';
5
5
  import { spawnSync } from 'child_process';
6
6
  import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';