@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.
- package/README.md +34 -19
- package/bin/multiagent-safety.js +2 -7784
- package/package.json +2 -1
- package/src/cli/args.js +7 -0
- package/src/cli/dispatch.js +86 -0
- package/src/cli/main.js +7719 -0
- package/src/context.js +503 -0
- package/src/core/runtime.js +119 -0
- package/src/finish/index.js +425 -0
- package/src/git/index.js +112 -0
- package/src/hooks/index.js +74 -0
- package/src/output/index.js +398 -0
- package/src/sandbox/index.js +68 -0
- package/src/scaffold/index.js +169 -0
- package/src/toolchain/index.js +223 -0
- package/templates/AGENTS.multiagent-safety.md +3 -0
- package/templates/codex/skills/gitguardex/SKILL.md +1 -1
- package/templates/codex/skills/guardex-merge-skills-to-dev/SKILL.md +3 -3
- package/templates/githooks/pre-commit +21 -2
- package/templates/scripts/agent-branch-finish.sh +32 -19
- package/templates/scripts/agent-branch-merge.sh +24 -5
- package/templates/scripts/agent-branch-start.sh +74 -36
- package/templates/scripts/agent-file-locks.py +11 -11
- package/templates/scripts/codex-agent.sh +179 -61
- package/templates/scripts/review-bot-watch.sh +30 -7
- package/templates/vscode/guardex-active-agents/README.md +16 -10
- package/templates/vscode/guardex-active-agents/extension.js +901 -49
- package/templates/vscode/guardex-active-agents/package.json +61 -1
- package/templates/vscode/guardex-active-agents/session-schema.js +211 -17
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"""Per-file lock registry for concurrent agent branches.
|
|
3
3
|
|
|
4
4
|
Usage examples:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'scripts/
|
|
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'
|
|
329
|
+
f' gx locks claim --branch "{args.branch}" --allow-delete <file...>',
|
|
330
330
|
file=sys.stderr,
|
|
331
331
|
)
|
|
332
332
|
print(
|
|
333
|
-
f'
|
|
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'
|
|
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
|
-
|
|
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
|
-
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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="$(
|
|
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="$(
|
|
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
|
-
"$
|
|
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
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
|
-
|
|
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
|
-
|
|
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/`.
|