`npm run knip` now runs a second, --production pass, which asks whether the
code that ships uses an export, not just whether anything does. Of the 47
exports only tests reached:
- 34 are exported for their test and say so with @internal, naming the test.
- 11 were module-private names with a stray `export`. Two of them were not
used at all and are deleted.
- The unused alreadyReported re-export is gone.
Test kits, the e2e suite and the two build-tooling modules are excluded from
the production project, each named in knip.jsonc.
noUncheckedIndexedAccess is now on for the node and e2e tsconfigs too (0
errors), matching the app project. tsconfig.node.json listed a
tailwind.config.js that has not existed since Tailwind 4. That entry is now
playwright.config.ts, which the typed lint finds through this project.
Three strictness flags that the codebase already satisfies (0 errors each):
- noFallthroughCasesInSwitch on src + e2e — a missing `break` is now a type error.
- noUnusedLocals + noUnusedParameters on the e2e project, so it matches src and node
and dead spec scaffolding can't accumulate (it was the one project without them).
- allowJs + checkJs on the node project, pulling tailwind.config.js and
postcss.config.js under the type checker (the last hole in C-4.5) — a real type
error in either is now caught (verified: `content: 123` fails; Config stays
permissive on plugin keys by design).
noUncheckedIndexedAccess is NOT here — it has 98 call-site fixes and lands as its own
reviewable sub-sprint (S3b).
Locks the five flows the refactor must not break (feed, channel, player,
settings, nav) so later sprints can prove they changed nothing. Adds a thin
data-testid layer and a dedicated seeded non-demo account; the suite runs on
the baked :8080 stack (authoritative) or :5173. No product-behaviour change.