Skip to content

Require a scope on the version-driving commit types (ADR-0034)#294

Merged
Reefact merged 3 commits into
mainfrom
claude/issue-231-discussion-wfrh45
Jul 23, 2026
Merged

Require a scope on the version-driving commit types (ADR-0034)#294
Reefact merged 3 commits into
mainfrom
claude/issue-231-discussion-wfrh45

Conversation

@Reefact

@Reefact Reefact commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

Enforce, in commit-lint, that the two version-driving types — feat and fix — carry a scope, and reject an unscoped one at the commit-msg hook and in CI. This closes the release-record gap surfaced and documented by #231 / #292: the release tooling partitions commits into trains by scope, so an unscoped user-facing feat:/fix: matched no train and was silently dropped from the release notes and changelog. The decision is recorded as ADR-0034 (Accepted); CONTRIBUTING is updated (EN + FR) from a documented convention to the enforced rule.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Changes

  • tools/commit-lint/lint-commit-message.sh — a well-formed feat/fix header with no scope is now rejected, at the local commit-msg hook and in the CI check (one shared script), with a message that names the consequence. Every other type keeps the scope optional. Contributor-facing behaviour change: feat: … / fix: … with no scope, valid before, is now refused; add a scope (feat(core): …).
  • ADR-0034 (doc/handwritten/for-maintainers/adr/, EN + FR, indexed) — records the decision, its rationale, and the alternatives weighed (keep documenting only; require a scope on every type; change the release tooling to keep unscoped commits). Marked Accepted per the maintainer's explicit acceptance.
  • CONTRIBUTING.md / CONTRIBUTING.fr.md — the Scope section now states the enforced rule (scope required on feat/fix, optional elsewhere) instead of a convention to remember, and links ADR-0034.

No CI-workflow YAML change (the commit-lint workflow already invokes the shared script) and no release-tooling change (the partition semantics are unchanged; only the linter gains the requirement).

Testing

No library code changed, so the build/test suite was not run:

  • dotnet build FirstClassErrors.sln — not run (no code change)
  • dotnet test FirstClassErrors.sln — not run (no code change)
  • Analyzer tests pass (FirstClassErrors.Analyzers.UnitTests) — not run (no analyzer change)

Verified the linter behaviour directly by running the script against a matrix: feat: / fix: with no scope are rejected; feat(scope):, fix(scope,scope):, and the non-version-driving types (docs:, ci:, chore:, refactor:, perf:) with no scope all pass. The three commits of this PR themselves pass the commit-msg hook (and will pass the CI lint).

Documentation

  • Public API / error documentation updated
  • README / doc/ updated — CONTRIBUTING (Scope section) and a new ADR.
  • French translation updated — EN and FR kept in lockstep (ADR-0034 and CONTRIBUTING both bilingual). README.fr.md is not among the touched files.
  • No documentation change required

Architecture decisions

  • No architectural decision in this pull request
  • New decision recorded — ADR-0034, Require a scope on the version-driving commit types. Drafted for the maintainer and marked Accepted per their explicit acceptance in the originating conversation (I do not flip an ADR's status on my own initiative).
  • Supersedes an existing ADR — successor proposed, status not flipped: ADR-____
  • ⚠️ Conflicts with an existing ADR — flagged for the maintainer: ADR-____

Related issues

Closes #293


🤖 Generated with Claude Code


Generated by Claude Code

claude added 3 commits July 23, 2026 10:15
Record the decision that commit-lint requires a scope on the two
version-driving types (feat, fix): the release tooling partitions commits
into trains by scope, so an unscoped feat/fix is silently dropped from the
release notes and the changelog. The ADR weighs the alternatives (keep
documenting only, require a scope on every type, change the release
tooling), is drafted bilingually, and is indexed.

Refs: #293
feat and fix are the only version-driving types, and the release tooling
(tools/trains.sh) routes commits to trains by scope; an unscoped feat/fix
matches no train and is silently dropped from the release notes and the
changelog, so a user-facing change can vanish from the release record.
Reject an unscoped feat/fix at the commit-msg hook and in CI, naming the
consequence. Every other type keeps the scope optional.

Refs: #293
Update the Scope section (EN + FR) from "a user-facing change must carry a
scope" to the rule commit-lint now enforces: a scope is required on feat
and fix and rejected when absent, at the hook and in CI, and optional on
every other type. Link ADR-0034.

Refs: #293
@Reefact
Reefact merged commit e518084 into main Jul 23, 2026
16 checks passed
@Reefact
Reefact deleted the claude/issue-231-discussion-wfrh45 branch July 23, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

commit-lint: require a scope on feat: and fix: to close the unscoped-commit release gap

2 participants