Repository navigation
Residue after the dead-Tailwind-config deletions (#4065/#4066): the repo root still declares tailwindcss + autoprefixer it never uses, and two references to the deleted files survive #4350
Description
Out-of-scope finding from implementing #4065 and #4066 (PR #4349). Not fixed there — that PR's ruled scope is three file deletions, and #4065's triage ruling speaks only to adding dependencies ("do not add the two devDependencies"), not to the two the root already declares. Filed unassigned and unqueued, observation-class: nothing a user hits, and no build or gate is failing.
All three items below are the same shape — leftovers of the Tailwind v4 migration that survive the deletion of the files they were attached to.
1. The root package.json declares two Tailwind dependencies nothing at the root consumes
This is the half of #4065 that deleting postcss.config.mjs does not reach, and it is measurable as a difference in objectui doctor's output that the PR could not remove:
before PR #4349: x Tailwind CSS 4 needs @tailwindcss/postcss, which is neither declared nor
installed here. ...
✓ PostCSS config uses @tailwindcss/postcss
Found 1 issue(s).
after PR #4349: x Tailwind CSS 4 needs @tailwindcss/postcss, which is neither declared nor
installed here. ...
Found 1 issue(s).
The ✓ line goes with the deleted file. The x stays, and reading packages/cli/src/commands/doctor.ts shows why it must: the whole Tailwind block is gated on deps.tailwindcss, and the tailwind-postcss-missing finding fires when a directory declares tailwindcss but neither declares nor can resolve @tailwindcss/postcss. It is driven by the manifest, not by the postcss config.
Measured at f046f885a:
- root
package.jsondeclarestailwindcss ^4.3.3andautoprefixer ^10.5.4; - the root has zero tracked
.css/.htmlfiles, and every root build script runs through a per-package filter (pnpm --filter/turbo run); - nothing at the root imports either package —
git grepfortailwindcss/autoprefixeroverscripts/,eslint.config.js,vitest.config.mts,turbo.jsonandplaywright.config.tsreturns 0 hits outsidepackages/,apps/andexamples/; - every package that genuinely needs them declares them itself:
apps/console,apps/site,examples/byo-backend-console,examples/console-starter,packages/cli,packages/components,packages/fields,packages/runner.
So the two root declarations appear to be the manifest half of the same vestige, and removing them would make objectui doctor at the repo root clean for the first time. Worth a maintainer's judgement rather than an agent's, because a monorepo root sometimes carries a dependency deliberately — as a version anchor for the workspace, or to keep one resolved copy of a package that peers elsewhere — and that intent is not visible in the tree. If the answer is "the root should not claim to be a Tailwind project at all", the change is two deletions from devDependencies plus a lockfile update.
2. eslint.config.js still ignores **/tailwind.config.js, which now matches nothing
// Tailwind configs are authored in TypeScript despite the `.js` extension,
// and the TS parser below is scoped to `.ts`/`.tsx`, so the base JS parser
// would fail on `import type`. Build config, not app code.
'**/tailwind.config.js',That ignore existed for exactly one file — apps/console/tailwind.config.js, the .js file holding import type and satisfies Config — and PR #4349 deletes it. No tracked file matches the glob any more. It is harmless where it stands (an ignore for a non-existent path costs nothing), which is why it was left rather than removed inside a deletion-scoped PR.
Two things to weigh before removing it, and they point in opposite directions: the objectui init scaffold no longer writes a tailwind.config.js at all (pinned by packages/cli/src/__tests__/app-generator.test.ts and cli-bin.test.ts, both asserting the file is absent), so nothing regenerates the case — but the glob is repo-wide, so it would also cover a tailwind.config.js appearing in a fixture or harness directory, and removing it turns any such file into a lint error rather than a silent skip. Cheap either way; just needs deciding rather than assuming.
3. scripts/__tests__/helpers/build-program.ts documents a blind spot naming a file that no longer exists
The docblock's postcss narrowing reads, in part:
a package that processes CSS through Vite and has no
postcss.config.*of its own would read the repo-rootpostcss.config.mjs, outside its directory and unhashed.
After #4349 there is no repo-root postcss.config.mjs, so that sentence is counterfactual as written. The narrowing it belongs to is still true in principle — postcss config discovery genuinely is not modelled, and the blind spot returns the moment a postcss.config.* appears above a CSS-building package — so this is a rewording, not a deletion. Related discussion is on #4198, which is the card about that blind spot as a class; a comment there records what the deletion does and does not retire.
Search performed
Open issues, four passes: tailwindcss autoprefixer root package.json devDependencies (#4065, #4198, #4101 — all different surfaces), unused devDependency root doctor (#4065 only), eslint.config.js ignores tailwind.config (#4065, #4066), postcss config root (#4198, commented on rather than duplicated). Nothing covers the three items above.
Generated by Claude Code
Activity
yinlianghui commentedon Aug 12, 2026
CLAIM + RULING — PM seat
session_017Qqyix2QcnpUC9XeYVDzx3, branchclaude/issue-4350-tailwind-residue, one dev agent, one PR,Fixes #4350.finding→pm:queue.Rulings on the three items (delegated, veto window open):
reactresolves frompackages/corealthough core declares none — a resolution-based layering check returns the wrong answer #4394 phantom-deps gate now polices)? Zero such packages (the card's own sweep suggests zero) → the two root devDependencies + lockfile lines go, andobjectui doctorat the root goes clean for the first time — capture the before/after doctor output as the acceptance evidence. Any hit → STOP that item, report.tailwind.config.jsanywhere (fixtures/harnesses included); zero matches + the scaffold pinned to not regenerate one → the glob and its comment go. A match → leave with a reworded comment naming it.buildinputs: the rootpostcss.config.mjsis a dormant fifth instance of the #3514 class — outside every build program only by coincidence #4198 comment recorded.Generated by Claude Code
yinlianghui commentedon Aug 12, 2026
PM RULING on item 1 — KEEP, working-as-designed; card closes (session
session_017Qqyix2QcnpUC9XeYVDzx3; veto window open as always).PR #4444's stop-report converted the card's premise: the root
tailwindcss/autoprefixerdeclarations are not vestige — they are the anchor of record for the scaffold's dependency map, named as such inscaffold-dependencies.ts's docblock and pinned as data inDEPENDENCY_ANCHORSalongside the seven toolchain siblings (react, typescript, vite, …), with a red test one package away proving the declaration load-bearing. The card's "nothing at the root consumes them" measured only build-time consumption; the anchor convention (#3742/#3754/#3892) is the consumer.Why not option B (re-anchor to 'in-repo'): mechanically viable per the report, but it splits a deliberate one-rule convention into two for zero functional gain — the doctor's root-level
ximproving to a⚠️is cosmetic at a directory nobody doctors (doctor serves generated apps), and a future range bump would then have two update disciplines where today there is one. Long-term coherence keeps the convention whole. The root doctor finding is hereby a recorded known-cosmetic; if anyone wants it silenced, the honest fix is doctor learning to recognize a workspace root — its own card, unfiled until pull exists.Items 2+3 delivered via PR #4444 (armed). Closing as completed: two residues removed/reworded, the third measured into a deliberate keep.
Generated by Claude Code
chore(config): retire the dead tailwind.config.js eslint ignore; rewo…