Repository navigation
Description
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
- 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. - AC2: Given the PR template is not a committed regular file, or
gh_loginis not configured on the machine, when unattended publication starts, then it refuses. - 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. - AC4: Given
lint_pr_cmdis unset, set or empty, when the checks run, then the defaultmise run lint-pr-descriptionruns, the configured command runs, or the run refuses, respectively; givenpr_title_check_cmd, then it runs with the base, head and title available to it. - AC5: Given
pr_log_entryandpr_related_patternconfigured, when the unattended checks run, then a draft that breaks the policy findings of child 01 is refused and one that satisfies them passes. - AC6: Given
owner_pathsand a branch changing a matching path (including a deletion or a rename), when the delegation check is called, then it receives the restrictive--owner-pathsignal; given an invalid expression, then the run refuses. - 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.
- 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.
- AC9: Given a successful publication, when the report prints, then it names the number and URL, prints locally unless
mail_cmdandmail_toconfigure 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. - AC10: Given a mail failure, when the report is sent, then the unsent report is printed and publication is not repeated.
- 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.batsandauthority.batscases 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-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
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.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 27, 2026
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.
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