feat(cli): add commit message normalizer - #235
Open
gregggreg wants to merge 1 commit into
Open
Conversation
Add an internal/commitmsg package that parses, validates and normalizes commit messages against one Conventional Commits format, and expose it three ways from a single canonical spec: a nightshift commit-msg subcommand, a commit-msg git hook installed by make install-hooks, and the orchestrator's plan and implement prompts. Scope note: this makes the repository enforce one format going forward. Rewriting historical commits is destructive and deliberately out of scope. Nightshift-Task: commit-normalize Nightshift-Ref: https://github.com/marcus/nightshift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a dependency-free
internal/commitmsgpackage that parses, validates andnormalizes commit messages against one Conventional Commits format, and exposes
it three ways from a single canonical spec string so the CLI, the git hook,
the docs and the agent prompts can never drift apart:
nightshift commit-msg—--check/--fix/--print-spec/--quiet,reading a message file or stdin (
-). Issues print asfile:line: severity: message (rule); errors exit non-zero, warnings don't.scripts/commit-msg.sh— a git hook installed bymake install-hooksalongside the existing pre-commit hook. It prefers the built binary, falls
back to
go run ./cmd/nightshift, prints the spec on failure, and documentsthe
--no-verifyescape hatch.buildPlanPromptandbuildImplementPromptnowembed
commitmsg.PromptSpec(task.Type)instead of a hardcoded trailer blurb,so autonomous agents are told exactly the format the hook enforces. The
Nightshift-Task/Nightshift-Reftrailers are unchanged.Format enforced
type(scope)!: subject, header ≤72 chars, imperative mood, no trailing period,blank line before the body, body wrapped at 72 columns, and a single trailing
block of git trailers.
--fixinfers a type when it can (Fixed bug in X.→fix: fixed bug in X),lowercases the type, strips trailing periods, inserts the missing blank line,
reflows body paragraphs (leaving code blocks, indented text, lists and long
URLs alone), hoists stray trailers into one trailing block and dedupes them.
Normalization is idempotent, and an already-conforming message is a byte-exact
no-op. Git's comment lines and
--verbosediff are stripped before parsing so adiff can never leak into a message.
Scope assumption
This makes the repository enforce one format going forward. Rewriting
historical commits is destructive and deliberately out of scope.
Nightshift-Task/Nightshift-Refare not required of human commits — thehook would otherwise reject every manual commit. They're required via
Options.RequiredTrailers, which the orchestrator path and agents use.Testing
Test-driven —
internal/commitmsg/commitmsg_test.gowas written before theimplementation. Verified with
gofmt -l .(clean),go vet ./...,go build ./..., the fullgo test ./...suite, and a manual smoke test:The hook was exercised for real: this PR's own commit passed
scripts/commit-msg.shduringgit commit.🤖 Generated with Claude Code