From 6c11f160e013521b49799fee9e5ea30dab663dd6 Mon Sep 17 00:00:00 2001 From: mattrace-gloo Date: Thu, 13 Aug 2026 10:21:06 -0700 Subject: [PATCH 1/3] [#329]: Document pre-merge QA preview gate and align agent/CI docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make Needs QA? → preview-build → QA pass the documented merge path for device-facing work, and remove contradictory post-merge-only In QA guidance. --- .cursor/rules/delivery.mdc | 2 +- .cursor/rules/docs.mdc | 7 +- .cursor/rules/project-board.mdc | 4 +- .cursor/templates/pr-template.md | 7 ++ .eas/README.md | 6 +- .github/PULL_REQUEST_TEMPLATE.md | 7 ++ .github/README.md | 8 +- AGENTS.md | 8 +- CLAUDE.md | 9 +- docs/AGENT_ONBOARDING.md | 9 +- docs/ci.md | 11 ++- docs/guides/project-board.md | 11 ++- docs/guides/qa-preview-testing.md | 15 ++-- docs/guides/qa-process.md | 139 ++++++++++++++++++++++++++++++ docs/issue-tracking.md | 12 ++- 15 files changed, 219 insertions(+), 36 deletions(-) create mode 100644 docs/guides/qa-process.md diff --git a/.cursor/rules/delivery.mdc b/.cursor/rules/delivery.mdc index 8a529533..ba2fa5a1 100644 --- a/.cursor/rules/delivery.mdc +++ b/.cursor/rules/delivery.mdc @@ -14,7 +14,7 @@ Every change — including infra, CI, docs, Dependabot follow-ups, and `expo ins 1. **Ticket on Project 4** — GitHub Issue `#NNN` **on** the [Fluent Mobile Board](https://github.com/orgs/eten-tech-foundation/projects/4/views/9) (org project #4, view 9). Ask if missing. See [docs/issue-tracking.md](../../docs/issue-tracking.md). The repo Issues list is not the triage board. (Not Linear.) Board Status/Priority edits: [docs/guides/project-board.md](../../docs/guides/project-board.md) and [project-board.mdc](./project-board.mdc) — do not sweep Product or `Dev Ready` lanes without named approval. 2. **Feature branch** — `{author}/{type}/{issue-number}-{slug}` (see `/create-pr-branch`, or `/start-issue` for the full loop) 3. **Pull request** — title `[#NNN]: Description`; body filled from the PR template (below); include `Refs #NNN` under Details (never `Closes` / `Fixes` / `Resolves`); **assign the PR to the author** (`gh pr create --assignee @me` or `gh pr edit --add-assignee @me`); set Project 4 Status to **In PR Review**. Manually link the issue in the PR Development sidebar when needed (GitHub has no non-closing link API — do not use closing keywords). `/start-issue` chains to `/create-pr` (`/open-pr` is an alias) which automates the draft PR, board move, and CI watch. -4. **Human merge** — agents open PRs and push **feature branches only**; never merge on GitHub unless the user explicitly asks for a Dependabot squash merge in that session. After merge, set Project 4 Status to **In QA** (issues stay open for QA — do not auto-close) +4. **Human merge** — agents open PRs and push **feature branches only**; never merge on GitHub unless the user explicitly asks for a Dependabot squash merge in that session. For **QA-required** PRs ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)): add `preview-build`, wait for **In QA** / QA pass on **that PR’s** preview — **not mergeable until QA passes**. Engineering-only PRs skip that gate. Issues stay open — do not auto-close Allowed on `main` locally: `git checkout main`, `git pull`, read-only validation after merges. **Not allowed:** `git push origin main`, commits on `main`, or opening PRs with `main` as the head branch. diff --git a/.cursor/rules/docs.mdc b/.cursor/rules/docs.mdc index af6e9564..96ff57df 100644 --- a/.cursor/rules/docs.mdc +++ b/.cursor/rules/docs.mdc @@ -36,9 +36,12 @@ Cross-tool agents (Claude Code, Copilot, etc.) must still find the same contract [README.md](../../README.md) — human-focused setup (Android emulator, env vars). Link to `docs/AGENT_ONBOARDING.md` for agents; do not duplicate full architecture there. -## QA preview testing +## QA process + preview install -[docs/guides/qa-preview-testing.md](../../docs/guides/qa-preview-testing.md) — non-technical steps for PR previews (Fluent dev client, not Expo Go). Update when preview workflow comments or install flow change. +- [docs/guides/qa-process.md](../../docs/guides/qa-process.md) — Needs QA?, ownership, pass/fail, **pre-merge** merge gate +- [docs/guides/qa-preview-testing.md](../../docs/guides/qa-preview-testing.md) — non-technical install steps for PR previews (Fluent preview app, not Expo Go) + +Update these when preview workflow comments, install flow, or the QA merge gate change. ## PR template diff --git a/.cursor/rules/project-board.mdc b/.cursor/rules/project-board.mdc index 3abeac2b..05d37f85 100644 --- a/.cursor/rules/project-board.mdc +++ b/.cursor/rules/project-board.mdc @@ -13,6 +13,6 @@ Canonical policy: [docs/guides/project-board.md](../../docs/guides/project-board - **Do not** edit Status or Priority on `In Progress (Product)` (or other Product-owned columns) unless the tech lead **explicitly lists** those issue numbers. - **No board sweeps** without a proposed change set + explicit approval. Ambiguous = no. - **Do not merge PRs** unless explicitly asked (Dependabot process is the standing exception when requested). -- For the **assigned** ticket only: add to Project 4 if missing; set `In PR Review` when the PR opens; set **`In QA`** after merge (or when ready for QA) — never auto-close the issue; do **not** set `Done` until QA completes (human/QA process). +- For the **assigned** ticket only: add to Project 4 if missing; set `In PR Review` when the PR opens; if **Needs QA**, add `preview-build` and expect **`In QA` before merge** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)) — never auto-close the issue; do **not** set `Done` until QA completes (human/QA process). Do not merge QA-required PRs until QA passes that PR’s preview. -Tracker overview: [docs/issue-tracking.md](../../docs/issue-tracking.md). Delivery: [delivery.mdc](./delivery.mdc). +Tracker overview: [docs/issue-tracking.md](../../docs/issue-tracking.md). QA process: [docs/guides/qa-process.md](../../docs/guides/qa-process.md). Delivery: [delivery.mdc](./delivery.mdc). diff --git a/.cursor/templates/pr-template.md b/.cursor/templates/pr-template.md index 347ec8ba..cfb66cc5 100644 --- a/.cursor/templates/pr-template.md +++ b/.cursor/templates/pr-template.md @@ -8,6 +8,8 @@ - [ ] How to verify steps completed or valid waiver noted below - [ ] Acceptance criteria met, **or** unmet AC waived **in the issue** with linked follow-up (see `AGENTS.md`) - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval +- [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added +- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms) - [ ] Android device tested when required (native / mic / camera / filesystem / permissions) — do **not** check unless verified on a device ### Details @@ -16,6 +18,11 @@ Refs # +**Needs QA?** + +- [ ] No — engineering-only (docs, CI, refactor, logging, etc.) +- [ ] Yes — UI / native / mic / camera / filesystem / sync / device verification (`preview-build` required) + **Type of change:** - [ ] Bug fix diff --git a/.eas/README.md b/.eas/README.md index 4130fc52..ae26b25d 100644 --- a/.eas/README.md +++ b/.eas/README.md @@ -51,11 +51,11 @@ Monitor: Add the **`preview-build`** label to a pull request. GitHub Actions (`.github/workflows/preview-build.yml`) will: - Start a **fresh Android `preview` internal APK** for that PR commit (binary only — no `eas update` / shared OTA channel) -- Post the same install comment on the **PR and linked issue**; best-effort move Project 4 Status to **`In QA`** (from `In PR Review` / `In Progress (Dev)`). Optional secret: `PROJECT_BOARD_TOKEN`. +- Post the same install comment on the **PR and linked issue**; best-effort move Project 4 Status to **`In QA`** (from `In PR Review` / `In Progress (Dev)`) **before merge**. Optional secret: `PROJECT_BOARD_TOKEN`. -Each labeled PR forces a new build so multiple QA APKs can exist at once. Preview profile has Expo Updates **disabled** (same idea as nightly). +Each labeled PR forces a new build so multiple QA APKs can exist at once. Preview profile has Expo Updates **disabled** (same idea as nightly). Re-request after fixes: remove and re-add the label. **QA-required PRs are not mergeable until QA passes that preview** — [docs/guides/qa-process.md](../docs/guides/qa-process.md). -**QA testers:** [`docs/guides/qa-preview-testing.md`](../docs/guides/qa-preview-testing.md) +**Install how-to:** [`docs/guides/qa-preview-testing.md`](../docs/guides/qa-preview-testing.md) Uses the latest git tag for runtime version when available; otherwise falls back to `app.config.ts` / `package.json` version (no tag required for first preview). Requires `EXPO_TOKEN` in GitHub Actions secrets. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 347ec8ba..cfb66cc5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,6 +8,8 @@ - [ ] How to verify steps completed or valid waiver noted below - [ ] Acceptance criteria met, **or** unmet AC waived **in the issue** with linked follow-up (see `AGENTS.md`) - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval +- [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added +- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms) - [ ] Android device tested when required (native / mic / camera / filesystem / permissions) — do **not** check unless verified on a device ### Details @@ -16,6 +18,11 @@ Refs # +**Needs QA?** + +- [ ] No — engineering-only (docs, CI, refactor, logging, etc.) +- [ ] Yes — UI / native / mic / camera / filesystem / sync / device verification (`preview-build` required) + **Type of change:** - [ ] Bug fix diff --git a/.github/README.md b/.github/README.md index 6b3fc801..477c96d6 100644 --- a/.github/README.md +++ b/.github/README.md @@ -38,11 +38,15 @@ See [`.eas/README.md`](../.eas/README.md) for Expo GitHub app and Play Store set ## PR preview (QA) +Canonical process (Needs QA?, pass/fail, **pre-merge** merge gate): [`docs/guides/qa-process.md`](../docs/guides/qa-process.md). + 1. Create a `preview-build` label on the repo (if missing). 2. Add the label to a PR when ready for QA (PR should reference its ticket with `Refs #NNN` on its own Details line — not `Part of #NNN`). -3. Workflow starts a **fresh Android preview APK** (binary only — no OTA / `eas update`), posts the same install comment on the **PR** and each **linked GitHub issue** (`Refs` / legacy closing keywords via [`.github/scripts/preview-notify-linked-issues.cjs`](scripts/preview-notify-linked-issues.cjs)), and best-effort moves Project 4 cards from `In PR Review` / `In Progress (Dev)` → **`In QA`**. +3. Workflow starts a **fresh Android preview APK** (binary only — no OTA / `eas update`), posts the same install comment on the **PR** and each **linked GitHub issue** (`Refs` / legacy closing keywords via [`.github/scripts/preview-notify-linked-issues.cjs`](scripts/preview-notify-linked-issues.cjs)), and best-effort moves Project 4 cards from `In PR Review` / `In Progress (Dev)` → **`In QA`** (**before merge**). +4. **Re-request after fixes:** remove the `preview-build` label, then re-add it (workflow triggers on `labeled` only; always `FORCE_NEW_BUILD`). +5. **Merge gate:** QA-required PRs are not mergeable until QA passes that PR’s preview — currently **manual** (no required status check yet). -**QA guide (non-technical):** [`docs/guides/qa-preview-testing.md`](../docs/guides/qa-preview-testing.md) +**Install guide (non-technical):** [`docs/guides/qa-preview-testing.md`](../docs/guides/qa-preview-testing.md) Requires `EXPO_TOKEN` in repository secrets. Optional: `PROJECT_BOARD_TOKEN` (PAT with org **project** write) so Status updates on Project 4 succeed — without it, issue comments still post but the board move may be skipped. Each labeled PR forces a new EAS build (`FORCE_NEW_BUILD`) so concurrent QA previews are not collapsed by fingerprint reuse. `eas.json` profile `preview` is internal distribution with Expo Updates **disabled** (same idea as nightly). `EAS_USE_CACHE` (ccache) stays enabled on non-production profiles. diff --git a/AGENTS.md b/AGENTS.md index c1c7e55a..1d266839 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,11 +44,12 @@ Build for the case in front of you. ### 4. Human-only verification -If a change adds **native modules** or **mic / camera / filesystem / permissions** behavior: +If a change adds **native modules** or **mic / camera / filesystem / permissions** behavior (or otherwise **Needs QA** per [docs/guides/qa-process.md](docs/guides/qa-process.md)): -- **Android device QA is required** (unit tests and CI are not enough). +- **Android device QA is required** on that PR’s **isolated `preview-build`** (unit tests and CI are not enough). - Keep the PR **draft** or **changes-requested** until a human records device results on the PR. -- Agents must **flag** this requirement; do not check the device-QA box unless a human verified it. +- **QA-required PRs are not mergeable** until QA passes that preview — see [docs/guides/qa-process.md](docs/guides/qa-process.md). +- Agents must **flag** this requirement; do not check the device-QA / “QA passed preview” boxes unless a human verified it. ### 5. Agent-authorship is a review heuristic @@ -58,6 +59,7 @@ On feature PRs with heavy agent co-authorship, reviewers should prioritize **sco - Delivery / branch / PR process: [`.cursor/rules/delivery.mdc`](.cursor/rules/delivery.mdc) — **PR bodies must use** [`.cursor/templates/pr-template.md`](.cursor/templates/pr-template.md). Full loop: `/start-issue`; delivery-only: `/create-pr` (`.claude/commands/`). - Issue tracking (Project 4 Fluent Mobile Board): [docs/issue-tracking.md](docs/issue-tracking.md) +- QA process / pre-merge preview gate: [docs/guides/qa-process.md](docs/guides/qa-process.md) · install how-to: [docs/guides/qa-preview-testing.md](docs/guides/qa-preview-testing.md) - Board mutation rules: [docs/guides/project-board.md](docs/guides/project-board.md) · [`.cursor/rules/project-board.mdc`](.cursor/rules/project-board.mdc) - Expo-first deps: [docs/guides/expo-first-dependencies.md](docs/guides/expo-first-dependencies.md) · [`.cursor/rules/expo-first-dependencies.mdc`](.cursor/rules/expo-first-dependencies.mdc) - CI command order: [`.cursor/rules/commands.mdc`](.cursor/rules/commands.mdc) diff --git a/CLAUDE.md b/CLAUDE.md index 6299e0cf..2a4ac2af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,9 +8,10 @@ This file is the **entrypoint for non-Cursor agents** (Claude Code, Codex, Copil 2. [`docs/AGENT_ONBOARDING.md`](docs/AGENT_ONBOARDING.md) — setup, architecture, commands 3. [`docs/issue-tracking.md`](docs/issue-tracking.md) — Project 4 board, branches, PRs 4. [`docs/guides/project-board.md`](docs/guides/project-board.md) — **board mutation hard rules** -5. [`docs/guides/expo-first-dependencies.md`](docs/guides/expo-first-dependencies.md) — prefer Expo packages -6. [`.cursor/rules/`](.cursor/rules/) — always-on + topic rules (`delivery`, `architecture`, `android-only`, `project-board`, `expo-first-dependencies`, …) -7. [`.claude/commands/`](.claude/commands/) — canonical slash commands (`/start-issue`, `/create-pr`, …). Cursor `/` palette shims live in [`.cursor/commands/`](.cursor/commands/). +5. [`docs/guides/qa-process.md`](docs/guides/qa-process.md) — Needs QA? / pre-merge preview gate +6. [`docs/guides/expo-first-dependencies.md`](docs/guides/expo-first-dependencies.md) — prefer Expo packages +7. [`.cursor/rules/`](.cursor/rules/) — always-on + topic rules (`delivery`, `architecture`, `android-only`, `project-board`, `expo-first-dependencies`, …) +8. [`.claude/commands/`](.claude/commands/) — canonical slash commands (`/start-issue`, `/create-pr`, …). Cursor `/` palette shims live in [`.cursor/commands/`](.cursor/commands/). ## Precedence @@ -22,7 +23,7 @@ This file is the **entrypoint for non-Cursor agents** (Claude Code, Codex, Copil - Never push or merge to `main`; ticketed branch + PR; PR body from [`.cursor/templates/pr-template.md`](.cursor/templates/pr-template.md). Full loop: `/start-issue NNN` (chains to `/create-pr`). Delivery-only: `/create-pr` (`/open-pr` alias). - Do not reorganize Project 4 (`Dev Ready` / Product columns) without an approved change set - Prefer Expo SDK modules; do not rip out React Navigation without a ticket -- Mic / camera / filesystem / native modules → human Android device QA before ready-for-review +- Mic / camera / filesystem / native modules → human Android device QA on that PR’s `preview-build` **before merge** ([docs/guides/qa-process.md](docs/guides/qa-process.md)) ## Package manager / Node diff --git a/docs/AGENT_ONBOARDING.md b/docs/AGENT_ONBOARDING.md index 8b37b359..007c9e26 100644 --- a/docs/AGENT_ONBOARDING.md +++ b/docs/AGENT_ONBOARDING.md @@ -115,13 +115,16 @@ Setup and troubleshooting: [`.eas/README.md`](../.eas/README.md). ## PR preview (Android QA) -1. Add the **`preview-build`** label to the PR (uses latest git tag, or `app.config.ts` version if none). +Process and merge gate: [`docs/guides/qa-process.md`](guides/qa-process.md). Install steps: [`docs/guides/qa-preview-testing.md`](guides/qa-preview-testing.md). + +1. Add the **`preview-build`** label to the PR when it **Needs QA** (uses latest git tag, or `app.config.ts` version if none). 2. Workflow and build resolution: - **`runtimeVersion`:** `app.config.ts` sets **`runtimeVersion: { policy: 'appVersion' }`**. - **`preview-build.yml`:** [`.github/workflows/preview-build.yml`](../.github/workflows/preview-build.yml) starts a **fresh** Android EAS `preview` internal APK for that PR (binary only — no OTA); uses [`.github/scripts/eas-resolve-android-build.sh`](../.github/scripts/eas-resolve-android-build.sh) with `FORCE_NEW_BUILD=true`. - **`.fingerprintignore`:** excludes `docs/**/*` and `.github/**/*` (among other non-native paths) from EAS build fingerprint hashing. - **`eas.json` / production skip:** `preview` and `development` set **`EAS_USE_CACHE: "1"`**; `production` sets **`EAS_SAVE_CACHE: "1"`** and **`EAS_RESTORE_CACHE: "0"`** (save cache only, no restore). [`.eas/workflows/create-production-builds.yml`](../.eas/workflows/create-production-builds.yml) skips rebuild when fingerprint matches (`if: !needs.get_android_build.outputs.build_id`). -3. The bot comment links to **[`docs/guides/qa-preview-testing.md`](guides/qa-preview-testing.md)** for non-technical testers (Fluent preview app — **not Expo Go** or Metro dev builds). +3. The bot comments on the PR and linked issue; Project 4 may move to **`In QA` before merge**. QA-required PRs are **not mergeable** until QA passes that preview. +4. Re-request after fixes: remove and re-add the `preview-build` label. Requires `EXPO_TOKEN` in GitHub repository secrets. Preview builds use `eas.json` profile `preview` (internal distribution, Expo Updates **disabled** — no `developmentClient`; `EXPO_PUBLIC_API_BASE_URL=https://dev.api.fluent.bible`). Local `.env` keeps emulator localhost; `dev.app.fluent.bible` is the web app, not the mobile API host. Local/engineering builds use profile `development` (`developmentClient: true`). @@ -237,6 +240,8 @@ When adding features: mock `op-sqlite`, navigation, and sync in screen tests fol - Human setup: [README.md](../README.md) - Agent delivery guardrails: [`AGENTS.md`](../AGENTS.md) - Issue tracking (Project 4 Fluent Mobile Board): [issue-tracking.md](issue-tracking.md) +- QA process / pre-merge preview gate: [guides/qa-process.md](guides/qa-process.md) +- QA install how-to: [guides/qa-preview-testing.md](guides/qa-preview-testing.md) - CI inventory: [ci.md](ci.md) - Cursor rules: [`.cursor/rules/`](../.cursor/rules/) — **Android-only:** [android-only.mdc](../.cursor/rules/android-only.mdc) - Dependabot: [guides/dependabot-process.md](guides/dependabot-process.md) — use with `.cursor/rules/dependabot-workflow.mdc` diff --git a/docs/ci.md b/docs/ci.md index 92002e06..c45dd9d0 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -10,7 +10,7 @@ This repo runs GitHub Actions on pushes and pull requests. This doc maps what ru | `lint.yml` | `Lint & Format` | ESLint + Prettier (`format:check`) | | `test.yml` | `Unit Tests` | Jest (`npm test -- --ci`) | | `quality-gates.yml` | `TypeScript`, `expo-doctor`, `expo install --check` | Typecheck + Expo SDK / native-module alignment | -| `preview-build.yml` | Android EAS preview APK | On-demand when PR has label `preview-build` — binary only (no OTA); comments PR **and** linked issues; best-effort Project 4 → `In QA` | +| `preview-build.yml` | Android EAS preview APK | On-demand when PR has label `preview-build` — binary only (no OTA); comments PR **and** linked issues; best-effort Project 4 → `In QA` (**pre-merge** for QA-required PRs — [guides/qa-process.md](guides/qa-process.md)) | | `nightly-preview.yml` | Nightly Android APK | Scheduled binary-only internal APK (dev API); also `workflow_dispatch` | | `eas-build.yml` | Tag → version sync | Production release path on `v*` tags | @@ -57,9 +57,11 @@ PR template for the GitHub UI: [`.github/PULL_REQUEST_TEMPLATE.md`](../.github/P ## Preview / native compile - Preview APKs: `preview-build.yml` + [`.github/scripts/eas-resolve-android-build.sh`](../.github/scripts/eas-resolve-android-build.sh) with `FORCE_NEW_BUILD=true` (no fingerprint reuse; no OTA) -- After a successful preview comment, [`.github/scripts/preview-notify-linked-issues.cjs`](../.github/scripts/preview-notify-linked-issues.cjs) upserts the same body on issues linked via `Refs #NNN` (or legacy closing keywords; not `Part of #NNN`) and may move Project 4 Status to `In QA` (optional `PROJECT_BOARD_TOKEN`) -- Human QA steps: [guides/qa-preview-testing.md](guides/qa-preview-testing.md) -- Nightly internal APK (no OTA): `nightly-preview.yml` + EAS profile `nightly` — see [`.github/README.md`](../.github/README.md) +- After a successful preview comment, [`.github/scripts/preview-notify-linked-issues.cjs`](../.github/scripts/preview-notify-linked-issues.cjs) upserts the same body on issues linked via `Refs #NNN` (or legacy closing keywords; not `Part of #NNN`) and may move Project 4 Status to `In QA` (optional `PROJECT_BOARD_TOKEN`) — **before merge** for QA-required PRs +- **Process / merge gate:** [guides/qa-process.md](guides/qa-process.md) (Needs QA?, pass/fail, re-request by remove+re-add `preview-build`) +- Human install steps: [guides/qa-preview-testing.md](guides/qa-preview-testing.md) +- **Merge gate today:** manual — no required status check blocks merge until QA pass; reviewers enforce the invariant +- Nightly internal APK (no OTA): `nightly-preview.yml` + EAS profile `nightly` — see [`.github/README.md`](../.github/README.md) — does **not** satisfy the PR QA gate - Production: tag `v*` → `eas-build.yml` + [`.eas/README.md`](../.eas/README.md) ## Future guardrail — do not brick required checks @@ -74,6 +76,7 @@ Do **not** implement that skip pattern until the team explicitly wants required ## Related +- [guides/qa-process.md](guides/qa-process.md) - [issue-tracking.md](issue-tracking.md) - [AGENT_ONBOARDING.md](AGENT_ONBOARDING.md) - [guides/dependabot-process.md](guides/dependabot-process.md) diff --git a/docs/guides/project-board.md b/docs/guides/project-board.md index 20714148..64fa214c 100644 --- a/docs/guides/project-board.md +++ b/docs/guides/project-board.md @@ -13,7 +13,8 @@ This guide is for **any** coding agent (Cursor, Claude Code, Copilot, etc.). Boa | `Dev Ready` | Eng can code | Product/engineering already approved this for implementation. **Do not** move these cards to `Backlog` or `Sprint Shaping` to “sequence” or “clean up” the board. | | `In Progress (Dev)` | Assignee | Actively coding. | | `In PR Review` | Reviewers | Open PR exists (or should). Prefer this over leaving a card in `Dev Ready` once a PR is up. | -| `In QA` / `Passed QA` / `To Deploy` / `Done` | QA / release | Follow human process. After merge, agents set **`In QA`** (not `Done`). Do **not** auto-close issues. Agents set `Done` only when a human/QA process asks, or when closing obsolete/duplicate work with an approved change set. | +| `In QA` | QA | **Pre-merge** for QA-required PRs once `preview-build` is ready (automation may move here from `In PR Review` / `In Progress (Dev)`). Testers install **that PR’s** preview — see [qa-process.md](qa-process.md). | +| `Passed QA` / `To Deploy` / `Done` | QA / release | Humans set **`Passed QA`** after the PR preview passes → then merge is eligible. `To Deploy` / `Done` follow release process. Do **not** auto-close issues. Agents set `Done` only when a human/QA process asks, or when closing obsolete/duplicate work with an approved change set. | ## Hard rules @@ -30,16 +31,18 @@ When implementing the **assigned** ticket only: - Add the new issue to Project 4 if missing. - Set that issue to `In Progress (Dev)` while coding (optional) and **`In PR Review`** when the PR is open. -- Set **`In QA`** after merge (or when ready for QA). Leave the GitHub issue open — never use closing keywords in the PR. -- Set **`Done`** only after QA completes (human/QA process), or when closing obsolete/duplicate work with an approved change set and evidence. +- If the PR **Needs QA** ([qa-process.md](qa-process.md)): ensure `preview-build` is added; Status → **`In QA` before merge** when the preview is ready (automation may do this). Agents must **not** merge QA-required PRs until QA passes that preview. +- Engineering-only PRs: no preview/`In QA` gate for merge. +- Set **`Done`** only after QA/release completes (human/QA process), or when closing obsolete/duplicate work with an approved change set and evidence. Leave the GitHub issue open — never use closing keywords in the PR. Do **not** “helpfully” reorder neighboring cards. ## Linking keywords and stacked PRs -Do **not** use GitHub closing keywords (`Closes`, `Fixes`, `Resolves`) — they auto-close issues on merge to `main`. Always use **`Refs #NNN`** for the ticket this PR implements, or **`Part of #NNN`** for stacked/partial work. After merge of a `Refs`-linked PR (or when ready for QA), move the card to **`In QA`**. Preview-build automation follows the same rule: it comments / moves **In QA** for `Refs #NNN` (and legacy closing keywords), and does **not** treat `Part of #NNN` as a linked ticket. See [docs/issue-tracking.md](../issue-tracking.md). (Historical: issue #274 required `Closes` on `main`-targeting PRs; superseded by #300.) +Do **not** use GitHub closing keywords (`Closes`, `Fixes`, `Resolves`) — they auto-close issues on merge to `main`. Always use **`Refs #NNN`** for the ticket this PR implements, or **`Part of #NNN`** for stacked/partial work. For QA-required work, preview-build automation comments / moves **In QA** (pre-merge) for `Refs #NNN` (and legacy closing keywords), and does **not** treat `Part of #NNN` as a linked ticket. See [docs/issue-tracking.md](../issue-tracking.md) and [qa-process.md](qa-process.md). (Historical: issue #274 required `Closes` on `main`-targeting PRs; superseded by #300.) ## Related +- QA process / merge gate: [qa-process.md](qa-process.md) - Delivery / never push `main`: [`.cursor/rules/delivery.mdc`](../../.cursor/rules/delivery.mdc) - Cursor always-on pointer: [`.cursor/rules/project-board.mdc`](../../.cursor/rules/project-board.mdc) diff --git a/docs/guides/qa-preview-testing.md b/docs/guides/qa-preview-testing.md index e14b84f6..14b627cd 100644 --- a/docs/guides/qa-preview-testing.md +++ b/docs/guides/qa-preview-testing.md @@ -2,6 +2,8 @@ Plain-language guide for QA and reviewers. **No developer tools** — just an Android phone and the GitHub **PR or issue** comment. +**Process / merge gate (when QA is required, who owns what):** [qa-process.md](qa-process.md). This page is **how to install and test** the preview APK. + ## Quick start 1. Open the bot comment on the **pull request** or the **linked GitHub issue**. @@ -12,7 +14,7 @@ Plain-language guide for QA and reviewers. **No developer tools** — just an An The preview is a **standalone internal APK** for that PR (no over-the-air update). Each labeled PR gets its own build so multiple QA previews can exist at once. On one phone you can only have one Fluent install — reinstall when switching PRs. -When the preview is ready, the ticket usually moves to **In QA** on the Fluent Mobile Board. +When the preview is ready, the ticket usually moves to **In QA** on the Fluent Mobile Board. For QA-required PRs, that happens **before merge** — see [qa-process.md](qa-process.md). --- @@ -64,15 +66,18 @@ If the app looks wrong after installing a different PR’s preview: ## For developers +Full process (Needs QA?, pass/fail, merge eligibility, re-request): **[qa-process.md](qa-process.md)**. + 1. Link the ticket in the PR body (`Refs #NNN` on its own Details line — never `Closes` / `Fixes` / `Resolves`; do not use `Part of #NNN` for the ticket you want preview comments / In QA for). 2. Add the **`preview-build`** label to the PR. 3. Workflow starts a **fresh Android preview APK** (binary only — no OTA), comments on the **PR and linked issue**, and moves the ticket to **In QA** when Status was `In PR Review` or `In Progress (Dev)`. -4. Share this guide with QA: `docs/guides/qa-preview-testing.md` -5. Preview APKs use the EAS `preview` profile (internal distribution, Updates disabled — **not** `developmentClient`). -6. Optional repo secret `PROJECT_BOARD_TOKEN` enables Project 4 Status updates (issue comments work without it). +4. Share this guide with QA for install steps; share [qa-process.md](qa-process.md) for the merge gate. +5. After fixes: remove and re-add `preview-build` for a **new** isolated APK (see [qa-process.md](qa-process.md) § Re-request). +6. Preview APKs use the EAS `preview` profile (internal distribution, Updates disabled — **not** `developmentClient`). +7. Optional repo secret `PROJECT_BOARD_TOKEN` enables Project 4 Status updates (issue comments work without it). ### Nightly builds (optional) -Separate from PR previews: GitHub Actions can publish a **nightly Android APK** (EAS profile `nightly`, development API). Install from the Slack message or the Actions job summary — **not** from a PR comment. Nightlies are **binary only**. See [`.github/README.md`](../../.github/README.md). +Separate from PR previews: GitHub Actions can publish a **nightly Android APK** (EAS profile `nightly`, development API). Install from the Slack message or the Actions job summary — **not** from a PR comment. Nightlies are **binary only** and do **not** satisfy the PR QA merge gate. See [`.github/README.md`](../../.github/README.md). Technical details: [`.github/README.md`](../../.github/README.md) · [`.eas/README.md`](../../.eas/README.md) diff --git a/docs/guides/qa-process.md b/docs/guides/qa-process.md new file mode 100644 index 00000000..3b6df616 --- /dev/null +++ b/docs/guides/qa-process.md @@ -0,0 +1,139 @@ +# QA process (PR → preview → merge) + +Canonical **when / who / merge gate** for Fluent Mobile QA. For install steps on a phone, see [qa-preview-testing.md](qa-preview-testing.md). + +**Invariant:** A PR that **requires QA** is **not mergeable** until QA has **passed the isolated preview build for that PR**. + +## Mental model + +### Branch 1 — Does this change require QA? + +| Needs QA? | Examples | Path | +| --- | --- | --- | +| **No** | Logging, internal refactors, instrumentation, docs-only, Dependabot with no runtime UX, some performance-only changes | Engineering review → eligible to merge when CI is green | +| **Yes** | UI, native modules, mic / camera / filesystem / permissions, sync behavior, anything QA must verify on device | Author adds `preview-build` → QA flow below | + +When unsure, treat it as **Needs QA**. + +### Branch 2 — QA flow (`preview-build`) + +```text +PR ready + | + v +Needs QA? + / \ +No Yes +| | +Code Add preview-build +review label + | + v + Isolated PR build + | + v + CI posts install link + to PR + issue + | + v + QA + / \ + Pass Fail + | | + | Document issue + | + In Progress (Dev) + | | + | Developer fixes + | | + | New preview + | | + |______| + | + v +Eligible to merge +``` + +## Ownership + +| Role | Owns | +| --- | --- | +| **Developer** | Decide Needs QA?; add `preview-build` when yes; keep `Refs #NNN` correct; do not merge QA-required PRs before QA pass | +| **CI** | Isolated Android preview APK for that PR; install comment on **PR** and linked issue; best-effort Project 4 → `In QA` | +| **QA** | Pass/fail on **that** preview build (not another PR’s APK, not nightly, not production) | +| **Reviewer / merger** | Enforce the merge gate manually until an automated gate exists | + +## Needs QA? heuristics + +**Yes (add `preview-build`):** + +- User-visible UI or navigation changes +- Recording / playback / mic / camera / filesystem / permissions +- Sync, offline, or data that QA must exercise on device +- Native modules, Expo config plugins, or anything that needs a fresh APK to validate +- Agent-authored features that touch the surfaces in [AGENTS.md](../../AGENTS.md) § Human-only verification + +**No (engineering-only):** + +- Docs, CI YAML, agent rules, comments +- Pure refactors with no behavior change +- Logging / metrics / instrumentation only +- Dependabot bumps with no app UX impact (still run CI) + +## Status on Project 4 (QA-required PRs) + +Typical loop: + +| Step | Status | +| --- | --- | +| Coding | `In Progress (Dev)` | +| PR open | `In PR Review` | +| `preview-build` ready / bot commented | `In QA` (automation moves from `In PR Review` / `In Progress (Dev)` when possible) | +| QA fail | Back to `In Progress (Dev)` (human); developer fixes → new preview | +| QA pass | `Passed QA` (human) → **then** eligible to merge | +| After merge | Leave open until release process; humans set `Done` — do **not** auto-close on merge | + +Engineering-only PRs skip `preview-build` / `In QA` for this gate. They still use `In PR Review` and merge when review + CI allow. + +### Post-merge / release QA + +Production / tag (`v*`) and optional nightly APKs are **separate** from this PR gate. Do not use a nightly or another developer’s preview to satisfy “QA passed this PR.” Board columns after merge (`To Deploy`, `Done`) follow release process — see [project-board.md](project-board.md). + +## Developer checklist (QA-required) + +1. Open PR with `Refs #NNN` on its own Details line (never `Closes` / `Fixes` / `Resolves`; do not use `Part of #NNN` for the ticket that should get preview comments). +2. Add the **`preview-build`** label. +3. Wait for the bot comment on the **PR** and linked issue ([qa-preview-testing.md](qa-preview-testing.md)). +4. Confirm board moved to **In QA** (or move manually if `PROJECT_BOARD_TOKEN` was unavailable). +5. **Do not merge** until QA marks pass (`Passed QA` / explicit approval on the PR). +6. On fail: fix on the same branch → request a **new** preview (below) → QA retests. + +## Re-request a preview (fail / retest) + +`preview-build.yml` runs on **label added** (`pull_request` types: `labeled`) and always starts a **fresh** Android APK (`FORCE_NEW_BUILD=true`) for that PR’s head commit. + +To get a new isolated build after more commits: + +1. Remove the `preview-build` label from the PR. +2. Re-add the `preview-build` label. + +That triggers a new workflow run, a new install comment, and another best-effort `In QA` move. Always install from the **latest** bot comment for that PR/issue. + +## CI / automation (current) + +| Piece | Behavior | +| --- | --- | +| [`.github/workflows/preview-build.yml`](../../.github/workflows/preview-build.yml) | Label `preview-build` → fresh EAS `preview` internal APK (binary only, no OTA) | +| [`.github/scripts/preview-notify-linked-issues.cjs`](../../.github/scripts/preview-notify-linked-issues.cjs) | Mirrors install comment to issues linked via `Refs #NNN`; moves Project 4 → `In QA` from `In PR Review` / `In Progress (Dev)` when `PROJECT_BOARD_TOKEN` is set | +| Merge eligibility | **Manual** — no required GitHub status/label yet that blocks merge until QA pass | + +### Gap (manual gate) + +There is **no** automated branch-protection check that blocks merging a QA-required PR until QA passes. Reviewers and mergers must enforce the invariant. Hardening (required label / checklist / status) is tracked in **#330**. + +## Related + +- Install / phone steps: [qa-preview-testing.md](qa-preview-testing.md) +- Board rules: [project-board.md](project-board.md) +- Issue / PR linking: [../issue-tracking.md](../issue-tracking.md) +- CI inventory: [../ci.md](../ci.md) +- Agent delivery: [../../AGENTS.md](../../AGENTS.md) diff --git a/docs/issue-tracking.md b/docs/issue-tracking.md index 0699d93f..0cd8df98 100644 --- a/docs/issue-tracking.md +++ b/docs/issue-tracking.md @@ -16,7 +16,7 @@ The [repo Issues list](https://github.com/eten-tech-foundation/fluent-mobile/iss `Backlog` · `In Progress (Product)` · `Product Ready` · `Sprint Shaping` · `Dev Ready` · `In Progress (Dev)` · `In PR Review` · `In QA` · `Passed QA` · `To Deploy` · `Done` -For open PRs awaiting review, prefer **`In PR Review`**. After merge (or when ready for QA), set **`In QA`**. Set **`Done`** only after QA completes — never auto-close issues on PR merge. +For open PRs awaiting review, prefer **`In PR Review`**. For **QA-required** PRs, add `preview-build` and move to **`In QA` before merge** (preview automation does this when possible); humans set **`Passed QA`**, then merge. Engineering-only PRs skip that gate. Set **`Done`** only after QA/release completes — never auto-close issues on PR merge. Canonical process: [guides/qa-process.md](guides/qa-process.md). Do **not** use org Project 7 (“Fluent Mobile App”) as the primary tracker unless the team explicitly migrates. @@ -72,7 +72,8 @@ See [`.claude/commands/create-pr-branch.md`](../.claude/commands/create-pr-branc - **Development sidebar:** closing keywords are the only API-friendly way to auto-populate GitHub’s “linked issues” widget; we refuse those keywords, so link `#NNN` manually in the PR sidebar when the widget is empty (or ask a human). `Refs #NNN` still cross-references the issue in timelines. - For related / stacked work that is not the full ticket, say “Part of #NNN” in prose, or link manually in the PR sidebar - After opening a PR, set Project 4 Status to **`In PR Review`** (if not already) -- After merge (or when ready for QA), set Project 4 Status to **`In QA`** — leave the GitHub issue **open** +- If the PR **Needs QA** ([guides/qa-process.md](guides/qa-process.md)): add `preview-build`; Status → **`In QA`** when the preview is ready (**pre-merge**). Do **not** merge until QA passes that PR’s preview (`Passed QA`). Leave the GitHub issue **open** +- Engineering-only PRs: merge after review + CI; no preview/QA gate - **Template source of truth:** [`.cursor/templates/pr-template.md`](../.cursor/templates/pr-template.md) — also required by [delivery.mdc](../.cursor/rules/delivery.mdc); generate with `/generate-pr-description` or `/create-pr` ### Agent command: `/start-issue` @@ -91,9 +92,9 @@ Canonical instructions: [`.claude/commands/start-issue.md`](../.claude/commands/ Use `Refs #NNN` (or sidebar linking) so GitHub [does not auto-close](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) the issue on merge. -Never use `Closes`, `Fixes`, or `Resolves` in PR bodies for ticketed work. Issues stay open until QA finishes; humans set **`Done`** (and may close the issue) after **Passed QA** / release process — not on merge alone. +Never use `Closes`, `Fixes`, or `Resolves` in PR bodies for ticketed work. Issues stay open until QA finishes; humans set **`Done`** (and may close the issue) after **Passed QA** / release process — not on merge alone. **QA-required PRs are not mergeable until QA passes that PR’s preview build** ([guides/qa-process.md](guides/qa-process.md)). -Put `Refs #NNN` on its **own line** under Details (see the PR template). Preview-build notification ([`.github/scripts/preview-notify-linked-issues.cjs`](../.github/scripts/preview-notify-linked-issues.cjs)) treats that form as the linked ticket for install comments and Project 4 → **In QA**. `Part of #NNN` is ignored by that script (stacked/partial work stays out of automatic QA handoff). +Put `Refs #NNN` on its **own line** under Details (see the PR template). Preview-build notification ([`.github/scripts/preview-notify-linked-issues.cjs`](../.github/scripts/preview-notify-linked-issues.cjs)) treats that form as the linked ticket for install comments and Project 4 → **In QA** (pre-merge for QA-required work). `Part of #NNN` is ignored by that script (stacked/partial work stays out of automatic QA handoff). ## Agents / delivery @@ -101,9 +102,12 @@ Put `Refs #NNN` on its **own line** under Details (see the PR template). Preview - Done means acceptance criteria, not green CI alone ([AGENTS.md](../AGENTS.md)) - Triage and column moves: Project 4 Fluent Mobile Board — not the bare Issues index - Dependabot PRs: follow [guides/dependabot-process.md](guides/dependabot-process.md) +- QA process / merge gate: [guides/qa-process.md](guides/qa-process.md) ## Related +- [guides/qa-process.md](guides/qa-process.md) — Needs QA?, preview loop, pre-merge merge gate +- [guides/qa-preview-testing.md](guides/qa-preview-testing.md) — install/how-to for PR previews - [guides/project-board.md](guides/project-board.md) — board mutation hard rules for agents - [guides/expo-first-dependencies.md](guides/expo-first-dependencies.md) — prefer Expo packages - [docs/ci.md](ci.md) — CI workflows and required-check guardrails From 70c74730bb313e678e1ade2f0a85e6e75e305a6a Mon Sep 17 00:00:00 2001 From: mattrace-gloo Date: Thu, 13 Aug 2026 10:22:47 -0700 Subject: [PATCH 2/3] [#329]: Align agent surfaces with pre-merge QA preview gate Point guardrails, /create-pr, and code-reviewer at Needs QA? / preview-build merge eligibility; clarify Passed QA in the process flowchart. --- .claude/agents/code-reviewer.md | 7 +++++-- .claude/commands/create-pr.md | 18 ++++++++++++++---- .cursor/rules/agent-guardrails.mdc | 2 +- .cursor/templates/pr-template.md | 4 ++-- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- docs/guides/qa-process.md | 3 +++ 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.claude/agents/code-reviewer.md b/.claude/agents/code-reviewer.md index e312345b..67409d07 100644 --- a/.claude/agents/code-reviewer.md +++ b/.claude/agents/code-reviewer.md @@ -66,8 +66,11 @@ exact `file:line`, name the rule, and give a copy-pasteable fix. plan). One ticket = one PR ([AGENTS.md](../../AGENTS.md)). 8. **Device QA.** Changes that add native modules or mic / camera / filesystem - / permissions behavior must **flag** that Android device QA is required - before ready-for-review. Do not treat unit tests as sufficient. + / permissions behavior (or otherwise **Needs QA**) must **flag** Android + device QA on that PR’s **`preview-build`** before merge (see + [docs/guides/qa-process.md](../../docs/guides/qa-process.md)). Do not treat + unit tests as sufficient; QA-required PRs are not mergeable until that + preview passes. 9. **TypeScript.** New `any` (prefer `unknown` + narrowing). Missing types on exported functions where neighbors have them. diff --git a/.claude/commands/create-pr.md b/.claude/commands/create-pr.md index c69034be..8f97b1e0 100644 --- a/.claude/commands/create-pr.md +++ b/.claude/commands/create-pr.md @@ -136,15 +136,25 @@ and pre-fill: | ------- | ---------------- | | **TLDR** | 2–4 sentences: what / why / impact | | **Reviewer checklist** | Leave items unchecked unless verified ([AGENTS.md](../../AGENTS.md)) | -| **Details** | `Refs #NNN` on its own line; short summary; type-of-change checkboxes | +| **Details** | `Refs #NNN` on its own line; short summary; **Needs QA?** Yes/No; type-of-change checkboxes | | **Technical changes** | Key files as `` `path` `` bullets | | **Testing** | What gates ran (`format:check`, `lint`, `typecheck`, `npm test -- --ci`) | | **How to verify** | Numbered steps + **Expected** | | **Follow-ups** | Deferred AC → linked issues; otherwise say none | -Do **not** auto-check **Acceptance criteria**, **Scope**, or **Android device -tested** unless verified. Do **not** auto-check device QA for native / mic / -camera / filesystem / permissions changes. +**Needs QA? / preview gate** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)): + +1. Decide **Needs QA?** and check **No** or **Yes** in the PR body. +2. If **Yes**: remind the author to add the **`preview-build`** label (do not + merge until QA passes that PR’s preview). Leave “QA passed this PR’s + preview” and the Android device checkbox **unchecked** until a human + confirms. +3. If **No**: check engineering-only; skip preview/QA merge gate. + +Do **not** auto-check **Acceptance criteria**, **Scope**, **Needs QA? +preview-passed**, or **Android device tested** unless verified. Do **not** +auto-check device QA for native / mic / camera / filesystem / permissions +changes. Keep under ~400 lines; no nested fenced code blocks inside the PR body. diff --git a/.cursor/rules/agent-guardrails.mdc b/.cursor/rules/agent-guardrails.mdc index 71f52be8..b98cc615 100644 --- a/.cursor/rules/agent-guardrails.mdc +++ b/.cursor/rules/agent-guardrails.mdc @@ -12,7 +12,7 @@ Quick checklist: 1. **AC** — done means ticket acceptance criteria (or ticket-level waiver + follow-up), not green CI alone 2. **Scope** — one ticket = one PR; no adjacent tickets unless asked 3. **Abstraction** — no generic adapter/framework without a second caller or ticket ask -4. **Human QA** — native / mic / camera / filesystem / permissions need Android device results before ready-for-review +4. **Human QA** — Needs QA (native / mic / camera / filesystem / permissions / device UX) → that PR’s `preview-build` → **not mergeable until QA passes** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)) 5. **Agent-authored features** — review scope, abstraction, and AC-vs-CI first 6. **PR body** — filled from [`.cursor/templates/pr-template.md`](../templates/pr-template.md) on every agent-opened PR ([delivery.mdc](./delivery.mdc)) — not a short Summary/Test plan substitute diff --git a/.cursor/templates/pr-template.md b/.cursor/templates/pr-template.md index cfb66cc5..4d3d657e 100644 --- a/.cursor/templates/pr-template.md +++ b/.cursor/templates/pr-template.md @@ -9,8 +9,8 @@ - [ ] Acceptance criteria met, **or** unmet AC waived **in the issue** with linked follow-up (see `AGENTS.md`) - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval - [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added -- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms) -- [ ] Android device tested when required (native / mic / camera / filesystem / permissions) — do **not** check unless verified on a device +- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms; this is the device-QA gate when Needs QA? is Yes) +- [ ] Android device tested when required **and** Needs QA? is No — do **not** check unless verified on a device ### Details diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index cfb66cc5..4d3d657e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,8 +9,8 @@ - [ ] Acceptance criteria met, **or** unmet AC waived **in the issue** with linked follow-up (see `AGENTS.md`) - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval - [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added -- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms) -- [ ] Android device tested when required (native / mic / camera / filesystem / permissions) — do **not** check unless verified on a device +- [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms; this is the device-QA gate when Needs QA? is Yes) +- [ ] Android device tested when required **and** Needs QA? is No — do **not** check unless verified on a device ### Details diff --git a/docs/guides/qa-process.md b/docs/guides/qa-process.md index 3b6df616..e0202949 100644 --- a/docs/guides/qa-process.md +++ b/docs/guides/qa-process.md @@ -50,6 +50,9 @@ review label |______| | v +Passed QA + | + v Eligible to merge ``` From 081ec41b64694825628c2d5c2574e5b524443610 Mon Sep 17 00:00:00 2001 From: mattrace-gloo Date: Tue, 18 Aug 2026 14:44:36 -0700 Subject: [PATCH 3/3] [#329]: Tighten preview-build and Needs QA wording after review Make /create-pr add and verify the preview-build label, point Needs QA at qa-process.md, and treat In QA as tracking rather than a merge gate. --- .claude/commands/create-pr.md | 31 +++++++++++++++++++++--------- .cursor/rules/agent-guardrails.mdc | 2 +- .cursor/rules/delivery.mdc | 2 +- .cursor/rules/project-board.mdc | 2 +- .cursor/templates/pr-template.md | 3 +-- .github/PULL_REQUEST_TEMPLATE.md | 3 +-- CLAUDE.md | 2 +- 7 files changed, 28 insertions(+), 17 deletions(-) diff --git a/.claude/commands/create-pr.md b/.claude/commands/create-pr.md index 8f97b1e0..55302f0f 100644 --- a/.claude/commands/create-pr.md +++ b/.claude/commands/create-pr.md @@ -145,16 +145,15 @@ and pre-fill: **Needs QA? / preview gate** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)): 1. Decide **Needs QA?** and check **No** or **Yes** in the PR body. -2. If **Yes**: remind the author to add the **`preview-build`** label (do not - merge until QA passes that PR’s preview). Leave “QA passed this PR’s - preview” and the Android device checkbox **unchecked** until a human - confirms. +2. If **Yes**: leave “QA passed this PR’s preview” **unchecked** until a + human confirms. After `gh pr create` (below), **add** the + **`preview-build`** label and **verify** it is on the PR. **STOP** if + the label is missing — the isolated preview will not start. Do not + merge until QA passes that PR’s preview. 3. If **No**: check engineering-only; skip preview/QA merge gate. -Do **not** auto-check **Acceptance criteria**, **Scope**, **Needs QA? -preview-passed**, or **Android device tested** unless verified. Do **not** -auto-check device QA for native / mic / camera / filesystem / permissions -changes. +Do **not** auto-check **Acceptance criteria**, **Scope**, or **Needs QA? +preview-passed** unless verified. Keep under ~400 lines; no nested fenced code blocks inside the PR body. @@ -172,6 +171,19 @@ If the PR already exists without an assignee: gh pr edit --add-assignee @me ``` +**`preview-build` label (QA-required — hard gate):** If **Needs QA?** is +**Yes**, add the label immediately and confirm it is present. **STOP** if +it is missing. + +```bash +# Only when Needs QA? is Yes +gh pr edit --add-label preview-build +if ! gh pr view --json labels --jq '.labels[].name' | grep -qx preview-build; then + echo "STOP: Needs QA? Yes but preview-build label is missing." + exit 1 +fi +``` + **Issue link (Development sidebar):** `Refs #NNN` is the required non-closing reference. GitHub’s Development widget is only auto-populated by closing keywords or a **manual** sidebar link. Do **not** use closing keywords. After @@ -179,7 +191,8 @@ create, if the sidebar is empty, link `#NNN` once in the GitHub UI (or ask the user to). **Reviewers / labels:** CODEOWNERS handles review requests after the file is on -`main`. Omit `--reviewer` unless the user asks. +`main`. Omit `--reviewer` unless the user asks. Do **not** skip +`preview-build` when **Needs QA?** is **Yes** (hard gate above). Flag high-impact paths in the body when present: `package.json`, `package-lock.json`, `app.config.ts`, `plugins/`, `eas.json`, `src/db/schema.ts` diff --git a/.cursor/rules/agent-guardrails.mdc b/.cursor/rules/agent-guardrails.mdc index b98cc615..7531fb6c 100644 --- a/.cursor/rules/agent-guardrails.mdc +++ b/.cursor/rules/agent-guardrails.mdc @@ -12,7 +12,7 @@ Quick checklist: 1. **AC** — done means ticket acceptance criteria (or ticket-level waiver + follow-up), not green CI alone 2. **Scope** — one ticket = one PR; no adjacent tickets unless asked 3. **Abstraction** — no generic adapter/framework without a second caller or ticket ask -4. **Human QA** — Needs QA (native / mic / camera / filesystem / permissions / device UX) → that PR’s `preview-build` → **not mergeable until QA passes** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)) +4. **Human QA** — Needs QA per [docs/guides/qa-process.md](../../docs/guides/qa-process.md) → that PR’s `preview-build` → **not mergeable until QA passes** 5. **Agent-authored features** — review scope, abstraction, and AC-vs-CI first 6. **PR body** — filled from [`.cursor/templates/pr-template.md`](../templates/pr-template.md) on every agent-opened PR ([delivery.mdc](./delivery.mdc)) — not a short Summary/Test plan substitute diff --git a/.cursor/rules/delivery.mdc b/.cursor/rules/delivery.mdc index ba2fa5a1..9be13659 100644 --- a/.cursor/rules/delivery.mdc +++ b/.cursor/rules/delivery.mdc @@ -14,7 +14,7 @@ Every change — including infra, CI, docs, Dependabot follow-ups, and `expo ins 1. **Ticket on Project 4** — GitHub Issue `#NNN` **on** the [Fluent Mobile Board](https://github.com/orgs/eten-tech-foundation/projects/4/views/9) (org project #4, view 9). Ask if missing. See [docs/issue-tracking.md](../../docs/issue-tracking.md). The repo Issues list is not the triage board. (Not Linear.) Board Status/Priority edits: [docs/guides/project-board.md](../../docs/guides/project-board.md) and [project-board.mdc](./project-board.mdc) — do not sweep Product or `Dev Ready` lanes without named approval. 2. **Feature branch** — `{author}/{type}/{issue-number}-{slug}` (see `/create-pr-branch`, or `/start-issue` for the full loop) 3. **Pull request** — title `[#NNN]: Description`; body filled from the PR template (below); include `Refs #NNN` under Details (never `Closes` / `Fixes` / `Resolves`); **assign the PR to the author** (`gh pr create --assignee @me` or `gh pr edit --add-assignee @me`); set Project 4 Status to **In PR Review**. Manually link the issue in the PR Development sidebar when needed (GitHub has no non-closing link API — do not use closing keywords). `/start-issue` chains to `/create-pr` (`/open-pr` is an alias) which automates the draft PR, board move, and CI watch. -4. **Human merge** — agents open PRs and push **feature branches only**; never merge on GitHub unless the user explicitly asks for a Dependabot squash merge in that session. For **QA-required** PRs ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)): add `preview-build`, wait for **In QA** / QA pass on **that PR’s** preview — **not mergeable until QA passes**. Engineering-only PRs skip that gate. Issues stay open — do not auto-close +4. **Human merge** — agents open PRs and push **feature branches only**; never merge on GitHub unless the user explicitly asks for a Dependabot squash merge in that session. For **QA-required** PRs ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)): add `preview-build` and wait for QA pass on **that PR’s** isolated preview — **not mergeable until QA passes**. Project 4 `In QA` is best-effort tracking, not a merge prerequisite. Engineering-only PRs skip that gate. Issues stay open — do not auto-close Allowed on `main` locally: `git checkout main`, `git pull`, read-only validation after merges. **Not allowed:** `git push origin main`, commits on `main`, or opening PRs with `main` as the head branch. diff --git a/.cursor/rules/project-board.mdc b/.cursor/rules/project-board.mdc index 05d37f85..8da4bad0 100644 --- a/.cursor/rules/project-board.mdc +++ b/.cursor/rules/project-board.mdc @@ -13,6 +13,6 @@ Canonical policy: [docs/guides/project-board.md](../../docs/guides/project-board - **Do not** edit Status or Priority on `In Progress (Product)` (or other Product-owned columns) unless the tech lead **explicitly lists** those issue numbers. - **No board sweeps** without a proposed change set + explicit approval. Ambiguous = no. - **Do not merge PRs** unless explicitly asked (Dependabot process is the standing exception when requested). -- For the **assigned** ticket only: add to Project 4 if missing; set `In PR Review` when the PR opens; if **Needs QA**, add `preview-build` and expect **`In QA` before merge** ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)) — never auto-close the issue; do **not** set `Done` until QA completes (human/QA process). Do not merge QA-required PRs until QA passes that PR’s preview. +- For the **assigned** ticket only: add to Project 4 if missing; set `In PR Review` when the PR opens; if **Needs QA**, add `preview-build` and do **not** merge until QA passes that PR’s preview ([docs/guides/qa-process.md](../../docs/guides/qa-process.md)). Project 4 `In QA` is best-effort tracking, not a merge gate — never auto-close the issue; do **not** set `Done` until QA completes (human/QA process). Tracker overview: [docs/issue-tracking.md](../../docs/issue-tracking.md). QA process: [docs/guides/qa-process.md](../../docs/guides/qa-process.md). Delivery: [delivery.mdc](./delivery.mdc). diff --git a/.cursor/templates/pr-template.md b/.cursor/templates/pr-template.md index 4d3d657e..2572cb52 100644 --- a/.cursor/templates/pr-template.md +++ b/.cursor/templates/pr-template.md @@ -10,7 +10,6 @@ - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval - [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added - [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms; this is the device-QA gate when Needs QA? is Yes) -- [ ] Android device tested when required **and** Needs QA? is No — do **not** check unless verified on a device ### Details @@ -21,7 +20,7 @@ Refs # **Needs QA?** - [ ] No — engineering-only (docs, CI, refactor, logging, etc.) -- [ ] Yes — UI / native / mic / camera / filesystem / sync / device verification (`preview-build` required) +- [ ] Yes — see Needs QA? in `docs/guides/qa-process.md` (`preview-build` required) **Type of change:** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4d3d657e..2572cb52 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,6 @@ - [ ] Scope limited to this issue — no adjacent tickets implemented/stubbed without approval - [ ] **Needs QA?** decided (see `docs/guides/qa-process.md`) — if yes: `preview-build` label added - [ ] If QA-required: QA passed **this PR’s** preview build before merge (do **not** check until QA confirms; this is the device-QA gate when Needs QA? is Yes) -- [ ] Android device tested when required **and** Needs QA? is No — do **not** check unless verified on a device ### Details @@ -21,7 +20,7 @@ Refs # **Needs QA?** - [ ] No — engineering-only (docs, CI, refactor, logging, etc.) -- [ ] Yes — UI / native / mic / camera / filesystem / sync / device verification (`preview-build` required) +- [ ] Yes — see Needs QA? in `docs/guides/qa-process.md` (`preview-build` required) **Type of change:** diff --git a/CLAUDE.md b/CLAUDE.md index 2a4ac2af..5c1d5b2d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ This file is the **entrypoint for non-Cursor agents** (Claude Code, Codex, Copil - Never push or merge to `main`; ticketed branch + PR; PR body from [`.cursor/templates/pr-template.md`](.cursor/templates/pr-template.md). Full loop: `/start-issue NNN` (chains to `/create-pr`). Delivery-only: `/create-pr` (`/open-pr` alias). - Do not reorganize Project 4 (`Dev Ready` / Product columns) without an approved change set - Prefer Expo SDK modules; do not rip out React Navigation without a ticket -- Mic / camera / filesystem / native modules → human Android device QA on that PR’s `preview-build` **before merge** ([docs/guides/qa-process.md](docs/guides/qa-process.md)) +- Needs QA per [docs/guides/qa-process.md](docs/guides/qa-process.md) → human Android device QA on that PR’s `preview-build` **before merge** ## Package manager / Node