@imdeadpool/guardex 7.0.18 → 7.0.20

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.
@@ -2,11 +2,11 @@
2
2
  """Per-file lock registry for concurrent agent branches.
3
3
 
4
4
  Usage examples:
5
- python3 scripts/agent-file-locks.py claim --branch agent/a path/to/file1 path/to/file2
6
- python3 scripts/agent-file-locks.py claim --branch agent/a --allow-delete path/to/obsolete-file
7
- python3 scripts/agent-file-locks.py allow-delete --branch agent/a path/to/obsolete-file
8
- python3 scripts/agent-file-locks.py validate --branch agent/a --staged
9
- python3 scripts/agent-file-locks.py release --branch agent/a
5
+ gx locks claim --branch agent/a path/to/file1 path/to/file2
6
+ gx locks claim --branch agent/a --allow-delete path/to/obsolete-file
7
+ gx locks allow-delete --branch agent/a path/to/obsolete-file
8
+ gx locks validate --branch agent/a --staged
9
+ gx locks release --branch agent/a
10
10
  """
11
11
 
12
12
  from __future__ import annotations
@@ -27,9 +27,9 @@ CRITICAL_GUARDRAIL_PATHS = {
27
27
  'AGENTS.md',
28
28
  '.githooks/pre-commit',
29
29
  '.githooks/pre-push',
30
- 'scripts/agent-branch-start.sh',
31
- 'scripts/agent-branch-finish.sh',
32
- 'scripts/agent-file-locks.py',
30
+ '.githooks/post-merge',
31
+ '.githooks/post-checkout',
32
+ 'scripts/guardex-env.sh',
33
33
  }
34
34
  ALLOW_GUARDRAIL_DELETE_ENV = 'AGENT_ALLOW_GUARDRAIL_DELETE'
35
35
 
@@ -326,11 +326,11 @@ def cmd_validate(args: argparse.Namespace, repo_root: Path) -> int:
326
326
  print(f' - {file_path}', file=sys.stderr)
327
327
  print(' Approve explicit deletions with one of:', file=sys.stderr)
328
328
  print(
329
- f' python3 scripts/agent-file-locks.py claim --branch "{args.branch}" --allow-delete <file...>',
329
+ f' gx locks claim --branch "{args.branch}" --allow-delete <file...>',
330
330
  file=sys.stderr,
331
331
  )
332
332
  print(
333
- f' python3 scripts/agent-file-locks.py allow-delete --branch "{args.branch}" <file...>',
333
+ f' gx locks allow-delete --branch "{args.branch}" <file...>',
334
334
  file=sys.stderr,
335
335
  )
336
336
  if guardrail_delete_blocked:
@@ -343,7 +343,7 @@ def cmd_validate(args: argparse.Namespace, repo_root: Path) -> int:
343
343
  )
344
344
 
345
345
  print('\nClaim files with:', file=sys.stderr)
346
- print(f' python3 scripts/agent-file-locks.py claim --branch "{args.branch}" <file...>', file=sys.stderr)
346
+ print(f' gx locks claim --branch "{args.branch}" <file...>', file=sys.stderr)
347
347
  return 1
348
348
 
349
349
 
@@ -7,6 +7,7 @@ BASE_BRANCH="${GUARDEX_BASE_BRANCH:-}"
7
7
  BASE_BRANCH_EXPLICIT=0
8
8
  CODEX_BIN="${GUARDEX_CODEX_BIN:-codex}"
9
9
  NODE_BIN="${GUARDEX_NODE_BIN:-node}"
10
+ CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
10
11
  AUTO_FINISH_RAW="${GUARDEX_CODEX_AUTO_FINISH:-true}"
11
12
  AUTO_REVIEW_ON_CONFLICT_RAW="${GUARDEX_CODEX_AUTO_REVIEW_ON_CONFLICT:-true}"
12
13
  AUTO_CLEANUP_RAW="${GUARDEX_CODEX_AUTO_CLEANUP:-true}"
@@ -16,6 +17,30 @@ OPENSPEC_PLAN_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_PLAN_SLUG:-}"
16
17
  OPENSPEC_CHANGE_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CHANGE_SLUG:-}"
17
18
  OPENSPEC_CAPABILITY_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CAPABILITY_SLUG:-}"
18
19
  OPENSPEC_MASTERPLAN_LABEL_RAW="${GUARDEX_OPENSPEC_MASTERPLAN_LABEL-masterplan}"
20
+ OPENSPEC_TIER_RAW="${GUARDEX_OPENSPEC_TIER:-}"
21
+ OPENSPEC_TIER=""
22
+ OPENSPEC_SKIP_CHANGE=0
23
+ OPENSPEC_SKIP_PLAN=0
24
+ OPENSPEC_MINIMAL=0
25
+ TASK_MODE=""
26
+ TASK_ROUTING_REASON=""
27
+
28
+ run_guardex_cli() {
29
+ if [[ -n "$CLI_ENTRY" ]]; then
30
+ "$NODE_BIN" "$CLI_ENTRY" "$@"
31
+ return $?
32
+ fi
33
+ if command -v gx >/dev/null 2>&1; then
34
+ gx "$@"
35
+ return $?
36
+ fi
37
+ if command -v gitguardex >/dev/null 2>&1; then
38
+ gitguardex "$@"
39
+ return $?
40
+ fi
41
+ echo "[codex-agent] Guardex CLI entrypoint unavailable; rerun via gx." >&2
42
+ return 127
43
+ }
19
44
 
20
45
  normalize_bool() {
21
46
  local raw="${1:-}"
@@ -30,6 +55,117 @@ normalize_bool() {
30
55
  esac
31
56
  }
32
57
 
58
+ normalize_tier() {
59
+ local raw="${1:-}"
60
+ local fallback="${2:-T2}"
61
+ local upper
62
+ upper="$(printf '%s' "$raw" | tr '[:lower:]' '[:upper:]')"
63
+ case "$upper" in
64
+ T0|T1|T2|T3) printf '%s' "$upper" ;;
65
+ '') printf '%s' "$fallback" ;;
66
+ *) return 1 ;;
67
+ esac
68
+ }
69
+
70
+ string_contains_any() {
71
+ local haystack="$1"
72
+ shift
73
+ local needle
74
+ for needle in "$@"; do
75
+ if [[ "$haystack" == *"$needle"* ]]; then
76
+ return 0
77
+ fi
78
+ done
79
+ return 1
80
+ }
81
+
82
+ string_has_lightweight_prefix() {
83
+ local text="$1"
84
+ local prefix
85
+ for prefix in "quick:" "simple:" "tiny:" "minor:" "small:" "just:" "only:"; do
86
+ if [[ "$text" == "$prefix"* ]]; then
87
+ return 0
88
+ fi
89
+ done
90
+ return 1
91
+ }
92
+
93
+ derive_task_mode_from_tier() {
94
+ case "$1" in
95
+ T0|T1) printf 'caveman' ;;
96
+ T2|T3) printf 'omx' ;;
97
+ *) return 1 ;;
98
+ esac
99
+ }
100
+
101
+ apply_openspec_tier() {
102
+ OPENSPEC_SKIP_CHANGE=0
103
+ OPENSPEC_SKIP_PLAN=0
104
+ OPENSPEC_MINIMAL=0
105
+ case "$1" in
106
+ T0)
107
+ OPENSPEC_SKIP_CHANGE=1
108
+ OPENSPEC_SKIP_PLAN=1
109
+ ;;
110
+ T1)
111
+ OPENSPEC_SKIP_PLAN=1
112
+ OPENSPEC_MINIMAL=1
113
+ ;;
114
+ T2)
115
+ OPENSPEC_SKIP_PLAN=1
116
+ ;;
117
+ esac
118
+ }
119
+
120
+ decide_task_routing() {
121
+ local task_lower
122
+ task_lower="$(printf '%s' "$TASK_NAME" | tr '[:upper:]' '[:lower:]')"
123
+
124
+ if [[ -n "$OPENSPEC_TIER_RAW" ]]; then
125
+ if ! OPENSPEC_TIER="$(normalize_tier "$OPENSPEC_TIER_RAW" "T2")"; then
126
+ echo "[codex-agent] Unsupported OpenSpec tier: ${OPENSPEC_TIER_RAW}" >&2
127
+ return 1
128
+ fi
129
+ TASK_ROUTING_REASON="explicit tier override"
130
+ elif string_has_lightweight_prefix "$task_lower"; then
131
+ OPENSPEC_TIER="T1"
132
+ TASK_ROUTING_REASON="explicit lightweight prefix"
133
+ elif string_contains_any "$task_lower" \
134
+ "ralph" "autopilot" "ultrawork" "ultraqa" "ralplan" "deep interview" "ouroboros" \
135
+ "migration" "refactor" "architecture" "re-architect" "cross-cutting" "multi-agent" \
136
+ "multiagent" "parallel" "orchestr" "release" "zero-copy" "install surface" "workflow"
137
+ then
138
+ OPENSPEC_TIER="T3"
139
+ TASK_ROUTING_REASON="plan-heavy or orchestration-heavy task wording"
140
+ elif string_contains_any "$task_lower" \
141
+ "typo" "spelling" "comment-only" "comment only" "format-only" "format only" \
142
+ "whitespace" "one-liner" "one liner" "version bump" "bump version" \
143
+ "single-file" "single file"
144
+ then
145
+ OPENSPEC_TIER="T1"
146
+ TASK_ROUTING_REASON="small bounded maintenance wording"
147
+ else
148
+ OPENSPEC_TIER="T2"
149
+ TASK_ROUTING_REASON="default behavior-change route"
150
+ fi
151
+
152
+ if ! TASK_MODE="$(derive_task_mode_from_tier "$OPENSPEC_TIER")"; then
153
+ echo "[codex-agent] Unsupported task mode tier: ${OPENSPEC_TIER}" >&2
154
+ return 1
155
+ fi
156
+ apply_openspec_tier "$OPENSPEC_TIER"
157
+ }
158
+
159
+ describe_task_routing() {
160
+ case "$OPENSPEC_TIER" in
161
+ T0) printf 'caveman / T0 (no OpenSpec scaffold)' ;;
162
+ T1) printf 'caveman / T1 (notes-only OpenSpec)' ;;
163
+ T2) printf 'omx / T2 (change workspace only)' ;;
164
+ T3) printf 'omx / T3 (change plus plan workspace)' ;;
165
+ *) printf 'unknown / %s' "${OPENSPEC_TIER:-unset}" ;;
166
+ esac
167
+ }
168
+
33
169
  AUTO_FINISH="$(normalize_bool "$AUTO_FINISH_RAW" "1")"
34
170
  AUTO_REVIEW_ON_CONFLICT="$(normalize_bool "$AUTO_REVIEW_ON_CONFLICT_RAW" "1")"
35
171
  AUTO_CLEANUP="$(normalize_bool "$AUTO_CLEANUP_RAW" "1")"
@@ -40,7 +176,7 @@ resolve_openspec_masterplan_label() {
40
176
  local raw="${OPENSPEC_MASTERPLAN_LABEL_RAW:-}"
41
177
  local label
42
178
 
43
- if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ -z "$raw" ]]; then
179
+ if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ "$OPENSPEC_SKIP_PLAN" -eq 1 ]] || [[ -z "$raw" ]]; then
44
180
  printf ''
45
181
  return 0
46
182
  fi
@@ -68,6 +204,10 @@ while [[ $# -gt 0 ]]; do
68
204
  BASE_BRANCH_EXPLICIT=1
69
205
  shift 2
70
206
  ;;
207
+ --tier)
208
+ OPENSPEC_TIER_RAW="${2:-$OPENSPEC_TIER_RAW}"
209
+ shift 2
210
+ ;;
71
211
  --codex-bin)
72
212
  CODEX_BIN="${2:-$CODEX_BIN}"
73
213
  shift 2
@@ -133,6 +273,10 @@ if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
133
273
  exit 1
134
274
  fi
135
275
 
276
+ if ! decide_task_routing; then
277
+ exit 1
278
+ fi
279
+
136
280
  if ! command -v "$CODEX_BIN" >/dev/null 2>&1; then
137
281
  echo "[codex-agent] Missing Codex CLI command: $CODEX_BIN" >&2
138
282
  echo "[codex-agent] Install Codex first, then retry." >&2
@@ -375,12 +519,7 @@ start_sandbox_fallback() {
375
519
  printf '[agent-branch-start] Worktree: %s\n' "$worktree_path"
376
520
  }
377
521
 
378
- if [[ ! -x "${repo_root}/scripts/agent-branch-start.sh" ]]; then
379
- echo "[codex-agent] Missing scripts/agent-branch-start.sh. Run: gx setup" >&2
380
- exit 1
381
- fi
382
-
383
- start_args=("$TASK_NAME" "$AGENT_NAME")
522
+ start_args=(--tier "$OPENSPEC_TIER" "$TASK_NAME" "$AGENT_NAME")
384
523
  if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
385
524
  start_args+=("$BASE_BRANCH")
386
525
  fi
@@ -392,7 +531,7 @@ set +e
392
531
  start_output="$(
393
532
  GUARDEX_OPENSPEC_AUTO_INIT="$OPENSPEC_AUTO_INIT" \
394
533
  GUARDEX_OPENSPEC_MASTERPLAN_LABEL="$OPENSPEC_MASTERPLAN_LABEL_RAW" \
395
- bash "${repo_root}/scripts/agent-branch-start.sh" "${start_args[@]}" 2>&1
534
+ run_guardex_cli branch start "${start_args[@]}" 2>&1
396
535
  )"
397
536
  start_status=$?
398
537
  set -e
@@ -474,7 +613,10 @@ record_active_session_state() {
474
613
  --agent "$AGENT_NAME" \
475
614
  --worktree "$wt" \
476
615
  --pid "$$" \
477
- --cli "$CODEX_BIN"
616
+ --cli "$CODEX_BIN" \
617
+ --task-mode "$TASK_MODE" \
618
+ --openspec-tier "$OPENSPEC_TIER" \
619
+ --routing-reason "$TASK_ROUTING_REASON"
478
620
  }
479
621
 
480
622
  clear_active_session_state() {
@@ -529,9 +671,10 @@ print_takeover_prompt() {
529
671
  change_artifact="openspec/changes/${change_slug}/"
530
672
  fi
531
673
 
532
- finish_cmd="bash scripts/agent-branch-finish.sh --branch \"${branch}\" --base ${base_branch} --via-pr --wait-for-merge --cleanup"
674
+ finish_cmd="gx branch finish --branch \"${branch}\" --base ${base_branch} --via-pr --wait-for-merge --cleanup"
533
675
 
534
676
  echo "[codex-agent] Takeover sandbox: ${wt}"
677
+ echo "[codex-agent] Takeover routing: $(describe_task_routing) (${TASK_ROUTING_REASON})"
535
678
  echo "[codex-agent] Takeover prompt: Continue \`${change_slug}\` on branch \`${branch}\`. Work inside \`${wt}\`, review \`${change_artifact}\`, continue from the current state instead of creating a new sandbox, and when the work is done run \`${finish_cmd}\`."
536
679
  }
537
680
 
@@ -581,28 +724,16 @@ ensure_openspec_plan_workspace() {
581
724
  local wt="$1"
582
725
  local branch="$2"
583
726
 
584
- if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]]; then
727
+ if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ "$OPENSPEC_SKIP_PLAN" -eq 1 ]]; then
585
728
  return 0
586
729
  fi
587
730
 
588
- hydrate_local_helper_in_worktree "$wt" "scripts/openspec/init-plan-workspace.sh"
589
-
590
- local openspec_script="${wt}/scripts/openspec/init-plan-workspace.sh"
591
- if [[ ! -f "$openspec_script" ]]; then
592
- echo "[codex-agent] Missing OpenSpec init script in sandbox: ${openspec_script}" >&2
593
- echo "[codex-agent] Run 'gx setup --target ${repo_root}' and retry." >&2
594
- return 1
595
- fi
596
- if [[ ! -x "$openspec_script" ]]; then
597
- chmod +x "$openspec_script" 2>/dev/null || true
598
- fi
599
-
600
731
  local plan_slug
601
732
  plan_slug="$(resolve_openspec_plan_slug "$branch")"
602
733
  local init_output=""
603
734
  if ! init_output="$(
604
735
  cd "$wt"
605
- bash "scripts/openspec/init-plan-workspace.sh" "$plan_slug" 2>&1
736
+ run_guardex_cli internal run-shell planInit "$plan_slug" 2>&1
606
737
  )"; then
607
738
  printf '%s\n' "$init_output" >&2
608
739
  echo "[codex-agent] OpenSpec workspace initialization failed for plan '${plan_slug}'." >&2
@@ -618,28 +749,17 @@ ensure_openspec_change_workspace() {
618
749
  local wt="$1"
619
750
  local branch="$2"
620
751
 
621
- if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]]; then
752
+ if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ "$OPENSPEC_SKIP_CHANGE" -eq 1 ]]; then
622
753
  return 0
623
754
  fi
624
755
 
625
- hydrate_local_helper_in_worktree "$wt" "scripts/openspec/init-change-workspace.sh"
626
-
627
- local openspec_script="${wt}/scripts/openspec/init-change-workspace.sh"
628
- if [[ ! -f "$openspec_script" ]]; then
629
- echo "[codex-agent] Missing OpenSpec change init script in sandbox: ${openspec_script}" >&2
630
- echo "[codex-agent] Run 'gx setup --target ${repo_root}' and retry." >&2
631
- return 1
632
- fi
633
- if [[ ! -x "$openspec_script" ]]; then
634
- chmod +x "$openspec_script" 2>/dev/null || true
635
- fi
636
-
637
756
  local change_slug capability_slug init_output=""
638
757
  change_slug="$(resolve_openspec_change_slug "$branch")"
639
758
  capability_slug="$(resolve_openspec_capability_slug)"
640
759
  if ! init_output="$(
641
760
  cd "$wt"
642
- bash "scripts/openspec/init-change-workspace.sh" "$change_slug" "$capability_slug" 2>&1
761
+ GUARDEX_OPENSPEC_MINIMAL="$OPENSPEC_MINIMAL" \
762
+ run_guardex_cli internal run-shell changeInit "$change_slug" "$capability_slug" 2>&1
643
763
  )"; then
644
764
  printf '%s\n' "$init_output" >&2
645
765
  echo "[codex-agent] OpenSpec workspace initialization failed for change '${change_slug}'." >&2
@@ -668,11 +788,6 @@ worktree_has_changes() {
668
788
  claim_changed_files() {
669
789
  local wt="$1"
670
790
  local branch="$2"
671
- local lock_script="${repo_root}/scripts/agent-file-locks.py"
672
-
673
- if [[ ! -x "$lock_script" ]]; then
674
- return 0
675
- fi
676
791
 
677
792
  local changed_raw deleted_raw
678
793
  changed_raw="$({
@@ -683,7 +798,7 @@ claim_changed_files() {
683
798
 
684
799
  if [[ -n "$changed_raw" ]]; then
685
800
  mapfile -t changed_files < <(printf '%s\n' "$changed_raw")
686
- python3 "$lock_script" claim --branch "$branch" "${changed_files[@]}" >/dev/null 2>&1 || true
801
+ run_guardex_cli locks claim --branch "$branch" "${changed_files[@]}" >/dev/null 2>&1 || true
687
802
  fi
688
803
 
689
804
  deleted_raw="$({
@@ -693,7 +808,7 @@ claim_changed_files() {
693
808
 
694
809
  if [[ -n "$deleted_raw" ]]; then
695
810
  mapfile -t deleted_files < <(printf '%s\n' "$deleted_raw")
696
- python3 "$lock_script" allow-delete --branch "$branch" "${deleted_files[@]}" >/dev/null 2>&1 || true
811
+ run_guardex_cli locks allow-delete --branch "$branch" "${deleted_files[@]}" >/dev/null 2>&1 || true
697
812
  fi
698
813
  }
699
814
 
@@ -842,7 +957,7 @@ run_finish_flow() {
842
957
  return 2
843
958
  fi
844
959
 
845
- if finish_output="$(bash "${repo_root}/scripts/agent-branch-finish.sh" "${finish_args[@]}" 2>&1)"; then
960
+ if finish_output="$(run_guardex_cli branch finish "${finish_args[@]}" 2>&1)"; then
846
961
  printf '%s\n' "$finish_output"
847
962
  return 0
848
963
  fi
@@ -865,7 +980,7 @@ run_finish_flow() {
865
980
  fi
866
981
  )
867
982
 
868
- if finish_output="$(bash "${repo_root}/scripts/agent-branch-finish.sh" "${finish_args[@]}" 2>&1)"; then
983
+ if finish_output="$(run_guardex_cli branch finish "${finish_args[@]}" 2>&1)"; then
869
984
  printf '%s\n' "$finish_output"
870
985
  return 0
871
986
  fi
@@ -894,6 +1009,8 @@ if ! ensure_openspec_plan_workspace "$worktree_path" "$worktree_branch"; then
894
1009
  exit 1
895
1010
  fi
896
1011
 
1012
+ echo "[codex-agent] Task routing: $(describe_task_routing) (${TASK_ROUTING_REASON})"
1013
+
897
1014
  active_session_recorded=0
898
1015
  cleanup_active_session_state_on_exit() {
899
1016
  set +e
@@ -910,7 +1027,10 @@ trap cleanup_active_session_state_on_exit EXIT INT TERM
910
1027
  echo "[codex-agent] Launching ${CODEX_BIN} in sandbox: $worktree_path"
911
1028
  cd "$worktree_path"
912
1029
  set +e
913
- "$CODEX_BIN" "$@"
1030
+ GUARDEX_TASK_MODE="$TASK_MODE" \
1031
+ GUARDEX_OPENSPEC_TIER="$OPENSPEC_TIER" \
1032
+ GUARDEX_TASK_ROUTING_REASON="$TASK_ROUTING_REASON" \
1033
+ "$CODEX_BIN" "$@"
914
1034
  codex_exit="$?"
915
1035
  set -e
916
1036
 
@@ -954,18 +1074,16 @@ if [[ "$AUTO_FINISH" -eq 1 && -n "$worktree_branch" && "$worktree_branch" != "HE
954
1074
  fi
955
1075
  fi
956
1076
 
957
- if [[ -x "${repo_root}/scripts/agent-worktree-prune.sh" ]]; then
958
- echo "[codex-agent] Session ended (exit=${codex_exit}). Running worktree cleanup..."
959
- prune_args=()
960
- if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
961
- prune_args+=(--base "$BASE_BRANCH")
962
- fi
963
- if [[ "$AUTO_CLEANUP" -eq 1 && "$auto_finish_completed" -eq 1 ]]; then
964
- prune_args+=(--only-dirty-worktrees --delete-branches --delete-remote-branches)
965
- fi
966
- if ! bash "${repo_root}/scripts/agent-worktree-prune.sh" "${prune_args[@]}"; then
967
- echo "[codex-agent] Warning: automatic worktree cleanup failed." >&2
968
- fi
1077
+ echo "[codex-agent] Session ended (exit=${codex_exit}). Running worktree cleanup..."
1078
+ prune_args=()
1079
+ if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
1080
+ prune_args+=(--base "$BASE_BRANCH")
1081
+ fi
1082
+ if [[ "$AUTO_CLEANUP" -eq 1 && "$auto_finish_completed" -eq 1 ]]; then
1083
+ prune_args+=(--only-dirty-worktrees --delete-branches --delete-remote-branches)
1084
+ fi
1085
+ if ! run_guardex_cli worktree prune "${prune_args[@]}"; then
1086
+ echo "[codex-agent] Warning: automatic worktree cleanup failed." >&2
969
1087
  fi
970
1088
 
971
1089
  if [[ ! -d "$worktree_path" ]]; then
@@ -978,7 +1096,7 @@ else
978
1096
  echo "[codex-agent] Branch kept intentionally. Cleanup on demand: gx cleanup --branch \"${worktree_branch}\""
979
1097
  else
980
1098
  print_takeover_prompt "$worktree_path" "$worktree_branch"
981
- echo "[codex-agent] If finished, merge with: bash scripts/agent-branch-finish.sh --branch \"${worktree_branch}\" --base dev --via-pr --wait-for-merge"
1099
+ echo "[codex-agent] If finished, merge with: gx branch finish --branch \"${worktree_branch}\" --base dev --via-pr --wait-for-merge"
982
1100
  echo "[codex-agent] Cleanup on demand: gx cleanup --branch \"${worktree_branch}\""
983
1101
  fi
984
1102
  fi
@@ -9,10 +9,12 @@ BASE_BRANCH="${GUARDEX_REVIEW_BOT_BASE_BRANCH:-}"
9
9
  ONLY_PR="${GUARDEX_REVIEW_BOT_ONLY_PR:-}"
10
10
  RETRY_FAILED_RAW="${GUARDEX_REVIEW_BOT_RETRY_FAILED:-false}"
11
11
  INCLUDE_DRAFT_RAW="${GUARDEX_REVIEW_BOT_INCLUDE_DRAFT:-false}"
12
+ NODE_BIN="${GUARDEX_NODE_BIN:-node}"
13
+ CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
12
14
 
13
15
  usage() {
14
16
  cat <<'USAGE'
15
- Usage: bash scripts/review-bot-watch.sh [options]
17
+ Usage: gx review [options]
16
18
 
17
19
  Continuously monitor GitHub pull requests targeting a base branch and dispatch
18
20
  one Codex-agent task per newly opened/updated PR.
@@ -34,6 +36,23 @@ Environment overrides:
34
36
  USAGE
35
37
  }
36
38
 
39
+ run_guardex_cli() {
40
+ if [[ -n "$CLI_ENTRY" ]]; then
41
+ "$NODE_BIN" "$CLI_ENTRY" "$@"
42
+ return $?
43
+ fi
44
+ if command -v gx >/dev/null 2>&1; then
45
+ gx "$@"
46
+ return $?
47
+ fi
48
+ if command -v gitguardex >/dev/null 2>&1; then
49
+ gitguardex "$@"
50
+ return $?
51
+ fi
52
+ echo "[review-bot-watch] Guardex CLI entrypoint unavailable; rerun via gx." >&2
53
+ return 127
54
+ }
55
+
37
56
  normalize_bool() {
38
57
  local raw="${1:-}"
39
58
  local fallback="${2:-0}"
@@ -134,16 +153,20 @@ if ! command -v codex >/dev/null 2>&1; then
134
153
  exit 127
135
154
  fi
136
155
 
137
- if [[ ! -x "$repo_root/scripts/codex-agent.sh" ]]; then
138
- echo "[review-bot-watch] Missing scripts/codex-agent.sh. Run: gx setup" >&2
139
- exit 1
140
- fi
141
-
142
156
  if ! gh auth status >/dev/null 2>&1; then
143
157
  echo "[review-bot-watch] gh is not authenticated. Run: gh auth login" >&2
144
158
  exit 1
145
159
  fi
146
160
 
161
+ run_codex_agent() {
162
+ local local_script="$repo_root/scripts/codex-agent.sh"
163
+ if [[ -x "$local_script" ]]; then
164
+ bash "$local_script" "$@"
165
+ return $?
166
+ fi
167
+ run_guardex_cli internal run-shell codexAgent --target "$repo_root" "$@"
168
+ }
169
+
147
170
  sanitize_slug() {
148
171
  local raw="$1"
149
172
  local fallback="$2"
@@ -262,7 +285,7 @@ process_one_pr() {
262
285
 
263
286
  echo "[review-bot-watch] Dispatching Codex agent for PR #${pr} (${head_branch})"
264
287
  set +e
265
- bash "$repo_root/scripts/codex-agent.sh" \
288
+ run_codex_agent \
266
289
  --task "$task_name" \
267
290
  --agent "$AGENT_NAME" \
268
291
  --base "$BASE_BRANCH" \
@@ -2,20 +2,26 @@
2
2
 
3
3
  Local VS Code companion for Guardex-managed repos.
4
4
 
5
- What it does:
5
+ ## Quick Start
6
6
 
7
- - Adds an `Active Agents` view to the Source Control container.
8
- - Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
9
- - Shows one row per live Guardex sandbox session inside the repo's `ACTIVE AGENTS` section.
10
- - Shows repo-root git changes in a sibling `CHANGES` section when the guarded repo itself is dirty.
11
- - Derives `thinking` versus `working` from the live sandbox worktree and shows changed-file counts for active edits.
12
- - Uses VS Code's native animated `loading~spin` icon for the running-state affordance.
13
- - Reads repo-local presence files from `.omx/state/active-sessions/`.
7
+ Use the welcome view in Source Control to create or inspect Guardex sandboxes quickly.
14
8
 
15
- Install from a Guardex-wired repo:
9
+ 1. Install from a Guardex-wired repo:
16
10
 
17
11
  ```sh
18
12
  node scripts/install-vscode-active-agents-extension.js
19
13
  ```
20
14
 
21
- Then reload the VS Code window.
15
+ 2. Reload the VS Code window.
16
+ 3. In Source Control -> `Active Agents`, use `Start agent` to enter a task + agent name and run `gx branch start`.
17
+
18
+ What it does:
19
+
20
+ - Adds an `Active Agents` view to the Source Control container.
21
+ - Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
22
+ - Splits live sessions inside `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, and `DEAD` groups so stuck, active, and inactive lanes stand out immediately.
23
+ - Shows one row per live Guardex sandbox session inside those activity groups.
24
+ - Shows repo-root git changes in a sibling `CHANGES` section when the guarded repo itself is dirty.
25
+ - Derives session state from dirty worktree status, git conflict markers, PID liveness, and recent file mtimes, surfaces working/dead counts in the repo/header summary, and shows changed-file counts for active edits.
26
+ - Uses distinct VS Code codicons for each session state: `warning`, `edit`, `loading~spin`, `clock`, and `error`.
27
+ - Reads repo-local presence files from `.omx/state/active-sessions/`.