| type | Reference | ||||||
|---|---|---|---|---|---|---|---|
| title | Pipeline coverage and parity work queue | ||||||
| description | Phase tracker for Firestore Pipelines coverage expansion, platform parity audit/remediation, and SDK support reconciliation. | ||||||
| tags |
|
||||||
| timestamp | 2026-06-25 12:00:00 UTC |
COMPLETE: Merge gate closed — static pre-merge green; R closed. Ready for PR 9086 force-push + CI after validation evidence still valid on published commits. Goal/order: platform parity first; then TS/native coverage toward intractable limits. Links: parity, SDK audit, coverage, e2e, architecture.
Ephemeral tracker; see OKF policy.
Parity before coverage. Otherwise tests add Platform.* workarounds, misclassify bridge drift as intractable, and deepen Swift/Java drift.
Sequence from H onward: H → I drift inventory → Ib SDK support reconciliation → J (J0 probes → J0b iOS lowering consolidation → J1–J6 bridge) → K–Q coverage → R snapshot.
| Phase | Focus |
|---|---|
| Ib | Reconcile SDK CHANGELOG + bridge audit vs RNFB lowering; repeatable method |
| J0 | iOS runtime probes — one function per commit; authoritative guard list |
| J0b | iOS NodeBuilder lowering consolidation — dedupe boolean/receiver-chain paths added during J0 (see J0b); before J1–J6 |
| J1–J6 | Bridge remediation (P-001, P-005, P-010–P-012, P-034) after J0 + J0b |
Gate prerequisites before any :test-cover (host rule):
- Pre-flight: host-clear probes, services ready, harness matches validation tier (narrowing gate — required for unit-focused and area-focused; not push harness); [serial
:test-cover](../../testing/running-e2e.md#serialized-e2e-dispatch); frozen tree forindependent-review. - Guard probes: SDK runtime verification + Phase J protocol below.
- Coverage deltas: full clean cycle; never trust stale
.ec/profraw (coverage stale data).
| Phase | Focus | Status | Outcome |
|---|---|---|---|
| A | Baseline e2e + Jet TS coverage | ✅ | 3-platform verify; harness + jet patch |
| B | Android dead-code removal | ✅ | buildParsed* cluster; NodeBuilder 55%→66% |
| C | Gap map + tooling | ✅ | map-pipeline-coverage-gaps.sh |
| D | Native lowering e2e | ✅ | subcollection 100%; schedule dispatch 100% |
| E | Executor / Parser / BridgeFactory e2e | ✅ | Android Executor 49%→58%; iOS BridgeFactory 83% |
| F | Android L900–1299 lowering | ✅ | Dead removal — loop 106→77 missed; NodeBuilder 70.2% |
| G | iOS operand modes + map passthrough | ✅ | +8 operand probes via raw-where e2e; map execute intractable |
| H | TS pipeline_validate execute guards |
✅ | e2e tamper tests + Android parser ref-constant fix; pipeline_validate ~93% macOS TS lcov |
| I | Platform parity audit | ✅ | 31 e2e branches; registry P-001–P-031 |
| Ib | SDK support reconciliation | ✅ | Guard list vs iOS 12.15 / Android 34.15 CHANGELOG; audit method |
| J | Parity remediation | ✅ complete | J0 probes → J0b consolidation → J0 remainder → J1–J6 |
| K | TS pipeline_runtime + expressions |
✅ | Jest alias/normalization batch; expressions e2e receiver probe |
| L | Android parsed-aggregate tail | ✅ | expression-arg arrayAgg/arrayAggDistinct e2e; parsed tail 258/408 |
| M | Android exit frames + receiver chains | ✅ | 3 e2e; NodeBuilder 75.03%; exit −29 missed |
| N | iOS stage coercion | ✅ | iOS/web stage coercion + operand tail; macOS 139 / iOS 144 / Android 144 area-focused |
| O | Android Executor remainder | ✅ | 58%→60.94%; 7 e2e; ~130 missed dead-code → Phase Q |
| P | Jest-only TS paths | ✅ | 100% lines pipeline_validate; L49 → Q |
| Q | Intractability audit | ✅ | −238 Executor dead lines; intractable caps documented |
| R | Pre-merge harness restore | ✅ | 698/0 macOS; 866/0 Android; iOS 838/0 after 38cc8815a fix |
Compare-types exports: unblocked — R complete.
Label: after-phase-r-final; harness: full app (committed defaults)
Next item: force-push branch → PR 9086 CI → paste PR post draft — only after validation evidence still valid on published commits.
Current gates: Merge gate closed (2026-07-03). compare:types 19/19 documented; Jest 1146/1146; tsc + lint green. K–R complete.
E2e (Phase R full tier): macOS 698/0, iOS 838/0, Android 866/0 passing.
| Target | Phase A baseline | Phase R final | Delta |
|---|---|---|---|
TS pipeline_runtime.ts |
86% | 91.07% (204/224) | +5.07 pp |
TS expressions.ts |
89% | 93.98% (250/266) | +4.98 pp |
TS pipeline_validate.ts |
~93% | 88.64% (78/88) | −4.36 pp (e2e lcov vs macOS/Jest mix) |
| Android NodeBuilder | 67.5% (1167/1729) | 75.18% (1324/1761) | +7.68 pp |
| Android Executor | ~49% / 58% (post-E) | 76.59% (386/504) | +18.6–27.6 pp |
| iOS NodeBuilder | 68.89% | 69.10% (1516/2194) | +0.21 pp |
| Android EnterObject loop (L900 band) | 106 missed | 65 missed (71.98%) | −41 missed |
| iOS operand modes (L919–1006) | 27 missed (69.32%) | 17 missed (72.58%) | −10 missed |
Notable commits: parity J0–J6; coverage K–Q (−238 Executor dead lines); R-iOS 38cc8815a; android coverage upload 94299783a.
| Q Intractability audit | refactor(firestore, android): remove dead pipeline Executor lowering code | closed | closed | closed | — | — | — | −238 lines; 151 Android pass; intractable caps in queue |
| J2 P-005 integerLiteral | fix(firestore, android): align pipeline integerLiteral constant lowering with iOS | closed | closed | closed | — | — | — | P-005 → Resolved; CFBoolean deferral accepted |
| J3 P-010 stage option expressions | fix(firestore, android): align pipeline stage option expression fields with iOS | closed | closed | closed | — | — | — | P-010 → Resolved |
| J4 P-011 constant envelope | fix(firestore, android): align pipeline constant envelope routing with iOS | closed | closed | closed | — | — | — | P-011 → Resolved |
| J5 P-012 timestampTruncate arity | fix(firestore, android): align pipeline timestampTruncate arity validation with iOS | closed | closed | closed | — | — | — | P-012 → Resolved; iOS explicit arity guard deferred |
| J6 P-034 operand-mode audit | docs(firestore): close P-034 operand-mode e2e audit after J1 parity | closed | closed | closed | — | — | — | No code trims; P-021/P-022 confirmed |
| K TS runtime/expressions | test(firestore): expand pipeline TS runtime and expression coverage | closed | closed | closed | — | — | — | Jest batch + receiver currentTimestamp e2e probe |
Arbiter gate (2026-06-25):
| Probe | commit_subject |
implementation_gate |
review_gate |
next_work_type |
validation_tier |
platform |
Notes |
|---|---|---|---|---|---|---|---|
J0-1 stringRepeat |
— | closed | closed | — | — | — | stringRepeat unified iOS path |
J0-2 switchOn |
— | closed | closed | — | — | — | switchOn unified iOS path |
J0-3 trunc |
— | closed | closed | — | — | — | trunc unified iOS path |
J0-4 conditional |
— | closed | closed | — | — | — | iOS wire conditional; unified e2e |
J0-5 round |
— | closed | closed | — | — | — | round unified iOS path (TS-only) |
J0-6 substring |
— | closed | closed | — | — | — | rnfb-bridge-gap — reclassified; guard retained |
J0-7 timestampAdd |
— | closed | closed | — | — | — | rnfb-bridge-gap — probe + SDK source; guard retained |
J0-8 timestampSubtract |
— | closed | closed | — | — | — | rnfb-bridge-gap — SDK timestamp_subtract; fix iOS wire + receiver |
J0-9 arrayGet |
— | closed | closed | — | — | — | rnfb-bridge-gap — SDK array_get receiver wire; guard retained |
| J0b | — | closed | closed | — | — | — | switchOn boolean receiver consolidation |
J0-6′ substring |
— | closed | closed | — | — | — | iOS receiver chain; guard removed; unified e2e |
J0-7′ timestampAdd |
— | closed | closed | — | — | — | timestampAdd(amount:unit:) |
J0-8′ timestampSubtract |
— | closed | closed | — | — | — | wire timestamp_subtract |
J0-9′ arrayGet |
— | closed | closed | — | — | — | .arrayGet(_:) |
| J1 P-001 operand coercion | fix(firestore, android): align pipeline operand coercion with iOS |
closed | closed | closed | — | — | — |
| Target | macOS | iOS | Android (gap map) | Phase |
|---|---|---|---|---|
| Parity drift (bridge) | — | — | 0 open (P-034 closed) | J |
| Parity drift (SDK/macOS-js) | 11 vacuous | 10 reduced + 3 vacuous | documented | — |
TS pipeline_runtime.ts |
86% | 90.62% (203/224) | K batch (Jest; e2e lcov unchanged) | K |
TS expressions.ts |
89% | 93.61% (249/266) | K batch (+1 e2e line) | K |
| Android NodeBuilder | 67.5% (1167/1729) | 75.03% (1322/1762) | M: exit −29 missed; loop −12 | L, M |
| Android loop L900–1299 | 106 missed | 64 missed | M: −12 from baseline 76 | M |
| Android Executor | 58% | ~97% live (387/~397) post-Q dead removal | Q: −238 lines dead; jacoco regen at commit | O, Q |
| iOS NodeBuilder | 68.89% | ~70%+ (Phase N) | G: +15 hit; N: stage coercion | N |
| iOS operand modes L919–1006 | 27 missed | reduced (Phase N) | N operand tail e2e | N, Q |
bash scripts/map-pipeline-coverage-gaps.sh # current
bash scripts/map-pipeline-coverage-gaps.sh after-phase-g
bash scripts/map-pipeline-coverage-gaps.sh after-phase-f-dead-removal| Commit subject | Summary |
|---|---|
Android e2e infra: Detox FabricTimers, .ec delete, OKF stale-coverage docs |
Phase A infra |
| Android NodeBuilder: remove dormant lowering duplicates (Phase F) | Dead-code removal |
| E2e: expression frame lowering regression cases (Phase F) | Lowering e2e |
| E2e: iOS operand modes via raw where filters (Phase G) | Operand-mode probes |
Earlier: A–E baseline, dead code, gap map, lowering/executor e2e.
- Added five e2e tests under
enter object expression frame lowering coverage; green 128/133/133; zero Jacoco delta because Parser normalizes before NodeBuilder. - Removed 183 lines duplicate/zero-caller lowering: wrappers, raw-operator boolean arms duplicated in Parser, scalar/String/Expression entry arms unreachable from
serializeExpressionNode. - Result: loop 106 → 77 missed; NodeBuilder 67.5% → 70.2% (fewer lines, higher %).
- Remainder → Phase M: vector expression handler (expression-vector rhs), exit/receiver tails.
Lesson: e2e that passes but moves no probes → audit callers before adding more tests.
- One e2e:
coerces bare rhs operands through raw where filters; raw.where({ condition: { operator, fieldPath, value }})with bare string/array/bool rhs (modular wraps rhs constants and misses operand-mode arms). - Result: iOS NodeBuilder +0.95 pp; operand modes 69.32% → 78.41% (−8 missed).
- Map passthrough execute success (L1208–1219): intractable — Firestore rejects
map(field(…))execute; lowering already covered by existing error-path e2e. - Operand tail (19 missed): L928, L948–949, L961–966, L973–974, L990–1006 — triage in Phase I; Android side is P-001 (bridge gap, not coverage-only).
- Parity note: e2e uses
Platform.androidsplit for ordering RHS — must close in Phase J, not extend in Phase K+.
- Detox
FabricTimersIdlingResourceno-op under New Arch (launch crash fix). - Android post-e2e deletes processed
.ec(parity with iOS profraw delete). - OKF: stale coverage → full clean cycle, do not re-report without fresh e2e.
Commit subject: test(firestore): expand pipeline execute validation e2e coverage (representative).
- Six e2e tests tamper
_source/_stagesbeforeexecute()to hit JS validation guards. - Result:
pipeline_validate.ts~93% macOS TS lcov (+17 lines). - Remaining 6 lines → Phase P/Q: runtime-unreachable guards; Jest
pipelines-validate.test.tscovers direct-call paths. - Android parser fix: document-reference
{ path: "col/doc" }constants.
Deliverable: pipeline-platform-parity.md — full registry.
Audit inputs:
- E2e drift inventory — 31
Platform.*sites; 141/146 delta = 5 apputils*tests (not Pipeline) - Native bridge diff — NodeBuilder coercion is primary drift
- JS guards audit — single
isIOSpre-execute guard; execute-options JS gate on all platforms
Triage totals:
| Class | Count | Action |
|---|---|---|
| bridge | 5 | Phase J (J1–J5) |
| SDK | 3 stage/aggregate gaps | Document (P-013–P-015) |
| macOS-js | 11 vacuous/reduced Pipeline tests | Document (P-004, P-018–P-028) |
| test-only | 1 | Unify after J1 (P-034) |
| RNFB-JS | 2 | Document or narrow in J (P-016, P-017) |
| closed | P-002, P-006 | — |
Goal: Document repeatable SDK/bridge audit method; drive Phase J queue from runtime e2e + native lowering.
Pins audited: iOS Firestore 12.15.0, Android BOM 34.15.0.
Deliverables:
- pipeline-sdk-support-audit.md — repeatable method + support matrix
- Former iOS JS function guard removed (2026-06-25); parity is native bridge + unified e2e
- Runtime e2e probes (Phase J0/J0 remainder) are authoritative — CHANGELOG + bridge audit alone is insufficient
Audit input: native bridge + CHANGELOG cross-check.
Each J0 probe / J1–J6 bridge step follows one serial loop. No overlap. Work types: change authoring workflow.
| Step | Work type | Closes gate | Rules |
|---|---|---|---|
| 1 | implementation |
implementation |
Code/e2e changes; Jest + unit-focused tier; .only / tight area narrowing OK locally; no commit |
| 2 | independent-review |
review |
Frozen tree; area-focused tier; no .only; area narrowing only in tests/app.js + tests/globals.js; serial host rule |
| 3 | commit |
commit |
One focused commit only after review_gate closed with validation/coverage evidence recorded |
Canonical commands: serialized dispatch, one iteration, guard probes.
Per SDK audit §6: one function/commit; remove guard; restore full iOS e2e assertions; verify canonical iOS e2e only.
| Probe | Function | Rationale | implementation_gate |
review_gate |
next_work_type |
|---|---|---|---|---|---|
| J0-1 | stringRepeat |
iOS CHANGELOG 12.12.0 | closed | closed | — |
| J0-2 | switchOn |
iOS CHANGELOG 12.12.0 | closed | closed | — |
| J0-3 | trunc |
iOS CHANGELOG 12.11.0 | closed | closed | — |
| J0-4 | conditional |
ConditionalExpression 12.11.0; iOS wire conditional |
closed | closed | — |
| J0-5 | round |
No CHANGELOG; Android + bridge ok | closed | closed | — |
| J0-6 | substring |
SDK API present; generic iOS wire fails | closed | closed | — |
| J0-7 | timestampAdd |
SDK timestamp_add receiver wire |
closed | closed | — |
| J0-8 | timestampSubtract |
SDK timestamp_subtract; RNFB emits timestamp_sub |
closed | closed | — |
| J0-9 | arrayGet |
SDK array_get receiver wire |
closed | closed | — |
Output: unified cross-platform e2e, confirmed parity classifications.
Commit subject: refactor(firestore, ios): consolidate pipeline switchOn boolean receiver lowering
Why: switchOn landed a parallel coercion layer alongside existing stack-based lowering. Correctness verified; maintainability / drift risk if more one-off paths land before consolidation.
Goal: Consolidate J0-added boolean/receiver-chain lowering into shared NodeBuilder paths (align with Android scheduleBooleanReceiverChain / EnterObjectBooleanFrame where feasible). Remove fragile KVC probing where ExprBridge extraction exists. No behavior change — area-focused-tier Pipeline e2e must stay green (especially switchOn, stringRepeat, and any probe-specific cases).
Scope: packages/firestore/ios/RNFBFirestore/RNFBFirestorePipelineNodeBuilder.swift only (unless consolidation requires Parser touch — stop and note).
Protocol: Same Phase J iteration protocol — implementation (unit-focused, switchOn + affected probe tests) → independent-review (area-focused) → commit.
Gate for J1–J6: J0 complete + J0b committed + parity registry updated.
Status: complete — J0-6′…J0-9′ receiver-chain batch: iOS lowering, empty guard list, unified e2e.
Scope delivered: RNFBFirestorePipelineNodeBuilder.swift receiver infrastructure + unified e2e at substring / arrayGet (×2) / timestampAdd|Subtract sites. JS iOS function guard removed.
| Function | SDK wire (pinned iOS) | Fix |
|---|---|---|
substring |
substring [self, position, length?] |
.substring(position:length:) receiver chain |
timestampAdd |
timestamp_add [self, unit, amount] |
.timestampAdd(amount:unit:) (amount first in SDK) |
timestampSubtract |
timestamp_subtract [self, unit, amount] |
Wire timestamp_subtract + receiver chain |
arrayGet |
array_get [self, offset] |
.arrayGet(_:) receiver chain |
| Step | Registry | Work |
|---|---|---|
| J1 | P-001 | Android operand coercion parity |
| J2 | P-005 | Android integerLiteral constant lowering |
| J3 | P-010 | Expression-valued distanceField / indexField on Android |
| J4 | P-011 | Parser constant envelope routing |
| J5 | P-012 | timestampTruncate arity validation on Android |
| J6 | P-034 | Unify operand-mode e2e after bridge parity |
Gate for Phase K+: J0 complete + J0b committed + J1–J6 bridge commits + parity Resolved updated.
Status: closed — full-tier 3-platform; iOS fix 38cc8815a (fix(firestore, ios): align pipeline stage option coercion with Android).
| Platform | Exit | Pass / Fail / Pending | Log |
|---|---|---|---|
| macOS | 0 | 698 / 0 / 38 | /tmp/rnfb-e2e-macos-r-full.log |
| iOS | 0 | 838 / 0 / 87 | /tmp/rnfb-e2e-ios-r-full-rerun.log |
| Android | 0 | 866 / 0 / 58 | /tmp/rnfb-e2e-android-r-full.log |
R-iOS fix: coerceStageOptionFieldName for unnest/findNearest; limit/offset defer to bridge factory. Area-focused 151/0; full-tier iOS re-run 838/0.
Gap map: bash scripts/map-pipeline-coverage-gaps.sh after-phase-r-final; snapshot scripts/snapshot-pipeline-coverage.sh after-phase-r-final. TS + iOS + Android coverage artifacts present (coverage/lcov.info, coverage/ios-native/lcov.info, Jacoco).
| Phase | Target |
|---|---|
| K | pipeline_runtime.ts + expressions.ts normalization gaps |
| L | Android parsed-aggregate expression args (~143 missed) |
| M | Android exit frames, receiver chains, vector expression handler (F tail) |
| N | iOS stage coercion (~293 missed), operand tail |
| O | Android Executor error branches |
| P | Jest-only TS validation paths |
| Q | Intractability audit (map execute, debug gates, codegen caps) |
R: revert harness narrowing; full unfocused 3-platform run (full tier); final gate before compare-types.
- Push state (committed): full test app — all
platformSupportedModules+require.contextintests/app.js. For merge/CI only; not the harness for local:test-coverduring J–Q. - Local
:test-cover: must match arbiter**validation_tier** — running e2e § harness + narrowing gate.**implementation→ unit-focused** and**independent-review→ area-focused:** both require area narrowing locally before first run even when git has full harness. Revert before R (full tier). tests/globals.js—RNFBDebug = trueoptional locally for fail-fast; committed default must stayfalse(running e2e § RNFBDebug)
Phases I–J (parity):
- Audit or implement bridge fix with shared e2e assertions.
- Update OKF parity registry (open/close rows).
- Phase J: follow Phase J iteration protocol —
implementation(Jest + unit-focused tier) →independent-review(area-focused tier, frozen tree) →commit; never commit beforereview_gateclosed; never overlap:test-cover(host rule). - 3-platform e2e on canonical commands (running-e2e rules 6–7).
Phases K–Q (coverage):
bash scripts/map-pipeline-coverage-gaps.sh before-<id>- Prove live vs dead before implementing
- No new
Platform.branches* — if a probe only passes on one platform, stop and file drift for Phase J follow-up - OKF background +
:buildif native +:test-cover+ native post-process bash scripts/map-pipeline-coverage-gaps.sh after-<id>- One focused commit per logical change (message describes what, not phase letter)
Pitfalls: iOS constant(0/1) → bool (use constant(2+)); raw AND where is Android-native (Platform.other skip on macOS; document); Detox boots AVD, no manual emulator -avd.
Audit method: caller grep + buildNativePipeline stack trace for union routing; Parser owns readableMapToJava for execute entry.
Removed (Android Executor, zero callers):
| Cluster | Lines | Rationale |
|---|---|---|
getJavaValue / readableMapToJava / readableArrayToJava / populateReadableContainers + frame classes |
~200 | Duplicate Parser helpers; no call sites in Executor |
applyPrimitiveRawOptions |
~42 | Superseded by applyPrimitiveRawStageOptions (live at applyRawStage) |
applyUnionStage + applyStage union branch |
~9 | Unions handled in buildNativePipeline via PendingUnionPipelineStage; ParsedUnionStage never reaches applyStage |
Intractable (document only — no removal):
| Cap | Location | Rationale |
|---|---|---|
validateSource default param |
pipeline_validate.ts L49 |
Sole call site passes explicit `${fieldName}.source`; default unreachable; harmless |
| Map passthrough execute success | NodeBuilder L1208–1219 (G) | Firestore rejects map(field(…)) execute |
| Map execute / task-guard tails | Executor resolvePipelineTask empty-exception arm |
e2e-only; no stable probe |
| iOS operand-mode tail | NodeBuilder L928–1006 | Bridge parity closed; residual misses are SDK-shaped |
- A: Jet WS coverage transfer; 3-platform TS lcov baseline.
- B: Removed Android
buildParsed* (~690 lines, 0%). - C:
map-pipeline-coverage-gaps.sh. - D: Subcollection 100%; schedule dispatch 100%; lowering e2e expansion.
- E: Executor 49%→58%; database/rawOptions/sample/findNearest/unnest/rawStage e2e.