@rallycry/conveyor-agent 10.2.4 → 10.3.0

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.
@@ -217,10 +217,16 @@ if [ "${SESSION_MODE}" = "review" ]; then
217
217
  # branch), so a role check can't identify them — gating on role=reader here
218
218
  # is what let review pods fall through to the default task runner and boot
219
219
  # the parent's task agent in discovery mode. The agent CLI's RunnerMode is
220
- # spelled "code-review" (cli.ts validates task|pm|code-review|adhoc); the bare
220
+ # spelled "code-review" (cli.ts validates task|pm|code-review|adhoc|pack); the bare
221
221
  # "review" is the agentMode/tag axis, NOT a runner mode — passing it here
222
222
  # made the agent exit "Invalid CONVEYOR_MODE" and crash-loop every 10s.
223
223
  export CONVEYOR_MODE="code-review"
224
+ elif [ "${SESSION_MODE}" = "pack" ]; then
225
+ # Parent-card orchestrator (task-bound — CONVEYOR_TASK_ID is set): the agent
226
+ # runs the autonomous pack loop (start ready children, merge child PRs,
227
+ # complete the parent) instead of building code. Same task-mode lifecycle,
228
+ # different prompt/tool surface — see conveyor-agent pack-runner-prompt.ts.
229
+ export CONVEYOR_MODE="pack"
224
230
  elif [ "${SESSION_MODE}" = "adhoc" ]; then
225
231
  # Task-less USER SCRATCH pod (Sessions view): the agent runs an interactive
226
232
  # `claude` TUI relayed to the web terminal — no autonomous loop, no task. Must
@@ -324,6 +330,13 @@ if [ -n "${CONVEYOR_USER_ID}" ] && [ -n "${USER_HOME_PROJECT_ID}" ] && [ -d "${U
324
330
  ln -sfn "${USER_HOME_ROOT}/.claude" /home/conveyor/.claude
325
331
  ln -sfn "${USER_HOME_ROOT}/.claude.json" /home/conveyor/.claude.json
326
332
  ln -sfn "${USER_HOME_ROOT}/.config/claude" /home/conveyor/.config/claude
333
+
334
+ # OpenCode state (sessions + config) persists the same way as ~/.claude.
335
+ mkdir -p "${USER_HOME_ROOT}/.local/share/opencode" "${USER_HOME_ROOT}/.config/opencode" 2>/dev/null || true
336
+ rm -rf /home/conveyor/.local/share/opencode /home/conveyor/.config/opencode 2>/dev/null || true
337
+ mkdir -p /home/conveyor/.local/share 2>/dev/null || true
338
+ ln -sfn "${USER_HOME_ROOT}/.local/share/opencode" /home/conveyor/.local/share/opencode
339
+ ln -sfn "${USER_HOME_ROOT}/.config/opencode" /home/conveyor/.config/opencode
327
340
  else
328
341
  echo "[pool] Skipping user-home symlink (userId='${CONVEYOR_USER_ID}', projectId='${USER_HOME_PROJECT_ID}', mount present: $([ -d "${USER_HOME_MOUNT}" ] && echo yes || echo no))"
329
342
  # No persistent home — the CLI reads the pod-local config; seed it there so
@@ -331,6 +344,88 @@ else
331
344
  seed_claude_json /home/conveyor/.claude.json
332
345
  fi
333
346
 
347
+ # ── Wire published graphify bundles from the shared user-home mount ──
348
+ # A locally published graph lives in the same GCS-FUSE user-home bucket as
349
+ # Claude state, under users/_shared/graphify/<repo>/latest. Export the path
350
+ # contract before the agent starts, then bind the files into graphify-out after
351
+ # git has prepared the workspace but before the ready marker is released.
352
+ configure_graphify_env() {
353
+ if [ "${CONVEYOR_GRAPHIFY_DISABLE:-}" = "1" ]; then
354
+ return 0
355
+ fi
356
+
357
+ local slug="${CONVEYOR_GRAPHIFY_SLUG:-${REPO_NAME:-}}"
358
+ if [ -z "${slug}" ]; then
359
+ return 0
360
+ fi
361
+
362
+ local primary_root="${USER_HOME_MOUNT}/users/_shared/graphify"
363
+ local legacy_root="${USER_HOME_MOUNT}/_shared/graphify"
364
+ local shared_root="${CONVEYOR_GRAPHIFY_SHARED_ROOT:-}"
365
+ if [ -z "${shared_root}" ]; then
366
+ if [ -d "${primary_root}" ] || [ ! -d "${legacy_root}" ]; then
367
+ shared_root="${primary_root}"
368
+ else
369
+ shared_root="${legacy_root}"
370
+ fi
371
+ fi
372
+
373
+ export CONVEYOR_GRAPHIFY_SLUG="${slug}"
374
+ export CONVEYOR_GRAPHIFY_SHARED_ROOT="${shared_root}"
375
+ export CONVEYOR_GRAPHIFY_DIR="${CONVEYOR_GRAPHIFY_DIR:-${shared_root}/${slug}/latest}"
376
+ export CONVEYOR_GRAPHIFY_GRAPH="${CONVEYOR_GRAPHIFY_GRAPH:-${CONVEYOR_GRAPHIFY_DIR}/graph.json}"
377
+ }
378
+
379
+ bind_graphify_bundle() {
380
+ if [ "${CONVEYOR_GRAPHIFY_DISABLE:-}" = "1" ]; then
381
+ echo "[pool] Graphify bind disabled."
382
+ return 0
383
+ fi
384
+
385
+ if [ -z "${CONVEYOR_GRAPHIFY_SLUG:-}" ]; then
386
+ return 0
387
+ fi
388
+
389
+ local workspace="${CONVEYOR_WORKSPACE:-/workspaces/repo}"
390
+ local source_dir="${CONVEYOR_GRAPHIFY_DIR:-}"
391
+ local graph_file="${CONVEYOR_GRAPHIFY_GRAPH:-}"
392
+
393
+ if [ -z "${source_dir}" ] || [ -z "${graph_file}" ]; then
394
+ return 0
395
+ fi
396
+
397
+ if [ ! -f "${graph_file}" ]; then
398
+ echo "[pool] Graphify bundle not found for '${CONVEYOR_GRAPHIFY_SLUG}' at ${source_dir}"
399
+ return 0
400
+ fi
401
+
402
+ local target_dir="${workspace}/graphify-out"
403
+ if ! mkdir -p "${target_dir}" 2>/dev/null; then
404
+ echo "[pool] WARN: unable to create graphify-out at ${target_dir}"
405
+ return 0
406
+ fi
407
+
408
+ local rel
409
+ for rel in graph.json GRAPH_REPORT.md manifest.json .graphify_analysis.json .graphify_labels.json publish-manifest.json cost.json; do
410
+ if [ ! -e "${source_dir}/${rel}" ]; then
411
+ continue
412
+ fi
413
+ if [ -e "${target_dir}/${rel}" ] || [ -L "${target_dir}/${rel}" ]; then
414
+ continue
415
+ fi
416
+ ln -s "${source_dir}/${rel}" "${target_dir}/${rel}" 2>/dev/null || true
417
+ done
418
+
419
+ echo "[pool] Bound graphify bundle '${CONVEYOR_GRAPHIFY_SLUG}' into ${target_dir}"
420
+ }
421
+
422
+ mark_git_ready() {
423
+ bind_graphify_bundle
424
+ : > "$GIT_READY_MARKER"
425
+ }
426
+
427
+ configure_graphify_env
428
+
334
429
  # ═══════════════════════════════════════════════════════════════════════════
335
430
  # WORKSPACE GIT — moved OFF the pre-launch critical path (Claudespace v3).
336
431
  #
@@ -489,7 +584,7 @@ prepare_workspace_git() {
489
584
  # Task repo is ready HERE — release the gate. The agent (already launched)
490
585
  # is polling for this marker before it spawns Claude / runs setup. Reference
491
586
  # repos are cloned AFTER this so they never block Claude.
492
- : > "$GIT_READY_MARKER"
587
+ mark_git_ready
493
588
  elif [ -d "repo/.git" ] && [ -n "${CONVEYOR_GITHUB_TOKEN}" ]; then
494
589
  # Non-image but repo already present (e.g. a baked image running without
495
590
  # CONVEYOR_POD_IMAGE set). Must NOT settle for a bare remote-URL refresh —
@@ -501,7 +596,7 @@ prepare_workspace_git() {
501
596
  if ! sync_task_branch_to_repo; then
502
597
  return 1
503
598
  fi
504
- : > "$GIT_READY_MARKER"
599
+ mark_git_ready
505
600
  elif [ -n "${CONVEYOR_GITHUB_TOKEN}" ] && [ -n "${REPO_OWNER}" ] && [ -n "${REPO_NAME}" ] && [ -n "${BRANCH}" ]; then
506
601
  echo "[pool] Cloning repo post-assignment (pre-clone was missing)..."
507
602
  # Guard each clone/fetch/checkout: under `set -e` a bare failing clone would
@@ -543,14 +638,14 @@ prepare_workspace_git() {
543
638
  return 1
544
639
  fi
545
640
  fi
546
- : > "$GIT_READY_MARKER"
641
+ mark_git_ready
547
642
  else
548
643
  # No git plan (e.g. task-less pod, or no token/repo). Nothing to prepare —
549
644
  # the repo dir already exists (created before launch) and the agent's own
550
645
  # git-sync fallback (guarded by CONVEYOR_GIT_READY) never runs on this pod
551
646
  # path anyway. Signal ready so the agent doesn't wait out the timeout.
552
647
  echo "[pool] No git plan to prepare — marking git ready."
553
- : > "$GIT_READY_MARKER"
648
+ mark_git_ready
554
649
  fi
555
650
 
556
651
  # ── Clone reference repos into /workspaces/references (best-effort) ──