Repository navigation
Description
Problem
The unattended behavior of agent-commit (signing required, executable hooks required, repository lint command, bounded review rounds, held versus asked) is scattered through the shell and switched on by the DEVTOOLS_UNATTENDED environment variable (and the DT_UNATTENDED variable the shell also honors), which the wrappers set before running the sibling commit skill's scripts. Each rule widens an agent's authority if it slips, and the shell freeze in #588 rules out porting it ad hoc.
Part of #322, within #588. Child 06 in #322's Children list. Delivers in Go the unattended mode of agentrepo commit (--unattended), covering the behavior of the agent-commit scripts under packages/agents/source/skills/agent-commit/shared/scripts/ and packages/agents/source/lib/agent.sh.
Acceptance criteria
- AC1: Given
--unattended, whenagentrepo commitruns, then it never asks a question, and missing authority exits 75. - AC2: Given
--unattendedwith--confirmed, when the command runs, then it refuses and names pre-approval and delegation. - AC3: Given unattended mode, when the command commits, then it signs the commit, and a signing failure holds with exit 75, keeps the draft and index, and never falls back to an unsigned commit.
- AC4: Given unattended mode, when preflight or write runs, then missing signing and missing executable hooks each refuse or hold with the matching message; these two prerequisites are not added to the review entry point.
- AC5: Given unattended mode, when preflight, review or write runs, then an initial (root) commit is refused; a detached head is refused; a validated base merge is permitted; and any other interrupted operation is refused, at each of the three entry points.
- AC6: Given
lint_commit_cmdin repository configuration, when unattended mode runs, then that command is the commit-message gate and an empty value fails closed, and the full repository lint still runs. - AC7: Given repeated review findings on one staged tree, when the configured round bound is reached, then the command exits 3 without invoking the reviewer again; given a different tree, then the count restarts; given an unreadable review, then no round is spent; given a rejected draft, then the redesign lifecycle behaves as the shell does today; given a successful commit, then the counter clears.
- AC8: Given a hook that rewrites the message, the tree or the branch during an unattended commit, when verification runs, then it fails, the commit and review evidence stay, and the workflow does not move the branch.
- AC9: Given repository configuration with duplicate keys, a symlink or a machine-only key, when unattended mode runs, then it fails closed and never lets the repository choose the reviewer, delegation checker or identity.
- AC10: Given repository configuration that changes while the reviewer runs, when the review ends, then no stamp is written; given configuration changed after an existing stamp, when unattended mode reaches the write, then it refuses.
- AC11: Given
--unattended, or the environment without the flag, whenagentrepo commitruns during the compatibility window, then unattended mode is entered by the flag, or by the variables resolved as the shell resolves them:DEVTOOLS_UNATTENDEDis read first;DT_UNATTENDEDis read only whenDEVTOOLS_UNATTENDEDis unset (an emptyDEVTOOLS_UNATTENDEDdoes not fall back); and only the value1counts. The flag is the documented entry. - AC12: Non-functional: neither
DEVTOOLS_UNATTENDEDnorDT_UNATTENDED, nor any other internal unattended marker, is present in the environment of the repository's own gates or of any child process the command starts, whichever way unattended mode was entered.
Scope and non-goals
Scope: the --unattended mode across the agentrepo commit subcommands, with --unattended as the primary interface. Go keeps reading the environment variables through the N-2 compatibility window so that devtools bumps need zero configuration changes, with the shell's resolution at packages/agents/source/lib/lib.sh:34-36 (${DEVTOOLS_UNATTENDED-${DT_UNATTENDED:-0}}, then unexported): DEVTOOLS_UNATTENDED first, DT_UNATTENDED as the fallback only when the first is unset, only the value 1 counting, and neither variable passed to child processes.
Non-goal: agent-pr and agent-merge-pr, which keep their own areas. Non-goal: changing the delegation or pre-approval contracts. Non-goal: implementing the shared policy, round and signing mechanics, which #321 delivers; this child integrates them and tests the unattended outcomes. Non-goal: switching any shell wrapper, which child 07 handles. Non-goal: removing the environment reads, which happens after the N-2 window in the same final cleanup issue under #588 that deletes the shell; that cleanup removes both DEVTOOLS_UNATTENDED and DT_UNATTENDED.
Approach
Meet AC1 to AC12 with failing cases first, porting the agent-commit Bats suites' cases. The flag is the primary entry; the variable read exists only for compatibility and is covered by its own precedence and isolation cases.
Dependencies
Prerequisites: the unattended policy, bounded review rounds and signing deliverables of #321.
Size
M. One pull request.
Verify plan
- AC1, AC2: ported cases from
tests/skills/agent-commit/workflow.batswith no-authority, grant and refusal stubs. - AC3, AC8: tests with failing signing and hooks that mutate message, tree or branch (including a hook that moves the branch, as
workflow.batsdoes). - AC4: tests with missing signing and missing hooks at preflight and write, and a test that the review entry point does not check them.
- AC5: ported cases from
tests/skills/agent-commit/workflow.batsand the base-merge permit and refusal cases fromtests/skills/agent-commit/base-merge.bats, run at preflight, review and write. - AC6, AC9: configuration fixtures including duplicates and a symlink.
- AC7: tests over three rounds, tree changes, unreadable reviews, a rejected draft and a successful commit.
- AC10: tests with a stub reviewer that edits the repository configuration while it runs (no stamp), and a test that edits it after an existing stamp (write refused).
- AC11: parity checks that run the shell and Go on the same environments and compare the outcome: the flag alone;
DEVTOOLS_UNATTENDED=1alone;DT_UNATTENDED=1alone; both set with different values (each ordering of 1 and 0);DEVTOOLS_UNATTENDEDset to the empty string withDT_UNATTENDED=1(no fallback, so not unattended); and values other than1, which do not enter the mode. - AC12: a test shows the gate environment and a child process each lack both variables for each way of entering the mode, including a child process started with neither variable set that inherits neither.
- 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
This is the path that commits without a person present, so any slip in AC1 to AC3 widens an agent's authority. The refusal cases are the control. Undo: revert the change; no caller uses the mode until child 07.
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 — Run agent-commit unattended without the commit skill beside it
Model: gpt-6-astra
Child 06 Run agent-commit unattended without the commit skill beside it
Verdict: READY
Checked: The environment amendment matches
packages/agents/source/lib/lib.sh:35:DEVTOOLS_UNATTENDEDtakes precedence even when empty, andDT_UNATTENDEDsupplies the fallback only when the primary variable is unset. Mode checks require the literal value1, for example atpackages/agents/source/skills/commit/shared/scripts/commit.sh:81. Both variables are unexported atpackages/agents/source/lib/lib.sh:36. AC11 and AC12 explicitly assign precedence and isolation checks.The prior findings remain closed:
packages/agents/source/lib/lib.sh:567.packages/agents/source/lib/lib.sh:615andpackages/agents/source/lib/lib.sh:695.packages/agents/source/lib/agent.sh:93andpackages/agents/source/lib/lib.sh:715.tests/skills/agent-commit/workflow.bats:261.Every AC has an assigned check. Shared mechanics remain #321’s responsibility, wrapper switching remains separately owned, and compatibility removal remains outside this child. Scope, dependencies, risks, undo and operator authority are consistent. No implementation layout is prescribed.
Gaps: None.
Split: None. M remains credible with shared policy, rounds and signing supplied by #321.
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: 1 of 3