Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ To install the real companion into local VS Code from a GitGuardex-wired repo:
node scripts/install-vscode-active-agents-extension.js
```

It adds an `Active Agents` view to the Source Control container, groups each live repo into `ACTIVE AGENTS` and `CHANGES` sections, splits `ACTIVE AGENTS` into `WORKING NOW` and `THINKING` when both states are present, reads `.omx/state/active-sessions/*.json`, derives `thinking` versus `working` from each live sandbox worktree, and surfaces a working-count summary in the repo/header affordances. Reload the VS Code window after install.
It adds an `Active Agents` view to the Source Control container, groups each live repo into `ACTIVE AGENTS` and `CHANGES` sections, splits `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, and `DEAD` when those states are present, reads `.omx/state/active-sessions/*.json`, derives session state from git conflict markers, dirty worktree status, PID liveness, and recent file mtimes, and surfaces working/dead counts in the repo/header affordances. Reload the VS Code window after install.

---

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-22
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# T1 Notes

- Handoff: change=`agent-codex-nest-active-agent-changes-2026-04-22-10-53`; scope=`vscode/guardex-active-agents/{extension.js,session-schema.js}`; action=`nest repo changes under the owning active session row when the path belongs to that session worktree, and keep only unmatched paths in a Repo root residual group`.
- Add `changedPaths` to normalized active-session records so the extension reuses the per-worktree change set already derived from each session's worktree status.
- Rebuild the CHANGES tree grouping so active-session worktree ownership is resolved once and rendered as session subtrees with the existing folder/change item components.
- Preserve the existing file/folder rendering for all leaf nodes and leave only paths that do not belong to any active worktree inside a residual `Repo root` group.
- Verification widened scope: runtime helper parity was already broken on this branch baseline, so `scripts/{agent-branch-start.sh,agent-branch-finish.sh,codex-agent.sh}` are also being resynced to their template behavior to clear repo-wide verification.
- Verification follow-up: `test/merge-workflow.test.js` still expected a repo-local merge shim, but the install surface now keeps workflow shims CLI-owned by default; align that stale assertion with the current zero-copy setup policy so full-suite verification matches the rest of the install tests.
- Replace the Active Agents polling loop with file watchers for `**/.omx/state/active-sessions/*.json`, `**/.omx/state/agent-file-locks.json`, and each live session worktree index so the SCM companion refreshes only when session or dirty-state inputs change.
- Debounce watcher-driven refresh to a trailing 250ms timer and keep a session-keyed watcher map so per-session index watchers are created and disposed as active sessions appear and vanish.
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
## ADDED Requirements

### Requirement: Active Agents highlights currently working lanes
The VS Code Active Agents companion SHALL separate actively editing Guardex lanes from idle-thinking lanes inside the `ACTIVE AGENTS` section.
### Requirement: Active Agents highlights sandbox session state clearly
The VS Code Active Agents companion SHALL separate Guardex sandbox sessions into explicit state groups inside the `ACTIVE AGENTS` section.

#### Scenario: Working and thinking sessions render in separate groups
- **WHEN** a repo has both live `working` and `thinking` Guardex sessions
#### Scenario: Session states render in distinct groups
- **WHEN** a repo has live Guardex sessions inferred as `blocked`, `working`, `idle`, `stalled`, or `dead`
- **THEN** the repo node contains an `ACTIVE AGENTS` section
- **AND** that section contains `WORKING NOW` and `THINKING` child groups
- **AND** the working group appears before the thinking group.
- **AND** that section renders child groups for each present state
- **AND** the groups are ordered `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, `DEAD`
- **AND** the `BLOCKED` group appears above `WORKING NOW`.

#### Scenario: Repo summary exposes working counts
- **WHEN** a repo has one or more live working sessions
- **THEN** the repo row description includes the working count in addition to the active session count
- **AND** the Source Control badge tooltip mentions how many active sessions are currently working.
#### Scenario: Repo summary exposes working and dead counts
- **WHEN** a repo has one or more live `working` or `dead` sessions
- **THEN** the repo row description includes the working count in addition to the active count
- **AND** the repo row description includes the dead count when present
- **AND** the Source Control badge tooltip mentions working-now and dead counts when present.

#### Scenario: Working sessions use a distinct visual affordance
- **WHEN** a live Guardex session is inferred as `working`
- **THEN** its row uses a distinct codicon from `thinking` rows
#### Scenario: Each session state uses a distinct visual affordance
- **WHEN** a live Guardex session is inferred as `blocked`, `working`, `idle`, `stalled`, or `dead`
- **THEN** its row uses a distinct codicon for that state
- **AND** its tooltip summarizes the derived state reason
- **AND** the row still keeps the existing activity/count/elapsed description text.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ Handoff: 2026-04-22 09:05Z codex owns `templates/vscode/guardex-active-agents/*`

## 2. Implementation

- [x] 2.1 Split the `ACTIVE AGENTS` section into visible `WORKING NOW` and `THINKING` groups, preserving live session rows.
- [x] 2.2 Surface working counts in the repo row / view badge summary and add a distinct icon for working lanes.
- [x] 2.3 Update README guidance and focused regression tests for the new grouping behavior.
- [x] 2.1 Expand session activity derivation to `blocked`, `working`, `idle`, `stalled`, and `dead`, using git markers, dirty worktree status, PID liveness, and worktree mtimes.
- [x] 2.2 Group `ACTIVE AGENTS` into visible `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, and `DEAD` sections, with distinct ThemeIcons/tooltips and updated repo/badge summaries.
- [x] 2.3 Update README guidance and focused regression tests for the expanded session-state behavior.

## 3. Verification

Expand All @@ -30,3 +30,5 @@ Handoff: 2026-04-22 09:05Z codex owns `templates/vscode/guardex-active-agents/*`
- [ ] 4.1 Run the cleanup pipeline: `bash scripts/agent-branch-finish.sh --branch agent/codex/vscode-working-agents-groups-2026-04-22-09-05 --base main --via-pr --wait-for-merge --cleanup`.
- [ ] 4.2 Record the PR URL and final merge state (`MERGED`) in the completion handoff.
- [ ] 4.3 Confirm the sandbox worktree is gone (`git worktree list` no longer shows the agent path; `git branch -a` shows no surviving local/remote refs for the branch).

BLOCKED: This sandbox picked up unrelated concurrent edits in `scripts/agent-branch-finish.sh`, `scripts/agent-branch-start.sh`, `scripts/codex-agent.sh`, plus a new untracked `openspec/changes/agent-codex-nest-active-agent-changes-2026-04-22-10-53/` workspace after the session-state patch was verified. Do not run finish/cleanup until the branch owner decides whether to keep or split those additional changes.
51 changes: 32 additions & 19 deletions scripts/agent-branch-finish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,30 @@ DELETE_REMOTE_BRANCH=0
DELETE_REMOTE_BRANCH_EXPLICIT=0
MERGE_MODE="auto"
GH_BIN="${GUARDEX_GH_BIN:-gh}"
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
CLEANUP_AFTER_MERGE_RAW="${GUARDEX_FINISH_CLEANUP:-false}"
WAIT_FOR_MERGE_RAW="${GUARDEX_FINISH_WAIT_FOR_MERGE:-false}"
WAIT_TIMEOUT_SECONDS_RAW="${GUARDEX_FINISH_WAIT_TIMEOUT_SECONDS:-1800}"
WAIT_POLL_SECONDS_RAW="${GUARDEX_FINISH_WAIT_POLL_SECONDS:-10}"

run_guardex_cli() {
if [[ -n "$CLI_ENTRY" ]]; then
"$NODE_BIN" "$CLI_ENTRY" "$@"
return $?
fi
if command -v gx >/dev/null 2>&1; then
gx "$@"
return $?
fi
if command -v gitguardex >/dev/null 2>&1; then
gitguardex "$@"
return $?
fi
echo "[agent-branch-finish] Guardex CLI entrypoint unavailable; rerun via gx." >&2
return 127
}

normalize_bool() {
local raw="${1:-}"
local fallback="${2:-0}"
Expand Down Expand Up @@ -431,7 +450,7 @@ run_pr_flow() {
if [[ -z "$pr_title" ]]; then
pr_title="Merge ${SOURCE_BRANCH} into ${BASE_BRANCH}"
fi
pr_body="Automated by scripts/agent-branch-finish.sh (PR flow)."
pr_body="Automated by gx branch finish (PR flow)."

"$GH_BIN" pr create \
--base "$BASE_BRANCH" \
Expand Down Expand Up @@ -517,9 +536,7 @@ if [[ "$PUSH_ENABLED" -eq 1 ]]; then
fi
fi

if [[ -x "${repo_root}/scripts/agent-file-locks.py" ]]; then
python3 "${repo_root}/scripts/agent-file-locks.py" release --branch "$SOURCE_BRANCH" >/dev/null 2>&1 || true
fi
run_guardex_cli locks release --branch "$SOURCE_BRANCH" >/dev/null 2>&1 || true

base_worktree="$(get_worktree_for_branch "$BASE_BRANCH")"
if [[ -n "$base_worktree" ]] && is_clean_worktree "$base_worktree" && [[ "$PUSH_ENABLED" -eq 1 ]]; then
Expand Down Expand Up @@ -555,29 +572,25 @@ if [[ "$CLEANUP_AFTER_MERGE" -eq 1 ]]; then
fi
fi

if [[ -x "${repo_root}/scripts/agent-worktree-prune.sh" ]]; then
prune_args=(--base "$BASE_BRANCH" --only-dirty-worktrees --delete-branches)
if [[ "$DELETE_REMOTE_BRANCH" -eq 1 ]]; then
prune_args+=(--delete-remote-branches)
fi
if ! bash "${repo_root}/scripts/agent-worktree-prune.sh" "${prune_args[@]}"; then
echo "[agent-branch-finish] Warning: automatic worktree prune failed." >&2
echo "[agent-branch-finish] You can run manual cleanup: bash scripts/agent-worktree-prune.sh --base ${BASE_BRANCH} --delete-branches" >&2
fi
prune_args=(--base "$BASE_BRANCH" --only-dirty-worktrees --delete-branches)
if [[ "$DELETE_REMOTE_BRANCH" -eq 1 ]]; then
prune_args+=(--delete-remote-branches)
fi
if ! run_guardex_cli worktree prune "${prune_args[@]}"; then
echo "[agent-branch-finish] Warning: automatic worktree prune failed." >&2
echo "[agent-branch-finish] You can run manual cleanup: gx cleanup --base ${BASE_BRANCH}" >&2
fi

echo "[agent-branch-finish] Merged '${SOURCE_BRANCH}' into '${BASE_BRANCH}' via ${merge_status} flow and cleaned source branch/worktree."
if [[ "$source_worktree" == "$current_worktree" && "$source_worktree" == "${agent_worktree_root}"/* ]]; then
echo "[agent-branch-finish] Current worktree '${source_worktree}' still exists because it is the active shell cwd." >&2
echo "[agent-branch-finish] Leave this directory, then run: bash scripts/agent-worktree-prune.sh --base ${BASE_BRANCH} --delete-branches" >&2
echo "[agent-branch-finish] Leave this directory, then run: gx cleanup --base ${BASE_BRANCH}" >&2
fi
else
if [[ -x "${repo_root}/scripts/agent-worktree-prune.sh" ]]; then
if ! bash "${repo_root}/scripts/agent-worktree-prune.sh" --base "$BASE_BRANCH"; then
echo "[agent-branch-finish] Warning: temporary worktree prune failed." >&2
fi
if ! run_guardex_cli worktree prune --base "$BASE_BRANCH"; then
echo "[agent-branch-finish] Warning: temporary worktree prune failed." >&2
fi

echo "[agent-branch-finish] Merged '${SOURCE_BRANCH}' into '${BASE_BRANCH}' via ${merge_status} flow and kept source branch/worktree."
echo "[agent-branch-finish] Cleanup later with: bash scripts/agent-worktree-prune.sh --base ${BASE_BRANCH} --delete-branches --delete-remote-branches"
echo "[agent-branch-finish] Cleanup later with: gx cleanup --base ${BASE_BRANCH}"
fi
Loading