Commit Message Conventions¶
When to use: Adopting or retrofitting commit message standards in a repo that uses git, npm, and agent-assisted delivery â including library ports and customer clones of the HoEN pattern.
Instructions¶
Goal¶
Give humans and agents a single, enforceable commit contract:
- Header â Conventional Commits with a 72-character subject cap.
- Body â optional; when present, starts after a blank line; long bodies open with a đ bottom-line line.
- Footer â optional
Co-Authored-Bytrailer for agent attribution. - Enforcement â commitlint via husky locally; CI backstop on PRs where the platform supports it.
Pair this skill with git-hygiene for branch policy; this skill covers message shape and lint wiring only.
Message contract¶
Header (required)¶
Allowed types: feat, fix, docs, refactor, test, chore, ci,
build, perf, style, revert.
Scope is freeform â name the area touched (skills, library-maintenance,
agents, repo, âĻ).
Subject rules enforced by commitlint:
- max 72 characters (including type, scope, and colon)
- no forced sentence case
Body (optional, đ when long)¶
When the change needs more than a one-liner, open the body with the bottom line up front. The 72-char subject is the headline; the first body line is the đ summary (emoji prefix, no colon); detail follows below.
commitlint enforces body-leading-blank and footer-leading-blank so the
subject, body, and footer stay visually distinct in git log.
Example:
feat(skills): add git-hygiene enforcement
đ block direct commits to main; require a feature branch.
The commit-msg hook now refuses commits made on main and prompts for a
feature branch. Rationale, edge cases, and rollout notes follow here.
Co-Authored-By: Cursor (Composer 2.5), Driven by Alex Example đšī¸
Co-Authored-By trailer (optional)¶
Use one Co-Authored-By: line per distinct agent session that contributed
to the change. Pack the model(s) and human driver into that single line:
Rules:
- one trailer per agent session, not per file or turn
- do not add a separate
Co-Authored-Byfor the human git author - drop context-window tags (e.g. "1M context") from the agent label
- keep the đšī¸ emoji â it is part of the convention
commitlint disables body/footer line-length limits so long đ bodies and
trailers pass without --no-verify.
File layout baseline¶
Store tooling config under library-maintenance/config/ when the repo follows
the HoEN library layout; otherwise use <repo-root>/ or an existing
config/ folder â but keep one canonical commitlint config path and
reference it from husky, npm scripts, and CI.
.
âââ .husky/
â âââ commit-msg # runs commitlint on each commit
âââ library-maintenance/
â âââ config/
â âââ commitlint.config.mjs
âââ package.json # prepare + commitlint scripts
âââ AGENTS.md # human + agent policy (copy from reference)
Canonical templates live in this skill folder:
| Asset | Purpose |
|---|---|
assets/commitlint.config.mjs |
Shared commitlint rules |
assets/husky-commit-msg |
Husky hook template |
assets/package-json-scripts.json |
npm script + devDependency snippet |
assets/github-commitlint-workflow.yml |
GitHub Actions PR backstop |
references/agents-md-commit-section.md |
Drop-in AGENTS.md section |
references/azure-pipelines-commitlint-step.md |
Azure DevOps PR step |
Retrofit rollout (existing repository)¶
Run in order:
- Copy config â place
commitlint.config.mjsat the chosen config path. - Wire husky â copy
.husky/commit-msg; ensurepackage.jsonhas"prepare": "husky"and commitlint devDependencies (see asset snippet). - Add npm scripts â at minimum
commitlint(hook) andlint:commits(branch range check). - Document policy â add or merge the AGENTS.md section from
references/agents-md-commit-section.md; link from CONTRIBUTING.md. - Add CI backstop â GitHub: copy the workflow asset; Azure DevOps: add
the step from
references/azure-pipelines-commitlint-step.md. - Bootstrap locally â run
npm installonce per clone so husky registers. - Verify â test a good message and a deliberately bad header:
npm install
echo "bad message" | npx commitlint --config <config-path>
echo "feat(repo): test commitlint wiring" | npx commitlint --config <config-path>
npm run lint:commits # after at least one conventional commit on the branch
Transplant to a customer or sibling library¶
When porting from HoEN to a licensed clone (e.g. Fonterra PRM):
- Copy the assets verbatim unless the target already has an equivalent path.
- Point husky and npm scripts at the same
--configpath as CI. - Merge the AGENTS.md section; adjust scope examples (
docs, internal team names) but keep types, 72-char cap, đ opener, and trailer rules unchanged. - Record the port in skill
provenance.source(ported_from,source_commit) on any new skills â commit conventions stay identical across ports. - If the target uses Azure DevOps instead of GitHub, skip the workflow asset and use the Azure reference step.
Platform notes¶
| Platform | Local enforcement | CI backstop |
|---|---|---|
| GitHub | husky commit-msg |
.github/workflows/commitlint.yml |
| Azure DevOps | husky commit-msg |
PR pipeline step (see reference) |
| No Node in repo | not supported by this pattern | document manual review only |
Husky v9 expects the hook file at .husky/commit-msg with no shebang
required; invoke commitlint via node_modules/.bin/commitlint.
References¶
- Conventional Commits
- @commitlint/config-conventional
- git-hygiene â branch policy companion
- wagoid/commitlint-github-action
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Hook never runs | npm install not run after clone |
Run npm install; confirm .husky/commit-msg exists |
commitlint: command not found |
devDependencies missing | Add @commitlint/cli and @commitlint/config-conventional; reinstall |
| CI fails but local passes | CI uses default root config | Pass --config or set configFile in the workflow |
header-max-length failures |
Subject too long | Shorten subject; move detail to đ body |
body must have leading blank line |
Subject glued to body | Insert blank line between header and body |
Co-Authored-By rejected |
Wrong commitlint rules | Ensure body-max-line-length and footer-max-line-length are disabled |
Contributors use --no-verify |
No CI backstop | Add PR commitlint job; document in CONTRIBUTING.md |