| type | Reference | |||||
|---|---|---|---|---|---|---|
| title | Agent command policy | |||||
| description | Canonical allowlist for agent shell commands — install, prepare, validation, and e2e. Supersedes improvised diagnostics. | |||||
| tags |
|
|||||
| timestamp | 2026-07-26 00:00:00 UTC |
Single source for which shell commands agents may run in this repo. E2e is a subset of this policy; running e2e § agent rule adds e2e-specific prohibitions.
If a command is not listed here (or linked from here as canonical), do not run it — including “diagnostic probes” suggested by log output, package READMEs, or Yarn CLI help.
- Run only commands in the registry below (repo root unless noted).
yarn/yarn lerna:preparemust finish before anything else — see prepare must finish first. Do not parallelize install/prepare with e2e, Metro, builds, or other shell commands.- Before any native
:build: rootyarnexit 0 and patched fmt ≥ 12.1.0 — install / patch / fmt gate. Do not invent Podfile/fmt workarounds. - When a canonical command fails: read the full output, fix product code (or re-run root
yarnfor a patch miss), re-run the same command. Do not switch invocation style. - Do not infer alternate commands from error strings (
command not found: genversion,Couldn't find a script named "jet", etc.) — see known traps. - Subagents (Task, explore, orchestrator): same rule — paste the handoff block into every RNFB task prompt.
| Intent | Command | Never use instead |
|---|---|---|
| Install / refresh deps | yarn (repo root) |
yarn workspace …, npm install, npm install in a package, yarn install / yarn in tests/ alone for root deps, skipping root yarn before e2e/build |
Transpile lib/** → dist/module/** (all packages) |
yarn lerna:prepare |
yarn workspace @react-native-firebase/* prepare, cd packages/<pkg> && yarn prepare, cd packages/<pkg> && yarn run build |
| Transpile one package | yarn lerna run prepare --scope @react-native-firebase/<pkg> |
yarn workspace @react-native-firebase/<pkg> prepare |
After packages/*/lib/** edits (Metro serves dist/module/**) |
yarn lerna:prepare; Metro restart when already running (running e2e § prepare completion gate) — platform :build only when running e2e § Rules #3 requires native/codegen/instrumentation, not for JS alone |
ad-hoc bob, babel, or package-scoped prepare |
| TS/JS validation sequence | validation checklist | ad-hoc tsc in package dirs unless listed there |
| JS lint (implementation / review gate) | yarn lint:js, yarn lint:js --fix |
package-scoped eslint, npx eslint |
| Android Java format / lint | yarn lint:android |
yarn google-java-format, bare google-java-format, google-java-format -i, npx google-java-format, any invented format script |
| Docs lint (when docs in diff) | yarn lint:markdown, yarn lint:spellcheck |
ad-hoc prettier/eslint on single files |
| Android JVM unit tests | yarn tests:android:unit |
ad-hoc ./gradlew … outside this yarn script; bare Robolectric/JUnit IDE-only as the agent gate |
| Android merged Jacoco (unit + e2e) | yarn tests:android:post-e2e-coverage (after e2e); yarn tests:android:test:jacoco-report when regenerating the merge report |
./gradlew jacocoAndroidTestReport as Codecov path; inventing other jacoco yarn scripts |
| E2e + coverage | running e2e — only yarn tests:* |
jet, npx jet, yarn jet, detox test, bare detox, cd tests && …, direct Metro/emulator starts |
| iOS Detox framework cache rebuild | yarn tests:ios:detox-framework-cache:rebuild |
cd tests && yarn detox clean-framework-cache, cd tests && yarn detox build-framework-cache, bare detox … |
Host pre-flight (before each :test-cover) |
running e2e § host-clear probes | pgrep, polling :8090, spawn probes of Jet/Detox |
yarn lerna:prepare runs each package's prepare script (build → compile via react-native-builder-bob). That is what produces dist/module/** consumed by Metro in debug e2e — only **release** builds pre-bundle/embed JS (running e2e § Rules #3).
yarn compile(package script) is not a standalone agent entrypoint — it is invoked insidepreparevia lerna. Do not runcd packages/<pkg> && yarn compilefor handoff unless validation checklist explicitly adds an exception (none today).yarnat repo root runspostinstallDev→yarn prepare && yarn lerna:prepare; a fresh install already transpiles. Re-runyarn lerna:prepareafterlib/**edits without reinstalling.
yarn, yarn lerna:prepare, and yarn lerna run prepare --scope … are blocking foreground commands. Wait for the shell to return exit code 0 before starting any other command — including in the same agent turn via parallel tool calls.
| Do not start until prepare exits 0 | Why |
|---|---|
yarn tests:* (e2e, packager, build) |
Metro (debug JS) reads dist/module/**, not lib/\*\* — partial prepare → missing modules, stale bundles |
yarn tests:packager:jet-reset-cache |
Reset after prepare, not during it |
yarn tsc:compile, Jest, compare:types |
May read transpiled output or assume dist/ is current |
Another yarn / scoped prepare |
Overlapping Nx/Lerna runs race on dist/ |
Agent rule: one prepare invocation per message batch; wait for completion; then run the next step (Metro restart if needed → pre-flight → :test-cover). Running e2e § prepare completion gate is the e2e-side mirror of this rule.
Symptoms when violated: Cannot find module '…/dist/module/…', Metro 500 on bundle, e2e failures before tests run, or green Metro /status while the app loads a half-written dist/.
Canonical owner for install + patch freshness before Detox native builds. E2e docs link here — do not restate this procedure elsewhere.
Before any yarn tests:ios:build, yarn tests:android:build, or other Detox native build path:
- Root
yarnMUST have run and exited 0 in this checkout. Required on a fresh checkout, after deletingnode_modules, after pulling patch changes, and whenever patches may be stale. Do not start native:builduntil that install finished successfully. - Root
yarnapplies.yarn/patches(jet, detox, mocha-remote) and workspacepatch-packagepatches, includingtests/patches/react-native+0.78.3.patch(bumps React Native's fmt pin to 12.1.0).testsprepareispatch-packageand must not be Nx-cache-skipped (MonoTool-AD-12). - Verify the patched React Native fmt podspec reports version ≥ 12.1.0 (Xcode 26 / Apple Clang 21-safe floor for this pin). Yarn exit 0 alone is not sufficient — always run the check below before native
:build(a prepare cache-skip historically left fmt at 11.0.2 despite a green install):
rg 'spec\.version|:tag' tests/node_modules/react-native/third-party-podspecs/fmt.podspecExpect 12.1.0 (or higher) on both spec.version and :tag.
- If fmt is still 11.0.2 (or anything < 12.1.0): STOP. Re-run root
yarn/ fix patch application (including Nxtests:preparecache policy — MonoTool-AD-12). Do not invent Podfilepost_installfmt hacks,FMT_USE_CONSTEVAL/base.hpatches, c++17-for-fmt-only, or web-search workarounds — the durable fix is the existing patch applied on install.
Symptoms when violated: Apple Clang 21 consteval errors compiling unpatched fmt 11.0.2; agents inventing Podfile/fmt workarounds instead of re-running root yarn / fixing prepare cache policy.
- Re-run from repo root:
yarnoryarn lerna:prepare(full log — do not truncate). - Note the first Nx/Lerna project that failed (e.g.
@react-native-firebase/functions:prepare). - Fix product code in that package (TypeScript errors, missing exports, etc.).
- Re-run
yarn lerna:prepare— same command, same cwd. - Do not “verify tooling” with
yarn workspace … prepare,yarn bin …, or package-scopedyarn run build— Yarn 4 uses different PATH for those invocations (genversion trap).
| Command | Why |
|---|---|
yarn workspace @react-native-firebase/* prepare (and variants) |
Not canonical; breaks root devDependency binary resolution |
cd packages/<pkg> && yarn prepare / yarn run build |
Same trap; not the postinstall / lerna code path |
yarn google-java-format, bare google-java-format, npx google-java-format, google-java-format -i |
Invented format entrypoints — only yarn lint:android |
npm install (any cwd) / yarn / yarn install only in tests/ for monorepo deps |
Root yarn applies patches and workspace links; tests-only install is insufficient |
Ad-hoc ./gradlew … outside allowlisted yarn scripts (tests:android:unit, tests:android:build, tests:android:post-e2e-coverage, tests:android:test:jacoco-report, etc.) |
Wrong task / cwd / report path; invents CI that does not match Codecov |
yarn jet, npx jet, cd tests && yarn jet … |
E2e agent rule |
detox test, bare detox, cd tests && detox … |
E2e agent rule |
| Ad-hoc Metro / emulator start | Use yarn tests:packager:jet, yarn tests:emulator:start |
| Spawn / PATH probes to “test” Jet or genversion | Log triage only; fix product code and re-run canonical command |
genversionexists at rootnode_modules/.binafteryarn.yarn lerna:prepare(andyarn install→postinstallDev) runs prepare via Nx with root toolchain on PATH → baregenversionin package"build"scripts works.yarn workspace … prepareorcd packages/foo && yarn run builddoes not expose root-only devDependencies →command not found: genversion. That is not corruptnode_modules; do not patch scripts withyarn run -T genversionunless deliberately changing repo policy onmain.
yarn jet --helpworking or failing intests/is not a valid e2e or install gate.- Jet is started internally by
yarn tests:<platform>:test-cover. Stale:8090→ pre-flight recovery, then re-run the same:test-covercommand.
- There is no
yarn google-java-formatscript. Inventedgoogle-java-format/npx google-java-formatinvocations are forbidden. - Canonical:
yarn lint:android(repo root) — wrapsgoogle-java-format --set-exit-if-changed --replaceonpackages/*/android/srcand fails if the tree would change.
- Do not invent
cd tests && yarn install, then bare./gradlewfrom an arbitrary cwd. - Unit:
yarn tests:android:unitonly (AndroidTest-AD-1). - Merged coverage after e2e:
yarn tests:android:post-e2e-coverage(Codecov path isjacocoTestReport, not e2e-onlyjacocoAndroidTestReport) — coverage design. - Optional explicit merge:
yarn tests:android:test:jacoco-report.
cd packages/<pkg> && yarn ios:codegen(oryarn android:codegen) often fails withunknown command 'codegen'after a cleanyarn—@react-native-community/cliresolves from the test app workspace.- Canonical: turbomodule workflow § Running codegen —
cd tests,npx @react-native-community/cli codegen --path ../packages/<pkg> …with--outputPathcopied from that package'spackage.jsonscript. - After regen: commit
android/.../generated+ios/generated, then:build+ Metro reset-cache before:test-cover.
- Unpatched RN ships fmt 11.0.2. On Xcode 26 / Apple Clang 21 that fails consteval builds.
- Canonical fix: root
yarnapplyingtests/patches/react-native+0.78.3.patch→ fmt 12.1.0. See install / patch / fmt gate. - Trap: yarn exit 0 does not prove the patch landed. If Nx cache-skips
react-native-firebase-tests:prepare(patch-package), fmt stays at 11.0.2. Durable policy: MonoTool-AD-12 (testspreparecache: false). Always run the fmtrgverification before native:build. - Never invent Podfile
post_installfmt hacks,FMT_USE_CONSTEVAL,base.hpatches, or c++17-for-fmt-only as a substitute for a missed install/patch.
Paste into Task / explore / work-queue prompts:
RNFB agent command policy: okf-bundle/testing/agent-command-policy.md ONLY.
E2e: okf-bundle/testing/running-e2e.md yarn tests:* ONLY.
Never: yarn workspace prepare, yarn jet, npx jet, cd packages/* && yarn prepare/build for diagnostics.
Never invent format/install: yarn google-java-format, bare/npx google-java-format, npm install, yarn install in tests/ alone — use root yarn first; Java format = yarn lint:android ONLY.
Never invent Android Gradle: ad-hoc ./gradlew outside yarn tests:android:unit / :build / :post-e2e-coverage / :test:jacoco-report; bare detox/jet/metro.
Prepare/install: yarn or yarn lerna:prepare must exit 0 before ANY other command — never parallelize with e2e/Metro/build.
Before native :build: root yarn exit 0 + verify tests/node_modules/react-native/third-party-podspecs/fmt.podspec ≥ 12.1.0 — okf-bundle/testing/agent-command-policy.md#install-patch-fmt-gate-blocking. If fmt < 12.1.0: STOP and re-run yarn; never invent Podfile/FMT_USE_CONSTEVAL/c++17 fmt hacks.
Area harness: okf-bundle/testing/running-e2e.md#local-harness-overrides-harnessoverridesjs — copy harness.overrides.example.js to gitignored harness.overrides.js; set modules + RNFBDebug; delete overrides after run.
TurboModule contract test (NewArch-AD-17.1): packages/app/__tests__/nativeModuleContract.test.ts — yarn tests:jest -- packages/app/__tests__/nativeModuleContract.test.ts
Android JVM unit (AndroidTest-AD-1): yarn tests:android:unit — not a substitute for platform e2e.
On failure: fix product code (or re-run yarn for patch miss), re-run the same canonical command.
Gate close / push: return [validation evidence package](validation-checklist.md#validation-evidence-package) and [coverage evidence package](coverage-design.md#coverage-evidence-package) when lib/native touched — required before commit or publication ([change authoring § validation evidence](change-authoring-workflow.md#validation-evidence-blocking)).
| Topic | Owner |
|---|---|
| E2e commands, pre-flight, tiers | running-e2e.md |
Install / patch / fmt before :build |
§ install / patch / fmt gate |
| Handoff validation sequence | validation-checklist.md |
| Android JVM unit ADR | android-architecture-decisions.md |
| Work types and gates | change-authoring-workflow.md |
| Doc / commit policy | documentation-policy.md |