@imdeadpool/guardex 7.0.23 → 7.0.25
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 +30 -3
- package/package.json +1 -1
- package/src/cli/args.js +9 -0
- package/src/cli/main.js +7 -2
- package/src/context.js +22 -0
- package/src/doctor/index.js +158 -5
- package/src/finish/index.js +1 -0
- package/src/report/session-severity.js +77 -8
- package/templates/AGENTS.multiagent-safety.md +3 -0
- package/templates/codex/skills/guardex-merge-skills-to-dev/SKILL.md +3 -2
- package/templates/scripts/agent-branch-finish.sh +155 -5
- package/templates/scripts/agent-branch-start.sh +35 -0
- package/templates/scripts/agent-worktree-prune.sh +22 -1
- package/templates/vscode/guardex-active-agents/README.md +6 -3
- package/templates/vscode/guardex-active-agents/extension.js +1706 -247
- package/templates/vscode/guardex-active-agents/fileicons/gitguardex-fileicons.json +54 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/agent.svg +4 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/branch.svg +4 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/config.svg +4 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/hook.svg +3 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/openspec.svg +5 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/plan.svg +4 -0
- package/templates/vscode/guardex-active-agents/fileicons/icons/spec.svg +4 -0
- package/templates/vscode/guardex-active-agents/media/active-agents-hivemind.svg +14 -0
- package/templates/vscode/guardex-active-agents/package.json +39 -11
- package/templates/vscode/guardex-active-agents/session-schema.js +226 -8
|
@@ -15,6 +15,7 @@ CLEANUP_AFTER_MERGE_RAW="${GUARDEX_FINISH_CLEANUP:-false}"
|
|
|
15
15
|
WAIT_FOR_MERGE_RAW="${GUARDEX_FINISH_WAIT_FOR_MERGE:-false}"
|
|
16
16
|
WAIT_TIMEOUT_SECONDS_RAW="${GUARDEX_FINISH_WAIT_TIMEOUT_SECONDS:-1800}"
|
|
17
17
|
WAIT_POLL_SECONDS_RAW="${GUARDEX_FINISH_WAIT_POLL_SECONDS:-10}"
|
|
18
|
+
PARENT_GITLINK_AUTO_COMMIT_RAW="${GUARDEX_FINISH_PARENT_GITLINK_AUTO_COMMIT:-true}"
|
|
18
19
|
|
|
19
20
|
run_guardex_cli() {
|
|
20
21
|
if [[ -n "$CLI_ENTRY" ]]; then
|
|
@@ -67,6 +68,7 @@ CLEANUP_AFTER_MERGE="$(normalize_bool "$CLEANUP_AFTER_MERGE_RAW" "0")"
|
|
|
67
68
|
WAIT_FOR_MERGE="$(normalize_bool "$WAIT_FOR_MERGE_RAW" "0")"
|
|
68
69
|
WAIT_TIMEOUT_SECONDS="$(normalize_int "$WAIT_TIMEOUT_SECONDS_RAW" "1800" "30")"
|
|
69
70
|
WAIT_POLL_SECONDS="$(normalize_int "$WAIT_POLL_SECONDS_RAW" "10" "0")"
|
|
71
|
+
PARENT_GITLINK_AUTO_COMMIT="$(normalize_bool "$PARENT_GITLINK_AUTO_COMMIT_RAW" "1")"
|
|
70
72
|
|
|
71
73
|
while [[ $# -gt 0 ]]; do
|
|
72
74
|
case "$1" in
|
|
@@ -117,6 +119,14 @@ while [[ $# -gt 0 ]]; do
|
|
|
117
119
|
WAIT_POLL_SECONDS="$(normalize_int "${2:-}" "10" "0")"
|
|
118
120
|
shift 2
|
|
119
121
|
;;
|
|
122
|
+
--parent-gitlink-commit)
|
|
123
|
+
PARENT_GITLINK_AUTO_COMMIT=1
|
|
124
|
+
shift
|
|
125
|
+
;;
|
|
126
|
+
--no-parent-gitlink-commit)
|
|
127
|
+
PARENT_GITLINK_AUTO_COMMIT=0
|
|
128
|
+
shift
|
|
129
|
+
;;
|
|
120
130
|
--mode)
|
|
121
131
|
MERGE_MODE="${2:-auto}"
|
|
122
132
|
shift 2
|
|
@@ -131,7 +141,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
131
141
|
;;
|
|
132
142
|
*)
|
|
133
143
|
echo "[agent-branch-finish] Unknown argument: $1" >&2
|
|
134
|
-
echo "Usage: $0 [--base <branch>] [--branch <branch>] [--no-push] [--cleanup|--no-cleanup] [--wait-for-merge|--no-wait-for-merge] [--wait-timeout-seconds <n>] [--wait-poll-seconds <n>] [--keep-remote-branch|--delete-remote-branch] [--mode auto|direct|pr|--via-pr|--direct-only]" >&2
|
|
144
|
+
echo "Usage: $0 [--base <branch>] [--branch <branch>] [--no-push] [--cleanup|--no-cleanup] [--wait-for-merge|--no-wait-for-merge] [--wait-timeout-seconds <n>] [--wait-poll-seconds <n>] [--parent-gitlink-commit|--no-parent-gitlink-commit] [--keep-remote-branch|--delete-remote-branch] [--mode auto|direct|pr|--via-pr|--direct-only]" >&2
|
|
135
145
|
exit 1
|
|
136
146
|
;;
|
|
137
147
|
esac
|
|
@@ -173,6 +183,8 @@ if [[ -z "$stored_worktree_root_rel" ]]; then
|
|
|
173
183
|
stored_worktree_root_rel=".omx/agent-worktrees"
|
|
174
184
|
fi
|
|
175
185
|
agent_worktree_root="${repo_common_root}/${stored_worktree_root_rel}"
|
|
186
|
+
runtime_state_root_rel="$(dirname "$stored_worktree_root_rel")"
|
|
187
|
+
temp_worktree_root="${repo_common_root}/${runtime_state_root_rel}/.tmp-worktrees"
|
|
176
188
|
|
|
177
189
|
if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
|
|
178
190
|
echo "[agent-branch-finish] --base requires a non-empty branch name." >&2
|
|
@@ -218,7 +230,7 @@ fi
|
|
|
218
230
|
|
|
219
231
|
get_worktree_for_branch() {
|
|
220
232
|
local branch="$1"
|
|
221
|
-
git -C "$repo_root" worktree list --porcelain | awk -v target="refs/heads/${branch}" -v probe_prefix="${
|
|
233
|
+
git -C "$repo_root" worktree list --porcelain | awk -v target="refs/heads/${branch}" -v probe_prefix="${temp_worktree_root}/__source-probe-" '
|
|
222
234
|
$1 == "worktree" { wt = $2 }
|
|
223
235
|
$1 == "branch" && $2 == target {
|
|
224
236
|
if (index(wt, probe_prefix) != 1) {
|
|
@@ -242,7 +254,7 @@ remove_stale_source_probe_worktrees() {
|
|
|
242
254
|
git -C "$stale_probe" merge --abort >/dev/null 2>&1 || true
|
|
243
255
|
git -C "$repo_root" worktree remove "$stale_probe" --force >/dev/null 2>&1 || true
|
|
244
256
|
done < <(
|
|
245
|
-
git -C "$repo_root" worktree list --porcelain | awk -v target="refs/heads/${branch}" -v probe_prefix="${
|
|
257
|
+
git -C "$repo_root" worktree list --porcelain | awk -v target="refs/heads/${branch}" -v probe_prefix="${temp_worktree_root}/__source-probe-" '
|
|
246
258
|
$1 == "worktree" { wt = $2 }
|
|
247
259
|
$1 == "branch" && $2 == target {
|
|
248
260
|
if (index(wt, probe_prefix) == 1) {
|
|
@@ -264,11 +276,15 @@ source_worktree="$(get_worktree_for_branch "$SOURCE_BRANCH")"
|
|
|
264
276
|
created_source_probe=0
|
|
265
277
|
source_probe_path=""
|
|
266
278
|
integration_worktree=""
|
|
279
|
+
integration_branch=""
|
|
267
280
|
|
|
268
281
|
cleanup() {
|
|
269
282
|
if [[ -n "$integration_worktree" && -d "$integration_worktree" ]]; then
|
|
270
283
|
git -C "$repo_root" worktree remove "$integration_worktree" --force >/dev/null 2>&1 || true
|
|
271
284
|
fi
|
|
285
|
+
if [[ -n "${integration_branch:-}" ]]; then
|
|
286
|
+
git -C "$repo_root" branch -D "$integration_branch" >/dev/null 2>&1 || true
|
|
287
|
+
fi
|
|
272
288
|
if [[ "$created_source_probe" -eq 1 && -n "$source_probe_path" && -d "$source_probe_path" ]]; then
|
|
273
289
|
# Abort any in-progress git op so `worktree remove --force` succeeds on conflict-stuck probes.
|
|
274
290
|
git -C "$source_probe_path" rebase --abort >/dev/null 2>&1 || true
|
|
@@ -279,7 +295,7 @@ cleanup() {
|
|
|
279
295
|
trap cleanup EXIT
|
|
280
296
|
|
|
281
297
|
if [[ -z "$source_worktree" ]]; then
|
|
282
|
-
source_probe_path="${
|
|
298
|
+
source_probe_path="${temp_worktree_root}/__source-probe-${SOURCE_BRANCH//\//__}-$(date +%Y%m%d-%H%M%S)"
|
|
283
299
|
mkdir -p "$(dirname "$source_probe_path")"
|
|
284
300
|
git -C "$repo_root" worktree add "$source_probe_path" "$SOURCE_BRANCH" >/dev/null
|
|
285
301
|
source_worktree="$source_probe_path"
|
|
@@ -343,7 +359,7 @@ if [[ "$should_require_sync" -eq 1 ]] && git -C "$repo_root" show-ref --verify -
|
|
|
343
359
|
fi
|
|
344
360
|
|
|
345
361
|
integration_stamp="$(date +%Y%m%d-%H%M%S)"
|
|
346
|
-
integration_worktree_base="${
|
|
362
|
+
integration_worktree_base="${temp_worktree_root}/__integrate-${BASE_BRANCH//\//__}-${integration_stamp}"
|
|
347
363
|
integration_branch_base="__agent_integrate_${BASE_BRANCH//\//_}_$(date +%Y%m%d_%H%M%S)"
|
|
348
364
|
integration_worktree="$integration_worktree_base"
|
|
349
365
|
integration_branch="$integration_branch_base"
|
|
@@ -455,6 +471,128 @@ read_pr_state() {
|
|
|
455
471
|
return 0
|
|
456
472
|
}
|
|
457
473
|
|
|
474
|
+
read_merged_pr_for_head() {
|
|
475
|
+
local head_sha="${1:-}"
|
|
476
|
+
local state_line=""
|
|
477
|
+
local parsed_state=""
|
|
478
|
+
local parsed_merged_at=""
|
|
479
|
+
local parsed_url=""
|
|
480
|
+
|
|
481
|
+
if [[ -z "$head_sha" ]]; then
|
|
482
|
+
return 1
|
|
483
|
+
fi
|
|
484
|
+
|
|
485
|
+
state_line="$("$GH_BIN" pr list \
|
|
486
|
+
--state merged \
|
|
487
|
+
--head "$SOURCE_BRANCH" \
|
|
488
|
+
--base "$BASE_BRANCH" \
|
|
489
|
+
--json state,mergedAt,url,headRefOid \
|
|
490
|
+
--jq "map(select(.headRefOid == \"$head_sha\")) | sort_by(.mergedAt // \"\") | reverse | (.[0] // {}) | [(.state // \"\"), (.mergedAt // \"\"), (.url // \"\")] | join(\"\u001f\")" \
|
|
491
|
+
2>/dev/null || true)"
|
|
492
|
+
if [[ -z "$state_line" ]]; then
|
|
493
|
+
return 1
|
|
494
|
+
fi
|
|
495
|
+
|
|
496
|
+
IFS=$'\x1f' read -r parsed_state parsed_merged_at parsed_url <<< "$state_line"
|
|
497
|
+
if [[ -z "$parsed_state" && -z "$parsed_merged_at" && -z "$parsed_url" ]]; then
|
|
498
|
+
return 1
|
|
499
|
+
fi
|
|
500
|
+
if [[ "$parsed_state" != "MERGED" && -z "$parsed_merged_at" ]]; then
|
|
501
|
+
return 1
|
|
502
|
+
fi
|
|
503
|
+
|
|
504
|
+
PR_STATE="$parsed_state"
|
|
505
|
+
PR_MERGED_AT="$parsed_merged_at"
|
|
506
|
+
if [[ -n "$parsed_url" ]]; then
|
|
507
|
+
pr_url="$parsed_url"
|
|
508
|
+
fi
|
|
509
|
+
return 0
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
maybe_auto_commit_parent_gitlink() {
|
|
513
|
+
local base_wt="${1:-}"
|
|
514
|
+
local base_wt_real=""
|
|
515
|
+
local super_root_raw=""
|
|
516
|
+
local super_root=""
|
|
517
|
+
local subrepo_rel=""
|
|
518
|
+
local gitlink_mode=""
|
|
519
|
+
local gitlink_index_sha=""
|
|
520
|
+
local gitlink_parent_head_sha=""
|
|
521
|
+
local subrepo_head_sha=""
|
|
522
|
+
local update_index_output=""
|
|
523
|
+
local commit_output=""
|
|
524
|
+
local commit_message=""
|
|
525
|
+
|
|
526
|
+
if [[ "$PARENT_GITLINK_AUTO_COMMIT" -ne 1 || "$PUSH_ENABLED" -ne 1 ]]; then
|
|
527
|
+
return 0
|
|
528
|
+
fi
|
|
529
|
+
if [[ -z "$base_wt" ]]; then
|
|
530
|
+
return 0
|
|
531
|
+
fi
|
|
532
|
+
if ! base_wt_real="$(cd "$base_wt" && pwd -P 2>/dev/null)"; then
|
|
533
|
+
return 0
|
|
534
|
+
fi
|
|
535
|
+
if [[ "$base_wt_real" != "$repo_common_root" ]]; then
|
|
536
|
+
return 0
|
|
537
|
+
fi
|
|
538
|
+
if ! is_clean_worktree "$repo_common_root"; then
|
|
539
|
+
echo "[agent-branch-finish] Parent gitlink auto-commit skipped; nested base worktree is dirty: ${repo_common_root}" >&2
|
|
540
|
+
return 0
|
|
541
|
+
fi
|
|
542
|
+
|
|
543
|
+
super_root_raw="$(git -C "$repo_common_root" rev-parse --show-superproject-working-tree 2>/dev/null || true)"
|
|
544
|
+
if [[ -z "$super_root_raw" ]]; then
|
|
545
|
+
return 0
|
|
546
|
+
fi
|
|
547
|
+
if ! super_root="$(cd "$super_root_raw" && pwd -P 2>/dev/null)"; then
|
|
548
|
+
return 0
|
|
549
|
+
fi
|
|
550
|
+
|
|
551
|
+
case "$repo_common_root" in
|
|
552
|
+
"$super_root"/*) subrepo_rel="${repo_common_root#"$super_root"/}" ;;
|
|
553
|
+
*) return 0 ;;
|
|
554
|
+
esac
|
|
555
|
+
if [[ -z "$subrepo_rel" || "$subrepo_rel" == "$repo_common_root" ]]; then
|
|
556
|
+
return 0
|
|
557
|
+
fi
|
|
558
|
+
|
|
559
|
+
gitlink_mode="$(git -C "$super_root" ls-files -s -- "$subrepo_rel" | awk 'NR == 1 { print $1 }')"
|
|
560
|
+
if [[ "$gitlink_mode" != "160000" ]]; then
|
|
561
|
+
return 0
|
|
562
|
+
fi
|
|
563
|
+
gitlink_index_sha="$(git -C "$super_root" ls-files -s -- "$subrepo_rel" | awk 'NR == 1 { print $2 }')"
|
|
564
|
+
gitlink_parent_head_sha="$(git -C "$super_root" ls-tree HEAD -- "$subrepo_rel" | awk 'NR == 1 { print $3 }')"
|
|
565
|
+
subrepo_head_sha="$(git -C "$repo_common_root" rev-parse HEAD 2>/dev/null || true)"
|
|
566
|
+
if [[ -z "$subrepo_head_sha" ]]; then
|
|
567
|
+
return 0
|
|
568
|
+
fi
|
|
569
|
+
if [[ -n "$gitlink_index_sha" && "$gitlink_index_sha" == "$gitlink_parent_head_sha" && "$gitlink_index_sha" == "$subrepo_head_sha" ]]; then
|
|
570
|
+
return 0
|
|
571
|
+
fi
|
|
572
|
+
|
|
573
|
+
if [[ "$gitlink_index_sha" != "$subrepo_head_sha" ]]; then
|
|
574
|
+
if ! update_index_output="$(git -C "$super_root" update-index --cacheinfo 160000 "$subrepo_head_sha" "$subrepo_rel" 2>&1)"; then
|
|
575
|
+
echo "[agent-branch-finish] Warning: parent gitlink staging failed for ${subrepo_rel} in ${super_root}." >&2
|
|
576
|
+
[[ -n "$update_index_output" ]] && echo "$update_index_output" >&2
|
|
577
|
+
return 0
|
|
578
|
+
fi
|
|
579
|
+
gitlink_index_sha="$(git -C "$super_root" ls-files -s -- "$subrepo_rel" | awk 'NR == 1 { print $2 }')"
|
|
580
|
+
fi
|
|
581
|
+
gitlink_parent_head_sha="$(git -C "$super_root" ls-tree HEAD -- "$subrepo_rel" | awk 'NR == 1 { print $3 }')"
|
|
582
|
+
if [[ "$gitlink_index_sha" == "$gitlink_parent_head_sha" ]]; then
|
|
583
|
+
return 0
|
|
584
|
+
fi
|
|
585
|
+
|
|
586
|
+
commit_message="Update ${subrepo_rel} subrepo pointer"
|
|
587
|
+
if ! commit_output="$(git -C "$super_root" commit -m "$commit_message" -- "$subrepo_rel" 2>&1)"; then
|
|
588
|
+
echo "[agent-branch-finish] Warning: parent gitlink auto-commit failed in ${super_root}." >&2
|
|
589
|
+
[[ -n "$commit_output" ]] && echo "$commit_output" >&2
|
|
590
|
+
return 0
|
|
591
|
+
fi
|
|
592
|
+
|
|
593
|
+
echo "[agent-branch-finish] Parent gitlink auto-committed '${subrepo_rel}' in ${super_root}."
|
|
594
|
+
}
|
|
595
|
+
|
|
458
596
|
wait_for_pr_merge() {
|
|
459
597
|
local deadline
|
|
460
598
|
deadline=$(( $(date +%s) + WAIT_TIMEOUT_SECONDS ))
|
|
@@ -509,11 +647,22 @@ wait_for_pr_merge() {
|
|
|
509
647
|
}
|
|
510
648
|
|
|
511
649
|
run_pr_flow() {
|
|
650
|
+
local source_head_sha=""
|
|
651
|
+
|
|
512
652
|
if ! command -v "$GH_BIN" >/dev/null 2>&1; then
|
|
513
653
|
echo "[agent-branch-finish] PR fallback requested but GitHub CLI not found: ${GH_BIN}" >&2
|
|
514
654
|
return 1
|
|
515
655
|
fi
|
|
516
656
|
|
|
657
|
+
source_head_sha="$(git -C "$repo_root" rev-parse "$SOURCE_BRANCH" 2>/dev/null || true)"
|
|
658
|
+
if read_merged_pr_for_head "$source_head_sha"; then
|
|
659
|
+
echo "[agent-branch-finish] Source branch head already landed in a merged PR; skipping new PR creation and continuing cleanup." >&2
|
|
660
|
+
if [[ -n "$pr_url" ]]; then
|
|
661
|
+
echo "[agent-branch-finish] Merged PR: ${pr_url}" >&2
|
|
662
|
+
fi
|
|
663
|
+
return 0
|
|
664
|
+
fi
|
|
665
|
+
|
|
517
666
|
git -C "$source_worktree" push -u origin "$SOURCE_BRANCH"
|
|
518
667
|
|
|
519
668
|
pr_title="$(git -C "$repo_root" log -1 --pretty=%s "$SOURCE_BRANCH" 2>/dev/null || true)"
|
|
@@ -612,6 +761,7 @@ base_worktree="$(get_worktree_for_branch "$BASE_BRANCH")"
|
|
|
612
761
|
if [[ -n "$base_worktree" ]] && is_clean_worktree "$base_worktree" && [[ "$PUSH_ENABLED" -eq 1 ]]; then
|
|
613
762
|
git -C "$base_worktree" pull --ff-only origin "$BASE_BRANCH" >/dev/null 2>&1 || true
|
|
614
763
|
fi
|
|
764
|
+
maybe_auto_commit_parent_gitlink "$base_worktree"
|
|
615
765
|
|
|
616
766
|
if [[ "$CLEANUP_AFTER_MERGE" -eq 1 ]]; then
|
|
617
767
|
if [[ "$source_worktree" == "$repo_root" ]]; then
|
|
@@ -155,6 +155,15 @@ env_flag_truthy() {
|
|
|
155
155
|
esac
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
maybe_fail_after_auto_transfer_stash() {
|
|
159
|
+
if env_flag_truthy "${GUARDEX_TEST_FAIL_AFTER_AUTO_TRANSFER_STASH:-}"; then
|
|
160
|
+
echo "[agent-branch-start] Simulated failure after capturing auto-transfer stash." >&2
|
|
161
|
+
return 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
return 0
|
|
165
|
+
}
|
|
166
|
+
|
|
158
167
|
default_worktree_root_rel() {
|
|
159
168
|
local raw_agent="$1"
|
|
160
169
|
local override="${GUARDEX_AGENT_TYPE:-}"
|
|
@@ -580,6 +589,27 @@ fi
|
|
|
580
589
|
auto_transfer_stash_ref=""
|
|
581
590
|
auto_transfer_message=""
|
|
582
591
|
auto_transfer_source_branch=""
|
|
592
|
+
auto_transfer_completed=0
|
|
593
|
+
|
|
594
|
+
restore_auto_transfer_stash_on_failure() {
|
|
595
|
+
local exit_code="${1:-0}"
|
|
596
|
+
if [[ "$exit_code" -eq 0 ]] || [[ -z "$auto_transfer_stash_ref" ]] || [[ "$auto_transfer_completed" -eq 1 ]]; then
|
|
597
|
+
return 0
|
|
598
|
+
fi
|
|
599
|
+
|
|
600
|
+
local transfer_label="${auto_transfer_source_branch:-$BASE_BRANCH}"
|
|
601
|
+
if git -C "$repo_root" stash apply "$auto_transfer_stash_ref" >/dev/null 2>&1; then
|
|
602
|
+
git -C "$repo_root" stash drop "$auto_transfer_stash_ref" >/dev/null 2>&1 || true
|
|
603
|
+
auto_transfer_stash_ref=""
|
|
604
|
+
echo "[agent-branch-start] Restored moved changes back to '${transfer_label}' after startup failure." >&2
|
|
605
|
+
else
|
|
606
|
+
echo "[agent-branch-start] Startup failed and auto-restore also failed." >&2
|
|
607
|
+
echo "[agent-branch-start] Changes are preserved in ${auto_transfer_stash_ref} on ${transfer_label}." >&2
|
|
608
|
+
fi
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
trap 'restore_auto_transfer_stash_on_failure "$?"' EXIT
|
|
612
|
+
|
|
583
613
|
current_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
|
|
584
614
|
protected_branches_raw="$(resolve_protected_branches "$repo_root")"
|
|
585
615
|
if [[ -n "$current_branch" && "$current_branch" != "HEAD" ]] && is_protected_branch_name "$current_branch" "$protected_branches_raw"; then
|
|
@@ -593,6 +623,9 @@ if [[ -n "$current_branch" && "$current_branch" != "HEAD" ]] && is_protected_bra
|
|
|
593
623
|
if [[ -n "$auto_transfer_stash_ref" ]]; then
|
|
594
624
|
auto_transfer_source_branch="$current_branch"
|
|
595
625
|
echo "[agent-branch-start] Detected local changes on protected branch '${current_branch}'. Moving them to '${branch_name}'..."
|
|
626
|
+
if ! maybe_fail_after_auto_transfer_stash; then
|
|
627
|
+
exit 1
|
|
628
|
+
fi
|
|
596
629
|
fi
|
|
597
630
|
fi
|
|
598
631
|
fi
|
|
@@ -610,7 +643,9 @@ git -C "$worktree_path" branch --unset-upstream "$branch_name" >/dev/null 2>&1 |
|
|
|
610
643
|
|
|
611
644
|
if [[ -n "$auto_transfer_stash_ref" ]]; then
|
|
612
645
|
if git -C "$worktree_path" stash apply "$auto_transfer_stash_ref" >/dev/null 2>&1; then
|
|
646
|
+
auto_transfer_completed=1
|
|
613
647
|
git -C "$repo_root" stash drop "$auto_transfer_stash_ref" >/dev/null 2>&1 || true
|
|
648
|
+
auto_transfer_stash_ref=""
|
|
614
649
|
transfer_label="${auto_transfer_source_branch:-$BASE_BRANCH}"
|
|
615
650
|
echo "[agent-branch-start] Moved local changes from '${transfer_label}' into '${branch_name}'."
|
|
616
651
|
else
|
|
@@ -20,7 +20,9 @@ PR_MERGED_LOOKUP_LOADED=0
|
|
|
20
20
|
declare -A MERGED_PR_BRANCHES=()
|
|
21
21
|
WORKTREE_ROOT_RELS=(
|
|
22
22
|
".omx/agent-worktrees"
|
|
23
|
+
".omx/.tmp-worktrees"
|
|
23
24
|
".omc/agent-worktrees"
|
|
25
|
+
".omc/.tmp-worktrees"
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
if [[ -n "$BASE_BRANCH" ]]; then
|
|
@@ -90,9 +92,15 @@ repo_common_dir="$(cd "$repo_common_dir" && pwd -P)"
|
|
|
90
92
|
resolve_worktree_root_rel_for_entry() {
|
|
91
93
|
local entry="$1"
|
|
92
94
|
case "$entry" in
|
|
95
|
+
*/.omc/.tmp-worktrees/*)
|
|
96
|
+
printf '%s' '.omc/.tmp-worktrees'
|
|
97
|
+
;;
|
|
93
98
|
*/.omc/agent-worktrees/*)
|
|
94
99
|
printf '%s' '.omc/agent-worktrees'
|
|
95
100
|
;;
|
|
101
|
+
*/.omx/.tmp-worktrees/*)
|
|
102
|
+
printf '%s' '.omx/.tmp-worktrees'
|
|
103
|
+
;;
|
|
96
104
|
*)
|
|
97
105
|
printf '%s' '.omx/agent-worktrees'
|
|
98
106
|
;;
|
|
@@ -538,6 +546,19 @@ if [[ "$DELETE_BRANCHES" -eq 1 ]]; then
|
|
|
538
546
|
if branch_has_worktree "$branch"; then
|
|
539
547
|
continue
|
|
540
548
|
fi
|
|
549
|
+
if [[ "$branch" == __agent_integrate_* || "$branch" == __source-probe-* ]]; then
|
|
550
|
+
if ! branch_idle_gate "$branch" "" "temporary-worktree"; then
|
|
551
|
+
continue
|
|
552
|
+
fi
|
|
553
|
+
if run_cmd git -C "$repo_root" branch -D "$branch" >/dev/null 2>&1; then
|
|
554
|
+
removed_branches=$((removed_branches + 1))
|
|
555
|
+
echo "[agent-worktree-prune] Deleted stale temporary branch: ${branch}"
|
|
556
|
+
fi
|
|
557
|
+
continue
|
|
558
|
+
fi
|
|
559
|
+
if [[ "$branch" != agent/* ]]; then
|
|
560
|
+
continue
|
|
561
|
+
fi
|
|
541
562
|
if ! branch_idle_gate "$branch" "" "stale-merged-branch"; then
|
|
542
563
|
continue
|
|
543
564
|
fi
|
|
@@ -566,7 +587,7 @@ if [[ "$DELETE_BRANCHES" -eq 1 ]]; then
|
|
|
566
587
|
fi
|
|
567
588
|
fi
|
|
568
589
|
fi
|
|
569
|
-
done < <(git -C "$repo_root" for-each-ref --format='%(refname:short)' refs/heads
|
|
590
|
+
done < <(git -C "$repo_root" for-each-ref --format='%(refname:short)' refs/heads)
|
|
570
591
|
fi
|
|
571
592
|
|
|
572
593
|
run_cmd git -C "$repo_root" worktree prune
|
|
@@ -4,7 +4,7 @@ Local VS Code companion for Guardex-managed repos.
|
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
|
-
Use the
|
|
7
|
+
Use the dedicated Active Agents sidebar icon to create or inspect Guardex sandboxes quickly.
|
|
8
8
|
|
|
9
9
|
1. Install from a Guardex-wired repo:
|
|
10
10
|
|
|
@@ -13,16 +13,19 @@ node scripts/install-vscode-active-agents-extension.js
|
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
2. Reload the VS Code window.
|
|
16
|
-
3. In
|
|
16
|
+
3. In the Activity Bar, open the `Active Agents` hive icon under Source Control. Use `Start agent` to enter a task + agent name and launch the repo Guardex agent runner. The companion prefers `bash scripts/codex-agent.sh` when present, falls back to `npm run agent:codex --`, and only uses `gx branch start` as a last resort.
|
|
17
17
|
|
|
18
18
|
What it does:
|
|
19
19
|
|
|
20
20
|
- Bundles a local GitGuardex icon so repo installs show branded extension metadata inside VS Code.
|
|
21
|
-
-
|
|
21
|
+
- Bundles the optional `GitGuardex File Icons` theme for OpenSpec, agent worktree, and hook files in Explorer.
|
|
22
|
+
- Adds a dedicated `Active Agents` Activity Bar container with a hive icon and live badge count for active sessions.
|
|
22
23
|
- Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
|
|
23
24
|
- Splits live sessions inside `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `THINKING`, `STALLED`, and `DEAD` groups so stuck, active, and inactive lanes stand out immediately.
|
|
24
25
|
- Mirrors the same live state in the VS Code status bar so the selected session or active-agent count stays visible outside the tree.
|
|
25
26
|
- Shows one row per live Guardex sandbox session inside those activity groups, with changed-file rows nested under sessions that are touching files.
|
|
27
|
+
- Labels session rows with provider identity and snapshot context; snapshot-backed rows use a one-letter snapshot badge such as `N` for `nagyviktor@edixa.com`.
|
|
28
|
+
- Shows raw agent branch groups with the `git-branch` icon instead of the generic folder icon.
|
|
26
29
|
- Shows repo-root git changes in a sibling `CHANGES` section when the guarded repo itself is dirty.
|
|
27
30
|
- Derives session state from dirty worktree status, git conflict markers, heartbeat freshness, PID liveness, and recent file mtimes, surfaces working/dead/conflict counts in the repo/header summary, and shows changed-file counts for active edits.
|
|
28
31
|
- Uses distinct VS Code codicons for each session state, including animated `loading~spin` for `WORKING NOW`.
|