diff --git a/okf-bundle/ci-workflows/android.md b/okf-bundle/ci-workflows/android.md
new file mode 100644
index 000000000..f834b75d5
--- /dev/null
+++ b/okf-bundle/ci-workflows/android.md
@@ -0,0 +1,46 @@
+---
+type: Reference
+title: Android CI workflow
+description: Shape and triage notes for .github/workflows/android.yml.
+tags: [ci, gradle, android]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Android CI
+
+Workflow: [.github/workflows/android.yml](../../.github/workflows/android.yml)
+
+## Triggers
+
+- `pull_request`
+- `push`
+
+## Job shape
+
+| Step | Detail |
+|------|--------|
+| Runner | `ubuntu-latest`, 30m timeout |
+| Checkout | `actions/checkout` (pinned) |
+| Cache | `~/.gradle/caches`, `~/.gradle/wrapper` keyed on Gradle files |
+| JDK | Temurin **21** |
+| Build | `./scripts/build.sh` |
+| On failure | `./scripts/print_build_logs.sh` |
+
+
+
+## What `build.sh` runs
+
+Canonical owner for the CI unit-path step list. Script: [scripts/build.sh](../../scripts/build.sh).
+
+1. Copy `library/google-services.json` → `app/` and `proguard-tests/`
+2. `./gradlew --max-workers=2 clean`
+3. `./gradlew --max-workers=2 assembleDebug`
+4. `./gradlew --max-workers=2 checkstyle`
+5. `./gradlew --max-workers=2 testDebugUnitTest -x :e2eTest:testDebugUnitTest`
+
+`proguard-tests:build` is currently commented out (re-enable before release). Green Android CI does **not** prove ProGuard/R8 packaging.
+
+## Agent notes
+
+- Match this path locally with `./scripts/build.sh` — [agent command policy](../testing/agent-command-policy.md).
+- Do not treat this job as e2e coverage; that is [e2e.md](e2e.md).
diff --git a/okf-bundle/ci-workflows/e2e.md b/okf-bundle/ci-workflows/e2e.md
new file mode 100644
index 000000000..74a812078
--- /dev/null
+++ b/okf-bundle/ci-workflows/e2e.md
@@ -0,0 +1,35 @@
+---
+type: Reference
+title: E2E CI workflow
+description: Shape and triage notes for .github/workflows/e2e_test.yml.
+tags: [ci, e2e, emulator, auth]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# E2E CI
+
+Workflow: [.github/workflows/e2e_test.yml](../../.github/workflows/e2e_test.yml)
+
+## Triggers
+
+- `pull_request` only (not `push`)
+
+## Job shape
+
+| Step | Detail |
+|------|--------|
+| Runner | `ubuntu-latest`, 30m timeout |
+| Checkout | `actions/checkout` (pinned) |
+| Caches | Gradle caches/wrapper; `~/.cache/firebase/emulators` |
+| Node | **20** |
+| JDK | Temurin **21** |
+| Tools | `npm i -g firebase-tools` |
+| Emulator | `./scripts/start-firebase-emulator.sh` (`CI` set → background + readiness poll) |
+| Tests | `./gradlew e2eTest` |
+| On failure | `./scripts/print_build_logs.sh` |
+
+## Agent notes
+
+- Local procedure and suite semantics: [running e2e](../testing/running-e2e.md).
+- Auth emulator only — do not invent multi-emulator CI.
+- Unit CI excludes `:e2eTest`; this job is the canonical e2e gate for Auth UI changes.
diff --git a/okf-bundle/ci-workflows/index.md b/okf-bundle/ci-workflows/index.md
new file mode 100644
index 000000000..10d0cafb9
--- /dev/null
+++ b/okf-bundle/ci-workflows/index.md
@@ -0,0 +1,19 @@
+# CI workflows
+
+GitHub Actions job shape and failure triage for FirebaseUI-Android.
+
+## Jobs
+
+* [Android CI](android.md) — `android.yml`: JDK 21, Gradle cache, `./scripts/build.sh`
+* [E2E Tests](e2e.md) — `e2e_test.yml`: firebase-tools, Auth emulator, `./gradlew e2eTest`
+
+## Shared dependencies
+
+* [Agent command policy](../testing/agent-command-policy.md) — allowlisted commands for agents
+* [Running e2e — e2e agent rule](../testing/running-e2e.md#e2e-agent-rule) — emulator + `e2eTest` only
+* [Validation checklist](../testing/validation-checklist.md) — local handoff sequence matching CI
+
+## Related
+
+* [Running e2e tests](../testing/running-e2e.md) — local runbook
+* [Repo tooling](../repo-tooling/index.md) — Gradle modules, versioning
diff --git a/okf-bundle/documentation-policy.md b/okf-bundle/documentation-policy.md
new file mode 100644
index 000000000..54739080f
--- /dev/null
+++ b/okf-bundle/documentation-policy.md
@@ -0,0 +1,74 @@
+---
+type: Reference
+title: OKF documentation and commit policy
+description: Canonical rules for durable vs ephemeral knowledge, commit messages, and post-update bundle consistency.
+tags: [okf, documentation, policy, commits, work-queue]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# OKF documentation and commit policy
+
+Single source of truth for OKF knowledge and commit wording. Other OKF docs/work queues link here; do not restate.
+
+## Durable vs ephemeral
+
+| Kind | Where it lives | What it contains |
+|------|----------------|------------------|
+| **Durable** | OKF reference docs (design, runbooks, registries, workflows) | Stable API names, module layout, SDK/tooling versions, verification **methods**, architecture, canonical commands |
+| **Ephemeral** | Explicit **work-queue** docs only | Session phase/probe IDs, **planned commit subjects** (`commit_subject`), gate state, `next_work_type`, snapshot labels, dated banners, run counts |
+
+**Rules**
+
+1. General OKF docs get **durable only** updates: no phase IDs, **commit subjects**, session e2e counts, or gate snapshots.
+2. Ephemeral state lives **only** in work queues. When an item closes, durable outcomes move to reference docs; queue rows may archive/delete.
+3. Durable docs may link to a work queue for current status; do not duplicate ephemeral fields.
+4. Create a work-queue doc only when active cross-cutting work needs gate tracking. Do not invent empty queues for completed migrations.
+
+## Commits as documentation
+
+We treat **git commits** as durable documentation: they are the canonical record of what changed, when, and why — for humans and agents reviewing history later, not only for the current PR thread.
+
+Commit messages use [Conventional Commits](https://www.conventionalcommits.org/) and describe durable product/process deliverables: what changed and why, not probe IDs, gates, e2e counts, or “phase X complete”.
+
+Scopes commonly used in this repo: `auth`, `firestore`, `database`, `storage`, `common`, `ci`, `deps`, `docs`. Prefer the Gradle module name when the change is module-scoped.
+
+Examples from [CONTRIBUTING.md](../CONTRIBUTING.md):
+
+```text
+fix(auth): fixed a bug with email sign-in!
+feat(auth): add support for passkey authentication
+```
+
+## Pull requests
+
+When a PR contains **exactly one commit**, the **PR title must match that commit's subject line exactly** (character-for-character). Multi-commit PRs use a summary title that describes the overall change set.
+
+PR process expectations live in [.github/PULL_REQUEST_TEMPLATE.md](../.github/PULL_REQUEST_TEMPLATE.md) and [CONTRIBUTING.md](../CONTRIBUTING.md). New features that affect Auth UX should consider [FirebaseUI-iOS](https://github.com/firebase/FirebaseUI-iOS) parity.
+
+## OKF update contract
+
+OKF markdown edits require an **independent bundle consistency pass**. Use a fresh context with:
+
+1. A short summary of what changed and which files were touched.
+2. Instruction to scan the **entire** `okf-bundle/` tree.
+
+Confirm:
+
+| Check | Requirement |
+|-------|-------------|
+| **Canonical location** | Each topic has one owning doc; others link to it ([agent command policy](testing/agent-command-policy.md) for **all** agent shell commands; [change authoring](testing/change-authoring-workflow.md) for workflow/gates/frozen tree; [change authoring § validation evidence (blocking)](testing/change-authoring-workflow.md#validation-evidence-blocking); [running e2e](testing/running-e2e.md) for emulator + `e2eTest` detail; [iteration vocabulary](testing/iteration-vocabulary.md) for term ids only; [validation checklist](testing/validation-checklist.md) for command sequence; this file for doc/commit policy) |
+| **DRY** | No duplicated procedures, policy paragraphs, or ephemeral snapshots outside work queues |
+| **Link hygiene** | Cross-links resolve; indexes list canonical entry points |
+| **Durability** | No ephemeral fields leaked into general reference docs |
+
+Fix violations before handoff/merge. Work-queue edits still follow this split.
+
+## Work-queue documents
+
+Work queues are **intentionally ephemeral**: phases, **commit subjects**, gates, active coordination. They are not policy or finalized registry/design homes.
+
+Work queues record **gates**, **`next_work_type`**, **`validation_tier`**, and **`commit_subject`** using field names and allowed values from [iteration vocabulary](testing/iteration-vocabulary.md). Gate semantics and workflow rules: [change authoring workflow](testing/change-authoring-workflow.md). They do **not** name agent roles, dispatch instructions, or session choreography — those are out of scope for the public repo.
+
+Record **`commit_subject`** (the planned Conventional Commit subject line) **before** `git commit`, in the same staged changeset as the item being memorialized. Do not record SHAs — they are unstable under history rewrite. After commit, the subject in git and in the queue must match character-for-character ([PR title rule](#pull-requests) for single-commit PRs).
+
+New work queues link here in frontmatter/opening section; do not copy policy inline.
diff --git a/okf-bundle/index.md b/okf-bundle/index.md
new file mode 100644
index 000000000..cf5a5a894
--- /dev/null
+++ b/okf-bundle/index.md
@@ -0,0 +1,29 @@
+---
+okf_version: '0.1'
+---
+
+# FirebaseUI-Android knowledge bundle
+
+Agent-oriented knowledge for [firebase/FirebaseUI-Android](https://github.com/firebase/FirebaseUI-Android). Human-facing docs stay in `README.md`, `CONTRIBUTING.md`, module READMEs, and `docs/`.
+
+- [Documentation/commit policy](/documentation-policy.md) — durable vs ephemeral, commits as documentation, PR titles, OKF consistency
+
+# CI workflows
+
+- [CI workflows](/ci-workflows/index.md) — GitHub Actions job shape (`android.yml`, `e2e_test.yml`), failure log triage
+
+# Testing
+
+- [Agent command policy](/testing/agent-command-policy.md) — allowlisted shell commands for agents (Gradle, scripts, emulator, validation)
+- [Change authoring workflow](/testing/change-authoring-workflow.md) — verified product change loop (unit-focused → area-focused review → commit); [§ validation evidence (blocking)](/testing/change-authoring-workflow.md#validation-evidence-blocking)
+- [Iteration vocabulary](/testing/iteration-vocabulary.md) — work type, tier, and queue field identifiers
+- [Running e2e tests](/testing/running-e2e.md) — Auth emulator + `./gradlew e2eTest`
+- [Validation checklist](/testing/validation-checklist.md) — assemble, checkstyle, unit tests, e2e
+
+# Modules
+
+- [Modules](/modules/index.md) — auth, firestore, database, storage, common, and supporting Gradle modules
+
+# Repo tooling
+
+- [Repo tooling](/repo-tooling/index.md) — Gradle layout, versioning (`Config.kt`), release/branch pointers
diff --git a/okf-bundle/modules/auth.md b/okf-bundle/modules/auth.md
new file mode 100644
index 000000000..e96b686da
--- /dev/null
+++ b/okf-bundle/modules/auth.md
@@ -0,0 +1,55 @@
+---
+type: Reference
+title: Auth module notes
+description: Durable agent notes for firebase-ui-auth (Compose, configuration DSL, MFA, Credential Manager, tests).
+tags: [auth, compose, modules]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# `:auth` — firebase-ui-auth
+
+Primary Auth UI library. **v10+** is Kotlin + Jetpack Compose + Material 3 (breaking vs 9.x Views).
+
+## Layout
+
+| Path | Role |
+|------|------|
+| `com.firebase.ui.auth` | Core entrypoints (`FirebaseAuthUI`, flow/state types) |
+| `…/configuration` | `authUIConfiguration {}` DSL, `AuthProvider.*`, theme, validators, string provider |
+| `…/ui/screens` | Compose screens (`FirebaseAuthScreen`, email/phone/MFA, etc.) |
+| `…/ui/components` | Shared Compose widgets |
+| `…/ui/method_picker` | Provider picker |
+| `…/credentialmanager` | Android Credential Manager / password credentials |
+| `…/mfa` | MFA enrollment/challenge support |
+| `…/data`, `…/util` | Supporting types/helpers |
+
+Unit tests: `auth/src/test/…`. E2e: `e2eTest/src/test/…` — [running e2e](../testing/running-e2e.md).
+
+## Public integration surfaces
+
+Agents changing Auth should know both consumer APIs (do not break without migration notes):
+
+1. **High-level** — `FirebaseAuthScreen` + `authUIConfiguration { }` (Compose-first).
+2. **Low-level** — `AuthFlowController` for Activity-hosted flows.
+
+Consumer setup skill (outside this repo’s product code): `.agents/skills/firebaseui-android-getting-started/SKILL.md`.
+
+Human docs: [auth/README.md](../../auth/README.md), [docs/upgrade-to-10.0.md](../../docs/upgrade-to-10.0.md).
+
+## Validation
+
+Tier commands and handoff sequence: [validation checklist](../testing/validation-checklist.md). Auth UI / emulator path requires e2e — [running e2e § when required](../testing/running-e2e.md#when-e2e-is-required). Allowlist: [agent command policy](../testing/agent-command-policy.md).
+
+## Architectural facts (durable)
+
+- Configuration is Kotlin DSL (`AuthProvider.Email()`, etc.), not 9.x `IdpConfig` builders.
+- Theming uses `AuthUITheme` / Material 3, not XML Auth themes as the primary path.
+- State is reactive (`Flow`-oriented Auth state), not only `AuthStateListener` callbacks.
+- Credential Manager integration lives under `credentialmanager/` — treat password-save/retrieve as Auth-critical surface.
+- MFA (SMS/TOTP) has dedicated screens and e2e coverage (`MfaEnrollmentScreenTest`, `MfaChallengeScreenTest`, …).
+
+## Related
+
+* [Modules index](index.md)
+* [E2e CI](../ci-workflows/e2e.md)
+* [Change authoring](../testing/change-authoring-workflow.md)
diff --git a/okf-bundle/modules/common.md b/okf-bundle/modules/common.md
new file mode 100644
index 000000000..e63013833
--- /dev/null
+++ b/okf-bundle/modules/common.md
@@ -0,0 +1,26 @@
+---
+type: Reference
+title: Common module notes
+description: Durable agent notes for shared firebase-ui-common adapter primitives.
+tags: [common, modules]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# `:common` — firebase-ui-common
+
+Published shared Java primitives used by Firestore and Realtime Database UI adapters (`POM_ARTIFACT_ID=firebase-ui-common`). Not a primary consumer README surface like auth/firestore/database/storage — treat it as a shared library dependency those modules consume.
+
+## Key types
+
+| Type | Role |
+|------|------|
+| `BaseObservableSnapshotArray` | Base observable snapshot list |
+| `BaseCachingSnapshotParser` / `BaseSnapshotParser` | Parser bases |
+| `BaseChangeEventListener` / `ChangeEventType` | Change-event plumbing |
+| `Preconditions` | Shared precondition helpers |
+
+## Validation
+
+No `src/test` / `androidTest` today — empty-suite trap: [agent command policy](../testing/agent-command-policy.md#empty-unit-suite-trap). Commands and tiers: [validation checklist](../testing/validation-checklist.md) (module matrix).
+
+**Module-specific:** changes here can break `:firestore` and `:database`. Prefer also running `./gradlew :firestore:testDebugUnitTest` (real JVM suite) when the shared API is consumed there. Database has no JVM unit suite — [database.md](database.md).
diff --git a/okf-bundle/modules/database.md b/okf-bundle/modules/database.md
new file mode 100644
index 000000000..a3243f848
--- /dev/null
+++ b/okf-bundle/modules/database.md
@@ -0,0 +1,35 @@
+---
+type: Reference
+title: Database module notes
+description: Durable agent notes for firebase-ui-database adapters and paging.
+tags: [database, modules]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# `:database` — firebase-ui-database
+
+Java library binding Realtime Database references to RecyclerView / ListView (and AndroidX Paging).
+
+## Key types
+
+| Type | Role |
+|------|------|
+| `FirebaseRecyclerAdapter` | RecyclerView adapter |
+| `FirebaseListAdapter` | ListView adapter |
+| `FirebaseRecyclerOptions` / `FirebaseListOptions` | Options builders |
+| `FirebaseArray` / `FirebaseIndexArray` | Observable arrays (including indexed keys/values) |
+| `SnapshotParser` family | Snapshot → model mapping |
+| `paging/*` | Paging adapters/sources |
+
+Human docs: [database/README.md](../../database/README.md).
+
+## Tests / validation
+
+- No JVM `src/test`. Instrumented tests live under `database/src/androidTest` (human/device only — not CI / not allowlisted).
+- Empty-suite trap: [agent command policy](../testing/agent-command-policy.md#empty-unit-suite-trap).
+- Commands and tiers: [validation checklist](../testing/validation-checklist.md) (module matrix).
+
+## Related
+
+* Shared primitives: [common.md](common.md)
+* Firestore counterpart: [firestore.md](firestore.md)
diff --git a/okf-bundle/modules/firestore.md b/okf-bundle/modules/firestore.md
new file mode 100644
index 000000000..17e600e4d
--- /dev/null
+++ b/okf-bundle/modules/firestore.md
@@ -0,0 +1,35 @@
+---
+type: Reference
+title: Firestore module notes
+description: Durable agent notes for firebase-ui-firestore adapters and paging.
+tags: [firestore, modules]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# `:firestore` — firebase-ui-firestore
+
+Java library binding Cloud Firestore queries to RecyclerView (and AndroidX Paging).
+
+## Key types
+
+| Type | Role |
+|------|------|
+| `FirestoreRecyclerAdapter` | Lifecycle-aware RecyclerView adapter |
+| `FirestoreRecyclerOptions` | Query/options builder for the adapter |
+| `FirestoreArray` / `ObservableSnapshotArray` | Observable snapshot list |
+| `SnapshotParser` / `ClassSnapshotParser` / `CachingSnapshotParser` | Document → model mapping |
+| `paging/*` (`FirestorePagingAdapter`, `FirestorePagingSource`, …) | AndroidX Paging integration |
+
+Human docs: [firestore/README.md](../../firestore/README.md).
+
+## Tests / validation
+
+- JVM unit suite: `firestore/src/test`
+- Instrumented: `firestore/src/androidTest` — human/device only (not CI / not allowlisted)
+- Tier commands and evidence: [validation checklist](../testing/validation-checklist.md)
+- Auth emulator e2e is **not** required for Firestore-only changes — [running e2e § when required](../testing/running-e2e.md#when-e2e-is-required)
+
+## Related
+
+* Shared adapter primitives: [common.md](common.md)
+* Parallel Realtime Database adapters: [database.md](database.md)
diff --git a/okf-bundle/modules/index.md b/okf-bundle/modules/index.md
new file mode 100644
index 000000000..ee3af3980
--- /dev/null
+++ b/okf-bundle/modules/index.md
@@ -0,0 +1,30 @@
+# Modules
+
+Published library modules and supporting Gradle projects. Human-facing usage docs: module `README.md` files and [docs/](../../docs/).
+
+## Published libraries
+
+| Module | Artifact | Language / UI | OKF notes |
+|--------|----------|---------------|-----------|
+| `:auth` | `firebase-ui-auth` | Kotlin, Jetpack Compose (v10+) | [auth.md](auth.md) |
+| `:firestore` | `firebase-ui-firestore` | Java, RecyclerView / Paging | [firestore.md](firestore.md) |
+| `:database` | `firebase-ui-database` | Java, RecyclerView / ListView / Paging | [database.md](database.md) |
+| `:storage` | `firebase-ui-storage` | Java, Glide | [storage.md](storage.md) |
+| `:common` | `firebase-ui-common` | Java (shared adapter primitives) | [common.md](common.md) |
+
+Version and SDK floors: `buildSrc/.../Config.kt` — [repo tooling](../repo-tooling/index.md).
+
+## Supporting modules
+
+| Module | Role |
+|--------|------|
+| `:library` | Umbrella / publish aggregation (`prepareArtifacts`) |
+| `:app` | Demo app (Auth Compose sample) |
+| `:e2eTest` | Auth emulator e2e (Robolectric + Compose UI test) |
+| `:proguard-tests` | R8/ProGuard packaging checks (disabled in CI unit path — [Android CI](../ci-workflows/android.md)) |
+| `:lint`, `:internal:lint`, `:internal:lintchecks` | Custom lint plumbing |
+| `buildSrc` | Shared `Config` (version, SDK levels, submodule list) |
+
+## Cross-cutting note (v10 Auth)
+
+FirebaseUI Auth **10.x** is a Compose rewrite (breaking vs 9.x Views). User migration: [docs/upgrade-to-10.0.md](../../docs/upgrade-to-10.0.md). Firestore/database/storage remain View-based; there is no active Compose migration work-queue for those modules unless one is opened later ([documentation policy § work queues](../documentation-policy.md#work-queue-documents)).
diff --git a/okf-bundle/modules/storage.md b/okf-bundle/modules/storage.md
new file mode 100644
index 000000000..f82e56320
--- /dev/null
+++ b/okf-bundle/modules/storage.md
@@ -0,0 +1,20 @@
+---
+type: Reference
+title: Storage module notes
+description: Durable agent notes for firebase-ui-storage Glide integration.
+tags: [storage, modules]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# `:storage` — firebase-ui-storage
+
+Small Java library integrating Firebase Storage with Glide (`FirebaseImageLoader` and related image loading types under `…/storage/images`).
+
+## Agent notes
+
+- Consumers must register an `AppGlideModule` — see [storage/README.md](../../storage/README.md).
+- Keep the surface minimal; prefer fixing loader/Glide contract bugs with unit tests under `storage/src/test`.
+
+## Validation
+
+JVM unit suite under `storage/src/test`. Tier commands and evidence: [validation checklist](../testing/validation-checklist.md). Auth emulator e2e is not in scope for Storage-only changes — [running e2e § when required](../testing/running-e2e.md#when-e2e-is-required).
diff --git a/okf-bundle/repo-tooling/index.md b/okf-bundle/repo-tooling/index.md
new file mode 100644
index 000000000..1a6c2c7e0
--- /dev/null
+++ b/okf-bundle/repo-tooling/index.md
@@ -0,0 +1,44 @@
+---
+type: Reference
+title: Repo tooling
+description: Gradle multi-module layout, versioning, and release/branch pointers for FirebaseUI-Android.
+tags: [gradle, tooling, release]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Repo tooling
+
+## Gradle layout
+
+- Root build: `build.gradle.kts`, `settings.gradle`, `gradle.properties`, Wrapper via `./gradlew`
+- Version catalog: `gradle/libs.versions.toml`
+- Shared constants: `buildSrc/src/main/kotlin/Config.kt`
+ - `Config.version` (e.g. `10.0.0-beta03`)
+ - `Config.submodules` = `auth`, `common`, `firestore`, `database`, `storage`
+ - `Config.SdkVersions` — compile / target / min
+- Checkstyle: `library/quality/checkstyle.xml`
+- Included modules: see root `settings.gradle` and [modules/index](../modules/index.md)
+
+## Canonical scripts
+
+| Script | Role |
+|--------|------|
+| `scripts/build.sh` | CI unit path — step list in [Android CI](../ci-workflows/android.md#what-buildsh-runs) |
+| `scripts/start-firebase-emulator.sh` | Auth emulator for e2e — [running e2e](../testing/running-e2e.md) |
+| `scripts/print_build_logs.sh` | CI failure log dump |
+
+Command policy: [agent command policy](../testing/agent-command-policy.md). Note: PR template still says `./gradlew check`; agents use `./scripts/build.sh` — [PR template trap](../testing/agent-command-policy.md#pr-template-gradlew-check).
+
+## Branching / release (pointers)
+
+Human-maintained process docs (do not duplicate procedures here):
+
+* [docs/internal/branching.md](../../docs/internal/branching.md)
+* [docs/internal/releasing.md](../../docs/internal/releasing.md)
+
+Agents must **not** publish to Maven Central / Sonatype unless the user explicitly requests release work. **Release procedure owner:** [docs/internal/releasing.md](../../docs/internal/releasing.md) (includes `:library:prepareArtifacts` for remote publish). Optional **local-only** verify (not the release procedure): `./gradlew :library:prepareArtifacts publishToMavenLocal`.
+
+## Demo / config files
+
+- Template Firebase config: `library/google-services.json` (copied by `build.sh` into `app/` and `proguard-tests/`)
+- E2e emulator config: `e2eTest/firebase.json`, `e2eTest/.firebaserc`
diff --git a/okf-bundle/testing/agent-command-policy.md b/okf-bundle/testing/agent-command-policy.md
new file mode 100644
index 000000000..94fa7b057
--- /dev/null
+++ b/okf-bundle/testing/agent-command-policy.md
@@ -0,0 +1,128 @@
+---
+type: Reference
+title: Agent command policy
+description: Canonical allowlist for agent shell commands — Gradle, scripts, emulator, and validation. Supersedes improvised diagnostics.
+tags: [testing, validation, agents, workflow, gradle]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Agent command policy
+
+Single source for **which shell commands agents may run** in this repo. E2e is a subset of this policy; [running e2e § e2e agent rule](running-e2e.md#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, module READMEs, or Gradle task help.
+
+## Agent rule (read first)
+
+
+
+1. Run **only** commands in the [registry](#canonical-registry) below (repo root unless noted).
+2. Prefer **`./scripts/build.sh`** for the CI-equivalent unit build/test path (step list: [Android CI](../ci-workflows/android.md#what-buildsh-runs)). Do not invent alternate Gradle task graphs that skip `checkstyle` or re-include `:e2eTest` unit tests in the unit CI path.
+3. When a canonical command fails: read the **full** output, fix **product code** (or environment prerequisites), re-run the **same** command. Do **not** switch invocation style.
+4. Do **not** infer alternate commands from error strings — see [known traps](#known-traps).
+5. Subagents (Task, explore, orchestrator): same rule — paste the [handoff block](#subagent-handoff) into every FirebaseUI-Android task prompt.
+
+## Canonical registry
+
+| Intent | Command | Never use instead |
+|--------|---------|-------------------|
+| Full CI unit path (assemble + checkstyle + unit tests) | `./scripts/build.sh` | Ad-hoc `./gradlew clean assembleDebug test` without checkstyle; inventing a different exclusion set |
+| Unit tests (all library modules; exclude e2eTest) | `./gradlew testDebugUnitTest -x :e2eTest:testDebugUnitTest` | Bare `./gradlew test` (pulls wrong tasks / e2e); IDE-only as the agent gate |
+| Unit tests (one module with a real `src/test` suite) | `./gradlew ::testDebugUnitTest` (e.g. `:auth:testDebugUnitTest`, `:firestore:…`, `:storage:…`) | `:common:testDebugUnitTest` / `:database:testDebugUnitTest` as “green” evidence (empty suites — [empty unit-suite trap](#empty-unit-suite-trap)); full suite when only one module changed *as a substitute for* the CI path at handoff |
+| Assemble one module (when no JVM unit suite) | `./gradlew ::assembleDebug` (e.g. `:database`, `:common`) | Treating empty `testDebugUnitTest` as validation |
+| Checkstyle | `./gradlew checkstyle` | Invented ktlint/detekt entrypoints; editing files without re-running checkstyle when Java/Kotlin style is in scope |
+| Assemble debug | `./gradlew assembleDebug` | Module-scoped assemble as the only CI substitute at handoff |
+| Install demo app | `./gradlew :app:installDebug` | Manual APK sideload scripts |
+| Start Auth emulator (e2e prerequisite) | `./scripts/start-firebase-emulator.sh` | Bare `firebase emulators:start` with invented flags/ports; starting Firestore/Database emulators “just in case” |
+| E2e suite | `./gradlew e2eTest` (emulator already up) | `./gradlew :e2eTest:testDebugUnitTest` as a silent substitute without understanding the custom task; inventing Espresso/`connectedCheck` for this suite |
+| CI failure logs | `./scripts/print_build_logs.sh` | Truncating Gradle logs / guessing from partial output |
+| Local Maven publish (optional local verify only) | `./gradlew :library:prepareArtifacts publishToMavenLocal` | Treating this as the Maven Central release procedure ([releasing.md](../../docs/internal/releasing.md) owns release); remote publish unless the user explicitly requested a release |
+| Validation sequence | [validation checklist](validation-checklist.md) | Partial one-off task lists that omit checkstyle or the e2e exclusion |
+
+### JDK / tooling floor
+
+- **JDK 21+** (CI uses Temurin 21) — [CONTRIBUTING.md](../../CONTRIBUTING.md).
+- **Android SDK** with min API aligned to `Config.SdkVersions.min` in `buildSrc`.
+- E2e also needs **Node.js**, **npm**, **firebase-tools**, and **jq** (script preflights firebase/node/npm; `jq` is required to parse `e2eTest/.firebaserc` / `firebase.json` but is not preflight-checked — [running e2e](running-e2e.md)).
+
+### `google-services.json` copy
+
+`./scripts/build.sh` copies `library/google-services.json` → `app/` and `proguard-tests/`. Prefer the script over hand-copying. Replace `library/google-services.json` only when intentionally pointing the demo/proguard modules at a different Firebase project.
+
+## When a Gradle command fails
+
+1. Re-run from repo root with the **same** canonical command (full log — do not truncate). On CI-shaped failures, also run `./scripts/print_build_logs.sh`.
+2. Fix **product code** or missing prerequisites (JDK, SDK, emulator online).
+3. Re-run the **same** command.
+4. Do **not** “verify tooling” with invented Gradle flags, alternate tasks, or skipping checkstyle.
+
+## Forbidden (always)
+
+| Command / pattern | Why |
+|-------------------|-----|
+| Improvised `./gradlew …` graphs not in the registry or validation checklist | Wrong task / cwd / exclusions; invents CI that does not match `.github/workflows` |
+| Including `:e2eTest:testDebugUnitTest` in the unit CI path without an emulator | E2e suite expects Auth emulator; unit CI explicitly excludes it (`scripts/build.sh`) |
+| Bare `firebase emulators:start` with custom ports | Ports and project ID come from `e2eTest/firebase.json` / `.firebaserc` via the start script |
+| `connectedAndroidTest` / device Espresso as a substitute for `e2eTest` | Canonical e2e is Robolectric + emulator via `./gradlew e2eTest` |
+| Invented formatters (`ktlintFormat`, random `spotlessApply`) as the style gate | Canonical style gate is `./gradlew checkstyle` |
+| Publishing to Maven Central / Sonatype unless the user explicitly requested a release | Release process is human-gated — [repo tooling](../repo-tooling/index.md) |
+
+## Known traps
+
+
+
+### e2eTest vs unit exclusion
+
+- **Unit CI** runs `testDebugUnitTest -x :e2eTest:testDebugUnitTest`.
+- **E2e CI** starts the Auth emulator, then runs the custom Gradle task **`e2eTest`** (registered in `e2eTest/build.gradle.kts`), not a connected device suite.
+- Running `:e2eTest:testDebugUnitTest` without the emulator is not the CI e2e path.
+
+
+
+### Empty unit-suite trap (`:common`, `:database`)
+
+- `:common` has **no** test source set. `:database` has **only** `androidTest` (no `src/test`).
+- `./gradlew :common:testDebugUnitTest` / `:database:testDebugUnitTest` can exit **0 with zero tests** — that is **not** validation evidence.
+- Modules with real JVM unit suites today: `:auth`, `:firestore`, `:storage` (and `:e2eTest` via the custom `e2eTest` task, not the unit CI path).
+- Instrumented `connectedAndroidTest` is forbidden as an Auth e2e substitute and is **not** an allowlisted database/firestore gate (not run in `android.yml`). Module matrix: [validation checklist](validation-checklist.md#module-validation-matrix).
+
+
+
+### PR template `./gradlew check`
+
+- [.github/PULL_REQUEST_TEMPLATE.md](../../.github/PULL_REQUEST_TEMPLATE.md) mentions `./gradlew check` (stale vs current CI).
+- **Agents:** treat **`./scripts/build.sh`** as the CI-matching unit path — [Android CI](../ci-workflows/android.md). Full handoff (including e2e when Auth UI touched): [validation checklist](validation-checklist.md).
+
+### ProGuard tests disabled in build.sh
+
+- See [Android CI § `build.sh`](../ci-workflows/android.md#what-buildsh-runs) — `proguard-tests:build` is commented out; green unit CI does not prove ProGuard/R8.
+
+### Emulator foreground vs CI
+
+- Locally, `./scripts/start-firebase-emulator.sh` runs the emulator in the **foreground** (blocking). Start it in a separate terminal (or backgrounded shell the agent can leave running), then run `./gradlew e2eTest` in another.
+- In CI (`CI` set), the script backgrounds the emulator and waits until `FIREBASE_AUTH_EMULATOR_URL` responds.
+
+## Subagent handoff
+
+Paste into Task / explore / work-queue prompts:
+
+```text
+FirebaseUI-Android agent command policy: okf-bundle/testing/agent-command-policy.md ONLY.
+Unit CI path: ./scripts/build.sh (or the exact gradle tasks it runs) — never invent alternate graphs.
+Unit tests: ./gradlew testDebugUnitTest -x :e2eTest:testDebugUnitTest OR ./gradlew ::testDebugUnitTest only for modules with src/test (auth/firestore/storage). Never treat :common/:database testDebugUnitTest as evidence (empty suites).
+Style: ./gradlew checkstyle ONLY — do not invent ktlint/detekt entrypoints.
+E2e: ./scripts/start-firebase-emulator.sh then ./gradlew e2eTest — okf-bundle/testing/running-e2e.md.
+Never: bare firebase emulators:start with invented ports; connectedCheck as e2e substitute; Maven Central publish unless user asked.
+On failure: fix product code / prerequisites, re-run the same canonical command; use ./scripts/print_build_logs.sh for CI-shaped failures.
+Gate close / push: return validation evidence package from okf-bundle/testing/validation-checklist.md — required before commit or publication (okf-bundle/testing/change-authoring-workflow.md#validation-evidence-blocking).
+```
+
+## Related docs
+
+| Topic | Owner |
+|-------|--------|
+| E2e commands, emulator, narrowing | [running-e2e.md](running-e2e.md) |
+| Handoff validation sequence | [validation-checklist.md](validation-checklist.md) |
+| Work types and gates | [change-authoring-workflow.md](change-authoring-workflow.md) |
+| Doc / commit policy | [documentation-policy.md](../documentation-policy.md) |
+| CI job shape | [ci-workflows/index.md](../ci-workflows/index.md) |
diff --git a/okf-bundle/testing/change-authoring-workflow.md b/okf-bundle/testing/change-authoring-workflow.md
new file mode 100644
index 000000000..34cb30879
--- /dev/null
+++ b/okf-bundle/testing/change-authoring-workflow.md
@@ -0,0 +1,223 @@
+---
+type: Reference
+title: Change authoring workflow
+description: Canonical cross-module loop for verified product changes — baseline, unit-focused implementation, area-focused review, documentation, commit, and pre-merge validation.
+tags: [testing, validation, workflow, implementation, review]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Change authoring workflow
+
+Single source for **how to author and verify a product change** in FirebaseUI-Android (bug fix, feature, migration follow-up). Module docs add artifacts; work queues add ephemeral gate state — neither restates this loop.
+
+**Policy:** [OKF documentation and commit policy](../documentation-policy.md). **Terms:** [iteration vocabulary](iteration-vocabulary.md).
+
+## Primary loop
+
+```mermaid
+flowchart TD
+ START([Pick change scope]) --> GA{Need feasibility /
semantics check?}
+ GA -->|yes| GAP["gap-analysis
tier: none"]
+ GA -->|no| BC{Need before snapshot
or area baseline?}
+ GAP --> BC
+
+ BC -->|yes| BASE["baseline-capture
tier: area-focused"]
+ BC -->|no| IMPL
+ BASE --> IMPL
+
+ IMPL["implementation
tier: unit-focused
module tests + narrow e2e"]
+ IMPL --> IG{implementation gate
green?}
+ IG -->|no| IMPL
+ IG -->|yes| REV
+
+ REV["independent-review
tier: area-focused
frozen tree"]
+ REV --> RG{all findings
resolved?}
+ RG -->|any unresolved| IMPL
+ RG -->|yes| DOC
+
+ DOC{User-facing or
OKF durable updates?}
+ DOC -->|yes| DOCS["documentation
tier: none"]
+ DOC -->|no| COMMIT
+ DOCS --> COMMIT
+
+ COMMIT["commit
tier: none"]
+ COMMIT --> PM{Branch ready
to merge?}
+ PM -->|yes| FULL["pre-merge-validation
tier: full"]
+ PM -->|no| END([Hand off / next item])
+ FULL --> END
+```
+
+## Work types
+
+| Work type | When | Validation tier | Product edits | Commit |
+|-----------|------|-----------------|---------------|--------|
+| `gap-analysis` | Unclear feasibility, API shape, provider support | none | read-only | no |
+| `baseline-capture` | Need before metrics or area-focused suite on the item | `area-focused` | local narrowing OK | no |
+| `implementation` | Author fix/feature + tests | `unit-focused` | yes | no |
+| `independent-review` | Verify frozen diff | `area-focused` | no — [frozen tree](#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 temporary narrowing first | no |
+
+**Commands per work type:** [validation checklist](validation-checklist.md) — link only; do not duplicate here.
+
+## Validation tiers
+
+Tier id strings: [iteration vocabulary § validation tier identifiers](iteration-vocabulary.md#validation-tier-identifiers).
+
+```mermaid
+flowchart LR
+ subgraph unitFocused ["unit-focused — implementation"]
+ F1[Module-scoped unit tests]
+ F2[Optional focused e2e class]
+ F3[Fast feedback]
+ F4[Never commit temporary narrowing]
+ end
+
+ subgraph areaFocused ["area-focused — baseline / independent-review"]
+ A1[Touched module full unit suite]
+ A2[E2e when Auth UI / emulator path touched]
+ A3[Frozen tree for review]
+ end
+
+ subgraph full ["full — pre-merge-validation"]
+ P1[./scripts/build.sh]
+ P2[E2e when Auth in PR scope]
+ P3[Once per branch before merge]
+ end
+```
+
+E2e scope and emulator rules: [running e2e § e2e agent rule](running-e2e.md#e2e-agent-rule).
+
+**Command rule:** Agents run **only** [agent command policy](agent-command-policy.md) allowlisted commands — no improvised Gradle graphs or bare `firebase emulators:start`.
+
+## Gates
+
+| Gate | Closes when |
+|------|-------------|
+| `implementation` | `implementation` work type complete — code plus **unit-focused**-tier checks green; [static analysis](validation-checklist.md#lint-and-formatting) green on the diff; e2e green when Auth UI/emulator path changed |
+| `review` | `independent-review` complete — **area-focused**-tier checks green on frozen tree; applicable [validation checklist](validation-checklist.md) rows green; **every review finding resolved** ([§ quality standards](#quality-standards)) |
+| `commit` | Durable commit exists for the item **after** prior gates closed with [recorded evidence](#validation-evidence-blocking) |
+
+**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](#quality-standards).
+
+
+
+### Validation evidence (blocking)
+
+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`** | Gradle/script **exit codes**; module unit test pass summary; when Auth UI/emulator path touched: **e2e pass** + log path; **`./gradlew checkstyle` exit code 0** when style-relevant sources changed |
+| **`review`** | Frozen-tree re-run of area-focused checklist; checkstyle exit 0 when applicable; unit (+ e2e if Auth) evidence on the frozen tree |
+| **`commit`** | Prior gates closed **with evidence**; no temporary test narrowing 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 review finding gets **root-cause analysis** — add tests, delete dead code, or record an [acceptable exception](#acceptable-exceptions) with evidence. Do not label gaps "informational" without proof.
+
+
+
+### Forbidden shortcuts
+
+- **`git commit`** while 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** gaps — only [acceptable exceptions](#acceptable-exceptions) with user confirmation or intractability evidence in durable OKF.
+
+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](#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** — an agent or reviewer may not grant either on its own, and the item stays tracked until resolved.
+
+1. **Intractable-limitation bar.** The gap is caused by an intractable technical limitation of the language, platform SDK, compiler, or toolchain, shown with evidence — e.g. a Firebase Auth API 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.
+
+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.
+- Convenience, time pressure, "harmless", 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](#acceptable-exceptions). An agent or reviewer may **not** defer a finding on its own authority: "green with minors" is not green.
+
+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`**.
+
+## Frozen tree
+
+Required for **`independent-review`** and for any e2e run that closes the **`review`** gate:
+
+- No edits to library modules (`auth/`, `firestore/`, `database/`, `storage/`, `common/`), `e2eTest/`, `app/` product code, 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.
+
+## `implementation` inner loop
+
+```mermaid
+flowchart TD
+ P0[Pre-flight: JDK, SDK; emulator if e2e]
+ P1[Edit product code + tests]
+ P2["Module unit tests — :module:testDebugUnitTest"]
+ P3{Auth UI / emulator path?}
+ P3 -->|no| P4[checkstyle if style-relevant]
+ P3 -->|yes| P5["emulator + ./gradlew e2eTest (or focused class)"]
+ P4 --> P6{Green?}
+ P5 --> P6
+ P6 -->|no| P1
+ P6 -->|yes| DONE([Close implementation gate])
+ P0 --> P1
+```
+
+**Static analysis before handoff:** Before closing the **`implementation`** gate, run [validation checklist § lint and formatting](validation-checklist.md#lint-and-formatting) when style-relevant sources changed. Fix violations in product code — do not hand off with checkstyle failures.
+
+## `independent-review`
+
+On a **frozen tree**:
+
+1. Revert temporary test narrowing (focused class filters used only for diagnosis).
+2. Run **area-focused**-tier checks for the touched module(s).
+3. Run applicable [validation checklist](validation-checklist.md) rows — **blocking:** checkstyle when style-relevant; unit tests; e2e when Auth UI/emulator path is in the frozen diff.
+4. Outcome closes **review gate** or returns to **`implementation`**.
+
+## `commit`
+
+- One focused commit per item when gates close.
+- **Evidence required:** [§ validation evidence](#validation-evidence-blocking) must be recorded before `commit_gate` closes.
+- **Work queue:** before `git commit`, set the row's `commit_subject` to the commit's subject line, close `commit_gate`, and stage the queue doc **in the same commit** as the product change ([documentation policy § work queues](../documentation-policy.md#work-queue-documents)). Do not record SHAs in queue docs.
+
+```bash
+git status
+git diff --stat
+```
+
+## Module extensions
+
+| Module / area | Adds to this loop |
+|---------------|-------------------|
+| Auth (Compose) | Credential Manager / MFA surfaces — [modules/auth](../modules/auth.md); e2e required — [running e2e](running-e2e.md#when-e2e-is-required) |
+| Per-module evidence | [validation checklist § module matrix](validation-checklist.md#module-validation-matrix); empty-suite trap — [agent command policy](agent-command-policy.md#empty-unit-suite-trap) |
+| Module durable notes | [modules/index](../modules/index.md) |
+
+Ephemeral coordination (gate rows, `next_work_type`, `commit_subject`): **work queues only** — not part of this workflow.
+
+## Related docs
+
+| Topic | Document |
+|-------|----------|
+| Term ids and queue field schema | [iteration-vocabulary.md](iteration-vocabulary.md) |
+| E2e commands | [running-e2e.md](running-e2e.md) |
+| Validation commands | [validation-checklist.md](validation-checklist.md) |
+| Agent shell allowlist | [agent-command-policy.md](agent-command-policy.md) |
diff --git a/okf-bundle/testing/index.md b/okf-bundle/testing/index.md
new file mode 100644
index 000000000..a120c118c
--- /dev/null
+++ b/okf-bundle/testing/index.md
@@ -0,0 +1,8 @@
+# Testing
+
+* [Agent command policy](agent-command-policy.md) — **read before any shell command** (Gradle, scripts, emulator, validation)
+* [Documentation/commit policy](../documentation-policy.md) — durable vs ephemeral, OKF scan
+* [Change authoring workflow](change-authoring-workflow.md) — verified product change loop (unit-focused → area-focused review → commit); [§ quality standards](change-authoring-workflow.md#quality-standards); [§ validation evidence (blocking)](change-authoring-workflow.md#validation-evidence-blocking)
+* [Iteration vocabulary](iteration-vocabulary.md) — work type, tier, and queue field identifiers
+* [Running e2e tests](running-e2e.md) — Auth emulator + `./gradlew e2eTest`; start here for e2e
+* [Validation checklist](validation-checklist.md) — handoff command sequence
diff --git a/okf-bundle/testing/iteration-vocabulary.md b/okf-bundle/testing/iteration-vocabulary.md
new file mode 100644
index 000000000..57075d4ae
--- /dev/null
+++ b/okf-bundle/testing/iteration-vocabulary.md
@@ -0,0 +1,87 @@
+---
+type: Reference
+title: Iteration vocabulary
+description: Identifier glossary and work-queue field schema for OKF — not workflow rules or commands.
+tags: [testing, validation, workflow, work-queue]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Iteration vocabulary
+
+Glossary of **string identifiers** and **work-queue field names** used across OKF. This doc does not define procedures, gate rules, or Gradle commands — each topic has one owning doc; others link.
+
+**Policy:** [OKF documentation and commit policy](../documentation-policy.md).
+
+| Topic | Owner |
+|-------|--------|
+| Change loop, gates, frozen tree | [change authoring workflow](change-authoring-workflow.md) |
+| **All agent shell commands** | [agent command policy](agent-command-policy.md) |
+| E2e-only detail, emulator, suite scope | [running e2e](running-e2e.md) |
+| Validation command sequence | [validation checklist](validation-checklist.md) |
+| Work-queue gate snapshots | Module/area work queues (ephemeral) |
+
+## Work type identifiers
+
+| Work type | Brief meaning |
+|-----------|---------------|
+| `gap-analysis` | Read-only feasibility / semantics check |
+| `baseline-capture` | Record before snapshots or baselines |
+| `implementation` | Author product code and tests |
+| `independent-review` | Verify a frozen diff |
+| `documentation` | User docs and durable OKF updates |
+| `commit` | Stage and create one commit |
+| `pre-merge-validation` | Branch-wide merge gate |
+
+When to use each work type, validation tier, edit policy, and commit rules: [change authoring § work types](change-authoring-workflow.md#work-types).
+
+## Validation tier identifiers
+
+| Tier id | Brief meaning |
+|---------|---------------|
+| `unit-focused` | Fast validation while product code is changing (module-scoped unit tests; optional focused e2e) |
+| `area-focused` | Full loaded module/area suite for the change (module unit tests + e2e when Auth UI/emulator path touched) |
+| `full` | Unfocused — CI unit path + e2e when Auth is in scope |
+
+E2e scope and rules: [change authoring § validation tiers](change-authoring-workflow.md#validation-tiers), [running e2e](running-e2e.md).
+
+## Gate identifiers
+
+Work queues use these **field names** (values: `open` | `closed`):
+
+| Field | Tracks |
+|-------|--------|
+| `implementation_gate` | `implementation` work type complete |
+| `review_gate` | `independent-review` work type complete |
+| `commit_gate` | Durable commit exists for the item **after** prior gates closed with [validation evidence](change-authoring-workflow.md#validation-evidence-blocking) |
+
+What closes each gate, trust rules, and loop transitions: [change authoring § gates](change-authoring-workflow.md#gates).
+
+`commit_gate` closes when a durable commit exists whose subject matches the row's `commit_subject`, **after** `implementation_gate` and `review_gate` closed with [validation evidence](change-authoring-workflow.md#validation-evidence-blocking).
+
+Items may also be marked **`blocked`** when a dependency gate is open elsewhere.
+
+## Work-queue fields
+
+Ephemeral work queues may record:
+
+| Field | Allowed values / meaning |
+|-------|--------------------------|
+| `next_work_type` | A [work type identifier](#work-type-identifiers) |
+| `validation_tier` | `unit-focused` \| `area-focused` \| `full` |
+| `module` | Optional Gradle module scope (e.g. `auth`, `firestore`) |
+| `implementation_gate` | `open` \| `closed` |
+| `review_gate` | `open` \| `closed` |
+| `commit_gate` | `open` \| `closed` |
+| `commit_subject` | Planned or landed **first line** of the item's focused commit (Conventional Commits subject). Set **before** `git commit`; must match the commit that closes `commit_gate`. Do not record SHAs. |
+| `blocked` | Item or dependency blocked until named gate closes |
+
+Queues record **state**, not who executes the work.
+
+## Related docs
+
+| Topic | Document |
+|-------|----------|
+| **Change authoring loop** | [change-authoring-workflow.md](change-authoring-workflow.md) |
+| E2e commands | [running-e2e.md](running-e2e.md) |
+| Validation commands | [validation-checklist.md](validation-checklist.md) |
+| Doc/commit policy | [documentation-policy.md](../documentation-policy.md) |
diff --git a/okf-bundle/testing/running-e2e.md b/okf-bundle/testing/running-e2e.md
new file mode 100644
index 000000000..5e5239ff8
--- /dev/null
+++ b/okf-bundle/testing/running-e2e.md
@@ -0,0 +1,99 @@
+---
+type: Reference
+title: Running e2e tests
+description: Canonical Auth emulator + Gradle e2eTest commands, environment, and diagnosis for FirebaseUI-Android.
+tags: [testing, e2e, emulator, auth, gradle]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Running e2e tests
+
+Canonical e2e runbook for this repo. **Shell allowlist:** [agent command policy](agent-command-policy.md). Do not restate the full allowlist here.
+
+
+
+## E2e agent rule (read first)
+
+1. Start the Auth emulator with **`./scripts/start-firebase-emulator.sh`** only.
+2. Run the suite with **`./gradlew e2eTest`** only (custom task in `e2eTest/build.gradle.kts`).
+3. Do **not** use `connectedAndroidTest`, Espresso device runs, or bare `firebase emulators:start` with invented ports as substitutes.
+4. On failure: read the full Gradle output (and `./scripts/print_build_logs.sh` when useful), fix product/test code or prerequisites, re-run the **same** commands.
+
+## What this suite is
+
+| Property | Value |
+|----------|--------|
+| Module | `:e2eTest` |
+| Runner | Robolectric + Compose UI testing (`test` source set) |
+| Backend | Firebase **Auth** Emulator only |
+| Project ID | From `e2eTest/.firebaserc` (`fake-project-id`) |
+| Auth port | From `e2eTest/firebase.json` emulators.auth.port (`9099`) |
+| Custom task | `e2eTest` — mirrors the debug unit-test classpath; `doNotTrackState` so it always runs |
+
+Tests live under `e2eTest/src/test/java/com/firebase/ui/auth/ui/` — mostly `screens/` (email, phone, Google, MFA, reauth, credential linking, anonymous) plus `AccessibilityTest.kt` beside that package.
+
+This suite does **not** require a real Firebase project. Demo app / Play Services provider setup for the sample app is separate ([modules/auth](../modules/auth.md), [CONTRIBUTING.md](../../CONTRIBUTING.md)).
+
+## Prerequisites
+
+```bash
+# Once per machine (CI installs firebase-tools each job)
+npm install -g firebase-tools
+```
+
+Also needed: `node`, `npm`, `jq` (used to read `e2eTest/.firebaserc` / `firebase.json`; the script preflights only `firebase` / `node` / `npm`), and a free Auth emulator port.
+
+## Canonical local run
+
+**Terminal A** (foreground emulator locally):
+
+```bash
+./scripts/start-firebase-emulator.sh
+```
+
+**Terminal B**:
+
+```bash
+./gradlew e2eTest
+```
+
+CI order matches [.github/workflows/e2e_test.yml](../../.github/workflows/e2e_test.yml): install firebase-tools → start script (background when `CI` is set) → `./gradlew e2eTest`.
+
+## Focused runs (diagnosis only)
+
+Gradle supports narrowing to a test class while iterating. Prefer this during **`unit-focused`** diagnosis; revert to the full `e2eTest` task before **`area-focused`** / **`review`** gate closure.
+
+```bash
+./gradlew e2eTest --tests 'com.firebase.ui.auth.ui.screens.EmailAuthScreenTest'
+```
+
+Never commit temporary `.only`-style filters or leave the suite narrowed for review evidence.
+
+
+
+## When e2e is required
+
+| Change surface | E2e required? |
+|----------------|---------------|
+| `auth/` Compose screens, flow controller, credential manager, MFA | **Yes** — area-focused and full tiers |
+| `e2eTest/` itself | **Yes** |
+| `firestore/` / `database/` / `storage/` / `common/` only | **No** — unit/androidTest for that module |
+| Docs / OKF only | **No** |
+
+## Diagnosis
+
+1. Confirm emulator is up: start script succeeded; Auth URL responds (`FIREBASE_AUTH_EMULATOR_URL`, default `http://127.0.0.1:9099`).
+2. Confirm prerequisites: script exits non-zero if `firebase` / `node` / `npm` are missing; ensure `jq` is installed too (used without a dedicated preflight check).
+3. Re-run **`./gradlew e2eTest`** after product/test fixes — same command.
+4. On CI-shaped failures: `./scripts/print_build_logs.sh`.
+
+Do not “fix” emulator connectivity by inventing alternate ports or starting Firestore/Database emulators unless a future suite documents them as required.
+
+## Related docs
+
+| Topic | Document |
+|-------|----------|
+| Allowlisted commands | [agent-command-policy.md](agent-command-policy.md) |
+| Handoff checklist | [validation-checklist.md](validation-checklist.md) |
+| E2e CI job | [ci-workflows/e2e.md](../ci-workflows/e2e.md) |
+| Auth module notes | [modules/auth.md](../modules/auth.md) |
diff --git a/okf-bundle/testing/validation-checklist.md b/okf-bundle/testing/validation-checklist.md
new file mode 100644
index 000000000..71b59eb6c
--- /dev/null
+++ b/okf-bundle/testing/validation-checklist.md
@@ -0,0 +1,124 @@
+---
+type: Reference
+title: Validation checklist
+description: Canonical command sequence for validating FirebaseUI-Android changes and handoff.
+tags: [testing, validation, gradle, checkstyle, e2e]
+timestamp: 2026-07-31T00:00:00Z
+---
+
+# Validation checklist
+
+Validation commands for development/handoff. Other docs/skills link here; do not restate.
+
+**Agents:** [agent command policy](agent-command-policy.md) — only allowlisted invocations.
+
+## When to run what
+
+Work types and tiers: [change authoring workflow](change-authoring-workflow.md). Term ids: [iteration vocabulary](iteration-vocabulary.md).
+
+| Work type | Scope | Shortcuts |
+|-----------|-------|-----------|
+| `gap-analysis` | Read APIs, module READMEs, upgrade guides | n/a |
+| `baseline-capture` | Touched module unit suite (+ e2e if Auth) | **area-focused** tier |
+| `implementation` | Module unit tests; e2e when Auth UI/emulator path changed | **unit-focused** tier; optional `--tests` narrowing for diagnosis |
+| `independent-review` | Area checklist on [frozen tree](change-authoring-workflow.md#frozen-tree) | **area-focused**; no temporary narrowing left in place |
+| `pre-merge-validation` | CI unit path + e2e when Auth in PR | **full** tier — once per branch |
+
+## Build and unit tests
+
+Repo root. Full CI unit path (what `build.sh` runs): [Android CI](../ci-workflows/android.md).
+
+```bash
+./scripts/build.sh
+```
+
+Module-scoped while iterating — **only modules with a real `src/test` suite** count as unit evidence:
+
+```bash
+./gradlew :auth:testDebugUnitTest
+./gradlew :firestore:testDebugUnitTest
+./gradlew :storage:testDebugUnitTest
+```
+
+
+
+| Module | JVM `src/test`? | Unit-focused evidence | Area-focused / full |
+|--------|-----------------|----------------------|---------------------|
+| `:auth` | Yes | `:auth:testDebugUnitTest`; optional focused e2e — [running e2e](running-e2e.md) | Full auth unit + e2e; `./scripts/build.sh` at full |
+| `:firestore`, `:storage` | Yes | `::testDebugUnitTest` | Same + `./scripts/build.sh` at full |
+| `:database` | **No** (only `androidTest`) | `:database:assembleDebug` + checkstyle — **not** `:database:testDebugUnitTest` ([empty-suite trap](agent-command-policy.md#empty-unit-suite-trap)) | `./scripts/build.sh` |
+| `:common` | **No** | `:common:assembleDebug` + checkstyle + `:firestore:testDebugUnitTest` when shared API consumed — **not** `:common:testDebugUnitTest` ([trap](agent-command-policy.md#empty-unit-suite-trap)) | `./scripts/build.sh` |
+
+Instrumented `androidTest` (database/firestore) is **not** in CI or the agent allowlist — human/device only.
+
+
+
+## Lint and formatting
+
+**Blocking before `implementation` handoff and on the frozen tree for `independent-review`** when Java/Kotlin style-relevant sources changed.
+
+```bash
+./gradlew checkstyle
+```
+
+Config: `library/quality/checkstyle.xml` (wired from root `build.gradle.kts`). There is **no** separate agent entrypoint for ktlint/detekt — do not invent one.
+
+Follow [Kotlin coding conventions](https://kotlinlang.org/docs/coding-conventions.html), [Android Kotlin style](https://developer.android.com/kotlin/style-guide), and [Compose API guidelines](https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-api-guidelines.md) as described in [CONTRIBUTING.md](../../CONTRIBUTING.md).
+
+## E2e
+
+When Auth UI / `e2eTest` is in scope — [running e2e](running-e2e.md):
+
+```bash
+./scripts/start-firebase-emulator.sh # separate terminal locally
+./gradlew e2eTest
+```
+
+## Coverage
+
+This repo does **not** currently configure Jacoco/Codecov (or equivalent) in CI. Do not invent coverage tasks. Prefer meaningful unit + e2e assertions over synthetic coverage gates until tooling is added and documented here.
+
+## OKF bundle review
+
+Before handoff, follow [OKF policy](../documentation-policy.md#okf-update-contract):
+
+1. Update relevant `okf-bundle/modules/` docs with durable learnings.
+2. Check `okf-bundle/testing/` for conflicts with verified behavior; fix drift.
+3. Run independent scan for canonical ownership, DRY refs, link hygiene, durability.
+
+
+
+## Validation evidence package (blocking)
+
+Before closing **`implementation_gate`**, **`review_gate`**, **`commit_gate`**, or publishing (`git push` / PR update), record evidence per [change authoring § validation evidence](change-authoring-workflow.md#validation-evidence-blocking). Minimum template:
+
+```markdown
+| Step | Command | Exit | Evidence |
+|-------------|-------------------------------------------------------------------------|------|-----------------------------------------------|
+| unit CI | ./scripts/build.sh | 0 | — |
+| module unit | ./gradlew ::testDebugUnitTest | 0 | N/N tests — only if module has `src/test` |
+| assemble | ./gradlew ::assembleDebug | 0 | when module has no JVM unit suite |
+| checkstyle | ./gradlew checkstyle | 0 | when style-relevant sources |
+| e2e | ./gradlew e2eTest | 0 | when Auth UI — /tmp/...log |
+```
+
+**History rewrite invalidates** prior rows — re-run and replace the table after amend/rebase.
+
+## Handoff checklist
+
+- [ ] `./scripts/build.sh` (or equivalent assemble + checkstyle + unit exclusion path) exit 0
+- [ ] Module evidence per [module validation matrix](#module-validation-matrix)
+- [ ] `./gradlew checkstyle` when style-relevant sources changed
+- [ ] E2e green when Auth UI / `e2eTest` changed ([running e2e](running-e2e.md))
+- [ ] [Validation evidence package](#validation-evidence-package) recorded
+- [ ] OKF bundle reviewed/updated per § above
+- [ ] Conventional Commit subject prepared ([documentation policy](../documentation-policy.md)); single-commit PR title will match
+
+## Related docs
+
+| Topic | Document |
+|-------|----------|
+| Allowlist | [agent-command-policy.md](agent-command-policy.md) |
+| Change loop | [change-authoring-workflow.md](change-authoring-workflow.md) |
+| E2e | [running-e2e.md](running-e2e.md) |
+| CI | [ci-workflows/index.md](../ci-workflows/index.md) |