Skip to content

Run agent-pr unattended from agentrepo pr #919

Description

@tbhb-agent

Problem

The unattended agent-pr skill reaches into the sibling pr skill directory at run time: its four wrappers set DEVTOOLS_UNATTENDED=1 and exec the pr scripts, which then call pr-agent.sh and pr-checks.sh. Those hold the unattended rules: a clean tree, a committed regular-file template, a configured gh_login, a topic branch with commits, the lint_pr_cmd, pr_title_check_cmd, prose policy and owner_paths checks, an unchanged branch through publication, and the result report. The authority rules for unattended publication live in shell, and a deployment with only agent-pr installed cannot run.

Part of #588 and #323. Delivers in Go the behavior of packages/agents/source/skills/pr/shared/scripts/pr-agent.sh and check.sh, the unattended paths of the entry points they serve, and the report. This change adds Go behavior only and switches no caller.

Acceptance criteria

  1. AC1: Given a dirty tree, an interrupted operation, a detached HEAD, the base branch checked out, or no commits to publish, when unattended publication starts, then it refuses with the shell's message and writes nothing.
  2. AC2: Given the PR template is not a committed regular file, or gh_login is not configured on the machine, when unattended publication starts, then it refuses.
  3. AC3: Given --confirmed, when unattended publication is requested, then it is refused; given neither a session pre-approval nor a delegation grant, then it exits 75 without asking; each other entry point keeps its existing argument contract, so a flag an entry point forwards today is still forwarded and no new refusal is added.
  4. AC4: Given lint_pr_cmd is unset, set or empty, when the checks run, then the default mise run lint-pr-description runs, the configured command runs, or the run refuses, respectively; given pr_title_check_cmd, then it runs with the base, head and title available to it.
  5. AC5: Given pr_log_entry and pr_related_pattern configured, when the unattended checks run, then a draft that breaks the policy findings of child 01 is refused and one that satisfies them passes.
  6. AC6: Given owner_paths and a branch changing a matching path (including a deletion or a rename), when the delegation check is called, then it receives the restrictive --owner-path signal; given an invalid expression, then the run refuses.
  7. AC7: Given the persistent review rules of refactor(agents): port unattended review bounds and reporting to Go #770, when unattended publication runs, then an exhausted review bound refuses, a new subject starts a fresh round, a rejected draft is retained, and preflight preserves the bound.
  8. AC8: Given the branch changes between the checks and the publication, or the signed-in account or the draft changes after the push and before the write, when unattended publication runs, then it refuses with "review again" or the identity message and nothing is written to GitHub.
  9. AC9: Given a successful publication, when the report prints, then it names the number and URL, prints locally unless mail_cmd and mail_to configure a transport, records the result (number, URL, head, base, draft state, push kind) in the Git state directory, and clears the pr state; given an unreadable result, then it says to inspect GitHub before retrying.
  10. AC10: Given a mail failure, when the report is sent, then the unsent report is printed and publication is not repeated.
  11. AC11: Non-functional: unattended mode adds no authority source beyond session pre-approval and the machine delegation check.

Scope and non-goals

Scope: the unattended entry and checks, the prose-policy enforcement in unattended mode, the result record and report, and the check entry used by agent-pr, behind agentrepo pr with an unattended flag; the DEVTOOLS_UNATTENDED variable (with its DT_UNATTENDED alias) remains accepted as input.

Non-goal: the persistent review state and transport, which #770 owns; this child only requires its outcomes (AC7). Non-goal: the post-push recheck itself, which child 09 ports; this child verifies it end to end for unattended runs. Non-goal: changing delegation or pre-approval, which #762 owns. Non-goal: the wrapper cut-over of the pr and agent-pr skills, which children 12 and 13 do. Non-goal: unattended merge.

Approach

Meet AC1 to AC11 with failing table-driven cases first, using the stubs in tests/skills/agent-pr. Reuse the publication code from children 08 and 09 rather than a second path, and the policy check from child 01.

Dependencies

Blocked by: #915, #916, #917, #918, #762 (confirmation and delegation), #755 (context and harness), #770 (bounds and reporting), #753 (protection of new Go enforcement paths).

Prerequisite: #321.

Size

M. One pull request. Estimated under 600 changed code lines with tests.

Verify plan

  • AC1, AC2: table-driven refusal cases over scratch repositories.
  • AC3: tests for --confirmed, a grant, a refusal and no source, and for each entry point's forwarded arguments.
  • AC4, AC5, AC6: tests with repository configuration, draft fixtures and a recording checker.
  • AC7: tests that replay the refactor(agents): port unattended review bounds and reporting to Go #770 outcomes (exhausted bound, new subject, rejected draft, preflight with a bound) through the unattended entry.
  • AC8: tests that move the branch from inside a stub, switch the account after the push and change the draft; tests/skills/agent-pr/publish.bats and authority.bats cases are the oracle.
  • AC9, AC10: tests with a stub mail transport and a failing one, an unreadable result, and a read of the result record.
  • AC11: a test lists the sources consulted.
  • 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

Unattended publication writes without an operator, so any gate that loosens here is a silent authority change. The refusal cases are the control. Undo: revert the change; nothing calls the Go unattended mode yet and the shell wrappers behave as before.

Operator authority

None. The agent-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 — Run agent-pr unattended from agentrepo pr
    Model: gpt-6-astra

    Child 10 Run agent-pr unattended from agentrepo pr

    Verdict: READY

    Checked: Persistent bounds and reporting consume #770 without taking ownership of its implementation. Prose-policy enforcement, entry-specific argument behavior, post-push checks and unattended-only result recording have assigned verification. Evidence: packages/agents/source/skills/pr/shared/scripts/pr-agent.sh:45, packages/agents/source/skills/pr/shared/scripts/pr-agent.sh:86, packages/agents/source/skills/pr/shared/scripts/publish.sh:126.

    Gaps: None.

    Split: M is plausible for unattended integration.

    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