Repository navigation
Description
Problem
The first half of preflight.sh (404 lines) reads branch state in shell and prints it as the == worktree ==, == base and divergence ==, == commits that would land ==, == commit types on the branch ==, == changed files ==, == diff == and == push state == sections. It recommends the default branch as the base, compares against origin's copy of it where one exists, runs a bounded fetch and caps the diff. The commit workflow reads overlapping facts (head, operations in progress, the default branch, ahead and behind counts) in its own shell, and the write-pr-description context script re-derives the same facts again, so nothing reads branch state once.
Part of #588 and #323. Delivers in Go the behavior of the branch-state sections of packages/agents/source/skills/pr/shared/scripts/preflight.sh. This change adds Go behavior only and switches no caller.
Acceptance criteria
- AC1: Given a primary checkout, an agent worktree under
.claude/worktreesor.codex/worktrees, a rebase, merge or cherry-pick in progress, or a branch with or without an upstream, when the report prints, then== worktree ==shows the root, the branch, the layout, the upstream ornone, and the operation in progress with the shell's "finish or abort it first" guidance (ornone), and warns when the branch is the default branch. - AC2: Given the default branch exists as a local copy, as origin's copy, as both, as neither, or with the local copy behind origin, when the report prints, then
== base and divergence ==names the default branch (the branchorigin/HEADnames, elsemain, elsemasteronly whenmainis absent andmasterexists) as the recommended base, states which ref it compares against (origin's copy where one exists, else the local branch), and prints the ahead and behind counts and merge base as the shell does, with "unknown (missing ref)" and "unknown" where a ref or merge base is missing. - AC3: Given a bounded fetch of the default branch, when it succeeds, times out or fails, or is not requested, then the report says
ok,failed (counts below may be stale)orskippedrespectively and continues to the remaining sections. - AC4: Given a branch with commits, when the report prints, then
== commits that would land ==gives the count and one line per commit even whenlog.showSignatureis on, capped as the shell caps it, followed by the messages in full capped at 200 lines; given no commits, then it says there is nothing to open a pull request for and to commit the work first. - AC5: Given commits on the branch, when the report prints, then it lists the Conventional Commit types with counts, the changed files with their status and the diffstat, in the shell's order; given no commits, then each section prints
(none). - AC6: Given a diff longer than the shell's line cap, when the report prints, then the diff is omitted with the guidance to read it one path at a time; given a diff within the cap, then it is printed in full.
- AC7: Given uncommitted changes, no upstream, or an upstream the branch is ahead of or behind, when
== push state ==prints, then it lists the uncommitted changes and says they are not in the pull request, or saysnone; says there is no upstream and that creating the pull request pushes the branch; or prints the upstream with the ahead and behind counts against it. - AC8: Non-functional: the report writes no file; the only Git state it changes is the objects and the remote-tracking ref of the default branch from the one bounded fetch; and it makes no network connection other than that fetch.
Scope and non-goals
Scope: the seven branch-state sections above, in the shell's order and with its headings and wording.
Non-goal: the existing pull request, repository, template, pre-approval, review, preconditions and draft sections, which child 06 ports. Non-goal: the commit workflow's own base selection (local versus origin) and its report text. Non-goal: worktree readiness checking, which #755 owns. Non-goal: reading push state from live origin or choosing a push kind, which child 09 does. Non-goal: changing the report's wording. Non-goal: switching the shell caller, which child 12 does.
Approach
Meet AC1 to AC8 with failing table-driven cases first on real scratch repositories for the refs, with the fetch's outcome injected, comparing each section with captured shell output. The pull request report's own base choice (the default branch) is kept as it is. The package layout is the implementer's choice within those outcomes.
Dependencies
Blocked by: #910, #850 (child 01 of #322, "Read commit workflow state in Go", the commit-skill area state reader), whose reader supplies the head, operation-in-progress, default-branch, ahead and behind facts this report prints. The two areas keep one implementation of those reads and this child adds none; it adds only the pull request report's own selection and layout on top.
Prerequisite: harness and worktree context delivered under #321.
Size
M. One pull request. Estimated under 500 changed code lines with tests, because the state reads come from the #322 child 01 reader rather than being written here. If that reader is not merged first this child does not start; it does not grow to carry a second reader.
Verify plan
- AC1, AC2, AC4, AC5, AC6, AC7: Go tests over scratch repositories compare each section with captured shell output, including a stale local default branch and a diff over the cap.
- AC3: a test with a fetch runner that succeeds, sleeps past the bound, fails, and is not requested.
- AC4: one case sets
log.showSignatureon and checks one line per commit. - AC8: a test records the files written and the Git refs changed, and a stub
gitrejects any network operation other than the one fetch. - Go tests run in the existing Go CI on macOS, Linux and Windows.
- Definition of done: D1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification. D2 an independent review approves the exact merged head, and every finding has a recorded disposition. D3 required checks pass with no gate loosened. D4 the leak scans the repository specifies are clean, and every post made for this work passes the per-post leak review before it is posted. D5 every commit is signed. D6 the documentation matches the change or the Verification says why there is no impact. D7 every commit has an
Assisted-bytrailer and the pull request has theprovenance:agent-assistedlabel. D8 the pull request stays within the size limits. D9 follow-ups are filed as issues and listed under Related. D10 the merge closes the issue through a closing reference, the board shows Done, and the finalStatus:comment names the merge commit.
Risks
A base chosen differently from the validator and the review would compare against a stale local branch and count merged commits as landing. The AC2 cases are the control. Undo: revert the change; nothing calls the Go report yet and the shell prints these sections.
Operator authority
None.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 27, 2026
Refinement: READY — Print the pull request preflight's branch state from agentrepo pr
Model: gpt-6-astra
Child 05 Print the pull request preflight's branch state from agentrepo pr
Verdict: READY
Checked: The binding dependency on #322 child 01 resolves ownership and the reuse-dependent estimate. PR-specific base selection, upstream reporting and capped output remain distinct from commit reporting and publication planning. Evidence:
packages/agents/source/skills/pr/shared/scripts/preflight.sh:129,packages/agents/source/skills/pr/shared/scripts/preflight.sh:197.Gaps: None.
Split: M is plausible because the prerequisite supplies the shared state reads. The child explicitly waits for that prerequisite.
Definition of done
The definition of done for this issue (Feature). Tick each item and give its evidence.
check-leaks.shwith the repository's private-strings list, and the leak review of each post.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.provenance:agent-assistedlabel.Status:comment names the merge commit.mise run checkis green, and so are the coverage floorsmise run cover-go-checkandmise run cover-py-check, whichcheckdoesn't run.packages/agents/source/commits whatmise run generate-skills, thenmise run skill-tokens, thenapm installrewrite, in that order, andcheck-generated-skills(part oflint) passes.docs/agent-skills-migration.mdor the adoption docs, or the PR's Verification says "No consumer impact" and why.Round: 3 of 3