@rallycry/conveyor-agent 10.13.18 → 10.13.50

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 (39) hide show
  1. package/dist/{boot-YZCOIV3Q.js → boot-I353EAK6.js} +156 -125
  2. package/dist/boot-I353EAK6.js.map +1 -0
  3. package/dist/{chunk-3GDXX3OX.js → chunk-36VMMHYD.js} +5578 -2111
  4. package/dist/chunk-36VMMHYD.js.map +1 -0
  5. package/dist/{chunk-AGGVNADW.js → chunk-3Z4YQNJV.js} +59 -13
  6. package/dist/chunk-3Z4YQNJV.js.map +1 -0
  7. package/dist/chunk-5OQQSDVT.js +142 -0
  8. package/dist/chunk-5OQQSDVT.js.map +1 -0
  9. package/dist/{chunk-UZTJJD7Y.js → chunk-KCB7CSWJ.js} +43 -2
  10. package/dist/chunk-KCB7CSWJ.js.map +1 -0
  11. package/dist/{chunk-UDSRAHKP.js → chunk-QOJTJCYZ.js} +67 -19
  12. package/dist/chunk-QOJTJCYZ.js.map +1 -0
  13. package/dist/chunk-ULS4QPRE.js +138 -0
  14. package/dist/chunk-ULS4QPRE.js.map +1 -0
  15. package/dist/{chunk-72AEN6LB.js → chunk-XR6H326I.js} +26 -2
  16. package/dist/chunk-XR6H326I.js.map +1 -0
  17. package/dist/cli.js +196 -334
  18. package/dist/cli.js.map +1 -1
  19. package/dist/{client-BU4XA7CV.js → client-LRVVHTNG.js} +2 -2
  20. package/dist/heartbeat-worker.js +10 -12
  21. package/dist/heartbeat-worker.js.map +1 -1
  22. package/dist/index.d.ts +153 -8
  23. package/dist/index.js +5 -5
  24. package/dist/oom-watchdog-U7JERHA2.js +11 -0
  25. package/dist/server-NIOBJ46G.js +10 -0
  26. package/dist/server-NIOBJ46G.js.map +1 -0
  27. package/package.json +3 -3
  28. package/runtime/entrypoint.sh +5 -4
  29. package/dist/boot-YZCOIV3Q.js.map +0 -1
  30. package/dist/chunk-3GDXX3OX.js.map +0 -1
  31. package/dist/chunk-72AEN6LB.js.map +0 -1
  32. package/dist/chunk-7TQO4ZF4.js +0 -60
  33. package/dist/chunk-7TQO4ZF4.js.map +0 -1
  34. package/dist/chunk-AGGVNADW.js.map +0 -1
  35. package/dist/chunk-UDSRAHKP.js.map +0 -1
  36. package/dist/chunk-UZTJJD7Y.js.map +0 -1
  37. package/dist/server-BXAFMYDM.js +0 -9
  38. /package/dist/{client-BU4XA7CV.js.map → client-LRVVHTNG.js.map} +0 -0
  39. /package/dist/{server-BXAFMYDM.js.map → oom-watchdog-U7JERHA2.js.map} +0 -0
@@ -7,22 +7,26 @@ import {
7
7
  defaultGit,
8
8
  ensureDir,
9
9
  readAgentVersion,
10
- redactToken
11
- } from "./chunk-UZTJJD7Y.js";
10
+ redactToken,
11
+ reportBootMilestone
12
+ } from "./chunk-KCB7CSWJ.js";
12
13
  import {
13
14
  workbenchPort
14
15
  } from "./chunk-4VUQ2NPF.js";
15
16
  import {
16
17
  startWorkbenchServer
17
- } from "./chunk-AGGVNADW.js";
18
- import "./chunk-72AEN6LB.js";
18
+ } from "./chunk-3Z4YQNJV.js";
19
+ import "./chunk-XR6H326I.js";
19
20
  import {
20
21
  DEFAULT_WORKBENCH_PORT
21
22
  } from "./chunk-JIGG755T.js";
23
+ import {
24
+ oomWatchdogOptionsFromEnv
25
+ } from "./chunk-ULS4QPRE.js";
22
26
 
23
27
  // src/boot/index.ts
24
28
  import { spawn } from "child_process";
25
- import { statSync as statSync3 } from "fs";
29
+ import { statSync as statSync4 } from "fs";
26
30
  import { hostname as osHostname } from "os";
27
31
 
28
32
  // src/boot/bundle.ts
@@ -262,96 +266,17 @@ async function pollBootstrapBundle(apiUrl, token, deps) {
262
266
  }
263
267
  }
264
268
 
265
- // src/boot/self-update.ts
269
+ // src/boot/exec.ts
266
270
  import { execFile } from "child_process";
267
271
  import { promisify } from "util";
268
- var AGENT_PACKAGE = "@rallycry/conveyor-agent";
269
- var NPM_VIEW_TIMEOUT_MS = 3e3;
270
- var NPM_INSTALL_TIMEOUT_MS = 12e4;
271
- var NPM_CACHE_DIR = "/tmp/npm-cache";
272
- var NPM_REGISTRY_ARG = "--@rallycry:registry=https://registry.npmjs.org/";
273
- var SEMVER_RE = /^\d+\.\d+\.\d+([-+][A-Za-z0-9.-]+)?$/;
274
- function isValidSemver(value) {
275
- return SEMVER_RE.test(value);
276
- }
277
- function isStrictlyNewer(candidate, installed) {
278
- const num = (v) => (v.split(/[-+]/)[0] ?? "").split(".").map((p) => Number(p));
279
- const [a, b] = [num(candidate), num(installed)];
280
- for (let i = 0; i < 3; i++) {
281
- const av = a[i] ?? 0;
282
- const bv = b[i] ?? 0;
283
- if (av !== bv) return av > bv;
284
- }
285
- return false;
286
- }
287
272
  var execFileAsync = promisify(execFile);
288
273
  function defaultExec(cmd, args, opts) {
289
274
  return execFileAsync(cmd, args, { timeout: opts.timeoutMs });
290
275
  }
291
- async function runPreflightUpdate(deps) {
292
- let latest = "";
293
- try {
294
- const { stdout } = await deps.exec(
295
- "npm",
296
- ["view", "--cache", NPM_CACHE_DIR, NPM_REGISTRY_ARG, AGENT_PACKAGE, "version"],
297
- { timeoutMs: NPM_VIEW_TIMEOUT_MS }
298
- );
299
- latest = stdout.replace(/\s+/g, "");
300
- } catch (err) {
301
- deps.log.warn(
302
- `[boot] WARN preflight npm view failed (${err instanceof Error ? err.message : err}); keeping baked version`
303
- );
304
- return "skipped";
305
- }
306
- if (!isValidSemver(latest)) {
307
- deps.log.warn(
308
- `[boot] WARN preflight got non-semver '${latest}' from npm; keeping baked version`
309
- );
310
- return "skipped";
311
- }
312
- let installed = "";
313
- try {
314
- installed = (await deps.installedVersion()).trim();
315
- } catch (err) {
316
- deps.log.warn(
317
- `[boot] WARN preflight installed-version lookup failed (${err instanceof Error ? err.message : err}); keeping baked version`
318
- );
319
- return "skipped";
320
- }
321
- if (!isValidSemver(installed) || isStrictlyNewer(latest, installed)) {
322
- deps.log.info(
323
- `[boot] preflight updating ${AGENT_PACKAGE} ${installed || "unknown"} -> ${latest}`
324
- );
325
- try {
326
- await deps.exec(
327
- "sudo",
328
- [
329
- "npm",
330
- "install",
331
- "-g",
332
- "--cache",
333
- NPM_CACHE_DIR,
334
- "--silent",
335
- `${AGENT_PACKAGE}@${latest}`
336
- ],
337
- { timeoutMs: NPM_INSTALL_TIMEOUT_MS }
338
- );
339
- await deps.exec("sudo", ["rm", "-rf", NPM_CACHE_DIR], { timeoutMs: NPM_VIEW_TIMEOUT_MS }).catch(() => void 0);
340
- return "updated";
341
- } catch (err) {
342
- deps.log.warn(
343
- `[boot] WARN preflight install failed (${err instanceof Error ? err.message : err}); keeping baked version`
344
- );
345
- return "skipped";
346
- }
347
- }
348
- deps.log.info(`[boot] preflight agent ${installed} is current (registry ${latest})`);
349
- return "current";
350
- }
351
276
 
352
277
  // src/boot/supervisor.ts
353
278
  import { spawn as spawnChildProcess } from "child_process";
354
- import { appendFileSync as appendFileSync2, writeFileSync } from "fs";
279
+ import { appendFileSync as appendFileSync2, statSync, writeFileSync } from "fs";
355
280
  import { join } from "path";
356
281
 
357
282
  // src/boot/crash-report.ts
@@ -378,6 +303,7 @@ async function reportAgentCrash(apiUrl, bootstrapToken, report, fetchFn = fetch)
378
303
  // src/boot/supervisor.ts
379
304
  var AGENT_CRASH_MAX = 3;
380
305
  var AGENT_LOG_PATH = "/tmp/claudespace-agent.log";
306
+ var AGENT_LOG_MAX_BYTES = 16 * 1024 * 1024;
381
307
  var LAUNCH_MARKER_NAME = "conveyor-agent-launching";
382
308
  var RESTARTING_MARKER_NAME = "conveyor-agent-restarting";
383
309
  var LAUNCH_MARKER = `/tmp/${LAUNCH_MARKER_NAME}`;
@@ -394,14 +320,31 @@ function touchMarker(path, log) {
394
320
  );
395
321
  }
396
322
  }
397
- function teeChildOutput(child) {
398
- const onData = (chunk) => {
399
- process.stdout.write(chunk);
323
+ function createLogAppender(path, maxBytes) {
324
+ let size = 0;
325
+ try {
326
+ size = statSync(path).size;
327
+ } catch {
328
+ size = 0;
329
+ }
330
+ return (chunk) => {
400
331
  try {
401
- appendFileSync2(AGENT_LOG_PATH, chunk);
332
+ if (size + chunk.length > maxBytes) {
333
+ writeFileSync(path, chunk);
334
+ size = chunk.length;
335
+ } else {
336
+ appendFileSync2(path, chunk);
337
+ size += chunk.length;
338
+ }
402
339
  } catch {
403
340
  }
404
341
  };
342
+ }
343
+ function teeChildOutput(child, appendLog) {
344
+ const onData = (chunk) => {
345
+ process.stdout.write(chunk);
346
+ appendLog(chunk);
347
+ };
405
348
  child.stdout?.on("data", onData);
406
349
  child.stderr?.on("data", onData);
407
350
  }
@@ -475,12 +418,13 @@ async function superviseRunner(opts) {
475
418
  const launchMarkerPath = join(markerDir, LAUNCH_MARKER_NAME);
476
419
  const restartingMarkerPath = join(markerDir, RESTARTING_MARKER_NAME);
477
420
  touchMarker(launchMarkerPath, opts.log);
421
+ const appendLog = createLogAppender(AGENT_LOG_PATH, AGENT_LOG_MAX_BYTES);
478
422
  let attempt = 0;
479
423
  while (true) {
480
424
  attempt++;
481
425
  opts.log.info("[boot] Launching agent...");
482
426
  const child = spawnAgent(spawnFn, opts);
483
- teeChildOutput(child);
427
+ teeChildOutput(child, appendLog);
484
428
  const exitPromise = waitForExit(child);
485
429
  const winner = await Promise.race([
486
430
  exitPromise.then((code) => ({ type: "exit", code })),
@@ -517,11 +461,13 @@ async function superviseRunner(opts) {
517
461
  import {
518
462
  chmodSync,
519
463
  copyFileSync,
464
+ existsSync,
520
465
  lstatSync,
521
466
  mkdirSync,
522
467
  readFileSync,
468
+ readdirSync,
523
469
  rmSync,
524
- statSync,
470
+ statSync as statSync2,
525
471
  symlinkSync,
526
472
  writeFileSync as writeFileSync2
527
473
  } from "fs";
@@ -575,7 +521,7 @@ function seedClaudeJson(targetPath) {
575
521
  }
576
522
  function isDir(path) {
577
523
  try {
578
- return statSync(path).isDirectory();
524
+ return statSync2(path).isDirectory();
579
525
  } catch {
580
526
  return false;
581
527
  }
@@ -609,6 +555,29 @@ function wireCredentials(opts) {
609
555
  safely(log, "repoint credentials symlink", () => relink(podLocal, shared));
610
556
  safely(log, "chmod pod-local credentials", () => chmodSync(podLocal, 384));
611
557
  }
558
+ var AGENT_MEMORY_PROJECT_DIR = "-workspaces-repo";
559
+ function migrateMemories(from, to, log) {
560
+ let entries;
561
+ try {
562
+ entries = readdirSync(from);
563
+ } catch {
564
+ return;
565
+ }
566
+ for (const entry of entries) {
567
+ const target = join2(to, entry);
568
+ if (existsSync(target)) continue;
569
+ safely(log, `migrate memory ${entry}`, () => copyFileSync(join2(from, entry), target));
570
+ }
571
+ }
572
+ function wireSharedMemory(root, userHomeMount, projectId, log) {
573
+ const shared = join2(userHomeMount, "users", "_shared", "memory", projectId);
574
+ const link = join2(root, ".claude", "projects", AGENT_MEMORY_PROJECT_DIR, "memory");
575
+ safely(log, "mkdir shared memory dir", () => mkdirSync(shared, { recursive: true }));
576
+ safely(log, "migrate per-user memories", () => {
577
+ if (existsSync(link) && !lstatSync(link).isSymbolicLink()) migrateMemories(link, shared, log);
578
+ });
579
+ safely(log, "wire shared memory symlink", () => relink(shared, link));
580
+ }
612
581
  function wireMountedUserHome(opts) {
613
582
  const { home, userHomeMount, userId, projectId, sharedDir, log } = opts;
614
583
  const root = join2(userHomeMount, "users", userId, projectId);
@@ -626,6 +595,7 @@ function wireMountedUserHome(opts) {
626
595
  rmSync(join2(home, ".claude.json"), { recursive: true, force: true });
627
596
  seedClaudeJson(join2(home, ".claude.json"));
628
597
  });
598
+ wireSharedMemory(root, userHomeMount, projectId, log);
629
599
  wireCredentials({ home, root, sharedDir, log });
630
600
  safely(log, "mkdir opencode root", () => {
631
601
  mkdirSync(join2(root, ".local", "share", "opencode"), { recursive: true });
@@ -659,6 +629,11 @@ function wireNoMountUserHome(opts) {
659
629
  }
660
630
  function wireUserHome(opts) {
661
631
  const { home, userHomeMount, userId, projectId, sharedDir, log } = opts;
632
+ safely(
633
+ log,
634
+ "mkdir agent scratch dir",
635
+ () => mkdirSync(opts.scratchDir ?? "/tmp/claude-cmd", { recursive: true })
636
+ );
662
637
  if (userId && projectId && isDir(userHomeMount)) {
663
638
  wireMountedUserHome({ home, userHomeMount, userId, projectId, sharedDir, log });
664
639
  } else {
@@ -696,15 +671,27 @@ async function reclaimHomeOwnership(home, exec, log) {
696
671
  }
697
672
 
698
673
  // src/boot/sshd.ts
699
- import { chmodSync as chmodSync2, closeSync, existsSync, mkdirSync as mkdirSync2, openSync } from "fs";
674
+ import { chmodSync as chmodSync2, closeSync, copyFileSync as copyFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, openSync } from "fs";
700
675
  import { join as join3 } from "path";
676
+ function persistedAuthorizedKeys() {
677
+ return join3(
678
+ process.env.CONVEYOR_SHARED_DIR || "/var/run/conveyor-workbench",
679
+ "ssh",
680
+ "authorized_keys"
681
+ );
682
+ }
701
683
  async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPACE_SSH_PORT || "2222", home = "/home/conveyor") {
702
684
  try {
703
685
  const sshDir = join3(home, ".ssh");
704
686
  mkdirSync2(sshDir, { recursive: true });
705
687
  chmodSync2(sshDir, 448);
706
688
  const authorizedKeys = join3(sshDir, "authorized_keys");
707
- if (!existsSync(authorizedKeys)) closeSync(openSync(authorizedKeys, "a"));
689
+ const persisted = persistedAuthorizedKeys();
690
+ if (existsSync2(persisted)) {
691
+ copyFileSync2(persisted, authorizedKeys);
692
+ } else if (!existsSync2(authorizedKeys)) {
693
+ closeSync(openSync(authorizedKeys, "a"));
694
+ }
708
695
  chmodSync2(authorizedKeys, 384);
709
696
  } catch (err) {
710
697
  log.warn(
@@ -712,7 +699,7 @@ async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPA
712
699
  );
713
700
  return;
714
701
  }
715
- if (!existsSync("/usr/sbin/sshd")) {
702
+ if (!existsSync2("/usr/sbin/sshd")) {
716
703
  log.warn("[boot] WARN: workspace SSHD unavailable");
717
704
  return;
718
705
  }
@@ -729,12 +716,15 @@ async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPA
729
716
 
730
717
  // src/boot/workspace-extras.ts
731
718
  import {
732
- existsSync as existsSync2,
719
+ appendFileSync as appendFileSync3,
720
+ existsSync as existsSync3,
733
721
  lstatSync as lstatSync2,
734
722
  mkdirSync as mkdirSync3,
735
- readdirSync,
723
+ readdirSync as readdirSync2,
724
+ readFileSync as readFileSync2,
725
+ readlinkSync,
736
726
  rmSync as rmSync2,
737
- statSync as statSync2,
727
+ statSync as statSync3,
738
728
  symlinkSync as symlinkSync2
739
729
  } from "fs";
740
730
  import { join as join4 } from "path";
@@ -743,7 +733,7 @@ function errText(err) {
743
733
  }
744
734
  function isDir2(path) {
745
735
  try {
746
- return statSync2(path).isDirectory();
736
+ return statSync3(path).isDirectory();
747
737
  } catch {
748
738
  return false;
749
739
  }
@@ -769,7 +759,7 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
769
759
  const sourceDir = graphifyEnv.CONVEYOR_GRAPHIFY_DIR;
770
760
  const graphFile = graphifyEnv.CONVEYOR_GRAPHIFY_GRAPH;
771
761
  if (!slug || !sourceDir || !graphFile) return;
772
- if (!existsSync2(graphFile)) {
762
+ if (!existsSync3(graphFile)) {
773
763
  log.info(`[boot] Graphify bundle not found for '${slug}' at ${sourceDir}`);
774
764
  return;
775
765
  }
@@ -783,8 +773,8 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
783
773
  for (const rel of GRAPHIFY_BUNDLE_FILES) {
784
774
  const source = join4(sourceDir, rel);
785
775
  const target = join4(targetDir, rel);
786
- if (!existsSync2(source)) continue;
787
- if (existsSync2(target) || isSymlink(target)) continue;
776
+ if (!existsSync3(source)) continue;
777
+ if (existsSync3(target) || isSymlink(target)) continue;
788
778
  try {
789
779
  symlinkSync2(source, target);
790
780
  } catch {
@@ -794,7 +784,7 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
794
784
  }
795
785
  async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
796
786
  try {
797
- if (!existsSync2(join4(workspace, ".gitmodules"))) return;
787
+ if (!existsSync3(join4(workspace, ".gitmodules"))) return;
798
788
  let paths = "";
799
789
  try {
800
790
  ({ stdout: paths } = await git(
@@ -832,6 +822,30 @@ async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
832
822
  log.warn(`[boot] WARN: grimoire submodule check failed: ${errText(err)}`);
833
823
  }
834
824
  }
825
+ function excludeLinkedSkills(workspace, names, log) {
826
+ if (names.length === 0) return;
827
+ const infoDir = join4(workspace, ".git", "info");
828
+ if (!isDir2(join4(workspace, ".git"))) return;
829
+ try {
830
+ mkdirSync3(infoDir, { recursive: true });
831
+ const excludePath = join4(infoDir, "exclude");
832
+ const existing = existsSync3(excludePath) ? readFileSync2(excludePath, "utf8") : "";
833
+ const missing = names.map((name) => `.claude/skills/${name}`).filter((line) => !existing.split("\n").includes(line));
834
+ if (missing.length === 0) return;
835
+ const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
836
+ appendFileSync3(excludePath, `${prefix}${missing.join("\n")}
837
+ `);
838
+ } catch (err) {
839
+ log.warn(`[boot] WARN: unable to exclude grimoire skill links: ${errText(err)}`);
840
+ }
841
+ }
842
+ function symlinkTargetsGrimoire(path) {
843
+ try {
844
+ return readlinkSync(path).includes(join4("grimoire", "skills"));
845
+ } catch {
846
+ return false;
847
+ }
848
+ }
835
849
  function linkGrimoireSkills(workspace, log) {
836
850
  const sourceDir = join4(workspace, ".claude", "grimoire", "skills");
837
851
  const targetDir = join4(workspace, ".claude", "skills");
@@ -842,28 +856,42 @@ function linkGrimoireSkills(workspace, log) {
842
856
  log.warn(`[boot] WARN: unable to create ${targetDir}; skipping grimoire skill links`);
843
857
  return;
844
858
  }
845
- let linked = 0;
859
+ const linkedNames = [];
846
860
  let names = [];
847
861
  try {
848
- names = readdirSync(sourceDir);
862
+ names = readdirSync2(sourceDir);
849
863
  } catch {
850
864
  return;
851
865
  }
852
866
  for (const name of names) {
853
867
  if (!isDir2(join4(sourceDir, name))) continue;
854
868
  const target = join4(targetDir, name);
855
- if (existsSync2(target) && !isSymlink(target)) {
869
+ if (existsSync3(target) && !isSymlink(target)) {
856
870
  log.warn(`[boot] WARN: ${target} exists and is not a symlink; skipping`);
857
871
  continue;
858
872
  }
873
+ if (isSymlink(target) && !symlinkTargetsGrimoire(target)) continue;
859
874
  try {
860
875
  rmSync2(target, { force: true });
861
876
  symlinkSync2(join4("..", "grimoire", "skills", name), target);
862
- linked++;
877
+ linkedNames.push(name);
863
878
  } catch {
864
879
  }
865
880
  }
866
- log.info(`[boot] Linked ${linked} grimoire skills into ${targetDir}`);
881
+ excludeLinkedSkills(workspace, linkedNames, log);
882
+ log.info(`[boot] Linked ${linkedNames.length} grimoire skills into ${targetDir}`);
883
+ }
884
+ async function neutralizeGrimoirePointer(workspace, git, log) {
885
+ if (!existsSync3(join4(workspace, ".claude", "grimoire"))) return;
886
+ try {
887
+ await git(["update-index", "--assume-unchanged", ".claude/grimoire"], {
888
+ cwd: workspace,
889
+ timeoutMs: 1e4
890
+ });
891
+ log.info("[boot] Marked .claude/grimoire assume-unchanged (submodule pointer drift is noise)");
892
+ } catch (err) {
893
+ log.warn(`[boot] WARN: grimoire assume-unchanged failed: ${errText(err)}`);
894
+ }
867
895
  }
868
896
  function parseReferenceRepos(refsJson) {
869
897
  let parsed;
@@ -894,6 +922,7 @@ async function runPreReadyBinds(workspace, bundle, git, log) {
894
922
  bindGraphifyBundle(workspace, graphifyEnv, log);
895
923
  await ensureGrimoireSubmodule(workspace, bundle.githubToken, git, log);
896
924
  linkGrimoireSkills(workspace, log);
925
+ await neutralizeGrimoirePointer(workspace, git, log);
897
926
  }
898
927
  async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspaces/references") {
899
928
  if (!refsJson) return;
@@ -906,7 +935,7 @@ async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspa
906
935
  }
907
936
  for (const ref of refs) {
908
937
  const dest = join4(referencesDir, ref.slug);
909
- if (existsSync2(join4(dest, ".git"))) continue;
938
+ if (existsSync3(join4(dest, ".git"))) continue;
910
939
  try {
911
940
  await git(
912
941
  [
@@ -1015,16 +1044,22 @@ async function runWorkbenchBoot(ctx, overrides = {}) {
1015
1044
  const job = new GitPrepJob(deps.gitPrepDeps(ctx, bundle), {
1016
1045
  // Order pinned by the old entrypoint-grimoire test: binds BEFORE the
1017
1046
  // ready flip (Claude must not spawn before skills exist), references after.
1018
- onReady: () => deps.bindsBeforeReady(ctx, bundle),
1047
+ onReady: () => {
1048
+ const binds = deps.bindsBeforeReady(ctx, bundle);
1049
+ void reportBootMilestone({ key: "repo_synced" });
1050
+ return binds;
1051
+ },
1019
1052
  afterReady: () => deps.cloneReferences(ctx, bundle)
1020
1053
  });
1021
1054
  await deps.startDaemon({
1022
1055
  port: workbenchPort() ?? DEFAULT_WORKBENCH_PORT,
1023
1056
  token: ctx.bootstrapToken,
1024
1057
  version: readAgentVersion() ?? "unknown",
1025
- getGitStatus: () => toGitStatusFrame(job.status)
1058
+ getGitStatus: () => toGitStatusFrame(job.status),
1059
+ oomWatchdog: oomWatchdogOptionsFromEnv(ctx.log)
1026
1060
  });
1027
1061
  ctx.log.info("[boot] step=startDaemon listen socket up (startupProbe gate open)");
1062
+ void reportBootMilestone({ key: "workbench_ready" });
1028
1063
  try {
1029
1064
  deps.ensureWorkspaceDir(ctx);
1030
1065
  } catch (err) {
@@ -1052,13 +1087,9 @@ function defaultBootDeps() {
1052
1087
  }),
1053
1088
  spawnFn: spawn,
1054
1089
  exec: defaultExec,
1055
- installedVersion: () => {
1056
- const version = readAgentVersion();
1057
- return version ? Promise.resolve(version) : Promise.reject(new Error("could not read installed agent version"));
1058
- },
1059
1090
  dirExists: (path) => {
1060
1091
  try {
1061
- return statSync3(path).isDirectory();
1092
+ return statSync4(path).isDirectory();
1062
1093
  } catch {
1063
1094
  return false;
1064
1095
  }
@@ -1080,11 +1111,13 @@ function whenAborted2(signal) {
1080
1111
  });
1081
1112
  }
1082
1113
  function agentBootSteps(deps = defaultBootDeps(), signal = new AbortController().signal) {
1114
+ let reclaim;
1083
1115
  return [
1084
1116
  {
1085
1117
  name: "pollBootstrap",
1086
1118
  critical: true,
1087
1119
  run: async (ctx) => {
1120
+ reclaim = reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log).catch(() => void 0);
1088
1121
  const bundle = await pollBootstrapBundle(ctx.apiUrl, ctx.bootstrapToken, {
1089
1122
  fetchFn: deps.fetchFn,
1090
1123
  sleepFn: deps.sleepFn,
@@ -1123,7 +1156,7 @@ function agentBootSteps(deps = defaultBootDeps(), signal = new AbortController()
1123
1156
  critical: false,
1124
1157
  run: async (ctx) => {
1125
1158
  if (!ctx.bundle) return;
1126
- await reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log);
1159
+ await (reclaim ?? reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log));
1127
1160
  }
1128
1161
  },
1129
1162
  {
@@ -1227,11 +1260,7 @@ async function runWorkbenchRole(ctx, deps, signal) {
1227
1260
  async function runBoot(argv, deps = defaultBootDeps()) {
1228
1261
  const { log } = deps;
1229
1262
  if (argv.includes("--preflight-update")) {
1230
- await runPreflightUpdate({
1231
- exec: deps.exec,
1232
- installedVersion: deps.installedVersion,
1233
- log
1234
- });
1263
+ log.info("[boot] --preflight-update is a no-op (baked agent, no runtime self-update)");
1235
1264
  return 0;
1236
1265
  }
1237
1266
  const role = process.env.CONVEYOR_CONTAINER_ROLE;
@@ -1256,7 +1285,9 @@ async function runBoot(argv, deps = defaultBootDeps()) {
1256
1285
  hostname: deps.hostname,
1257
1286
  log
1258
1287
  };
1259
- return role === "workbench" ? runWorkbenchRole(ctx, deps, controller.signal) : runAgentRole(ctx, deps, controller.signal);
1288
+ const code = await (role === "workbench" ? runWorkbenchRole(ctx, deps, controller.signal) : runAgentRole(ctx, deps, controller.signal));
1289
+ controller.abort();
1290
+ return code;
1260
1291
  }
1261
1292
  export {
1262
1293
  TOMBSTONE_MESSAGE,
@@ -1266,4 +1297,4 @@ export {
1266
1297
  runBoot,
1267
1298
  workbenchBootSteps
1268
1299
  };
1269
- //# sourceMappingURL=boot-YZCOIV3Q.js.map
1300
+ //# sourceMappingURL=boot-I353EAK6.js.map