Skip to content

fix(hooks): drop biome --unsafe from the pre-commit format hook - #166

Merged
willgriffin merged 1 commit into
mainfrom
fix/issue-165-precommit-unsafe-autofix
Sep 14, 2026
Merged

willgriffin merged 1 commit into
mainfrom
fix/issue-165-precommit-unsafe-autofix

Conversation

@willgriffin

Copy link
Copy Markdown
Contributor

Summary

The pre-commit format hook ran npx biome check --write --unsafe with
stage_fixed: true. Biome documents unsafe fixes as ones that may change
runtime behavior; combined with auto-staging, such a rewrite landed in the
commit with no prompt, no diff, and exit 0 — so the committed revision could
differ from the reviewed one while every check still reported green.

Closes #165.

Found by sweeping sibling repositories after the identical defect was fixed in
happyvertical/smrt (happyvertical/smrt#2869, PR happyvertical/smrt#2870, now
merged). This applies the same resolution, adapted to this repository's naming.

The defect, reproduced against this repo's own biome config

Input (staged) Old command Result
db.transaction!(() => {}) in a branch already gated on transaction Checked 1 file in 39ms. Fixed 1 file. exit 0 rewritten to db.transaction?.(…) — an assertion becomes a silent skip

No diagnostic named the rule. fail_text only fires when Biome cannot fix
something, so a successful semantic rewrite was completely silent.

What changed

  • lefthook.yml — --unsafe removed from the pre-commit format command.
    Safe fixes and formatting still apply and still auto-stage, so the hook's
    convenience is unchanged. The same input is now preserved and the proposed
    change is printed as a warning instead.
  • fail_text — now names the scoped remedy and warns that unsafe fixes can
    change runtime behavior, instead of only saying "fix manually".
  • package.json — new format:unsafe, scoped to staged files (--staged;
    biome.json already sets vcs.enabled + clientKind: git), so the remedy
    touches only what the author is committing.

Naming note

smrt called its equivalent script lint:fix-unsafe. This repo uses
lint* = biome lint and format = biome check --write ., so the unsafe
counterpart of format is format:unsafe. The name follows this repository's
convention rather than smrt's; the fail_text names the correct script, so
there is nothing to memorize either way.

Intended behavior change, stated plainly

For an error-severity rule whose only fix is unsafe, the commit now fails
where it previously succeeded after silently rewriting the file. That is the
point of the change, and it is documented in the hook comment. Warn-level
diagnostics (e.g. noNonNullAssertion) do not block commits.

Lint enforcement does not regress: pre-push already runs
biome ci --diagnostic-level=error ., green across 35 files.

Validation

Evidence was regenerated after pnpm install --frozen-lockfile; a first run was
discarded because the worktree had no node_modules and the commands exited
ELIFECYCLE rather than actually checking anything.

Check Result
Old-vs-new probe, noNonNullAssertion old rewrote silently at exit 0; new preserves source and emits a warning with the proposed diff
format:unsafe scoping one staged file + identical unstaged sibling → Checked 1 file; sibling and every other repo file untouched
pnpm format-check Checked 35 files. No fixes applied.
npx lefthook dump effective run line carries no --unsafe
line width baseline had 3 lines >80 chars; head has 2 (yamllint is not a gate here)

No source file is touched, so svelte-check/tsc cannot observe this change;
the probes above are the executable evidence for the behavior that did change.

Review

Phase Reviewer Result
Preliminary codex-luna (fastest, gpt) CLEAN
Final claude-opus (advanced) CLEAN

Both findings accepted during smrt#2870's review (scope the opt-in script;
make fail_text name it) are already incorporated here rather than rediscovered.

{
  "schema": "hv-agent-run:v1",
  "runtime": "claude",
  "session": "a740c64d-ca3b-48fd-bb27-f43b473caaa5",
  "issue": 165,
  "policy_revision": "1.0.0",
  "status": "complete",
  "validation": [
    "probe: biome check --write --unsafe vs --write on noNonNullAssertion (base rewrote silently at exit 0; head preserves + warns)",
    "probe: pnpm format:unsafe with one staged file + identical unstaged sibling (Checked 1 file; sibling and all other files untouched)",
    "pnpm format-check (biome ci --diagnostic-level=error .) — 35 files, 0 errors",
    "npx lefthook dump — effective run line carries no --unsafe",
    "pnpm install --frozen-lockfile before evidence generation (first run discarded: no node_modules)",
    "commit made with hooks ENABLED (commitlint passed); no --no-verify"
  ]
}

The pre-commit `format` hook ran `biome check --write --unsafe` with
`stage_fixed: true`. Unsafe fixes may change runtime behavior, so that
combination could rewrite semantics and auto-stage the rewrite into the commit
with no prompt, no diff, and exit 0 — making the committed revision differ from
the reviewed one while every check reported green.

Verified against this repository's own biome config: the old command rewrote
`db.transaction!(...)` to `db.transaction?.(...)` and reported only
"Checked 1 file in 39ms. Fixed 1 file.". In a branch already gated on
`transaction` being present, that turns an assertion into a silent skip.
Without `--unsafe` the same input is left untouched and the proposed change is
printed as a warning instead, so formatting and safe fixes still auto-stage
while a semantics-changing fix becomes visible and opt-in.

Unsafe fixes remain available as `pnpm format:unsafe`, scoped with `--staged`
(biome vcs integration is already enabled) so the remedy touches only the files
being committed; a trailing path narrows it further. Verified with one staged
file and an identical unstaged sibling: "Checked 1 file", staged file rewritten,
sibling and every other repository file untouched.

One consequence is intended rather than incidental: for an error-severity rule
whose only fix is unsafe, the commit now fails instead of succeeding silently.
The fail_text therefore names the scoped command and warns that unsafe fixes can
change runtime behavior, rather than only saying "fix manually".

Lint enforcement does not regress: pre-push already runs
`biome ci --diagnostic-level=error .`, green across 35 files.

This is the same defect and the same resolution as happyvertical/smrt#2869
(PR happyvertical/smrt#2870), found by sweeping sibling repositories.

Refs #165
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-14T15:01:28.784050Z a4c4da1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@willgriffin
willgriffin merged commit 9cea4ee into main Sep 14, 2026
3 checks passed
@willgriffin
willgriffin deleted the fix/issue-165-precommit-unsafe-autofix branch September 14, 2026 15:20
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.

pre-commit hook applies Biome --unsafe fixes and auto-stages them, silently changing reviewed commits

1 participant