Skip to content

Commit ffec09d

Browse files
committed
Switch lint and CI to oxfmt and oxlint
1 parent cdfa3c5 commit ffec09d

8 files changed

Lines changed: 19 additions & 328 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@ concurrency:
1111
cancel-in-progress: ${{ github.event_name != 'push' }}
1212

1313
jobs:
14-
# Prettier, eslint, and typecheck share one runner: one checkout and one
15-
# install instead of three of each. Prettier and eslint still run un-cached
16-
# in CI: restored result caches can mark files clean against a stale tool
17-
# version or config, masking real failures. The --cache flags in the
18-
# package.json lint script remain for local speed.
14+
# oxfmt, oxlint, and typecheck share one runner: one checkout and one
15+
# install instead of three of each. Dummy job names prettier and eslint
16+
# stay for protect-main.
1917
static-analysis:
2018
runs-on: ubuntu-latest
2119
steps:
@@ -39,11 +37,11 @@ jobs:
3937
- name: Install dependencies
4038
run: bun install --frozen-lockfile
4139

42-
- name: Prettier
43-
run: bunx prettier --check .
40+
- name: oxfmt
41+
run: bunx oxfmt --check .
4442

45-
- name: ESLint
46-
run: bunx eslint .
43+
- name: oxlint
44+
run: bunx oxlint .
4745

4846
- name: Typecheck
4947
run: bun run typecheck

.prettierignore

Lines changed: 0 additions & 16 deletions
This file was deleted.

.prettierrc.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ When refactoring replaces an old path, delete the old one. No back-compat shims,
3434
- Bug fixes start with a failing test that reproduces the bug. Do not start by patching.
3535
- `tests/unit/` shared unit tests and helpers · co-located `src/**/*.test.ts` for module logic · `tests/fixtures/` fixture repos · `tests/integration/` reactor/permission harness. Planned: `tests/e2e/` (fixture-repo runs).
3636
- A test must not depend on another file having run, or on the default file order. It must pass under `bun test ./src ./tests ./evals ./scripts --randomize`. If a test mutates module-level state or calls `mock.module`, it must restore that state itself (`afterEach`/`afterAll`), not rely on the process happening to reset it. When capturing a module's real exports to restore later, shallow-copy them (`{ ...moduleNamespace }`) at capture time, whether the namespace came from `await import(path)` or a static `import * as ns from "path"` — Bun mutates the live namespace object in place when the module is mocked, so holding a bare reference to it (either form) silently turns into the mocked exports.
37-
- Never call `mock.module` directly. Bun runs every test file in one process, so a `mock.module` call without its own teardown stays installed for the rest of the run and silently replaces the real module for other files — producing failures in files the change never touched, with no obvious link to the cause and no signal from `tsc` or a per-file run (CL-6967). Use `withMockedModule`/`withMockedModuleDuring` from `tests/helpers/mock-module.ts`, which capture the real module and register their own restore. An eslint rule (`no-restricted-syntax` in `eslint.config.js`) rejects bare `mock.module` calls in `*.test.ts` files.
38-
- A test earns its place only if a real behavior change can fail it. Document copy, brand colors, marketing assets, and splash text are not behavior: assertions that pin an asset's literal wording, an exact palette hex/ANSI value, or rendered copy fail on copy/design edits and catch no regressions — assert the contract instead (parsing, formatting, ranges, aliases, invariants). Tests are code too: pinning a source file's own text is the same trap. This bar is a review and authorship rule, not an eslint shape match.
37+
- Never call `mock.module` directly. Bun runs every test file in one process, so a `mock.module` call without its own teardown stays installed for the rest of the run and silently replaces the real module for other files — producing failures in files the change never touched, with no obvious link to the cause and no signal from `tsc` or a per-file run (CL-6967). Use `withMockedModule`/`withMockedModuleDuring` from `tests/helpers/mock-module.ts`, which capture the real module and register their own restore. The oxlint plugin (`corbits/no-bare-mock-module` in `.oxlintrc.json` / `scripts/oxlint-plugin-corbits.js`) rejects bare `mock.module` calls in `*.test.ts` files.
38+
- A test earns its place only if a real behavior change can fail it. Document copy, brand colors, marketing assets, and splash text are not behavior: assertions that pin an asset's literal wording, an exact palette hex/ANSI value, or rendered copy fail on copy/design edits and catch no regressions — assert the contract instead (parsing, formatting, ranges, aliases, invariants). Tests are code too: pinning a source file's own text is the same trap. This bar is a review and authorship rule, not a linter shape match.
3939

4040
## Build & Validation
4141

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
5959

6060
### Changed
6161

62+
- oxfmt formats the tree and oxlint is the lint gate. Prettier and ESLint are
63+
gone. Dummy CI job names `prettier` and `eslint` stay for protect-main.
64+
Empty functions and non-null assertions are errors.
65+
6266
- Skywalker may spawn one successor with a changed brief after a failed or
6367
incomplete-report fleet worker. A parent-initiated interrupt
6468
(`stop_reason: interrupted`) is a resumable pause — `resume_agent` or

0 commit comments

Comments
 (0)