docs(agents): agents author their commits as Claude (<BEADS_ACTOR>) (improvise-1xfb.3)
The rule sits beside the claim in agent-rules.md, and the brief checklist in wave/SKILL.md ties the actor to it. The evidence entry records why the wrapper sets GIT_AUTHOR_NAME and not user.name, and its two rivals. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
committed by
Edward Langley
parent
eff92f3e3c
commit
256057b7f8
@@ -52,7 +52,10 @@ nobody corrects. The brief adds only what varies per wave:
|
||||
suite, which it is not. The agent still measures its own.
|
||||
3. **Its ground, and the ground that is not.** Name any orchestrator-only file
|
||||
it is exceptionally allowed to edit.
|
||||
4. **Its `BEADS_ACTOR` and its tickets.**
|
||||
4. **Its `BEADS_ACTOR` and its tickets.** The actor also names the agent's
|
||||
commits: it commits through `scripts/agent-git`, which authors each one as
|
||||
`Claude (<BEADS_ACTOR>)` (`agent-rules.md`, "Discipline per ticket"). So
|
||||
give each agent its own actor, and do not tell it to set `user.name`.
|
||||
5. **The attribution line, commit trailers and PR footer**, spelled out.
|
||||
They name the agent (Claude's line opens `_Posted by Claude (<model>)…_`)
|
||||
and this session's URL, which is why the shared `agent-rules.md` cannot
|
||||
|
||||
@@ -216,6 +216,30 @@ out on purpose:
|
||||
- **Claim first:** `export BEADS_ACTOR=<your actor>` in every shell, then
|
||||
`bd update <id> --claim`. Exit 13 means another actor holds it. Pick another;
|
||||
do not retry.
|
||||
- **Author every commit as `Claude (<BEADS_ACTOR>)`.** The user: "agents
|
||||
should override git author name, I think to include an agent identifier
|
||||
(matching BEADS_ACTOR)" (2026-09-25; improvise-1xfb.3). Make every commit
|
||||
through the wrapper, merge commits included:
|
||||
`BEADS_ACTOR=<your actor> scripts/agent-git commit …`, and the same for
|
||||
`merge` or `cherry-pick`. The wrapper sets the author name for that one
|
||||
command, and it refuses (exit 2) when `BEADS_ACTOR` is unset or empty. It
|
||||
reads `BEADS_ACTOR` from its own environment, so the prefix works in a shell
|
||||
that keeps nothing between commands.
|
||||
- **The author email, the committer and the `Co-Authored-By` trailer stay as
|
||||
they are.** The email is the owner's configured one, so GitHub still links
|
||||
the commit.
|
||||
- **Never set `user.name` with `git config`.** Worktrees share
|
||||
`.git/config`, so it renames every agent at once. Do not use
|
||||
`git -c user.name=…` either: `user.name` names the committer as well as
|
||||
the author. Why the wrapper uses `GIT_AUTHOR_NAME`:
|
||||
`context/test-evidence/tooling.md`.
|
||||
- A plain `git commit --amend` keeps the author it amends, so amend with
|
||||
plain git or with the wrapper.
|
||||
- Before you push, check `git log --format='%an <%ae> | %cn' <pinned
|
||||
SHA>..HEAD`. Every line must name your actor.
|
||||
- **The format is a proposal.** `Claude (<BEADS_ACTOR>)` is the default
|
||||
proposed on improvise-1xfb.3's PR. The user may change it there. The format
|
||||
lives in `scripts/agent-git` and nowhere else.
|
||||
- **`bd` needs `.envrc` allowed in your worktree.** Without it you get a
|
||||
**version mismatch**, not a clean failure. Run `direnv allow` in the worktree,
|
||||
or rely on the `[whitelist] prefix` in `~/.config/direnv/direnv.toml`.
|
||||
|
||||
@@ -1772,3 +1772,33 @@ The output includes the user's inline answers on
|
||||
**Scope sweep.** `scripts/pr-watch` passes its JSON through `printf '%s' | jq`,
|
||||
never as an argument. `grep -rn 'argjson\|--arg '` over `scripts/`,
|
||||
`.agents/` and `.claude/skills/` finds no other data argument.
|
||||
|
||||
### An agent authors its commits, and the committer is left alone — `scripts/agent-git-test.sh` (improvise-1xfb.3)
|
||||
|
||||
**What was missing.** Every agent commit was authored as the repository owner,
|
||||
so history could not say which agent wrote what. `scripts/agent-git` runs one
|
||||
git command with `GIT_AUTHOR_NAME="Claude ($BEADS_ACTOR)"` and refuses, exit 2,
|
||||
when `BEADS_ACTOR` is unset or empty.
|
||||
|
||||
**Why not `git -c user.name=…`,** the mechanism the ticket and the brief both
|
||||
offered first. `user.name` is the default for the committer as well as the
|
||||
author, so it renames both. The ticket asks for the committer to be left
|
||||
alone. Probed in a scratch repo: a `-c user.name` commit reads
|
||||
`Claude (u) <o@x> | Claude (u)` as author and committer. A `GIT_AUTHOR_NAME`
|
||||
commit reads `Claude (t) <o@x> | Owner`. The same probe showed that a merge
|
||||
takes `GIT_AUTHOR_NAME` too, and that a plain `--amend` keeps the author it
|
||||
amends.
|
||||
|
||||
**Rivals.**
|
||||
- **`exec git -c user.name="Claude ($BEADS_ACTOR)" "$@"`**: 10 passed,
|
||||
1 failed, "the committer is untouched" (got `Claude (agent-a1)`).
|
||||
- **The refusal removed** (`if false`): 7 passed, 4 failed. They are "an unset
|
||||
BEADS_ACTOR is refused" (exit 1 from `set -u`, not 2), "the refusal names
|
||||
BEADS_ACTOR", "an empty BEADS_ACTOR is refused" (exit 0: the commit landed
|
||||
under the name `Claude ()`), and "a refusal commits nothing". So `set -u`
|
||||
alone would not cover the empty case.
|
||||
|
||||
**Fixture.** The repo's identity comes from its own config, with
|
||||
`GIT_CONFIG_GLOBAL=/dev/null` and `GIT_CONFIG_NOSYSTEM=1`, and every `GIT_*`
|
||||
identity variable is unset first. So a caller's own identity cannot make the
|
||||
author or committer assertions agree by accident.
|
||||
|
||||
Reference in New Issue
Block a user