What's the commit-message contract, and why is it strict?

The contract enforced by the commit-message hook:

  • Title: Conventional Commits — type(scope): subject, type ∈ feat fix docs perf refactor build ci test chore style revert, ≤100 chars.
  • Body: ≤3 non-empty lines.
  • No noise: no AI attribution, no Co-Authored-By trailers, no pasted prompts, no file lists or verification tables (those belong in the work log / PR body).

Why strict: two consumers read commit titles forever.

  1. Release automation parses the type to build the changelog — an unparseable title means the change silently disappears from release notes.
  2. Humans running git log — history is the one document nobody can edit later. Three tight lines survive; a 40-line pasted test log makes history unreadable.

Examples that pass:

feat(board): add swimlane filter to cos board output
fix(hooks): source cos-env before reading state dir
docs(quickstart): correct uv install command for zsh

The hook names the rule you broke — fix that one thing and re-commit. Agent sessions can’t bypass it (--no-verify is itself blocked for agents, on purpose).