Skip to content

Bring harper-pro to prettier-clean, gate main on it in CI - #902

Open
kriszyp wants to merge 9 commits into
mainfrom
fix/prettier-clean-main
Open

kriszyp wants to merge 9 commits into
mainfrom
fix/prettier-clean-main

Conversation

@kriszyp

@kriszyp kriszyp commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Bring harper-pro to prettier-clean and gate main on it in CI.

npx prettier --check . failed on origin/main: it hard-errored walking into the core submodule's deliberately malformed test fixtures (nothing previously excluded core from prettier's own default .gitignore/.prettierignore lookup — it's tracked as a submodule, not gitignored), and separately warned on 27 unformatted files in harper-pro's own tree. Because main wasn't clean, the guideline-mandated npm run format:write rewrote ~20 unrelated files for every contributor, who then hand-reverted them. There was also no format check in .github/workflows/.

For the human reviewer

  1. Is the requirement warranted? Yes, as specified. A repo with no format gate keeps drifting the moment anyone forgets format:write, and the CONTRIBUTING.md sync process already assumes clean formatting between drift-free commits.
  2. Whole-tree reformat once vs. format-as-touched — chosen: one clean baseline commit now, enforced going forward, over letting files reformat piecemeal as they're touched (which never converges and keeps the CI gate meaningless until every file happens to get edited). Cost: git blame on ~25 touched files now points at the reformat commit; mitigated by recording it in .git-blame-ignore-revs (see below). A second cost, surfaced by this PR's rebases: any open backport PR touching the same lines on a release branch will now hit whitespace-only conflicts against main; reversible by running the same reformat on each release branch if that becomes a problem. A third cost, surfaced by the Oct 10 rebase: a concurrent main PR can land an unformatted file after this branch's last push, which then fails the new gate until this branch rebases again and reformats it (happened once already — see the cherryPickPatch.test.mjs note below).
  3. Merge method matters for .git-blame-ignore-revs to keep working. Only an actual merge commit preserves the SHAs it records. GitHub's "Rebase and merge" also rewrites every commit (new parent → new SHA — the same mechanism this branch's own rebases onto main have twice demonstrated on its own commits), so it loses the blame-skip exactly like squash does; recent main history (titled (#NNN)) suggests squash is this repo's usual strategy. Not blocking: git blame --ignore-revs-file degrades gracefully on an unresolvable SHA (verified — exit 0, falls back to normal attribution) rather than erroring, so any non-merge-commit strategy just quietly loses the blame-skip until someone records the landed SHA in a follow-up. Whoever merges this PR needs to pick a merge commit, or plan that follow-up.
  4. HTML fixtures got reformatted too — the served bytes now include extra whitespace. Verified safe: every assertion against these fixtures in integrationTests/cluster/replicatedStaticRedeploy.test.mjs uses .body.includes(...), not exact/byte equality, and both fixture versions of control.html remain byte-identical to each other pre- and post-format (this is a cross-fixture equality claim, not a claim that the bytes match the pre-Prettier fixture). Independently re-verified during this PR's cross-model review (a Gemini "major" finding claiming the opposite was checked against the actual assertions and dropped as factually wrong).
  5. CI gate is a step in the existing runLinter job, not a new workflow — reuses the job/runner instead of provisioning a second one for a single fast command. Tradeoff: a formatting failure now also hides whether companion-check.test.mjs (the step after it) would have passed, since the job stops at the first failing step. Verified runLinter is actually enforced: it's a required status check on main via the repo's "Main - Force CI" ruleset, so this isn't advisory-only.
  6. npm i vs npm ci --ignore-scripts — left as-is (pre-existing in this job, typecheck.yaml uses the latter). Means the exact Prettier version resolved by npm i isn't strictly lockfile-pinned the way typecheck.yaml's is, though prettier ~3.9.0 in package.json plus the lockfile's pinned 3.9.8 bound the practical risk. Flagging in case that inconsistency is worth reconciling separately — didn't fix here since it's pre-existing job behavior, not something this change introduces.
  7. CI checks the whole tree, not just changed files — chosen deliberately: the point of this PR is that an unformatted merge should be impossible going forward, and a changed-files-only check would let drift back in via any PR whose diff doesn't touch the newly-drifted file. Means one future unformatted merge breaks every later PR's gate until someone reformats again (demonstrated by item Update README install instructions #2's third cost above); a one-line change to git diff --name-only scoping if that trade ever stops being worth it.

Changes

  • .prettierignore — excludes /core/ (root-anchored) since it's a separate repo/submodule with its own formatting and CI, plus two local-only trees that are excluded from git only via the unversioned .git/info/exclude (which Prettier doesn't read): .claude/ (this repo's worktree convention — found during the first rebase review) and integrationTests/cluster/qa-scratch/ (a local QA-exploration scratch dir — found during this round's rebase review). Without these a whole-tree format run from a checkout that has either directory silently recurses into it.
  • .github/workflows/lint-code.yaml — adds permissions: contents: read at the workflow level (this job runs PR-authored package.json scripts against the repo's write-scoped default token; matches the existing pattern in typecheck.yaml), and a new step npm run format -- --check (reuses the format script from package.json rather than a bare npx prettier --check ., so a future change to that script's flags/ignore-paths reaches CI automatically).
  • .git-blame-ignore-revs — new file, # Formatting Changes section per CONTRIBUTING.md's existing (previously unfulfilled) instruction, recording both formatting commits currently on this branch (the original baseline reformat and the cherryPickPatch.test.mjs follow-up below) so git blame on the touched files skips past them to the real authors. These SHAs shift on every rebase — see item Add CODEOWNERS file #3 above for the merge-method caveat and why that matters more now that there are two of them to keep in sync.
  • licensing/usageLicensing.ts — layout only: reflows an existing splice(...) call's arguments. No logic change.
  • unitTests/github/cherryPickPatch.test.mjs — layout only. This file landed on main after this branch's previous push (via Skip a release cherry-pick whose change is already on the release branch), unformatted; the Oct 10 rebase caught it via npx prettier --check . and reformatted it in its own commit, same as the original baseline reformat.

Note: CONTRIBUTING.md, scripts/patch-release.js, and security/keyCustody.ts were part of earlier states of this PR's reformat commit but have since dropped out of the diff entirely — each because main substantively rewrote or reformatted the same file itself (first two: Oct 2 rebase; security/keyCustody.ts: Oct 10 rebase, file now identical to main). This branch's formatting of their old content is moot. integrationTests/stress/largeClone.test.mjs hit the same situation on the Oct 10 rebase but as a real conflict rather than a clean drop: main had rewritten the test's actual logic (added an exact-count check at the first Available tick, not just at the end) since this branch's reformat commit, which had only reflowed the old logic's whitespace. Resolved by taking main's content entirely — the reformat commit made zero semantic changes to begin with, so there was nothing of this PR's to preserve, and main's version is itself already Prettier-clean.

Verification

Related PRs: 3 others independent
Complexity: easy

Origin — the dispatch brief this PR was written from

Bring harper-pro main to prettier-clean and keep it there: run the repo's prettier over the tree (respecting the existing ignore rules, which exclude the core submodule), commit the pure-format result as its own commit, and add a CI step that runs npx prettier --check . (or npm run format -- --check) so formatting drift fails a PR.

Acceptance

npx prettier --check . exits 0 on the PR branch; the format commit contains only whitespace/format changes (no semantic edits); a CI job fails on unformatted files and passes on the PR. Do not touch the core submodule.

Dispatch: task harper-pro-prettier-clean-and-check · queued by finding-triage/wave-19 · ran by claude/sonnet/xhigh · worker kzyp-xps-1

Review-Coverage: authored=claude; ran=codex,gemini; adjudicated=domain; declined=cursor-grok,cursor-composer,cursor-kimi,cursor-muse; rounds=10; full=4 @ b7c8431

Review-Attention: study ~11m (sensitive: lint-code.yaml, usageLicensing.ts; decisions: ignore-list-location, format-step-placement, whole-tree-reformat, blame-ignore-merge-method) @ b7c8431

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request consists entirely of code formatting and style adjustments across various integration tests, unit tests, scripts, and source files, aligning them with the project's formatting rules. There are no functional code changes. As there were no review comments provided, I have no additional feedback to offer.

@kriszyp
kriszyp marked this pull request as ready for review September 24, 2026 15:55
@kriszyp
kriszyp requested review from a team as code owners September 24, 2026 15:55

@dawsontoth dawsontoth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty

Comment thread .github/workflows/lint-code.yaml
@claude

claude Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@kriszyp
kriszyp force-pushed the fix/prettier-clean-main branch from 647d923 to 1b47912 Compare October 2, 2026 18:17
Comment thread .git-blame-ignore-revs Outdated
kriszyp and others added 9 commits October 9, 2026 21:59
npx prettier --check . currently errors on the core submodule's
deliberately-malformed test fixtures and warns on 27 unformatted
files in harper-pro's own tree. Add .prettierignore to exclude
core/ (it's a separate repo with its own formatting/CI), then run
prettier --write over the rest. Pure reformat, no semantic changes.

Dispatch-Task: harper-pro-prettier-clean-and-check
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWh88RGtbanyJqx6hB3b15
harper-pro had no format check in CI, so main drifted from
prettier-clean and npm run format:write rewrote ~20 unrelated
files for every contributor. Now that the tree is clean (previous
commit), fail the existing lint job on formatting drift.

Dispatch-Task: harper-pro-prettier-clean-and-check
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWh88RGtbanyJqx6hB3b15
- Anchor .prettierignore's core/ as /core/ so it can't silently
  match a future nested Pro directory of the same name.
- Route the CI check through npm run format -- --check instead of
  bare npx prettier --check ., so a future flag/ignore-path change
  to the format script reaches CI too.
- Add permissions: contents: read to lint-code.yaml (the job runs
  PR-authored package.json scripts against a write-scoped default
  token; matches typecheck.yaml's existing pattern).
- Drop the narrating comment restating what .prettierignore already
  says.

Dispatch-Task: harper-pro-prettier-clean-and-check
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWh88RGtbanyJqx6hB3b15
CONTRIBUTING.md already instructs recording formatting commits
here; the file just didn't exist yet. Also drop a stale
cross-reference from the permissions comment.

Dispatch-Task: harper-pro-prettier-clean-and-check
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWh88RGtbanyJqx6hB3b15
.claude/worktrees/ (this repo's own worktree convention) and the rest of
.claude/ are untracked local state, excluded only via .git/info/exclude.
Prettier reads .gitignore but not .git/info/exclude, so a whole-tree
format run from the main checkout was recursing into every worktree,
including each worktree's own nested core/ checkout and dist/ output.

Found by the pre-push review's domain adjudication on this PR's rebase.

Dispatch-Task: pr-maint-1ac41b4a39b4cea6189b4e615027add7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main added this file, not prettier-clean, since this branch last rebased.
Caught by npx prettier --check . after rebasing onto origin/main.

Dispatch-Task: pr-maint-1ac41b4a39b4cea6189b4e615027add7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rebasing onto main rewrote the formatting commit's SHA (3660c05 ->
d125334) and this branch gained a second formatting commit
(8d6b747, for a file that landed on main unformatted after the
original push). The blame-ignore file still pointed at the old,
now-unreachable SHA, which git/GitHub silently skip rather than error
on, so blame on the 19 reformatted files would have kept crediting
the formatting commit to its authors.

Caught by prepush review (codex + gemini + cursor-composer, domain
adjudication) on the rebased head.

Dispatch-Task: pr-maint-1ac41b4a39b4cea6189b4e615027add7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same bug class as the .claude/ fix: integrationTests/cluster/qa-scratch/
is excluded only via .git/info/exclude (local QA-exploration scratch
state), which Prettier doesn't read, so a whole-tree format:write from
the main checkout would recurse into it on any machine that has it.

Flagged by prepush review (harper-domain) on the rebased branch.

Dispatch-Task: pr-maint-1ac41b4a39b4cea6189b4e615027add7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Flagged by prepush review (codex/gemini/domain, all three) as repeating
the same per-clone-exclude rationale twice; one shared comment above
both entries says it once.

Dispatch-Task: pr-maint-1ac41b4a39b4cea6189b4e615027add7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kriszyp
kriszyp force-pushed the fix/prettier-clean-main branch from f7b9d34 to b7c8431 Compare October 10, 2026 04:33

This branch has not been deployed

No deployments
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.

2 participants