@kitman-sh/cli 0.10.53 → 0.10.55

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 (34) hide show
  1. package/dist/{chunk-x9dhxfts.js → chunk-148mjppg.js} +5 -5
  2. package/dist/{chunk-pp1p3g6e.js → chunk-4kssrezn.js} +6 -1
  3. package/dist/{chunk-ctasxxz5.js → chunk-5j3cxsnp.js} +10 -10
  4. package/dist/{chunk-7thnf14y.js → chunk-5y5axze6.js} +609 -6
  5. package/dist/{chunk-mbctzx7e.js → chunk-61k67vxh.js} +76 -1389
  6. package/dist/{chunk-arvwar2c.js → chunk-7evwar6b.js} +1 -1
  7. package/dist/{chunk-mej2bx5n.js → chunk-99ver3za.js} +4 -4
  8. package/dist/{chunk-jagzz148.js → chunk-axdmbr61.js} +26 -26
  9. package/dist/{chunk-p6spvbwq.js → chunk-dgb6s5vq.js} +482 -100
  10. package/dist/{chunk-v290mf51.js → chunk-dj7pp4w4.js} +179 -35
  11. package/dist/{chunk-eg8f5ncv.js → chunk-dkpqwk0q.js} +7 -7
  12. package/dist/{chunk-r8p3nxcp.js → chunk-eerh2t20.js} +10 -10
  13. package/dist/{chunk-jafetf7z.js → chunk-g53wn1q8.js} +2 -2
  14. package/dist/chunk-g7vk5tjp.js +1109 -0
  15. package/dist/{chunk-vjmz23rs.js → chunk-gwcqz1bj.js} +1 -1
  16. package/dist/{chunk-wh1pa2aa.js → chunk-m32wb6t0.js} +245 -108
  17. package/dist/{chunk-3bj7sc3v.js → chunk-mmetyep8.js} +7 -7
  18. package/dist/{chunk-30397r95.js → chunk-mtgkvbk4.js} +4 -4
  19. package/dist/{chunk-dzh9e6n2.js → chunk-q0yna8sw.js} +52 -35
  20. package/dist/{chunk-6vns3ej0.js → chunk-rjfxnk05.js} +5 -5
  21. package/dist/{chunk-g5bs3f6z.js → chunk-twp7aprz.js} +4 -6
  22. package/dist/{chunk-x0b92bjb.js → chunk-vtn088tq.js} +6 -6
  23. package/dist/{chunk-b6thzgc9.js → chunk-wczs5vrq.js} +2 -2
  24. package/dist/{chunk-11p4wf6n.js → chunk-xgwjcq4z.js} +3 -3
  25. package/dist/egress-proxy.ts +138 -21
  26. package/dist/half-close-relay.ts +125 -0
  27. package/dist/index.js +4 -4
  28. package/dist/tcp-forwarder.ts +29 -0
  29. package/package.json +1 -1
  30. package/dist/chunk-1mc9vgcr.js +0 -39
  31. package/dist/chunk-jfvq7s24.js +0 -145
  32. package/dist/chunk-txwt6r25.js +0 -1731
  33. package/dist/chunk-vyv0p5eq.js +0 -3183
  34. package/dist/chunk-z821b2gp.js +0 -164
@@ -5,7 +5,7 @@ import {
5
5
  isObject,
6
6
  isJsonObject,
7
7
  isString
8
- } from "./chunk-arvwar2c.js";
8
+ } from "./chunk-7evwar6b.js";
9
9
  import {
10
10
  pipeArguments,
11
11
  dual,
@@ -42,7 +42,7 @@ import {
42
42
  isFailure2,
43
43
  hasInterrupts,
44
44
  makeUnsafe5,
45
- make17,
45
+ make16,
46
46
  _await,
47
47
  fail5,
48
48
  isDoneUnsafe,
@@ -154,7 +154,11 @@ import {
154
154
  encodePrettyJsonString,
155
155
  decodeJsonStringSync,
156
156
  encodeUnknownJsonStringSync
157
- } from "./chunk-mbctzx7e.js";
157
+ } from "./chunk-61k67vxh.js";
158
+ import {
159
+ Id,
160
+ secretReference
161
+ } from "./chunk-4kssrezn.js";
158
162
  import {
159
163
  currentTimeMillis,
160
164
  SecureRandom,
@@ -217,11 +221,7 @@ import {
217
221
  installCommand,
218
222
  checkServicesFile,
219
223
  checkServices
220
- } from "./chunk-wh1pa2aa.js";
221
- import {
222
- Id,
223
- secretReference
224
- } from "./chunk-pp1p3g6e.js";
224
+ } from "./chunk-m32wb6t0.js";
225
225
  import {
226
226
  join,
227
227
  interrupt,
@@ -257,12 +257,13 @@ import {
257
257
  writeSrtSettings2,
258
258
  srtStepArgv2,
259
259
  srtArgv2
260
- } from "./chunk-11p4wf6n.js";
260
+ } from "./chunk-xgwjcq4z.js";
261
261
  import {
262
262
  writeAgentEnvironmentConfigFile2,
263
263
  readManifestSkillPaths2,
264
264
  tomlTableHeader2,
265
265
  tomlKeyPath2,
266
+ kitmanSkillEntry,
266
267
  SourceResolver,
267
268
  withSourceResolutionCache2,
268
269
  AgentEnvironmentMaterializationError2,
@@ -272,8 +273,8 @@ import {
272
273
  applyAgentEnvironmentMaterialization2,
273
274
  isPathWithin2,
274
275
  skillIdentity2
275
- } from "./chunk-7thnf14y.js";
276
- import"./chunk-g5bs3f6z.js";
276
+ } from "./chunk-5y5axze6.js";
277
+ import"./chunk-twp7aprz.js";
277
278
  import {
278
279
  sliceBytes2,
279
280
  maxLineBytes2,
@@ -281,31 +282,28 @@ import {
281
282
  decodedOption2,
282
283
  decoded2,
283
284
  readOpencode2
284
- } from "./chunk-x0b92bjb.js";
285
+ } from "./chunk-vtn088tq.js";
285
286
  import {
286
287
  writeSecretRegistry,
287
288
  secretRefusalLog,
288
289
  parseSecretRefusals
289
- } from "./chunk-jafetf7z.js";
290
- import"./chunk-txwt6r25.js";
290
+ } from "./chunk-g53wn1q8.js";
291
291
  import {
292
292
  uploadRunFile,
293
293
  programLease,
294
294
  rpcRunFiles,
295
295
  programHostsEnv,
296
296
  undeclaredHostsEnv
297
- } from "./chunk-jfvq7s24.js";
298
- import"./chunk-ctasxxz5.js";
297
+ } from "./chunk-g7vk5tjp.js";
298
+ import"./chunk-5j3cxsnp.js";
299
299
  import {
300
300
  nextInt
301
- } from "./chunk-vjmz23rs.js";
302
- import"./chunk-x9dhxfts.js";
301
+ } from "./chunk-gwcqz1bj.js";
303
302
  import {
304
303
  ChildProcessSpawner,
305
- make7
306
- } from "./chunk-3bj7sc3v.js";
307
- import"./chunk-1mc9vgcr.js";
308
- import"./chunk-z821b2gp.js";
304
+ make3
305
+ } from "./chunk-mmetyep8.js";
306
+ import"./chunk-148mjppg.js";
309
307
 
310
308
  // packages/core/src/sync-kit.ts
311
309
  import { createHash } from "crypto";
@@ -2432,20 +2430,20 @@ var requireKitCommands = (setup, runs) => gen(function* () {
2432
2430
  });
2433
2431
  var stepKitSetup = (agent, harness) => gen(function* () {
2434
2432
  const kits = agent.brief.kits ?? [];
2435
- if (kits.length === 0)
2436
- return;
2437
- const fetch = agent.setupArchive;
2438
2433
  const unavailable = (reason) => ({
2439
2434
  refused: failed("kit_setup_unavailable", `Kitman could not load the Run's Kit setup: ${reason}`)
2440
2435
  });
2436
+ if (!isKitHarness(harness))
2437
+ return kits.length === 0 ? undefined : unavailable(`no Kit setup renders for the ${harness} harness`);
2438
+ if (kits.length === 0)
2439
+ return materializeKitSetup(harness, [kitmanSkillEntry], agent.brief.listedSkills ?? []);
2440
+ const fetch = agent.setupArchive;
2441
2441
  if (fetch === undefined)
2442
2442
  return unavailable("this Runner fetches no setup archives");
2443
- if (!isKitHarness(harness))
2444
- return unavailable(`no Kit setup renders for the ${harness} harness`);
2445
2443
  const setups = yield* forEach(kits, (kit) => fetch(kit.setupDigest).pipe(flatMap3(decodeSetupArchive), map8((archive) => ({ name: kit.name, version: kit.version, archive })))).pipe(result);
2446
2444
  if (isFailure(setups))
2447
2445
  return unavailable(setups.failure.message);
2448
- const setup = materializeKitSetup(harness, setups.success, agent.brief.listedSkills ?? []);
2446
+ const setup = materializeKitSetup(harness, [...setups.success, kitmanSkillEntry], agent.brief.listedSkills ?? []);
2449
2447
  for (const server of setup.mcpServers) {
2450
2448
  const missing = kitMcpSecretNames(server.transport).find((name) => agent.secrets?.[name] === undefined);
2451
2449
  if (missing !== undefined)
@@ -5312,8 +5310,71 @@ var harnessesInSrt = (input) => gen(function* () {
5312
5310
  binaries: Object.fromEntries(probed.flatMap((entry) => entry.binary === undefined ? [] : [[entry.harness, entry.binary]]))
5313
5311
  };
5314
5312
  });
5315
- // packages/agent-runtime/src/check-postgres.ts
5313
+ // packages/agent-runtime/src/check-docker.ts
5314
+ import { fileURLToPath as fileURLToPath2 } from "url";
5315
+
5316
+ // packages/agent-runtime/src/loopback-tunnel.ts
5316
5317
  import * as net from "net";
5318
+
5319
+ class LoopbackTunnelUnavailable extends TaggedError("LoopbackTunnelUnavailable") {
5320
+ }
5321
+ var srtLoopbackTunnel = (tunnel) => [
5322
+ "proxy=${HTTP_PROXY:?srt set no HTTP_PROXY}",
5323
+ "proxy=${proxy#*://}",
5324
+ "proxy=${proxy%%/*}",
5325
+ "auth=",
5326
+ "case $proxy in *@*)",
5327
+ ` auth=$(printf %s "\${proxy%@*}" | awk 'BEGIN { for (i = 1; i < 256; i++) hex[sprintf("%02X", i)] = sprintf("%c", i) }
5328
+ { out = ""; while (match($0, /%[0-9A-Fa-f][0-9A-Fa-f]/)) { out = out substr($0, 1, RSTART - 1) hex[toupper(substr($0, RSTART + 1, 2))]; $0 = substr($0, RSTART + 3) } printf "%s", out $0 }')`,
5329
+ " proxy=${proxy##*@} ;;",
5330
+ "esac",
5331
+ "log=$(mktemp)",
5332
+ `${tunnel.listener ?? `socat -t 86400 TCP-LISTEN:${tunnel.listenPort},bind=127.0.0.1,fork,reuseaddr "PROXY:\${proxy%:*}:127.0.0.1:${tunnel.hostPort},proxyport=\${proxy##*:}\${auth:+,proxyauth=$auth}"`} 2>"$log" &`,
5333
+ "tunnel=$!",
5334
+ `fail() { echo "Kitman: the ${tunnel.service} tunnel did not open: $1" >&2; cat "$log" >&2; kill $tunnel 2>/dev/null; rm -f "$log"; exit 1; }`,
5335
+ "tries=0",
5336
+ "while :; do",
5337
+ ' kill -0 $tunnel 2>/dev/null || fail "its listener stopped"',
5338
+ ` answer=$( (${tunnel.probe}; sleep 1) | socat - TCP:127.0.0.1:${tunnel.listenPort} 2>/dev/null | ${tunnel.read})`,
5339
+ ` case $answer in ${tunnel.answers}) break ;; esac`,
5340
+ " tries=$((tries + 1))",
5341
+ ` [ $tries -lt 30 ] || fail "${tunnel.service} did not answer through it"`,
5342
+ " sleep 0.2",
5343
+ "done",
5344
+ 'kill -0 $tunnel 2>/dev/null || fail "its listener stopped"',
5345
+ 'sh -c "$1"',
5346
+ "status=$?",
5347
+ "kill $tunnel 2>/dev/null",
5348
+ 'rm -f "$log"',
5349
+ "exit $status"
5350
+ ].join(`
5351
+ `);
5352
+ var loopbackSocketForwarder = (hostPort, socket) => gen(function* () {
5353
+ const fs = yield* FileSystem;
5354
+ const dir = yield* flatMap3(fs.makeTempDirectoryScoped({ prefix: "kitman-lo-" }), fs.realPath).pipe(mapError2((error) => new LoopbackTunnelUnavailable({ reason: error.message })));
5355
+ yield* acquireRelease(callback3((resume) => {
5356
+ const open = new Set;
5357
+ const server = net.createServer({ allowHalfOpen: true }, (client) => {
5358
+ const upstream = net.connect({ port: hostPort, host: "127.0.0.1", allowHalfOpen: true });
5359
+ for (const connection of [client, upstream]) {
5360
+ open.add(connection);
5361
+ connection.on("close", () => open.delete(connection));
5362
+ }
5363
+ client.pipe(upstream);
5364
+ upstream.pipe(client);
5365
+ client.on("error", () => upstream.destroy());
5366
+ upstream.on("error", () => client.destroy());
5367
+ });
5368
+ server.once("error", (error) => resume(fail7(new LoopbackTunnelUnavailable({ reason: error.message }))));
5369
+ server.listen(`${dir}/${socket}`, () => resume(succeed6({ server, open })));
5370
+ }), ({ server, open }) => callback3((resume) => {
5371
+ server.close(() => resume(void_3));
5372
+ open.forEach((connection) => connection.destroy());
5373
+ }));
5374
+ return dir;
5375
+ });
5376
+
5377
+ // packages/agent-runtime/src/check-postgres.ts
5317
5378
  var CheckPostgresImage = "pgvector/pgvector:0.8.7-pg16@sha256:7b822b0aac60967beb1ea5e576b8602c94c300a157d187f385ae3e0da199b90a";
5318
5379
  var checkPostgresSandboxPort = 5432;
5319
5380
  var checkPostgresAlias = "kitman-postgres";
@@ -5413,60 +5474,202 @@ var dockerCheckPostgres = (runnerId, replicaId) => (id) => gen(function* () {
5413
5474
  return { container, hostPort, user, password };
5414
5475
  });
5415
5476
  var sslRequestOctal = String.raw`\000\000\000\010\004\322\026\057`;
5416
- var srtPostgresTunnel = (hostPort, listenPort = checkPostgresSandboxPort) => [
5417
- "proxy=${HTTP_PROXY:?srt set no HTTP_PROXY}",
5418
- "proxy=${proxy#*://}",
5419
- "proxy=${proxy%%/*}",
5420
- "auth=",
5421
- "case $proxy in *@*)",
5422
- ` auth=$(printf %s "\${proxy%@*}" | awk 'BEGIN { for (i = 1; i < 256; i++) hex[sprintf("%02X", i)] = sprintf("%c", i) }
5423
- { out = ""; while (match($0, /%[0-9A-Fa-f][0-9A-Fa-f]/)) { out = out substr($0, 1, RSTART - 1) hex[toupper(substr($0, RSTART + 1, 2))]; $0 = substr($0, RSTART + 3) } printf "%s", out $0 }')`,
5424
- " proxy=${proxy##*@} ;;",
5425
- "esac",
5426
- "log=$(mktemp)",
5427
- `socat TCP-LISTEN:${listenPort},bind=127.0.0.1,fork,reuseaddr "PROXY:\${proxy%:*}:127.0.0.1:${hostPort},proxyport=\${proxy##*:}\${auth:+,proxyauth=$auth}" 2>"$log" &`,
5428
- "tunnel=$!",
5429
- 'fail() { echo "Kitman: the Postgres tunnel did not open: $1" >&2; cat "$log" >&2; kill $tunnel 2>/dev/null; rm -f "$log"; exit 1; }',
5430
- "tries=0",
5431
- "while :; do",
5432
- ' kill -0 $tunnel 2>/dev/null || fail "its listener stopped"',
5433
- ` answer=$( (printf '${sslRequestOctal}'; sleep 1) | socat - TCP:127.0.0.1:${listenPort} 2>/dev/null | head -c 1)`,
5434
- " case $answer in N|S) break ;; esac",
5435
- " tries=$((tries + 1))",
5436
- ' [ $tries -lt 30 ] || fail "Postgres did not answer through it"',
5437
- " sleep 0.2",
5438
- "done",
5439
- 'kill -0 $tunnel 2>/dev/null || fail "its listener stopped"',
5440
- 'sh -c "$1"',
5441
- "status=$?",
5442
- "kill $tunnel 2>/dev/null",
5443
- 'rm -f "$log"',
5444
- "exit $status"
5445
- ].join(`
5446
- `);
5447
- var postgresSocketForwarder = (hostPort) => gen(function* () {
5448
- const fs = yield* FileSystem;
5449
- const dir = yield* fs.realPath(yield* fs.makeTempDirectoryScoped({ prefix: "kpg-" }));
5450
- yield* acquireRelease(callback3((resume) => {
5451
- const open = new Set;
5452
- const server = net.createServer((client) => {
5453
- const upstream = net.connect(hostPort, "127.0.0.1");
5454
- for (const socket of [client, upstream]) {
5455
- open.add(socket);
5456
- socket.on("close", () => open.delete(socket));
5457
- }
5458
- client.pipe(upstream);
5459
- upstream.pipe(client);
5460
- client.on("error", () => upstream.destroy());
5461
- upstream.on("error", () => client.destroy());
5462
- });
5463
- server.once("error", (error) => resume(fail7(new CheckPostgresUnavailable({ reason: error.message }))));
5464
- server.listen(`${dir}/.s.PGSQL.${checkPostgresSandboxPort}`, () => resume(succeed6({ server, open })));
5465
- }), ({ server, open }) => callback3((resume) => {
5466
- server.close(() => resume(void_3));
5467
- open.forEach((socket) => socket.destroy());
5468
- }));
5469
- return dir;
5477
+ var srtPostgresTunnel = (hostPort, listenPort = checkPostgresSandboxPort) => srtLoopbackTunnel({
5478
+ service: "Postgres",
5479
+ hostPort,
5480
+ listenPort,
5481
+ probe: `printf '${sslRequestOctal}'`,
5482
+ read: "head -c 1",
5483
+ answers: "N|S"
5484
+ });
5485
+ var postgresSocketForwarder = (hostPort) => loopbackSocketForwarder(hostPort, `.s.PGSQL.${checkPostgresSandboxPort}`).pipe(mapError2((error) => new CheckPostgresUnavailable({ reason: error.reason })));
5486
+
5487
+ // packages/agent-runtime/src/check-docker.ts
5488
+ var checkDockerPort = 2375;
5489
+ var checkDockerAlias = "kitman-docker";
5490
+ var DockerHubRegistry = "https://registry-1.docker.io";
5491
+ var CheckDockerLabel = "kitman.check-docker";
5492
+ var CheckDockerReplicaLabel = "kitman.check-docker-replica";
5493
+ var rootlessDataRoot = "/home/rootless/.local/share/docker";
5494
+ var registryDataRoot = "/var/lib/registry";
5495
+ var registryMirrorPort = 5000;
5496
+ var egressProxyPort = 3128;
5497
+
5498
+ class CheckDockerUnavailable extends TaggedError("CheckDockerUnavailable") {
5499
+ get message() {
5500
+ return `A pipeline check runs with a Docker daemon of its own, which this Runner could not start: ${this.reason}`;
5501
+ }
5502
+ }
5503
+ var dockerName2 = (id) => id.replaceAll(/[^a-zA-Z0-9_.-]/g, "-");
5504
+ var checkRegistryCacheVolume = (runnerId) => `kitman-check-registry-cache-${dockerName2(runnerId)}`;
5505
+ var checkDockerProxyEnvironment = (proxy, mirror) => {
5506
+ const direct = `localhost,127.0.0.1,${new URL(mirror).hostname}`;
5507
+ return {
5508
+ HTTP_PROXY: proxy,
5509
+ HTTPS_PROXY: proxy,
5510
+ http_proxy: proxy,
5511
+ https_proxy: proxy,
5512
+ NO_PROXY: direct,
5513
+ no_proxy: direct
5514
+ };
5515
+ };
5516
+ var checkDockerDaemonArgs = (input) => [
5517
+ "run",
5518
+ "--detach",
5519
+ "--name",
5520
+ input.name,
5521
+ ...input.labels.flatMap(([key, value]) => ["--label", `${key}=${value}`]),
5522
+ "--network",
5523
+ input.network,
5524
+ "--network-alias",
5525
+ checkDockerAlias,
5526
+ "--security-opt",
5527
+ "seccomp=unconfined",
5528
+ "--security-opt",
5529
+ "apparmor=unconfined",
5530
+ "--security-opt",
5531
+ "systempaths=unconfined",
5532
+ "--device",
5533
+ "/dev/net/tun",
5534
+ "--volume",
5535
+ rootlessDataRoot,
5536
+ "--env",
5537
+ "DOCKER_TLS_CERTDIR=",
5538
+ ...Object.entries(input.proxy === undefined ? {} : checkDockerProxyEnvironment(input.proxy, input.mirror)).flatMap(([key, value]) => ["--env", `${key}=${value}`]),
5539
+ input.image,
5540
+ "--registry-mirror",
5541
+ input.mirror,
5542
+ "--tls=false"
5543
+ ];
5544
+ var checkRegistryMirrorArgs = (input) => [
5545
+ "run",
5546
+ "--detach",
5547
+ "--rm",
5548
+ "--name",
5549
+ input.name,
5550
+ ...input.labels.flatMap(([key, value]) => ["--label", `${key}=${value}`]),
5551
+ "--network",
5552
+ input.network,
5553
+ "--volume",
5554
+ `${input.volume}:${registryDataRoot}`,
5555
+ "--env",
5556
+ `REGISTRY_PROXY_REMOTEURL=${DockerHubRegistry}`,
5557
+ "--env",
5558
+ "REGISTRY_PROXY_TTL=0",
5559
+ input.image
5560
+ ];
5561
+ var checkDockerClientConfig = (proxy) => proxy === undefined ? {} : { proxies: { default: { httpProxy: proxy, httpsProxy: proxy, noProxy: "localhost,127.0.0.1" } } };
5562
+ var orphanedCheckDocker = (listing, live) => listing.split(`
5563
+ `).map((line) => line.trim().split(/\s+/)).flatMap(([id, replica]) => id === undefined || id === "" || live.has(replica ?? "") ? [] : [id]);
5564
+ var removeCheckDocker = (runnerId, liveReplicas) => gen(function* () {
5565
+ const filter = ["--filter", `label=${CheckDockerLabel}=${runnerId}`];
5566
+ const format = `{{.ID}} {{.Label "${CheckDockerReplicaLabel}"}}`;
5567
+ const containers = orphanedCheckDocker(yield* runCommand2("docker", ["ps", "--all", ...filter, "--format", format], { timeout: "10 seconds" }), liveReplicas);
5568
+ if (containers.length > 0)
5569
+ yield* runCommand2("docker", ["rm", "--force", "--volumes", ...containers], { timeout: "30 seconds" });
5570
+ const networks = orphanedCheckDocker(yield* runCommand2("docker", ["network", "ls", ...filter, "--format", format], { timeout: "10 seconds" }), liveReplicas);
5571
+ if (networks.length > 0)
5572
+ yield* runCommand2("docker", ["network", "rm", ...networks], { timeout: "30 seconds" });
5573
+ }).pipe(ignore);
5574
+ var daemonLogs = (container) => gen(function* () {
5575
+ const state = yield* runCommand2("docker", [
5576
+ "inspect",
5577
+ "--format",
5578
+ "{{.State.Status}} (exit code {{.State.ExitCode}})",
5579
+ container
5580
+ ]);
5581
+ const logs = yield* runCommand2("sh", ["-c", 'docker logs --tail 40 "$0" 2>&1', container]);
5582
+ return `${state.trim()}
5583
+ ${logs.trim().slice(-3000)}`;
5584
+ }).pipe(orElseSucceed(() => "nothing, since docker could not show its state or logs"));
5585
+ var randomHex2 = () => Array.from(crypto.getRandomValues(new Uint8Array(4)), (byte) => byte.toString(16).padStart(2, "0")).join("");
5586
+ var dockerCheckDaemon = (input) => ({ id, network: allowed }) => gen(function* () {
5587
+ const run = `${dockerName2(id)}-${randomHex2()}`;
5588
+ const daemon = `kitman-check-docker-${run}`;
5589
+ const network = `kitman-check-docker-net-${run}`;
5590
+ const outside = `kitman-check-docker-out-${run}`;
5591
+ const mirror = `kitman-check-docker-mirror-${run}`;
5592
+ const proxyContainer = `kitman-check-docker-egress-${run}`;
5593
+ const forwarder = `kitman-check-docker-api-${run}`;
5594
+ const runLabel = "kitman.check-docker-run";
5595
+ const labels = [
5596
+ [CheckDockerLabel, input.runnerId],
5597
+ [CheckDockerReplicaLabel, input.replicaId],
5598
+ [runLabel, run]
5599
+ ];
5600
+ const labelArgs = labels.flatMap(([key, value]) => ["--label", `${key}=${value}`]);
5601
+ const docker = (args, timeout = "30 seconds") => runCommand2("docker", args, { timeout }).pipe(mapError2((error) => new CheckDockerUnavailable({ reason: error.message })));
5602
+ yield* acquireRelease(void_3, () => gen(function* () {
5603
+ const ids = (yield* docker(["ps", "--all", "--quiet", "--filter", `label=${runLabel}=${run}`])).split(`
5604
+ `).filter((line) => line.trim() !== "");
5605
+ if (ids.length > 0)
5606
+ yield* docker(["rm", "--force", "--volumes", ...ids], "2 minutes");
5607
+ yield* ignore(docker(["network", "rm", network]));
5608
+ yield* ignore(docker(["network", "rm", outside]));
5609
+ }).pipe(ignore));
5610
+ yield* docker(["network", "create", "--opt", "com.docker.network.bridge.enable_icc=false", ...labelArgs, outside]);
5611
+ yield* docker(["network", "create", ...allowed === "open" ? [] : ["--internal"], ...labelArgs, network]);
5612
+ const addressOn = (container) => gen(function* () {
5613
+ yield* docker(["network", "connect", network, container]);
5614
+ const address = (yield* docker([
5615
+ "inspect",
5616
+ "--format",
5617
+ `{{(index .NetworkSettings.Networks "${network}").IPAddress}}`,
5618
+ container
5619
+ ])).trim();
5620
+ if (address === "")
5621
+ return yield* new CheckDockerUnavailable({ reason: `${container} has no address` });
5622
+ return address;
5623
+ });
5624
+ const helper = (name, args) => docker(["run", "--detach", "--rm", "--name", name, ...labelArgs, "--network", outside, ...args], "30 minutes");
5625
+ yield* docker(checkRegistryMirrorArgs({
5626
+ name: mirror,
5627
+ image: input.registryImage,
5628
+ labels,
5629
+ network: outside,
5630
+ volume: checkRegistryCacheVolume(input.runnerId)
5631
+ }), "30 minutes");
5632
+ const mirrorUrl = `http://${yield* addressOn(mirror)}:${registryMirrorPort}`;
5633
+ const proxy = allowed === "open" ? undefined : yield* gen(function* () {
5634
+ yield* helper(proxyContainer, [
5635
+ "--volume",
5636
+ `${fileURLToPath2(import.meta.resolve("./egress-proxy.ts"))}:/kitman/egress-proxy.ts:ro`,
5637
+ input.proxyImage ?? EgressProxyImage,
5638
+ "bun",
5639
+ "/kitman/egress-proxy.ts",
5640
+ allowed.hosts.join(",")
5641
+ ]);
5642
+ return `http://${yield* addressOn(proxyContainer)}:${egressProxyPort}`;
5643
+ });
5644
+ yield* docker(checkDockerDaemonArgs({
5645
+ name: daemon,
5646
+ image: input.image,
5647
+ labels,
5648
+ network,
5649
+ mirror: mirrorUrl,
5650
+ ...proxy === undefined ? undefined : { proxy }
5651
+ }), "30 minutes");
5652
+ yield* helper(forwarder, [
5653
+ "--publish",
5654
+ `127.0.0.1::${checkDockerPort}`,
5655
+ "--volume",
5656
+ `${fileURLToPath2(import.meta.resolve("./tcp-forwarder.ts"))}:/kitman/tcp-forwarder.ts:ro`,
5657
+ input.proxyImage ?? EgressProxyImage,
5658
+ "bun",
5659
+ "/kitman/tcp-forwarder.ts",
5660
+ String(checkDockerPort),
5661
+ checkDockerAlias,
5662
+ String(checkDockerPort)
5663
+ ]);
5664
+ yield* docker(["network", "connect", network, forwarder]);
5665
+ const hostPort = publishedPort(yield* docker(["port", forwarder, `${checkDockerPort}/tcp`]));
5666
+ if (hostPort === undefined)
5667
+ return yield* new CheckDockerUnavailable({ reason: "docker published no port" });
5668
+ yield* docker(["--host", `tcp://127.0.0.1:${hostPort}`, "version", "--format", "{{.Server.Version}}"], "10 seconds").pipe(retry({ schedule: spaced("500 millis"), times: 240 }), catch_((error) => gen(function* () {
5669
+ const logs = yield* daemonLogs(daemon);
5670
+ return yield* new CheckDockerUnavailable({ reason: `${error.reason}; the daemon logged: ${logs}` });
5671
+ })));
5672
+ return { container: daemon, hostPort, ...proxy === undefined ? undefined : { proxy } };
5470
5673
  });
5471
5674
  // packages/agent-runtime/src/codex-hook-trust.ts
5472
5675
  class CodexAppServerFailed extends TaggedError("CodexAppServerFailed") {
@@ -5494,7 +5697,7 @@ var codexAppServer = (binary = "codex") => (env) => gen(function* () {
5494
5697
  const input = yield* unbounded2();
5495
5698
  const pending = new Map;
5496
5699
  let lastId = 0;
5497
- const handle = yield* spawner.spawn(make7(binary, ["app-server"], {
5700
+ const handle = yield* spawner.spawn(make3(binary, ["app-server"], {
5498
5701
  cwd: env.home,
5499
5702
  extendEnv: true,
5500
5703
  env: { HOME: env.home, CODEX_HOME: env.codexHome },
@@ -5517,7 +5720,7 @@ var codexAppServer = (binary = "codex") => (env) => gen(function* () {
5517
5720
  return {
5518
5721
  request: (method, params) => gen(function* () {
5519
5722
  const id = ++lastId;
5520
- const deferred = yield* make17();
5723
+ const deferred = yield* make16();
5521
5724
  pending.set(id, deferred);
5522
5725
  yield* send({ id, method, params });
5523
5726
  return yield* _await(deferred).pipe(mapError2((error) => new CodexAppServerFailed({ reason: `${method}: ${error.message}` })));
@@ -5657,7 +5860,7 @@ var handshake = [
5657
5860
  `).join("");
5658
5861
  var kitmanMcpPreflight = (mcp) => gen(function* () {
5659
5862
  const spawner = yield* ChildProcessSpawner;
5660
- const server = yield* spawner.spawn(make7(mcp.command, [...mcp.args], {
5863
+ const server = yield* spawner.spawn(make3(mcp.command, [...mcp.args], {
5661
5864
  extendEnv: true,
5662
5865
  env: mcp.env,
5663
5866
  stdin: { stream: make11(new TextEncoder().encode(handshake)), endOnDone: false },
@@ -5733,7 +5936,7 @@ var programProcessExecutor = (input) => (work) => gen(function* () {
5733
5936
  };
5734
5937
  const exitCode = sandbox === undefined ? yield* gen(function* () {
5735
5938
  const spawner = yield* ChildProcessSpawner;
5736
- const handle = yield* spawner.spawn(make7(input.bun ?? process.execPath, [file], {
5939
+ const handle = yield* spawner.spawn(make3(input.bun ?? process.execPath, [file], {
5737
5940
  stdin: make11(new TextEncoder().encode(stdin)),
5738
5941
  stdout: "inherit",
5739
5942
  stderr: "inherit",
@@ -5796,9 +5999,110 @@ var programProcessExecutor = (input) => (work) => gen(function* () {
5796
5999
  status: "deferred",
5797
6000
  crashed: `it did not start: ${error.message}`.slice(0, 500)
5798
6001
  })));
6002
+ // packages/agent-runtime/src/half-close-relay.ts
6003
+ import { once } from "events";
6004
+ import { connect as connect2, createServer as createServer2 } from "net";
6005
+ var frameHeader = 4;
6006
+ var endOfInput = Buffer.alloc(frameHeader);
6007
+ var maxFrame = 1024 * 1024;
6008
+ var keepUp = (from, to, accepted) => {
6009
+ if (accepted)
6010
+ return;
6011
+ from.pause();
6012
+ to.once("drain", () => from.resume());
6013
+ };
6014
+ var closeTogether = (...sockets) => sockets.forEach((socket) => {
6015
+ socket.on("error", () => sockets.forEach((other) => other.destroy()));
6016
+ socket.on("close", () => sockets.forEach((other) => other.end()));
6017
+ });
6018
+ var listening = (server, port) => once(server.listen(port, "127.0.0.1"), "listening").then(() => server);
6019
+ var startHalfCloseDecoder = (input) => listening(createServer2({ allowHalfOpen: true }, (client) => {
6020
+ const upstream = connect2({ port: input.targetPort, host: "127.0.0.1", allowHalfOpen: true });
6021
+ let pending = Buffer.alloc(0);
6022
+ client.on("data", (chunk) => {
6023
+ pending = Buffer.concat([pending, chunk]);
6024
+ if (pending.length >= frameHeader && pending.readUInt32BE(0) > maxFrame)
6025
+ return void client.destroy();
6026
+ while (pending.length >= frameHeader && pending.length >= frameHeader + pending.readUInt32BE(0)) {
6027
+ const length = pending.readUInt32BE(0);
6028
+ if (length === 0)
6029
+ upstream.end();
6030
+ else
6031
+ keepUp(client, upstream, upstream.write(pending.subarray(frameHeader, frameHeader + length)));
6032
+ pending = pending.subarray(frameHeader + length);
6033
+ }
6034
+ });
6035
+ client.on("end", () => upstream.end());
6036
+ upstream.pipe(client);
6037
+ closeTogether(client, upstream);
6038
+ }), input.port);
6039
+ if (false)
6040
+ ;
6041
+
5799
6042
  // packages/agent-runtime/src/verification-executor.ts
6043
+ import { fileURLToPath as fileURLToPath3 } from "url";
5800
6044
  var checkTimeout = "30 minutes";
5801
6045
  var checkFilesPerVerification = 50;
6046
+ var halfCloseEncoder = [process.execPath, fileURLToPath3(import.meta.resolve("./half-close-relay.ts"))];
6047
+ var srtDockerTunnel = (relayPort) => srtLoopbackTunnel({
6048
+ service: "Docker daemon",
6049
+ hostPort: relayPort,
6050
+ listenPort: checkDockerPort,
6051
+ listener: `${halfCloseEncoder.map(quoted).join(" ")} ${checkDockerPort} "$HTTP_PROXY" ${relayPort}`,
6052
+ probe: String.raw`printf 'GET /_ping HTTP/1.0\r\n\r\n'`,
6053
+ read: "tail -c 2",
6054
+ answers: "OK"
6055
+ });
6056
+ var pipelineEnvironment = (docker, dockerHost) => ({
6057
+ DOCKER_HOST: dockerHost,
6058
+ DOCKER_CONFIG: `${docker.clientDir}/docker`,
6059
+ GCL_HOME: `${docker.clientDir}/gitlab-ci-local-home`
6060
+ });
6061
+ var dockerRoute = (backend, docker) => {
6062
+ if (docker === undefined)
6063
+ return { env: {}, hosts: [], unixSockets: [], services: [], tunnel: undefined };
6064
+ if (backend === "docker")
6065
+ return {
6066
+ env: {
6067
+ ...pipelineEnvironment(docker, `tcp://${checkDockerAlias}:${checkDockerPort}`),
6068
+ NO_PROXY: `localhost,127.0.0.1,${checkDockerAlias}`,
6069
+ no_proxy: `localhost,127.0.0.1,${checkDockerAlias}`
6070
+ },
6071
+ hosts: [],
6072
+ unixSockets: [],
6073
+ services: [{ container: docker.container, alias: checkDockerAlias }],
6074
+ tunnel: undefined
6075
+ };
6076
+ switch (docker.route.kind) {
6077
+ case "socket":
6078
+ return {
6079
+ env: pipelineEnvironment(docker, `unix://${docker.route.dir}/docker.sock`),
6080
+ hosts: [],
6081
+ unixSockets: [docker.route.dir],
6082
+ services: [],
6083
+ tunnel: undefined
6084
+ };
6085
+ case "relay":
6086
+ return {
6087
+ env: pipelineEnvironment(docker, `tcp://127.0.0.1:${checkDockerPort}`),
6088
+ hosts: [`127.0.0.1:${docker.route.port}`],
6089
+ unixSockets: [],
6090
+ services: [],
6091
+ tunnel: srtDockerTunnel(docker.route.port)
6092
+ };
6093
+ case "direct":
6094
+ throw new Error("A pipeline check in srt reaches its daemon through a socket or the relay, never directly.");
6095
+ }
6096
+ };
6097
+ var hostCheckEnvironment = (docker) => {
6098
+ const { POSTGRES_URL: _runnerDatabase, ...runner } = withoutPreloads2();
6099
+ if (docker === undefined)
6100
+ return runner;
6101
+ return {
6102
+ ...Object.fromEntries(Object.entries(runner).filter(([name]) => !name.startsWith("DOCKER_") && !name.startsWith("GCL_") && name !== "SSH_AUTH_SOCK")),
6103
+ ...pipelineEnvironment(docker, `tcp://127.0.0.1:${docker.hostPort}`)
6104
+ };
6105
+ };
5802
6106
  var postgresRoute = (backend, postgres) => {
5803
6107
  if (postgres === undefined)
5804
6108
  return { url: undefined, hosts: [], unixSockets: [], services: [], tunnel: undefined };
@@ -5826,12 +6130,13 @@ var postgresRoute = (backend, postgres) => {
5826
6130
  tunnel: srtPostgresTunnel(postgres.hostPort)
5827
6131
  };
5828
6132
  };
5829
- var checkSandboxPolicy = (work, sandbox, checkout, cache, filesDir, postgresHosts) => ({
6133
+ var checkSandboxPolicy = (work, sandbox, checkout, cache, filesDir, postgresHosts, clientDir) => ({
5830
6134
  ...runnerStateSandboxPolicy(sandbox.runner, [
5831
6135
  repositoryClone(sandbox.runner.workRoot, work.repoBinding.id),
5832
- checkout
6136
+ checkout,
6137
+ ...clientDir === undefined ? [] : [clientDir, ...halfCloseEncoder]
5833
6138
  ]),
5834
- writablePaths: [checkout, cache, filesDir],
6139
+ writablePaths: [checkout, cache, filesDir, ...clientDir === undefined ? [] : [clientDir]],
5835
6140
  network: verificationNetworkAllowlist({
5836
6141
  apiUrl: sandbox.apiUrl,
5837
6142
  storageOrigin: work.storageOrigin,
@@ -5841,16 +6146,15 @@ var checkSandboxPolicy = (work, sandbox, checkout, cache, filesDir, postgresHost
5841
6146
  environment: srtCacheEnvironment2(cache)
5842
6147
  });
5843
6148
  var checkGitEnvironment = { GIT_CONFIG_GLOBAL: "/dev/null", GIT_TERMINAL_PROMPT: "0" };
5844
- var checkRunner = (work, sandbox, cache, inherited) => (checkout) => ({ command, cwd, filesDir, onOutput, postgres }) => {
6149
+ var checkRunner = (work, sandbox, cache, inherited) => (checkout) => ({ command, cwd, filesDir, onOutput, postgres, docker }) => {
5845
6150
  const env = { ...checkGitEnvironment, KITMAN_RUN_FILES_DIR: filesDir };
5846
6151
  const output = onOutput === undefined ? undefined : { onOutput };
5847
6152
  if (sandbox === undefined || sandbox.backend === undefined) {
5848
- const { POSTGRES_URL: _runnerDatabase, ...runner } = withoutPreloads2();
5849
6153
  return runShell2(command, {
5850
6154
  cwd,
5851
6155
  extendEnv: false,
5852
6156
  env: {
5853
- ...runner,
6157
+ ...hostCheckEnvironment(docker),
5854
6158
  ...env,
5855
6159
  ...postgres === undefined ? undefined : { POSTGRES_URL: checkPostgresUrl(postgres, "127.0.0.1", postgres.hostPort) }
5856
6160
  },
@@ -5859,14 +6163,18 @@ var checkRunner = (work, sandbox, cache, inherited) => (checkout) => ({ command,
5859
6163
  });
5860
6164
  }
5861
6165
  const route = postgresRoute(sandbox.backend, postgres);
5862
- const policy = checkSandboxPolicy(work, sandbox, checkout, cache, filesDir, route.hosts);
6166
+ const daemon = dockerRoute(sandbox.backend, docker);
6167
+ const policy = checkSandboxPolicy(work, sandbox, checkout, cache, filesDir, [...route.hosts, ...daemon.hosts], docker?.clientDir);
6168
+ const [tunnel, ...innerTunnels] = [route.tunnel, daemon.tunnel].filter((script) => script !== undefined);
6169
+ const tunnelled = innerTunnels.reduceRight((inner, script) => `sh -c ${quoted(script)} sh ${quoted(inner)}`, command);
5863
6170
  const sandboxCommand = {
5864
- argv: route.tunnel === undefined ? ["sh", "-c", command] : ["sh", "-c", route.tunnel, "sh", command],
6171
+ argv: tunnel === undefined ? ["sh", "-c", command] : ["sh", "-c", tunnel, "sh", tunnelled],
5865
6172
  cwd,
5866
6173
  env: {
5867
6174
  ...env,
5868
6175
  KITMAN_CHECK_SANDBOX: sandbox.backend,
5869
- ...route.url === undefined ? undefined : { POSTGRES_URL: route.url }
6176
+ ...route.url === undefined ? undefined : { POSTGRES_URL: route.url },
6177
+ ...daemon.env
5870
6178
  },
5871
6179
  timeout: checkTimeout,
5872
6180
  ...output
@@ -5875,7 +6183,7 @@ var checkRunner = (work, sandbox, cache, inherited) => (checkout) => ({ command,
5875
6183
  backend: "srt",
5876
6184
  policy,
5877
6185
  command: { ...sandboxCommand, env: { ...inherited, ...sandboxCommand.env }, extendEnv: false },
5878
- unixSockets: route.unixSockets,
6186
+ unixSockets: [...route.unixSockets, ...daemon.unixSockets],
5879
6187
  ...sandbox.srtCommand === undefined ? undefined : { srtCommand: sandbox.srtCommand }
5880
6188
  }) : runSandboxCommand({
5881
6189
  backend: "docker",
@@ -5885,7 +6193,7 @@ var checkRunner = (work, sandbox, cache, inherited) => (checkout) => ({ command,
5885
6193
  readOnlyPaths: [repositoryClone(sandbox.runner.workRoot, work.repoBinding.id)],
5886
6194
  policy,
5887
6195
  command: sandboxCommand,
5888
- services: route.services
6196
+ services: [...route.services, ...daemon.services]
5889
6197
  });
5890
6198
  };
5891
6199
  var regularFiles = (dir) => gen(function* () {
@@ -5939,6 +6247,38 @@ var checkoutPostgres = (worktree, services) => gen(function* () {
5939
6247
  });
5940
6248
  return yield* services.postgres(services.id).pipe(mapError2((error) => new ServicesUnavailable({ reason: error.message })));
5941
6249
  });
6250
+ var decodeListeningPort = decodeUnknownEffect2(Struct({ port: Finite }));
6251
+ var pipelineDaemon = (services, check) => gen(function* () {
6252
+ if (services.docker === undefined)
6253
+ return yield* new ServicesUnavailable({
6254
+ reason: `The pipeline check ${check} runs with a Docker daemon of its own, and this Runner cannot start one: set KITMAN_RUNNER_CHECK_DOCKER_IMAGE to a docker:*-dind-rootless image and KITMAN_RUNNER_CHECK_REGISTRY_IMAGE to a registry:3 image, each pinned by digest.`
6255
+ });
6256
+ const fs = yield* FileSystem;
6257
+ const started = yield* services.docker({ id: services.id, network: services.network }).pipe(mapError2((error) => new ServicesUnavailable({ reason: error.message })));
6258
+ const clientDir = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-check-docker-" });
6259
+ yield* fs.makeDirectory(`${clientDir}/docker`);
6260
+ yield* fs.makeDirectory(`${clientDir}/gitlab-ci-local-home`);
6261
+ yield* fs.writeFileString(`${clientDir}/docker/config.json`, encodeUnknownJsonStringSync(checkDockerClientConfig(started.proxy)));
6262
+ if (services.backend !== "srt")
6263
+ return { ...started, clientDir, route: { kind: "direct" } };
6264
+ if (services.platform !== "darwin") {
6265
+ const relay = yield* acquireRelease(promise(() => startHalfCloseDecoder({ port: 0, targetPort: started.hostPort })), (server) => sync2(() => server.close()));
6266
+ const { port } = yield* decodeListeningPort(relay.address()).pipe(mapError2(() => new ServicesUnavailable({
6267
+ reason: `The pipeline check ${check} cannot reach its Docker daemon: its relay has no port`
6268
+ })));
6269
+ return { ...started, clientDir, route: { kind: "relay", port } };
6270
+ }
6271
+ return {
6272
+ ...started,
6273
+ clientDir,
6274
+ route: {
6275
+ kind: "socket",
6276
+ dir: yield* loopbackSocketForwarder(started.hostPort, "docker.sock").pipe(mapError2((error) => new ServicesUnavailable({
6277
+ reason: `The pipeline check ${check} cannot reach its Docker daemon: ${error.reason}`
6278
+ })))
6279
+ }
6280
+ };
6281
+ });
5942
6282
  var reachCheckPostgres = (postgres, services, worktree, run) => gen(function* () {
5943
6283
  if (services.backend !== "srt")
5944
6284
  return postgres;
@@ -5987,11 +6327,13 @@ var runChecks = (worktree, checks, tree, known, run, keeper, services) => gen(fu
5987
6327
  const filesDir = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-check-files-" });
5988
6328
  const output = path.join(yield* fs.makeTempDirectoryScoped({ prefix: "kitman-check-output-" }), "output");
5989
6329
  const sink = keeper === undefined ? undefined : yield* fs.open(output, { flag: "w" });
6330
+ const docker = check.pipeline === true ? yield* pipelineDaemon(services, check.name) : undefined;
5990
6331
  const ran = yield* run({
5991
6332
  command: check.command,
5992
6333
  cwd: path.join(worktree, check.workingDirectory ?? "."),
5993
6334
  filesDir,
5994
6335
  ...postgres === undefined ? undefined : { postgres },
6336
+ ...docker === undefined ? undefined : { docker },
5995
6337
  ...sink === undefined ? undefined : { onOutput: (chunk) => sink.writeAll(chunk) }
5996
6338
  });
5997
6339
  const durationMs = (yield* currentTimeMillis) - startedAt;
@@ -6090,6 +6432,27 @@ var measureRevisions = (work, measure, checkouts, runIn) => gen(function* () {
6090
6432
  }
6091
6433
  };
6092
6434
  });
6435
+ var ownRepository = (worktree, clone, targetBranch) => gen(function* () {
6436
+ const fs = yield* FileSystem;
6437
+ const path = yield* Path;
6438
+ const scratch = yield* fs.makeTempDirectoryScoped({
6439
+ directory: path.dirname(worktree),
6440
+ prefix: "kitman-check-git-"
6441
+ });
6442
+ const gitDir = path.join(scratch, "git");
6443
+ const git = (...args) => runCommand2("git", ["--git-dir", gitDir, ...args]);
6444
+ const revision = (yield* runCommand2("git", ["-C", worktree, "rev-parse", "HEAD"])).trim();
6445
+ const originUrl = (yield* runCommand2("git", ["-C", clone, "config", "--get", "remote.origin.url"])).trim();
6446
+ yield* runCommand2("git", ["clone", "--quiet", "--bare", "--no-hardlinks", clone, gitDir]);
6447
+ yield* git("fetch", "--quiet", clone, "+refs/remotes/origin/*:refs/remotes/origin/*");
6448
+ yield* git("config", "core.bare", "false");
6449
+ yield* git("remote", "set-url", "origin", originUrl);
6450
+ yield* git("symbolic-ref", "refs/remotes/origin/HEAD", `refs/remotes/origin/${targetBranch}`);
6451
+ yield* git("update-ref", "--no-deref", "HEAD", revision);
6452
+ yield* fs.remove(path.join(worktree, ".git"));
6453
+ yield* fs.rename(gitDir, path.join(worktree, ".git"));
6454
+ yield* runCommand2("git", ["-C", worktree, "reset", "--quiet"]);
6455
+ }).pipe(scoped);
6093
6456
  var treeOf = (worktree) => map8(runCommand2("git", ["-C", worktree, "rev-parse", "HEAD^{tree}"]), (tree) => tree.trim());
6094
6457
  var verificationExecutor = (input) => (work) => gen(function* () {
6095
6458
  if (input.sandbox !== undefined && input.sandbox.backend === undefined)
@@ -6115,15 +6478,22 @@ var verificationExecutor = (input) => (work) => gen(function* () {
6115
6478
  }, work.repoBinding);
6116
6479
  const pipelineOnly = work.checks.every((check) => check.pipeline === true);
6117
6480
  const baseline = pipelineOnly ? head : yield* baselineAt(work.baseline).pipe(catch_(() => baselineAt()));
6481
+ if (work.checks.some((check) => check.pipeline === true))
6482
+ yield* ownRepository(head, repositoryClone(input.rootDir, work.repoBinding.id), work.repoBinding.defaultTargetBranch);
6118
6483
  const headTree = yield* treeOf(head);
6119
6484
  const baselineTree = yield* treeOf(baseline);
6120
6485
  const trees = headTree === baselineTree ? [headTree] : [headTree, baselineTree];
6121
6486
  const known = yield* input.known(work, trees);
6487
+ const sandbox = input.sandbox;
6488
+ const checkNetwork = sandbox === undefined || sandbox.backend === undefined ? "open" : checkSandboxPolicy(work, sandbox, head, cache, cache, []).network;
6489
+ const daemonNetwork = checkNetwork === "open" ? "open" : { hosts: checkNetwork.hosts };
6122
6490
  const services = (id) => ({
6123
6491
  id,
6124
6492
  backend: input.sandbox?.backend,
6125
6493
  platform: (input.sandbox?.backend === "srt" ? input.sandbox.platform : undefined) ?? process.platform,
6126
- postgres: input.postgres
6494
+ postgres: input.postgres,
6495
+ docker: input.docker,
6496
+ network: daemonNetwork
6127
6497
  });
6128
6498
  const headChecks = yield* runChecks(head, work.checks, headTree, known, runIn(head), keeper(""), services(work.id)).pipe(scoped);
6129
6499
  return {
@@ -6138,7 +6508,7 @@ var verificationExecutor = (input) => (work) => gen(function* () {
6138
6508
  baseline: {
6139
6509
  revision: (yield* runCommand2("git", ["-C", baseline, "rev-parse", "HEAD"])).trim(),
6140
6510
  tree: baselineTree,
6141
- checks: yield* runChecks(baseline, work.checks, baselineTree, known, runIn(baseline), keeper("baseline-"), services(`${work.id}-baseline`)).pipe(scoped)
6511
+ checks: yield* runChecks(baseline, work.checks.filter((check) => check.pipeline !== true), baselineTree, known, runIn(baseline), keeper("baseline-"), services(`${work.id}-baseline`)).pipe(scoped)
6142
6512
  }
6143
6513
  }
6144
6514
  }
@@ -6162,11 +6532,13 @@ export {
6162
6532
  AgentRuntimePackageName,
6163
6533
  AgentStepFailure,
6164
6534
  BundleRefused,
6535
+ CheckDockerUnavailable,
6165
6536
  CheckPostgresImage,
6166
6537
  CheckPostgresUnavailable,
6167
6538
  CommandFailed2 as CommandFailed,
6168
6539
  CommandRunner2 as CommandRunner,
6169
6540
  ContainerError,
6541
+ DockerHubRegistry,
6170
6542
  EgressProxyImage,
6171
6543
  HERDR_CORE_GENERATION2 as HERDR_CORE_GENERATION,
6172
6544
  HERDR_CORE_INSTALL_COMMAND2 as HERDR_CORE_INSTALL_COMMAND,
@@ -6190,11 +6562,18 @@ export {
6190
6562
  applyAgentEnvironmentMaterialization2 as applyAgentEnvironmentMaterialization,
6191
6563
  applyAgentEnvironmentPlans,
6192
6564
  assertHerdrRunnerCapability2 as assertHerdrRunnerCapability,
6565
+ checkDockerAlias,
6566
+ checkDockerClientConfig,
6567
+ checkDockerDaemonArgs,
6568
+ checkDockerPort,
6569
+ checkDockerProxyEnvironment,
6193
6570
  checkPostgresAlias,
6194
6571
  checkPostgresSandboxPort,
6195
6572
  checkPostgresSocketUrl,
6196
6573
  checkPostgresSweepInterval,
6197
6574
  checkPostgresUrl,
6575
+ checkRegistryCacheVolume,
6576
+ checkRegistryMirrorArgs,
6198
6577
  clearSettledCheckpoints,
6199
6578
  commandHostProbe,
6200
6579
  compiled2 as compiled,
@@ -6202,6 +6581,7 @@ export {
6202
6581
  controlFailureKind,
6203
6582
  defaultAgentRuntimeUserConfigPath,
6204
6583
  detectHarnesses2 as detectHarnesses,
6584
+ dockerCheckDaemon,
6205
6585
  dockerCheckPostgres,
6206
6586
  dockerContainerRunner,
6207
6587
  dockerExecArgv,
@@ -6239,6 +6619,7 @@ export {
6239
6619
  liveReplicaIds,
6240
6620
  loadAgentRuntimeConfig,
6241
6621
  makeReplicaSignals,
6622
+ orphanedCheckDocker,
6242
6623
  orphanedCheckPostgres,
6243
6624
  pinnedSrtCommand2 as pinnedSrtCommand,
6244
6625
  pinnedSrtStepCommand2 as pinnedSrtStepCommand,
@@ -6253,6 +6634,7 @@ export {
6253
6634
  publishedPort,
6254
6635
  readManifestSkillPaths2 as readManifestSkillPaths,
6255
6636
  refuseAgentRequest,
6637
+ removeCheckDocker,
6256
6638
  removeCheckPostgres,
6257
6639
  removeRunnerContainers,
6258
6640
  removeRunnerTerminals,