pushing-commits-to-the-repo
GitHub指导 Agent 完成 PR 创建、代码推送、CI 监控及评论处理的全流程。包含模型选择策略、合并标准(Merge Bar)及元数据更新规范,确保 PR 符合审查要求并顺利合入。
触发场景
安装
npx skills add pydantic/pydantic-ai --skill pushing-commits-to-the-repo -g -y
SKILL.md
Frontmatter
{
"name": "pushing-commits-to-the-repo",
"description": "Open and advance a PR — write current metadata, apply the bounded pre-push review gate and its exemptions, push, watch CI, and triage comments. Use whenever you open a PR or push a commit."
}
pushing-commits-to-the-repo
Pushing starts a loop; it does not end the task. Work stops only when the current HEAD meets the merge bar below, every comment is triaged, and metadata is current. Apply the prose-only documentation exception when that exception covers the whole PR.
Lifecycle: implement → targeted verification → commit → pre-push gate → push → CI → required reviews → metadata. Apply the exceptions below at each gate.
Model tiers
Choose by the session's model family, not by the harness.
| Family | Strong | Light |
|---|---|---|
| Claude | latest Opus | latest Haiku |
| GPT | latest Sol | latest Luna |
| Other | session's model | session's model |
Start sessions that drive a PR on the strong tier.
Use the light tier for the metadata check and, when your environment provides it, local /review-branch runs.
Use the light tier for pre-push review until hosted review has commented on two earlier pushes.
Then use the strong tier for pre-push review.
Pass the model explicitly when the dispatch accepts one.
Set the light model's effort from the PR's complexity.
Merge bar
A maintainer with merge rights (Douwe, Aditya or Mike) merges at this bar. Never merge the PR yourself.
| Size label | Needs |
|---|---|
| S | CI green and a clean douwebot approval. An obviously trivial S PR needs CI green only. |
| M, L, XL | CI green and a clean douwebot approval. |
Judge an S PR trivial only for string fixes or a clearly positive one-file docs update.
State that judgment in the PR body.
Until a size label exists, do not claim the trivial-S exception.
Clean means douwebot APPROVE on the current head, with no douwebot comments on that head.
Address every douwebot comment, including non-blocking comments.
After addressing comments, obtain a clean approval on the resulting head.
Resolve every review thread.
Douwebot posts as github-actions[bot] through the trusted PR Bots publisher.
Verify its successful run and <!-- douwebot:review run=<id> head=<sha> --> receipt.
CI Review can use the same bot account but carries a separate gh-aw receipt; it cannot satisfy this bar.
Associate inline comments with their parent review's commit because GitHub can move a comment's commit_id after a push.
A clean, maintainer-authorized douwebot:review-agent-config approval satisfies the same requirement for protected paths.
A human approval does not substitute for douwebot.
PR Review Gates enforces M/L/XL against the recomputed size and exactly one matching label.
Size S remains a manual judgment; review enforcement skips merge groups after admission.
A merge-queue removal posts no comment and leaves the PR open. Detect it as a new removed_from_merge_queue event in gh api --paginate repos/pydantic/pydantic-ai/issues/<number>/timeline while the PR is still open; a merge logs the same event.
Diagnose the failed jobs of the PR's newest merge_group run (head_branch gh-readonly-queue/main/pr-<number>-<sha>) as step 2 of "After you push — the loop" requires. Never re-enqueue the PR; a maintainer does.
After diagnosing, post a PR comment that names each failed job and its cause, with evidence: your fix commit, a known flake, or a failure already on main. When the current head meets the merge bar again, comment that the PR is ready to re-enqueue.
When you open the PR
Carry maintainer ownership onto the PR
For immediate maintainer work, assign the PR to the same human maintainer.
Use gh pr create --assignee <maintainer-login> or gh pr edit <number> --add-assignee <maintainer-login>.
Recover the owner from existing context or the linked issue's maintainer assignee and pydanty:skip label.
Write the title and body
Follow the title and template rules in the root AGENTS.md.
Put every closing issue reference at the start of the body, immediately after any required
attribution line. These references are the first non-attribution content; use one Closes #<issue>
line per issue the PR will close. Put related but non-closing issues in the explanation instead.
Keep visible body content within 40 lines. Exclude template lines and collapsed <details>
contents from the count. For a feature or behavior change, use this order:
- Why we make these changes — State the problem and decision in a few sentences. Link the issue.
- New public surface — List each new maintained symbol. Write
nonewhen there is none. - User-visible behavior — Show the smallest before-and-after example. Replace it with a call-path diff when the changed call chain explains the behavior; do not include both.
- Verification — Link the exact proving tests from the PR's Files changed tab so links survive
later pushes. Put a minimal runnable playground in
<details>only when it helps reviewers reproduce the behavior. - What changes for existing users — State the effect in one sentence.
Nothingis valid.
Use one collapsed <details> section per goal only when the PR has multiple independent goals.
For a trivial PR, use the issue link, a short summary, and the test plan.
User-visible call-path diff
Use one fenced diff tree from the public entry point to the changed observable result.
- Format each node as
path/file.py :: Class.method()orpath/file.py :: function(). - Indent each callee beneath its caller with
└─. Preserve enough unchanged nodes to show each edge. - Collapse irrelevant intermediate calls as
… unchanged machinery …. - Include arguments only when they explain the change.
- Include results only on relevant leaves.
- Keep the shared caller prefix unmarked. Mark only diverging nodes, relevant arguments, or results.
- Target 12 content lines inside the fence. Never exceed 20; collapse secondary branches instead.
Publish PR decisions
When .claude/skills/branch-context/pr-decisions.md has at least one entry, include them near the
end of the body, before the checklist. Skip the section entirely when the log is empty or absent —
/initialize-worktree and /adopt-pr own creating it, not this step:
<details>
<summary>PR decisions</summary>
<dated decision entries>
</details>
Do not copy the decisions template's instructions into the PR body. The section is public. Leave out confidential or privileged reasoning. Keep session ids: a later agent uses them to find the session that made the decision.
Keep labels current with the title and body
For prose-only documentation, handle title, body, and labels directly. Otherwise, assign updates to the same subagent. Reconcile labels whenever the title or body changes.
Run .agents/skills/pushing-commits-to-the-repo/label-catalog. Read the printed file directly for prose-only documentation; otherwise give it to the subagent.
The checked-in catalog supplies clones and worktrees without label-read requests.
Run the helper with --refresh after creating, renaming, or updating repository labels.
Commit refreshed catalog changes.
The helper uses at most two requests and verifies completeness before replacing the catalog.
Never fetch labels individually or pass raw label API responses.
Keep the category label aligned with the PR's purpose (bug, feature, docs, chore, refactor).
Add existing topic labels for every subject materially covered by the final title, body, and diff.
Ignore incidental references, checklist text, and verification boilerplate when choosing topics.
Remove topic labels only when the final scope no longer supports those labels.
Preserve size, priority, review, and automation labels. Do not create or rename labels unless the user requests that change.
Apply label additions and removals in a batch with the title/body update. Verify the resulting metadata.
Apply exactly one package label: pkg:core, pkg:harness, pkg:clai2, pkg:evals, pkg:graph or pkg:clai.
Use the catalog descriptions to choose. Tests and docs count toward the package they cover.
Use pkg:core for repository infrastructure. For changes spanning packages, choose the package whose users the change serves.
Labelling needs triage permission on the repo (Pydantic team members and their agents). If it fails, quote the actual error rather than concluding you lack permission. Size labels are applied automatically — don't set them.
Prose-only documentation
Prose-only documentation changes only natural-language text, including docstring prose and descriptive instruction wording. Substantive changes to instruction or review policy do not qualify. Executable code, code examples/snippets, configuration, schemas, CI logic, and machine-consumed data changes do not qualify.
Skip pre-push-review, all local reviewers, the second-opinion choice, and the final metadata-subagent review.
Handle metadata directly. Keep CI checks and triage comments already posted before handoff.
Apply the merge bar, including its trivial-S exception, to required hosted reviews.
Leave automatic configured CI and hosted review workflows unchanged; they may run independently. Do not edit workflows or triggers to implement this exception. Once the merge bar is met and posted comments are triaged, hand the PR diff to the maintainer driving you, or another maintainer, to inspect and merge. Never merge the PR yourself.
Mechanical text/data refreshes
A small mechanical text/data refresh changes no code, runtime behavior, CI logic, or substantive instruction or review policy. A catalog-row refresh is one example.
For this case, skip local pre-push-review and any additional substantive review dispatch. Do not
ask for a second-opinion choice. Automatic configured CI and hosted reviews still run.
Review scope
The first substantive pre-push review assesses the full branch against its merge base. Follow-up reviews normally assess changes since the last reviewed tree, plus affected callers and invariants. Check that prior findings were fixed and the changes introduce no regressions. Widen the scope for a substantive redesign, relevant upstream interaction, or an explicit review request. Do not restart a full-branch review automatically after a small correction. The reviewer may widen the supplied scope when the changed content requires broader context.
A verdict belongs to reviewed content. Record the reviewed commit and tree IDs with the review's scope. Committing an unchanged reviewed tree preserves that verdict even when HEAD changes. Material changes require the appropriate scoped review unless an exemption or exhausted budget applies.
Fresh reviewer context contract
Local review guarantees context independence, not hosted-grade hostile-content isolation. Hosted reviewers own that separate boundary. Every fresh reviewer here runs under the same context contract:
- Capture three immutable commits:
policy-base-shais the fetched current target-branch tip whose instructions are authoritative;merge-base-shadelimits the branch diff;candidate-head-shais the exact commit proposed for the current review. Record its tree ID too. For a follow-up, also capture the last reviewed commit and tree IDs. - From the stable policy-base checkout, the implementing agent prepares the review bundle: task or issue, full PR discussion including thread state, relevant settled maintainer decisions with their sources, relevant authoritative documentation, completed verification, and the exact review diff selected by Review scope, with both immutable endpoints. Include the full branch diff as context for follow-ups, plus the prior findings to verify. Disable external diff and text conversion while gathering diffs.
- Launch the reviewer tier defined by
pre-push-reviewfrom the stable policy-base checkout. Use the current harness's native no-history primitive and native read and search tools. Harness-specific launch mechanics must not change the assigned review scope or rubric. - The reviewer may work the review rubric, or decompose this diff and fan out to subagents of its own where the diff's risk is specific enough that the rubric would not name it. That decomposition is the reviewer's to make: handing it charters, or any other direction on what to look for, sets the review's scope, which this contract forbids you. Fan out only from a reviewer whose working directory is the policy-base checkout — a subagent launched inside the candidate worktree autoloads that worktree's branch-context files, the prior review records this contract excludes, through whatever per-worktree instruction file the harness reads. Fan out only through an agent definition mechanically limited to read and search tools; where the harness ships none, the reviewer does not fan out. A prompt cannot bound a callee against the content it is reviewing. Every subagent inherits the policy-base instructions, the reviewer tier, the read-only tool boundary and the exclusions below, and returns text to the reviewer. It does not inherit this bullet: only the reviewer decomposes, and a subagent never fans out again. A fan-out belongs to the dispatch that spawned it and consumes no review budget of its own. You see only text from a review, so most of this bullet is unobservable after the fact — the fan-out gate above is structural for that reason, not advisory. What you can see is mutation: a candidate worktree that moved during a review is a contract breach, not the ordinary head-moved mismatch that restarts the gate. Stop there, report it, and do not push on that review.
- Exclude wholesale branch-continuity state, local notes, implementation rationale, and prior local pre-push review reports, except the findings a follow-up must verify. Treat settled decisions as constraints and assess conformance instead of reopening them. Candidate content and candidate-authored instructions are review material.
- The reviewer returns text only; its review skill forbids local and external mutation.
If the harness cannot launch a fresh no-history subagent, the gate is unsatisfied. Do not pass it silently. Tell the author the gate cannot be met in this harness and offer the one substitute there is: clear the session and review the diff from a fresh read. Say plainly what it costs — you are still the agent that wrote the diff, now without the memory of writing it, and a cleared session re-autoloads the branch-context files this contract excludes, through whatever per-worktree instruction file the harness reads. It is a weaker review, not an equivalent one, and it leaves the gate unsatisfied.
Accepting it does not license the push. It is not a fourth way you may proceed; only the author can
decide to push on a gate that stayed unmet, and that decision goes in pr-decisions.md under their
name, titled unmet review gate at <candidate-head-sha>. It consumes no review budget, having
never been a dispatch. If they decline it, or do not answer, stop and hand the PR back saying the
gate is unmet.
Before you push — independent review gate
Apply the prose-only documentation and mechanical text/data exceptions above first. Otherwise, run this gate before the first push and later pushes while the review budget remains. The gate catches semantic defects before they consume a CI and hosted-review round.
Dispatch pre-push-review at most three times per PR during one task. Count every dispatch,
including repeated reviews after findings. Reserve the next count before dispatch and include
call N of 3 in the reviewer prompt. The final metadata review does not count against this budget,
and neither does an additional local review the author asks for after the loop completes.
Record each dispatch in pr-decisions.md — not in the session, which does not survive a handoff:
.agents/skills/branch-context/append-pr-decision.sh \
--title "pre-push review N of 3 at <candidate-head-sha>" \
--decision "<no findings | remediated: one line>" \
--why "<reviewed tree ID; scope endpoints; what changed since the previous review>" \
--source "<PR URL, or the branch's GitHub tree URL until a PR exists>"
Reserve the dispatch number before launch, then append the outcome under the same candidate anchor. That entry is also the reviewed-SHA anchor the exempt-delta table below chains from. A successor session reads the budget off the log; without it the cap silently resets.
-
Commit the exact state you intend to push. Leave nothing staged, unstaged, or uncommitted unless the user's instructions override this.
-
Fetch the declared target branch. Capture and validate the full policy-base and candidate HEAD SHAs, compute the merge-base SHA, and verify the candidate worktree is clean. Materialize the policy-base checkout the contract above refers to — it does not exist until you make it:
POLICY_BASE_DIR="$(mktemp -d)/policy-base" git worktree add --detach "$POLICY_BASE_DIR" "$POLICY_BASE_SHA" # ... run the gate ... git worktree remove --force "$POLICY_BASE_DIR"Put it outside the candidate worktree. A path inside it dirties the tree the clean check below is about to inspect. Materialize it for every review, including one that only needs to read instructions: whether the reviewer may decompose the diff turns on it, so skipping it would let your launch choice decide the review's scope, which the contract forbids you.
-
Select the review scope above. Prepare the review bundle under the context contract.
-
Launch the fresh subagent under the context contract above. Require actionable findings or
current at <full-candidate-head-sha>. -
Triage every finding. Remediate valid findings, rerun affected verification, and commit. Dismiss invalid findings only with concrete evidence. If a finding exposes a real design choice, API trade-off, or behavioral default, pause the push and give the maintainer the options, trade-offs, evidence, and a recommendation; record the resulting decision. A remediation changes the candidate content. Reapply this gate, including its scope and exemptions, only while the budget remains. After a maintainer decision changes the acceptance criteria, dispatch a different fresh subagent when the budget remains. An evidence-backed dismissal on unchanged reviewed content does not require another pass. Escalate persistent disagreement.
Stop after a review returns no findings. After the third review, remediate its findings and run the relevant local checks. Do not dispatch a fourth review. Continue with the push, CI, and hosted review. Budget exhaustion is one of four ways a pushed SHA can go un-reviewed; the others are an evidence-backed dismissal on unchanged reviewed content, above, an exempt delta from the table below, and a push the author authorized over a gate that could not be met, recorded under their name. The first three you may decide. The fourth only they may. Nothing else.
Immediately before pushing, verify the worktree is clean and its tree equals the recorded reviewed tree. A different commit with the same tree keeps the verdict; record the new commit alongside the reviewed anchor. After third-review remediation, verify HEAD equals the locally checked remediation commit instead. Any other mismatch restarts the gate while the budget remains, unless the delta is exempt below.
When a later push does not need another review
Classify the actual delta, regardless of whether CI or a reviewer triggered the change. Routine CI repairs may skip repeated review only under the checks below. Changes to runtime, API, compatibility, design choices, or assumptions require review within the remaining budget. Keep targeted verification and configured CI and hosted reviews for exempt deltas.
Compute that delta from the last reviewed SHA, never from the last pushed one, and record which reviewed SHA the exemption chains from beside the budget count. Otherwise consecutive exempt pushes drift arbitrarily far from anything a reviewer read, each hop defensible on its own.
| Exempt delta since the reviewed SHA | Check |
|---|---|
| Missing coverage, test-harness repairs, or fixture/snapshot corrections to established intended behavior | inspect the full diff: test code/data only; cite the established expectation and run affected tests; a snapshot must not bless a newly observed regression |
Output of the repo's own tooling (make format, lint autofix) |
run that tooling on the reviewed SHA in a scratch checkout; its tree equals HEAD's |
Comments or docstrings only, no docs/** page |
no non-comment line appears in git diff <reviewed>..HEAD |
| Target-branch merge with no conflict resolution | git diff <old-base>...<reviewed-head> equals git diff <new-base>...HEAD |
| Commit or revert to a tree that was already reviewed | git rev-parse HEAD^{tree} equals a recorded reviewed tree |
| Lockfile-only dependency bump | only lock and manifest paths changed |
Anything not named above re-reviews. Size is never the test: a one-line production fix is the shape a
wrong fix hides in, which is why the root AGENTS.md requires reproducing the defect first. Four
deltas that look exempt and are not — a cassette re-record whose request body changed (a
wire-contract change wearing a test path), a conflict resolution inside an otherwise-exempt merge,
a snapshot accepting a newly observed regression, and any change to public API including a rename.
Applying a review finding follows the same delta classification; an exact suggested edit is not itself an exemption.
To claim an exemption the table does not name, write down the rubric rung the delta could touch and
why it cannot, in pr-decisions.md.
Never use the implementing agent as the reviewer. The one exception is the substitute the contract names for a harness that cannot launch a fresh no-history subagent at all — the author accepts it, and it leaves this gate unsatisfied. Never treat this gate as test execution.
Never force-push an open PR branch. Push follow-up commits so previous reviews remain valid; maintainers can squash them when merging.
Attempt the push. If it fails, read the real error. Do not infer a restriction from metadata.
After you push — the loop
These gates catch different failures; none replaces another:
- Independent pre-push review catches semantic and design defects before they consume a CI or hosted-review round.
- CI runs the repository-wide type check, test, and coverage gates.
- Hosted reviewers inspect the pushed diff with different models, instructions, and context.
For prose-only documentation, follow the exception above for local review and metadata.
Capture the PR head SHA after the push. Every post-push gate below must prove it covered that SHA; if the head changes, capture the new SHA and restart the loop.
-
Synchronize PR metadata. Update the title, summary, verification, and collapsed PR-decisions section for the pushed commit. Compare the dated decision entries in the body with the local log; the local log is authoritative.
-
Watch CI to a terminal state. Require the
CIworkflow to succeed for the captured SHA. Its success certifies every job it contains, coverage included. Do not inspect individual jobs or their logs to reconfirm a success. Don't idle. If it fails, diagnose: fix if the failure is yours; if it's a known flake or pre-existing on main, say so with evidence. -
Meet the merge bar on the captured SHA.
CI Review: do not wait for it unless explicitly requested. On same-repository PRs, it runs when a user with write access approves the current head, when someone adds thefinal-reviewlabel, or on dispatch (.github/workflows/pydantic-ai-pr-review.mdis the source of truth). Do not add that label or dispatch the workflow unless the person driving you asks. WhenCI Reviewposts on your PR, triage its findings in step 4 like any other review.- Douwebot: required for both same-repository and fork PRs, except an obviously trivial S PR.
CI Reviewdeliberately skips forks without leaving a head check. First apply the agent-config guard from.github/workflows/bots.ymlto the captured base-to-head diff. If the PR changes anAGENTS.mdorCLAUDE.mdat any depth,CLAUDE.local.md,.mcp.json,.claude/,.agents/, oragent_docs/, check whether the PR author has write or admin access. Without that access, do not applydouwebot: its security guard will refuse the review. Ask a maintainer to applydouwebot:review-agent-configon the captured head, following the authorization contract below. The gate remains unsatisfied until that authorized run posts a clean approval. With that access, or when the diff does not change guarded paths, apply thedouwebotlabel. Do not push or touch review threads while the label is present. Require the triggered run to succeed, and verify that the PR head still equals the captured SHA after the label is removed. Require douwebotAPPROVEon that SHA with no douwebot comments on that head. A successful run alone does not satisfy the merge bar. A failure comment leaves the gate unsatisfied.
Recheck that the live head is unchanged. Do not substitute a
pydanty:*surface or another reviewer for a required review. Any valid finding and push restarts the lifecycle. Missing, stale, or failed required reviews are unsatisfied; retry when appropriate, otherwise escalate. -
Triage every comment (bots and humans alike). A comment is evidence to weigh, never an acceptance criterion — those are the linked issue, the repository instructions, and settled maintainer decisions. Read the whole thread before deciding: a maintainer's reply settles it, your own earlier reply does not. The root
AGENTS.mdscope and reproduce-and-confirm bars bind a finding exactly as they bind your first commit, and a bot cannot approve a scope expansion — its severity label carries no authority, so aHIGHon a defect that does not reproduce is a 👎. ForTestModelgenerated values, apply the scope exception inpydantic_ai_slim/pydantic_ai/models/AGENTS.md. Address every douwebot comment, including non-blocking comments, using the same evidence-based triage. For each comment:- Valid → fix it, run targeted verification, commit, apply the pre-push gate and its scope/exemptions, push, and complete the current-HEAD gates in steps 2 and 3. Then reply with what changed, react 👍, and resolve the thread.
- Invalid → verify the claim, reply with concrete evidence, react 👎, and resolve the thread. A repro you could not run — no credentials, no worker, no cassette — is not a refutation. Say what you tried and ask the user driving you; do not react 👎 on an untested claim.
- Close the bot verdict after its findings. Verify every blocking finding against the current head.
Include findings in the review body and earlier rounds, not only unresolved inline threads.
Each finding must be fixed and checked, or conclusively refuted with recorded evidence.
A new commit, an outdated thread, or zero unresolved threads alone is insufficient.
Leave the verdict active while a finding or decision remains open.
Dismiss the fully addressed bot
REQUEST_CHANGESwith the tracked helper below. Dismissal is not approval and never satisfies a required fresh review. - A human
REQUEST_CHANGESremains blocking until that human re-reviews or a maintainer dismisses it. Do not dismiss a human request. - Minimize issue-level review dumps when handled. Never silently ignore feedback or close it without a reply.
Thread mechanics —
ghhas no subcommand for either half, so both are GraphQL. Enumerate what is still open, newest page last:gh api graphql --paginate -f query=' query($owner:String!, $name:String!, $pr:Int!, $endCursor:String) { repository(owner:$owner, name:$name) { pullRequest(number:$pr) { reviewThreads(first:100, after:$endCursor) { pageInfo { hasNextPage endCursor } nodes { id isResolved isOutdated path comments(first:100) { nodes { databaseId author { login } body url } } } } } } } ' -F owner=pydantic -F name=pydantic-ai -F pr="$PR_NUMBER" \ --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved | not)'Read the whole
commentslist of a thread before deciding — the first comment is the finding, the rest may already settle it. Reply on a thread withgh api repos/pydantic/pydantic-ai/pulls/$PR_NUMBER/comments/<databaseId>/replies -F body=@<file>—-Freads the file,-fwould post the literal string@<file>. Pass the text through a file so contributor-quoted$(...)and backticks are never expanded by your shell. Then resolve the thread by its nodeid:gh api graphql -f query=' mutation($id:ID!) { resolveReviewThread(input:{threadId:$id}) { thread { isResolved } } } ' -F id="$THREAD_ID"Resolving is not the same as agreeing: resolve a thread you answered with evidence too. Leave one open only while a person still owes a response.
After verifying every blocker in a bot verdict, prepare a dismissal reason file. Use the attribution required by your active repository or harness instructions for the first line. Explain each fix or refutation and link the commits or evidence. Pass the explicit review ID and full verified head to the tracked helper:
bash .agents/skills/pushing-commits-to-the-repo/dismiss-addressed-bot-review \ pydantic/pydantic-ai "$PR_NUMBER" "$REVIEW_ID" "$VERIFIED_HEAD" "$REASON_FILE" \ --all-blockers-addressedThe final flag attests that you assessed every blocker, including review-body findings. The helper rejects human verdicts, unresolved threads involving that bot, and changed or closed heads. Multiple workflows share a bot account; identify the review by its body and originating run. Read the resulting PR review state; another active request may still block review eligibility. If dismissal fails, report the actual error and leave that close-out item pending.
-
Escalate real trade-offs, don't guess. If a comment needs a maintainer decision (a design choice, an API trade-off, a behavioral default), leave a comment containing: the background, your reasoning, the decision that needs making, the trade-offs (pros/cons of each option), and your recommendation. Then poll every 30 minutes for a reply and continue when it lands.
-
Stop when steps 2 through 4 have each reached an accepted terminal state on the current HEAD, with any documented skip classified explicitly. Their results are the evidence; do not re-read a state an earlier step already established. When the HEAD changes, capture the new SHA and repeat the loop.
When the loop completes — choose an additional review surface
Skip this choice for prose-only documentation and mechanical text/data refreshes defined above.
The required reviews are not on this menu. Step 3 applies the merge bar to both same-repository
and fork PRs. CI Review starts on a write-access approval of the head, a final-review label,
or a dispatch. Green CI alone never starts CI Review.
What this section chooses is a second opinion on top of the required reviews, and the choice belongs to the person whose PR it is, not to you.
Report the diff first: its size label, how many files it changes, and where the change lands on the
review rubric — public API, then concepts and behavior, documentation, tests, code quality. Then
recommend one from those three facts and ask. Lean toward none when the change cannot move a rung
the required review has already covered: a dependency bump, a formatting pass, a test closing a
coverage gap. Lean toward a surface when it moves public API, concepts and behavior, or user-facing
docs — where a reviewer catches things like an example built on an outdated model. Small diffs are
cheap to review, so take one when the call is close.
| Surface | Choose it when |
|---|---|
pydanty:review-branch |
The diff reaches widely and you want findings fixed rather than only reported. It runs a fixed reviewer roster and pushes remediation commits to the branch. It waits on green CI. |
pydanty:review-lite |
The diff is narrow or unusual enough that a fixed roster would look past it. It writes review charters for this diff, dispatches one reviewer per charter, and adjudicates before posting. It reports and never remediates, and it has no CI precondition. |
douwebot |
One last high-judgment pass. Inline findings and a formal verdict, one review per label application. Unless the trivial-S exception applied, this is a second application of the reviewer that already gated the PR, against the diff as it now stands. |
| local | No hosted surface fits, or you want a read before the PR moves again. Dispatch pre-push-review under the context contract above and triage its findings like any other. |
| none | No second opinion. The merge bar still gates the PR. |
If the author does not answer, stop and hand the PR back naming the surface still pending. Do not pick one yourself to keep moving.
Triggering a hosted surface
The pydanty:* labels are defined outside this repository; what follows is their contract as the
maintainers run them, not something this repo can show you.
- Apply the label last, not early. None of them re-runs on a later push, so a deep review of a still-moving PR reports on a diff that no longer exists.
- How:
gh pr edit <number> --add-label <name>, after confirming the name against the checked-in label catalog. This needs triage permission on the repo. If it fails, quote the actual error rather than skipping the step on an assumed lack of permission. - The label tells you nothing about the outcome. Every surface consumes its own trigger label —
pydanty on pickup, before it has reviewed anything;
douwebotfrom analways()step that also runs when the job was cancelled. A faileddouwebotrun comments saying so and invites a re-apply. A completed douwebot review posts a formalAPPROVEorREQUEST_CHANGESverdict; inline findings arrive in separateCOMMENTEDreviews. An incomplete run or a moved head may have no verdict. Read the run conclusion and the captured-head reviews, as step 3 requires. - Wait for a pydanty run. It adds
pydanty:is-workingwhen it starts. Poll every 15 minutes for up to 2 hours 30 minutes. Never push to the branch and never touch a thread whilepydanty:is-workingis set.pydanty:review-branchreports either a review,pydanty:reviewedon a clean pass, orpydanty:rb-pending— which means it deferred on red or conflicted CI and will retry on its own, so fix CI rather than re-applying.pydanty:review-liteposts a review and sets neither label. If nothing has landed at 2 hours 30 minutes, stop and hand the PR back saying the run has not reported. - A pydanty remediation commit is a new HEAD. Fast-forward before acting on the verdict, or you will read a head behind the PR. Then treat it as the loop preamble requires of any head change: capture the new SHA and restart the loop against it. Classify the remediation delta under the pre-push gate above.
- Known
douwebotrefusal: the job fails without reviewing if the PR touches anAGENTS.mdorCLAUDE.mdat any depth,CLAUDE.local.md,.mcp.json, or anything under.claude/,.agents/oragent_docs/— a security guard against a PR editing the reviewer's own instructions. The guard is skipped for an author with write or admin access on the repo. Don't apply the label to a PR the guard covers; the red check is the guard working. - When a maintainer explicitly requests review of those protected paths, apply
douwebot:review-agent-config. It authorizes one review only when its firstlabeledevent came from aUserwith current write or admin permission and the PR still has the event head. Do not treat label presence as approval for an ordinarydouwebottrigger or a later head. If the run fails or is canceled, remove and reapply the label; rerunning the old event is denied. - Afterwards, re-enter the loop. A hosted surface posts comments that need the same triage as any other.
Before handing the PR back
For prose-only documentation, check the title, body, and labels directly against this skill, root AGENTS.md, and the PR template.
Correct metadata directly, then hand the PR diff to a maintainer after the merge bar and comment triage are complete.
Skip the subagent steps below.
For other diffs, run this final metadata check after CI, any required hosted review, and comments have settled. Any author-selected additional review must also have settled.
-
Capture the current title, body, and labels. Dispatch a fresh subagent under the context contract above. The metadata subagent has not worked on the PR and never decomposes the diff. Run the subagent on the light tier from Model tiers. Set effort from the PR's complexity. The check compares text against written rules.
-
Give it the PR URL, linked issue, current
base...HEADdiff, final test status, captured metadata, complete catalog, and the local dated PR decisions. Exclude prior local review reports; permit the decisions log only to check its public mirror. -
Ask it to check only the title, body, and labels against this skill, the root
AGENTS.md, and the PR template. -
Require either
currentor exact corrections: title or body text changes and label additions/removals.- Require each correction to cite the rule it enforces.
- Require each correction to quote the title, body text, or label that breaks the rule. When the rule requires a missing element, require the correction to name that element instead.
-
Verify each correction. Keep a correction only when a rule in this skill, the root
AGENTS.md, or the PR template says what the correction claims and the current title, body, or labels break that rule. When that rule is not the one the correction cites, cite it on the kept correction. When you find a violation that no correction names, verify it the same way and add it as a kept correction. -
Edit the title, body, and labels once. Use the kept corrections, and write your own changes where they fall short. The edit is done when all three hold:
- The edited title, body, and labels follow every rule a kept correction cites.
- The edited title, body, and labels break no rule that the current ones follow.
- The edit applies no subagent text that no kept correction covers.
Committed changes restart the post-push loop; GitHub metadata-only changes do not.
-
Verify the live title, body, and labels match the checked metadata. After metadata corrections, wait for the corresponding edited-event checks and triage feedback. Require workflow-defined accepted terminal outcomes; earlier checks on the same HEAD do not cover the edit. Hand the PR back after these gates settle.
版本历史
-
819c9e7
当前 2026-11-03 00:26
新增对 merge-queue 移除事件的检测逻辑;移除基于大小的手动审批门禁;明确负责合并的维护者名单;强化 PR Review Gates 的大小依赖审批规则;澄清维护者问题路由及 PR 所有权保留机制。
-
b86a877
2026-10-19 07:24
优化PR元数据检查流程,使用轻量模型验证修正;强制每个PR必须包含一个pkg:标签;简化AI代码复选框步骤。
-
8a1a67f
2026-09-03 08:11
新增要求:在处理审查反馈前,必须先提供复现步骤和作用域检查。
-
fad54a9
2026-08-28 10:03
新增 PR 标题和正文撰写规范,包括变更原因、公共接口、行为示例及验证链接;引入调用路径差异格式;细化标签获取与应用逻辑。
-
43f982f
2026-08-19 23:48
新增PR创建时的标签自动应用逻辑;明确禁止强制推送;引入CI Review与douwebot的双层审查机制。
- 20cdf45 2026-07-25 05:33


