@rallycry/conveyor-agent 10.13.8 → 10.13.10

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.
@@ -143,7 +143,20 @@ reclaim_home_ownership() {
143
143
  done
144
144
  }
145
145
 
146
- start_workspace_sshd
146
+ # ── Container role (workbench split) ──
147
+ # Split-mode pods run TWO app containers from this same entrypoint:
148
+ # agent — supervisor + conveyor-agent only (protected, restartPolicy
149
+ # Never semantics); no repo, no sshd, no git prep.
150
+ # workbench — the workspace: git prep, sshd, claude + all workloads behind
151
+ # the launcher daemon (native sidecar, restartPolicy Always).
152
+ # Unset = today's monolith container; every guard below must be a no-op then.
153
+ CONTAINER_ROLE="${CONVEYOR_CONTAINER_ROLE:-}"
154
+
155
+ # Split-mode pods: SSH attach lands in the WORKBENCH container (the workspace
156
+ # lives there); the agent container skips sshd.
157
+ if [ "${CONTAINER_ROLE}" != "agent" ]; then
158
+ start_workspace_sshd
159
+ fi
147
160
 
148
161
  # ── Required env vars (injected by pod spec — v3: exactly these two) ──
149
162
  : "${CONVEYOR_API_URL:?CONVEYOR_API_URL is required}"
@@ -442,6 +455,13 @@ if [ -n "${CONVEYOR_USER_ID}" ] && [ -n "${USER_HOME_PROJECT_ID}" ] && [ -d "${U
442
455
  # blocks wrong-account attribution.
443
456
  CRED_SHARED="${USER_HOME_ROOT}/.claude/.credentials.json"
444
457
  CRED_POD_LOCAL="/home/conveyor/.claude-credentials.pod.json"
458
+ # Split-mode pods: the agent container WRITES credentials (harness auth) and
459
+ # claude in the workbench READS them through the shared-dir symlink — so the
460
+ # pod-local file must live on the shared emptyDir. Still pod-local, so the
461
+ # concurrent-pods clobber fix above is preserved.
462
+ if [ -n "${CONVEYOR_SHARED_DIR:-}" ]; then
463
+ CRED_POD_LOCAL="${CONVEYOR_SHARED_DIR}/claude-credentials.pod.json"
464
+ fi
445
465
  if [ -f "${CRED_SHARED}" ] && [ ! -L "${CRED_SHARED}" ]; then
446
466
  # Legacy shared regular file: carry its contents into this pod so auth
447
467
  # survives the cutover; the agent re-synthesizes from its own token at
@@ -464,6 +484,14 @@ else
464
484
  # No persistent home — the CLI reads the pod-local config; seed it there so
465
485
  # non-FUSE pods get the same first-run gate suppression as the mounted path.
466
486
  seed_claude_json /home/conveyor/.claude.json
487
+ # Split-mode pods without a persistent user-home: ~/.claude must still cross
488
+ # the container boundary (claude writes transcripts in the workbench; the
489
+ # agent's tailer reads them), so it lives on the shared emptyDir.
490
+ if [ -n "${CONVEYOR_SHARED_DIR:-}" ]; then
491
+ mkdir -p "${CONVEYOR_SHARED_DIR}/claude-home/.claude" 2>/dev/null || true
492
+ rm -rf /home/conveyor/.claude 2>/dev/null || true
493
+ ln -sfn "${CONVEYOR_SHARED_DIR}/claude-home/.claude" /home/conveyor/.claude
494
+ fi
467
495
  boot_mark "no user-home mount — pod-local seed only"
468
496
  fi
469
497
 
@@ -636,6 +664,12 @@ configure_graphify_env
636
664
  # ═══════════════════════════════════════════════════════════════════════════
637
665
  GIT_READY_MARKER="/workspaces/.conveyor-git-ready"
638
666
  GIT_FAILED_MARKER="/workspaces/.conveyor-git-failed"
667
+ # Split-mode pods: the markers live on the shared emptyDir so the workbench's
668
+ # git prep is visible to the agent container (which never sees /workspaces).
669
+ if [ -n "${CONVEYOR_SHARED_DIR:-}" ]; then
670
+ GIT_READY_MARKER="${CONVEYOR_SHARED_DIR}/git-ready"
671
+ GIT_FAILED_MARKER="${CONVEYOR_SHARED_DIR}/git-failed"
672
+ fi
639
673
 
640
674
  reset_tracked_repo_changes_before_assignment_checkout() {
641
675
  # The baked/pooled repo is not user-owned until this git gate succeeds. Reset
@@ -878,15 +912,23 @@ prepare_workspace_git() {
878
912
  # A leftover ready marker from a PRIOR pod on the baked image would be
879
913
  # catastrophic: the agent would spawn Claude before THIS pod's git runs. Clear
880
914
  # both before starting the background prep.
881
- rm -f "$GIT_READY_MARKER" "$GIT_FAILED_MARKER"
882
- # Ensure the repo dir exists for launch on BOTH paths (the background clone
883
- # populates an empty dir on the non-image path; the pod-image path already has
884
- # repo/.git).
885
- mkdir -p /workspaces/repo
915
+ #
916
+ # Split-mode agent container: the WORKBENCH owns the repo and the git prep and
917
+ # writes the shared markers; this container only reads them. It must not clear
918
+ # them either — the workbench may have already written ready.
919
+ if [ "${CONTAINER_ROLE}" != "agent" ]; then
920
+ rm -f "$GIT_READY_MARKER" "$GIT_FAILED_MARKER"
921
+ # Ensure the repo dir exists for launch on BOTH paths (the background clone
922
+ # populates an empty dir on the non-image path; the pod-image path already has
923
+ # repo/.git).
924
+ mkdir -p /workspaces/repo
886
925
 
887
- # Run the full git prep in the background so the agent can connect (card lights
888
- # up) and stream setup output while git finishes.
889
- prepare_workspace_git &
926
+ # Run the full git prep in the background so the agent can connect (card lights
927
+ # up) and stream setup output while git finishes.
928
+ prepare_workspace_git &
929
+ else
930
+ echo "[pool] agent role — skipping git prep (workbench owns the workspace)"
931
+ fi
890
932
 
891
933
  # Signal to the agent that bash owns the git block (skip the agent's OWN
892
934
  # git-sync fallback) and that it must await the ready marker before spawning
@@ -897,10 +939,52 @@ export CONVEYOR_GIT_FAILED_MARKER="$GIT_FAILED_MARKER"
897
939
  # Target the repo regardless of when the background clone lands.
898
940
  export CONVEYOR_WORKSPACE=/workspaces/repo
899
941
 
942
+ # ── Workbench container (split-mode): exec the launcher daemon as PID 1 ──
943
+ # No crash loop here — the workbench is a native sidecar (restartPolicy
944
+ # Always); the kubelet owns restarts. Git prep above ran in THIS container
945
+ # (the repo lives here); the daemon serves the agent container's exec/pty/
946
+ # snapshot/file operations over loopback (token-authed, see workbench/server).
947
+ if [ "${CONTAINER_ROLE}" = "workbench" ]; then
948
+ # Bounded git-prep retry, backgrounded so the daemon starts immediately
949
+ # (the startupProbe gates pod readiness on the daemon listening). The repo
950
+ # lives HERE, so the retry must run here — the agent container's launch-loop
951
+ # retry is role-guarded off (found live 2026-07-16: an unguarded agent-side
952
+ # retry cloned the repo into the agent's own dead overlay).
953
+ (
954
+ _wb_git_attempts=0
955
+ while true; do
956
+ sleep 10
957
+ [ -f "$GIT_READY_MARKER" ] && break
958
+ if [ -f "$GIT_FAILED_MARKER" ]; then
959
+ if [ "$_wb_git_attempts" -ge 3 ]; then
960
+ echo "[pool] workbench git prep failed 3 times — giving up (agent surfaces the failure)."
961
+ break
962
+ fi
963
+ _wb_git_attempts=$((_wb_git_attempts + 1))
964
+ echo "[pool] workbench git prep failed — retrying (attempt ${_wb_git_attempts}/3)..."
965
+ rm -f "$GIT_READY_MARKER" "$GIT_FAILED_MARKER"
966
+ prepare_workspace_git
967
+ fi
968
+ done
969
+ ) &
970
+ cd /workspaces/repo
971
+ boot_mark "launching workbench daemon (env-inject → daemon-launch total)"
972
+ echo "[pool] Launching workbench launcher daemon..."
973
+ export CONVEYOR_MODE=workbench
974
+ exec conveyor-agent
975
+ fi
976
+
900
977
  # Launch agent — exit-code-aware restart loop.
901
978
  # Exit 0 = clean shutdown (idle timeout, task complete) — pod dies.
902
979
  # Non-zero = crash — retry after a brief pause.
903
- cd /workspaces/repo
980
+ #
981
+ # Split-mode agent container: /workspaces/repo in THIS container is a stale
982
+ # baked overlay, never the live tree — cwd must not resolve into it.
983
+ if [ "${CONTAINER_ROLE}" = "agent" ]; then
984
+ cd /home/conveyor
985
+ else
986
+ cd /workspaces/repo
987
+ fi
904
988
  boot_mark "launching agent (env-inject → agent-launch total)"
905
989
  echo "[pool] Launching agent..."
906
990
  set +e
@@ -935,7 +1019,9 @@ report_agent_crash() {
935
1019
  }
936
1020
 
937
1021
  while true; do
938
- if [ -f "$GIT_FAILED_MARKER" ]; then
1022
+ # Split-mode agent container: the workbench owns git prep AND its retry —
1023
+ # re-running prep here would clone into this container's dead overlay.
1024
+ if [ -f "$GIT_FAILED_MARKER" ] && [ "${CONTAINER_ROLE}" != "agent" ]; then
939
1025
  if [ "$_git_prep_attempts" -lt "$GIT_PREP_MAX_RETRIES" ]; then
940
1026
  _git_prep_attempts=$((_git_prep_attempts + 1))
941
1027
  echo "[pool] git prep previously failed — retrying (attempt ${_git_prep_attempts}/${GIT_PREP_MAX_RETRIES})..."