Skip to content

feat(commit): let an agent author stand in for its co-author #402

Closed

Description

@AbysmalBiscuit

A project can require each agent commit to name its agent in a Co-authored-by trailer (required = "agents" on the coauthors variable). Some callers make the agent harness the commit's git author instead, for work that no person asked for. The author line already names the agent, so a trailer repeats it. Today devkit commit refuses that commit: devkit commit needs --coauthor=... (required for agents).

Make a commit whose git author is the agent satisfy a co-author requirement for agents. A commit with a person as the author still needs --coauthor as today. The other agent-only requirements, such as proof and done_when, stay as they are.

Done when

  • An agent caller whose git author is set to the agent (GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL or user.name/user.email) runs devkit commit without --coauthor in a project with coauthors required for agents, and the commit succeeds with no Co-authored-by trailer (proof: test)
  • An agent caller whose git author is a person still gets the --coauthor refusal (proof: test)
  • The docs for template variables say how an agent author meets a co-author requirement (proof: diff)

Stop and ask if

  • Recognizing an agent author needs a new config key: ask before adding it.

Context

Blocked by: none

  • Found by AbysmalBiscuit/workcell#268, whose runs can make the harness the commit author. That ticket waits on this one.
  • Decide how devkit recognizes an agent author (for example a known agent identity list, or the caller's own declared identity) and say which in the PR.

Activity

  1. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    Workcell progress

    • stage 1: implementing. An agent author satisfies a co-author requirement for agents. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • stage 2: review roles deferred until midnight UTC (box Claude quota spent). Implementer commit 5fb255e. Opening the PR with local checks next. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • PR feat(commit): let an agent author stand #412 open at 5fb255e. Report posted. Reviews deferred to senior until midnight UTC. Waiting on issue 402. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • ask-1: 2026-10-17T21:55:23.148569Z Question for senior: stage 2 cannot end, and review roles cannot start until midnight UTC. Posted on issue 402. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052. tracker feat(commit): let an agent author stand in for its co-author #402 (comment)
    • ask-1 answered: hold at stage 2. Senior reviews PR feat(commit): let an agent author stand #412 at 5fb255e on the laptop. No push until the rows land on issue 402. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • stage 2: still holding for the laptop review of PR feat(commit): let an agent author stand #412 at 5fb255e. Next round runs review roles as herdr Codex workers. No push meanwhile. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • stage 5: round 1 of 3. Laptop review of PR feat(commit): let an agent author stand #412 at 5fb255e has 4 majors, 2 minors, 1 nit. Receiving those rows, then fixing them. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • stage 5: round 2 of 3. Head c4a07b8 fixes the round 1 rows. Starting Codex code-reviewer and verifier. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • stage 5: round 3 of 5. Head fe98aa7 keeps required=always. Starting Codex code-reviewer and verifier. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
    • final report: review stop reached. PR feat(commit): let an agent author stand #412 at fe98aa7. One held row, the PR body, already rewritten. Not merged. Session 01a14bcd-7bc3-7661-a2da-ca49c55f3052.
  2. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    #412 #412
    Head: 5fb255e
    Reviews: deferred to senior (box Claude quota spent)

    Local checks on that head:

    • cargo nextest run --workspace --all-features --locked --no-fail-fast: exit 100. 4283 tests, 4281 passed, 2 failed. Failures, same panic on origin/main at e3ffce0:
      • devkit::issue_create without_a_kind_only_the_detected_trackers_table_is_checked at tests/issue_create.rs:691: [ticket.fields.linear.team] has no type and where.
      • devkit::ticket_fields both_tables_without_a_kind_use_the_detected_trackers at tests/ticket_fields.rs:40: the same error.
        The branch does not touch those files. Confirm them on the laptop.
    • cargo test --workspace --doc: exit 0.
    • cargo clippy --workspace --all-targets -- -D warnings: exit 0.
    • devrun task fmt-check: skipped. This box has no nightly toolchain.

    No review role ran. It is 21:51 UTC, before midnight. Code review and verification are yours on the laptop. Post the rows on this issue. I will receive them as the reviewers' findings.

    The PR is ready, not a draft. I will not merge it.

    Rule: an agent author is the commit author devkit commit would record, and that email is a GitHub bot address (<digits>+<name>[bot]@users.noreply.github.com). GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL win when both are set. Otherwise user.name and user.email. That address is the caller's own declared identity, the form a harness uses when it authors the commit. No new config key and no identity list. A person address, a blank half, a human caller, and a project's own commit_message still need --coauthor. proof and done_when are unchanged.

    Commit: 5fb255e feat(commit): let an agent author stand. Rebased onto origin/main (already current) and published. No force-push. No herdr test panes left open.

    Session: 01a14bcd-7bc3-7661-a2da-ca49c55f3052

  3. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    Question for senior: stage 2 cannot end, and review roles cannot start until midnight UTC.

    The stop hook refuses to end this turn while the run is at gate_work. It is 21:55 UTC. Your extra instructions say not to start code-reviewer, verifier, receiver or pr-reviewer until midnight UTC, then only as Claude opus workers.

    PR #412 is open and ready: #412
    Head: 5fb255e
    Report: #402 (comment)

    How should I hold stage 2 until you post the review rows, or until midnight UTC?

    Stage asked: gate_work

  4. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    Senior answer to ask 402-1: the question is the open ask, so stop at gate_work and wait. Round 1 review of PR #412 at 5fb255e is running on the laptop, with nightly fmt and the full nextest run. I post the rows here when done.

  5. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    Senior review, PR #412 round 1 at 5fb255e (Codex reviewer, laptop). Verdict: FIX. 4 majors, 2 minors, 1 nit. Repro script and logs: ~/senior-files/devkit-402/ (revdk412-r1-*). The 207 nextest failures also fail on main in the reviewer's environment; none are PR-only.

    Senior decision on row 6: make it in scope. Recognize an agent author by the GitHub bot form plus a built-in list of the harness identities workcell uses: Claude noreply@anthropic.com and Codex noreply@openai.com. Use no new config key. Parse the bot form strictly (row 5). Add entry-point tests for Grok, Claude and Codex authors.

    PR #412 at 5fb255e95ee7a598f1e07a54f910287b96f6ff17 needs changes. This review found four major defects, two minor defects, and one formatting nit.

    The contract is issue #402, its comments, and the supplied review brief. Workcell #268 supplies the downstream requirements.

    Run python3 /tmp/revdk412-r1-cases.py /tmp/revdk412-r1-devkit to reproduce the runtime findings. The script uses disposable repositories and the saved PR binary. The recorded results contain each exit result, recorded author, and commit message. The Claude and Codex expectations describe downstream coverage beyond the chosen GitHub bot rule.

    # file:line severity finding evidence suggested fix
    1 crates/devkit-ports/src/templates.rs:236 major Amendment checks the prospective author, although Git retains the existing commit's author. This bypasses the requirement for a person author. Case amend person commit with bot environment succeeds without a trailer. The recorded author remains Prior person <person@example.invalid>. The reverse case refuses an amendment whose retained author is the bot. Resolve the retained author for --amend before rendering. Pass the commit selection into that decision. Test both amendment cases through devkit commit.
    2 crates/devkit-git/src/backend.rs:371 major Reading only user.name and user.email misses Git's author.name and author.email overrides. A person author can pass the bot exemption. Case author.email overrides bot user.email clears both author environment variables. It configures bot user.email and person author.email. The commit succeeds without a trailer and records Person <person@example.invalid>. The reverse configuration wrongly refuses the bot. Resolve the effective Git author, including author.*, before granting the exemption. Preserve the intended refusal for incomplete environment identities explicitly. Add both override cases.
    3 crates/devkit-ports/src/templates.rs:214 major The exemption bypasses a project's custom commit template. The condition checks [templates].commit_message but misses [templates.custom.commit_message], which takes precedence. Case custom template override declares a custom template that reads coauthors, with coauthors required for agents. The bot commit succeeds without --coauthor. The recorded message contains only fix: example. This contradicts the documented custom-template exception. Check the resolved template and both override forms. Apply the exemption only to the unchanged built-in template. Add a custom-template refusal test.
    4 crates/devkit-ports/src/templates.rs:260 major Removing trailers from the complete rendered message deletes caller-supplied body text. The filter removes matching lines anywhere in the body. Case retain supplied body supplies Before\n\nCo-authored-by: Ada <ada@example.invalid>\n\nAfter. The recorded body contains only Before\n\nAfter. The supplied line is an interior body line, followed by another paragraph. Satisfy the requirement without inserting a synthetic co-author into the rendered message. Suppress only the generated trailer. Test exact preservation of the supplied body.
    5 crates/devkit-ports/src/templates.rs:252 minor The classifier accepts more than the stated <digits>+<name>[bot]@users.noreply.github.com form. Substring matching accepts absent numeric IDs and a marker inside a name. Cases no digits, nonnumeric id, marker in middle, and empty name all succeed without trailers. Examples include grok[bot]@users.noreply.github.com and 123+grok[bot]human@users.noreply.github.com. Parse the numeric prefix, separator, nonempty name, terminal [bot], and domain. Keep explicit tests for accepted case normalization and surrounding spaces.
    6 crates/devkit-ports/src/templates.rs:252 minor The chosen rule leaves the Claude and Codex authors unsupported. Workcell's harness-author requirement therefore remains incomplete. Cases Claude author and Codex author both receive the exact agent --coauthor refusal. Their emails are noreply@anthropic.com and noreply@openai.com. Grok's specified bot address succeeds. These identities also appear in this checkout's coauthors description. Define support for the harness identities workcell uses and add entry-point tests. The issue permits an identity-list decision. If recognition needs a new config key, stop and ask before adding it, as the issue requires.
    7 crates/devkit-vcs/src/lib.rs:292; tests/commit.rs:282 nit The required nightly formatting check fails on both changed files. The formatting log shows the doc-comment wrap and assertion rewrite. The command exits 1. Apply nightly rustfmt to the changed files and run the formatting check again.

    The first Done when item passes for Grok through both complete GIT_AUTHOR_* values and user.* configuration. Both commits omit the trailer. Claude and Codex remain the minor design gap above. The second item passes for ordinary person identities, but findings 1 and 2 expose bypasses. The third item has documentation changes. Findings 3 and 5 identify behavior that contradicts those descriptions.

    The adversarial script ran 30 cases through devkit commit. Incomplete author environment pairs and a person environment identity over bot user.* configuration retain the exact agent refusal. Missing [bot] and another domain also retain that refusal. Uppercase domains, surrounding spaces, and a + inside the name succeed. Uppercase [BOT] does not succeed. A human caller with an agents-only requirement succeeds as before. A human caller with an always-required co-author still receives a refusal. The CLI has no --author option. An explicit --coauthor keeps its trailer. A project override under [templates].commit_message still refuses the omitted co-author.

    The script also confirms that a template reading proof and done_when still refuses both missing agent requirements. The changed code does not alter their requirement checks. The new VersionControl::author method has one production call site, in the commit-template logic. Existing user_email callers retain their implementation. The new integration tests use the real CLI, temporary directories, and per-process environment changes. Source inspection found no new Windows-specific dependency; this review ran on Linux.

    The required checks used the prescribed isolated HOME, TMPDIR, Cargo homes, and shared target directory. Commands used --manifest-path from /tmp. The local hook required the task wrapper, but that wrapper refused the repository-free export. The checks then used Cargo directly with the explicit manifest.

    Check Result Evidence
    cargo +nightly fmt --all -- --check Failed, exit 1. Formatting log.
    cargo clippy --workspace --all-targets -- -D warnings Passed, exit 0, with RUSTC_WRAPPER empty. Successful log. The first invocation failed in the global zccache wrapper with multiple input filenames provided. Initial log.
    cargo nextest run --workspace --all-features --locked --no-fail-fast Failed, exit 100. PR: 4,283 tests, 4,076 passed, 207 failed. All 26 commit integration tests passed. PR log.
    cargo test --workspace --doc Passed, exit 0. All 42 doctests passed. Doctest log.
    Full nextest suite on origin/main at e3ffce0a383d5e21f3b82309eb90b653b0b214f3 Failed, exit 100. Main: 4,276 tests, 4,069 passed, the same 207 failures. No PR-only failures. Main log, comparison, every failing test.

    Both manager-reported failures reproduce on the actual main export: issue_create without_a_kind_only_the_detected_trackers_table_is_checked and ticket_fields both_tables_without_a_kind_use_the_detected_trackers. The other 205 failures also reproduce on main. The linked failure table names each one.

    The prescribed TMPDIR lies below the exported devkit.toml. Configuration-discovery tests inherit that file. For example, resolve_errors_when_no_config_found resolves the export's project config, and a_checkout_with_no_config_stays_silent prints its tasks. This explains additional environment-related failures without assigning them to this PR.

    The first main attempt reused PR artifacts from the shared target. Its test list included PR-only tests. The review discarded that comparison, refreshed source timestamps in the main export, and rebuilt with the compiler wrapper disabled. The valid main run contains the expected 4,276 tests and no PR-only commit tests.

    The review removed the isolated exports. The shared target directory, saved PR binary, reproduction scripts, and logs remain available.

    VERDICT: FIX

  6. AbysmalBiscuit commented on Oct 17, 2026

    @AbysmalBiscuit
    OwnerAuthor

    #412 #412
    Head: fe98aa7
    Reviews: code-reviewer Codex (code-reviewer-00cf), verifier Codex (verifier-1057). No pr-reviewer: the repo lists no review skill. Receiver not spawned: the only finding was dropped.

    Local checks on that head:

    • cargo nextest run --workspace --all-features --locked --no-fail-fast: exit 100. 4309 tests, 4307 passed, 2 failed. Same two as origin/main at e3ffce0: devkit::issue_create without_a_kind_only_the_detected_trackers_table_is_checked, devkit::ticket_fields both_tables_without_a_kind_use_the_detected_trackers.
    • cargo test --workspace --doc: exit 0.
    • cargo clippy --workspace --all-targets -- -D warnings: exit 0.
    • devrun task fmt-check: skipped. This box has no nightly toolchain.

    Round 1 was the laptop Codex review of 5fb255e. All 7 rows applied in c4a07b8. Round 2 Codex review of c4a07b8 found that the exemption also covered required = "always". Fixed in 4e18b6d. Author lookup docs landed in fe98aa7.

    Round 3 found one low finding, the stale PR body. check_review.py dropped it because it cites no file. I rewrote the PR body from the pr_body template so it names the strict bot form, Claude noreply@anthropic.com, Codex noreply@openai.com, author.* before user.*, and the required = "agents" limit.

    Verifier: all 3 Done when items verified. 52 commit tests passed.

    I will not merge. Laptop CI, Windows, and the merge stay with you.

    Session: 01a14bcd-7bc3-7661-a2da-ca49c55f3052

  7. AbysmalBiscuit commented on Oct 18, 2026

    @AbysmalBiscuit
    OwnerAuthor

    Senior handover: a local senior session is taking over PR #412. It will rebase #412 onto main after #417 merges, run the gate, and merge it. Please make no further pushes to the branch.

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

Metadata

Metadata

Labels

area:commandShell-command analyzer (devkit-command)enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions