/red-line-digital
Interactive field guide

The /pre-commit-check auditor

The commit you're about to make claims one thing; the diff does another. This auditor reads the staged changes, drafts a message that matches them, checks that every claim is backed by a real change, flags the refactor that snuck in, and catches the TODO you left in the code. Then it hands you the findings and gets out of the way.

It is deliberately diagnostic; it surfaces the problems and drafts the message, it never rewrites your commit or unstages a file for you. If you want it to auto-fix what it finds, tell me why. Reply on LinkedIn.

How to read this map

Each card is a stage of the auditor, in order. It is read-only from start to finish; nothing here changes a file or your commit.
The colour on each card's edge tells you what kind of work it is: gathering, checking, or reporting the verdict.
Open any card for the full, plain-language walkthrough at that stage.

Pick a stage to walk, or start at the top

Get this command /plugin marketplace add fire-farmer/red-line-toolkit view source →

The walkthrough, as text

Every stage of the interactive walkthrough above, as plain readable text. Each stage has its own link.

Stage 1Pick the mode, gather the diffStaged, a commit, or a range

Gather

The auditor picks a mode from how you called it: the staged changes by default, one past commit with --commit, or a whole range with --range. It reads the diff, infers what the task was, and drafts a commit message that matches what actually changed.

Read the diff for the chosen mode, infer the task, and auto-draft a conventional-commit message from the changes.

What happens

With no arguments it audits what's staged. --commit a1b2c3d audits one past commit; --range main..HEAD audits every commit in the range, one at a time, before you open a PR. It validates any sha you pass with git rev-parse first, to catch a typo before it reads the wrong thing.

Then it drafts the message the diff earns, in conventional-commit form. A diff that renames a column and updates its two callers drafts as fix(db): rename lease_end to lease_end_date, update callers, nothing more. You can override the inferred task or the drafted message if it read the intent wrong.

Who acts

  • Bash, tool: Runs git status and git diff to read the staged changes or the named commit.
  • Read, tool: Reads STACK.md for the current task tree, to infer what the work was meant to do.

The rules

  • Default to staged. No arguments means audit what's staged right now; the zero-argument path is the one you'll use before almost every commit.
  • Draft only what the diff supports. The auto-drafted message describes the changes that are actually present, not the changes you meant to make.

In: An invocation: staged by default, or --commit / --range. Out: The diff, the inferred task, and a drafted commit message.

Stage 2Is the message true?Every claim backed by a change

Check

The auditor takes the drafted message apart claim by claim and checks each one against the diff. A claim about a file that wasn't touched, or a behavior that isn't in the changes, gets flagged. A message that reads "did A and B and C and D" gets flagged too, because that many conjunctions usually means the commit isn't focused.

Verify every claim in the message is backed by an actual change in the diff; flag claims with no matching change.

What happens

The check is one direction: for each thing the message says, is there a change in the diff that backs it up? A message claiming "add rate-limit middleware" against a diff that only touches the README fails, because the claim outruns the change.

Conjunction-heavy messages get a warning of their own. "Refactor auth, add tests, bump deps, and fix the typo" is four commits wearing one message; the auditor names each strand so you can decide whether to split them.

Who acts

  • the auditor, agent: Matches each claim in the message against the diff and flags the unbacked ones.

The rules

  • Every claim needs a change. A claim in the message with no matching change in the diff is a warning; the message describes work that isn't there.
  • Watch the conjunctions. A message that strings together "A and B and C and D" usually means one commit is doing four jobs; flag it for a possible split.

In: The drafted message and the diff. Out: A pass, or a list of claims the diff doesn't back.

Stage 3Did the scope hold?Each change traces to the task

Check

The auditor walks the changed lines and asks one question of each: does this trace to the task? A refactor you weren't asked for, a rename in a file that has nothing to do with the work, a formatting sweep, a new abstraction nobody requested, each of those gets a warning. Good work; wrong commit.

For each changed line, ask whether it traces to the inferred task; flag refactors, renames, formatting, and abstractions that don't.

What happens

Say the task was "fix the null check in the invoice parser." The diff has the fix, plus a rename of an unrelated helper, plus Prettier reflowing a file you happened to open. The fix is in scope; the rename and the reflow are drive-bys that belong in their own commit, and the auditor flags them.

It isn't saying the extra work is wrong, only that it's wearing the wrong label. A scope-clean commit is one you can revert without losing anything you didn't mean to, and one whose message tells the whole truth about what it did.

Who acts

  • the auditor, agent: Traces each changed line to the task and flags the ones that don't.

The rules

  • Every change traces to the task. A changed line that doesn't map to the inferred task is a warning: refactors, renames, formatting, and unrequested abstractions all count.
  • Drive-bys get their own commit. The flag isn't a verdict on the change; it's a nudge to move it out so this commit stays one clean thing.

In: The changed lines and the inferred task. Out: A pass, or the changes that don't trace to the task.

Stage 4Was anything dropped?TODOs captured, not buried

Check

The auditor scans the diff for new TODO, FIXME, and HACK comments. A note-to-self left in the code is a note nobody will find again; it belongs in the backlog. It also asks whether the observations the work surfaced actually made it into STACK.md, or evaporated in the conversation.

Find new TODO/FIXME/HACK comments in the diff that belong in the backlog, and check the work's observations were recorded.

What happens

A new // TODO: handle the timeout case in the diff gets flagged: real follow-up, wrong home. In the code it's invisible; in STACK.md's follow-ups it's a tracked item someone will actually get to. The comment can stay if you want, but the work needs a home outside the source.

The softer half of the check is memory. The work usually turns up something worth keeping, a fragile assumption, a place that needs tests, a decision made in passing. The auditor asks whether that landed in the backlog or only in the chat, because chat isn't durable.

Who acts

  • the auditor, agent: Scans the diff for orphaned TODO/FIXME/HACK notes and checks the backlog caught the observations.

The rules

  • A TODO belongs in the backlog. A new TODO, FIXME, or HACK in the diff should be a tracked follow-up, not a note that lives only in the code.
  • Observations get recorded. Something the work surfaced but didn't finish belongs in STACK.md, not stranded in a conversation that scrolls away.

In: The diff and STACK.md's follow-ups. Out: A pass, or the notes and observations that never made the backlog.

Stage 5Report the verdictPass, warn, or fail, your call

Report

The auditor prints the mode, the drafted message, the inferred task, and a pass / warn / fail line for each of the three checks. If anything flagged, it lays out your options and stops. It never rewrites the message or unstages a file; the call is yours.

Print pass/warn/fail per check plus the drafted message, then let the user apply the fixes, accept as-is, or move flagged changes out.

What happens

The report reads like a checklist: ✅ Commit truth, ⚠️ Scope discipline: an unrelated rename in utils.ts, ✅ Follow-up discipline, with the drafted message above it. Everything you need to decide, on one screen.

If a check warned or failed, it asks how you want to proceed, and every option is yours to take: apply the recommendations yourself, confirm the changes are in-scope and commit as-is, or move the flagged changes out into their own commit. It does none of those for you, on purpose.

Who acts

  • the auditor, agent: Prints the per-check verdict and the drafted message, then presents the options.
  • AskUserQuestion, tool: Asks how to proceed when a check warned or failed, and hands the decision back to you.

The rules

  • Diagnostic to the end. The auditor surfaces findings and drafts the message; it never edits the commit or unstages a change for you.
  • You pick the path. Apply the fixes, accept as-is, or split the commit; the recommendation is a suggestion, not an action taken.

In: The results of the three checks. Out: A per-check verdict, the drafted message, and your decision.

Stage ✓A commit you can trustTrue, scoped, and captured

Audited

What you end with is a commit whose message is true, whose changes all trace to one task, and whose loose ends made it to the backlog instead of the code. Nothing was auto-changed; you saw every finding and decided.

The auditor turns a commit you hope is clean into one you know is, without touching a file for you.

What happens

A commit that passes all three reads honestly a year later: the message matches the diff, the diff is one coherent thing, and nothing was quietly dropped. That's the whole product, a git history you can trust as a forensic record.

Run it before a single commit, retro on one that's already landed, or sweep a whole range before you open the PR. Same three checks every time; the discipline lives in the command, not in remembering to be careful.

The rules

  • Trust, not automation. The auditor's only product is a commit you can trust; it reports and drafts, and never commits or edits on your behalf.

In: A commit you're about to make. Out: A verified message, a clean scope, and a captured backlog.