Skip to content

Commit 0c6df42

Browse files
committed
Harden handoff push approval flow
1 parent 79e30c3 commit 0c6df42

1 file changed

Lines changed: 50 additions & 5 deletions

File tree

.agents/skills/handoff/SKILL.md

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,61 @@ Never use `--no-verify`. Never amend as a workaround for a failed hook.
228228

229229
## Phase 4: Push Handoff
230230

231-
Determine the branch:
231+
Determine the branch and configured upstream:
232232

233233
```bash
234234
git rev-parse --abbrev-ref HEAD
235+
git rev-parse --abbrev-ref --symbolic-full-name '@{u}'
235236
```
236237

237-
Push only if the handoff trigger or user instruction authorizes it. If the
238-
branch has no upstream, use `git push -u origin <branch>`. Explicit `$handoff`
239-
invocation is normal push authorization for the standard handoff commit. Never
240-
force-push.
238+
Treat a non-zero upstream lookup as the expected no-upstream case, not as a
239+
Phase failure. Do not substitute a different branch. If an upstream exists,
240+
derive its remote name from the returned `<remote>/<branch>` value and verify
241+
that remote's push URL. If no upstream exists, verify `origin` because it is the
242+
only remote authorized for the setup push:
243+
244+
```bash
245+
git remote get-url --push <upstream-remote>
246+
git remote get-url --push origin
247+
```
248+
249+
Run only the command that matches the detected upstream state. Halt if the
250+
required push remote is missing.
251+
252+
When the push remote is on `github.com`, establish destination evidence in this
253+
same handoff turn immediately before the push:
254+
255+
```bash
256+
gh auth status -h github.com
257+
gh api user --jq .login
258+
gh repo view <owner>/<repo> --json viewerPermission --jq .viewerPermission
259+
```
260+
261+
Derive `<owner>/<repo>` from the verified remote URL. Run these read-only GitHub
262+
checks with the network access they require; a failure from a network-restricted
263+
sandbox is not evidence that the stored credential is invalid. Never request or
264+
display a token. Continue only when the authenticated account and a `WRITE`,
265+
`MAINTAIN`, or `ADMIN` permission establish that the destination is authorized.
266+
Otherwise halt and report the exact failed check.
267+
268+
Push only if the handoff trigger or user instruction authorizes it. Use exactly
269+
one of these command shapes:
270+
271+
- Existing upstream: `git push`.
272+
- No upstream: `git push -u origin <branch>`.
273+
274+
Request the required escalation with the scoped approval prefix
275+
`["git", "push"]`. The justification must state that this is the explicitly
276+
authorized, non-force handoff push; name the verified remote, authenticated
277+
account and permission; and identify the current branch/upstream. Explicit
278+
`$handoff` invocation is normal push authorization for the standard handoff
279+
commit. Never force-push.
280+
281+
If policy or automatic approval review rejects the push, halt Phase 4. Report
282+
the exact rejection and do not retry with another command shape, indirect
283+
execution, or workaround. When the current Codex surface supports it, direct
284+
the user to `/approve` and the denied action for the documented single-action
285+
retry; otherwise ask the user to perform the push directly.
241286

242287
## Phase 5: Report And Stop
243288

0 commit comments

Comments
 (0)