Topic 04

History an Agent Wrote

Git

An agent writes commit messages that say what changed, "Update refund window and tests", which the diff already says. A message is for why: the business decision, the rule, the choice made at the boundary. History that a reviewer, a search through history and a future reader can follow is something you shape before the branch is shared.

This matters more with an agent than without one, for two reasons. The agent cannot know where a decision came from unless you told it, so its messages are accurate and empty. And the history you leave is part of the context the next agent will read.

What the Message Is For

The diff answers what changed. The message answers why, in the facts no reader can get from the diff: "Refund window 24 hours to 12, an operations decision. A cancellation exactly 12 hours ahead is refunded. The deadline is computed in the gym's local time." Three facts, each one a decision someone made, none of them visible in a changed constant or a comparison.

The subject line and the body do different jobs. The subject is what a reader scanning the log sees, so it names the change in a few words: "Shorten the full-refund window to 12 hours". The body is what a reader who stopped on this commit needs: the decision behind it, the boundary it settled, and why any existing test changed. Git for Beginners covers the form; this page is about what an agent leaves out of it.

Two messages for the same diff
What the agent draftedaccurate, and says nothing new
"Update refund window and tests. All tests pass." The diff already shows the update, and "all tests pass" is a claim about one run on one machine.
What the message should carrythe decisions
Who decided, and when the rule applies. That exactly 12 hours is refunded, by ruling. That the deadline is local time. Why two existing tests changed.

Drafts, Not Final

Let the agent draft the message from the diff and the task, then correct it. It is good at summarising what changed and at finding the files a change touched. Then check every claim in the draft. "All tests pass" is a claim about one run, on one machine, possibly a targeted one. "No behaviour change" is a claim Chapter 7 taught you to doubt, because the agent says it about refactors that changed a rounding rule.

The fastest way to correct a draft is to give the agent what it was missing. Tell it where the decision came from and which boundary was ruled on, and ask it to redraft the body around those facts. It is good at prose once it has the facts; what it cannot do is invent the operations decision or Ines's ruling, and a draft that seems to state them anyway has guessed. Read the redraft for that, too.

Shaping the Branch

The commit-before-every-request rhythm leaves a branch full of working commits. Before the pull request, each step's working commits become one meaningful commit, so the branch reads as the plan from Chapter 5: the tests, the shared value, the rule change. On your own branch that is done with an interactive rebase or a squash. On a shared branch it is never done, because rewriting shared history breaks everyone who has it.

Nine working commits for step three on your own branch, before it is shared
$ git log --oneline main..
f1da43f (HEAD -> refund-window-12h) wip: email wording
d90f598 wip: tidy test helper
a83b467 wip: note the inclusive boundary
dab97d9 wip: schedule page
6353823 wip: email
bc9c212 wip: second-zone line back to 21:00
7ce62b0 wip: 23-hour case now refunds
415a3ba wip: before deadline attempt 2
18b0ce6 wip: boundary tests, failing
2941125 Use one refund window for refunds and the cancellation screen
a4cdd33 Pin the 24-hour refund rule an hour either side of the line
After squashing step three (git reset --soft HEAD~9, then two commits)
$ git log --oneline main..
ad3ceeb (HEAD -> refund-window-12h) Shorten the full-refund window to 12 hours
b92efa0 Fix a typo in a schedule comment
2941125 Use one refund window for refunds and the cancellation screen
a4cdd33 Pin the 24-hour refund rule an hour either side of the line

Squashing loses the noise and keeps the decisions, because the decisions go into the message you write for each squashed commit. Nine "wip" lines told a reviewer nothing. One commit for the rule change, with its tests, the email and the schedule page, tells them what changed and why. The agent's typo fix came out as a commit of its own, ready to move to its own branch.

The order is part of the message. Tests first, then the shared value, then the rule change: a reviewer reading commit by commit sees the specification before the code that meets it, which is the reading order of Chapter 6 built into the history. A search through history that lands on the rule change finds one behaviour change with its reason attached, not a session's worth of attempts.

The rule change, with its why and a trailer added by git commit --trailer
$ git log -1 --format=%B HEAD
Shorten the full-refund window to 12 hours

Operations decision: the 12 hours apply to every cancellation from the
day this ships, whatever the booking date.

A cancellation exactly 12 hours ahead is refunded ("up to 12 hours"
includes the twelfth, Ines's ruling). The deadline is computed in the
gym's local time. The 23-hour test now expects a refund because the
rule changed; the second-zone line moves from 09:00 to 21:00 for the
same reason and no other. The cancellation email and the schedule
page now say 12 hours.

Assisted-by: coding agent

$ git log -1 --format=%B HEAD | git interpret-trailers --parse
Assisted-by: coding agent

Attribution

Whether and how AI assistance is recorded in history is a team or project decision, and Chapter 13 covers writing that policy down. The mechanism is a trailer: a line of the form "key, colon, value" at the end of the message, which git can add when committing and parse back out afterwards, as the example above shows.

As of 2026 projects are still settling what they want, and their rules move. The Linux kernel's documentation on AI coding assistants asked for an "Assisted-by" tag on such contributions, and in October 2026 its maintainers agreed to drop it: too few contributors added the tag for its absence to mean anything, and they would rather read how the tools were used in the patch's cover letter. The rule that stayed is the one on sign-off: "AI agents MUST NOT add Signed-off-by tags", because "only humans can legally certify" the Developer Certificate of Origin that the sign-off represents. So follow your project's current policy, not a recollection of it. And check what your own tool adds to a commit by default before the first one ships.

The Author Is Still You

The commit's author is the person accountable for it, the contract Chapter 2 set out. An attribution trailer records how the change was made; it does not move who answers for it. The kernel's rule puts it plainly: the human who submits the contribution is responsible for reviewing it and for "taking full responsibility for the contribution". The same holds at Cragmoor with no rule written down.

History for the Next Agent

Messages that record decisions become context. An agent asked to work on refunds can read the log, the way Chapter 4 taught you to point it at evidence. "A cancellation exactly 12 hours ahead is refunded, by decision" in the history is what stops the next agent from "correcting" the inclusive boundary to the strict one it has seen everywhere else, the quiet change of Chapter 7. A message that only said "update refund window" protects nothing.

It works in practice because agents read history when they are pointed at it. "Before changing anything in refunds, read the log for that module" is a sentence in Cragmoor's project instructions file now. With good messages, that instruction brings the decisions into the context at the start of every refund task. With messages like "wip" and "fix tests", it brings in noise.

Misconceptions
  • "The diff speaks for itself." It says what changed. The decision that exactly 12 hours is refunded is not in the diff in any readable form.
  • "Agent-written messages are fine as they are." They describe the diff accurately and the decision not at all, and they repeat claims, "tests pass", that nobody checked again.
  • "Squashing loses information." It loses the working noise. The decisions go into the message you write for the squashed commit.
  • "An attribution trailer moves responsibility to the tool." The human author and sign-off carry it, and the kernel's policy says so explicitly.
  • "History is only for blame." It is the record a search through history walks, as in Chapter 10, and the context the next agent reads.
Why It Matters
  • Write the why in every commit message: the decision, where it came from, and any boundary choice.
  • Check every factual claim in an agent-drafted message before committing it.
  • Squash working commits into reviewable steps before sharing the branch, and never rewrite it after.
  • Follow the team's attribution policy with a trailer, and keep the author a person.

Knowledge Check

What must the refund change's commit message carry that the diff cannot show?

  • The names of all the files that the change touched in the repository
  • How many lines were added and removed in each file that it changed
  • That operations decided it, and that exactly 12 hours is refunded
  • That the refund window constant now has the value of 12 hours in it

The agent's draft message says "No behaviour change. All tests pass." What should you do with those two claims?

  • Keep them, since the agent wrote them right after doing the work
  • Check both against a fresh full run and the diff, or delete them
  • Shorten them to "No change" so that the message stays brief
  • Move them into a trailer at the end of the message instead

Your branch has nine working commits. When should you squash them into one?

  • After the pull request merges, so that the main line looks clean
  • After every request, so that the branch never has working commits
  • Before the branch is shared, while it is still only on your machine
  • Whenever a reviewer asks for it, even after they have fetched it

A commit carries an "Assisted-by" trailer. What does that change about who is responsible for the code?

  • Responsibility is shared between the author and the tool's vendor
  • Responsibility moves to whoever reviews and approves the change
  • The agent becomes the author of record and takes responsibility
  • Nothing: it records how the change was made, and the author answers

You got correct