Skip to content

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.

LocationRole today
apps/agentpants/src-nuxt/eslint.config.mjswithNuxt(prettierConfig), no ignores
apps/legacy-polish/src-nuxt/eslint.config.mjsignores 2 generated paths, + prettier
apps/ontological-legacy/src-nuxt/eslint.config.mjs44 lines: 3 generated ignores, a no-restricted-imports fence on @tauri-apps/*, the pages multi-word rule, + prettier
apps/pumice/src-nuxt/eslint.config.mjsstorybook plugin + 2 generated ignores, NO prettier config
apps/zoo/src-nuxt/eslint.config.mjsbare withNuxt(), NO prettier config
solutions/ontological/desktop/src-nuxt/eslint.config.mjs1 generated ignore + a vue rule, NO prettier config
solutions/augmented/apps/augmented_web/eslint.config.mjspages multi-word rule only, NO prettier config
solutions/augmented/apps/vimit_prototype/eslint.config.mjsbare withNuxt(), NO prettier config
solutions/augmented/apps/learn_web/eslint.config.mjsimports a shared ignore list that does not exist — broken, see T-RREG-lint-configs-that-do-nothing
apps/pumice/src-nuxt/.oxlintrc.jsonno-console/no-debugger + ignore patterns; the other three apps copy this block

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.

  1. 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, and vue/multi-word-component-names: off for pages.
  2. Create packages/ts/eslint-config exporting that array, with the same internal-package shape the tsconfig and prettier packages use.
  3. Adopt it app by app, verifying bun run lint before and after each. Expect findings in the six apps that gain eslint-config-prettier — that is the drift being closed, and it may take fixes.
  4. Move the oxlint rules to a root .oxlintrc.json; delete the per-app copies, keeping only genuinely app-specific ignorePatterns where they differ.
  5. Point learn_web at the shared ignores, closing the import it has been reaching for.
LocationKindChange
packages/ts/eslint-config/newthe shared flat-config layer
.oxlintrc.jsonnewone oxlint rules block for the repo
apps/pumice/src-nuxt/eslint.config.mjsmodifyappend the shared layer; keep the storybook plugin
apps/zoo/src-nuxt/eslint.config.mjsmodifyappend the shared layer
solutions/ontological/desktop/src-nuxt/eslint.config.mjsmodifyappend the shared layer
solutions/augmented/apps/modifythe three augmented app configs append the shared layer
apps/pumice/src-nuxt/.oxlintrc.jsondeletesuperseded by the root config
  • 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.json governs oxlint; no per-app copy of the rules block remains.
  • AC-3: bun run lint exits 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 a packages/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.
  • eslint for the library tier. withNuxt does 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 lint scripts themselves. This task ships the config; the manifests that invoke it belong to the two Layer A tasks.
  • Replacing eslint or adopting biome.
  • T-RREG-lint-configs-that-do-nothing shipped first and left learn_web with an inline ignores stub plus a note pointing here. This task replaces that stub with the shared list, which is the import learn_web was reaching for all along.

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.


← Back to Tasks