Summary
push_to_pull_request_branch fails in multi-repo workflows where a target repository is checked out into a subdirectory alongside the workflow repository (e.g. via actions/checkout with a path: parameter).
Error messages observed
Two errors are returned by the tool across successive retries:
First attempt — the handler runs getCurrentBranch() without cwd, so it detects the wrong branch (from the workflow repo root). It generates a patch against that wrong branch. When the target branch has no new commits relative to that wrong baseline, the tool reports:
No new commits to push - your changes may already be on the remote branch
Second attempt — after the agent specifies the branch name explicitly, the handler tries to generate an incremental patch for the correct target branch. But git is still running in the workflow repo root, where the target branch does not exist:
Branch repo-assist/fix-issue-NNNN-<description> does not exist locally. Cannot generate incremental patch.
The agent's own conclusion from the run (via thinking):
The tool seems to be looking in the workflow repo, not in the target-repo/ subdirectory. The target-repo was checked out into target-repo/. My commits are in /home/runner/work/<workflow-repo>/<workflow-repo>/target-repo/ which is a different git repo. The safeoutputs tool may be looking at the workflow repo instead.
Root cause
The push_to_pull_request_branch handler in safe_outputs_handlers.cjs does not look up the target repo's local checkout path. All git operations (git ls-remote, git fetch, git checkout, git am, etc.) run against process.cwd(), which in a multi-repo workflow is the workflow repo root — not the subdirectory where the target repo is checked out.
Contrast with create_pull_request
The create_pull_request handler already handles this correctly:
// safe_outputs_handlers.cjs — create_pull_request handler
let repoCwd = null;
if (entry.repo && entry.repo.trim()) {
repoSlug = repoResult.repo;
const checkoutResult = findRepoCheckout(repoSlug);
if (checkoutResult.success) {
repoCwd = checkoutResult.path;
}
}
const detectedBranch = getCurrentBranch(repoCwd);
// ...
transportOptions.cwd = repoCwd;
The push_to_pull_request_branch handler has none of this logic.
Expected behaviour
push_to_pull_request_branch should call findRepoCheckout(repoSlug) when entry.repo is set, and pass the resulting path as cwd to getCurrentBranch() and pushTransportOptions — the same pattern used by create_pull_request.
Suggested fix
In the push_to_pull_request_branch handler, after const { repoParts } = repoResult;:
let repoCwd = null;
if (entry.repo && entry.repo.trim()) {
const repoSlug = repoResult.repo;
const checkoutResult = findRepoCheckout(repoSlug);
if (checkoutResult.success) {
repoCwd = checkoutResult.path;
entry.repo_cwd = repoCwd;
}
}
Then:
// change
const detectedBranch = getCurrentBranch();
// to
const detectedBranch = getCurrentBranch(repoCwd);
And after const pushTransportOptions = { mode: "incremental" };:
if (repoCwd) { pushTransportOptions.cwd = repoCwd; }
Filed by Claude Code
Summary
push_to_pull_request_branchfails in multi-repo workflows where a target repository is checked out into a subdirectory alongside the workflow repository (e.g. viaactions/checkoutwith apath:parameter).Error messages observed
Two errors are returned by the tool across successive retries:
First attempt — the handler runs
getCurrentBranch()withoutcwd, so it detects the wrong branch (from the workflow repo root). It generates a patch against that wrong branch. When the target branch has no new commits relative to that wrong baseline, the tool reports:Second attempt — after the agent specifies the branch name explicitly, the handler tries to generate an incremental patch for the correct target branch. But
gitis still running in the workflow repo root, where the target branch does not exist:The agent's own conclusion from the run (via thinking):
Root cause
The
push_to_pull_request_branchhandler insafe_outputs_handlers.cjsdoes not look up the target repo's local checkout path. All git operations (git ls-remote,git fetch,git checkout,git am, etc.) run againstprocess.cwd(), which in a multi-repo workflow is the workflow repo root — not the subdirectory where the target repo is checked out.Contrast with
create_pull_requestThe
create_pull_requesthandler already handles this correctly:The
push_to_pull_request_branchhandler has none of this logic.Expected behaviour
push_to_pull_request_branchshould callfindRepoCheckout(repoSlug)whenentry.repois set, and pass the resulting path ascwdtogetCurrentBranch()andpushTransportOptions— the same pattern used bycreate_pull_request.Suggested fix
In the
push_to_pull_request_branchhandler, afterconst { repoParts } = repoResult;:Then:
And after
const pushTransportOptions = { mode: "incremental" };:Filed by Claude Code