- Single object arg (`DiagnoseProjectsInput`) instead of two positional args
- "Projects" vocabulary matching the rest of the codebase
- Per-project scan options (`deadCode`, `lint`, etc.) flat on the entry
instead of nested in `config.deadCode`
- `config` on a project entry means `ReactDoctorConfig` directly
- Discriminated union `ProjectResult` (`ok: true | false`) instead of
separate `modules` + `errors` arrays
Completes P4 of the cleanup plan.
The fixtures/ directory (basic-react, monorepo-with-root-react,
nextjs-app, pnpm-catalog-workspace, ..., 14 project shapes + the
.oxlintignore stub) move to packages/core/tests/fixtures/, its
canonical home — project-shape fixtures are core's territory under
AGENTS.md, and the previous packages/react-doctor/tests/fixtures/
location forced packages/api/tests/diagnose.test.ts to reach
across packages with '../../react-doctor/tests/fixtures'.
Seven more core-internal tests move to packages/core/tests/:
- discover-project.test.ts (1092 lines — biggest remaining
architectural-drift test file)
- find-monorepo-root.test.ts
- read-ignore-file.test.ts
- can-oxlint-extend-config.test.ts
- check-dead-code.test.ts
- merge-and-filter-diagnostics.test.ts (inlined the 5-line writeFile
+ buildDiagnostic helpers from regressions/_helpers.ts to avoid
coupling core tests to the regressions harness)
Consumers that stay in react-doctor/tests/ (CLI / end-to-end /
regression-style tests) update their FIXTURES_DIRECTORY constant
to point at the new core/tests/fixtures location:
- packages/api/tests/diagnose.test.ts
- packages/react-doctor/tests/inspect.test.ts
- packages/react-doctor/tests/inspect-surface-filter.test.ts (this
tests the CLI inspect() wrapper, not the core orchestrator, so
it stays in react-doctor/tests/)
- packages/react-doctor/tests/namespace-hooks.test.ts
- packages/react-doctor/tests/regressions/rn-package-scoping.test.ts
- packages/react-doctor/tests/run-oxlint/_helpers.ts
After this final batch:
- 21 core-internal test files have moved from react-doctor/tests/
to packages/core/tests/ (was 14 in the previous batches).
- Core has 346 tests across 35 files (was 247 / 29).
- react-doctor has 1317 tests across 103 files.
- Total tests unchanged (1670).
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Standing up packages/api/ as the home of the programmatic public
API. Moves diagnose() into it as a thin Effect.runPromise shell
around #412's runInspect orchestrator, with tagged-error translation
back to legacy thrown classes (NoReactDependencyError /
ProjectNotFoundError / AmbiguousProjectError) for backwards compat.
inspect() stays in react-doctor/src/ for now (CLI rendering coupled
in). PR 6 (cli package) moves it.
## Files
- packages/api/ (private workspace package)
- src/diagnose.ts: pre-resolves rootDir redirect + resolveDiagnoseTarget,
then runInspect, translates tagged failures, returns DiagnoseResult.
- src/index.ts: re-exports diagnose + public types + legacy errors.
- tests/diagnose.test.ts: 4 tests — happy path, NoReactDependency,
ProjectNotFound, elapsedMilliseconds positive.
- packages/react-doctor/src/index.ts: deletes ~120-line local diagnose,
re-exports from @react-doctor/api.
- packages/core/src/run-inspect.ts: rejects projects without React via
tagged NoReactDependency (used to happen in the legacy diagnose).
## Validation
- pnpm typecheck (12/12)
- pnpm test — 123 files / 1485 pass / 3 skipped
- pnpm lint, format:check, build, smoke:json-report — all green
Co-authored-by: Cursor <cursoragent@cursor.com>