# Contributor handoff — facebook/react

> Canonical page: https://codevetter.com/unpack/react/agent-handoff

# Contributor handoff — facebook/react

Scanned commit 59aff3e18cb5b3a336c280bbfa57ec37999511b9 (2026-09-18). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Treat `/compiler/` and everything else as two separate projects with separate package managers, lockfiles, CI workflows and conventions — the root `CLAUDE.md` says so explicitly, and `compiler/CLAUDE.md` even documents Sapling (`sl`) rather than git for that subtree. Never run `jest` or `rollup` directly; use `yarn test` / `yarn flow` / `yarn linc` / `yarn prettier`, and let CI do builds. The single most important structural fact to internalise before editing is the fork/shim system: `ReactFiberConfig`, `ReactFeatureFlags` and the flight/fizz configs resolve differently under Rollup, Jest and Flow, so 'it works in one channel' is not a signal. Read the work loop, the root scheduler and the feature-flag file before touching reconciler behaviour, and read the relevant `docs/passes/` doc before touching a compiler pass.
- The repo is explicitly split: root `CLAUDE.md` scopes itself to 'All files outside `/compiler/`' and defers the compiler to its own instructions; `compiler/` has its own `package.json`, `yarn.lock`, `Cargo.toml` and CI workflows. — [CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/CLAUDE.md) [compiler/CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/CLAUDE.md) [compiler/package.json](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/package.json) [compiler/Cargo.toml](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/Cargo.toml)
- Read first, in order: `CLAUDE.md`, `packages/react-dom/src/client/ReactDOMRoot.js` (entry), `packages/react-reconciler/src/ReactFiberWorkLoop.js` (the engine), `packages/react-reconciler/src/ReactFiberRootScheduler.js` (when work runs), `packages/shared/ReactFeatureFlags.js` (what's on), and `scripts/rollup/forks.js` + `scripts/shared/inlinedHostConfigs.js` (how modules actually resolve). — [CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/CLAUDE.md) [packages/react-reconciler/src/ReactFiberWorkLoop.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react-reconciler/src/ReactFiberWorkLoop.js) [packages/react-reconciler/src/ReactFiberRootScheduler.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react-reconciler/src/ReactFiberRootScheduler.js) [scripts/rollup/forks.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/rollup/forks.js)
- The prescribed pre-commit gate is `/verify`: `yarn prettier` → `yarn linc` (stop on failure), then `/flow`, `/test` and `/test www` in parallel — mirroring the CI jobs, so passing it locally is a strong predictor of green CI. — [.claude/skills/verify/SKILL.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.claude/skills/verify/SKILL.md) [.github/workflows/runtime_build_and_test.yml#L118-L285](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.github/workflows/runtime_build_and_test.yml#L118-L285)
- Yarn 1 is mandatory (`packageManager: yarn@1.22.22`) and Node is pinned by `.nvmrc`, which every CI job consumes via `node-version-file: '.nvmrc'`. — [package.json#L163](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L163) [.nvmrc](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.nvmrc) [.github/workflows/runtime_build_and_test.yml#L54-L61](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.github/workflows/runtime_build_and_test.yml#L54-L61)
- Do not invoke Jest directly — the root `jest.testRegex` deliberately points at `scripts/jest/dont-run-jest-directly.js`; run `yarn test -r <channel> --env <env>` instead, and `yarn test-www` / `yarn test-stable` for the common channels. — [package.json#L119-L121](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L119-L121) [package.json#L138-L142](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L138-L142) [scripts/jest/jest-cli.js#L10-L50](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/jest/jest-cli.js#L10-L50)
- Do not build locally unless told to: root `CLAUDE.md` states 'Builds are handled by CI', and `yarn build` runs a multi-channel Rollup + Closure pipeline that also shells out to git and rewrites versions. — [CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/CLAUDE.md) [scripts/rollup/build-all-release-channels.js#L24-L180](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/rollup/build-all-release-channels.js#L24-L180)
- Adding a feature flag is a multi-file edit: the base `packages/shared/ReactFeatureFlags.js` plus each of the 13 forks under `packages/shared/forks/`, verified by `yarn flags` and the CI `flags` job. — [packages/shared/ReactFeatureFlags.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/shared/ReactFeatureFlags.js) [packages/shared/forks/ReactFeatureFlags.www.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/shared/forks/ReactFeatureFlags.www.js) [scripts/flags/flags.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/flags/flags.js) [.github/workflows/runtime_build_and_test.yml#L192-L215](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.github/workflows/runtime_build_and_test.yml#L192-L215)
- Adding a user-visible `throw` requires running `yarn extract-errors` and committing the new entry in `scripts/error-codes/codes.json`; the script greps the `build` directory, so it only works after a build exists. — [package.json#L136](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L136) [scripts/error-codes/extract-errors.js#L24-L40](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/error-codes/extract-errors.js#L24-L40) [.claude/skills/extract-errors/SKILL.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.claude/skills/extract-errors/SKILL.md)
- Tests that depend on a flag or channel must carry a `// @gate <expr>` pragma (supports `&&`, `!`, multiple gates); `FIXME`/`TODO` are reserved gate names that disable a test wholesale. — [scripts/jest/TestFlags.js#L1-L52](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/jest/TestFlags.js#L1-L52)
- Compiler work has its own loop: `yarn snap` to run fixtures, `yarn snap -p <pattern> -d` to dump per-pass HIR, `yarn snap -u` to update `.expect.md`, `yarn snap compile <path>` for arbitrary files, `yarn snap minimize <path>` to shrink a repro. — [compiler/CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/CLAUDE.md)
- Before implementing from a Rust-port plan doc, `compiler/CLAUDE.md` requires checking `git log --oneline --grep="<plan-name>"` and the plan's Remaining Work section; afterwards update the plan status, run `/compiler-verify`, and ensure `compiler/scripts/test-babel-ast.sh` passes. — [compiler/CLAUDE.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/CLAUDE.md) [compiler/docs/rust-port/rust-port-architecture.md](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/compiler/docs/rust-port/rust-port-architecture.md) [.github/workflows/compiler_rust.yml#L62-L68](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/.github/workflows/compiler_rust.yml#L62-L68)
- Trap: `packages/react-reconciler/src/ReactFiberConfig.js` throws on import by design. If a new test or script resolves it, the fix is registering the renderer in `scripts/jest/setupHostConfigs.js` / `inlinedHostConfigs.js`, not editing the shim. — [packages/react-reconciler/src/ReactFiberConfig.js#L10-L22](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react-reconciler/src/ReactFiberConfig.js#L10-L22) [scripts/jest/setupHostConfigs.js#L137-L220](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/jest/setupHostConfigs.js#L137-L220)
- Trap: `packages/react/src/` contains parallel client and server builds of the same package (`ReactClient.js`, `ReactServer.js`, `ReactServer.experimental.js`, `ReactServer.fb.js`, `ReactSharedInternalsClient.js` vs `…Server.js`) — an export added to one is not automatically present in the other. — [packages/react/src/ReactClient.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react/src/ReactClient.js) [packages/react/src/ReactServer.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react/src/ReactServer.js) [packages/react/src/ReactSharedInternalsClient.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react/src/ReactSharedInternalsClient.js) [packages/react/src/ReactSharedInternalsServer.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react/src/ReactSharedInternalsServer.js)
- Safe-to-edit boundaries: `fixtures/` are manual-test apps (only `fixtures/flight` has automated e2e), `scripts/` is developer tooling, and `packages/*/src/__tests__/` are tests. High-caution zones are `ReactFiberWorkLoop.js`, `ReactFiberCommitWork.js`, `ReactFiberHooks.js`, `ReactFizzServer.js`, `ReactFlightServer.js` and anything under `scripts/rollup/` or `scripts/release/`. (inferred) — [fixtures/dom/package.json](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/fixtures/dom/package.json) [fixtures/flight/playwright.config.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/fixtures/flight/playwright.config.js) [packages/react-reconciler/src/ReactFiberCommitWork.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/react-reconciler/src/ReactFiberCommitWork.js) [scripts/release/publish.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/release/publish.js)
- Flow is the type system for runtime code (`flow-bin@^0.317.0`, `postinstall` runs `scripts/flow/createFlowConfigs.js` to generate per-renderer configs) while the compiler and ESLint plugin are TypeScript — so `@flow` pragmas and `$FlowFixMe` suppressions are normal in `packages/` and out of place in `compiler/`. — [package.json#L82-L85](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L82-L85) [package.json#L137](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/package.json#L137) [scripts/flow/createFlowConfigs.js](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/scripts/flow/createFlowConfigs.js) [packages/eslint-plugin-react-hooks/src/index.ts](https://github.com/facebook/react/blob/59aff3e18cb5b3a336c280bbfa57ec37999511b9/packages/eslint-plugin-react-hooks/src/index.ts)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
