@imdeadpool/guardex 7.0.18 → 7.0.19
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 +28 -19
- package/bin/multiagent-safety.js +199 -122
- package/package.json +1 -1
- 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 +23 -29
- package/templates/scripts/agent-file-locks.py +11 -11
- package/templates/scripts/codex-agent.sh +37 -55
- package/templates/scripts/review-bot-watch.sh +30 -7
- package/templates/vscode/guardex-active-agents/README.md +3 -2
- package/templates/vscode/guardex-active-agents/extension.js +49 -9
|
@@ -24,7 +24,7 @@ echo "$BASE_BRANCH"
|
|
|
24
24
|
2. Start a dedicated integration sandbox from base:
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
|
|
27
|
+
gx branch start "merge-skill-files-to-${BASE_BRANCH}" "skill-merge" "$BASE_BRANCH"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
3. Enter the sandbox worktree printed by the command above.
|
|
@@ -48,11 +48,11 @@ git diff --name-only
|
|
|
48
48
|
```sh
|
|
49
49
|
git add .codex/skills templates/codex/skills
|
|
50
50
|
git commit -m "Merge skill file updates into ${BASE_BRANCH}"
|
|
51
|
-
|
|
51
|
+
gx branch finish --branch "$(git rev-parse --abbrev-ref HEAD)" --base "$BASE_BRANCH" --via-pr --wait-for-merge --cleanup
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
## Notes
|
|
55
55
|
|
|
56
56
|
- If a source branch has non-skill changes, this runbook keeps them out of the merge.
|
|
57
|
-
- If merge conflicts occur, resolve only within the skill files, then rerun `
|
|
57
|
+
- If merge conflicts occur, resolve only within the skill files, then rerun `gx branch finish`.
|
|
58
58
|
- Do not commit directly on `dev`/`main`; always merge through an agent branch/worktree.
|
|
@@ -13,6 +13,8 @@ repo_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
|
13
13
|
if [[ -z "$repo_root" ]]; then
|
|
14
14
|
exit 0
|
|
15
15
|
fi
|
|
16
|
+
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
|
|
17
|
+
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
|
|
16
18
|
guardex_env_helper="${repo_root}/scripts/guardex-env.sh"
|
|
17
19
|
if [[ -f "$guardex_env_helper" ]]; then
|
|
18
20
|
# shellcheck source=/dev/null
|
|
@@ -22,6 +24,23 @@ if declare -F guardex_repo_is_enabled >/dev/null 2>&1 && ! guardex_repo_is_enabl
|
|
|
22
24
|
exit 0
|
|
23
25
|
fi
|
|
24
26
|
|
|
27
|
+
run_guardex_cli() {
|
|
28
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
29
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
30
|
+
return $?
|
|
31
|
+
fi
|
|
32
|
+
if command -v gx >/dev/null 2>&1; then
|
|
33
|
+
gx "$@"
|
|
34
|
+
return $?
|
|
35
|
+
fi
|
|
36
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
37
|
+
gitguardex "$@"
|
|
38
|
+
return $?
|
|
39
|
+
fi
|
|
40
|
+
echo "[agent-branch-guard] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
41
|
+
return 127
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
if [[ "${ALLOW_COMMIT_ON_PROTECTED_BRANCH:-0}" == "1" ]]; then
|
|
26
45
|
exit 0
|
|
27
46
|
fi
|
|
@@ -191,11 +210,11 @@ if [[ "$branch" == agent/* ]]; then
|
|
|
191
210
|
while IFS= read -r staged_file; do
|
|
192
211
|
[[ -z "$staged_file" ]] && continue
|
|
193
212
|
[[ "$staged_file" == ".omx/state/agent-file-locks.json" ]] && continue
|
|
194
|
-
|
|
213
|
+
run_guardex_cli locks claim --branch "$branch" "$staged_file" >/dev/null 2>&1 || true
|
|
195
214
|
done < <(git diff --cached --name-only --diff-filter=ACMRDTUXB)
|
|
196
215
|
fi
|
|
197
216
|
|
|
198
|
-
if !
|
|
217
|
+
if ! run_guardex_cli locks validate --branch "$branch" --staged; then
|
|
199
218
|
cat >&2 <<'MSG'
|
|
200
219
|
[agent-branch-guard] Agent branch commits require file ownership locks.
|
|
201
220
|
Claim files first:
|
|
@@ -9,11 +9,30 @@ DELETE_REMOTE_BRANCH=0
|
|
|
9
9
|
DELETE_REMOTE_BRANCH_EXPLICIT=0
|
|
10
10
|
MERGE_MODE="auto"
|
|
11
11
|
GH_BIN="${GUARDEX_GH_BIN:-gh}"
|
|
12
|
+
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
|
|
13
|
+
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
|
|
12
14
|
CLEANUP_AFTER_MERGE_RAW="${GUARDEX_FINISH_CLEANUP:-false}"
|
|
13
15
|
WAIT_FOR_MERGE_RAW="${GUARDEX_FINISH_WAIT_FOR_MERGE:-false}"
|
|
14
16
|
WAIT_TIMEOUT_SECONDS_RAW="${GUARDEX_FINISH_WAIT_TIMEOUT_SECONDS:-1800}"
|
|
15
17
|
WAIT_POLL_SECONDS_RAW="${GUARDEX_FINISH_WAIT_POLL_SECONDS:-10}"
|
|
16
18
|
|
|
19
|
+
run_guardex_cli() {
|
|
20
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
21
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
22
|
+
return $?
|
|
23
|
+
fi
|
|
24
|
+
if command -v gx >/dev/null 2>&1; then
|
|
25
|
+
gx "$@"
|
|
26
|
+
return $?
|
|
27
|
+
fi
|
|
28
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
29
|
+
gitguardex "$@"
|
|
30
|
+
return $?
|
|
31
|
+
fi
|
|
32
|
+
echo "[agent-branch-finish] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
33
|
+
return 127
|
|
34
|
+
}
|
|
35
|
+
|
|
17
36
|
normalize_bool() {
|
|
18
37
|
local raw="${1:-}"
|
|
19
38
|
local fallback="${2:-0}"
|
|
@@ -431,7 +450,7 @@ run_pr_flow() {
|
|
|
431
450
|
if [[ -z "$pr_title" ]]; then
|
|
432
451
|
pr_title="Merge ${SOURCE_BRANCH} into ${BASE_BRANCH}"
|
|
433
452
|
fi
|
|
434
|
-
pr_body="Automated by
|
|
453
|
+
pr_body="Automated by gx branch finish (PR flow)."
|
|
435
454
|
|
|
436
455
|
"$GH_BIN" pr create \
|
|
437
456
|
--base "$BASE_BRANCH" \
|
|
@@ -517,9 +536,7 @@ if [[ "$PUSH_ENABLED" -eq 1 ]]; then
|
|
|
517
536
|
fi
|
|
518
537
|
fi
|
|
519
538
|
|
|
520
|
-
|
|
521
|
-
python3 "${repo_root}/scripts/agent-file-locks.py" release --branch "$SOURCE_BRANCH" >/dev/null 2>&1 || true
|
|
522
|
-
fi
|
|
539
|
+
run_guardex_cli locks release --branch "$SOURCE_BRANCH" >/dev/null 2>&1 || true
|
|
523
540
|
|
|
524
541
|
base_worktree="$(get_worktree_for_branch "$BASE_BRANCH")"
|
|
525
542
|
if [[ -n "$base_worktree" ]] && is_clean_worktree "$base_worktree" && [[ "$PUSH_ENABLED" -eq 1 ]]; then
|
|
@@ -555,29 +572,25 @@ if [[ "$CLEANUP_AFTER_MERGE" -eq 1 ]]; then
|
|
|
555
572
|
fi
|
|
556
573
|
fi
|
|
557
574
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
echo "[agent-branch-finish] You can run manual cleanup: bash scripts/agent-worktree-prune.sh --base ${BASE_BRANCH} --delete-branches" >&2
|
|
566
|
-
fi
|
|
575
|
+
prune_args=(--base "$BASE_BRANCH" --only-dirty-worktrees --delete-branches)
|
|
576
|
+
if [[ "$DELETE_REMOTE_BRANCH" -eq 1 ]]; then
|
|
577
|
+
prune_args+=(--delete-remote-branches)
|
|
578
|
+
fi
|
|
579
|
+
if ! run_guardex_cli worktree prune "${prune_args[@]}"; then
|
|
580
|
+
echo "[agent-branch-finish] Warning: automatic worktree prune failed." >&2
|
|
581
|
+
echo "[agent-branch-finish] You can run manual cleanup: gx cleanup --base ${BASE_BRANCH}" >&2
|
|
567
582
|
fi
|
|
568
583
|
|
|
569
584
|
echo "[agent-branch-finish] Merged '${SOURCE_BRANCH}' into '${BASE_BRANCH}' via ${merge_status} flow and cleaned source branch/worktree."
|
|
570
585
|
if [[ "$source_worktree" == "$current_worktree" && "$source_worktree" == "${agent_worktree_root}"/* ]]; then
|
|
571
586
|
echo "[agent-branch-finish] Current worktree '${source_worktree}' still exists because it is the active shell cwd." >&2
|
|
572
|
-
echo "[agent-branch-finish] Leave this directory, then run:
|
|
587
|
+
echo "[agent-branch-finish] Leave this directory, then run: gx cleanup --base ${BASE_BRANCH}" >&2
|
|
573
588
|
fi
|
|
574
589
|
else
|
|
575
|
-
if
|
|
576
|
-
|
|
577
|
-
echo "[agent-branch-finish] Warning: temporary worktree prune failed." >&2
|
|
578
|
-
fi
|
|
590
|
+
if ! run_guardex_cli worktree prune --base "$BASE_BRANCH"; then
|
|
591
|
+
echo "[agent-branch-finish] Warning: temporary worktree prune failed." >&2
|
|
579
592
|
fi
|
|
580
593
|
|
|
581
594
|
echo "[agent-branch-finish] Merged '${SOURCE_BRANCH}' into '${BASE_BRANCH}' via ${merge_status} flow and kept source branch/worktree."
|
|
582
|
-
echo "[agent-branch-finish] Cleanup later with:
|
|
595
|
+
echo "[agent-branch-finish] Cleanup later with: gx cleanup --base ${BASE_BRANCH}"
|
|
583
596
|
fi
|
|
@@ -6,18 +6,37 @@ BASE_BRANCH_EXPLICIT=0
|
|
|
6
6
|
TARGET_BRANCH=""
|
|
7
7
|
TASK_NAME=""
|
|
8
8
|
AGENT_NAME="${GUARDEX_MERGE_AGENT_NAME:-codex}"
|
|
9
|
+
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
|
|
10
|
+
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
|
|
9
11
|
declare -a SOURCE_BRANCHES=()
|
|
10
12
|
|
|
11
13
|
usage() {
|
|
12
14
|
cat <<'EOF'
|
|
13
|
-
Usage:
|
|
15
|
+
Usage: gx branch merge --branch <agent/...> [--branch <agent/...> ...] [--into <agent/...>] [--task <task>] [--agent <agent>] [--base <branch>]
|
|
14
16
|
|
|
15
17
|
Examples:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
gx branch merge --branch agent/codex/ui-a --branch agent/codex/ui-b
|
|
19
|
+
gx branch merge --into agent/codex/owner-lane --branch agent/codex/helper-a --branch agent/codex/helper-b
|
|
18
20
|
EOF
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
run_guardex_cli() {
|
|
24
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
25
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
26
|
+
return $?
|
|
27
|
+
fi
|
|
28
|
+
if command -v gx >/dev/null 2>&1; then
|
|
29
|
+
gx "$@"
|
|
30
|
+
return $?
|
|
31
|
+
fi
|
|
32
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
33
|
+
gitguardex "$@"
|
|
34
|
+
return $?
|
|
35
|
+
fi
|
|
36
|
+
echo "[agent-branch-merge] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
37
|
+
return 127
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
sanitize_slug() {
|
|
22
41
|
local raw="$1"
|
|
23
42
|
local fallback="${2:-merge-agent-branches}"
|
|
@@ -262,7 +281,7 @@ if [[ -z "$TARGET_BRANCH" ]]; then
|
|
|
262
281
|
start_output=""
|
|
263
282
|
if ! start_output="$(
|
|
264
283
|
cd "$repo_root"
|
|
265
|
-
|
|
284
|
+
GUARDEX_OPENSPEC_AUTO_INIT=1 run_guardex_cli branch start "$TASK_NAME" "$AGENT_NAME" "$BASE_BRANCH" 2>&1
|
|
266
285
|
)"; then
|
|
267
286
|
printf '%s\n' "$start_output" >&2
|
|
268
287
|
exit 1
|
|
@@ -418,4 +437,4 @@ echo "[agent-branch-merge] Merge sequence complete for '${TARGET_BRANCH}'."
|
|
|
418
437
|
if [[ "$target_created" -eq 1 ]]; then
|
|
419
438
|
echo "[agent-branch-merge] Review and verify in '${target_worktree}', then finish the integration branch when ready."
|
|
420
439
|
fi
|
|
421
|
-
echo "[agent-branch-merge] Next step:
|
|
440
|
+
echo "[agent-branch-merge] Next step: gx branch finish --branch \"${TARGET_BRANCH}\" --base \"${BASE_BRANCH}\" --via-pr --wait-for-merge --cleanup"
|
|
@@ -7,6 +7,8 @@ BASE_BRANCH=""
|
|
|
7
7
|
BASE_BRANCH_EXPLICIT=0
|
|
8
8
|
WORKTREE_ROOT_REL=""
|
|
9
9
|
WORKTREE_ROOT_EXPLICIT=0
|
|
10
|
+
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
|
|
11
|
+
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
|
|
10
12
|
OPENSPEC_AUTO_INIT_RAW="${GUARDEX_OPENSPEC_AUTO_INIT:-false}"
|
|
11
13
|
OPENSPEC_PLAN_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_PLAN_SLUG:-}"
|
|
12
14
|
OPENSPEC_CHANGE_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CHANGE_SLUG:-}"
|
|
@@ -15,6 +17,23 @@ OPENSPEC_MASTERPLAN_LABEL_RAW="${GUARDEX_OPENSPEC_MASTERPLAN_LABEL-masterplan}"
|
|
|
15
17
|
PRINT_NAME_ONLY=0
|
|
16
18
|
POSITIONAL_ARGS=()
|
|
17
19
|
|
|
20
|
+
run_guardex_cli() {
|
|
21
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
22
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
23
|
+
return $?
|
|
24
|
+
fi
|
|
25
|
+
if command -v gx >/dev/null 2>&1; then
|
|
26
|
+
gx "$@"
|
|
27
|
+
return $?
|
|
28
|
+
fi
|
|
29
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
30
|
+
gitguardex "$@"
|
|
31
|
+
return $?
|
|
32
|
+
fi
|
|
33
|
+
echo "[agent-branch-start] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
34
|
+
return 127
|
|
35
|
+
}
|
|
36
|
+
|
|
18
37
|
while [[ $# -gt 0 ]]; do
|
|
19
38
|
case "$1" in
|
|
20
39
|
--task)
|
|
@@ -385,26 +404,14 @@ initialize_openspec_plan_workspace() {
|
|
|
385
404
|
local worktree="$2"
|
|
386
405
|
local plan_slug="$3"
|
|
387
406
|
|
|
388
|
-
hydrate_local_helper_in_worktree "$repo" "$worktree" "scripts/openspec/init-plan-workspace.sh"
|
|
389
|
-
|
|
390
407
|
if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]]; then
|
|
391
408
|
return 0
|
|
392
409
|
fi
|
|
393
410
|
|
|
394
|
-
local openspec_script="${worktree}/scripts/openspec/init-plan-workspace.sh"
|
|
395
|
-
if [[ ! -f "$openspec_script" ]]; then
|
|
396
|
-
echo "[agent-branch-start] OpenSpec init script is missing in sandbox worktree." >&2
|
|
397
|
-
echo "[agent-branch-start] Run 'gx setup --target \"$repo\"' to repair templates, then retry." >&2
|
|
398
|
-
return 1
|
|
399
|
-
fi
|
|
400
|
-
if [[ ! -x "$openspec_script" ]]; then
|
|
401
|
-
chmod +x "$openspec_script" 2>/dev/null || true
|
|
402
|
-
fi
|
|
403
|
-
|
|
404
411
|
local init_output=""
|
|
405
412
|
if ! init_output="$(
|
|
406
413
|
cd "$worktree"
|
|
407
|
-
|
|
414
|
+
run_guardex_cli internal run-shell planInit "$plan_slug" 2>&1
|
|
408
415
|
)"; then
|
|
409
416
|
printf '%s\n' "$init_output" >&2
|
|
410
417
|
echo "[agent-branch-start] OpenSpec workspace initialization failed for plan '${plan_slug}'." >&2
|
|
@@ -423,26 +430,14 @@ initialize_openspec_change_workspace() {
|
|
|
423
430
|
local change_slug="$3"
|
|
424
431
|
local capability_slug="$4"
|
|
425
432
|
|
|
426
|
-
hydrate_local_helper_in_worktree "$repo" "$worktree" "scripts/openspec/init-change-workspace.sh"
|
|
427
|
-
|
|
428
433
|
if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]]; then
|
|
429
434
|
return 0
|
|
430
435
|
fi
|
|
431
436
|
|
|
432
|
-
local openspec_script="${worktree}/scripts/openspec/init-change-workspace.sh"
|
|
433
|
-
if [[ ! -f "$openspec_script" ]]; then
|
|
434
|
-
echo "[agent-branch-start] OpenSpec change init script is missing in sandbox worktree." >&2
|
|
435
|
-
echo "[agent-branch-start] Run 'gx setup --target \"$repo\"' to repair templates, then retry." >&2
|
|
436
|
-
return 1
|
|
437
|
-
fi
|
|
438
|
-
if [[ ! -x "$openspec_script" ]]; then
|
|
439
|
-
chmod +x "$openspec_script" 2>/dev/null || true
|
|
440
|
-
fi
|
|
441
|
-
|
|
442
437
|
local init_output=""
|
|
443
438
|
if ! init_output="$(
|
|
444
439
|
cd "$worktree"
|
|
445
|
-
|
|
440
|
+
run_guardex_cli internal run-shell changeInit "$change_slug" "$capability_slug" 2>&1
|
|
446
441
|
)"; then
|
|
447
442
|
printf '%s\n' "$init_output" >&2
|
|
448
443
|
echo "[agent-branch-start] OpenSpec workspace initialization failed for change '${change_slug}'." >&2
|
|
@@ -592,7 +587,6 @@ if [[ -n "$auto_transfer_stash_ref" ]]; then
|
|
|
592
587
|
fi
|
|
593
588
|
fi
|
|
594
589
|
|
|
595
|
-
hydrate_local_helper_in_worktree "$repo_root" "$worktree_path" "scripts/codex-agent.sh"
|
|
596
590
|
hydrate_dependency_dir_symlink_in_worktree "$repo_root" "$worktree_path" "node_modules"
|
|
597
591
|
hydrate_dependency_dir_symlink_in_worktree "$repo_root" "$worktree_path" "apps/frontend/node_modules"
|
|
598
592
|
hydrate_dependency_dir_symlink_in_worktree "$repo_root" "$worktree_path" "apps/backend/node_modules"
|
|
@@ -609,6 +603,6 @@ echo "[agent-branch-start] OpenSpec change: openspec/changes/${openspec_change_s
|
|
|
609
603
|
echo "[agent-branch-start] OpenSpec plan: openspec/plan/${openspec_plan_slug}"
|
|
610
604
|
echo "[agent-branch-start] Next steps:"
|
|
611
605
|
echo " cd \"${worktree_path}\""
|
|
612
|
-
echo "
|
|
606
|
+
echo " gx locks claim --branch \"${branch_name}\" <file...>"
|
|
613
607
|
echo " # implement + commit"
|
|
614
|
-
echo "
|
|
608
|
+
echo " gx branch finish --branch \"${branch_name}\" --base ${BASE_BRANCH} --via-pr --wait-for-merge"
|
|
@@ -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}"
|
|
@@ -17,6 +18,23 @@ 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}"
|
|
19
20
|
|
|
21
|
+
run_guardex_cli() {
|
|
22
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
23
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
24
|
+
return $?
|
|
25
|
+
fi
|
|
26
|
+
if command -v gx >/dev/null 2>&1; then
|
|
27
|
+
gx "$@"
|
|
28
|
+
return $?
|
|
29
|
+
fi
|
|
30
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
31
|
+
gitguardex "$@"
|
|
32
|
+
return $?
|
|
33
|
+
fi
|
|
34
|
+
echo "[codex-agent] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
35
|
+
return 127
|
|
36
|
+
}
|
|
37
|
+
|
|
20
38
|
normalize_bool() {
|
|
21
39
|
local raw="${1:-}"
|
|
22
40
|
local fallback="${2:-0}"
|
|
@@ -375,11 +393,6 @@ start_sandbox_fallback() {
|
|
|
375
393
|
printf '[agent-branch-start] Worktree: %s\n' "$worktree_path"
|
|
376
394
|
}
|
|
377
395
|
|
|
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
396
|
start_args=("$TASK_NAME" "$AGENT_NAME")
|
|
384
397
|
if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
|
|
385
398
|
start_args+=("$BASE_BRANCH")
|
|
@@ -392,7 +405,7 @@ set +e
|
|
|
392
405
|
start_output="$(
|
|
393
406
|
GUARDEX_OPENSPEC_AUTO_INIT="$OPENSPEC_AUTO_INIT" \
|
|
394
407
|
GUARDEX_OPENSPEC_MASTERPLAN_LABEL="$OPENSPEC_MASTERPLAN_LABEL_RAW" \
|
|
395
|
-
|
|
408
|
+
run_guardex_cli branch start "${start_args[@]}" 2>&1
|
|
396
409
|
)"
|
|
397
410
|
start_status=$?
|
|
398
411
|
set -e
|
|
@@ -529,7 +542,7 @@ print_takeover_prompt() {
|
|
|
529
542
|
change_artifact="openspec/changes/${change_slug}/"
|
|
530
543
|
fi
|
|
531
544
|
|
|
532
|
-
finish_cmd="
|
|
545
|
+
finish_cmd="gx branch finish --branch \"${branch}\" --base ${base_branch} --via-pr --wait-for-merge --cleanup"
|
|
533
546
|
|
|
534
547
|
echo "[codex-agent] Takeover sandbox: ${wt}"
|
|
535
548
|
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}\`."
|
|
@@ -585,24 +598,12 @@ ensure_openspec_plan_workspace() {
|
|
|
585
598
|
return 0
|
|
586
599
|
fi
|
|
587
600
|
|
|
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
601
|
local plan_slug
|
|
601
602
|
plan_slug="$(resolve_openspec_plan_slug "$branch")"
|
|
602
603
|
local init_output=""
|
|
603
604
|
if ! init_output="$(
|
|
604
605
|
cd "$wt"
|
|
605
|
-
|
|
606
|
+
run_guardex_cli internal run-shell planInit "$plan_slug" 2>&1
|
|
606
607
|
)"; then
|
|
607
608
|
printf '%s\n' "$init_output" >&2
|
|
608
609
|
echo "[codex-agent] OpenSpec workspace initialization failed for plan '${plan_slug}'." >&2
|
|
@@ -622,24 +623,12 @@ ensure_openspec_change_workspace() {
|
|
|
622
623
|
return 0
|
|
623
624
|
fi
|
|
624
625
|
|
|
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
626
|
local change_slug capability_slug init_output=""
|
|
638
627
|
change_slug="$(resolve_openspec_change_slug "$branch")"
|
|
639
628
|
capability_slug="$(resolve_openspec_capability_slug)"
|
|
640
629
|
if ! init_output="$(
|
|
641
630
|
cd "$wt"
|
|
642
|
-
|
|
631
|
+
run_guardex_cli internal run-shell changeInit "$change_slug" "$capability_slug" 2>&1
|
|
643
632
|
)"; then
|
|
644
633
|
printf '%s\n' "$init_output" >&2
|
|
645
634
|
echo "[codex-agent] OpenSpec workspace initialization failed for change '${change_slug}'." >&2
|
|
@@ -668,11 +657,6 @@ worktree_has_changes() {
|
|
|
668
657
|
claim_changed_files() {
|
|
669
658
|
local wt="$1"
|
|
670
659
|
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
660
|
|
|
677
661
|
local changed_raw deleted_raw
|
|
678
662
|
changed_raw="$({
|
|
@@ -683,7 +667,7 @@ claim_changed_files() {
|
|
|
683
667
|
|
|
684
668
|
if [[ -n "$changed_raw" ]]; then
|
|
685
669
|
mapfile -t changed_files < <(printf '%s\n' "$changed_raw")
|
|
686
|
-
|
|
670
|
+
run_guardex_cli locks claim --branch "$branch" "${changed_files[@]}" >/dev/null 2>&1 || true
|
|
687
671
|
fi
|
|
688
672
|
|
|
689
673
|
deleted_raw="$({
|
|
@@ -693,7 +677,7 @@ claim_changed_files() {
|
|
|
693
677
|
|
|
694
678
|
if [[ -n "$deleted_raw" ]]; then
|
|
695
679
|
mapfile -t deleted_files < <(printf '%s\n' "$deleted_raw")
|
|
696
|
-
|
|
680
|
+
run_guardex_cli locks allow-delete --branch "$branch" "${deleted_files[@]}" >/dev/null 2>&1 || true
|
|
697
681
|
fi
|
|
698
682
|
}
|
|
699
683
|
|
|
@@ -842,7 +826,7 @@ run_finish_flow() {
|
|
|
842
826
|
return 2
|
|
843
827
|
fi
|
|
844
828
|
|
|
845
|
-
if finish_output="$(
|
|
829
|
+
if finish_output="$(run_guardex_cli branch finish "${finish_args[@]}" 2>&1)"; then
|
|
846
830
|
printf '%s\n' "$finish_output"
|
|
847
831
|
return 0
|
|
848
832
|
fi
|
|
@@ -865,7 +849,7 @@ run_finish_flow() {
|
|
|
865
849
|
fi
|
|
866
850
|
)
|
|
867
851
|
|
|
868
|
-
if finish_output="$(
|
|
852
|
+
if finish_output="$(run_guardex_cli branch finish "${finish_args[@]}" 2>&1)"; then
|
|
869
853
|
printf '%s\n' "$finish_output"
|
|
870
854
|
return 0
|
|
871
855
|
fi
|
|
@@ -954,18 +938,16 @@ if [[ "$AUTO_FINISH" -eq 1 && -n "$worktree_branch" && "$worktree_branch" != "HE
|
|
|
954
938
|
fi
|
|
955
939
|
fi
|
|
956
940
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
echo "[codex-agent] Warning: automatic worktree cleanup failed." >&2
|
|
968
|
-
fi
|
|
941
|
+
echo "[codex-agent] Session ended (exit=${codex_exit}). Running worktree cleanup..."
|
|
942
|
+
prune_args=()
|
|
943
|
+
if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
|
|
944
|
+
prune_args+=(--base "$BASE_BRANCH")
|
|
945
|
+
fi
|
|
946
|
+
if [[ "$AUTO_CLEANUP" -eq 1 && "$auto_finish_completed" -eq 1 ]]; then
|
|
947
|
+
prune_args+=(--only-dirty-worktrees --delete-branches --delete-remote-branches)
|
|
948
|
+
fi
|
|
949
|
+
if ! run_guardex_cli worktree prune "${prune_args[@]}"; then
|
|
950
|
+
echo "[codex-agent] Warning: automatic worktree cleanup failed." >&2
|
|
969
951
|
fi
|
|
970
952
|
|
|
971
953
|
if [[ ! -d "$worktree_path" ]]; then
|
|
@@ -978,7 +960,7 @@ else
|
|
|
978
960
|
echo "[codex-agent] Branch kept intentionally. Cleanup on demand: gx cleanup --branch \"${worktree_branch}\""
|
|
979
961
|
else
|
|
980
962
|
print_takeover_prompt "$worktree_path" "$worktree_branch"
|
|
981
|
-
echo "[codex-agent] If finished, merge with:
|
|
963
|
+
echo "[codex-agent] If finished, merge with: gx branch finish --branch \"${worktree_branch}\" --base dev --via-pr --wait-for-merge"
|
|
982
964
|
echo "[codex-agent] Cleanup on demand: gx cleanup --branch \"${worktree_branch}\""
|
|
983
965
|
fi
|
|
984
966
|
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" \
|
|
@@ -6,9 +6,10 @@ What it does:
|
|
|
6
6
|
|
|
7
7
|
- Adds an `Active Agents` view to the Source Control container.
|
|
8
8
|
- Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
|
|
9
|
-
-
|
|
9
|
+
- Splits live sessions inside `ACTIVE AGENTS` into `WORKING NOW` and `THINKING` groups so active edit lanes stand out immediately.
|
|
10
|
+
- Shows one row per live Guardex sandbox session inside those activity groups.
|
|
10
11
|
- 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
|
+
- Derives `thinking` versus `working` from the live sandbox worktree, surfaces working counts in the repo/header summary, and shows changed-file counts for active edits.
|
|
12
13
|
- Uses VS Code's native animated `loading~spin` icon for the running-state affordance.
|
|
13
14
|
- Reads repo-local presence files from `.omx/state/active-sessions/`.
|
|
14
15
|
|