Troubleshooting
The house rule linters
What the commit hook and the prose linter complain about, in their own words.
Every threshold comes from workflow.style in torta.json. See
the style schema for the keys.
Enable the hook once per clone:
git config core.hooksPath .githooks
The commit hook refused my message
The hook prints one finding per line as <file>:<line>: <complaint>.
subject is not type(scope): summary
A subject is a lower case type, a scope of lower case letters, digits and
. _ / -, then a colon, a space, and a summary.
subject is N columns, the shape is at least 80
Or at most 90. Columns are terminal columns, so a wide character counts as
two.
the subject summary starts with x, which is past tense
Also which is a gerund and which is third person. Write update the wizard, not updated, updating or updates. When the word is an irregular
verb the finding names the form to use instead, as in
the imperative is write``. Otherwise it quotes the rule:
write it in the imperative, for example `update the wizard`
rather than `updated the wizard`
A word that ends in a rejected suffix without being an inflection is kept:
press and focus end in s, proceed ends in ed, and a stem with no
vowel left was never a suffix.
the subject summary is 1 word
a description is a verb and its object, for example `update
the wizard`, not `update`
the subject summary starts with Update, which is not lower case
a description starts with a lower case verb, for example
`update the wizard`
bullet is N columns, the shape is at most 90
Body bullets have their own width.
body line is not - one thing this commit did
A body is - bullets, then the trailer sections:
refs:[ticket#1][ticket#2], agents:[infra,archi,frontend],
models:[fable(review),opus(build)], hitl:[published].
the refs: line is not refs:[ticket#1][ticket#2]
The section was recognised by its lead but does not match its pattern.
agents: sits below models:
The order is bullets, then refs:, then agents:, then models:, then
hitl:. The same finding appears as a bullet sits below ... when a bullet
comes after a section.
em dash in the commit message
em dash in the commit message; a comma or a colon says the
same
attribution trailer
No Co-Authored-By:, no Claude-Session:, no Generated-By:, no “generated
with”, anywhere in the message, not only at the end.
the commit message is empty
Nothing but git’s own comment lines.
Messages git wrote itself
A subject beginning Merge, Revert, fixup!, squash!, or exactly
Initial commit, is exempt from the shape, the body grammar and the banned
characters, but not from the trailer scan.
Getting past it
git commit --no-verify bypasses the hook. The backstop a review or CI runs
is:
python3 engine/lint-commit.py --range A..B
The prose linter found something
python3 engine/lint-prose.py .
python3 engine/lint-prose.py --summary .
One finding per line as path:line: message, exit 1 when there is one.
--summary adds counts per top level directory.
em dash in prose (U+2014)
Rewrite with a comma, a colon, or a full stop.
em dash in a comment (U+2014)
The same character inside a code comment. A banned character inside a string literal is allowed.
comment block is N rows, the shape is at most 4
A run of comment-only rows is a block. Cut it. A trailing comment after code does not join a block.
A block whose opener is exempt, /** by default, is not counted for rows, but
is still counted for width and may not carry a banned character.
comment row is N columns, the shape is at most 80
Measured in terminal columns, so an emoji or a CJK character counts as two.
There is no –fix
Asking for one prints why:
lint-prose: there is no --fix. What replaces a banned character is a writing
decision (a dash, a comma, a colon, a rewrite), and a comment block over the
shape has to be cut, not reflowed.
lint-prose: no such path
That path does not exist. Exit code 2 means the linter could not run, where 1 means findings.
What is never read
Directories named node_modules, vendor, __pycache__ and .git, and
files matching package-lock.json, *.min.js or *.lock. Extensions outside
the prose and source lists are not opened.