Summary
When using the SideRepoOps pattern to create a PR against a non-default branch of the target repository, the default safeoutputs configuration generates an E003 error (patch exceeds the 100-file limit), making it impossible to open the PR without a custom workaround.
Root Cause
safeoutputs computes the patch as diff(origin/$DEFAULT_BRANCH, HEAD). In a SideRepoOps setup, DEFAULT_BRANCH is automatically set to the default branch of the checked-out target repo (typically master or main).
When the agentic workflow is designed to operate on a non-default release branch (e.g. release-1.12.x), the agent switches to that branch after checkout. The diff baseline, however, remains origin/master. The resulting patch includes every file that diverges between master and the release branch — potentially hundreds or thousands of files — far exceeding the 100-file limit, even if the agent's actual change is just 1–2 files.
Failure Sequence
checkout step starts at master → DEFAULT_BRANCH=master
- Agent reads the target branch from the issue and runs
git checkout release-1.12.x
safeoutputs computes diff(origin/master, HEAD) = ~hundreds of files + the actual fix
- E003: patch exceeds 100-file limit → PR is not created
Workaround
We added a pre-step between checkout and the agent job that:
- Reads the target branch from a
branch/<name> issue label
- Re-anchors the git checkout to that branch
- Writes
DEFAULT_BRANCH=<branch> to $GITHUB_ENV so safeoutputs uses origin/<branch> as the patch baseline
- name: Re-anchor checkout to target release branch
shell: bash
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
# safeoutputs generates the patch as diff(origin/$DEFAULT_BRANCH, HEAD).
# The checkout above starts at master, so DEFAULT_BRANCH=master and the patch
# baseline is origin/master. If the agent then switches to a release branch,
# the patch includes all files that diverge between master and that
# release branch plus the actual fix — far exceeding the 100-file limit.
# Fix: read the target branch from the issue's branch/<name> label, re-anchor
# the checkout to that branch, and override DEFAULT_BRANCH so safeoutputs
# computes diff(origin/release-X.Y.x, HEAD) = just the actual fix.
ISSUE_NUMBER="${{ github.event.issue.number || github.event.inputs.issue_number }}"
if [ -z "$ISSUE_NUMBER" ]; then
echo "Error: no issue number available"
exit 1
fi
# Read the target branch from the issue's branch/<name> label.
# Exactly one such label is required — zero or multiple are a hard error.
mapfile -t BRANCH_LABELS < <(gh issue view "$ISSUE_NUMBER" --repo <target-repo> --json labels \
-q '.labels[] | .name | select(startswith("branch/"))')
if [ "${#BRANCH_LABELS[@]}" -ne 1 ]; then
echo "Error: issue must have exactly one branch/<name> label, found ${#BRANCH_LABELS[@]}: ${BRANCH_LABELS[*]}"
exit 1
fi
BRANCH="${BRANCH_LABELS[0]#branch/}"
if [[ \! "$BRANCH" =~ ^(master|release-[0-9]+\.[0-9]+\.x)$ ]]; then
echo "Error: branch/<name> label '${BRANCH}' does not match expected pattern"
exit 1
fi
echo "Re-anchoring checkout from master to ${BRANCH}"
git -C <repo-path> checkout -B "$BRANCH" "origin/$BRANCH"
git -C <repo-path> remote set-head origin "$BRANCH"
# Override DEFAULT_BRANCH so the safeoutputs patch baseline is origin/$BRANCH
# instead of origin/master (which would include all master→release divergence).
echo "DEFAULT_BRANCH=$BRANCH" >> "$GITHUB_ENV"
Suggested Improvement
This workaround is non-obvious, requires understanding safeoutputs internals, and has to be re-implemented by every workflow author that needs to target a non-default branch.
A few possible fixes:
-
Document the pattern in the SideRepoOps guide with an explicit note that DEFAULT_BRANCH must be overridden when the agent targets a non-default branch.
-
Add a base-branch option to checkout that, when set, automatically writes DEFAULT_BRANCH=<branch> to $GITHUB_ENV after the checkout completes — removing the need for a custom pre-step entirely.
-
Derive DEFAULT_BRANCH from the branch the agent is actually on at the time safeoutputs runs (rather than from the repo's default branch at checkout time).
Option 2 or 3 would be the most ergonomic; option 1 is the minimal acceptable fix.
Reported by Claude (claude-sonnet-4-6) based on a SideRepoOps workflow that creates PRs against versioned release branches.
Summary
When using the SideRepoOps pattern to create a PR against a non-default branch of the target repository, the default
safeoutputsconfiguration generates an E003 error (patch exceeds the 100-file limit), making it impossible to open the PR without a custom workaround.Root Cause
safeoutputscomputes the patch asdiff(origin/$DEFAULT_BRANCH, HEAD). In a SideRepoOps setup,DEFAULT_BRANCHis automatically set to the default branch of the checked-out target repo (typicallymasterormain).When the agentic workflow is designed to operate on a non-default release branch (e.g.
release-1.12.x), the agent switches to that branch after checkout. Thediffbaseline, however, remainsorigin/master. The resulting patch includes every file that diverges betweenmasterand the release branch — potentially hundreds or thousands of files — far exceeding the 100-file limit, even if the agent's actual change is just 1–2 files.Failure Sequence
checkoutstep starts atmaster→DEFAULT_BRANCH=mastergit checkout release-1.12.xsafeoutputscomputesdiff(origin/master, HEAD)= ~hundreds of files + the actual fixWorkaround
We added a pre-step between
checkoutand the agent job that:branch/<name>issue labelDEFAULT_BRANCH=<branch>to$GITHUB_ENVsosafeoutputsusesorigin/<branch>as the patch baselineSuggested Improvement
This workaround is non-obvious, requires understanding
safeoutputsinternals, and has to be re-implemented by every workflow author that needs to target a non-default branch.A few possible fixes:
Document the pattern in the SideRepoOps guide with an explicit note that
DEFAULT_BRANCHmust be overridden when the agent targets a non-default branch.Add a
base-branchoption tocheckoutthat, when set, automatically writesDEFAULT_BRANCH=<branch>to$GITHUB_ENVafter the checkout completes — removing the need for a custom pre-step entirely.Derive
DEFAULT_BRANCHfrom the branch the agent is actually on at the timesafeoutputsruns (rather than from the repo's default branch at checkout time).Option 2 or 3 would be the most ergonomic; option 1 is the minimal acceptable fix.
Reported by Claude (claude-sonnet-4-6) based on a SideRepoOps workflow that creates PRs against versioned release branches.