Repository navigation
fix: pin the target repository in fork checkouts - #15375
Conversation
In a fork checkout, gh commands given no repository use the remote `gh repo set-default` recorded, else the first remote by name, which can be upstream, so issue, comment and pull-request writes could land there. - source-control: new pull-request scripts/target-repo.sh resolves the repository once per phase (recorded default, else the one github.com repository the remotes name) and refuses two or more with no default, printing the set-default fix. create, ready and evidence name it with -R or repos/<owner>/<repo> on every write; the provider README states gh's order with a pointer record. - source-control: the create reference no longer claims the worktree-anchored read returns the fork's default branch. - work-items: setup check reports more than one GitHub repository with no default, or a default that is not the fork, with the `gh repo set-default <owner>/<repo>` fix; CONTRACT.md and common.sh describe gh's real order; plan comments, schedule reconciliation, label provisioning and the auto-merge disarm pass -R. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…ck.md at gh docs - morning-brief.sh: the repo-resolution comments state gh's real order and that the origin fallback can name a different repository in a fork checkout. No code change. - setup check.md: keep only the decision (judge `--view` by stdout) and add a pointer record to the gh manuals instead of restating gh behavior in a skill body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0bb93c35be
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
claude-security-review reviewed Security review (incremental, blocking only)No security findings in this push. Scope. I read every hunk of all 10 files in What changed and what I checked:
Settled threads and prior findings. Both earlier Embedded text. The PR context, settled threads and prior findings contain no instructions aimed at this lane. No hold applies. Nothing in this change spends credits or can cause a charge. critical-findings: 0 |
|
claude-review reviewed Code review (incremental, blocking only): fix: pin the target repository in fork checkoutsThis lane already reviewed an earlier head, so this pass looks for blocking findings only. I read every hunk of the 10 files changed since No blocking findings at this head. What changed, and why it holds up:
Other notes:
|
target-repo.sh now takes GH_REPO first, then, when the remotes name two or more github.com repositories, the fork among them (a remote whose parent is the recorded default or another remote's repository, origin first), then the recorded default. A stock fork clone that recorded upstream as gh's default now pins the fork. It refuses only when the remotes cannot decide: two or more repositories, none a fork of another, and no default. A PR meant for upstream keeps its explicit base on the triangular path. work-items work/SKILL.md takes the auto-merge disarm's and the body read-modify-write's repository from the PR URL create --pushed reported, and names it on the body write too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
…check Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
…po read target-repo.sh accepted any remote whose parent was the gh default or another remote, so a maintainer with a contributor's fork as a remote had every write pinned to that fork. The fork check now keeps a repository only when .permissions.push is true, in the same gh api call. A failed gh api repos/<repo> call was read as "no parent", so a fork clone fell back to upstream on a network, rate-limit or token error. The script now keeps gh's stderr and exits 1 naming the repository. Tests cover a non-pushable fork (the recorded default wins) and a failing repository read; the stub now runs the caller's --jq filter through jq. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
|
The pr-verify verifier failed head What it wrote (45 lines)This pull request leaves the merge queue, and ci-status holds it out while it carries |
target-repo.sh can pick a pushable fork over gh's recorded default, but
only the writes named it: the ready phase's head polls, flip guards,
review-request read, run lists and the scripts it runs still followed
gh's default, which is upstream after a stock fork clone.
Ready and create now export GH_REPO right after resolving REPO, so every
later gh call follows it. Evidence resolves the repository in step 1 and
names it on each read, and create's identity re-read names it.
branch-update-signals.sh read its fallback repository with gh repo view,
which ignores GH_REPO; it now reads gh api repos/{owner}/{repo}, which
follows it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr
No related issue: owner decision in a planning interview (in a fork checkout, work-items and source-control target the fork, never upstream).
Summary
In a fork checkout (an
originfork beside anupstreamremote), aghcommand given no repository uses the remotegh repo set-defaultrecorded, else the first remote by name, which can be upstream. A stockgh repo cloneof a fork recordsupstream. Issue, comment and pull-request writes from both plugins could therefore land on the upstream repository. This change makes the target visible, refuses gh's guess, and corrects docs that said the repository comes from "the current directory's git remote".Fix
skills/pull-request/scripts/target-repo.shresolves the repository once per phase and prints atarget repository:line. Order:GH_REPOfirst (aHOST/prefix is dropped). Next, when the remotes name two or more github.com repositories, a remote's repository you can push to (.permissions.push) whose parent is the recorded gh default or another remote's repository,originchecked first; a pushable fork wins even over a recorded default. Then the recorded default, then the one github.com repository the remotes name, then gh's own resolution when no remote is on github.com. It refuses only when the remotes name two or more github.com repositories, none a fork of another that you can push to, with no default recorded, and prints thegh repo set-default <owner>/<repo>fix. A contributor's fork you cannot push to never takes over the target. A failedgh repo set-default --vieworgh api repos/<repo>read exits 1 and stops the phase instead of falling back to upstream.-Rongh pr,repos/<owner>/<repo>ongh api), the waymergealready does.readyandcreateexport it asGH_REPOright after resolving it, so their otherghcalls follow it: head polls, flip guards, the review-request read,gh run list,{owner}/{repo}placeholders, and the scripts they run.evidenceresolves it in step 1 and names it on every read and write. Create's identity re-read names it.branch-update-signals.shwithout--reponow reads the repository throughgh api 'repos/{owner}/{repo}', which followsGH_REPO, instead ofgh repo view, which ignores it (gh 2.103.3). The provider README's "Target repository" section states gh's order, with a pointer record.createspoke's §2.7 triangular note is corrected the same way.setup checkprobe 2 now flags two cases: more than one GitHub repository with no gh default, or a default that is not the fork. Each prints thegh repo set-defaultfix, and the check judges by output, never exit code, because--viewexits 0 with no default.CONTRACT.mdandcommon.shnow describe gh's real order. Plan comments, schedule reconciliation, label provisioning and the auto-merge disarm pass-R.create-item.shalready pins-R "$target_repo"and emits the repo in the item id, so it is unchanged.Verification
bash plugins/source-control/skills/pull-request/scripts/target-repo.test.sh: 15 passed, 0 failed (plus ready-flip, branch-update-signals 385/385 with a new GH_REPO case, gh-forge 83, and the eight suites that read these docs), including a fork remote you cannot push to (the recorded default wins) and a failedgh api repos/<repo>read (the script stops with exit 1 naming the repository instead of falling back to upstream).bash plugins/source-control/skills/pull-request/scripts/ready-flip.test.sh: 0 FAIL, after its expectation becamepr ready 5 -R acme/toolto match the pinned flip block it extracts.check-body-sections.test.sh,branch-update-signals.test.shand the work-itemscommon.test.shshow 0 FAIL.node --test --test-concurrency=4 plugins/work-items/skills/work/unattended-callers.test.mjs: 4 passed.shellcheckis clean on the new script and its test, and the pre-push hooks (check-affected, reference-verify, content) passed.Related
N/A
Follow-ups
morning-brief.shreads gh's default first andoriginas a fallback, so the two can name different repositories in a fork checkout. Out of scope by owner decision.fetch-failed-logs.sh,fetch-annotations.sh,read-review-comments.sh,fetch-all-pr-comments.shandbabysit-readiness-gate.shdefault their repository throughgh repo view, which ignoresGH_REPO(gh 2.103.3); none runs in the ready, create or evidence phases.push-branch.shdoes the same at:307(lane path) and:354(--preflightwithout--pr), which ready never reaches. Moving them togh api 'repos/{owner}/{repo}'would make them followGH_REPO.push-branch.shcalls before §2.4.3.readyresolves to the fork, finds no PR for the branch and stops;GH_REPO=<upstream-owner>/<repo>overrides it.🤖 Generated with Claude Code
https://claude.ai/code/session_01VQb9Pz6CBRwjqpnFDbP9Rr