| type | Reference | |||||
|---|---|---|---|---|---|---|
| title | Change authoring workflow | |||||
| description | Canonical cross-package loop for verified product changes — baseline, unit-focused implementation, area-focused review, documentation, commit, and pre-merge validation. | |||||
| tags |
|
|||||
| timestamp | 2026-06-26 00:00:00 UTC |
Single source for how to author and verify a product change in RNFB (bug fix, feature, parity, coverage). Package workflows add artifacts; work queues add ephemeral gate state — neither restates this loop.
Policy: OKF documentation and commit policy. Terms: iteration vocabulary.
flowchart TD
START([Pick change scope]) --> GA{Need feasibility /<br/>semantics check?}
GA -->|yes| GAP["gap-analysis<br/>tier: none"]
GA -->|no| BC{Need before snapshot<br/>or area-focused e2e baseline?}
GAP --> BC
BC -->|yes| BASE["baseline-capture<br/>tier: area-focused"]
BC -->|no| IMPL
BASE --> IMPL
IMPL["implementation<br/>tier: unit-focused<br/>Jest + narrow e2e loop"]
IMPL --> IG{implementation gate<br/>green?}
IG -->|no| IMPL
IG -->|yes| REV
REV["independent-review<br/>tier: area-focused<br/>frozen tree"]
REV --> RG{all findings<br/>resolved?}
RG -->|any unresolved| IMPL
RG -->|yes| DOC
DOC{User-facing or<br/>OKF durable updates?}
DOC -->|yes| DOCS["documentation<br/>tier: none"]
DOC -->|no| COMMIT
DOCS --> COMMIT
COMMIT["commit<br/>tier: none"]
COMMIT --> PM{Branch ready<br/>to merge?}
PM -->|yes| FULL["pre-merge-validation<br/>tier: full"]
PM -->|no| END([Hand off / next item])
FULL --> END
| Work type | When | Validation tier | Product edits | Commit |
|---|---|---|---|---|
gap-analysis |
Unclear feasibility, export shape, platform support | none | read-only | no |
baseline-capture |
Need before metrics or area-focused e2e on the item | area-focused |
harness narrow OK locally | no |
implementation |
Author fix/feature + tests | unit-focused |
yes | no |
independent-review |
Verify frozen diff | area-focused |
no — frozen tree | no |
documentation |
User docs + durable OKF updates | none | docs only | no |
commit |
Gates closed for the item | none | staging only | yes |
pre-merge-validation |
Branch merge gate | full |
revert narrowing first | no |
Commands per work type: validation checklist — link only; do not duplicate here.
Tier id strings: iteration vocabulary § validation tier identifiers.
flowchart LR
subgraph unitFocused ["unit-focused — implementation"]
F1[Area harness narrowing required]
F2[Jest + package-scoped tests]
F3[".only OK locally"]
F4[Fast e2e subset]
F5[Never commit narrowing or .only]
end
subgraph areaFocused ["area-focused — baseline-capture / independent-review"]
A1[Area harness narrowing required]
A2[Full loaded package spec]
A3[No .only]
A4[Frozen tree for review]
end
subgraph full ["full — pre-merge-validation"]
P1[Revert all narrowing]
P2[All modules / full app]
P3[Once per branch before merge]
end
E2e scope, pre-flight, and harness gate: running e2e § agent rule (canonical commands only), validation tiers, harness narrowing gate.
Command rule: Agents run only agent command policy allowlisted commands for install, prepare, and validation — no improvised yarn workspace … prepare, yarn jet, or package-scoped build probes.
| Gate | Closes when |
|---|---|
implementation |
implementation work type complete — code plus unit-focused-tier checks green on every required platform when native bridge or macOS TS/runtime path changed (platform coverage gate); static analysis green on the diff |
review |
independent-review complete — area-focused-tier checks green on frozen tree; applicable validation checklist rows green (including static analysis); every review finding resolved (§ quality standards) |
commit |
Durable commit exists for the item after prior gates closed with recorded evidence |
Trust rule: Code on disk or in git with review still open is unverified until independent-review closes the gate.
Any unresolved review finding returns the item to implementation (unit-focused), then repeats independent-review (area-focused) — see § quality standards.
Gates close only when recorded evidence shows the required validation tier ran and passed. Assumed green, implementer summaries without exit codes, or "tests passed earlier" without a log path do not close a gate.
| Gate | Minimum evidence (record in work-queue notes or review handoff) |
|---|---|
implementation |
Prepare/tsc/jest exit codes; when native or macOS runtime touched: e2e pass count per required platform + log path (e.g. /tmp/rnfb-e2e-*.log); yarn lint exit code 0; when packages/*/lib/** in diff: yarn lint:deps exit code 0 (dependency-cycle linting); when docs/** changed: yarn lint:markdown + yarn lint:spellcheck exit code 0 |
review |
Frozen-tree re-run of area-focused checklist; yarn lint exit code 0; when docs/** in frozen diff: yarn lint:markdown + yarn lint:spellcheck exit code 0; coverage evidence package when native or packages/*/lib/** bridge code touched (coverage design § evidence package); compare:types row for touched registered package |
commit |
Prior gates closed with evidence; no .only / harness overrides staged |
Publication (git push, force-push, PR refresh) |
review gate closed on the exact commits being published; evidence still valid (no product edits since last area-focused run) |
Investigate before close: Any coverage plateau, parity asymmetry, or review finding gets root-cause analysis — add tests, delete dead code, or record an acceptable exception with evidence. Do not label gaps "informational" or "defensive" without wire/runtime proof.
git commitwhile the current work type's validation tier is incomplete or evidence is missing.git push/ force-push / PR update claiming remediation or review-green without fresh area-focused evidence after the last product edit on the published commits.- History rewrite (rebase, amend stack) without re-running validation for the rewritten scope — prior green results are invalid.
- Self-accepted parity or coverage gaps — only acceptable exceptions with user confirmation or intractability evidence in durable OKF (e.g. parity registry row).
Publication is not a separate work type; it follows the same evidence bar as review + commit.
Two authoring standards gate every item, and both admit the same narrow set of acceptable exceptions — the only things that may be documented and tracked instead of fixed.
Only two things may be documented and tracked instead of fixed. Both require the user's explicit acceptance and confirmation plus a recorded rationale — an agent or reviewer may not grant either on its own, and the item stays tracked until resolved.
- Intractable-limitation bar. The gap or firebase-js-sdk divergence is caused by an intractable technical limitation of the language, platform SDK, compiler, or toolchain, shown with evidence — e.g. a compiler/codegen-expanded branch that is provably unreachable, or a native SDK that does not expose the capability, cited by version.
- User-accepted deferral. The gap is addressable, but the user explicitly defers it with a documented rationale — e.g. it needs architectural design or human review not available now, or the compute cost is not currently justified.
Anything else is drift or a defect, never a self-justifying exception:
- If code can be authored, a test that exercises it can be authored — otherwise it is dead code; delete it, do not document it.
- A divergence with no accepted exception is drift — align to firebase-js-sdk and remove any config entry.
- Convenience, time pressure, "harmless", "low-value", or "low-risk" carry weight only through an explicit user-accepted deferral (2), never on an agent's own authority.
independent-review classifies findings critical / serious / minor / nit. The review gate closes only when every finding — including minor and nit — is resolved by a fix, unless the finding is covered by one of the two acceptable exceptions. An agent or reviewer may not defer a finding on its own authority: "green with minors" is not green, and parity, quality, and coverage gaps are cheapest to fix while the diff is fresh.
A finding covered by an accepted exception is recorded — with evidence or the user's rationale — and tracked, not silently dropped. A finding that is neither fixed nor covered by an accepted exception returns the item to implementation.
Domain applications reference this section rather than restating it:
- Coverage completion: coverage design § expectations.
- Type parity / API drift: compare-types justification bar.
Required for independent-review and for any :test-cover run that closes the review gate:
- No edits to
packages/**,tests/**(except reverting.only), or bundle-affecting OKF docs during the run. - Wait for or cancel in-flight runs before editing again.
Keep implementation and independent-review in separate passes. E2e enforcement during runs: running e2e § rules.
On a shared dev host during change authoring:
- One
:test-coverat a time — never overlap unit-focused-tier and area-focused-tier runs. - Every run starts from running e2e § pre-flight (host-clear probes, services, harness tier).
- Use only canonical e2e commands. Stalled runs → stalled run detection.
flowchart TD
P0[Pre-flight: host clear, services, harness tier]
P1[Edit product code + tests]
P2[Jest — package or scoped paths]
P3{Native touched?}
P3 -->|no| P4[macOS e2e when TS/runtime path]
P3 -->|yes| P5["native rebuild + platform e2e"]
P4 --> P6{Green?}
P5 --> P6
P6 -->|no| P1
P6 -->|yes| STATIC[Static analysis — validation checklist § lint]
STATIC --> DONE([Close implementation gate])
P0 --> P1
Host rule: one :test-cover at a time; never overlap unit-focused and area-focused tiers on one host (§ host rule).
Static analysis before handoff: Before closing the implementation gate, run the validation checklist § lint and formatting rows — yarn lint (CI Lint job: js + deps + android + ios check) on every diff with package sources; when packages/*/lib/** is in the diff, confirm yarn lint:deps passes (dependency-cycle linting); yarn lint:markdown + yarn lint:spellcheck when docs/** changed (CI docs job). Fix violations in product code — do not hand off with lint failures. Command list lives only in the checklist; do not duplicate here.
Step detail: running e2e § unit-focused iteration loop.
Before changing native bridge code that calls a platform SDK (Firebase Android/iOS, OS APIs, vendor SDKs, etc.):
- Read each platform's official API signature and docs independently — do not assume Android, iOS, and Web behave the same because the RNFB bridge presents a unified JavaScript surface.
- Verify null vs empty string — many SDKs treat absent values (
null/nil) and empty strings ("") differently; map bridge fields to the SDK parameter the docs specify for "absent" values. - Do not apply defensive parity — fixing platform A does not justify the same change on platform B without checking B's contract (e.g.
@Nullablevsnonnull, optional vs required). - Record evidence — link or cite the reference URL / header signature in the work queue note or triage report when the fix is native-only on one platform.
When unit-focused e2e fails and product cause is unclear:
- Confirm pre-flight was complete (prepare completion gate when
lib/**changed, host-clear probes, services, harness overrides,RNFBDebug: truevia overrides). - If the same failure repeats on back-to-back runs with no assertion progress and the host is known clean → sub-suite narrow (running e2e § fail-fast): one spec file or
describe.onlyon the failing band (e.g. aggregatecount()/average()/sum()only). Still unit-focused; never commit narrowing. - If sub-suite runs still fail without actionable assertion text → add temporary native instrumentation (NSLog,
adb logcattags, etc.) on the code path under test; use running e2e § diagnosing hangs for log commands. Remove instrumentation beforecommitand beforearea-focusedgate closure on a frozen tree. - Do not treat Jet WS disconnect / orchestration timeout alone as product failure — stalled run detection and pre-flight recovery first.
This escalation applies to any change authoring item, not only namespace removal. Work queues record outcomes; they do not restate this loop.
On a frozen tree:
- Revert all
.only. - Keep area narrowing; run area-focused-tier e2e for loaded package spec(s) on every required platform (serial; pre-flight each run).
- Run applicable validation checklist rows — blocking: static analysis § lint and formatting (
yarn lint:json the frozen tree; markdown/spellcheck when docs touched);yarn reference:apiwhen public surface changed. For packages registered incompare:types,yarn compare:typesis a blocking review gate: the touched package must have zero undocumented or stale differences beforereview_gatecloses. If the global command fails on unrelated registered packages, record/fix that drift in the work queue; do not treat an unrelated failure as permission to skip the touched package's type-parity check. - Coverage evidence package — blocking when
packages/*/lib/**or native bridge sources in the frozen diff: produce and attach per coverage design § evidence package; investigate every non-100% reachable line before closingreview. - Outcome closes review gate or returns to
implementation.
Keep implementation and independent-review in separate passes (§ frozen tree).
Before the first :test-cover at unit-focused or area-focused tier: create local tests/harness.overrides.js even when the branch commit has full harness — running e2e § local harness overrides. Set modules to the package area and RNFBDebug: true. Full app load is full tier only (delete overrides file).
| Kind | implementation (unit-focused) |
independent-review (area-focused) |
pre-merge-validation (full) |
commit |
|---|---|---|---|---|
| Area narrowing | Required before :test-cover (overrides file) |
Required before :test-cover |
Delete overrides — all modules | Never commit overrides |
RNFBDebug: true |
Required in overrides before :test-cover |
Required in overrides before :test-cover |
Delete overrides / false |
Never |
Single-test (.only) |
Allowed (diagnosis) | Revert | Revert | Never |
Single-suite (describe.only / one spec file) |
Allowed (diagnosis only — escalation) | Revert | Revert | Never |
Package workflows define which module/spec to load (e.g. Firestore → pipeline implementation workflow § narrowing).
Sanity check: pass counts must match loaded scope — not full-app totals (running e2e § gate).
- One focused commit per item when gates close.
- Evidence required: § validation evidence must be recorded before
commit_gatecloses; orchestration summaries are not substitutes for exit codes, e2e counts, and coverage tables. - Never stage:
tests/harness.overrides.js, any.only, temporary sub-suite edits intests/app.js, or native instrumentation (running e2e § before merge, platform coverage gate). - Work queue: before
git commit, set the row'scommit_subjectto the commit's subject line, closecommit_gate, and stage the queue doc in the same commit as the product change (documentation policy § work queues). Do not record SHAs in queue docs.
git status
git diff --stat
rg '\.only\(' packages/| Package / area | Adds to this loop |
|---|---|
| Firestore Pipelines | Compare-types gap pick, serialization matrix, Pipeline.e2e.js setup, coverage snapshots — pipeline implementation workflow |
| TurboModule migration | Spec inventory, codegen commit, New Architecture harness, multi-module spec split — turbomodule implementation workflow |
| Other packages | okf-bundle/packages/<pkg>/ index when a workflow exists |
Ephemeral coordination (gate rows, next_work_type, commit_subject): work queues only — not part of this workflow.
| Topic | Document |
|---|---|
| Term ids and queue field schema | iteration-vocabulary.md |
| E2e commands | running-e2e.md |
| Validation commands | validation-checklist.md |
| Coverage policy | coverage-design.md |
| Android JVM unit ADR | android-architecture-decisions.md |