Skip to content

Check the gates and resolve confirmation before publishing from agentrepo pr #917

Description

@tbhb-agent

Problem

create-pr.sh is the entry point for publication. Before anything is written it parses a flag allowlist, refuses an unsafe branch state, checks the active gh account against the machine's gh_login, validates the draft, resolves the draft's labels, milestone and issue references against GitHub (properties.sh, which only create-pr.sh calls), verifies the review stamp's bindings, runs the leak scans, lint, the independent review and the tests through the cached gate runner, and resolves the confirmation (--confirmed, then session pre-approval, then the machine delegation check). That is the authority logic for publishing a pull request, about 270 lines of shell between the two scripts.

Part of #588 and #323. Delivers in Go the behavior of packages/agents/source/skills/pr/shared/scripts/create-pr.sh up to the point of the push, and of properties.sh. This change adds Go behavior only and switches no caller.

Acceptance criteria

  1. AC1: Given any flag outside --dry-run, --check-description, --rerun-gates, --rewrite and --confirmed, or --confirmed in unattended mode, when publication starts, then it refuses with the shell's usage or message before any check.
  2. AC2: Given no draft, a rebase, merge or cherry-pick in progress, a detached HEAD, a draft with no base, the base branch checked out, or a base naming no local or origin branch, when publication starts, then it refuses with the shell's message and nothing is pushed or written.
  3. AC3: Given a shallow repository, a missing origin/<base> or no merge base between HEAD and origin/<base>, when publication starts without --check-description, then it exits with status 2 saying the leak scan is incomplete and nothing was pushed.
  4. AC4: Given the active gh account differs from the machine gh_login, when publication starts, then it refuses before any write and prints both logins; given no configured login, then the output says the account check is skipped, except in unattended mode where it refuses.
  5. AC5: Given the description checks run, when the draft has findings, then publication stops before property resolution, the stamp check and every other gate.
  6. AC6: Given draft labels, a milestone and issue or pull request references in the body, when properties are resolved, then a label GitHub lacks (matched exactly, from up to 200 labels) is refused by name; an empty, ~, null, "" or '' milestone requests none, a missing milestone is refused and more than 100 open milestones is refused; the distinct references are sorted as text, as the shell sorts them, and only the first 20 are looked up in total (a later reference causes no lookup and no second batch), a missing one among them is refused, and a failed lookup stops with the lookup's own exit status and the reference named; this runs after the description checks and before the stamp check.
  7. AC7: Given --check-description, when it runs, then only the description checks and property resolution run, no review or other gate runs, nothing is pushed or written beyond scratch copies, and it exits 0 when they pass.
  8. AC8: Given no review stamp, or a stamp whose draft, branch name, HEAD, base, base commit or merge base no longer matches (including a fetch that moved the base after the review), or a draft copy whose digest differs from the stamped digest, when publication checks the stamp, then it refuses, naming the review script to run again, and nothing is pushed.
  9. AC9: Given a clean committed tree and an unchanged cache key, when the gates run, then the cached description lint and test passes are used and each is printed as cached; --rerun-gates forces fresh runs; the publication-scoped leak scans and the publication-scoped lint always run fresh; and the independent review always runs.
  10. AC10: Given a failing scripted scan, lint or independent review, when publication runs, then it exits before the test gate and before any push.
  11. AC11: Given --confirmed, a session pre-approval or a delegation check, when confirmation resolves, then the first source that answers wins in that order and the output names it; given none, then the run exits 75 and writes nothing; given the stamp matches before the confirmation and not after, or the draft copy changed, then it refuses and writes nothing; given --dry-run, then confirmation is never consulted and nothing is pushed or written.
  12. AC12: Non-functional: no push and no GitHub write happens before every check above has passed.

Scope and non-goals

Scope: argument parsing, branch-state refusals, identity, the description check, property resolution, stamp verification, gates, confirmation and the hand-off to child 09's push and write.

Non-goal: the push plan, --dry-run push planning output, the push and the gh writes, which child 09 ports. Non-goal: the gate runner, its cache, the confirmation order and delegation, which #713 and #762 own. Non-goal: the GraphQL quota reader owned by #760. Non-goal: loosening any gate. Non-goal: switching the shell caller, which child 12 does.

Approach

Meet AC1 to AC12 with failing table-driven cases first, using the stubs the Bats suite uses (fake gh, checker, reviewer) in Go, and comparing messages and exit statuses with the shell's. The stamp, gate and confirmation behavior is consumed as delivered under #321 rather than reimplemented. Property resolution runs in this child, in the shell's order, because at origin/main its only caller is create-pr.sh; it is not a separate entry point.

Dependencies

Blocked by: #910, #911, #912, #916, #713 (gate runner and cache), #762 (confirmation and delegation), #760 (identity and rate-limit classification), #769 (stamps), #753 (protection of new Go enforcement paths).

Prerequisite: #321.

Size

M. One pull request. Estimated at 650 to 750 changed code lines with tests (about 270 shell lines of behavior). Property resolution (about 47 shell lines, AC6) is part of this count; if the count passes 750 while drafting, it is split into its own pull request as an earlier blocker of this one before this one is opened.

Verify plan

  • AC1, AC2, AC3: tables of unknown flags, branch states and repository shapes, checking message and exit status.
  • AC4: a test with a fake gh signed in as another account, with no configured login, and unattended.
  • AC5, AC7: tests that fail the description check and run --check-description, with a recording gate runner.
  • AC6: Go tests with a fake gh and call counts: unknown label, each milestone form, over 100 milestones, 25 distinct references (asserting exactly 20 lookups, the first 20 in sorted order, and none for the other 5), a missing reference, and a failing lookup (a rate-limit text for GraphQL, checking status and diagnostic).
  • AC8: tests that move HEAD, the branch, the draft, the base and the base commit between steps, and a stamp-less run.
  • AC9, AC10: tests with a recording gate runner and cache fixtures; tests/skills/pr/scripts/pr-workflow.bats publication-lint regression is the oracle for fresh scoped lint.
  • AC11: tests per source in order, the exit 75 case with no source, a stamp moved by the confirmation, and a dry run with a recording confirmation source.
  • AC12: an ordering test asserts the write stubs are untouched until the last check passes.
  • 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-by trailer and the pull request has the provenance:agent-assisted label. 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 final Status: comment names the merge commit.

Risks

A gate that passes in Go where the shell refused would publish unreviewed work, and an extra GitHub call per reference spends quota. The refusal cases and call counts above are the control. Undo: revert the change; nothing calls the Go gates yet and the shell script publishes as before.

Operator authority

None. The pr scripts are not on the owner-path list in .agents/agent-skills.conf; if the port touches lib.sh, agent.sh or a guard*.sh file, the pull request says so and states the owner review.

Activity

  1. tbhb-agent commented on Oct 27, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: READY — Check the gates and resolve confirmation before publishing from agentrepo pr
    Model: gpt-6-astra

    Child 08 Check the gates and resolve confirmation before publishing from agentrepo pr

    Verdict: READY

    Checked: Property ownership is settled. AC6 now correctly limits lookup to the first 20 text-sorted distinct references in total. Fresh publication lint, stamp checks, refusal boundaries and dry-run confirmation bypass remain covered. Evidence: packages/agents/source/skills/pr/shared/scripts/properties.sh:55, packages/agents/source/skills/pr/shared/scripts/create-pr.sh:189, packages/agents/source/skills/pr/shared/scripts/publish.sh:64.

    Gaps: None.

    Split: M is plausible at 650–750 changed code lines. The properties contingency activates before the hard limit.

    Definition of done

    The definition of done for this issue (Feature). Tick each item and give its evidence.

    • D1 The author verified each AC on the merged head, and the Verification section of the pull request cites each AC ID with its evidence: the command and its result, or a link.
    • D2 An independent reviewer approved the exact merged head, and the author resolved each finding or filed it as a follow-up.
    • D3 The required checks pass on that head, and any loosened gate has the owner's approval of that exact head.
    • D4 The leak scans come back clean: gitleaks, devtools' check-leaks.sh with the repository's private-strings list, and the leak review of each post.
    • D5 The author signed each commit, the squash included.
    • D6 The docs match the change (README, docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.
    • D7 The commits and the squash have Assisted-by trailers, and the pull request has the provenance:agent-assisted label.
    • D8 The pull request stays within the size limits, or the owner approved its exact head over the hard limit.
    • D9 The author files follow-ups and deferred findings as issues with at least a Problem and numbered AC and lists them under the Related section of the pull request. Any work left in the code links its issue.
    • D10 The merge closes the issue through a closing reference and the board shows Done. The final Status: comment names the merge commit.
    • devtools-1 mise run check is green, and so are the coverage floors mise run cover-go-check and mise run cover-py-check, which check doesn't run.
    • devtools-2 A change to skill sources under packages/agents/source/ commits what mise run generate-skills, then mise run skill-tokens, then apm install rewrite, in that order, and check-generated-skills (part of lint) passes.
    • devtools-3 A consumer-visible change (the vendored payload, a skill, a reusable workflow, a task or a pin) has its consumer steps in docs/agent-skills-migration.md or the adoption docs, or the PR's Verification says "No consumer impact" and why.

    Round: 3 of 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refinement:readyPassed the Definition of Ready; may be picked up

    Fields

    Priority

    None yet

    Work type

    None yet

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions