| type | Reference | |||||
|---|---|---|---|---|---|---|
| title | Change authoring workflow | |||||
| description | Canonical cross-package loop for verified product changes — baseline, unit-focused implementation, documentation, area-focused review, 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. Queue home is a Linear project document (documentation policy); existing repo *work-queue.md files stay until next pickup. Neither restates this loop.
Policy: OKF documentation and commit policy — public vs ephemeral vs private; Efficiency. 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| DOC
DOC{User-facing or<br/>OKF durable updates?}
DOC -->|yes| DOCS["documentation<br/>tier: none"]
DOC -->|no| REV
DOCS --> REV
REV["independent-review<br/>tier: area-focused<br/>frozen tree"]
REV --> RG{all findings<br/>resolved?}
RG -->|product / tests / lint| IMPL
RG -->|OKF / AGENTS / CONTRIBUTING only| DOCS
RG -->|yes| 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 |
documentation |
Promote user docs + durable OKF + AGENTS.md + CONTRIBUTING.md on the same change set, before independent-review. Does not run the OKF scan |
none | those files only | no |
independent-review |
Verify frozen diff. When the frozen tree includes okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md, this pass is the OKF bundle scan |
area-focused |
no — frozen tree except revert .only |
no |
commit |
Gates closed for the item; staging only | 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, committed **/generated/**, podspec/spec/codegen wiring, macOS TS/runtime path, or packages/*/e2e/** changed (platform coverage gate; running e2e § Rules #3); static analysis green on the diff |
coverage_evidence |
Coverage evidence package attached with verdict line — required when frozen diff touches packages/*/lib/**, native bridge (packages/*/{android,ios}/**), or packages/app/**/*.rb; otherwise n/a |
review |
independent-review complete — area-focused-tier checks green on frozen tree; applicable validation checklist rows green (including static analysis); coverage_evidence gate closed when required; OKF bundle scan when okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md are in the frozen tree (§ OKF bundle review); every review finding resolved (§ quality standards) |
commit |
Durable commit exists for the item after implementation, coverage_evidence (when required), and review gates closed with recorded evidence. When those OKF/AGENTS.md/CONTRIBUTING.md files changed, close only after the frozen scan. Fix OKF contract violations before git commit — the frozen scan reports only |
Trust rule: Code on disk or in git with review still open is unverified until independent-review closes the gate.
Follow-up splits by what failed (§ frozen tree, § quality standards): product/tests/lint → implementation; okf-bundle/ / AGENTS.md / CONTRIBUTING.md → documentation then another frozen independent-review. Do not send every finding to documentation.
Gates close only when recorded evidence shows the required validation tier ran and passed. Assumed green, 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 packages/app/**/*.rb or packages/app/__tests__/*_test.rb touched: yarn tests:ios:ruby exit 0 + coverage/ios-ruby/lcov.info (validation checklist § iOS Ruby); when native bridge, packages/*/ios/generated/** / packages/*/android/**/generated/**, podspec/spec/codegen wiring, macOS runtime, or packages/*/e2e/** touched: e2e pass count per required platform + log path (e.g. /tmp/rnfb-e2e-*.log) — package e2e specs require the same platform coverage matrix even with no native hunk for that OS; yarn codegen:verify alone does not close this; lint and formatting evidence (by-tree scripts; exit 0) |
coverage_evidence |
When lib/native bridge or packages/app/**/*.rb touched: full coverage evidence package at .agents/reports/<item>/coverage-evidence.md (or work-queue notes) including verdict line; post-process native artifacts after fresh e2e (coverage design § reading per-file); Ruby: § iOS Ruby SimpleCov |
review |
Frozen-tree re-run of area-focused checklist; lint and formatting evidence (check-only by-tree); coverage_evidence gate closed when required (native, **/generated/**, packages/*/lib/** bridge code, or packages/app/**/*.rb); OKF bundle scan report when okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md in the frozen tree (§ OKF bundle review); compare:types row for touched registered package; e2e evidence must include services checkout ownership when platforms ran |
commit |
Prior gates closed with evidence; no .only / harness overrides staged; OKF contract violations fixed before git commit when those files changed (frozen scan was report-only) |
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 — includingcoverage_evidencegate open when lib/native bridge touched.- Jet NYC
text-summaryafter narrowed e2e as coverage proof for native orpackages/*/lib/**changes — it measures remapped TS only; use Jacoco/lcov on changed files (coverage design § anti-patterns). 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).
yarn codegen:verify(or scripts/OKF-only static checks) instead of platform e2e when committedpackages/*/ios/generated/**,packages/*/android/**/generated/**, native shells, podspecs, or TurboModule specs changed — running e2e § Rules #3 / platform coverage.- Pre-flight that only checks ports/HTTP while Metro or Firebase emulators belong to another worktree — services checkout ownership.
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 — neither exception may be granted without that, 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. Do not defer a finding without that exception: "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 follows § frozen tree: product/tests/lint → implementation; okf-bundle/ / AGENTS.md / CONTRIBUTING.md → documentation then another frozen independent-review.
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:
- Report/check-only except reverting
.only. - No edits to
packages/**,tests/**(except reverting.only),okf-bundle/reference docs,AGENTS.md, orCONTRIBUTING.mdduring the run. - Wait for or cancel in-flight runs before editing again.
Keep implementation, documentation, and independent-review in separate passes. Do not add OKF / AGENTS.md / CONTRIBUTING.md after a frozen review without another independent-review. E2e enforcement during runs: running e2e § rules.
Follow-up splits by what failed:
| Failed in | Next work type |
|---|---|
| Product, tests, or lint | implementation (then documentation?, then frozen scan) |
okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md |
documentation then another frozen independent-review |
Do not send every finding to documentation.
On a shared dev host during change authoring:
- One unslotted
:test-coverat a time — never overlap unit-focused-tier and area-focused-tier runs. Slotted cross-platform concurrency (distinct worktrees/ports/devices): running e2e § parallel topology. - Every run starts from running e2e § pre-flight (host-clear probes, services ready, checkout ownership, harness tier).
- Use only canonical e2e commands. Startup-fail markers → startup fail-fast poll (do not wait the full
launchApptimeout). 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 that match the diff. Fix violations in product code — do not hand off with lint failures. Commands live only in that section.
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 is general change authoring. 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 (frozen: check-only by-tree);
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: after fresh area-focused e2e, run native post-process (coverage design § reading per-file); produce package per coverage design § evidence package; closecoverage_evidencegate with verdict line; investigate every non-100% reachable line. Missing or stale package = serious finding — same bar as missing e2e counts. - When the frozen tree includes
okf-bundle/reference docs,AGENTS.md, orCONTRIBUTING.md, run the OKF bundle scan — report only. - Outcome closes
reviewgate (only aftercoverage_evidencegate when required) or follows § frozen tree split (not every finding →documentation).
Keep implementation, documentation, and independent-review in separate passes (§ frozen tree). Do not add OKF after this pass without another independent-review.
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.
- When
okf-bundle/reference docs,AGENTS.md, orCONTRIBUTING.mdchanged,commitcloses only after the frozen OKF bundle scan is clean. Contract findings belong indocumentation?then another frozenindependent-review— not edits on thecommitpass. - Evidence required: § validation evidence must be recorded before
commit_gatecloses; summaries without exit codes, e2e counts, and coverage tables do not substitute. - 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_subjecton the Linear queue document to the commit's subject line and closecommit_gate. Do not stage a queue file. Do not record SHAs. After commit, the git subject and the queuecommit_subjectmust match character-for-character. Single-commit PR titles: documentation-policy § pull requests. Queues are ephemeral (documentation policy § work-queue documents); do not copy policy here.
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 |
| TurboModules | Durable decisions — New Architecture ADR / index. Codegen commands: agent command policy |
| Other packages | okf-bundle/packages/<pkg>/ index when a workflow exists |
Ephemeral coordination (gate rows, next_work_type, commit_subject) lives in work queues only — do not paste gate rows into this file. How to stage those fields: § commit.
| 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 | AndroidTest-AD-1 |