T-BBYP-shared-eslint-oxlint-layer
State: closed/done · Impact: medium · Complexity: medium
Nine eslint configs, each a withNuxt() wrapper, disagree about things they
should not. eslint-config-prettier is applied in three of them and missing
from six — including pumice, zoo and sdf, all of which run prettier, so
eslint and prettier can fight over the same file. Five hand-list their own
generated-output ignores. Four oxlint configs share one rules block by copy.
learn_web’s config already tries to require a shared ignore list, which
tells you someone intended this and it never landed.
| Location | Role today |
|---|---|
apps/agentpants/src-nuxt/eslint.config.mjs | withNuxt(prettierConfig), no ignores |
apps/legacy-polish/src-nuxt/eslint.config.mjs | ignores 2 generated paths, + prettier |
apps/ontological-legacy/src-nuxt/eslint.config.mjs | 44 lines: 3 generated ignores, a no-restricted-imports fence on @tauri-apps/*, the pages multi-word rule, + prettier |
apps/pumice/src-nuxt/eslint.config.mjs | storybook plugin + 2 generated ignores, NO prettier config |
apps/zoo/src-nuxt/eslint.config.mjs | bare withNuxt(), NO prettier config |
solutions/ontological/desktop/src-nuxt/eslint.config.mjs | 1 generated ignore + a vue rule, NO prettier config |
solutions/augmented/apps/augmented_web/eslint.config.mjs | pages multi-word rule only, NO prettier config |
solutions/augmented/apps/vimit_prototype/eslint.config.mjs | bare withNuxt(), NO prettier config |
solutions/augmented/apps/learn_web/eslint.config.mjs | imports a shared ignore list that does not exist — broken, see T-RREG-lint-configs-that-do-nothing |
apps/pumice/src-nuxt/.oxlintrc.json | no-console/no-debugger + ignore patterns; the other three apps copy this block |
Proposed
Section titled “Proposed”packages/ts/eslint-config → @sksizer/eslint-config, exporting the flat-config
array an app appends to its withNuxt(...) call: the generated-output ignores,
eslint-config-prettier, and the filesystem-routing rule relaxation Nuxt pages
need. Each app keeps only what is genuinely its own — pumice’s storybook
plugin, ontological-legacy’s Tauri import fence, and each app’s own generated
paths where they differ.
A single .oxlintrc.json at the repo root replaces the four copies, since
oxlint resolves its config by walking up. That walk is also what gives the
library tier its lint: a package declaring lint: oxlint . resolves the same
root config with no config of its own, which is how the ~40 libraries that have
no lint today get one. Those scripts are added by
T-076A-the-script-vocabulary-lands-in-packages-apps-and-sites and
T-9FH9-the-script-vocabulary-lands-across-solutions; this task supplies the
config they resolve against.
The Nuxt-generated half stays per-app and untouched: withNuxt reads
./.nuxt/eslint.config.mjs, which only that app’s build produces.
Approach
Section titled “Approach”- Read all nine and separate what is shared from what is genuinely per-app.
The shared candidates are:
eslint-config-prettier, the generated-directory ignore patterns, andvue/multi-word-component-names: offfor pages. - Create
packages/ts/eslint-configexporting that array, with the same internal-package shape the tsconfig and prettier packages use. - Adopt it app by app, verifying
bun run lintbefore and after each. Expect findings in the six apps that gaineslint-config-prettier— that is the drift being closed, and it may take fixes. - Move the oxlint rules to a root
.oxlintrc.json; delete the per-app copies, keeping only genuinely app-specificignorePatternswhere they differ. - Point
learn_webat the shared ignores, closing the import it has been reaching for.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
packages/ts/eslint-config/ | new | the shared flat-config layer |
.oxlintrc.json | new | one oxlint rules block for the repo |
apps/pumice/src-nuxt/eslint.config.mjs | modify | append the shared layer; keep the storybook plugin |
apps/zoo/src-nuxt/eslint.config.mjs | modify | append the shared layer |
solutions/ontological/desktop/src-nuxt/eslint.config.mjs | modify | append the shared layer |
solutions/augmented/apps/ | modify | the three augmented app configs append the shared layer |
apps/pumice/src-nuxt/.oxlintrc.json | delete | superseded by the root config |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: All nine apps apply
eslint-config-prettier, where six do not today — verifiable by asserting no eslint rule reports on a prettier-formatted file. - AC-2: One
.oxlintrc.jsongoverns oxlint; no per-app copy of the rules block remains. - AC-3:
bun run lintexits 0 in every app that has the script. - AC-4:
learn_web’s config imports the shared ignores rather than carrying the inline stub T-RREG-lint-configs-that-do-nothing left. - AC-5:
oxlint .run from apackages/ts/*directory that has no config of its own resolves the root.oxlintrc.json— proven by a rule in that file, not in oxlint’s defaults, reporting on a probe file.
Out of scope
Section titled “Out of scope”- eslint for the library tier.
withNuxtdoes not apply to a plain TypeScript package, and a second flat config for libraries is a larger question. The libraries are covered by oxlint through the root config instead — that decision is recorded in M-3MGB. - The
lintscripts themselves. This task ships the config; the manifests that invoke it belong to the two Layer A tasks. - Replacing eslint or adopting biome.
Dependencies
Section titled “Dependencies”- T-RREG-lint-configs-that-do-nothing shipped first and left
learn_webwith an inlineignoresstub plus a note pointing here. This task replaces that stub with the shared list, which is the importlearn_webwas reaching for all along.
Discovery context
Section titled “Discovery context”Scoped out of the original shared-config work (#1644) as weaker than the tsconfig and prettier cases, then pulled back in deliberately. The eslint-config-prettier gap — three of nine — is the concrete drift that justifies it.