Skip to content

Add scripts/format-changed.sh: sanctioned pre-commit formatting - #213

Merged
skylerberg merged 1 commit into
mainfrom
format-changed-script
Sep 22, 2026
Merged

skylerberg merged 1 commit into
mainfrom
format-changed-script

Conversation

@skylerberg

@skylerberg skylerberg commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

What

The format:check chicken-and-egg: the only sanctioned formatter was the post-commit hook's amend, so a working tree was guaranteed red until after the commit — every branch paid one doomed check:all run. This adds the pre-commit half.

How

  • .githooks/format-touched --no-amend — the same per-package buckets and pinned fixers, but nothing is staged or amended, and files with unstaged changes are formatted rather than skipped. That skip only ever protected the amend from swallowing WIP; with no amend there is nothing to protect — a dirty working-tree file is exactly what the mode is for.
  • scripts/format-changed.sh — the documented front door: collects modified + untracked files from git status --porcelain (renames resolve to their new name; deletions are skipped by format-touched's [ -f ]) and delegates. Files the branch already committed are deliberately not revisited — the hook formatted them at commit time, and re-reading them against a stale base would only reformat whatever main gained since.

The new loop: scripts/format-changed.sh → check:all green on the first run → commit → the hook finds nothing to do.

The hand-run ban stays and is the point: no root node_modules, per-package pinned binaries, and only web's prettier parses .svelte — so the fixer dispatch has one owner, and both entry points go through it.

Tests

  • Hook suite (24 cases, +5): --no-amend formats a file with unstaged changes, folds nothing into HEAD even when fixers rewrote it, no-ops with no paths; the wrapper collects modified/untracked/renamed and skips deleted; clean tree runs nothing.
  • shellcheck + per-shebang syntax checks clean (the repo-ci repo-files steps run locally).
  • check-comments green; root AGENTS.md, cli/AGENTS.md and scripts/README.md updated where the rule lives.
  • End-to-end in this worktree: an untracked badly-formatted web/src/*.ts and a dirty tracked one were both rewritten by web's own pinned prettier, prettier --check green after, HEAD untouched.

The "never run prettier --write or eslint --fix by hand" rule was right, but
its only sanctioned formatter ran after the commit — so format:check was
guaranteed red on a working tree, and every branch paid one doomed check:all
run before the post-commit hook's amend made it green.

- format-touched gains --no-amend: same per-package buckets and fixers, but
  nothing is staged or amended, and files with unstaged changes are formatted
  rather than skipped (the skip only ever protected the amend from swallowing
  WIP; with no amend there is nothing to protect).
- scripts/format-changed.sh collects the working tree's modified and untracked
  files from git status --porcelain and delegates. Files the branch already
  committed are not revisited — the hook formatted them at commit time.
- Tests: --no-amend formats dirty files and never folds into HEAD; the
  wrapper collects modified/untracked/renamed paths and skips deletions.
- Root and cli AGENTS.md now name the wrapper where the rule lives;
  scripts/README.md indexes it.
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
🟣 Preview removed (PR closed).

@skylerberg
skylerberg merged commit 9ec7ed2 into main Sep 22, 2026
15 checks passed
@skylerberg
skylerberg deleted the format-changed-script branch September 22, 2026 20:32
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.

1 participant