team commits check

Checks a commit, or a range of commits, against the team file's rules: every commit must carry a seat's signature where the file says, and no line of its message may match a forbidden pattern. commits check is what a seat runs on its own branch before it reports, and what CI runs on every push. The request to merge is a separate run, team pr check, which checks a pull request's body alone and needs no git.

Synopsis

team commits check <ref> [--since <ref>] [--file <path>]

What it reads and writes

Reads the team file (or the one --file names), the ledger of this machine's store (every seat the team has had here, so a removed seat's commits still pass), and the git history of <ref>. It writes nothing: no state file, no log line, no store.

Who may run it

Anyone. It needs no herdr session, no terminal and no approval of its own; a seat runs it on its own branch and CI runs it on a push.

Flags

FlagMeaning
<ref>one commit, or a range when it holds .., passed to git as given (origin/main..HEAD)
--since <ref>skip this commit and everything reachable from it, for this run; overrides identity.since
--file <path>the team file, instead of .agents/team.yaml
--help, -hthe usage, and exit 0

What it finds

Every offending commit is printed with its hash and subject, then one block per finding:

<sha> Tidy the logs
  line 5: forbidden pattern ^Claude-Session:
    Claude-Session: 8f21c4a9
FindingMeaning
no signature: expected "Agent: {display} · {role}" in the final trailer blockthe message carries no signature at all
the signature is not in the final trailer blocka seat's signature is there, but not where the file's rule says
the signature shares its paragraph with prose ("…"), so git reads no trailer block: put it in a paragraph of its own, with trailers onlythe signature touches ordinary text, so git reads no trailer
a signature no seat of this team has had (the model, the version and the role must all match one seat)a signature-shaped line naming a model, version or role no seat has
forbidden pattern <source>the line matches one of the file's patterns, or one of the two defaults

The summary says what was read — <n> commits checked, <n> by a human or a merge, <n> skipped (since <ref>) — and then ok, or 1 commit refused, or 2 commits refused.

Refusals

MessageExit
team commits check: a <ref> is required (with the usage)2
team commits check: one <ref> at most (with the usage)2
team commits check: unknown option --<name> (with the usage)2
team commits check: --since needs a value (with the usage)2
team commits check: <path>, line <n>: <message>2
team commits check: not in a git repository2
team commits check: "<ref>" doesn't name a commit2
team commits check: the range "<ref>" can't be resolved2
team commits check: the range "<ref>" holds no commit2
team commits check: since "<ref>" doesn't name a commit here (a shallow clone doesn't hold the history it needs)2
team commits check: since "<ref>" is not reachable from "<ref>"2

The body's own refusals are team pr check's. The old spelling team check … still runs all of this, one notice line first: team check.

Exit codes

  • 0 — every commit checked passes.
  • 1 — at least one commit was refused.
  • 2 — the check can't run: a bad invocation, a team file that can't be read, a ref that names nothing.

Examples

.agents/team.yaml
format: 1
project: beacon
coordinator: claude-keeper
operator: claude-keeper

identity:
  humans: [[email protected]]

trust:
  - ~/.config/team/lobby
  - ~/Code/beacon

workspace:
  mode: shared

seats:
  - role: coordinator
    name: claude-keeper
    label: coordinator
    cli: claude-code
    vendor: anthropic
    model: Claude Opus
    version: "5.5"
    launch: claude --model claude-opus-5-5

  - role: implementer
    name: claude-beacon
    label: implementer
    cli: claude-code
    vendor: anthropic
    model: Claude Opus
    version: "5.5"
    launch: claude --model claude-opus-5-5

A seat signs its commits in a trailer block of its own:

the commit message
Sketch the layout

Agent: Claude Opus 5.5 · implementer

The person named in identity.humans never signs:

the commit message
Review the copy

This one forgot, and this one signed but leaked a line the file forbids:

the commit message
Add the metrics page

The counters come from the tracker's webhook, not from a poll.
the commit message
Tidy the logs

The reader printed one line too many, so the reports carried noise.

Claude-Session: 8f21c4a9
Agent: Claude Opus 5.5 · implementer

The commit a person wrote needs no signature:

Terminal
 team commits check HEAD~2 ; echo "exit $?"
team commits check: warning: line 3: `coordinator:` is now `leads: true` on the lead's seat, and is still read
team commits check: 1 commit checked, 1 by a human or a merge: ok
exit 0

The newest commit signs, but leaks the forbidden line:

Terminal
 team commits check HEAD ; echo "exit $?"
team commits check: warning: line 3: `coordinator:` is now `leads: true` on the lead's seat, and is still read
<sha> Tidy the logs
  line 5: forbidden pattern ^Claude-Session:
    Claude-Session: 8f21c4a9
team commits check: 1 commit checked: 1 commit refused
exit 1

A range reads newest first and reports every commit with findings:

Terminal
 team commits check HEAD~3..HEAD ; echo "exit $?"
team commits check: warning: line 3: `coordinator:` is now `leads: true` on the lead's seat, and is still read
<sha> Tidy the logs
  line 5: forbidden pattern ^Claude-Session:
    Claude-Session: 8f21c4a9
<sha> Add the metrics page
  no signature: expected "Agent: {display} · {role}" in the final trailer block
team commits check: 3 commits checked, 1 by a human or a merge: 2 commits refused
exit 1

--since leaves that commit and everything reachable from it out of the report:

Terminal
 team commits check HEAD~3..HEAD --since HEAD~1 ; echo "exit $?"
team commits check: warning: line 3: `coordinator:` is now `leads: true` on the lead's seat, and is still read
<sha> Tidy the logs
  line 5: forbidden pattern ^Claude-Session:
    Claude-Session: 8f21c4a9
team commits check: 1 commit checked, 2 skipped (since <sha>): 1 commit refused
exit 1

A ref that names nothing can't be checked:

Terminal
 team commits check origin/main ; echo "exit $?"
team commits check: warning: line 3: `coordinator:` is now `leads: true` on the lead's seat, and is still read
team commits check: "origin/main" doesn't name a commit
exit 2