Skip to content

Commit 1a39ebe

Browse files
NagyViktNagyVikt
andauthored
fix(agent-flow): auto-allow staged deletions + surface gh pr create failures (#565)
Two ergonomic fixes to remove recurring friction in the agent commit + finish flow. 1. pre-commit auto-claim: the existing GUARDEX_AUTOCLAIM_STAGED_LOCKS block iterated --diff-filter=ACMRDTUXB and claimed every staged path without --allow-delete, so 'locks validate --staged' then rejected the same deletion the operator just staged, forcing a manual 'gx locks allow-delete' + re-commit loop. Split non-deletion staged paths from deletions and claim deletions with --allow-delete, gated by GUARDEX_AUTOCLAIM_STAGED_DELETES (default 1). 2. agent-branch-finish run_pr_flow: 'gh pr create' was wrapped in '>/dev/null 2>&1 || true', so auth, branch-protection, or gh-version failures were invisible. The function then ran 'gh pr view' (empty URL) and 'gh pr merge' (silent no-op), leaving operators with a 'merged via pr flow' log and no PR. Capture stderr, let the idempotent 'PR already exists' path through, surface every other failure verbatim, fail fast if no URL appears, and log the URL on success. Both changes are additive and behind opt-out env vars where behavior diverges; existing operators see strictly fewer reject+retry loops and louder PR-create failures. Co-authored-by: NagyVikt <nagy.viktordp@gmail.com>
1 parent 7694495 commit 1a39ebe

4 files changed

Lines changed: 69 additions & 3 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-05-11
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# agent-claude-smoother-finish-autoclaim-deletes-and-lo-2026-05-12-00-28 (minimal / T1)
2+
3+
Branch: `agent/claude/smoother-finish-autoclaim-deletes-and-lo-2026-05-12-00-28` against `main`.
4+
5+
Two surgical ergonomic fixes to remove recurring friction in the agent commit + finish flow:
6+
7+
1. `templates/githooks/pre-commit`: the existing `GUARDEX_AUTOCLAIM_STAGED_LOCKS` block iterates `--diff-filter=ACMRDTUXB` and calls `locks claim --branch ... <file>` without `--allow-delete`. The next step (`locks validate --staged`) then rejects the deletion because its `allow_delete` flag is False, forcing the operator to run `gx locks allow-delete` and re-commit. The fix splits non-deletion paths from deletions, claims deletions with `--allow-delete`, and gates the new behavior behind `GUARDEX_AUTOCLAIM_STAGED_DELETES` (default `1`, opt-out only).
8+
9+
2. `templates/scripts/agent-branch-finish.sh` `run_pr_flow`: `gh pr create` was wrapped in `>/dev/null 2>&1 || true`, so when it fails (auth, branch protection, gh version skew), the failure was invisible. The function then proceeded to `gh pr view` (empty URL) and `gh pr merge` (silent no-op), leaving operators with a "merged via pr flow" log line and no PR. The fix captures stderr, allows the idempotent "PR already exists" path through silently, surfaces every other failure verbatim, and fails the function fast when `pr_view` returns no URL.
10+
11+
Both changes are additive and behind opt-out env vars where behavior diverges; existing operators see strictly fewer reject + retry loops and louder PR-create failures.
12+
13+
## Handoff
14+
15+
- Handoff: change=`agent-claude-smoother-finish-autoclaim-deletes-and-lo-2026-05-12-00-28`; branch=`agent/<your-name>/<branch-slug>`; scope=`TODO`; action=`continue this sandbox or finish cleanup after a usage-limit/manual takeover`.
16+
- Copy prompt: Continue `agent-claude-smoother-finish-autoclaim-deletes-and-lo-2026-05-12-00-28` on branch `agent/<your-name>/<branch-slug>`. Work inside the existing sandbox, review `openspec/changes/agent-claude-smoother-finish-autoclaim-deletes-and-lo-2026-05-12-00-28/notes.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`.
17+
18+
## Cleanup
19+
20+
- [ ] Run: `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`
21+
- [ ] Record PR URL + `MERGED` state in the completion handoff.
22+
- [ ] Confirm sandbox worktree is gone (`git worktree list`, `git branch -a`).

templates/githooks/pre-commit

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,32 @@ fi
207207

208208
if [[ "$branch" == agent/* ]]; then
209209
if [[ "${GUARDEX_AUTOCLAIM_STAGED_LOCKS:-1}" == "1" ]]; then
210+
# Auto-claim non-deletion staged paths. Deletions need an explicit
211+
# `--allow-delete` flag below so `locks validate --staged` doesn't
212+
# reject the commit on the same trip the user staged the delete.
210213
while IFS= read -r staged_file; do
211214
[[ -z "$staged_file" ]] && continue
212215
[[ "$staged_file" == ".omx/state/agent-file-locks.json" ]] && continue
213216
run_guardex_cli locks claim --branch "$branch" "$staged_file" >/dev/null 2>&1 || true
214-
done < <(git diff --cached --name-only --diff-filter=ACMRDTUXB)
217+
done < <(git diff --cached --name-only --diff-filter=ACMRTUXB)
218+
219+
# Auto-approve deletions for the same branch (gated separately so
220+
# operators can disable this single behavior without disabling the
221+
# broader auto-claim). Defaults to enabled — matches the auto-claim
222+
# default and removes the "first commit fails, then `gx locks
223+
# allow-delete`, then commit again" loop.
224+
if [[ "${GUARDEX_AUTOCLAIM_STAGED_DELETES:-1}" == "1" ]]; then
225+
_staged_deletes=()
226+
while IFS= read -r staged_delete; do
227+
[[ -z "$staged_delete" ]] && continue
228+
[[ "$staged_delete" == ".omx/state/agent-file-locks.json" ]] && continue
229+
_staged_deletes+=("$staged_delete")
230+
done < <(git diff --cached --name-only --diff-filter=D)
231+
if (( ${#_staged_deletes[@]} > 0 )); then
232+
run_guardex_cli locks claim --branch "$branch" --allow-delete \
233+
"${_staged_deletes[@]}" >/dev/null 2>&1 || true
234+
fi
235+
fi
215236
fi
216237

217238
if ! run_guardex_cli locks validate --branch "$branch" --staged; then

templates/scripts/agent-branch-finish.sh

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,14 +1126,35 @@ run_pr_flow() {
11261126
fi
11271127
pr_body="Automated by gx branch finish (PR flow)."
11281128

1129-
"$GH_BIN" pr create \
1129+
pr_create_output=""
1130+
if pr_create_output="$("$GH_BIN" pr create \
11301131
--base "$BASE_BRANCH" \
11311132
--head "$SOURCE_BRANCH" \
11321133
--title "$pr_title" \
1133-
--body "$pr_body" >/dev/null 2>&1 || true
1134+
--body "$pr_body" 2>&1)"; then
1135+
:
1136+
else
1137+
# Idempotent: a PR already opened for this head is fine — fall through
1138+
# to `gh pr view` so we still capture the URL. Anything else is a real
1139+
# failure and the user needs to see it.
1140+
if ! grep -qiE 'already exists|a pull request for branch' <<<"$pr_create_output"; then
1141+
echo "[agent-branch-finish] gh pr create failed:" >&2
1142+
echo "${pr_create_output}" >&2
1143+
fi
1144+
fi
11341145

11351146
pr_url="$("$GH_BIN" pr view "$SOURCE_BRANCH" --json url --jq '.url' 2>/dev/null || true)"
11361147

1148+
if [[ -z "$pr_url" ]]; then
1149+
echo "[agent-branch-finish] No PR found for '${SOURCE_BRANCH}' after gh pr create; cannot proceed with PR merge." >&2
1150+
if [[ -n "$pr_create_output" ]]; then
1151+
echo "[agent-branch-finish] Last gh pr create output:" >&2
1152+
echo "${pr_create_output}" >&2
1153+
fi
1154+
return 1
1155+
fi
1156+
echo "[agent-branch-finish] PR URL: ${pr_url}" >&2
1157+
11371158
merge_output=""
11381159
if merge_output="$("$GH_BIN" pr merge "$SOURCE_BRANCH" --squash --delete-branch 2>&1)"; then
11391160
return 0

0 commit comments

Comments
 (0)