@outerlayer/cli 0.34.0-next.20261026214534 → 0.34.0-next.20261026230708

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 (54) hide show
  1. package/README.md +12 -4
  2. package/dist/{build-BBWAD5LR.js → build-M4UYZAFH.js} +3 -2
  3. package/dist/{build-disk-TGLM5XK7.js → build-disk-ZDVSSHO2.js} +3 -2
  4. package/dist/build-info.json +1 -1
  5. package/dist/{builder-FD53GTWL.js → builder-IORYS76D.js} +2 -1
  6. package/dist/{check-FOWN6M3C.js → check-V66LZDNK.js} +15 -14
  7. package/dist/{chunk-T2HH7IHT.js → chunk-63A6NUEZ.js} +1 -1
  8. package/dist/{chunk-3HJMY3H5.js → chunk-6NXBXWOP.js} +1 -1
  9. package/dist/{chunk-3PUOHONX.js → chunk-DFBY6LX3.js} +6 -5
  10. package/dist/{chunk-RNMCFAYH.js → chunk-F5H3LVHR.js} +2 -2
  11. package/dist/chunk-HDLON3RJ.js +274 -0
  12. package/dist/{chunk-FVF2LMVG.js → chunk-IZVDQXTC.js} +9 -9
  13. package/dist/{chunk-LY62UHRR.js → chunk-JZLMFYFM.js} +1 -1
  14. package/dist/{chunk-XYLHSCLR.js → chunk-KOZ6IBEI.js} +8 -279
  15. package/dist/{chunk-K3ACC2CV.js → chunk-MIRCFK4X.js} +2 -33
  16. package/dist/{chunk-5ZBVKRDK.js → chunk-PN7RMFPP.js} +2 -2
  17. package/dist/{chunk-BQQPDBSF.js → chunk-Q3L5AC75.js} +2 -2
  18. package/dist/{chunk-2GDKM2O4.js → chunk-T6HSNQAT.js} +4 -4
  19. package/dist/{chunk-KR2TIRNQ.js → chunk-T7HUNNJ2.js} +30 -16
  20. package/dist/{chunk-JKLSQOYO.js → chunk-TGBST2QL.js} +11 -7
  21. package/dist/{chunk-3NCWHEGM.js → chunk-TLIZ7FY4.js} +2 -2
  22. package/dist/{chunk-XHZBLIB2.js → chunk-XDJ376OP.js} +7 -1
  23. package/dist/{chunk-ZADRW2V2.js → chunk-XLJXO4QC.js} +4 -4
  24. package/dist/{cli-3RDQSLYI.js → cli-HQWQEHXJ.js} +79 -44
  25. package/dist/{command-C5YKBTK4.js → command-TONUMZ2A.js} +8 -7
  26. package/dist/{config-EBT5VYPX.js → config-4K6OG2SZ.js} +4 -3
  27. package/dist/{container-start-RLX2PL3C.js → container-start-R74IO7CI.js} +12 -11
  28. package/dist/demo-record-cmd-7HJ5C7KM.js +208 -0
  29. package/dist/{demo-voice-cmd-DF6C7EST.js → demo-voice-cmd-MBK3BGHZ.js} +1 -2
  30. package/dist/{docker-CP656XNO.js → docker-XWQM4F7B.js} +2 -1
  31. package/dist/{doctor-EQIAHHZD.js → doctor-SF4GAWAO.js} +9 -8
  32. package/dist/{emit-demo-cmd-YKTL6XWP.js → emit-demo-cmd-6VTA5BSJ.js} +1 -2
  33. package/dist/{find-unit-O6WL6UIW.js → find-unit-I4GWKY4T.js} +6 -5
  34. package/dist/{host-checks-V25YUP4Q.js → host-checks-FKLQST3J.js} +10 -9
  35. package/dist/index.js +1 -1
  36. package/dist/{init-KO3FT2XP.js → init-3MO5WCU3.js} +8 -7
  37. package/dist/{init-YYZ7B4ZD.js → init-TDLUTI6F.js} +8 -7
  38. package/dist/{init-cmd-D3BDS7KY.js → init-cmd-MQ5R35O2.js} +1 -1
  39. package/dist/{loop-UVONXWXB.js → loop-NNNDBFAS.js} +14 -13
  40. package/dist/{machine-2BI76JZO.js → machine-GCW2GGI2.js} +8 -7
  41. package/dist/recorder.cjs +916 -0
  42. package/dist/{runner-env-QN4BLTVZ.js → runner-env-LVVLUHY2.js} +6 -5
  43. package/dist/{runner-identity-53I4UTVY.js → runner-identity-73F2IWBT.js} +2 -1
  44. package/dist/{runner-key-JKXJWGGY.js → runner-key-ASPZ7TQH.js} +8 -7
  45. package/dist/{status-YCQHAY45.js → status-35Z3TW42.js} +10 -9
  46. package/dist/{update-steps-MC3IUHW7.js → update-steps-ZTNIK7LA.js} +11 -10
  47. package/dist/{work-claim-cmd-O54L5DSL.js → work-claim-cmd-QPYCZUMI.js} +4 -3
  48. package/dist/{work-proofs-cmd-LIXV252G.js → work-proofs-cmd-56EY7O45.js} +1 -1
  49. package/dist/{work-proofs-record-MCSA56F5.js → work-proofs-record-SPGI47OS.js} +2 -3
  50. package/package.json +5 -4
  51. package/skill-pack/maintained/outerlayer-amend/SKILL.md +2 -2
  52. package/skill-pack/maintained/outerlayer-build/references/evidence.md +12 -11
  53. package/skill-pack/maintained/outerlayer-evidence/SKILL.md +6 -6
  54. package/skill-pack/maintained/outerlayer-evidence/references/demo.md +12 -11
@@ -1,18 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { BUILDKIT_IMAGE } from './chunk-4UPET3R7.js';
4
+ import { resolveDevcontainerCli, devcontainerBuildInvocation, RecipeError } from './chunk-HDLON3RJ.js';
4
5
  import { ensureHostKey } from './chunk-L5VHGRQE.js';
5
6
  import { compareVersions } from './chunk-OOD5NDQA.js';
6
7
  import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, runnerDir, jobsDir } from './chunk-GJ4KBHBD.js';
7
8
  import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-SDAEXUIX.js';
8
9
  import { JOIN_DIR, RELAY_ID, JOIN_SOCKET, TARGET_GATEWAY, TARGET_CLAUDE, destinationTarget, RELAY_USER } from './chunk-MESOOLF4.js';
9
10
  import { createHash } from 'crypto';
10
- import { existsSync, readdirSync, readFileSync, lstatSync, realpathSync, writeFileSync, mkdirSync, createWriteStream, rmSync, chmodSync, renameSync } from 'fs';
11
- import { join, resolve, relative, dirname, sep, basename } from 'path';
11
+ import { mkdirSync, createWriteStream, rmSync, existsSync, readFileSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
12
+ import { dirname, join, resolve } from 'path';
12
13
  import { StringDecoder } from 'string_decoder';
13
14
  import { spawn } from 'child_process';
14
- import { createRequire as createRequire$1 } from 'module';
15
- import { fileURLToPath } from 'url';
16
15
 
17
16
  createRequire(import.meta.url);
18
17
 
@@ -47,276 +46,6 @@ function cut(line) {
47
46
  const last = head.charCodeAt(head.length - 1);
48
47
  return last >= 55296 && last <= 56319 ? head.slice(0, -1) : head;
49
48
  }
50
-
51
- // src/runner/image/properties.ts
52
- var LIFECYCLE = ["onCreateCommand", "updateContentCommand", "postCreateCommand", "postStartCommand"];
53
- var HONOURED = ["image", "build", "features", "containerEnv", "remoteUser", ...LIFECYCLE];
54
- var IGNORED_BUILD_KEYS = ["options"];
55
- var HOST_REFERENCE = /\$\{(?:localEnv|env)[:}]/;
56
- var DROP = /* @__PURE__ */ Symbol("drop");
57
- function isHonoured(property) {
58
- return HONOURED.includes(property);
59
- }
60
- function isObject(value) {
61
- return typeof value === "object" && value !== null && !Array.isArray(value);
62
- }
63
- function featureName(id) {
64
- const slash = id.lastIndexOf("/");
65
- const cut2 = id.slice(slash + 1).search(/[:@]/);
66
- return cut2 === -1 ? id : id.slice(0, slash + 1 + cut2);
67
- }
68
- var DOCKER_FEATURE = "ghcr.io/devcontainers/features/docker-in-docker";
69
- function asksForDocker(recipe, metadata) {
70
- const isDocker = (id) => featureName(id) === DOCKER_FEATURE;
71
- if (isObject(recipe.features) && Object.keys(recipe.features).some(isDocker)) return true;
72
- return metadata.some((entry) => typeof entry.id === "string" && isDocker(entry.id));
73
- }
74
- function sameValue(a, b) {
75
- return JSON.stringify(a) === JSON.stringify(b);
76
- }
77
- function isFilesOwnEntry(entry, recipe) {
78
- if (typeof entry.id === "string") return false;
79
- const keys = Object.keys(entry);
80
- return keys.length > 0 && keys.every((key) => key in recipe && sameValue(entry[key], recipe[key]));
81
- }
82
- function withoutHostReferences(value, path, dropped) {
83
- if (typeof value === "string") {
84
- if (!HOST_REFERENCE.test(value)) return value;
85
- dropped.push(path);
86
- return DROP;
87
- }
88
- if (Array.isArray(value)) {
89
- if (!HOST_REFERENCE.test(JSON.stringify(value))) return value;
90
- dropped.push(path);
91
- return DROP;
92
- }
93
- if (isObject(value)) {
94
- const kept = {};
95
- for (const [key, item] of Object.entries(value)) {
96
- if (HOST_REFERENCE.test(key)) {
97
- dropped.push(`${path}.${key}`);
98
- continue;
99
- }
100
- const clean = withoutHostReferences(item, `${path}.${key}`, dropped);
101
- if (clean !== DROP) kept[key] = clean;
102
- }
103
- return kept;
104
- }
105
- return value;
106
- }
107
- function honouredWithoutHostReferences(entry) {
108
- const kept = {};
109
- const dropped = [];
110
- for (const property of HONOURED) {
111
- if (!(property in entry)) continue;
112
- const value = entry[property];
113
- const clean = withoutHostReferences(
114
- property === "build" && isObject(value) ? withoutIgnoredBuildKeys(value) : value,
115
- property,
116
- dropped
117
- );
118
- if (clean !== DROP) kept[property] = clean;
119
- }
120
- return { kept, dropped };
121
- }
122
- function withoutIgnoredBuildKeys(build) {
123
- return Object.fromEntries(Object.entries(build).filter(([key]) => !IGNORED_BUILD_KEYS.includes(key)));
124
- }
125
- function ignoredIn(entry, source) {
126
- const found = [];
127
- for (const property of Object.keys(entry)) {
128
- if (property === "id" || property.startsWith("$") || isHonoured(property)) continue;
129
- found.push({ property, source });
130
- }
131
- if (isObject(entry.build)) {
132
- for (const key of IGNORED_BUILD_KEYS) {
133
- if (key in entry.build) found.push({ property: `build.${key}`, source });
134
- }
135
- }
136
- for (const property of honouredWithoutHostReferences(entry).dropped) found.push({ property, source });
137
- return found;
138
- }
139
- function emptyApply() {
140
- return { containerEnv: {}, lifecycle: { onCreateCommand: [], updateContentCommand: [], postCreateCommand: [], postStartCommand: [] } };
141
- }
142
- function applyEntry(apply, raw, source) {
143
- const entry = honouredWithoutHostReferences(raw).kept;
144
- if (typeof entry.remoteUser === "string") apply.remoteUser = entry.remoteUser;
145
- if (isObject(entry.containerEnv)) {
146
- for (const [key, value] of Object.entries(entry.containerEnv)) {
147
- if (typeof value === "string") apply.containerEnv[key] = value;
148
- }
149
- }
150
- for (const name of LIFECYCLE) {
151
- if (entry[name] !== void 0) apply.lifecycle[name].push({ source, command: entry[name] });
152
- }
153
- }
154
- function classifyProperties(recipe, metadata) {
155
- const ignored = ignoredIn(recipe, "file");
156
- const apply = emptyApply();
157
- let fileApplied = false;
158
- const sanitized = sanitizeRecipe(recipe);
159
- for (const entry of metadata) {
160
- if (isFilesOwnEntry(entry, sanitized)) {
161
- applyEntry(apply, entry, "file");
162
- fileApplied = true;
163
- continue;
164
- }
165
- const source = typeof entry.id === "string" ? `feature ${featureName(entry.id)}` : "image label";
166
- ignored.push(...ignoredIn(entry, source));
167
- applyEntry(apply, entry, source);
168
- }
169
- if (!fileApplied) applyEntry(apply, recipe, "file");
170
- return { docker: asksForDocker(recipe, metadata), honoured: HONOURED.filter((property) => property in recipe), ignored, apply };
171
- }
172
- function sanitizeRecipe(recipe) {
173
- return honouredWithoutHostReferences(recipe).kept;
174
- }
175
-
176
- // src/runner/image/recipe.ts
177
- var RecipeError = class extends Error {
178
- constructor(code, message, logPath) {
179
- super(message);
180
- this.code = code;
181
- this.logPath = logPath;
182
- }
183
- };
184
- var DIR_RECIPE = ".devcontainer/devcontainer.json";
185
- var ROOT_RECIPE = ".devcontainer.json";
186
- function locateRecipe(checkoutDir) {
187
- if (existsSync(join(checkoutDir, DIR_RECIPE))) return { kind: "file", path: DIR_RECIPE };
188
- if (existsSync(join(checkoutDir, ROOT_RECIPE))) return { kind: "file", path: ROOT_RECIPE };
189
- const named = namedConfigurations(checkoutDir);
190
- if (named.length > 0) {
191
- throw new RecipeError(
192
- "recipe_ambiguous",
193
- `the repository has only named devcontainer configurations (${named.join(", ")}); add ${DIR_RECIPE} so the runner knows which to build`
194
- );
195
- }
196
- return { kind: "default" };
197
- }
198
- function namedConfigurations(checkoutDir) {
199
- const dir = join(checkoutDir, ".devcontainer");
200
- if (!existsSync(dir)) return [];
201
- return readdirSync(dir).sort().map((entry) => `.devcontainer/${entry}/devcontainer.json`).filter((path) => existsSync(join(checkoutDir, path)));
202
- }
203
- var COMMENTS = /("(?:[^"\\]|\\.)*")|\/\/[^\n]*|\/\*[\s\S]*?(?:\*\/|$)/g;
204
- var TRAILING_COMMAS = /("(?:[^"\\]|\\.)*")|,(\s*[}\]])/g;
205
- function parseJsonc(text) {
206
- const withoutComments = text.replace(COMMENTS, (_match, str) => str ?? "");
207
- return JSON.parse(withoutComments.replace(TRAILING_COMMAS, (_match, str, close) => str ?? close ?? ""));
208
- }
209
- function readRecipe(checkoutDir, location) {
210
- if (location.kind === "default") return {};
211
- const parsed = parseJsonc(readFileSync(join(checkoutDir, location.path), "utf8"));
212
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
213
- throw new Error(`${location.path} is not a JSON object`);
214
- }
215
- return parsed;
216
- }
217
- function within(dir, path) {
218
- const rel = relative(dir, path);
219
- return rel !== ".." && !rel.startsWith(`..${sep}`);
220
- }
221
- function realish(path) {
222
- let existing = path;
223
- let rest = "";
224
- while (!existsSync(existing)) {
225
- rest = join(basename(existing), rest);
226
- existing = dirname(existing);
227
- }
228
- return join(realpathSync(existing), rest);
229
- }
230
- function assertBuildable(checkoutDir, location, recipe) {
231
- if (location.kind === "default") return;
232
- const devcontainerDir = join(checkoutDir, ".devcontainer");
233
- if (existsSync(devcontainerDir) && lstatSync(devcontainerDir).isSymbolicLink()) {
234
- throw new RecipeError(
235
- "recipe_context_outside",
236
- ".devcontainer is a symbolic link, so the build could read files outside the repository; commit a real directory"
237
- );
238
- }
239
- if (recipe.dockerComposeFile !== void 0) {
240
- throw new RecipeError(
241
- "recipe_needs_docker",
242
- "the recipe uses dockerComposeFile; its services need Docker, which a container build does not have"
243
- );
244
- }
245
- const build = recipe.build;
246
- if (typeof build !== "object" || build === null) return;
247
- const { dockerfile, context } = build;
248
- const base = resolve(checkoutDir, location.path, "..");
249
- const allowed = join(realpathSync(checkoutDir), ".devcontainer");
250
- const contextPath = resolve(base, typeof context === "string" ? context : ".");
251
- const paths = [contextPath];
252
- if (typeof dockerfile === "string") paths.push(resolve(base, dockerfile));
253
- for (const path of paths) {
254
- if (!within(devcontainerDir, path) || !within(allowed, realish(path))) {
255
- throw new RecipeError(
256
- "recipe_context_outside",
257
- `the recipe's build reads ${relative(checkoutDir, path) || "."}, outside .devcontainer/; move the build files into .devcontainer/`
258
- );
259
- }
260
- }
261
- }
262
- function writeSanitizedRecipe(checkoutDir, location, recipe) {
263
- if (location.kind === "default") throw new Error("the default image has no recipe to sanitize");
264
- const path = location.path === ROOT_RECIPE ? join(checkoutDir, ".outerlayer-recipe.json") : join(checkoutDir, ".devcontainer", SANITIZED_NAME);
265
- writeFileSync(path, `${JSON.stringify(sanitizeRecipe(recipe), null, 2)}
266
- `);
267
- return path;
268
- }
269
- var SANITIZED_NAME = "outerlayer-recipe.json";
270
-
271
- // src/runner/image/devcontainer-cli.ts
272
- var PACKAGE = "@devcontainers/cli";
273
- function buildRootFromDist(moduleDir = dirname(fileURLToPath(import.meta.url))) {
274
- try {
275
- const info = JSON.parse(readFileSync(join(moduleDir, "build-info.json"), "utf8"));
276
- return typeof info.root === "string" ? info.root : void 0;
277
- } catch {
278
- return void 0;
279
- }
280
- }
281
- function resolveDevcontainerCli(opts = {}) {
282
- const resolve3 = opts.resolve ?? createRequire$1(import.meta.url).resolve;
283
- try {
284
- const bin = join(dirname(resolve3(`${PACKAGE}/package.json`)), "devcontainer.js");
285
- if (existsSync(bin)) return { command: process.execPath, args: [bin] };
286
- } catch {
287
- }
288
- const buildRoot = opts.buildRoot ?? buildRootFromDist();
289
- const fallback = buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", PACKAGE);
290
- if (fallback !== void 0 && existsSync(join(fallback, "devcontainer.js"))) {
291
- return { command: process.execPath, args: [join(fallback, "devcontainer.js")] };
292
- }
293
- throw new RecipeError(
294
- "devcontainer_cli_missing",
295
- `the devcontainer CLI is not installed: looked beside this package and in ${fallback ?? "the checkout this build came from (unknown)"}. Run yarn install in that checkout.`
296
- );
297
- }
298
- function devcontainerBuildInvocation(cli, req) {
299
- return {
300
- command: cli.command,
301
- args: [
302
- ...cli.args,
303
- "build",
304
- "--workspace-folder",
305
- req.workspace,
306
- "--config",
307
- req.config,
308
- "--image-name",
309
- req.imageName,
310
- ...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
311
- "--log-format",
312
- "text",
313
- // Written as an OCI layout instead of loaded into Docker: the runner's builder cannot read Docker's image store, so the next layer starts FROM the layout.
314
- ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
315
- ]
316
- };
317
- }
318
-
319
- // src/runner/image/docker.ts
320
49
  var CHILD_ENVIRONMENT_NAMES = [
321
50
  "PATH",
322
51
  "HOME",
@@ -354,7 +83,7 @@ function childEnvironment(base) {
354
83
  }
355
84
  return env;
356
85
  }
357
- var spawnRun = (command, args, opts = {}) => new Promise((resolve3) => {
86
+ var spawnRun = (command, args, opts = {}) => new Promise((resolve2) => {
358
87
  let log;
359
88
  if (opts.logPath !== void 0) {
360
89
  mkdirSync(dirname(opts.logPath), { recursive: true });
@@ -370,11 +99,11 @@ var spawnRun = (command, args, opts = {}) => new Promise((resolve3) => {
370
99
  settled = true;
371
100
  const result = { status, stdout: stdout + stdoutDecoder.end(), stderr: stderr + stderrDecoder.end() + extra };
372
101
  if (log === void 0) {
373
- resolve3(result);
102
+ resolve2(result);
374
103
  return;
375
104
  }
376
105
  if (extra) log.write(extra);
377
- log.end(() => resolve3(result));
106
+ log.end(() => resolve2(result));
378
107
  };
379
108
  let timer;
380
109
  const child = spawn(command, args, {
@@ -921,7 +650,7 @@ function ensureBuilder(rawRun, spec, options = {}) {
921
650
  const result = serialized(async () => {
922
651
  const state = await buildxState(run);
923
652
  if (state !== "usable") return { ok: false, problem: state.problem };
924
- const sleep = options.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
653
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
925
654
  const inspected = await run("docker", ["buildx", "inspect", spec.name]);
926
655
  let create = inspected.status !== 0;
927
656
  if (!create) {
@@ -987,4 +716,4 @@ function ensureBuilder(rawRun, spec, options = {}) {
987
716
  );
988
717
  }
989
718
 
990
- export { BUILD_LABEL, COMMAND_DIR, DOCKER_FEATURE, HASH_ARGV, JUDGE_DIR, JUDGE_ITEMS, JUDGE_MAX_TURNS, JUDGE_PROGRAM, JUDGE_REPORT, MAX_ITEMS_BYTES, MAX_REPORT_BYTES, MIN_BUILDX_VERSION, RUNNER_LABEL, RecipeError, SANITIZED_NAME, assertBuildable, builderName, builderNameFor, builderSpec, buildxState, childEnvironment, classifyProperties, containerExecArgs, containerRunArgs, createDockerHost, dockerIdentity, ensureBuilder, ensureFailureCount, ensureRunnerIdentity, exceedsDisk, identityDockerFor, isOutOfMemory, judgeCommand, locateRecipe, parseProgramHash, parseSize, pathLabelValue, prepareRunArgs, proxyEnvironment, readDu, readJobFile, readJobFileChecked, readRecipe, readRunnerIdentity, resolveDevcontainerCli, runnerLabelValue, spawnRun, trackImageBuild, withAnswerProtocol, writeJobFile, writeSanitizedRecipe };
719
+ export { BUILD_LABEL, COMMAND_DIR, HASH_ARGV, JUDGE_DIR, JUDGE_ITEMS, JUDGE_MAX_TURNS, JUDGE_PROGRAM, JUDGE_REPORT, MAX_ITEMS_BYTES, MAX_REPORT_BYTES, MIN_BUILDX_VERSION, RUNNER_LABEL, builderName, builderNameFor, builderSpec, buildxState, childEnvironment, containerExecArgs, containerRunArgs, createDockerHost, dockerIdentity, ensureBuilder, ensureFailureCount, ensureRunnerIdentity, exceedsDisk, identityDockerFor, isOutOfMemory, judgeCommand, parseProgramHash, parseSize, pathLabelValue, prepareRunArgs, proxyEnvironment, readDu, readJobFile, readJobFileChecked, readRunnerIdentity, runnerLabelValue, spawnRun, trackImageBuild, withAnswerProtocol, writeJobFile };
@@ -3,20 +3,18 @@ import { createRequire } from 'node:module';
3
3
  import { readNewestDemo } from './chunk-ER6KQCVJ.js';
4
4
  import { runEmitArtifact } from './chunk-QWXBWOVV.js';
5
5
  import { VoiceDownloadError, downloadPinned, sha256OfFile } from './chunk-2PGI6RDE.js';
6
- import { compareVersions } from './chunk-TQMI335S.js';
7
6
  import { VOICE_PACK_FILES, VOICE_PACK_VERSION } from './chunk-4UPET3R7.js';
8
7
  import { detectActiveSession } from './chunk-IP7BIBXJ.js';
9
8
  import { autoConnect } from './chunk-OKGHWCSK.js';
10
9
  import { C } from './chunk-ANPNT6PM.js';
11
10
  import { defaultFetch, resolveGatewayCredentials } from './chunk-7QAJQDHS.js';
12
11
  import { resolveRepoIdentity } from './chunk-OOD5NDQA.js';
13
- import { resolvePackageVersion } from './chunk-RA3O54FC.js';
14
12
  import { launchedItemForSession } from './chunk-T2Q7ISPE.js';
15
13
  import { ARTIFACT_MAX_BYTES, ARTIFACT_MAX_CAPTION_LENGTH, DEMO_RECORD_MEDIA_TYPE, ARTIFACT_MAX_REPLACES_TARGETS, DEMO_MANIFEST_LATEST_VERSION, DemoManifestSchema, ARTIFACT_KINDS } from './chunk-DINRXUQA.js';
16
14
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
17
15
  import { __commonJS, __require, __toESM } from './chunk-Z5GEFMRW.js';
18
16
  import { createHash } from 'crypto';
19
- import { mkdtempSync, writeFileSync, statSync, readFileSync, rmSync, mkdirSync, existsSync, copyFileSync, realpathSync, accessSync, constants, createReadStream, createWriteStream } from 'fs';
17
+ import { mkdtempSync, writeFileSync, statSync, readFileSync, rmSync, mkdirSync, existsSync, copyFileSync, accessSync, constants, realpathSync, createReadStream, createWriteStream } from 'fs';
20
18
  import { tmpdir } from 'os';
21
19
  import { resolve, dirname, join, relative, sep, isAbsolute, delimiter, normalize } from 'path';
22
20
  import { execFileSync, spawn } from 'child_process';
@@ -2646,33 +2644,6 @@ function recordedFrame(chapter, stored) {
2646
2644
  if (frame === void 0 || stored.screenshot === void 0) return {};
2647
2645
  return { screenshot: { artifactId: stored.screenshot.artifactId, check: frame.check, sha256: frame.sha256, fullPage: frame.fullPage, masked: frame.masked } };
2648
2646
  }
2649
- var RECORDER_PACKAGE = "@outerlayer/playwright";
2650
- function installedRecorderVersion(dir) {
2651
- for (let current = dir; ; current = dirname(current)) {
2652
- let real;
2653
- try {
2654
- real = realpathSync(join(current, "node_modules", "@outerlayer", "playwright"));
2655
- } catch {
2656
- real = void 0;
2657
- }
2658
- if (real !== void 0) {
2659
- if (!real.split(sep).includes("node_modules")) return void 0;
2660
- try {
2661
- const version = JSON.parse(readFileSync(join(real, "package.json"), "utf8")).version;
2662
- return typeof version === "string" ? version : void 0;
2663
- } catch {
2664
- return void 0;
2665
- }
2666
- }
2667
- if (dirname(current) === current) return void 0;
2668
- }
2669
- }
2670
- function recorderVersionNote(recorder, cli) {
2671
- if (recorder === void 0) return void 0;
2672
- const order = compareVersions(recorder, cli);
2673
- if (order === void 0 || order === 0) return void 0;
2674
- return order < 0 ? `this demo was recorded with ${RECORDER_PACKAGE} ${recorder}, and this CLI is ${cli}: install ${RECORDER_PACKAGE}@${cli}, which releases with this CLI` : `this demo was recorded with ${RECORDER_PACKAGE} ${recorder}, newer than this CLI (${cli}): update the CLI to ${recorder}`;
2675
- }
2676
2647
 
2677
2648
  // src/demo/timeline.ts
2678
2649
  var JOIN_GAP = 0.25;
@@ -3064,7 +3035,7 @@ function parseManifest(path, options) {
3064
3035
  const version = typeof raw === "object" && raw !== null ? raw.schemaVersion : void 0;
3065
3036
  if (typeof version === "number" && version > DEMO_MANIFEST_LATEST_VERSION) {
3066
3037
  throw new EmitDemoError(
3067
- `the manifest "${path}" is version ${version}, and this CLI reads versions 1 to ${DEMO_MANIFEST_LATEST_VERSION}: update the CLI to the version of the recorder that wrote it`
3038
+ `the manifest "${path}" is version ${version}, and this CLI reads versions 1 to ${DEMO_MANIFEST_LATEST_VERSION}: a newer CLI recorded it, so update this one`
3068
3039
  );
3069
3040
  }
3070
3041
  const parsed = DemoManifestSchema.safeParse(raw);
@@ -3092,8 +3063,6 @@ async function runEmitDemo(opts) {
3092
3063
  };
3093
3064
  const manifestPath = resolve(cwd, opts.manifest);
3094
3065
  const { manifest, videoPath, text: manifestText } = parseManifest(manifestPath, { needVideo: true });
3095
- const recorderNote = recorderVersionNote(installedRecorderVersion(dirname(manifestPath)), opts.cliVersion ?? resolvePackageVersion());
3096
- if (recorderNote !== void 0) say(`${C.yellow}!${C.reset} ${recorderNote}`);
3097
3066
  const comparisons = compareRuns({ first: { manifest, dir: dirname(manifestPath) }, firstPath: manifestPath, secondPath: opts.compare === void 0 ? void 0 : resolve(cwd, opts.compare) });
3098
3067
  const narrated = opts.noNarration !== true && manifest.chapters.some((chapter) => chapter.narration.trim() !== "" || (beatsOf(chapter) ?? []).some((beat) => beat.narration.trim() !== ""));
3099
3068
  for (const program of narrated ? ["ffmpeg", "ffprobe", "espeak-ng"] : ["ffmpeg", "ffprobe"]) {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { stripTerminalControls } from './chunk-JKLSQOYO.js';
3
+ import { stripTerminalControls } from './chunk-TGBST2QL.js';
4
4
  import { tagToPull, imageTag, pullInstruction, readUpdateStatus, runnerImageVersion } from './chunk-SDELQEG4.js';
5
5
  import { readFileSync } from 'fs';
6
6
 
@@ -55,7 +55,7 @@ function envNamesOf(row, imageEnv) {
55
55
  return [...new Set(names)].sort();
56
56
  }
57
57
  async function readOwnContainer(deps = {}) {
58
- const run = deps.run ?? (await import('./docker-CP656XNO.js')).spawnRun;
58
+ const run = deps.run ?? (await import('./docker-XWQM4F7B.js')).spawnRun;
59
59
  const ids = candidateIds(deps.env ?? process.env, deps.readFile ?? ((path) => readFileSync(path, "utf8")));
60
60
  if (ids.length === 0) return { ok: false, reason: "the runner cannot tell which container it runs in: HOSTNAME is empty and /proc/self/mountinfo names none" };
61
61
  let problem = "";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { DEFAULT_CACHE_DISK, DEFAULT_BUILD_DISK } from './chunk-3HJMY3H5.js';
4
- import { parseSize } from './chunk-XYLHSCLR.js';
3
+ import { DEFAULT_CACHE_DISK, DEFAULT_BUILD_DISK } from './chunk-6NXBXWOP.js';
4
+ import { parseSize } from './chunk-KOZ6IBEI.js';
5
5
  import { builderDiskPinned } from './chunk-4UPET3R7.js';
6
6
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
7
7
  import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-SDAEXUIX.js';
@@ -1195,8 +1195,8 @@ function doctorExitCode(checks) {
1195
1195
 
1196
1196
  // src/doctor-report.ts
1197
1197
  async function gatherDoctorChecks() {
1198
- const { DEFAULT_BUILD_DISK, DEFAULT_CACHE_DISK } = await import('./build-disk-TGLM5XK7.js');
1199
- const { defaultRunnerConfigPath, hasRunnerBlock, loadRunnerConfig, runnerVmOf } = await import('./config-EBT5VYPX.js');
1198
+ const { DEFAULT_BUILD_DISK, DEFAULT_CACHE_DISK } = await import('./build-disk-ZDVSSHO2.js');
1199
+ const { defaultRunnerConfigPath, hasRunnerBlock, loadRunnerConfig, runnerVmOf } = await import('./config-4K6OG2SZ.js');
1200
1200
  const configPath = defaultRunnerConfigPath();
1201
1201
  const runnerHost = hasRunnerBlock(configPath);
1202
1202
  const hooks = (() => {
@@ -1217,7 +1217,7 @@ async function gatherDoctorChecks() {
1217
1217
  const { runnerVmCheck } = await import('./doctor-53F2PYY7.js');
1218
1218
  checks.push(runnerVmCheck(configPath, { lima: realLima(), home: homeFromEnv(), instance: runnerVm.instance }));
1219
1219
  } else if (hasRunnerBlock(configPath)) {
1220
- const { runnerHostChecks } = await import('./doctor-EQIAHHZD.js');
1220
+ const { runnerHostChecks } = await import('./doctor-SF4GAWAO.js');
1221
1221
  const gateway = (() => {
1222
1222
  try {
1223
1223
  const { url, apiKey, appId } = loadRunnerConfig(configPath);
@@ -1244,7 +1244,7 @@ async function gatherDoctorChecks() {
1244
1244
  const service = await (async () => {
1245
1245
  const { existsSync: existsSync3 } = await import('fs');
1246
1246
  if (process.platform !== "linux" || !existsSync3("/run/systemd/system")) return void 0;
1247
- const { inspectRunnerService } = await import('./find-unit-O6WL6UIW.js');
1247
+ const { inspectRunnerService } = await import('./find-unit-I4GWKY4T.js');
1248
1248
  return inspectRunnerService(configPath);
1249
1249
  })();
1250
1250
  checks.push(...await runnerHostChecks({ configPath, hooks, gateway, repos, runner, service }));
@@ -159,13 +159,22 @@ function checkoutPlaces(cwd) {
159
159
  if (dirname(dir) === dir) return void 0;
160
160
  }
161
161
  }
162
- async function judgeCheckName(cwd) {
162
+ function governingDir(cwd) {
163
163
  const places = checkoutPlaces(cwd);
164
- if (places === void 0) return {};
165
- const delivered = readDeliveryRecord(places.common);
166
- const dir = delivered?.dir ?? places.root;
164
+ if (places === void 0) return void 0;
165
+ return readDeliveryRecord(places.common)?.dir ?? places.root;
166
+ }
167
+ async function testProofMode(cwd) {
168
+ const dir = governingDir(cwd);
169
+ if (dir === void 0) return "any";
170
+ const { testProofIn } = await import('./host-checks-FKLQST3J.js');
171
+ return testProofIn(dir);
172
+ }
173
+ async function judgeCheckName(cwd) {
174
+ const dir = governingDir(cwd);
175
+ if (dir === void 0) return {};
167
176
  if (!existsSync(dir)) return { note: `the governed context at ${dir} is not readable` };
168
- const { checksIn, isJudgeCheck } = await import('./host-checks-V25YUP4Q.js');
177
+ const { checksIn, isJudgeCheck } = await import('./host-checks-FKLQST3J.js');
169
178
  const quiet = { line: () => void 0, error: () => void 0 };
170
179
  const check = checksIn(dir, quiet, "").checks.find((c) => isJudgeCheck(c) && c.judge.subjects === "criteria");
171
180
  return check === void 0 ? {} : { name: check.name };
@@ -211,19 +220,19 @@ function otherPullRequestHeads(pullRequests, ownPr, checkoutRepository) {
211
220
  }
212
221
  return heads;
213
222
  }
214
- function classifyProofs(data, checkoutHead) {
223
+ function classifyProofs(data, checkoutHead, listing = {}) {
215
224
  const heads = /* @__PURE__ */ new Set();
216
225
  if (checkoutHead !== void 0 && checkoutHead !== "") heads.add(checkoutHead.toLowerCase());
217
226
  data.pullRequests?.forEach((pr) => {
218
227
  const head = liveHead(pr);
219
228
  if (head !== void 0) heads.add(head);
220
229
  });
221
- return classifyProofsAt(data, heads);
230
+ return classifyProofsAt(data, heads, listing);
222
231
  }
223
- function classifyProofsAt(data, heads) {
232
+ function classifyProofsAt(data, heads, listing = {}) {
224
233
  const entries = [];
225
234
  for (const criterion of data.criteria?.items ?? []) {
226
- if (criterion.proof === null || criterion.proof === "test") continue;
235
+ if (criterion.proof === null || criterion.proof === "test" && listing.tests !== true) continue;
227
236
  const newest = criterion.newestProof;
228
237
  if (newest === null || newest === void 0) {
229
238
  entries.push({ id: criterion.id, proof: criterion.proof, state: "missing", commit: null });
@@ -244,11 +253,14 @@ function renderEntry(e) {
244
253
  if (e.state === "failed") {
245
254
  return `${id} none failed ${sanitizeTerminal(e.commit)} The judge failed it: ${sanitizeTerminal(e.reason)} No test that cites it has changed since. Change a test that cites ${id}.`;
246
255
  }
247
- return `${id} ${sanitizeTerminal(e.proof)} ${STATE_LABEL[e.state]} ${sanitizeTerminal(e.commit ?? "no commit")}`;
256
+ const row = `${id} ${sanitizeTerminal(e.proof)} ${STATE_LABEL[e.state]} ${sanitizeTerminal(e.commit ?? "no commit")}`;
257
+ if (e.proof !== "test" || e.state === "current") return row;
258
+ return `${row} Run the tests with a JUnit reporter at HEAD, then run outerlayer emit artifact <file> --for ${id}`;
248
259
  }
249
- function render(entries, notes, json) {
260
+ function render(entries, notes, json, tests) {
250
261
  if (json) return JSON.stringify(entries);
251
- const lines = entries.length === 0 ? ["No criterion declares a proof other than test."] : entries.map(renderEntry);
262
+ const none = tests ? "No criterion declares a proof." : "No criterion declares a proof other than test.";
263
+ const lines = entries.length === 0 ? [none] : entries.map(renderEntry);
252
264
  if (notes.length > 0) lines.push(`The command could not check the judge's results: ${notes.map(sanitizeTerminal).join("; ")}.`);
253
265
  return lines.join("\n");
254
266
  }
@@ -283,11 +295,13 @@ async function runWorkProofs(opts) {
283
295
  if (!checkoutHead) {
284
296
  throw new WorkCommandError("cannot read the checkout's HEAD. Run this inside the git checkout, or pass the head explicitly.");
285
297
  }
286
- const declared = classifyProofs(body, checkoutHead);
287
- const unproven = await findUnproven({ item: body, cwd: opts.cwd ?? process.cwd(), head: checkoutHead });
298
+ const cwd = opts.cwd ?? process.cwd();
299
+ const tests = body.criteria?.testProofsReported === true && await testProofMode(cwd) === "any";
300
+ const declared = classifyProofs(body, checkoutHead, { tests });
301
+ const unproven = await findUnproven({ item: body, cwd, head: checkoutHead });
288
302
  const entries = [...declared, ...unproven.entries];
289
303
  const json = opts.json === true;
290
- const output = render(entries, json ? [] : unproven.notes, json);
304
+ const output = render(entries, json ? [] : unproven.notes, json, tests);
291
305
  if (!opts.quiet) {
292
306
  process.stdout.write(output + "\n");
293
307
  if (json && unproven.notes.length > 0) process.stderr.write(`The command could not check the judge's results: ${unproven.notes.join("; ")}.
@@ -300,7 +314,7 @@ async function runWorkProofs(opts) {
300
314
  async function runWorkProofsCommand(opts) {
301
315
  try {
302
316
  if (opts.record) {
303
- const { runWorkProofsRecord } = await import('./work-proofs-record-MCSA56F5.js');
317
+ const { runWorkProofsRecord } = await import('./work-proofs-record-SPGI47OS.js');
304
318
  const result2 = await runWorkProofsRecord(opts);
305
319
  process.exitCode = result2.exitCode;
306
320
  return;
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { readsJobState, READ_JOB_STATE_FORMATS, jobStateFormatOf } from './chunk-ZVB57WI6.js';
4
3
  import { itemsSentence, criteriaOf, hostItemsOf, loadCitationFinder, MAX_TEST_FILE_BYTES, MAX_TEST_FILES, criterionInputs, planCriteria, parseJudgeAnswer, inCriteriaOrder, oneLineReason, judgedItems } from './chunk-6CK2OC4Q.js';
4
+ import { readsJobState, READ_JOB_STATE_FORMATS, jobStateFormatOf } from './chunk-ZVB57WI6.js';
5
5
  import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-P3NPTFLF.js';
6
6
  import { zodProblem } from './chunk-I3LTIAOR.js';
7
7
  import { senderPidfile } from './chunk-WBTPI5MP.js';
8
8
  import { installScrubContext } from './chunk-QRJIBTNQ.js';
9
9
  import { writeDockerClientConfig } from './chunk-CFFVCI2I.js';
10
10
  import { upgradedStarterText } from './chunk-TZMDRHWB.js';
11
- import { ADDED_USER, shellQuote, GH_CONFIG_YML, ghHostsYml, hasClaudeCredential, AssetError, obtainImage, ensureRootfs, makeBuildsDirPrivate, gitRemoteFor, startServicesFor, createLeaseChannel, createBuildDisk, machineConfig, startJailedInto, resolveAgentUser, AgentUserError, runBuildSteps, createContainerRuntime, containerSenderCommand, hostCommandEnvironment, execArgv, signalInContainer, startHostServices, LEASE_SECONDS, managedBuildSettingsFor, stopContainer, cleanupContainer, outOfMemoryReason, closeHostBuild, dropManagedClaudeKey, dropManagedBuildSettings, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, syncInContainer, copyTranscriptsFromContainer, MANAGED_UNJAILED_REASON, senderAliveScript, managedMachineLimits, withFactoryHosts, helperFirecrackerNote, managedClaudeKeyValues, managedBuildSettingValues, stopJailed, deleteBuildDisk, managedClaudeKeyFor, ROOT_DISK_ID_PREFIX, copyTranscripts, containerJudgeEnvironment, senderSignalScript, copyJudgeTree } from './chunk-3PUOHONX.js';
12
- import { fetchCommit, readBranchHead, diffBetween } from './chunk-XHZBLIB2.js';
11
+ import { ADDED_USER, shellQuote, GH_CONFIG_YML, ghHostsYml, hasClaudeCredential, AssetError, obtainImage, ensureRootfs, makeBuildsDirPrivate, gitRemoteFor, startServicesFor, createLeaseChannel, createBuildDisk, machineConfig, startJailedInto, resolveAgentUser, AgentUserError, runBuildSteps, createContainerRuntime, containerSenderCommand, hostCommandEnvironment, execArgv, signalInContainer, startHostServices, LEASE_SECONDS, managedBuildSettingsFor, stopContainer, cleanupContainer, outOfMemoryReason, closeHostBuild, dropManagedClaudeKey, dropManagedBuildSettings, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, syncInContainer, copyTranscriptsFromContainer, MANAGED_UNJAILED_REASON, senderAliveScript, managedMachineLimits, withFactoryHosts, helperFirecrackerNote, managedClaudeKeyValues, managedBuildSettingValues, stopJailed, deleteBuildDisk, managedClaudeKeyFor, ROOT_DISK_ID_PREFIX, copyTranscripts, containerJudgeEnvironment, senderSignalScript, copyJudgeTree } from './chunk-DFBY6LX3.js';
12
+ import { fetchCommit, readBranchHead, diffBetween } from './chunk-XDJ376OP.js';
13
13
  import { waitForAgent, vmExecArgs } from './chunk-3VZTNXK5.js';
14
14
  import { socketPathProblem, vsockLinks, LEASE_LINK, linkVsockSockets } from './chunk-6KFJIU73.js';
15
15
  import { describeCallFailure, resolveGoverningSource, prefetchGovernedContext, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, removeKeptContext, formatDuration, retrySend, formatClock, keptContextTree, WORKFLOW_PERMISSION_REASON } from './chunk-77VBS2RT.js';
16
- import { imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-BQQPDBSF.js';
17
- import { formatBytes, DEFAULT_CACHE_DISK, allocatedBytes } from './chunk-3HJMY3H5.js';
18
- import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, parseSize, childEnvironment, withAnswerProtocol, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR, COMMAND_DIR, MAX_ITEMS_BYTES } from './chunk-XYLHSCLR.js';
16
+ import { imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-Q3L5AC75.js';
17
+ import { formatBytes, DEFAULT_CACHE_DISK, allocatedBytes } from './chunk-6NXBXWOP.js';
18
+ import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, parseSize, childEnvironment, withAnswerProtocol, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR, COMMAND_DIR, MAX_ITEMS_BYTES } from './chunk-KOZ6IBEI.js';
19
19
  import { CLAUDE_CODE_VERSION, FIRECRACKER_VERSION } from './chunk-4UPET3R7.js';
20
20
  import { isSameProcess, startTimeOf } from './chunk-JBJTC3UU.js';
21
21
  import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-QABXXQ67.js';
@@ -3104,6 +3104,10 @@ function asHostReads(file, base, log, tag) {
3104
3104
  log.line(`${tag} ${file.path} is an unedited copy an earlier release wrote, so it is read as this CLI writes it`);
3105
3105
  return { path: file.path, content: upgraded };
3106
3106
  }
3107
+ function testProofIn(root) {
3108
+ const policyText = readInside(root, POLICY_FILE);
3109
+ return parsePolicy(policyText === void 0 ? null : { path: POLICY_FILE, content: policyText }, []).testProof;
3110
+ }
3107
3111
  function checksIn(root, log, tag) {
3108
3112
  const base = existsSync(join(root, AGENTS_SKILLS_BASE)) ? AGENTS_SKILLS_BASE : OUTERLAYER_SKILLS_BASE;
3109
3113
  const policyText = readInside(root, POLICY_FILE);
@@ -3471,4 +3475,4 @@ async function runHostChecks(input) {
3471
3475
  }
3472
3476
  }
3473
3477
 
3474
- export { ALREADY_RELEASED, AttemptLogBook, EXIT_CODE_FILE, GUEST_USAGE_INTERVAL_MS, MAX_CHECK_ITEMS_BYTES, MICROVM_COMMAND_DIR, RENEW_INTERVAL_SECONDS, appendCommandLog, checksIn, commandItems, commandLogOffset, deliverCommitHooks, describeHookEnd, finishJob, foldSample, hookLimitsFor, inTeardown, isContainerTracked, isGroupAlive, isIdle, isJudgeCheck, isMicroVmTracked, isReadable, isTimedOut, isTracked, isUnfinished, jobEnv, judgeProbe, listAdoptableJobs, listTrackedJobs, listUnreadableJobs, makeRecorder, microVmCommandLine, microVmOomKills, needsRenew, outcomeFromExitCode, probeCommand, probeMicroVmCommand, provisionMicroVm, provisionProcess, readCpuUsec, readDefinitions, readProvisionOut, recoverLostJobs, releaseLease, renewLease, restartSender, retryFailedReleases, runCommand, runHook, runHostChecks, sampleGuest, scrubReason, serveLease, setStage, startMicroVmCommand, startSender, stopOrphanedMicroVms, stripTerminalControls, timeoutAfter, unfinishedJobs, vmAlive, workdirProblem, writeGuestGhConfig };
3478
+ export { ALREADY_RELEASED, AttemptLogBook, EXIT_CODE_FILE, GUEST_USAGE_INTERVAL_MS, MAX_CHECK_ITEMS_BYTES, MICROVM_COMMAND_DIR, RENEW_INTERVAL_SECONDS, appendCommandLog, checksIn, commandItems, commandLogOffset, deliverCommitHooks, describeHookEnd, finishJob, foldSample, hookLimitsFor, inTeardown, isContainerTracked, isGroupAlive, isIdle, isJudgeCheck, isMicroVmTracked, isReadable, isTimedOut, isTracked, isUnfinished, jobEnv, judgeProbe, listAdoptableJobs, listTrackedJobs, listUnreadableJobs, makeRecorder, microVmCommandLine, microVmOomKills, needsRenew, outcomeFromExitCode, probeCommand, probeMicroVmCommand, provisionMicroVm, provisionProcess, readCpuUsec, readDefinitions, readProvisionOut, recoverLostJobs, releaseLease, renewLease, restartSender, retryFailedReleases, runCommand, runHook, runHostChecks, sampleGuest, scrubReason, serveLease, setStage, startMicroVmCommand, startSender, stopOrphanedMicroVms, stripTerminalControls, testProofIn, timeoutAfter, unfinishedJobs, vmAlive, workdirProblem, writeGuestGhConfig };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { builtinKind, keepsHostBuilder } from './chunk-BQQPDBSF.js';
4
- import { parseSize } from './chunk-XYLHSCLR.js';
3
+ import { builtinKind, keepsHostBuilder } from './chunk-Q3L5AC75.js';
4
+ import { parseSize } from './chunk-KOZ6IBEI.js';
5
5
  import { runnerDir } from './chunk-GJ4KBHBD.js';
6
6
  import { FD_SLOTS_PER_BUILD, FD_STORE_ENV, BUILD_SLICE_MEMORY_ENV, CLAUDE_CREDENTIAL_ID, CLAUDE_ENV_FILE, credentialLineIn, withoutCredentialLines } from './chunk-SDAEXUIX.js';
7
7
  import { existsSync, readFileSync, writeFileSync, chmodSync, renameSync } from 'fs';
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RecipeError, locateRecipe, readRecipe, assertBuildable, runnerLabelValue, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-XYLHSCLR.js';
3
+ import { runnerLabelValue } from './chunk-KOZ6IBEI.js';
4
4
  import { GH_VERSION, VOICE_PACK_FILES, VOICE_PACK_VERSION, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, TINI_SHA256, TINI_VERSION, CLAUDE_CODE_VERSION, NODE_IMAGE, DEFAULT_BASE_IMAGE, MEDIA_PINS, PLAYWRIGHT_VERSION } from './chunk-4UPET3R7.js';
5
+ import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-HDLON3RJ.js';
5
6
  import { claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-LQHCNXPK.js';
6
7
  import { startTimeOf } from './chunk-JBJTC3UU.js';
7
8
  import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, repoCacheDir, imagesDir, imageBuildLogsDir, attemptStamp, runnerDir, rootfsPathFor } from './chunk-GJ4KBHBD.js';
@@ -244,6 +245,11 @@ function toolsDockerfile(parts) {
244
245
  `RUN npm install --global --prefix /out/opt/outerlayer/claude @anthropic-ai/claude-code@${version}`,
245
246
  "COPY dist /out/opt/outerlayer/cli/dist",
246
247
  "COPY package.json /out/opt/outerlayer/cli/package.json",
248
+ // `outerlayer demo record` runs a demo on the Playwright release this CLI depends on, found beside the CLI as an npm
249
+ // install puts it. Only the library, with no install scripts: the layer adds no browser to a repository's own image.
250
+ "RUN mkdir -p /tmp/cli-deps && cd /tmp/cli-deps && echo '{}' > package.json \\",
251
+ ` && npm install --no-audit --no-fund --ignore-scripts @playwright/test@${plain("the Playwright version", PLAYWRIGHT_VERSION, /^[0-9.]+$/)} \\`,
252
+ " && mv node_modules /out/opt/outerlayer/cli/node_modules",
247
253
  // `outerlayer claude` installs the maintained skills from this pack into the build's home folder before the agent starts.
248
254
  "COPY skill-pack /out/opt/outerlayer/cli/skill-pack",
249
255
  "RUN mkdir -p /out/opt/outerlayer/bin /out/usr/local/bin /out/etc/claude-code /out/build \\",