PRD: Conventional Commit Validation
Author: TBD Status: Draft Created: 2026-07-17 Updated: 2026-07-17 Team: TBD Stakeholders: TBD
1. Problem Statement
EOS requires conventional commits through repository guidance, but it does not validate commit messages. Contributors can therefore create commits or merge pull requests whose messages are inconsistent with the repository convention. The inconsistency weakens the readability and machine-readability of the final history, and contributors receive no timely, actionable feedback when a message is invalid.
2. Goals and Success Metrics
- Check every commit created while the repository-managed local hooks are
installed.
- Metric: Percentage of local commit attempts processed by Commitlint.
- Target: 100%.
- Check the title of every pull request before it is eligible to merge.
- Metric: Percentage of mergeable pull requests with a completed title validation check.
- Target: 100%.
- Give contributors actionable feedback when validation fails.
- Metric: Invalid-message results that identify the violated rule and show a valid message shape.
- Target: 100%.
- Preserve a fast local commit workflow.
- Counter-metric: Added wall-clock time for local commit-message validation.
- Target: No more than one second per commit attempt.
3. Solution Overview
EOS will use Commitlint with the maintained
@commitlint/config-conventional
preset at two points: when a contributor creates a local commit and when CI
evaluates the pull-request title that will become a squash-merged commit’s final
subject. Invalid input will fail with Commitlint’s standard rule diagnostics. CI
will also report invalid newly introduced commits on main, giving the
repository visibility into bypassed local hooks even though post-push validation
cannot undo a push.
EOS will adopt the preset without custom Commitlint rules, plugins, parser overrides, or ignore overrides. The preset is compatible with Conventional Commits 1.0.0 but intentionally adds a fixed type list, lowercase and subject style rules, and 100-character limits.
4. Functional Requirements
Validation policy
- [P0] MUST use
@commitlint/config-conventionalas the complete Commitlint policy without EOS-owned rules or overrides.- AC: The Commitlint configuration extends
@commitlint/config-conventionaland does not declarerules,plugins,parserPreset,ignores, ordefaultIgnores. - AC: The accepted types are
build,chore,ci,docs,feat,fix,perf,refactor,revert,style, andtest. - AC: Types must be lowercase; descriptions must be non-empty, must not use sentence case, start case, Pascal case, or uppercase, and must not end in a full stop.
- AC: Headers longer than 100 characters and non-URL body or footer lines longer than 100 characters are rejected.
- AC: Missing blank lines before a body or footer produce the preset’s standard warnings without introducing an EOS-specific severity change.
- AC: The Commitlint configuration extends
- [P0] MUST retain Commitlint’s default ignored-message behavior.
- AC: Merge, revert, semantic-version, automatic-merge,
fixup!, andsquash!messages recognized by Commitlint’s default ignore functions are not rejected by EOS-owned policy.
- AC: Merge, revert, semantic-version, automatic-merge,
- [P0] MUST communicate semantic author responsibilities that syntax validation
cannot infer from a message and diff alone.
- AC: Contributor guidance states that
featis used for a feature andfixis used for a bug fix. - AC: Guidance distinguishes author responsibilities from rules enforced by Commitlint.
- AC: Contributor guidance states that
Local validation
- [P0] MUST validate a proposed commit message whenever an installed,
repository-managed local Git hook creates or amends a commit.
- AC: A conforming or default-ignored message allows the Git operation to continue.
- AC: A non-conforming, non-ignored message stops the Git operation with a non-zero exit status.
- AC: Commitlint reads the message file supplied by Git through the existing repository-managed hook framework.
- [P0] MUST use Commitlint’s standard failure diagnostics for local validation.
- AC: Failure output identifies each failing rule and includes Commitlint’s configured help URL.
- AC: The contributor can correct the message and retry without repairing or reinstalling the hooks.
Pull-request and final-history validation
- [P0] MUST run a CI status check against the pull-request title that will form
the subject of its squash-merge commit.
- AC: The check runs when a pull request is opened, reopened, synchronized, or its title is edited.
- AC: A conforming or default-ignored title passes the check and a non-conforming, non-ignored title fails it.
- AC: Commitlint standard output is visible in the failed GitHub Actions job.
- [P0] MUST make successful pull-request title validation a prerequisite for
merging into
main.- AC: An open pull request with a failing or incomplete validation check is not eligible to merge under EOS repository rules.
- [P0] MUST report Commitlint violations in newly introduced commits on
main.- AC: A push-triggered CI check evaluates only the commits introduced by that push rather than unrelated historical commits.
- AC: The check fails and identifies each invalid, non-ignored newly introduced commit.
- AC: Automated Changesets commits and pull-request titles continue to pass
with their current
chore(release): version packagesmessage.
Consistency and guidance
- [P0] MUST use the same Commitlint version and configuration in local and CI
validation.
- AC: Both validation paths resolve Commitlint from the root lockfile and load
the root
commitlint.config.mjsfile.
- AC: Both validation paths resolve Commitlint from the root lockfile and load
the root
- [P1] SHOULD document how to run Commitlint manually and how to correct a
failed local or CI check.
- AC: Repository documentation includes commands for validating a sample message and the most recent commit.
- AC: Documentation explains the configured types and subject constraints.
- AC: Documentation explains that local hooks are bypassable and CI protects the pull-request merge path.
5. Out of Scope
- Distributing commit validation to repositories other than EOS — this PRD is limited to EOS.
- EOS-owned Commitlint rules, plugins, parser behavior, formatters, or ignore patterns — the maintained conventional preset is the policy boundary.
- Literal enforcement of every machine-verifiable Conventional Commits 1.0.0 form — the selected preset intentionally adds restrictions and default exemptions.
- Rewriting existing Git history — validation applies prospectively.
- Preventing contributors from bypassing local Git hooks — CI provides the authoritative pull-request merge check.
- Validating every intermediate commit in a pull-request branch — the approved squash workflow validates the pull-request title that becomes final history.
- Automatically correcting commit messages or pull-request titles — failures provide guidance, while contributors retain control of the message.
- Interactive commit-message authoring — this change validates messages but does not add Commitizen or another prompt tool.
6. Effort and Feasibility
Engineering size: S Design effort: None
Cost of delay: There is no time-sensitive deadline. Delay prolongs the period in which repository guidance is not enforced and inconsistent messages can reach the history.
Third-party dependencies: Local enforcement depends on Git, Commitlint, and the repository-managed Lefthook installation. CI enforcement depends on GitHub Actions and EOS repository rules that can require the validation status check.
Assumptions and Dependencies
- EOS uses squash merging and the pull-request title becomes the final commit subject.
- The validation CI check can be configured as a required repository status
check for
main. - The existing Changesets release automation retains its conforming commit and pull-request title.
- Contributors who install dependencies receive the repository-managed Git hooks through the existing Lefthook setup.
- Commitlint and its conventional preset continue to support the Node.js version supplied by the EOS Nix development shell.
Risks and Mitigations
- Preset updates may change accepted messages. Pin dependency resolution in
pnpm-lock.yamland review Commitlint release notes during upgrades. - The preset is stricter than Conventional Commits 1.0.0. Document its fixed types, subject rules, and line limits so contributors understand the actual EOS policy.
- GitHub repository settings may diverge from the assumed squash workflow. Verify squash-merge and required-check settings during delivery and document the dependency.
- Local hooks can be absent or bypassed. Treat the local hook as early feedback and the required pull-request status check as the merge boundary.
- A direct invalid push is detected only after it reaches
main. Keep direct pushes governed by repository permissions; use post-push validation for visibility rather than claiming it can prevent the push.
Open Questions
- Who is the PRD author? Owner: TBD; due: before status moves to Approved.
- Which team owns delivery and maintenance? Owner: TBD; due: before status moves to Approved.
- Who must review and approve the PRD? Owner: TBD; due: before status moves to Approved.