Uh oh!
There was an error while loading. Please reload this page.
chore: introduce Biome linter with CI gate (#415) - #1019
Conversation
Installs @biomejs/biome 2.5.4 (exact) and adds biome.jsonc: formatter (2-space, 100-col, single quotes, semicolons, trailing commas), linter starting from the recommended preset, VCS-aware file discovery, and Tailwind CSS 4 directive parsing for apps/desktop's renderer stylesheet. Adds `npm run lint` (biome lint .) and `npm run format` (biome format --write .) scripts, and wires `npm run lint` into the CI typecheck job right after `npm ci` for a fast-fail gate. Import-sorting/organize-imports assist actions are left disabled (assist.enabled: false) — that lands in a follow-up auto-fix PR per apache#415. 64 recommended lint rules had pre-existing violations on this tree and are disabled (each with its violation count as a comment) so `npm run lint` passes without touching any source file. Top offenders: noNonNullAssertion (1274), useTemplate (137), useExhaustiveDependencies (110), noAdjacentSpacesInRegex (84), noUnusedImports (74), noUnsafeOptionalChaining (74), noControlCharactersInRegex (67), noExplicitAny (60), noLabelWithoutControl (51). `npx biome format .` (check-only) reports 1299 of 1555 scanned files would be reformatted — deferred to the follow-up auto-fix PR, not applied here.
The gate is wired correctly (runs on push/PR to main, after Must fix: the 9 new Recommendation on the shape, worth reconsidering before this becomes the baseline. Measured against the full So the current shape enforces a lint gate that is green only because the bug-catchers are off, while the formatter is configured but never gated (zero consistency value). Consider inverting it:
|
…e#415) The local npm config points at a npmmirror.com mirror, which leaked 9 resolved URLs for @biomejs/* packages into package-lock.json; repin them to the canonical registry.npmjs.org tarball URLs.
…pache#415) Reshape the gate per PR apache#1019 review: correctness-first instead of tracking style debt. - cu-provider-matrix.test.mjs: remove the stale flat fixtureState duplicate key that silently overrode the windowId-keyed shape the test actually exercises (the masked bug noDuplicateObjectKeys catches). - Hand-fix all noUnsafeOptionalChaining sites (74) and the one noNonNullAssertedOptionalChain site across 12 test files: drop `?.` where presence is already asserted/constructed, extend the chain where undefined still fails the assertion identically, or use a non-null assertion in TS tests where presence is structural. - Re-enable noDuplicateObjectKeys, noUnsafeOptionalChaining, and noNonNullAssertedOptionalChain in the gate. - biome.jsonc: reorganize remaining off-rules into "dropped outright" (noNonNullAssertion, useTemplate, noExplicitAny — pure style, not tracked as debt) vs "deferred" (follow-up fix passes); useExhaustiveDependencies noted as a real bug-catcher needing per-case judgment. Verified: biome lint clean; test:scripts 91/91; runtime 1936 tests 0 fail; desktop 2542/2542; typecheck clean. headless 960/963 — the 2 failures (harbor-adapter opencode stop runner) reproduce identically on the unmodified baseline and pass in isolation; local-only flake.
UncertaintyDeterminesYou4ndMe
commented
Jul 15, 2026
Thanks for the review — both points addressed, plus measurement data that informs the formatter question. FixedLockfile registry ( Correctness-first reshape (
Verified locally: lint clean, Formatter: measurement first, then your callI measured auto-fix coverage on a throwaway worktree with all 64 rules re-enabled (2,441 baseline diagnostics):
Two findings worth knowing before anyone runs a real fix pass:
On your two options: I'd take the one-time format baseline + |
Astro-Han
commented
Jul 15, 2026
Thanks, the reshape is exactly right and CI is green. Two things before merge. Formatter: let's go with (b). Drop the formatter config (and the Linter shape: make it an explicit allowlist rather than Happy to merge once the formatter config is out and the linter is on the explicit allowlist. |
… formatter (apache#415) Per PR apache#1019 review, address the two pre-merge asks. Linter: invert from `recommended` minus a 64-rule disabled list to an explicit allowlist (`preset: "none"`) that turns on only the three correctness rules actually enforced — noUnsafeOptionalChaining, noDuplicateObjectKeys, noNonNullAssertedOptionalChain. Nothing re-enters the gate implicitly, so it can't silently drift from a correctness gate into a style gate, and the standing 64-rule debt list is gone. A comment fixes the admission bar: a rule joins only if it catches a defect (not a style preference) and the tree is zero-violation or hand-fixed first. Formatter: drop the formatter config and the `npm run format` script. `formatter.enabled: true` on main is picked up by editors' format-on-save and would leak the 1,299-file reformat piecemeal into unrelated PRs. It returns as one atomic follow-up PR (config + one-time baseline + a `biome format` check-mode gate + `.git-blame-ignore-revs`), timed when few PRs are open. Verified: `npm run lint` clean (exit 0, no deprecation notice); a probe file confirms all three rules fire (negative test), so the gate is not a silent no-op.
UncertaintyDeterminesYou4ndMe
commented
Jul 15, 2026
Both pre-merge asks done in Formatter removed. Dropped the formatter config and the Linter is now an explicit allowlist. Two verification notes:
Net diff of this commit: biome.jsonc −99/+32, package.json −1. CI re-running. |
Uh oh!
There was an error while loading. Please reload this page.
…che#415) Follow-up to apache#1019, which introduced the linter but deliberately left the formatter out. Restores the formatter config (2-space, 100-col, single quotes, semicolons, trailing commas — matching dominant existing style), adds `format` (write) / `format:check` scripts, and a `npm run format:check` CI step in the typecheck job. Formatter-scoped exclusions (all still fully linted): - apps/desktop/** and packages/ui/**: the UI surface's source-contract tests read .ts/.tsx source (desktop's own and packages/ui's) and regex-match exact single-line shapes; a whole-tree reformat broke 145 desktop-source assertions plus ~45 contracts introspecting packages/ui. UI-surface formatting lands as a follow-up once those contract tests are format-tolerant. - Byte-sensitive provenance artifacts (SOURCE.json is SHA-256'd and size-checked by scripts/prepare-cua-driver.mjs) and bundled-tools.json. The mechanical baseline reformat is the next commit; the check gate goes green only with both included.
…che#415) Follow-up to apache#1019, which introduced the linter but deliberately left the formatter out. Restores the formatter config (2-space, 100-col, single quotes, semicolons, trailing commas — matching dominant existing style), adds `format` (write) / `format:check` scripts, and a `npm run format:check` CI step in the typecheck job. Formatter-scoped exclusions (all still fully linted): - apps/desktop/** and packages/ui/**: the UI surface's source-contract tests read .ts/.tsx source (desktop's own and packages/ui's) and regex-match exact single-line shapes; a whole-tree reformat broke 145 desktop-source assertions plus ~45 contracts introspecting packages/ui. UI-surface formatting lands as a follow-up once those contract tests are format-tolerant. - Byte-sensitive provenance artifacts (SOURCE.json is SHA-256'd and size-checked by scripts/prepare-cua-driver.mjs) and bundled-tools.json. The mechanical baseline reformat is the next commit; the check gate goes green only with both included.
…che#415) Follow-up to apache#1019, which introduced the linter but deliberately left the formatter out. Restores the formatter config (2-space, 100-col, single quotes, semicolons, trailing commas — matching dominant existing style), adds `format` (write) / `format:check` scripts, and a `npm run format:check` CI step in the typecheck job. Formatter-scoped exclusions (all still fully linted): - apps/desktop/** and packages/ui/**: the UI surface's source-contract tests read .ts/.tsx source (desktop's own and packages/ui's) and regex-match exact single-line shapes; a whole-tree reformat broke 145 desktop-source assertions plus ~45 contracts introspecting packages/ui. UI-surface formatting lands as a follow-up once those contract tests are format-tolerant. - Byte-sensitive provenance artifacts (SOURCE.json is SHA-256'd and size-checked by scripts/prepare-cua-driver.mjs) and bundled-tools.json. The mechanical baseline reformat is the next commit; the check gate goes green only with both included.
…op) (#415) (#1122) * build(lint): re-enable Biome formatter with a check-mode CI gate (#415) Follow-up to #1019, which introduced the linter but deliberately left the formatter out. Restores the formatter config (2-space, 100-col, single quotes, semicolons, trailing commas — matching dominant existing style), adds `format` (write) / `format:check` scripts, and a `npm run format:check` CI step in the typecheck job. Formatter-scoped exclusions (all still fully linted): - apps/desktop/** and packages/ui/**: the UI surface's source-contract tests read .ts/.tsx source (desktop's own and packages/ui's) and regex-match exact single-line shapes; a whole-tree reformat broke 145 desktop-source assertions plus ~45 contracts introspecting packages/ui. UI-surface formatting lands as a follow-up once those contract tests are format-tolerant. - Byte-sensitive provenance artifacts (SOURCE.json is SHA-256'd and size-checked by scripts/prepare-cua-driver.mjs) and bundled-tools.json. The mechanical baseline reformat is the next commit; the check gate goes green only with both included. * style: apply Biome format baseline outside the UI surface (#415) Regenerated on top of current main (the previous baseline commit was 90 commits stale and conflicting; a whole-repo mechanical reformat is rebased by re-running the formatter, not by resolving 660 files of textual conflicts). Same scope as before: biome.json excludes the apps/desktop UI surface. Two adjustments the reformat itself required: a @ts-expect-error in proxy-test.ts moved onto the property line it suppresses (the reformat split the fetch call, displacing the directive), and a second formatter pass over two files where Biome's first pass is not idempotent. * chore: add .git-blame-ignore-revs scaffold for the format baseline (#415) * test(runtime): make RunTracePhase contract regex layout-tolerant (#415) --------- Co-authored-by: 陆逊 <jiaxiong.liu@longbridge-inc.com>
Closes part of #415 (config + scripts + CI gate; the full-repo auto-fix is a dedicated follow-up PR per the issue's own sequencing).
What
@biomejs/biome2.5.4 (exact-pinned, root devDependency).biome.jsonc: formatter matched to the existing dominant style (2-space, 100-col, single quotes, semicolons, trailing commas), linter from therecommendedpreset, VCS-aware file discovery (useIgnoreFile), and Tailwind CSS 4 directive parsing (the desktop renderer stylesheet uses@import/@source, which the default CSS parser rejects).npm run lint(biome lint .) andnpm run format(biome format --write .).npm run lintadded to thetypecheckjob right afternpm ci— fast-fail, needs no build.Zero source diffs, by design
This PR touches exactly 4 files:
package.json,package-lock.json,biome.jsonc,.github/workflows/ci.yml. No source file is reformatted or lint-fixed, so it can't conflict with the currently open PRs.To make the gate pass on the current tree, 64 recommended rules with pre-existing violations are disabled, each annotated in
biome.jsoncwith its violation count. Top offenders:noNonNullAssertion(1274),useTemplate(137),useExhaustiveDependencies(110),noAdjacentSpacesInRegex(84),noUnusedImports(74),noUnsafeOptionalChaining(74),noExplicitAny(60). The gate still enforces everything else in the recommended preset from day one, and locks in a ratchet: new violations of the enabled rules fail CI.biome format .(check-only) reports 1299/1555 files would be reformatted — deferred.Follow-up (next PR, on request)
noDuplicateObjectKeys,noUnsafeOptionalChaining, …).Verification
npm run lint→ exit 0 (Checked 1583 files in ~0.5s).npm run typecheckon this branch is unchanged from its merge-base behavior (verified by stash/rerun); the CI job builds before typechecking as before.