Skip to content

Latest commit

 

History

History
307 lines (219 loc) · 29.5 KB

File metadata and controls

307 lines (219 loc) · 29.5 KB
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
testing
validation
workflow
implementation
review
timestamp 2026-06-26 00:00:00 UTC

Change authoring workflow

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.

Primary loop

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
Loading

Work types

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.

Validation tiers

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
Loading

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.

Gates

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.mddocumentation then another frozen independent-review. Do not send every finding to documentation.

Validation evidence (blocking)

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.

Forbidden shortcuts

  • git commit while the current work type's validation tier is incomplete or evidence is missing — including coverage_evidence gate open when lib/native bridge touched.
  • Jet NYC text-summary after narrowed e2e as coverage proof for native or packages/*/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 committed packages/*/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.

Quality standards

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.

Acceptable exceptions

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.

  1. 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.
  2. 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.

Review findings — resolve, do not defer

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.mddocumentation then another frozen independent-review.

Domain applications reference this section rather than restating it:

Frozen tree

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, or CONTRIBUTING.md during 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.

Host rule

On a shared dev host during change authoring:

implementation inner loop

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
Loading

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.

Platform SDK bridge contracts (blocking)

Before changing native bridge code that calls a platform SDK (Firebase Android/iOS, OS APIs, vendor SDKs, etc.):

  1. 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.
  2. 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.
  3. Do not apply defensive parity — fixing platform A does not justify the same change on platform B without checking B's contract (e.g. @Nullable vs nonnull, optional vs required).
  4. 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.

E2e diagnosis escalation

When unit-focused e2e fails and product cause is unclear:

  1. Confirm pre-flight was complete (prepare completion gate when lib/** changed, host-clear probes, services, harness overrides, RNFBDebug: true via overrides).
  2. 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.only on the failing band (e.g. aggregate count() / average() / sum() only). Still unit-focused; never commit narrowing.
  3. If sub-suite runs still fail without actionable assertion text → add temporary native instrumentation (NSLog, adb logcat tags, etc.) on the code path under test; use running e2e § diagnosing hangs for log commands. Remove instrumentation before commit and before area-focused gate closure on a frozen tree.
  4. 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.

independent-review

On a frozen tree:

  1. Revert all .only.
  2. Keep area narrowing; run area-focused-tier e2e for loaded package spec(s) on every required platform (serial; pre-flight each run).
  3. Run applicable validation checklist rows — blocking: static analysis § lint and formatting (frozen: check-only by-tree); yarn reference:api when public surface changed. For packages registered in compare:types, yarn compare:types is a blocking review gate: the touched package must have zero undocumented or stale differences before review_gate closes. 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.
  4. Coverage evidence packageblocking 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; close coverage_evidence gate with verdict line; investigate every non-100% reachable line. Missing or stale package = serious finding — same bar as missing e2e counts.
  5. When the frozen tree includes okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md, run the OKF bundle scanreport only.
  6. Outcome closes review gate (only after coverage_evidence gate 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.

Harness narrowing

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).

commit

  • One focused commit per item when gates close.
  • When okf-bundle/ reference docs, AGENTS.md, or CONTRIBUTING.md changed, commit closes only after the frozen OKF bundle scan is clean. Contract findings belong in documentation? then another frozen independent-review — not edits on the commit pass.
  • Evidence required: § validation evidence must be recorded before commit_gate closes; summaries without exit codes, e2e counts, and coverage tables do not substitute.
  • Never stage: tests/harness.overrides.js, any .only, temporary sub-suite edits in tests/app.js, or native instrumentation (running e2e § before merge, platform coverage gate).
  • Work queue: before git commit, set the row's commit_subject on the Linear queue document to the commit's subject line and close commit_gate. Do not stage a queue file. Do not record SHAs. After commit, the git subject and the queue commit_subject must 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 extensions

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.

Related docs

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