diff --git a/.agents/skills/wave/agent-rules.md b/.agents/skills/wave/agent-rules.md index 59af1596..9bcc7934 100644 --- a/.agents/skills/wave/agent-rules.md +++ b/.agents/skills/wave/agent-rules.md @@ -221,8 +221,7 @@ out on purpose: (matching BEADS_ACTOR)" (2026-09-25; improvise-1xfb.3). Make every commit through the wrapper, merge commits included: `BEADS_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 + `merge`. 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 @@ -235,8 +234,12 @@ out on purpose: `context/test-evidence/tooling.md`. - A plain `git commit --amend` keeps the author it amends, so amend with plain git or with the wrapper. + - **A cherry-pick keeps its source's author**, through the wrapper or not: + git ignores `GIT_AUTHOR_NAME` there. That is right, because rule 8 allows + only `cherry-pick -x` of commits that keep whoever wrote them. - Before you push, check `git log --format='%an <%ae> | %cn' ..HEAD`. Every line must name your actor. + SHA>..HEAD`. Every commit **you made** must name your actor. A + cherry-picked commit, or one from a PR you stack on, keeps its own author. - **The format is a proposal.** `Claude ()` 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. diff --git a/context/test-evidence/tooling.md b/context/test-evidence/tooling.md index f6e10d8f..c6ea8088 100644 --- a/context/test-evidence/tooling.md +++ b/context/test-evidence/tooling.md @@ -1789,7 +1789,16 @@ commit reads `Claude (t) | Owner`. The same probe showed that a merge takes `GIT_AUTHOR_NAME` too, and that a plain `--amend` keeps the author it amends. -**Rivals.** +**A cherry-pick keeps its source's author** (Codex P2 and the review on PR +#310). The first version of the rule listed `cherry-pick` among the wrapper's +subcommands, but git ignores `GIT_AUTHOR_NAME` there. That is the behaviour +this repo wants, since rule 8 allows only `cherry-pick -x` of commits that keep +their own author. So the contract names only `commit` and `merge`. The case "a +cherry-pick keeps its source's author" picks a commit authored `Claude +(agent-b2)` with the wrapper set to `agent-a1`, and asserts `agent-b2`. A pick +that failed would leave the owner-authored base at HEAD and fail the case too. + +**Rivals** (run against the first eleven cases). - **`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 diff --git a/scripts/agent-git b/scripts/agent-git index 7ef84b2a..b87c1012 100755 --- a/scripts/agent-git +++ b/scripts/agent-git @@ -5,7 +5,7 @@ set -euo pipefail if [ -z "${BEADS_ACTOR:-}" ]; then echo 'agent-git: BEADS_ACTOR is unset; refusing to author as the owner' >&2 - echo 'usage: BEADS_ACTOR= scripts/agent-git commit|merge|cherry-pick ...' >&2 + echo 'usage: BEADS_ACTOR= scripts/agent-git commit|merge ...' >&2 exit 2 fi diff --git a/scripts/agent-git-test.sh b/scripts/agent-git-test.sh index 3e2ee6f7..12eb5951 100644 --- a/scripts/agent-git-test.sh +++ b/scripts/agent-git-test.sh @@ -50,6 +50,12 @@ BEADS_ACTOR=agent-a1 "$RUN" merge -q --no-edit side same "a merge commit is authored by the agent" 'Claude (agent-a1)' "$(git log -1 --format=%an)" same "the merge has two parents" 2 "$(git log -1 --format=%P | wc -w | tr -d ' ')" +# A cherry-pick keeps its source's author, whatever the wrapper sets. +git checkout -q -b pick "$base" +BEADS_ACTOR=agent-a1 "$RUN" cherry-pick -x --allow-empty "$(git rev-parse side)" > /dev/null 2>&1 +same "a cherry-pick keeps its source's author" 'Claude (agent-b2)' "$(git log -1 --format=%an)" +git checkout -q - + # git's own failure is passed through, not swallowed. BEADS_ACTOR=agent-a1 "$RUN" commit -q -m nothing-staged > /dev/null 2>&1 rc=$?