7.2 KiB
issue, issue_title
| issue | issue_title |
|---|---|
| 14 | Set up prek for pre-commit linting (Biome + markdownlint) |
Set up prek for pre-commit linting
Problem Statement
During the #13 retro, a Biome version-skew issue surfaced: running npm run lint:fix locally with a different Biome version than the one pinned in package-lock.json produced formatting changes that CI rejected.
A pre-commit hook running the project-local linters would catch these mismatches before they reach CI, saving round-trip time on failed builds.
Goals
- Install and configure prek as the git hook manager.
- Run
npx biome checkon staged files in the pre-commit hook so the project-pinned Biome version is always used. - Run
npx markdownlint-cli2on staged Markdown files in the pre-commit hook. - Document the setup so contributors know how to install hooks and what they enforce.
Non-Goals
- Adding new lint rules or changing existing Biome/markdownlint configuration — out of scope.
- Running the full test suite or type-check in the pre-commit hook — too slow for a pre-commit gate; CI handles these.
- Migrating CI to use prek — CI continues to run
npm run lintandnpm run lint:mddirectly.
Background
- Origin: #13 retro (
docs/retro/0013-consolidate-session-start-handlers.md) — astyle:commit with wrong Biome formatting caused a CI failure and 2 extra fixup commits. - Existing lint scripts:
npm run lint(biome check .),npm run lint:md(markdownlint-cli2 '*.md' 'docs/**/*.md' '.pi/prompts/**/*.md'). - CI:
.github/workflows/ci.ymlrunsnpm run lintandnpm run lint:mdas separate steps. - Permission surface: none — this is a developer-tooling concern with no policy semantics.
- On-disk identity: no impact — prek config lives in
.prek.yamlat the repo root, not in the Pi config directory.
Design Overview
prek is a Rust-based git hook manager (drop-in replacement for pre-commit).
It reads .prek.yaml at the repo root and installs git hooks that run configured checks on staged files.
Hook configuration
The .prek.yaml file defines two hooks under pre-commit:
- Biome — runs
npx biome checkon staged JS/TS/JSON files. Usingnpx biomeensures the project-local version fromnode_modulesis used, preventing version skew. - markdownlint — runs
npx markdownlint-cli2on staged.mdfiles.
Both hooks should operate only on staged files (prek handles this via types/files filters and passes matching filenames to the command).
Developer setup
After cloning, a developer runs prek install once to set up the git hooks.
This is a one-time step documented in README.md and optionally wired as a prepare npm script so npm install auto-installs hooks.
Module-Level Changes
Added
.prek.yaml— prek hook configuration with Biome and markdownlint hooks scoped to relevant file types.
Changed
package.json— add apreparescript (prek install) so hooks are installed automatically afternpm install. This is the standard convention for git hook managers.README.md— document the pre-commit setup: what it runs, how to install hooks manually if needed, how to skip hooks (git commit --no-verify) in emergencies..gitignore— no changes needed; prek does not generate files that need ignoring.
Not changed
biome.json— no changes; the hook invokes the existing config..markdownlint-cli2.yaml— no changes; the hook invokes the existing config..github/workflows/ci.yml— no changes; CI continues to run the full lint suite independently.
TDD Order
This issue is primarily a configuration/tooling change with no application logic, so the "test" cycles are validation-oriented rather than unit-test-oriented.
-
Verify prek is installable and
.prek.yamlis valid. Create.prek.yamlwith both hooks. Runprek installand confirm hooks are registered (.git/hooks/pre-commitexists and delegates to prek). Commit:feat: add prek pre-commit config for Biome and markdownlint (#14) -
Verify Biome hook catches lint violations on staged files. Stage a file with a deliberate Biome violation, run
git commit(orprek run pre-commit), confirm it fails. Stage a clean file, confirm it passes. Commit:test: verify Biome pre-commit hook catches violations (#14)(manual verification, no committed test file) -
Verify markdownlint hook catches Markdown violations on staged files. Stage a
.mdfile with a deliberate violation (e.g., trailing spaces), run the hook, confirm failure. Stage a clean.mdfile, confirm it passes. Commit:test: verify markdownlint pre-commit hook catches violations (#14)(manual verification) -
Add
preparescript and update README. Wireprek installintopackage.json'spreparescript. Add a "Pre-commit hooks" section toREADME.md. Commit:docs: document prek pre-commit setup (#14)
Risks and Mitigations
| Risk | Mitigation |
|---|---|
prek not installed on contributor's machine → prepare script fails |
Document prek installation in README. The prepare script can use prek install with a guard (command -v prek or similar) so it warns but does not block npm install. |
| Hook runs full-repo lint instead of staged-only → slow commits | Configure prek to pass only staged filenames to each command. Verify with a manual test. |
| Could this silently weaken a permission? | No — this change is purely developer tooling. It adds a pre-commit gate; it does not touch any permission surface, policy file, or runtime code. |
markdownlint glob mismatch between hook and npm run lint:md |
Use the same glob patterns in .prek.yaml as in package.json's lint:md script. |
npx biome falls back to a global install if local is missing |
npx resolves from node_modules/.bin first when run inside a project with a lockfile. Document that npm install must be run before committing. |
Open Questions
- Should
preparesilently skip if prek is not installed? A guard likecommand -v prek >/dev/null 2>&1 && prek install || trueavoids blockingnpm installfor contributors who haven't installed prek yet, but it also means hooks silently won't exist. Decide during implementation. - Should we pin a prek version?
prek is installed globally (via
cargo installor a binary download), not as an npm dependency. Pinning is not straightforward — defer unless version-specific breakage appears.