Skip to main content
Tracked commits carry headers that join the commit to the plan. The commit-msg hook resolves them at commit time; the git history becomes the join table between plans and code.

PRD-tracked work

feat(scope): add email validation

PRD: signup-email-validation
Feature: email-validation
Task: Add email validation

Why the change was made, not just what changed.

Fix-tracked work

fix(auth): serialise token refresh

Fix: login-timeout
Task: Serialise token refresh behind a mutex

The rules

  • Task: is matched by equality against the task description in the markdown (whitespace trimmed, escaped backticks tolerated). A reworded header fails to resolve and the commit is rejected — copy the description exactly as it appears in the feature or fix file.
  • One commit can close several tasks — give it one Task: header per task. All of them are tracked against the same SHA.
  • Every stage carries the same headers — the test:, feat:, and refactor: commits of one task all reference it identically; the commit type is what distinguishes RED from GREEN from REFACTOR (see the loop).
  • Untracked work needs no headerschore: and untracked: commits pass through the hook without them. Use them for maintenance that belongs to no plan, not to dodge tracking.
  • Write the why. The body is for the reasoning — the diff already says what changed.

Scopes

The parenthesised scope (feat(api):, test(signup):) is conventional- commits style and yours to choose — the hooks key off the type and headers, not the scope.