fix(review): resolve default branch dynamically before origin/main fallback (#436)#591
Conversation
|
Claude finished @kyle-sexton's task in 1m 59s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
SummaryThis is a well-scoped, correctly implemented fix. The Verdict: LGTM — one minor observation and one design note worth tracking, neither blocking. FindingsShell expression correctnessThe
Empty-output edge case (remote unreachable, remote in detached HEAD, awk matches nothing): the outer Security — shell injection surfaceThe extracted branch name is embedded inside double-quoted Minor observation: network round-trip with no explicit timeout
The PR body notes "same transport the clone already used" as justification — a valid point that a freshly-cloned checkout should have fast connectivity to the same remote. This is a design tradeoff, not a defect. Tracking it via #442 (the cross-plugin shared default-branch helper) would be the right place to address a Consistency across nine surfaces ✓All nine surfaces named in the PR body carry the identical sub-expression:
The Prose accuracy ✓The updated prose in Plugin design rules ✓
|
Post-green review classification
No blocking findings. CI green (14/14), consistency verified across all 9 surfaces. Flipping to ready for review. |
|
Claude finished @kyle-sexton's task in 2m 5s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
SummaryWell-scoped, correctly implemented fix. The Verdict: LGTM — one minor observation (pre-existing from the earlier automated review), not blocking. Shell expression analysisThe inserted rung across the four agent files: git merge-base "origin/$(git ls-remote --symref --end-of-options origin HEAD 2>/dev/null | awk '/^ref:/{sub(/refs\/heads\//,"",$2); print $2; exit}')" HEAD 2>/dev/null
The three-dot form in git diff --shortstat "origin/$(git ls-remote --symref --end-of-options origin HEAD 2>/dev/null | awk '/^ref:/{sub(/refs\/heads\//,"",$2); print $2; exit}')...HEAD" 2>/dev/null
Security
Consistency across nine surfaces ✓
The Plugin design rules ✓
Minor observation: network round-trip with no explicit timeout
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 15631b0e65
ℹ️ 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".
…rectly The dynamic default-branch rung added earlier resolved only the branch NAME via `git ls-remote --symref`, then ran `merge-base "origin/<default>"`. `ls-remote` does not populate a local `refs/remotes/origin/*` ref, so in `--single-branch`/shallow clones (the default `actions/checkout` shape, and the exact CI scenario the changelog names) `origin/<default>` is unresolvable, the rung fails, and the ladder falls through to the empty-diff terminal — a silent no-op review, the very bug this fix targeted. Fetch the resolved branch and diff against `FETCH_HEAD` (empirically the only locally-resolvable handle after fetching a non-tracked branch), mirroring the existing `PR_BASE` fetch. The rung stays lazy: the network `ls-remote`/fetch fire only when the local `origin/HEAD` rung fails, so the well-connected common case pays no round-trip (keeping the no-timeout tradeoff deferred to #442 out of the hot path). Applied across the four reviewer agents and the fanout diff-size snippet; the ladder ORDER is unchanged, so the prose surfaces stay accurate. Addresses the codex P1 on PR #591. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 55s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
SummaryThis PR now has two commits. The first ( The second commit is correct and closes the gap. Verdict: LGTM. Analysis of commit 2: fetch-before-merge-baseThe old rung (commit 1): git merge-base "origin/$(git ls-remote ... | awk '...')" HEAD 2>/dev/nullThe new rung (commit 2): { D="$(git ls-remote --symref --end-of-options origin HEAD 2>/dev/null | awk '/^ref:/{sub(/refs\/heads\//,"",$2); print $2; exit}')"; [ -n "$D" ] && git fetch origin "$D" 2>/dev/null && git merge-base FETCH_HEAD HEAD 2>/dev/null; }Shell correctness (
Consistency across 5 executable surfaces — all apply the identical pattern:
The The 4 prose-only surfaces ( CHANGELOG ( Version — Security — Carry-forward observation (non-blocking)The minor observation from prior reviews — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e0ae7355ac
ℹ️ 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 finished @kyle-sexton's task in 2m 13s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
Summary of commit 3 (
|
| Scenario | Fix covers? | Changelog says? | Match |
|---|---|---|---|
Full clone, origin/HEAD unset |
✓ Yes | "full clone whose origin/HEAD is unset" |
✓ |
Full-depth --single-branch |
✓ Yes | "full-depth --single-branch clone" |
✓ |
--depth=1 (default actions/checkout) |
✗ No | "Known limitation" section, deferred to #442 | ✓ |
The "Known limitation" language is accurate and honest. ✓
Residual observation (non-blocking, unchanged from prior reviews)
The git ls-remote + git fetch network round-trip has no explicit timeout. This remains a design tradeoff — not a defect — and the rung only fires when origin/HEAD is absent, keeping it off the hot path. Deferred to #442.
Verdict
LGTM. The three commits together form a coherent, correctly scoped fix:
- Commit 1 (
15631b0): adds thels-remotename-resolution rung - Commit 2 (
e0ae735): adds the fetch-before-merge-base step so the rung actually resolves in full-depth single-branch/unset-symref clones - Commit 3 (
bc546d1): corrects the changelog overclaim and honestly documents the--depth=1limitation
The --depth=1 gap is real and unaddressed by the code, but correctly documented as a known limitation deferred to #442. No new defects introduced. Plugin design rules and semver bump are correct.
|
Claude finished @kyle-sexton's task in 1m 25s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
SummaryCommits 1–3 were already LGTM'd by prior automated passes. Commit 4 ( Verdict: LGTM. The retargeting is correct, the prose is more accurate than before, and no code changes are introduced. Commit 4 analysisThe commit is CHANGELOG-only — exactly 2 lines changed in Before: After: Retargeting rationale is sound. The commit message explains it directly: #442 is scoped to the Prose improvement. The new wording ("a real design fork, tracked and deferred to #625") is more precise than the old ("a heavier tradeoff deferred to the #442 shared default-branch helper") — it names a concrete design choice (deepening vs. report-and-stop) rather than implying it's just a weight consideration, and it drops the inaccurate "shared default-branch helper" label. No code changes. All five executable surfaces ( No new prose drift. The four prose-only surfaces ( Carry-forward observation (non-blocking, unchanged from prior reviews)The |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 99e52af577
ℹ️ 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".
…llback (#436) Every review diff-base surface resolved the default branch as origin/HEAD, then fell straight to a literal origin/main. origin/HEAD is frequently unset in CI/shallow/fresh clones, so a master/develop repo fell past a non-existent origin/main to the echo HEAD terminal — an empty diff on a clean committed branch (silent no-op review). Insert a git ls-remote --symref rung before origin/main across the 4 reviewer agents, the fanout diff-size snippet, and the fanout/quality-gate ladder prose. Same fix mechanism as toolchain #411. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011V31qpAHP3jfs76B9d5Rfo
…rectly The dynamic default-branch rung added earlier resolved only the branch NAME via `git ls-remote --symref`, then ran `merge-base "origin/<default>"`. `ls-remote` does not populate a local `refs/remotes/origin/*` ref, so in `--single-branch`/shallow clones (the default `actions/checkout` shape, and the exact CI scenario the changelog names) `origin/<default>` is unresolvable, the rung fails, and the ladder falls through to the empty-diff terminal — a silent no-op review, the very bug this fix targeted. Fetch the resolved branch and diff against `FETCH_HEAD` (empirically the only locally-resolvable handle after fetching a non-tracked branch), mirroring the existing `PR_BASE` fetch. The rung stays lazy: the network `ls-remote`/fetch fire only when the local `origin/HEAD` rung fails, so the well-connected common case pays no round-trip (keeping the no-timeout tradeoff deferred to #442 out of the hot path). Applied across the four reviewer agents and the fanout diff-size snippet; the ladder ORDER is unchanged, so the prose surfaces stay accurate. Addresses the codex P1 on PR #591. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The FETCH_HEAD fix covers full-depth single-branch clones (and full
clones with unset origin/HEAD), NOT --depth=1 shallow clones. Default
actions/checkout is --depth=1 --single-branch, where fetching the
resolved branch at the same shallow depth leaves merge-base without a
common ancestor — verified empirically — so it still degrades to the
empty-diff terminal. Correct the overclaim ("the exact CI scenario")
and record the depth-1 limitation as deferred to #442.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The 0.14.3 changelog deferred the --depth=1 shallow-clone empty-diff residual to "the #442 shared default-branch helper", but #442 is scoped to the source-control plugin's origin remote-name hardcode and does not cover this review-plugin, distinct-mechanism (shallow deepen/report) concern. Point the deferral at the dedicated issue #625 so the tracked home is accurate and does not drift. Co-Authored-By: Claude <noreply@anthropic.com>
99e52af to
5186cf8
Compare
|
Claude finished @kyle-sexton's task in 2m 18s —— View job PR Review: fix(review): resolve default branch dynamically before origin/main fallback
SummaryThis PR has four commits that have been reviewed incrementally across prior automated passes. This pass covers the full PR at HEAD ( Commit 4 (
|
Summary
The
reviewplugin's diff-base resolution bakedmainas its terminal default-branch fallback. Every base-resolution surface resolved the default branch asorigin/HEAD, then fell straight to a literalorigin/main.origin/HEADis frequently unset in CI, shallow, single-branch, and fresh clones, so a repository whose default branch ismaster/developfell past a non-existentorigin/mainall the way to theecho HEAD/echo "unavailable"terminal — producing an empty diff on a clean committed branch: a silent no-op review with no error. This violated the convention-resolution ladder's "No baked repo assumptions, ever" (docs/MIGRATION-PLAYBOOK.md).Fix
A dynamic resolution rung now sits before the literal
origin/mainin every surface:This queries the remote's own default branch over the same transport the clone already used — host-agnostic, needing neither a locally-set
origin/HEADsymref norgh— andorigin/mainremains only as the terminal last resort (the existingecho HEAD/echo "unavailable"finals are unchanged).Mechanism choice. Two candidates resolve the default branch independently of the local
origin/HEADsymref:gh repo view --json defaultBranchRefandgit ls-remote --symref.git symbolic-ref refs/remotes/origin/HEADwas rejected — it reads the same ref the existing first rung (origin/HEAD) already tries, so it would be a no-op that merely satisfies a grep check. Between the survivors,git ls-remotewins on the plugin design boundary ("must work outside the repository and organization that produced it"; "never assume a browser is present") —ghis GitHub-only and often unauthenticated in exactly the CI/shallow-clone environment this bug targets. It also matches the resolution mechanism the sibling toolchain gap (#411, resolved separately) converged on.The remote name stays
origin; de-hardcoding the remote is the cross-plugin shared default-branch helper tracked by #442, out of scope here.Applied identically across nine surfaces — the resolution sub-expression is held constant, adapted to each line's surrounding syntax:
code-reviewer,security-reviewer,architecture-guardian,ecosystem-specialist) — themerge-basediff-base one-liner.fanout/SKILL.mdpre-computed diff-size shortstat snippet (three-dot range).fanout/SKILL.md,quality-gate/SKILL.md,quality-gate/context/per-slice.md,quality-gate/context/self.md— the ladder-describing prose, updated so the docs don't drift from the changed runtime behavior.Verification
Post-fix census — every remaining
origin/maininplugins/review/is the intentional terminal fallback preceded by the new rung, or updated prose (CHANGELOG excluded):Behavioral proof — with the local
origin/HEADsymref deleted (the CI/shallow-clone scenario), the first rung fails yet the base still resolves via the newgit ls-remoterung before reachingorigin/main:Repo lint/validation, post-fix:
Closes #436
Related
<default-branch>placeholder in check/lint has no repo-agnostic resolution guidance #411 — the same baked-<default-branch>bug shape in thetoolchainplugin, resolved separately (informational only; not touched here — it has its own open work). This PR reuses that fix'sgit ls-remote --symrefresolution mechanism for consistency.originhardcoded in pull-request create flow (low severity) #442 — the cross-plugin shared default-branch helper (de-hardcoding the remote name), which this fix defers to and stays scoped away from.🤖 Generated with a Claude Code implementation subagent (issue #436)