@rallycry/conveyor-agent 10.13.17 → 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-NMXFM4GK.js → boot-I353EAK6.js} +156 -124
  2. package/dist/boot-I353EAK6.js.map +1 -0
  3. package/dist/{chunk-NI5L2R2N.js → chunk-36VMMHYD.js} +5607 -2115
  4. package/dist/chunk-36VMMHYD.js.map +1 -0
  5. package/dist/{chunk-5UYMDSAE.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-JG54UJ6V.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 +154 -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-NMXFM4GK.js.map +0 -1
  30. package/dist/chunk-5UYMDSAE.js.map +0 -1
  31. package/dist/chunk-7TQO4ZF4.js +0 -60
  32. package/dist/chunk-7TQO4ZF4.js.map +0 -1
  33. package/dist/chunk-JG54UJ6V.js.map +0 -1
  34. package/dist/chunk-NI5L2R2N.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-CO5O7G4U.js +0 -9
  38. /package/dist/{client-BU4XA7CV.js.map → client-LRVVHTNG.js.map} +0 -0
  39. /package/dist/{server-CO5O7G4U.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-5UYMDSAE.js";
18
- import "./chunk-JG54UJ6V.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,95 +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
- return "updated";
340
- } catch (err) {
341
- deps.log.warn(
342
- `[boot] WARN preflight install failed (${err instanceof Error ? err.message : err}); keeping baked version`
343
- );
344
- return "skipped";
345
- }
346
- }
347
- deps.log.info(`[boot] preflight agent ${installed} is current (registry ${latest})`);
348
- return "current";
349
- }
350
276
 
351
277
  // src/boot/supervisor.ts
352
278
  import { spawn as spawnChildProcess } from "child_process";
353
- import { appendFileSync as appendFileSync2, writeFileSync } from "fs";
279
+ import { appendFileSync as appendFileSync2, statSync, writeFileSync } from "fs";
354
280
  import { join } from "path";
355
281
 
356
282
  // src/boot/crash-report.ts
@@ -377,6 +303,7 @@ async function reportAgentCrash(apiUrl, bootstrapToken, report, fetchFn = fetch)
377
303
  // src/boot/supervisor.ts
378
304
  var AGENT_CRASH_MAX = 3;
379
305
  var AGENT_LOG_PATH = "/tmp/claudespace-agent.log";
306
+ var AGENT_LOG_MAX_BYTES = 16 * 1024 * 1024;
380
307
  var LAUNCH_MARKER_NAME = "conveyor-agent-launching";
381
308
  var RESTARTING_MARKER_NAME = "conveyor-agent-restarting";
382
309
  var LAUNCH_MARKER = `/tmp/${LAUNCH_MARKER_NAME}`;
@@ -393,14 +320,31 @@ function touchMarker(path, log) {
393
320
  );
394
321
  }
395
322
  }
396
- function teeChildOutput(child) {
397
- const onData = (chunk) => {
398
- 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) => {
399
331
  try {
400
- 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
+ }
401
339
  } catch {
402
340
  }
403
341
  };
342
+ }
343
+ function teeChildOutput(child, appendLog) {
344
+ const onData = (chunk) => {
345
+ process.stdout.write(chunk);
346
+ appendLog(chunk);
347
+ };
404
348
  child.stdout?.on("data", onData);
405
349
  child.stderr?.on("data", onData);
406
350
  }
@@ -474,12 +418,13 @@ async function superviseRunner(opts) {
474
418
  const launchMarkerPath = join(markerDir, LAUNCH_MARKER_NAME);
475
419
  const restartingMarkerPath = join(markerDir, RESTARTING_MARKER_NAME);
476
420
  touchMarker(launchMarkerPath, opts.log);
421
+ const appendLog = createLogAppender(AGENT_LOG_PATH, AGENT_LOG_MAX_BYTES);
477
422
  let attempt = 0;
478
423
  while (true) {
479
424
  attempt++;
480
425
  opts.log.info("[boot] Launching agent...");
481
426
  const child = spawnAgent(spawnFn, opts);
482
- teeChildOutput(child);
427
+ teeChildOutput(child, appendLog);
483
428
  const exitPromise = waitForExit(child);
484
429
  const winner = await Promise.race([
485
430
  exitPromise.then((code) => ({ type: "exit", code })),
@@ -516,11 +461,13 @@ async function superviseRunner(opts) {
516
461
  import {
517
462
  chmodSync,
518
463
  copyFileSync,
464
+ existsSync,
519
465
  lstatSync,
520
466
  mkdirSync,
521
467
  readFileSync,
468
+ readdirSync,
522
469
  rmSync,
523
- statSync,
470
+ statSync as statSync2,
524
471
  symlinkSync,
525
472
  writeFileSync as writeFileSync2
526
473
  } from "fs";
@@ -574,7 +521,7 @@ function seedClaudeJson(targetPath) {
574
521
  }
575
522
  function isDir(path) {
576
523
  try {
577
- return statSync(path).isDirectory();
524
+ return statSync2(path).isDirectory();
578
525
  } catch {
579
526
  return false;
580
527
  }
@@ -608,6 +555,29 @@ function wireCredentials(opts) {
608
555
  safely(log, "repoint credentials symlink", () => relink(podLocal, shared));
609
556
  safely(log, "chmod pod-local credentials", () => chmodSync(podLocal, 384));
610
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
+ }
611
581
  function wireMountedUserHome(opts) {
612
582
  const { home, userHomeMount, userId, projectId, sharedDir, log } = opts;
613
583
  const root = join2(userHomeMount, "users", userId, projectId);
@@ -625,6 +595,7 @@ function wireMountedUserHome(opts) {
625
595
  rmSync(join2(home, ".claude.json"), { recursive: true, force: true });
626
596
  seedClaudeJson(join2(home, ".claude.json"));
627
597
  });
598
+ wireSharedMemory(root, userHomeMount, projectId, log);
628
599
  wireCredentials({ home, root, sharedDir, log });
629
600
  safely(log, "mkdir opencode root", () => {
630
601
  mkdirSync(join2(root, ".local", "share", "opencode"), { recursive: true });
@@ -658,6 +629,11 @@ function wireNoMountUserHome(opts) {
658
629
  }
659
630
  function wireUserHome(opts) {
660
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
+ );
661
637
  if (userId && projectId && isDir(userHomeMount)) {
662
638
  wireMountedUserHome({ home, userHomeMount, userId, projectId, sharedDir, log });
663
639
  } else {
@@ -695,15 +671,27 @@ async function reclaimHomeOwnership(home, exec, log) {
695
671
  }
696
672
 
697
673
  // src/boot/sshd.ts
698
- 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";
699
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
+ }
700
683
  async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPACE_SSH_PORT || "2222", home = "/home/conveyor") {
701
684
  try {
702
685
  const sshDir = join3(home, ".ssh");
703
686
  mkdirSync2(sshDir, { recursive: true });
704
687
  chmodSync2(sshDir, 448);
705
688
  const authorizedKeys = join3(sshDir, "authorized_keys");
706
- 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
+ }
707
695
  chmodSync2(authorizedKeys, 384);
708
696
  } catch (err) {
709
697
  log.warn(
@@ -711,7 +699,7 @@ async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPA
711
699
  );
712
700
  return;
713
701
  }
714
- if (!existsSync("/usr/sbin/sshd")) {
702
+ if (!existsSync2("/usr/sbin/sshd")) {
715
703
  log.warn("[boot] WARN: workspace SSHD unavailable");
716
704
  return;
717
705
  }
@@ -728,12 +716,15 @@ async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPA
728
716
 
729
717
  // src/boot/workspace-extras.ts
730
718
  import {
731
- existsSync as existsSync2,
719
+ appendFileSync as appendFileSync3,
720
+ existsSync as existsSync3,
732
721
  lstatSync as lstatSync2,
733
722
  mkdirSync as mkdirSync3,
734
- readdirSync,
723
+ readdirSync as readdirSync2,
724
+ readFileSync as readFileSync2,
725
+ readlinkSync,
735
726
  rmSync as rmSync2,
736
- statSync as statSync2,
727
+ statSync as statSync3,
737
728
  symlinkSync as symlinkSync2
738
729
  } from "fs";
739
730
  import { join as join4 } from "path";
@@ -742,7 +733,7 @@ function errText(err) {
742
733
  }
743
734
  function isDir2(path) {
744
735
  try {
745
- return statSync2(path).isDirectory();
736
+ return statSync3(path).isDirectory();
746
737
  } catch {
747
738
  return false;
748
739
  }
@@ -768,7 +759,7 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
768
759
  const sourceDir = graphifyEnv.CONVEYOR_GRAPHIFY_DIR;
769
760
  const graphFile = graphifyEnv.CONVEYOR_GRAPHIFY_GRAPH;
770
761
  if (!slug || !sourceDir || !graphFile) return;
771
- if (!existsSync2(graphFile)) {
762
+ if (!existsSync3(graphFile)) {
772
763
  log.info(`[boot] Graphify bundle not found for '${slug}' at ${sourceDir}`);
773
764
  return;
774
765
  }
@@ -782,8 +773,8 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
782
773
  for (const rel of GRAPHIFY_BUNDLE_FILES) {
783
774
  const source = join4(sourceDir, rel);
784
775
  const target = join4(targetDir, rel);
785
- if (!existsSync2(source)) continue;
786
- if (existsSync2(target) || isSymlink(target)) continue;
776
+ if (!existsSync3(source)) continue;
777
+ if (existsSync3(target) || isSymlink(target)) continue;
787
778
  try {
788
779
  symlinkSync2(source, target);
789
780
  } catch {
@@ -793,7 +784,7 @@ function bindGraphifyBundle(workspace, graphifyEnv, log) {
793
784
  }
794
785
  async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
795
786
  try {
796
- if (!existsSync2(join4(workspace, ".gitmodules"))) return;
787
+ if (!existsSync3(join4(workspace, ".gitmodules"))) return;
797
788
  let paths = "";
798
789
  try {
799
790
  ({ stdout: paths } = await git(
@@ -831,6 +822,30 @@ async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
831
822
  log.warn(`[boot] WARN: grimoire submodule check failed: ${errText(err)}`);
832
823
  }
833
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
+ }
834
849
  function linkGrimoireSkills(workspace, log) {
835
850
  const sourceDir = join4(workspace, ".claude", "grimoire", "skills");
836
851
  const targetDir = join4(workspace, ".claude", "skills");
@@ -841,28 +856,42 @@ function linkGrimoireSkills(workspace, log) {
841
856
  log.warn(`[boot] WARN: unable to create ${targetDir}; skipping grimoire skill links`);
842
857
  return;
843
858
  }
844
- let linked = 0;
859
+ const linkedNames = [];
845
860
  let names = [];
846
861
  try {
847
- names = readdirSync(sourceDir);
862
+ names = readdirSync2(sourceDir);
848
863
  } catch {
849
864
  return;
850
865
  }
851
866
  for (const name of names) {
852
867
  if (!isDir2(join4(sourceDir, name))) continue;
853
868
  const target = join4(targetDir, name);
854
- if (existsSync2(target) && !isSymlink(target)) {
869
+ if (existsSync3(target) && !isSymlink(target)) {
855
870
  log.warn(`[boot] WARN: ${target} exists and is not a symlink; skipping`);
856
871
  continue;
857
872
  }
873
+ if (isSymlink(target) && !symlinkTargetsGrimoire(target)) continue;
858
874
  try {
859
875
  rmSync2(target, { force: true });
860
876
  symlinkSync2(join4("..", "grimoire", "skills", name), target);
861
- linked++;
877
+ linkedNames.push(name);
862
878
  } catch {
863
879
  }
864
880
  }
865
- 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
+ }
866
895
  }
867
896
  function parseReferenceRepos(refsJson) {
868
897
  let parsed;
@@ -893,6 +922,7 @@ async function runPreReadyBinds(workspace, bundle, git, log) {
893
922
  bindGraphifyBundle(workspace, graphifyEnv, log);
894
923
  await ensureGrimoireSubmodule(workspace, bundle.githubToken, git, log);
895
924
  linkGrimoireSkills(workspace, log);
925
+ await neutralizeGrimoirePointer(workspace, git, log);
896
926
  }
897
927
  async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspaces/references") {
898
928
  if (!refsJson) return;
@@ -905,7 +935,7 @@ async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspa
905
935
  }
906
936
  for (const ref of refs) {
907
937
  const dest = join4(referencesDir, ref.slug);
908
- if (existsSync2(join4(dest, ".git"))) continue;
938
+ if (existsSync3(join4(dest, ".git"))) continue;
909
939
  try {
910
940
  await git(
911
941
  [
@@ -1014,16 +1044,22 @@ async function runWorkbenchBoot(ctx, overrides = {}) {
1014
1044
  const job = new GitPrepJob(deps.gitPrepDeps(ctx, bundle), {
1015
1045
  // Order pinned by the old entrypoint-grimoire test: binds BEFORE the
1016
1046
  // ready flip (Claude must not spawn before skills exist), references after.
1017
- onReady: () => deps.bindsBeforeReady(ctx, bundle),
1047
+ onReady: () => {
1048
+ const binds = deps.bindsBeforeReady(ctx, bundle);
1049
+ void reportBootMilestone({ key: "repo_synced" });
1050
+ return binds;
1051
+ },
1018
1052
  afterReady: () => deps.cloneReferences(ctx, bundle)
1019
1053
  });
1020
1054
  await deps.startDaemon({
1021
1055
  port: workbenchPort() ?? DEFAULT_WORKBENCH_PORT,
1022
1056
  token: ctx.bootstrapToken,
1023
1057
  version: readAgentVersion() ?? "unknown",
1024
- getGitStatus: () => toGitStatusFrame(job.status)
1058
+ getGitStatus: () => toGitStatusFrame(job.status),
1059
+ oomWatchdog: oomWatchdogOptionsFromEnv(ctx.log)
1025
1060
  });
1026
1061
  ctx.log.info("[boot] step=startDaemon listen socket up (startupProbe gate open)");
1062
+ void reportBootMilestone({ key: "workbench_ready" });
1027
1063
  try {
1028
1064
  deps.ensureWorkspaceDir(ctx);
1029
1065
  } catch (err) {
@@ -1051,13 +1087,9 @@ function defaultBootDeps() {
1051
1087
  }),
1052
1088
  spawnFn: spawn,
1053
1089
  exec: defaultExec,
1054
- installedVersion: () => {
1055
- const version = readAgentVersion();
1056
- return version ? Promise.resolve(version) : Promise.reject(new Error("could not read installed agent version"));
1057
- },
1058
1090
  dirExists: (path) => {
1059
1091
  try {
1060
- return statSync3(path).isDirectory();
1092
+ return statSync4(path).isDirectory();
1061
1093
  } catch {
1062
1094
  return false;
1063
1095
  }
@@ -1079,11 +1111,13 @@ function whenAborted2(signal) {
1079
1111
  });
1080
1112
  }
1081
1113
  function agentBootSteps(deps = defaultBootDeps(), signal = new AbortController().signal) {
1114
+ let reclaim;
1082
1115
  return [
1083
1116
  {
1084
1117
  name: "pollBootstrap",
1085
1118
  critical: true,
1086
1119
  run: async (ctx) => {
1120
+ reclaim = reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log).catch(() => void 0);
1087
1121
  const bundle = await pollBootstrapBundle(ctx.apiUrl, ctx.bootstrapToken, {
1088
1122
  fetchFn: deps.fetchFn,
1089
1123
  sleepFn: deps.sleepFn,
@@ -1122,7 +1156,7 @@ function agentBootSteps(deps = defaultBootDeps(), signal = new AbortController()
1122
1156
  critical: false,
1123
1157
  run: async (ctx) => {
1124
1158
  if (!ctx.bundle) return;
1125
- await reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log);
1159
+ await (reclaim ?? reclaimHomeOwnership(HOME_DIR2, deps.exec, ctx.log));
1126
1160
  }
1127
1161
  },
1128
1162
  {
@@ -1226,11 +1260,7 @@ async function runWorkbenchRole(ctx, deps, signal) {
1226
1260
  async function runBoot(argv, deps = defaultBootDeps()) {
1227
1261
  const { log } = deps;
1228
1262
  if (argv.includes("--preflight-update")) {
1229
- await runPreflightUpdate({
1230
- exec: deps.exec,
1231
- installedVersion: deps.installedVersion,
1232
- log
1233
- });
1263
+ log.info("[boot] --preflight-update is a no-op (baked agent, no runtime self-update)");
1234
1264
  return 0;
1235
1265
  }
1236
1266
  const role = process.env.CONVEYOR_CONTAINER_ROLE;
@@ -1255,7 +1285,9 @@ async function runBoot(argv, deps = defaultBootDeps()) {
1255
1285
  hostname: deps.hostname,
1256
1286
  log
1257
1287
  };
1258
- 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;
1259
1291
  }
1260
1292
  export {
1261
1293
  TOMBSTONE_MESSAGE,
@@ -1265,4 +1297,4 @@ export {
1265
1297
  runBoot,
1266
1298
  workbenchBootSteps
1267
1299
  };
1268
- //# sourceMappingURL=boot-NMXFM4GK.js.map
1300
+ //# sourceMappingURL=boot-I353EAK6.js.map