ANTIGRAVITY LABJP
Articles/Agents & Manager
Agents & Manager/2026-07-10Advanced

Tracing Why an Agent Wrote That Line Six Months Ago — Commit Granularity and Provenance Trailers

When an agent packs 14 files and 800 lines into a single commit, git blame tells you nothing six months later. Here is how I split commits at intent boundaries, recorded provenance as machine-readable Git trailers, and built a one-command path from a blamed line back to the design decision behind it.

Antigravity318Agents18Git6Commit DesignProvenanceLong-term Operations2

Premium Article

Six months ago I ran git blame on my own repository and stopped cold.

The three lines I needed to change were attributed to me. Dated January. Commit message: "Refactor cache layer and update tests." Fourteen files touched, over 800 lines of diff.

An agent had written those three lines. I had approved the plan, skimmed the diff, squashed everything into one commit, and pushed. What remained for future-me was three lines adrift in an 800-line sea, and a sentence that said nothing at all.

Why was that branch necessary? Which error did we hit before settling on this ordering? Nothing left to answer with.

A Commit Marks an Intent, Not a Work Session

Back when humans wrote every line by hand, commit granularity regulated itself. You spent an hour fixing one thing, then committed it. Elapsed time acted as a natural ceiling.

Hand the work to an agent and that ceiling vanishes. One session advances six plan steps and rewrites fourteen files. Folding that into a single commit feels right only because the session boundary looks like a commit boundary.

To anyone reading history later, a session boundary carries no meaning. An intent boundary does.

How commits are splitWhat git blame returns six months laterMedian diff size
One session, one commit"Refactor cache layer and update tests"400–900 lines
One plan step, one commit"Add TTL guard to cache read path"30–120 lines
One file, one commitThe filename restated. Intent still lost.10–60 lines

Look closely at the third row. Smaller is not automatically better. Splitting per file records nothing about why the change was needed.

The test is not line count. It is whether the change can be explained on its own. Antigravity agents carry an explicit plan, and a single plan step is, by construction, a change that can stand alone. That is the boundary I settled on while automating article generation across my four sites. As an indie developer whose only code reviewer is myself, how readable the history stays translates directly into how fast I can fix things later.

Committing at Plan Step Boundaries

The implementation can stay plain. Stop telling the agent to commit once everything is finished; have it commit as each step completes.

# .agent/commit-step.sh
# usage: commit-step.sh <step-id> <summary>
set -euo pipefail
 
STEP_ID="$1"; shift
SUMMARY="$*"
 
# Nothing staged means nothing to record. Never create empty commits.
if git diff --cached --quiet; then
  echo "step ${STEP_ID}: no staged changes, skipping commit."
  exit 0
fi
 
FILES=$(git diff --cached --name-only | wc -l | tr -d ' ')
LINES=$(git diff --cached --numstat | awk '{ add += $1; del += $2 } END { print add + del }')
 
# Warn the moment a step outgrows a single explainable intent.
if [ "${FILES}" -gt 8 ] || [ "${LINES}" -gt 300 ]; then
  echo "⚠️ step ${STEP_ID}: ${FILES} files / ${LINES} lines. This plan step may be too large." >&2
fi
 
git commit -m "${SUMMARY}" \
  -m "Agent-Run-Id: ${AGENT_RUN_ID}" \
  -m "Agent-Step: ${STEP_ID}" \
  -m "Agent-Model: ${AGENT_MODEL}" \
  -m "Agent-Plan-Sha: ${AGENT_PLAN_SHA}"

Passing several -m flags stacks each as its own paragraph. When the final paragraph consists solely of Key: Value lines, Git treats it as a trailer block — which means git interpret-trailers --parse and git log --format='%(trailers:key=Agent-Run-Id,valueonly)' can extract it mechanically.

That is categorically different from writing "generated by an agent" in prose. Prose is readable. It is not queryable, and it is not countable.

AGENT_PLAN_SHA hashes the plan text you approved. The plan itself lives and dies with the session, but the hash lets you prove later that three particular commits descended from one approved plan.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A working script that walks from any source line back through Git trailers to the agent run, its intent, and the alternatives it rejected
Why one-commit-per-session fails, where to place commit boundaries instead, and how to enforce that mechanically with a commit-msg hook
A provenance freezing design that assumes artifacts disappear, keeping only the durable summary in-repo at 1 to 3 KB per step
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Agents & Manager2026-07-10
When Your Agent's Files Vanish Into .gitignore — A Pre-Commit Detection Gate
When an agent writes files that match .gitignore, the diff review looks perfect but nothing lands in the commit. Here is a gate script that catches ignored build output before you push, plus the tuning it needs.
Agents & Manager2026-06-29
When Your Antigravity Agent Opens a PR That Just Says "Update files" — and a Gate That Forces a Reviewable Summary
Pull requests opened automatically by an Antigravity agent tend to carry empty descriptions like "Update files." Here is a validation gate, with working code, that estimates risk from the diff and rejects vacuous descriptions so a human can actually review them.
Agents & Manager2026-06-21
Taking Stock of the Dependencies Your Agent Added — A Design for Keeping License and Provenance Traceable
A few months of letting agents work, and your package.json quietly grows dependencies you don't remember adding. Here is a design for taking stock — recovering what was added, when, and why, in a form you can still trace later.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →